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/pdo.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 #include <ntddk.h> 15 16 #define NDEBUG 17 #include <debug.h> 18 19 NTSTATUS 20 USBCCGP_PdoHandleQueryDeviceText( 21 IN PDEVICE_OBJECT DeviceObject, 22 IN OUT PIRP Irp) 23 { 24 LPWSTR Buffer; 25 PPDO_DEVICE_EXTENSION PDODeviceExtension; 26 LPWSTR GenericString = L"Composite USB Device"; 27 // 28 // get device extension 29 // 30 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 31 32 // 33 // is there a device description 34 // 35 if (PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length) 36 { 37 // 38 // allocate buffer 39 // 40 Buffer = AllocateItem(NonPagedPool, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length + sizeof(WCHAR)); 41 if (!Buffer) 42 { 43 // 44 // no memory 45 // 46 return STATUS_INSUFFICIENT_RESOURCES; 47 } 48 49 // 50 // copy buffer 51 // 52 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 53 RtlCopyMemory(Buffer, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Buffer, PDODeviceExtension->FunctionDescriptor->FunctionDescription.Length); 54 return STATUS_SUCCESS; 55 } 56 57 // 58 // FIXME use GenericCompositeUSBDeviceString 59 // 60 UNIMPLEMENTED; 61 Buffer = AllocateItem(PagedPool, (wcslen(GenericString) + 1) * sizeof(WCHAR)); 62 if (!Buffer) 63 { 64 // 65 // no memory 66 // 67 return STATUS_INSUFFICIENT_RESOURCES; 68 } 69 RtlCopyMemory(Buffer, GenericString, (wcslen(GenericString) + 1) * sizeof(WCHAR)); 70 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 71 72 return STATUS_SUCCESS; 73 } 74 75 NTSTATUS 76 USBCCGP_PdoHandleDeviceRelations( 77 IN PDEVICE_OBJECT DeviceObject, 78 IN OUT PIRP Irp) 79 { 80 PDEVICE_RELATIONS DeviceRelations; 81 PIO_STACK_LOCATION IoStack; 82 83 DPRINT("USBCCGP_PdoHandleDeviceRelations\n"); 84 85 // 86 // get current irp stack location 87 // 88 IoStack = IoGetCurrentIrpStackLocation(Irp); 89 90 // 91 // check if relation type is BusRelations 92 // 93 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 94 { 95 // 96 // PDO handles only target device relation 97 // 98 return Irp->IoStatus.Status; 99 } 100 101 // 102 // allocate device relations 103 // 104 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); 105 if (!DeviceRelations) 106 { 107 // 108 // no memory 109 // 110 return STATUS_INSUFFICIENT_RESOURCES; 111 } 112 113 // 114 // initialize device relations 115 // 116 DeviceRelations->Count = 1; 117 DeviceRelations->Objects[0] = DeviceObject; 118 ObReferenceObject(DeviceObject); 119 120 // 121 // store result 122 // 123 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 124 125 // 126 // completed successfully 127 // 128 return STATUS_SUCCESS; 129 } 130 131 NTSTATUS 132 USBCCGP_PdoAppendInterfaceNumber( 133 IN LPWSTR DeviceId, 134 IN ULONG InterfaceNumber, 135 OUT LPWSTR *OutString) 136 { 137 ULONG Length = 0, StringLength; 138 LPWSTR String; 139 140 // 141 // count length of string 142 // 143 String = DeviceId; 144 while (*String) 145 { 146 StringLength = wcslen(String) + 1; 147 Length += StringLength; 148 Length += 6; //&MI_XX 149 String += StringLength; 150 } 151 152 // 153 // now allocate the buffer 154 // 155 String = AllocateItem(NonPagedPool, (Length + 2) * sizeof(WCHAR)); 156 if (!String) 157 { 158 // 159 // no memory 160 // 161 return STATUS_INSUFFICIENT_RESOURCES; 162 } 163 164 // 165 // store result 166 // 167 *OutString = String; 168 169 while (*DeviceId) 170 { 171 StringLength = swprintf(String, L"%s&MI_%02x", DeviceId, InterfaceNumber) + 1; 172 Length = wcslen(DeviceId) + 1; 173 DPRINT("String %p\n", String); 174 175 // 176 // next string 177 // 178 String += StringLength; 179 DeviceId += Length; 180 } 181 182 // 183 // success 184 // 185 return STATUS_SUCCESS; 186 } 187 188 189 NTSTATUS 190 USBCCGP_PdoHandleQueryId( 191 PDEVICE_OBJECT DeviceObject, 192 PIRP Irp) 193 { 194 PIO_STACK_LOCATION IoStack; 195 PUNICODE_STRING DeviceString = NULL; 196 PPDO_DEVICE_EXTENSION PDODeviceExtension; 197 NTSTATUS Status; 198 LPWSTR Buffer; 199 200 // 201 // get current irp stack location 202 // 203 IoStack = IoGetCurrentIrpStackLocation(Irp); 204 205 // 206 // get device extension 207 // 208 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 209 210 211 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID) 212 { 213 // 214 // handle query device id 215 // 216 Status = USBCCGP_SyncForwardIrp(PDODeviceExtension->NextDeviceObject, Irp); 217 if (NT_SUCCESS(Status)) 218 { 219 // 220 // allocate buffer 221 // 222 Buffer = AllocateItem(NonPagedPool, (wcslen((LPWSTR)Irp->IoStatus.Information) + 7) * sizeof(WCHAR)); 223 if (Buffer) 224 { 225 // 226 // append interface number 227 // 228 ASSERT(Irp->IoStatus.Information); 229 swprintf(Buffer, L"%s&MI_%02x", (LPWSTR)Irp->IoStatus.Information, PDODeviceExtension->FunctionDescriptor->FunctionNumber); 230 DPRINT("BusQueryDeviceID %S\n", Buffer); 231 232 ExFreePool((PVOID)Irp->IoStatus.Information); 233 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 234 } 235 else 236 { 237 // 238 // no memory 239 // 240 Status = STATUS_INSUFFICIENT_RESOURCES; 241 } 242 } 243 return Status; 244 } 245 else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) 246 { 247 // 248 // handle instance id 249 // 250 DeviceString = &PDODeviceExtension->FunctionDescriptor->HardwareId; 251 } 252 else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) 253 { 254 // 255 // handle instance id 256 // 257 Buffer = AllocateItem(NonPagedPool, 5 * sizeof(WCHAR)); 258 if (!Buffer) 259 { 260 // 261 // no memory 262 // 263 return STATUS_INSUFFICIENT_RESOURCES; 264 } 265 266 // 267 // use function number 268 // 269 swprintf(Buffer, L"%04x", PDODeviceExtension->FunctionDescriptor->FunctionNumber); 270 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 271 return STATUS_SUCCESS; 272 } 273 else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) 274 { 275 // 276 // handle instance id 277 // 278 DeviceString = &PDODeviceExtension->FunctionDescriptor->CompatibleId; 279 } 280 else 281 { 282 // 283 // unsupported query 284 // 285 return Irp->IoStatus.Status; 286 } 287 288 // 289 // sanity check 290 // 291 ASSERT(DeviceString != NULL); 292 293 // 294 // allocate buffer 295 // 296 Buffer = AllocateItem(NonPagedPool, DeviceString->Length + sizeof(WCHAR)); 297 if (!Buffer) 298 { 299 // 300 // no memory 301 // 302 return STATUS_INSUFFICIENT_RESOURCES; 303 } 304 305 // 306 // copy buffer 307 // 308 RtlCopyMemory(Buffer, DeviceString->Buffer, DeviceString->Length); 309 Buffer[DeviceString->Length / sizeof(WCHAR)] = UNICODE_NULL; 310 Irp->IoStatus.Information = (ULONG_PTR)Buffer; 311 312 return STATUS_SUCCESS; 313 } 314 315 NTSTATUS 316 PDO_HandlePnp( 317 PDEVICE_OBJECT DeviceObject, 318 PIRP Irp) 319 { 320 PIO_STACK_LOCATION IoStack; 321 PPDO_DEVICE_EXTENSION PDODeviceExtension; 322 NTSTATUS Status; 323 ULONG Index, bFound; 324 325 // 326 // get current stack location 327 // 328 IoStack = IoGetCurrentIrpStackLocation(Irp); 329 330 // 331 // get device extension 332 // 333 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 334 335 // 336 // sanity check 337 // 338 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE); 339 340 switch(IoStack->MinorFunction) 341 { 342 case IRP_MN_QUERY_DEVICE_RELATIONS: 343 { 344 // 345 // handle device relations 346 // 347 Status = USBCCGP_PdoHandleDeviceRelations(DeviceObject, Irp); 348 break; 349 } 350 case IRP_MN_QUERY_DEVICE_TEXT: 351 { 352 // 353 // handle query device text 354 // 355 Status = USBCCGP_PdoHandleQueryDeviceText(DeviceObject, Irp); 356 break; 357 } 358 case IRP_MN_QUERY_ID: 359 { 360 // 361 // handle request 362 // 363 Status = USBCCGP_PdoHandleQueryId(DeviceObject, Irp); 364 break; 365 } 366 case IRP_MN_REMOVE_DEVICE: 367 { 368 // 369 // remove us from the fdo's pdo list 370 // 371 bFound = FALSE; 372 for(Index = 0; Index < PDODeviceExtension->FDODeviceExtension->FunctionDescriptorCount; Index++) 373 { 374 if (PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] == DeviceObject) 375 { 376 // 377 // remove us 378 // 379 PDODeviceExtension->FDODeviceExtension->ChildPDO[Index] = NULL; 380 bFound = TRUE; 381 break; 382 } 383 } 384 385 // 386 // Complete the IRP 387 // 388 Irp->IoStatus.Status = STATUS_SUCCESS; 389 IoCompleteRequest(Irp, IO_NO_INCREMENT); 390 391 if (bFound) 392 { 393 // 394 // Delete the device object 395 // 396 IoDeleteDevice(DeviceObject); 397 } 398 return STATUS_SUCCESS; 399 } 400 case IRP_MN_QUERY_CAPABILITIES: 401 { 402 // 403 // copy device capabilities 404 // 405 RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES)); 406 407 /* Complete the IRP */ 408 Irp->IoStatus.Status = STATUS_SUCCESS; 409 IoCompleteRequest(Irp, IO_NO_INCREMENT); 410 return STATUS_SUCCESS; 411 } 412 case IRP_MN_QUERY_REMOVE_DEVICE: 413 case IRP_MN_QUERY_STOP_DEVICE: 414 { 415 // 416 // sure 417 // 418 Status = STATUS_SUCCESS; 419 break; 420 } 421 case IRP_MN_START_DEVICE: 422 { 423 // 424 // no-op for PDO 425 // 426 DPRINT("[USBCCGP] PDO IRP_MN_START\n"); 427 Status = STATUS_SUCCESS; 428 break; 429 } 430 case IRP_MN_QUERY_INTERFACE: 431 { 432 // 433 // forward to lower device object 434 // 435 IoSkipCurrentIrpStackLocation(Irp); 436 return IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); 437 } 438 default: 439 { 440 // 441 // do nothing 442 // 443 Status = Irp->IoStatus.Status; 444 break; 445 } 446 } 447 448 // 449 // complete request 450 // 451 if (Status != STATUS_PENDING) 452 { 453 // 454 // store result 455 // 456 Irp->IoStatus.Status = Status; 457 458 // 459 // complete request 460 // 461 IoCompleteRequest(Irp, IO_NO_INCREMENT); 462 } 463 464 // 465 // done processing 466 // 467 return Status; 468 469 } 470 471 NTSTATUS 472 USBCCGP_BuildConfigurationDescriptor( 473 PDEVICE_OBJECT DeviceObject, 474 PIRP Irp) 475 { 476 PIO_STACK_LOCATION IoStack; 477 PPDO_DEVICE_EXTENSION PDODeviceExtension; 478 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; 479 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; 480 ULONG TotalSize, Index; 481 ULONG Size; 482 PURB Urb; 483 PVOID Buffer; 484 PUCHAR BufferPtr; 485 UCHAR InterfaceNumber; 486 487 // 488 // get current stack location 489 // 490 IoStack = IoGetCurrentIrpStackLocation(Irp); 491 492 DPRINT("USBCCGP_BuildConfigurationDescriptor\n"); 493 494 // 495 // get device extension 496 // 497 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 498 499 // 500 // get configuration descriptor 501 // 502 ConfigurationDescriptor = PDODeviceExtension->ConfigurationDescriptor; 503 504 // 505 // calculate size of configuration descriptor 506 // 507 TotalSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); 508 509 for (Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++) 510 { 511 // 512 // get current interface descriptor 513 // 514 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index]; 515 InterfaceNumber = InterfaceDescriptor->bInterfaceNumber; 516 517 // 518 // add to size and move to next descriptor 519 // 520 TotalSize += InterfaceDescriptor->bLength; 521 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); 522 523 do 524 { 525 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength)) 526 { 527 // 528 // reached end of configuration descriptor 529 // 530 break; 531 } 532 533 // 534 // association descriptors are removed 535 // 536 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE) 537 { 538 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) 539 { 540 if (InterfaceNumber != InterfaceDescriptor->bInterfaceNumber) 541 { 542 // 543 // reached next descriptor 544 // 545 break; 546 } 547 548 // 549 // include alternate descriptor 550 // 551 } 552 553 // 554 // append size 555 // 556 TotalSize += InterfaceDescriptor->bLength; 557 } 558 559 // 560 // move to next descriptor 561 // 562 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); 563 } while(TRUE); 564 } 565 566 // 567 // now allocate temporary buffer for the configuration descriptor 568 // 569 Buffer = AllocateItem(NonPagedPool, TotalSize); 570 if (!Buffer) 571 { 572 // 573 // failed to allocate buffer 574 // 575 DPRINT1("[USBCCGP] Failed to allocate %lu Bytes\n", TotalSize); 576 return STATUS_INSUFFICIENT_RESOURCES; 577 } 578 579 // 580 // first copy the configuration descriptor 581 // 582 RtlCopyMemory(Buffer, ConfigurationDescriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR)); 583 BufferPtr = (PUCHAR)((ULONG_PTR)Buffer + ConfigurationDescriptor->bLength); 584 585 for (Index = 0; Index < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; Index++) 586 { 587 // 588 // get current interface descriptor 589 // 590 InterfaceDescriptor = PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[Index]; 591 InterfaceNumber = InterfaceDescriptor->bInterfaceNumber; 592 593 // 594 // copy descriptor and move to next descriptor 595 // 596 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength); 597 BufferPtr += InterfaceDescriptor->bLength; 598 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); 599 600 do 601 { 602 if ((ULONG_PTR)InterfaceDescriptor >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength)) 603 { 604 // 605 // reached end of configuration descriptor 606 // 607 break; 608 } 609 610 // 611 // association descriptors are removed 612 // 613 if (InterfaceDescriptor->bDescriptorType != USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE) 614 { 615 if (InterfaceDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) 616 { 617 if (InterfaceNumber != InterfaceDescriptor->bInterfaceNumber) 618 { 619 // 620 // reached next descriptor 621 // 622 break; 623 } 624 625 // 626 // include alternate descriptor 627 // 628 DPRINT("InterfaceDescriptor %p Alternate %x InterfaceNumber %x\n", InterfaceDescriptor, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bInterfaceNumber); 629 } 630 631 // 632 // copy descriptor 633 // 634 RtlCopyMemory(BufferPtr, InterfaceDescriptor, InterfaceDescriptor->bLength); 635 BufferPtr += InterfaceDescriptor->bLength; 636 } 637 638 // 639 // move to next descriptor 640 // 641 InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); 642 } while(TRUE); 643 } 644 645 // 646 // modify configuration descriptor 647 // 648 ConfigurationDescriptor = Buffer; 649 ConfigurationDescriptor->wTotalLength = (USHORT)TotalSize; 650 ConfigurationDescriptor->bNumInterfaces = PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; 651 652 // 653 // get urb 654 // 655 Urb = (PURB)IoStack->Parameters.Others.Argument1; 656 ASSERT(Urb); 657 658 // 659 // copy descriptor 660 // 661 Size = min(TotalSize, Urb->UrbControlDescriptorRequest.TransferBufferLength); 662 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, Size); 663 664 // 665 // store final size 666 // 667 Urb->UrbControlDescriptorRequest.TransferBufferLength = Size; 668 669 // 670 // free buffer 671 // 672 FreeItem(Buffer); 673 674 // 675 // done 676 // 677 return STATUS_SUCCESS; 678 } 679 680 NTSTATUS 681 USBCCGP_PDOSelectConfiguration( 682 PDEVICE_OBJECT DeviceObject, 683 PIRP Irp) 684 { 685 PIO_STACK_LOCATION IoStack; 686 PPDO_DEVICE_EXTENSION PDODeviceExtension; 687 PURB Urb, NewUrb; 688 PUSBD_INTERFACE_INFORMATION InterfaceInformation; 689 ULONG InterfaceIndex, Length; 690 PUSBD_INTERFACE_LIST_ENTRY Entry; 691 ULONG NeedSelect, FoundInterface; 692 NTSTATUS Status; 693 694 // 695 // get current stack location 696 // 697 IoStack = IoGetCurrentIrpStackLocation(Irp); 698 699 // 700 // get device extension 701 // 702 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 703 704 // 705 // get urb 706 // 707 Urb = (PURB)IoStack->Parameters.Others.Argument1; 708 ASSERT(Urb); 709 710 // 711 // is there already an configuration handle 712 // 713 if (Urb->UrbSelectConfiguration.ConfigurationHandle) 714 { 715 // 716 // nothing to do 717 // 718 return STATUS_SUCCESS; 719 } 720 721 // 722 // if there is no configuration descriptor, unconfigure the device 723 // 724 if (Urb->UrbSelectConfiguration.ConfigurationDescriptor == NULL) 725 { 726 return STATUS_SUCCESS; 727 } 728 729 // sanity checks 730 //C_ASSERT(sizeof(struct _URB_HEADER) == 16); 731 //C_ASSERT(FIELD_OFFSET(struct _URB_SELECT_CONFIGURATION, Interface.Length) == 24); 732 //C_ASSERT(sizeof(USBD_INTERFACE_INFORMATION) == 36); 733 //C_ASSERT(sizeof(struct _URB_SELECT_CONFIGURATION) == 0x3C); 734 735 // available buffer length 736 Length = Urb->UrbSelectConfiguration.Hdr.Length - FIELD_OFFSET(struct _URB_SELECT_CONFIGURATION, Interface.Length); 737 738 // 739 // check all interfaces 740 // 741 InterfaceInformation = &Urb->UrbSelectConfiguration.Interface; 742 743 Entry = NULL; 744 do 745 { 746 DPRINT1("[USBCCGP] SelectConfiguration Function %x InterfaceNumber %x Alternative %x Length %lu InterfaceInformation->Length %lu\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, Length, InterfaceInformation->Length); 747 ASSERT(InterfaceInformation->Length); 748 // 749 // search for the interface in the local interface list 750 // 751 FoundInterface = FALSE; 752 for (InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->FunctionDescriptor->NumberOfInterfaces; InterfaceIndex++) 753 { 754 if (PDODeviceExtension->FunctionDescriptor->InterfaceDescriptorList[InterfaceIndex]->bInterfaceNumber == InterfaceInformation->InterfaceNumber) 755 { 756 // found interface entry 757 FoundInterface = TRUE; 758 break; 759 } 760 } 761 762 if (!FoundInterface) 763 { 764 // 765 // invalid parameter 766 // 767 DPRINT1("InterfaceInformation InterfaceNumber %x Alternative %x NumberOfPipes %x not found\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes); 768 return STATUS_INVALID_PARAMETER; 769 } 770 771 // 772 // now query the total interface list 773 // 774 Entry = NULL; 775 for (InterfaceIndex = 0; InterfaceIndex < PDODeviceExtension->InterfaceListCount; InterfaceIndex++) 776 { 777 if (PDODeviceExtension->InterfaceList[InterfaceIndex].Interface->InterfaceNumber == InterfaceInformation->InterfaceNumber) 778 { 779 // 780 // found entry 781 // 782 Entry = &PDODeviceExtension->InterfaceList[InterfaceIndex]; 783 } 784 } 785 786 // 787 // sanity check 788 // 789 ASSERT(Entry); 790 if (!Entry) 791 { 792 // 793 // corruption detected 794 // 795 KeBugCheck(0); 796 } 797 798 NeedSelect = FALSE; 799 if (Entry->InterfaceDescriptor->bAlternateSetting == InterfaceInformation->AlternateSetting) 800 { 801 for(InterfaceIndex = 0; InterfaceIndex < InterfaceInformation->NumberOfPipes; InterfaceIndex++) 802 { 803 if (InterfaceInformation->Pipes[InterfaceIndex].MaximumTransferSize != Entry->Interface->Pipes[InterfaceIndex].MaximumTransferSize) 804 { 805 // 806 // changed interface 807 // 808 NeedSelect = TRUE; 809 } 810 } 811 } 812 else 813 { 814 // 815 // need select as the interface number differ 816 // 817 NeedSelect = TRUE; 818 } 819 820 if (!NeedSelect) 821 { 822 // 823 // interface is already selected 824 // 825 ASSERT(Length >= Entry->Interface->Length); 826 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length); 827 828 // 829 // adjust remaining buffer size 830 // 831 ASSERT(Entry->Interface->Length); 832 Length -= Entry->Interface->Length; 833 834 // 835 // move to next output interface information 836 // 837 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length); 838 } 839 else 840 { 841 // 842 // select interface 843 // 844 DPRINT1("Selecting InterfaceIndex %lu AlternateSetting %lu NumberOfPipes %lu\n", InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting, InterfaceInformation->NumberOfPipes); 845 ASSERT(InterfaceInformation->Length == Entry->Interface->Length); 846 847 // 848 // build urb 849 // 850 NewUrb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes)); 851 if (!NewUrb) 852 { 853 // 854 // no memory 855 // 856 return STATUS_INSUFFICIENT_RESOURCES; 857 } 858 859 // 860 // now prepare interface urb 861 // 862 UsbBuildSelectInterfaceRequest(NewUrb, (USHORT)GET_SELECT_INTERFACE_REQUEST_SIZE(InterfaceInformation->NumberOfPipes), PDODeviceExtension->ConfigurationHandle, InterfaceInformation->InterfaceNumber, InterfaceInformation->AlternateSetting); 863 864 // 865 // now select the interface 866 // 867 Status = USBCCGP_SyncUrbRequest(PDODeviceExtension->NextDeviceObject, NewUrb); 868 DPRINT1("SelectInterface Status %x\n", Status); 869 870 if (!NT_SUCCESS(Status)) 871 { 872 // 873 // failed 874 // 875 break; 876 } 877 878 // 879 // update configuration info 880 // 881 ASSERT(Entry->Interface->Length >= NewUrb->UrbSelectInterface.Interface.Length); 882 ASSERT(Length >= NewUrb->UrbSelectInterface.Interface.Length); 883 RtlCopyMemory(Entry->Interface, &NewUrb->UrbSelectInterface.Interface, NewUrb->UrbSelectInterface.Interface.Length); 884 885 // 886 // update provided interface information 887 // 888 ASSERT(Length >= Entry->Interface->Length); 889 RtlCopyMemory(InterfaceInformation, Entry->Interface, Entry->Interface->Length); 890 891 // 892 // decrement remaining buffer size 893 // 894 ASSERT(Entry->Interface->Length); 895 Length -= Entry->Interface->Length; 896 897 // 898 // adjust output buffer offset 899 // 900 InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + Entry->Interface->Length); 901 902 // 903 // free urb 904 // 905 FreeItem(NewUrb); 906 } 907 908 } while(Length); 909 910 // 911 // store configuration handle 912 // 913 Urb->UrbSelectConfiguration.ConfigurationHandle = PDODeviceExtension->ConfigurationHandle; 914 915 DPRINT1("[USBCCGP] SelectConfiguration Function %x Completed\n", PDODeviceExtension->FunctionDescriptor->FunctionNumber); 916 917 // 918 // done 919 // 920 return STATUS_SUCCESS; 921 } 922 923 NTSTATUS 924 PDO_HandleInternalDeviceControl( 925 PDEVICE_OBJECT DeviceObject, 926 PIRP Irp) 927 { 928 PIO_STACK_LOCATION IoStack; 929 PPDO_DEVICE_EXTENSION PDODeviceExtension; 930 NTSTATUS Status; 931 PURB Urb; 932 933 // 934 // get current stack location 935 // 936 IoStack = IoGetCurrentIrpStackLocation(Irp); 937 938 // 939 // get device extension 940 // 941 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 942 943 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB) 944 { 945 // 946 // get urb 947 // 948 Urb = (PURB)IoStack->Parameters.Others.Argument1; 949 ASSERT(Urb); 950 DPRINT("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x\n", Urb->UrbHeader.Function); 951 952 if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION) 953 { 954 // 955 // select configuration 956 // 957 Status = USBCCGP_PDOSelectConfiguration(DeviceObject, Irp); 958 Irp->IoStatus.Status = Status; 959 IoCompleteRequest(Irp, IO_NO_INCREMENT); 960 return Status; 961 } 962 else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE) 963 { 964 if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE) 965 { 966 // 967 // is the buffer big enough 968 // 969 if (Urb->UrbControlDescriptorRequest.TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR)) 970 { 971 // 972 // invalid buffer size 973 // 974 DPRINT1("[USBCCGP] invalid device descriptor size %lu\n", Urb->UrbControlDescriptorRequest.TransferBufferLength); 975 Urb->UrbControlDescriptorRequest.TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR); 976 Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; 977 IoCompleteRequest(Irp, IO_NO_INCREMENT); 978 return STATUS_INVALID_BUFFER_SIZE; 979 } 980 981 // 982 // copy device descriptor 983 // 984 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); 985 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &PDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); 986 Irp->IoStatus.Status = STATUS_SUCCESS; 987 IoCompleteRequest(Irp, IO_NO_INCREMENT); 988 return STATUS_SUCCESS; 989 } 990 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE) 991 { 992 // 993 // build configuration descriptor 994 // 995 Status = USBCCGP_BuildConfigurationDescriptor(DeviceObject, Irp); 996 Irp->IoStatus.Status = Status; 997 IoCompleteRequest(Irp, IO_NO_INCREMENT); 998 return Status; 999 } 1000 else if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE) 1001 { 1002 PUSB_STRING_DESCRIPTOR StringDescriptor; 1003 1004 // 1005 // get the requested string descriptor 1006 // 1007 ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); 1008 Status = USBCCGP_GetDescriptor(PDODeviceExtension->FDODeviceExtension->NextDeviceObject, 1009 USB_STRING_DESCRIPTOR_TYPE, 1010 Urb->UrbControlDescriptorRequest.TransferBufferLength, 1011 Urb->UrbControlDescriptorRequest.Index, 1012 Urb->UrbControlDescriptorRequest.LanguageId, 1013 (PVOID*)&StringDescriptor); 1014 if (NT_SUCCESS(Status)) 1015 { 1016 if (StringDescriptor->bLength == 2) 1017 { 1018 FreeItem(StringDescriptor); 1019 Status = STATUS_DEVICE_DATA_ERROR; 1020 } 1021 else 1022 { 1023 RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, 1024 StringDescriptor->bString, 1025 StringDescriptor->bLength + sizeof(WCHAR)); 1026 FreeItem(StringDescriptor); 1027 Status = STATUS_SUCCESS; 1028 } 1029 } 1030 Irp->IoStatus.Status = Status; 1031 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1032 return Status; 1033 } 1034 } 1035 else 1036 { 1037 IoSkipCurrentIrpStackLocation(Irp); 1038 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); 1039 return Status; 1040 } 1041 } 1042 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_GET_PORT_STATUS) 1043 { 1044 IoSkipCurrentIrpStackLocation(Irp); 1045 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); 1046 return Status; 1047 } 1048 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT) 1049 { 1050 IoSkipCurrentIrpStackLocation(Irp); 1051 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); 1052 return Status; 1053 } 1054 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT) 1055 { 1056 IoSkipCurrentIrpStackLocation(Irp); 1057 Status = IoCallDriver(PDODeviceExtension->NextDeviceObject, Irp); 1058 return Status; 1059 } 1060 1061 DPRINT1("IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); 1062 DPRINT1("InputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.InputBufferLength); 1063 DPRINT1("OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength); 1064 DPRINT1("Type3InputBuffer %p\n", IoStack->Parameters.DeviceIoControl.Type3InputBuffer); 1065 1066 ASSERT(FALSE); 1067 1068 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 1069 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1070 return STATUS_NOT_IMPLEMENTED; 1071 } 1072 1073 1074 NTSTATUS 1075 PDO_Dispatch( 1076 PDEVICE_OBJECT DeviceObject, 1077 PIRP Irp) 1078 { 1079 PIO_STACK_LOCATION IoStack; 1080 NTSTATUS Status; 1081 1082 /* get stack location */ 1083 IoStack = IoGetCurrentIrpStackLocation(Irp); 1084 1085 switch(IoStack->MajorFunction) 1086 { 1087 case IRP_MJ_PNP: 1088 return PDO_HandlePnp(DeviceObject, Irp); 1089 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 1090 return PDO_HandleInternalDeviceControl(DeviceObject, Irp); 1091 case IRP_MJ_POWER: 1092 PoStartNextPowerIrp(Irp); 1093 Irp->IoStatus.Status = STATUS_SUCCESS; 1094 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1095 return STATUS_SUCCESS; 1096 default: 1097 DPRINT1("PDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction); 1098 Status = Irp->IoStatus.Status; 1099 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1100 return Status; 1101 } 1102 } 1103