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