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