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