* Sync up to trunk head (r65074).
[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 for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
643 {
644 // get interface descriptor
645 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
646 if (InterfaceDescriptor == NULL)
647 {
648 //
649 // failed to find interface descriptor
650 //
651 DPRINT1("[USBCCGP] Failed to find interface descriptor index %lu\n", Index);
652 ASSERT(FALSE);
653 return STATUS_UNSUCCESSFUL;
654 }
655
656 //
657 // init function descriptor
658 //
659 FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index;
660 FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1;
661 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1);
662 if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList)
663 {
664 //
665 // no memory
666 //
667 return STATUS_INSUFFICIENT_RESOURCES;
668 }
669
670 //
671 // store interface descriptor
672 //
673 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor;
674
675 //
676 // now init the device ids
677 //
678 Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
679 if (!NT_SUCCESS(Status))
680 {
681 //
682 // failed to init ids
683 //
684 DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
685 return Status;
686 }
687
688 //
689 // store function count
690 //
691 FDODeviceExtension->FunctionDescriptorCount++;
692 }
693
694 //
695 // done
696 //
697 return Status;
698 }
699
700 NTSTATUS
701 USBCCGP_EnumWithUnionFunctionDescriptors(
702 IN PDEVICE_OBJECT DeviceObject)
703 {
704 UNIMPLEMENTED
705 return STATUS_NOT_IMPLEMENTED;
706 }
707
708 NTSTATUS
709 USBCCGP_EnumWithAudioLegacy(
710 IN PDEVICE_OBJECT DeviceObject)
711 {
712 ULONG Index;
713 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, FirstDescriptor = NULL;
714 PFDO_DEVICE_EXTENSION FDODeviceExtension;
715 NTSTATUS Status = STATUS_SUCCESS;
716
717 //
718 // get device extension
719 //
720 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
721 ASSERT(FDODeviceExtension->Common.IsFDO);
722
723
724 //
725 // first check if all interfaces belong to the same audio class
726 //
727 for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
728 {
729 //
730 // get interface descriptor
731 //
732 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
733 DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor);
734 ASSERT(InterfaceDescriptor);
735
736 if (InterfaceDescriptor->bInterfaceClass != 0x1)
737 {
738 //
739 // collection contains non audio class
740 //
741 return STATUS_UNSUCCESSFUL;
742 }
743
744 if (FirstDescriptor == NULL)
745 {
746 //
747 // store interface descriptor
748 //
749 FirstDescriptor = InterfaceDescriptor;
750 continue;
751 }
752
753 if (FirstDescriptor->bInterfaceSubClass == InterfaceDescriptor->bInterfaceSubClass)
754 {
755 //
756 // interface subclass must be different from the first interface
757 //
758 return STATUS_UNSUCCESSFUL;
759 }
760 }
761
762 //
763 // this is an composite audio device
764 //
765 DPRINT("[USBCCGP] Audio Composite Device detected\n");
766
767 //
768 // audio interfaces are all grouped into one single function
769 //
770 FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR));
771 if (!FDODeviceExtension->FunctionDescriptor)
772 {
773 //
774 // no memory
775 //
776 DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count\n");
777 return STATUS_INSUFFICIENT_RESOURCES;
778 }
779
780 //
781 // init function number
782 //
783 FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
784
785 //
786 // store interfaces
787 //
788 Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList);
789 if (!NT_SUCCESS(Status))
790 {
791 //
792 // failed to allocate descriptor array
793 //
794 DPRINT1("[USBCCGP] Failed to allocate descriptor array %lx\n", Status);
795 return Status;
796 }
797
798 //
799 // now init the device ids
800 //
801 Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, FirstDescriptor, 0, &FDODeviceExtension->FunctionDescriptor[0]);
802 if (!NT_SUCCESS(Status))
803 {
804 //
805 // failed to init ids
806 //
807 DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status);
808 return Status;
809 }
810
811 //
812 // number of interfaces
813 //
814 FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces;
815
816 //
817 // store function count
818 //
819 FDODeviceExtension->FunctionDescriptorCount = 1;
820
821 //
822 // done
823 //
824 return STATUS_SUCCESS;
825 }
826
827 NTSTATUS
828 USBCCGP_EnumerateFunctions(
829 IN PDEVICE_OBJECT DeviceObject)
830 {
831 NTSTATUS Status;
832 PFDO_DEVICE_EXTENSION FDODeviceExtension;
833
834 //
835 // get device extension
836 //
837 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
838 ASSERT(FDODeviceExtension->Common.IsFDO);
839
840 //
841 // first try with filter driver
842 //
843 Status = USBCCGP_CustomEnumWithInterface(DeviceObject);
844 if (NT_SUCCESS(Status))
845 {
846 //
847 // succeeded
848 //
849 return Status;
850 }
851
852 //
853 // enumerate functions with interface association descriptor
854 //
855 Status = USBCCGP_EnumWithAssociationDescriptor(DeviceObject);
856 if (NT_SUCCESS(Status))
857 {
858 //
859 // succeeded
860 //
861 return Status;
862 }
863
864 #if 0
865 //
866 // try with union function descriptors
867 //
868 Status = USBCCGP_EnumWithUnionFunctionDescriptors(DeviceObject);
869 if (NT_SUCCESS(Status))
870 {
871 //
872 // succeeded
873 //
874 return Status;
875 }
876 #endif
877
878 //
879 // try with legacy audio methods
880 //
881 Status = USBCCGP_EnumWithAudioLegacy(DeviceObject);
882 if (NT_SUCCESS(Status))
883 {
884 //
885 // succeeded
886 //
887 return Status;
888 }
889
890 //
891 // try with legacy enumeration
892 //
893 return USBCCGP_LegacyEnum(DeviceObject);
894 }