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