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