[SCSIPORT] Use pointer alignment for MiniPortDeviceExtension
[reactos.git] / drivers / usb / usbccgp / function.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbccgp/descriptor.c
5 * PURPOSE: USB device driver.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
9 * Cameron Gutman
10 */
11
12 #include "usbccgp.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 NTSTATUS
18 USBCCGP_QueryInterface(
19 IN PDEVICE_OBJECT DeviceObject,
20 OUT PUSBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface)
21 {
22 KEVENT Event;
23 NTSTATUS Status;
24 PIRP Irp;
25 IO_STATUS_BLOCK IoStatus;
26 PIO_STACK_LOCATION Stack;
27
28 /* Sanity checks */
29 ASSERT(DeviceObject);
30
31 /* Initialize event */
32 KeInitializeEvent(&Event, NotificationEvent, FALSE);
33
34 /* Init interface */
35 RtlZeroMemory(BusInterface, sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1));
36 BusInterface->Version = USBC_DEVICE_CONFIGURATION_INTERFACE_VERSION_1;
37 BusInterface->Size = sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1);
38
39 /* Create irp */
40 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
41 DeviceObject,
42 NULL,
43 0,
44 NULL,
45 &Event,
46 &IoStatus);
47
48 //
49 // was irp built
50 //
51 if (Irp == NULL)
52 {
53 //
54 // no memory
55 //
56 return STATUS_INSUFFICIENT_RESOURCES;
57 }
58
59 //
60 // initialize request
61 //
62 Stack = IoGetNextIrpStackLocation(Irp);
63 Stack->MajorFunction = IRP_MJ_PNP;
64 Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
65 Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
66 Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBC_CONFIGURATION_GUID;
67 Stack->Parameters.QueryInterface.Version = 2;
68 Stack->Parameters.QueryInterface.Interface = (PINTERFACE)&BusInterface;
69 Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
70 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
71
72 //
73 // call driver
74 //
75 Status = IoCallDriver(DeviceObject, Irp);
76
77 //
78 // did operation complete
79 //
80 if (Status == STATUS_PENDING)
81 {
82 //
83 // wait for completion
84 //
85 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
86
87 //
88 // collect status
89 //
90 Status = IoStatus.Status;
91 }
92
93 return Status;
94 }
95
96 NTSTATUS
97 USBCCGP_CustomEnumWithInterface(
98 IN PDEVICE_OBJECT DeviceObject)
99 {
100 PFDO_DEVICE_EXTENSION FDODeviceExtension;
101 ULONG FunctionDescriptorBufferLength = 0;
102 NTSTATUS Status;
103 PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptorBuffer = NULL;
104
105 //
106 // get device extension
107 //
108 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
109 ASSERT(FDODeviceExtension->Common.IsFDO);
110
111 if (FDODeviceExtension->BusInterface.StartDeviceCallback == NULL)
112 {
113 //
114 // not supported
115 //
116 return STATUS_NOT_SUPPORTED;
117 }
118
119 //
120 // invoke callback
121 //
122 Status = FDODeviceExtension->BusInterface.StartDeviceCallback(FDODeviceExtension->DeviceDescriptor,
123 FDODeviceExtension->ConfigurationDescriptor,
124 &FunctionDescriptorBuffer,
125 &FunctionDescriptorBufferLength,
126 DeviceObject,
127 FDODeviceExtension->PhysicalDeviceObject);
128
129 DPRINT("USBCCGP_CustomEnumWithInterface Status %lx\n", Status);
130 if (!NT_SUCCESS(Status))
131 {
132 //
133 // failed
134 //
135 return Status;
136 }
137
138 DPRINT("FunctionDescriptorBufferLength %lu\n", FunctionDescriptorBufferLength);
139 DPRINT("FunctionDescriptorBuffer %p\n", FunctionDescriptorBuffer);
140
141 //
142 // assume length % function buffer size
143 //
144 ASSERT(FunctionDescriptorBufferLength);
145 ASSERT(FunctionDescriptorBufferLength % sizeof(USBC_FUNCTION_DESCRIPTOR) == 0);
146
147 //
148 // store result
149 //
150 FDODeviceExtension->FunctionDescriptor = FunctionDescriptorBuffer;
151 FDODeviceExtension->FunctionDescriptorCount = FunctionDescriptorBufferLength / sizeof(USBC_FUNCTION_DESCRIPTOR);
152
153 //
154 // success
155 //
156 return STATUS_SUCCESS;
157 }
158
159 ULONG
160 USBCCGP_CountAssociationDescriptors(
161 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
162 {
163 PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
164 PUCHAR Offset, End;
165 ULONG Count = 0;
166
167 //
168 // init offsets
169 //
170 Offset = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->bLength;
171 End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
172
173 while (Offset < End)
174 {
175 //
176 // get association descriptor
177 //
178 Descriptor = (PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR)Offset;
179
180 if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
181 {
182 //
183 // found descriptor
184 //
185 Count++;
186 }
187
188 //
189 // move to next descriptor
190 //
191 Offset += Descriptor->bLength;
192 }
193
194 //
195 // done
196 //
197 return Count;
198 }
199
200 PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR
201 USBCCGP_GetAssociationDescriptorAtIndex(
202 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
203 IN ULONG Index)
204 {
205 PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
206 PUCHAR Offset, End;
207 ULONG Count = 0;
208
209 //
210 // init offsets
211 //
212 Offset = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->bLength;
213 End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
214
215 while (Offset < End)
216 {
217 //
218 // get association descriptor
219 //
220 Descriptor = (PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR)Offset;
221
222 if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
223 {
224 if (Index == Count)
225 {
226 //
227 // found descriptor
228 //
229 return Descriptor;
230 }
231
232 //
233 // not the searched one
234 //
235 Count++;
236 }
237
238 //
239 // move to next descriptor
240 //
241 Offset += Descriptor->bLength;
242 }
243
244 //
245 // failed to find descriptor at the specified index
246 //
247 return NULL;
248 }
249
250 NTSTATUS
251 USBCCGP_InitInterfaceListOfFunctionDescriptor(
252 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
253 IN PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR AssociationDescriptor,
254 OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
255 {
256 PUSB_INTERFACE_DESCRIPTOR Descriptor;
257 PUCHAR Offset, End;
258 ULONG Count = 0;
259
260 //
261 // init offsets
262 //
263 Offset = (PUCHAR)AssociationDescriptor + AssociationDescriptor->bLength;
264 End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
265
266 while (Offset < End)
267 {
268 //
269 // get association descriptor
270 //
271 Descriptor = (PUSB_INTERFACE_DESCRIPTOR)Offset;
272
273 if (Descriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
274 {
275 //
276 // store interface descriptor
277 //
278 FunctionDescriptor->InterfaceDescriptorList[Count] = Descriptor;
279 Count++;
280
281 if (Count == AssociationDescriptor->bInterfaceCount)
282 {
283 //
284 // got all interfaces
285 //
286 return STATUS_SUCCESS;
287 }
288 }
289
290 if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
291 {
292 //
293 // WTF? a association descriptor which overlaps the next association descriptor
294 //
295 DPRINT1("Invalid association descriptor\n");
296 ASSERT(FALSE);
297 return STATUS_UNSUCCESSFUL;
298 }
299
300 //
301 // move to next descriptor
302 //
303 Offset += Descriptor->bLength;
304 }
305
306 //
307 // invalid association descriptor
308 //
309 DPRINT1("Invalid association descriptor\n");
310 return STATUS_UNSUCCESSFUL;
311 }
312
313 NTSTATUS
314 USBCCGP_InitFunctionDescriptor(
315 IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
316 IN ULONG FunctionNumber,
317 OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
318 {
319 PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
320 NTSTATUS Status;
321 LPWSTR DescriptionBuffer;
322 WCHAR Buffer[100];
323 ULONG Index;
324
325 // init function number
326 FunctionDescriptor->FunctionNumber = (UCHAR)FunctionNumber;
327
328 // get association descriptor
329 Descriptor = USBCCGP_GetAssociationDescriptorAtIndex(FDODeviceExtension->ConfigurationDescriptor, FunctionNumber);
330 ASSERT(Descriptor);
331
332 // store number interfaces
333 FunctionDescriptor->NumberOfInterfaces = Descriptor->bInterfaceCount;
334
335 // allocate array for interface count
336 FunctionDescriptor->InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Descriptor->bInterfaceCount);
337 if (!FunctionDescriptor->InterfaceDescriptorList)
338 {
339 //
340 // no memory
341 //
342 return STATUS_INSUFFICIENT_RESOURCES;
343 }
344
345 // init interface list
346 Status = USBCCGP_InitInterfaceListOfFunctionDescriptor(FDODeviceExtension->ConfigurationDescriptor, Descriptor, FunctionDescriptor);
347 if (!NT_SUCCESS(Status))
348 {
349 //
350 // failed
351 //
352 return Status;
353 }
354
355 //
356 // now init interface description
357 //
358 if (Descriptor->iFunction)
359 {
360 //
361 // get interface description
362 //
363 Status = USBCCGP_GetStringDescriptor(FDODeviceExtension->NextDeviceObject,
364 100 * sizeof(WCHAR),
365 Descriptor->iFunction,
366 0x0409, //FIXME
367 (PVOID*)&DescriptionBuffer);
368 if (!NT_SUCCESS(Status))
369 {
370 //
371 // no description
372 //
373 RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, L"");
374 }
375 else
376 {
377 //
378 // init description
379 //
380 RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, DescriptionBuffer);
381 }
382 DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor->FunctionDescription);
383 }
384
385 //
386 // now init hardware id
387 //
388 Index = swprintf(Buffer, L"USB\\VID_%04x&PID_%04x&Rev_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
389 FDODeviceExtension->DeviceDescriptor->idProduct,
390 FDODeviceExtension->DeviceDescriptor->bcdDevice,
391 Descriptor->bFirstInterface) + 1;
392 Index += swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
393 FDODeviceExtension->DeviceDescriptor->idProduct,
394 Descriptor->bFirstInterface) + 1;
395
396 // allocate result buffer
397 DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
398 if (!DescriptionBuffer)
399 {
400 //
401 // failed to allocate memory
402 //
403 return STATUS_INSUFFICIENT_RESOURCES;
404 }
405
406 // copy description
407 RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
408 FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer;
409 FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR);
410 FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR);
411
412 //
413 // now init the compatible id
414 //
415 Index = swprintf(Buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", Descriptor->bFunctionClass, Descriptor->bFunctionSubClass, Descriptor->bFunctionProtocol) + 1;
416 Index += swprintf(&Buffer[Index], L"USB\\Class_%02x&SubClass_%02x", Descriptor->bFunctionClass, Descriptor->bFunctionSubClass) + 1;
417 Index += swprintf(&Buffer[Index], L"USB\\Class_%02x", Descriptor->bFunctionClass) + 1;
418
419 // allocate result buffer
420 DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
421 if (!DescriptionBuffer)
422 {
423 //
424 // failed to allocate memory
425 //
426 return STATUS_INSUFFICIENT_RESOURCES;
427 }
428
429 // copy description
430 RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
431 FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer;
432 FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR);
433 FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR);
434
435 //
436 // done
437 //
438 return STATUS_SUCCESS;
439 }
440
441 NTSTATUS
442 USBCCGP_EnumWithAssociationDescriptor(
443 IN PDEVICE_OBJECT DeviceObject)
444 {
445 ULONG DescriptorCount, Index;
446 PFDO_DEVICE_EXTENSION FDODeviceExtension;
447 NTSTATUS Status = STATUS_SUCCESS;
448
449 //
450 // get device extension
451 //
452 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
453 ASSERT(FDODeviceExtension->Common.IsFDO);
454
455 //
456 // count association descriptors
457 //
458 DescriptorCount = USBCCGP_CountAssociationDescriptors(FDODeviceExtension->ConfigurationDescriptor);
459 if (!DescriptorCount)
460 {
461 //
462 // no descriptors found
463 //
464 return STATUS_NOT_SUPPORTED;
465 }
466
467 //
468 // allocate function descriptor array
469 //
470 FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * DescriptorCount);
471 if (!FDODeviceExtension->FunctionDescriptor)
472 {
473 //
474 // no memory
475 //
476 DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count %x\n", DescriptorCount);
477 return STATUS_INSUFFICIENT_RESOURCES;
478 }
479
480 for (Index = 0; Index < DescriptorCount; Index++)
481 {
482 //
483 // init function descriptors
484 //
485 Status = USBCCGP_InitFunctionDescriptor(FDODeviceExtension, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
486 if (!NT_SUCCESS(Status))
487 {
488 //
489 // failed
490 //
491 return Status;
492 }
493 }
494
495 //
496 // store function descriptor count
497 //
498 FDODeviceExtension->FunctionDescriptorCount = DescriptorCount;
499
500 //
501 // done
502 //
503 return Status;
504 }
505
506 NTSTATUS
507 USBCCG_InitIdsWithInterfaceDescriptor(
508 IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
509 IN PUSB_INTERFACE_DESCRIPTOR Descriptor,
510 IN ULONG FunctionIndex,
511 OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
512 {
513 ULONG Index;
514 WCHAR Buffer[200];
515 LPWSTR DescriptionBuffer;
516 NTSTATUS Status;
517
518 //
519 // now init interface description
520 //
521 if (Descriptor->iInterface)
522 {
523 //
524 // get interface description
525 //
526 Status = USBCCGP_GetStringDescriptor(FDODeviceExtension->NextDeviceObject,
527 100 * sizeof(WCHAR),
528 Descriptor->iInterface,
529 0x0409, //FIXME
530 (PVOID*)&DescriptionBuffer);
531 if (!NT_SUCCESS(Status))
532 {
533 //
534 // no description
535 //
536 RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, L"");
537 }
538 else
539 {
540 //
541 // init description
542 //
543 RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, DescriptionBuffer);
544 }
545 DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor->FunctionDescription);
546 }
547
548
549 //
550 // now init hardware id
551 //
552 Index = swprintf(Buffer, L"USB\\VID_%04x&PID_%04x&Rev_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
553 FDODeviceExtension->DeviceDescriptor->idProduct,
554 FDODeviceExtension->DeviceDescriptor->bcdDevice,
555 FunctionIndex) + 1;
556 Index += swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
557 FDODeviceExtension->DeviceDescriptor->idProduct,
558 FunctionIndex) + 1;
559
560 // allocate result buffer
561 DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
562 if (!DescriptionBuffer)
563 {
564 //
565 // failed to allocate memory
566 //
567 return STATUS_INSUFFICIENT_RESOURCES;
568 }
569
570 // copy description
571 RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
572 FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer;
573 FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR);
574 FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR);
575
576 //
577 // now init the compatible id
578 //
579 Index = swprintf(Buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass, Descriptor->bInterfaceProtocol) + 1;
580 Index += swprintf(&Buffer[Index], L"USB\\Class_%02x&SubClass_%02x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass) + 1;
581 Index += swprintf(&Buffer[Index], L"USB\\Class_%02x", Descriptor->bInterfaceClass) + 1;
582
583 // allocate result buffer
584 DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
585 if (!DescriptionBuffer)
586 {
587 //
588 // failed to allocate memory
589 //
590 return STATUS_INSUFFICIENT_RESOURCES;
591 }
592
593 // copy description
594 RtlCopyMemory(DescriptionBuffer, Buffer, (Index + 1) * sizeof(WCHAR));
595 FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer;
596 FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR);
597 FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR);
598
599 //
600 // done
601 //
602 return STATUS_SUCCESS;
603 }
604
605
606 NTSTATUS
607 USBCCGP_LegacyEnum(
608 IN PDEVICE_OBJECT DeviceObject)
609 {
610 ULONG Index;
611 PFDO_DEVICE_EXTENSION FDODeviceExtension;
612 NTSTATUS Status = STATUS_SUCCESS;
613 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
614
615 //
616 // get device extension
617 //
618 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
619 ASSERT(FDODeviceExtension->Common.IsFDO);
620
621 //
622 // sanity check
623 //
624 ASSERT(FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
625
626 //
627 // allocate function array
628 //
629 FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
630 if (!FDODeviceExtension->FunctionDescriptor)
631 {
632 //
633 // no memory
634 //
635 DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor %lu\n", FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
636 return STATUS_INSUFFICIENT_RESOURCES;
637 }
638
639 //
640 // init function descriptors
641 //
642 FDODeviceExtension->FunctionDescriptorCount = 0;
643 for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
644 {
645 // get interface descriptor
646 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
647 if (InterfaceDescriptor == NULL)
648 {
649 //
650 // failed to find interface descriptor
651 //
652 DPRINT1("[USBCCGP] Failed to find interface descriptor index %lu\n", Index);
653 ASSERT(FALSE);
654 return STATUS_UNSUCCESSFUL;
655 }
656
657 //
658 // init function descriptor
659 //
660 FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index;
661 FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1;
662 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1);
663 if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList)
664 {
665 //
666 // no memory
667 //
668 return STATUS_INSUFFICIENT_RESOURCES;
669 }
670
671 //
672 // store interface descriptor
673 //
674 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor;
675
676 //
677 // now init the device ids
678 //
679 Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
680 if (!NT_SUCCESS(Status))
681 {
682 //
683 // failed to init ids
684 //
685 DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
686 return Status;
687 }
688
689 //
690 // store function count
691 //
692 FDODeviceExtension->FunctionDescriptorCount++;
693 }
694
695 //
696 // done
697 //
698 return Status;
699 }
700
701 NTSTATUS
702 USBCCGP_EnumWithUnionFunctionDescriptors(
703 IN PDEVICE_OBJECT DeviceObject)
704 {
705 UNIMPLEMENTED;
706 return STATUS_NOT_IMPLEMENTED;
707 }
708
709 NTSTATUS
710 USBCCGP_EnumWithAudioLegacy(
711 IN PDEVICE_OBJECT DeviceObject)
712 {
713 ULONG Index;
714 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, FirstDescriptor = NULL;
715 PFDO_DEVICE_EXTENSION FDODeviceExtension;
716 NTSTATUS Status = STATUS_SUCCESS;
717
718 //
719 // get device extension
720 //
721 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
722 ASSERT(FDODeviceExtension->Common.IsFDO);
723
724
725 //
726 // first check if all interfaces belong to the same audio class
727 //
728 for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
729 {
730 //
731 // get interface descriptor
732 //
733 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
734 DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor);
735 ASSERT(InterfaceDescriptor);
736
737 if (InterfaceDescriptor->bInterfaceClass != 0x1)
738 {
739 //
740 // collection contains non audio class
741 //
742 return STATUS_UNSUCCESSFUL;
743 }
744
745 if (FirstDescriptor == NULL)
746 {
747 //
748 // store interface descriptor
749 //
750 FirstDescriptor = InterfaceDescriptor;
751 continue;
752 }
753
754 if (FirstDescriptor->bInterfaceSubClass == InterfaceDescriptor->bInterfaceSubClass)
755 {
756 //
757 // interface subclass must be different from the first interface
758 //
759 return STATUS_UNSUCCESSFUL;
760 }
761 }
762
763 //
764 // this is an composite audio device
765 //
766 DPRINT("[USBCCGP] Audio Composite Device detected\n");
767
768 //
769 // audio interfaces are all grouped into one single function
770 //
771 FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR));
772 if (!FDODeviceExtension->FunctionDescriptor)
773 {
774 //
775 // no memory
776 //
777 DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count\n");
778 return STATUS_INSUFFICIENT_RESOURCES;
779 }
780
781 //
782 // init function number
783 //
784 FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
785
786 //
787 // store interfaces
788 //
789 Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList);
790 if (!NT_SUCCESS(Status))
791 {
792 //
793 // failed to allocate descriptor array
794 //
795 DPRINT1("[USBCCGP] Failed to allocate descriptor array %lx\n", Status);
796 return Status;
797 }
798
799 //
800 // now init the device ids
801 //
802 Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, FirstDescriptor, 0, &FDODeviceExtension->FunctionDescriptor[0]);
803 if (!NT_SUCCESS(Status))
804 {
805 //
806 // failed to init ids
807 //
808 DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
809 return Status;
810 }
811
812 //
813 // number of interfaces
814 //
815 FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces;
816
817 //
818 // store function count
819 //
820 FDODeviceExtension->FunctionDescriptorCount = 1;
821
822 //
823 // done
824 //
825 return STATUS_SUCCESS;
826 }
827
828 NTSTATUS
829 USBCCGP_EnumerateFunctions(
830 IN PDEVICE_OBJECT DeviceObject)
831 {
832 NTSTATUS Status;
833 PFDO_DEVICE_EXTENSION FDODeviceExtension;
834
835 //
836 // get device extension
837 //
838 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
839 ASSERT(FDODeviceExtension->Common.IsFDO);
840
841 //
842 // first try with filter driver
843 //
844 Status = USBCCGP_CustomEnumWithInterface(DeviceObject);
845 if (NT_SUCCESS(Status))
846 {
847 //
848 // succeeded
849 //
850 return Status;
851 }
852
853 //
854 // enumerate functions with interface association descriptor
855 //
856 Status = USBCCGP_EnumWithAssociationDescriptor(DeviceObject);
857 if (NT_SUCCESS(Status))
858 {
859 //
860 // succeeded
861 //
862 return Status;
863 }
864
865 #if 0
866 //
867 // try with union function descriptors
868 //
869 Status = USBCCGP_EnumWithUnionFunctionDescriptors(DeviceObject);
870 if (NT_SUCCESS(Status))
871 {
872 //
873 // succeeded
874 //
875 return Status;
876 }
877 #endif
878
879 //
880 // try with legacy audio methods
881 //
882 Status = USBCCGP_EnumWithAudioLegacy(DeviceObject);
883 if (NT_SUCCESS(Status))
884 {
885 //
886 // succeeded
887 //
888 return Status;
889 }
890
891 //
892 // try with legacy enumeration
893 //
894 return USBCCGP_LegacyEnum(DeviceObject);
895 }