Reactos
at master 936 lines 29 kB view raw
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 17NTSTATUS 18USBCCGP_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 96NTSTATUS 97USBCCGP_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 159ULONG 160USBCCGP_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 200PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR 201USBCCGP_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 250NTSTATUS 251USBCCGP_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 313NTSTATUS 314USBCCGP_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 441NTSTATUS 442USBCCGP_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 506NTSTATUS 507USBCCG_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 606NTSTATUS 607USBCCGP_LegacyEnum( 608 IN PDEVICE_OBJECT DeviceObject) 609{ 610 ULONG Index, SubIndex; 611 PFDO_DEVICE_EXTENSION FDODeviceExtension; 612 NTSTATUS Status = STATUS_SUCCESS; 613 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, NextInterfaceDescriptor; 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 = FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; 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 SubIndex = 0; 658 if (InterfaceDescriptor->bInterfaceClass == USB_DEVICE_CLASS_AUDIO) 659 { 660 // AUDIO CLASS lets group all audio interfaces together 661 // 662 // init function descriptor 663 // 664 FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index; 665 FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1; 666 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces); 667 if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList) 668 { 669 // 670 // no memory 671 // 672 FreeItem(FDODeviceExtension->FunctionDescriptor); 673 FDODeviceExtension->FunctionDescriptor = NULL; 674 FDODeviceExtension->FunctionDescriptorCount = 0; 675 return STATUS_INSUFFICIENT_RESOURCES; 676 } 677 678 // 679 // store interface descriptor 680 // 681 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex] = InterfaceDescriptor; 682 while (TRUE) 683 { 684 NextInterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index + SubIndex + 1, 0, -1, -1, -1); 685 if (!NextInterfaceDescriptor || NextInterfaceDescriptor->bInterfaceClass != USB_DEVICE_CLASS_AUDIO) 686 { 687 // end of collection 688 break; 689 } 690 SubIndex++; 691 ASSERT(SubIndex < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces); 692 FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces++; 693 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex] = NextInterfaceDescriptor; 694 } 695 } 696 else 697 { 698 // 699 // init function descriptor 700 // 701 FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index; 702 FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1; 703 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR)); 704 if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList) 705 { 706 // 707 // no memory 708 // 709 return STATUS_INSUFFICIENT_RESOURCES; 710 } 711 712 // 713 // store interface descriptor 714 // 715 FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor; 716 } 717 718 // 719 // now init the device ids 720 // 721 Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, Index, &FDODeviceExtension->FunctionDescriptor[Index]); 722 if (!NT_SUCCESS(Status)) 723 { 724 // 725 // failed to init ids 726 // 727 DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status); 728 return Status; 729 } 730 // 731 // increment interface count 732 // 733 Index += SubIndex; 734 } 735 736 // 737 // done 738 // 739 return Status; 740} 741 742NTSTATUS 743USBCCGP_EnumWithUnionFunctionDescriptors( 744 IN PDEVICE_OBJECT DeviceObject) 745{ 746 UNIMPLEMENTED; 747 return STATUS_NOT_IMPLEMENTED; 748} 749 750NTSTATUS 751USBCCGP_EnumWithAudioLegacy( 752 IN PDEVICE_OBJECT DeviceObject) 753{ 754 ULONG Index; 755 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, FirstDescriptor = NULL; 756 PFDO_DEVICE_EXTENSION FDODeviceExtension; 757 NTSTATUS Status = STATUS_SUCCESS; 758 759 // 760 // get device extension 761 // 762 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 763 ASSERT(FDODeviceExtension->Common.IsFDO); 764 765 766 // 767 // first check if all interfaces belong to the same audio class 768 // 769 for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++) 770 { 771 // 772 // get interface descriptor 773 // 774 InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1); 775 DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor); 776 ASSERT(InterfaceDescriptor); 777 778 if (InterfaceDescriptor->bInterfaceClass != USB_DEVICE_CLASS_AUDIO) 779 { 780 // 781 // collection contains non audio class 782 // 783 return STATUS_UNSUCCESSFUL; 784 } 785 786 if (FirstDescriptor == NULL) 787 { 788 // 789 // store interface descriptor 790 // 791 FirstDescriptor = InterfaceDescriptor; 792 continue; 793 } 794 795 if (FirstDescriptor->bInterfaceSubClass == InterfaceDescriptor->bInterfaceSubClass) 796 { 797 // 798 // interface subclass must be different from the first interface 799 // 800 return STATUS_UNSUCCESSFUL; 801 } 802 } 803 804 // 805 // this is an composite audio device 806 // 807 DPRINT("[USBCCGP] Audio Composite Device detected\n"); 808 809 // 810 // audio interfaces are all grouped into one single function 811 // 812 FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR)); 813 if (!FDODeviceExtension->FunctionDescriptor) 814 { 815 // 816 // no memory 817 // 818 DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count\n"); 819 return STATUS_INSUFFICIENT_RESOURCES; 820 } 821 822 // 823 // init function number 824 // 825 FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0; 826 827 // 828 // store interfaces 829 // 830 Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList); 831 if (!NT_SUCCESS(Status)) 832 { 833 // 834 // failed to allocate descriptor array 835 // 836 DPRINT1("[USBCCGP] Failed to allocate descriptor array %lx\n", Status); 837 return Status; 838 } 839 840 // 841 // now init the device ids 842 // 843 Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, FirstDescriptor, 0, &FDODeviceExtension->FunctionDescriptor[0]); 844 if (!NT_SUCCESS(Status)) 845 { 846 // 847 // failed to init ids 848 // 849 DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status); 850 return Status; 851 } 852 853 // 854 // number of interfaces 855 // 856 FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; 857 858 // 859 // store function count 860 // 861 FDODeviceExtension->FunctionDescriptorCount = 1; 862 863 // 864 // done 865 // 866 return STATUS_SUCCESS; 867} 868 869NTSTATUS 870USBCCGP_EnumerateFunctions( 871 IN PDEVICE_OBJECT DeviceObject) 872{ 873 NTSTATUS Status; 874 PFDO_DEVICE_EXTENSION FDODeviceExtension; 875 876 // 877 // get device extension 878 // 879 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 880 ASSERT(FDODeviceExtension->Common.IsFDO); 881 882 // 883 // first try with filter driver 884 // 885 Status = USBCCGP_CustomEnumWithInterface(DeviceObject); 886 if (NT_SUCCESS(Status)) 887 { 888 // 889 // succeeded 890 // 891 return Status; 892 } 893 894 // 895 // enumerate functions with interface association descriptor 896 // 897 Status = USBCCGP_EnumWithAssociationDescriptor(DeviceObject); 898 if (NT_SUCCESS(Status)) 899 { 900 // 901 // succeeded 902 // 903 return Status; 904 } 905 906#if 0 907 // 908 // try with union function descriptors 909 // 910 Status = USBCCGP_EnumWithUnionFunctionDescriptors(DeviceObject); 911 if (NT_SUCCESS(Status)) 912 { 913 // 914 // succeeded 915 // 916 return Status; 917 } 918#endif 919 920 // 921 // try with legacy audio methods 922 // 923 Status = USBCCGP_EnumWithAudioLegacy(DeviceObject); 924 if (NT_SUCCESS(Status)) 925 { 926 // 927 // succeeded 928 // 929 return Status; 930 } 931 932 // 933 // try with legacy enumeration 934 // 935 return USBCCGP_LegacyEnum(DeviceObject); 936}