1 /* 2 * PROJECT: ReactOS USB Hub Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBHub main driver functions 5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru> 6 */ 7 8 #include "usbhub.h" 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #define NDEBUG_USBHUB_SCE 14 #define NDEBUG_USBHUB_PNP 15 #include "dbg_uhub.h" 16 17 #include <ntddstor.h> 18 19 PWSTR GenericUSBDeviceString = NULL; 20 21 NTSTATUS 22 NTAPI 23 USBH_Wait(IN ULONG Milliseconds) 24 { 25 LARGE_INTEGER Interval; 26 27 DPRINT("USBH_Wait: Milliseconds - %x\n", Milliseconds); 28 Interval.QuadPart = -10000LL * Milliseconds - ((ULONGLONG)KeQueryTimeIncrement() - 1); 29 return KeDelayExecutionThread(KernelMode, FALSE, &Interval); 30 } 31 32 NTSTATUS 33 NTAPI 34 USBH_GetConfigValue(IN PWSTR ValueName, 35 IN ULONG ValueType, 36 IN PVOID ValueData, 37 IN ULONG ValueLength, 38 IN PVOID Context, 39 IN PVOID EntryContext) 40 { 41 NTSTATUS Status = STATUS_SUCCESS; 42 43 DPRINT("USBHUB_GetConfigValue: ... \n"); 44 45 if (ValueType == REG_BINARY) 46 { 47 *(PUCHAR)EntryContext = *(PUCHAR)ValueData; 48 } 49 else if (ValueType == REG_DWORD) 50 { 51 *(PULONG)EntryContext = *(PULONG)ValueData; 52 } 53 else 54 { 55 Status = STATUS_INVALID_PARAMETER; 56 } 57 58 return Status; 59 } 60 61 VOID 62 NTAPI 63 USBH_CompleteIrp(IN PIRP Irp, 64 IN NTSTATUS CompleteStatus) 65 { 66 if (CompleteStatus != STATUS_SUCCESS) 67 { 68 DPRINT1("USBH_CompleteIrp: Irp - %p, CompleteStatus - %X\n", 69 Irp, 70 CompleteStatus); 71 } 72 73 Irp->IoStatus.Status = CompleteStatus; 74 IoCompleteRequest(Irp, IO_NO_INCREMENT); 75 } 76 77 NTSTATUS 78 NTAPI 79 USBH_PassIrp(IN PDEVICE_OBJECT DeviceObject, 80 IN PIRP Irp) 81 { 82 DPRINT_PNP("USBH_PassIrp: DeviceObject - %p, Irp - %p\n", 83 DeviceObject, 84 Irp); 85 86 IoSkipCurrentIrpStackLocation(Irp); 87 return IoCallDriver(DeviceObject, Irp); 88 } 89 90 NTSTATUS 91 NTAPI 92 USBH_SyncIrpComplete(IN PDEVICE_OBJECT DeviceObject, 93 IN PIRP Irp, 94 IN PVOID Context) 95 { 96 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext; 97 KIRQL OldIrql; 98 BOOLEAN TimerCancelled; 99 100 DPRINT("USBH_SyncIrpComplete: ... \n"); 101 102 HubTimeoutContext = Context; 103 104 KeAcquireSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, &OldIrql); 105 HubTimeoutContext->IsNormalCompleted = TRUE; 106 TimerCancelled = KeCancelTimer(&HubTimeoutContext->UrbTimeoutTimer); 107 KeReleaseSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, OldIrql); 108 109 if (TimerCancelled) 110 { 111 KeSetEvent(&HubTimeoutContext->UrbTimeoutEvent, 112 EVENT_INCREMENT, 113 FALSE); 114 } 115 116 return STATUS_SUCCESS; 117 } 118 119 BOOLEAN 120 NTAPI 121 IsBitSet(IN PUCHAR BitMapAddress, 122 IN USHORT Bit) 123 { 124 BOOLEAN IsSet; 125 126 IsSet = (BitMapAddress[Bit / 8] & (1 << (Bit & 7))) != 0; 127 DPRINT("IsBitSet: Bit - %lX, IsSet - %x\n", Bit, IsSet); 128 return IsSet; 129 } 130 131 PUSBHUB_PORT_PDO_EXTENSION 132 NTAPI 133 PdoExt(IN PDEVICE_OBJECT DeviceObject) 134 { 135 PVOID PdoExtension; 136 137 DPRINT("PdoExt: DeviceObject - %p\n", DeviceObject); 138 139 if (DeviceObject) 140 { 141 PdoExtension = DeviceObject->DeviceExtension; 142 } 143 else 144 { 145 PdoExtension = NULL; 146 } 147 148 return (PUSBHUB_PORT_PDO_EXTENSION)PdoExtension; 149 } 150 151 NTSTATUS 152 NTAPI 153 USBH_WriteFailReasonID(IN PDEVICE_OBJECT DeviceObject, 154 IN ULONG FailReason) 155 { 156 NTSTATUS Status; 157 HANDLE KeyHandle; 158 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FailReasonID"); 159 160 DPRINT("USBH_WriteFailReason: ID - %x\n", FailReason); 161 162 Status = IoOpenDeviceRegistryKey(DeviceObject, 163 PLUGPLAY_REGKEY_DEVICE, 164 STANDARD_RIGHTS_ALL, 165 &KeyHandle); 166 167 if (NT_SUCCESS(Status)) 168 { 169 ZwSetValueKey(KeyHandle, 170 &ValueName, 171 0, 172 REG_DWORD, 173 &FailReason, 174 sizeof(FailReason)); 175 176 ZwClose(KeyHandle); 177 } 178 179 return Status; 180 } 181 182 VOID 183 NTAPI 184 USBH_UrbTimeoutDPC(IN PKDPC Dpc, 185 IN PVOID DeferredContext, 186 IN PVOID SystemArgument1, 187 IN PVOID SystemArgument2) 188 { 189 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext; 190 KIRQL OldIrql; 191 BOOL IsCompleted; 192 193 DPRINT("USBH_TimeoutDPC ... \n"); 194 195 HubTimeoutContext = DeferredContext; 196 197 KeAcquireSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, &OldIrql); 198 IsCompleted = HubTimeoutContext->IsNormalCompleted; 199 KeReleaseSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, OldIrql); 200 201 if (!IsCompleted) 202 { 203 IoCancelIrp(HubTimeoutContext->Irp); 204 } 205 206 KeSetEvent(&HubTimeoutContext->UrbTimeoutEvent, 207 EVENT_INCREMENT, 208 FALSE); 209 } 210 211 NTSTATUS 212 NTAPI 213 USBH_SetPdoRegistryParameter(IN PDEVICE_OBJECT DeviceObject, 214 IN PCWSTR ValueName, 215 IN PVOID Data, 216 IN ULONG DataSize, 217 IN ULONG Type, 218 IN ULONG DevInstKeyType) 219 { 220 NTSTATUS Status; 221 UNICODE_STRING ValueNameString; 222 HANDLE KeyHandle; 223 224 DPRINT("USBH_SetPdoRegistryParameter ... \n"); 225 226 RtlInitUnicodeString(&ValueNameString, ValueName); 227 228 Status = IoOpenDeviceRegistryKey(DeviceObject, 229 DevInstKeyType, 230 STANDARD_RIGHTS_ALL, 231 &KeyHandle); 232 233 if (NT_SUCCESS(Status)) 234 { 235 ZwSetValueKey(KeyHandle, 236 &ValueNameString, 237 0, 238 Type, 239 Data, 240 DataSize); 241 242 ZwClose(KeyHandle); 243 } 244 245 return Status; 246 } 247 248 NTSTATUS 249 NTAPI 250 USBH_SyncSubmitUrb(IN PDEVICE_OBJECT DeviceObject, 251 IN PURB Urb) 252 { 253 KEVENT Event; 254 IO_STATUS_BLOCK IoStatusBlock; 255 PIRP Irp; 256 PIO_STACK_LOCATION IoStack; 257 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext; 258 BOOLEAN IsWaitTimeout = FALSE; 259 LARGE_INTEGER DueTime; 260 NTSTATUS Status; 261 262 DPRINT("USBH_SyncSubmitUrb: ... \n"); 263 264 Urb->UrbHeader.UsbdDeviceHandle = NULL; 265 266 KeInitializeEvent(&Event, NotificationEvent, FALSE); 267 268 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, 269 DeviceObject, 270 NULL, 271 0, 272 NULL, 273 0, 274 TRUE, 275 &Event, 276 &IoStatusBlock); 277 278 if (!Irp) 279 { 280 return STATUS_INSUFFICIENT_RESOURCES; 281 } 282 283 IoStack = IoGetNextIrpStackLocation(Irp); 284 IoStack->Parameters.Others.Argument1 = Urb; 285 286 HubTimeoutContext = ExAllocatePoolWithTag(NonPagedPool, 287 sizeof(USBHUB_URB_TIMEOUT_CONTEXT), 288 USB_HUB_TAG); 289 290 if (HubTimeoutContext) 291 { 292 RtlZeroMemory(HubTimeoutContext, sizeof(USBHUB_URB_TIMEOUT_CONTEXT)); 293 294 HubTimeoutContext->Irp = Irp; 295 HubTimeoutContext->IsNormalCompleted = FALSE; 296 297 KeInitializeEvent(&HubTimeoutContext->UrbTimeoutEvent, 298 NotificationEvent, 299 FALSE); 300 301 KeInitializeSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock); 302 KeInitializeTimer(&HubTimeoutContext->UrbTimeoutTimer); 303 304 KeInitializeDpc(&HubTimeoutContext->UrbTimeoutDPC, 305 USBH_UrbTimeoutDPC, 306 HubTimeoutContext); 307 308 DueTime.QuadPart = -5000 * 10000; // Timeout 5 sec. 309 310 KeSetTimer(&HubTimeoutContext->UrbTimeoutTimer, 311 DueTime, 312 &HubTimeoutContext->UrbTimeoutDPC); 313 314 IoSetCompletionRoutine(Irp, 315 USBH_SyncIrpComplete, 316 HubTimeoutContext, 317 TRUE, 318 TRUE, 319 TRUE); 320 321 IsWaitTimeout = TRUE; 322 } 323 324 Status = IoCallDriver(DeviceObject, Irp); 325 326 if (Status == STATUS_PENDING) 327 { 328 KeWaitForSingleObject(&Event, 329 Suspended, 330 KernelMode, 331 FALSE, 332 NULL); 333 } 334 else 335 { 336 IoStatusBlock.Status = Status; 337 } 338 339 if (IsWaitTimeout) 340 { 341 KeWaitForSingleObject(&HubTimeoutContext->UrbTimeoutEvent, 342 Suspended, 343 KernelMode, 344 FALSE, 345 NULL); 346 347 ExFreePoolWithTag(HubTimeoutContext, USB_HUB_TAG); 348 } 349 350 return IoStatusBlock.Status; 351 } 352 353 NTSTATUS 354 NTAPI 355 USBH_FdoSyncSubmitUrb(IN PDEVICE_OBJECT FdoDevice, 356 IN PURB Urb) 357 { 358 PUSBHUB_FDO_EXTENSION HubExtension; 359 360 DPRINT("USBH_FdoSyncSubmitUrb: FdoDevice - %p, Urb - %p\n", 361 FdoDevice, 362 Urb); 363 364 HubExtension = FdoDevice->DeviceExtension; 365 return USBH_SyncSubmitUrb(HubExtension->LowerDevice, Urb); 366 } 367 368 NTSTATUS 369 NTAPI 370 USBH_Transact(IN PUSBHUB_FDO_EXTENSION HubExtension, 371 IN PVOID TransferBuffer, 372 IN ULONG BufferLen, 373 IN BOOLEAN IsDeviceToHost, 374 IN USHORT Function, 375 IN BM_REQUEST_TYPE RequestType, 376 IN UCHAR Request, 377 IN USHORT RequestValue, 378 IN USHORT RequestIndex) 379 { 380 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb; 381 ULONG TransferFlags; 382 PVOID Buffer = NULL; 383 ULONG Length; 384 NTSTATUS Status; 385 386 DPRINT("USBH_Transact: ... \n"); 387 388 if (BufferLen) 389 { 390 Length = ALIGN_DOWN_BY(BufferLen + sizeof(ULONG), sizeof(ULONG)); 391 392 Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, USB_HUB_TAG); 393 394 if (!Buffer) 395 { 396 return STATUS_INSUFFICIENT_RESOURCES; 397 } 398 399 RtlZeroMemory(Buffer, Length); 400 } 401 402 Urb = ExAllocatePoolWithTag(NonPagedPool, 403 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), 404 USB_HUB_TAG); 405 406 if (!Urb) 407 { 408 if (Buffer) 409 { 410 ExFreePoolWithTag(Buffer, USB_HUB_TAG); 411 } 412 413 return STATUS_INSUFFICIENT_RESOURCES; 414 } 415 416 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST)); 417 418 if (IsDeviceToHost) 419 { 420 if (BufferLen) 421 { 422 RtlZeroMemory(TransferBuffer, BufferLen); 423 } 424 425 TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK; 426 } 427 else 428 { 429 if (BufferLen) 430 { 431 RtlCopyMemory(Buffer, TransferBuffer, BufferLen); 432 } 433 434 TransferFlags = USBD_TRANSFER_DIRECTION_OUT; 435 } 436 437 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); 438 Urb->Hdr.Function = Function; 439 Urb->Hdr.UsbdDeviceHandle = NULL; 440 441 Urb->TransferFlags = TransferFlags; 442 Urb->TransferBuffer = BufferLen != 0 ? Buffer : NULL; 443 Urb->TransferBufferLength = BufferLen; 444 Urb->TransferBufferMDL = NULL; 445 Urb->UrbLink = NULL; 446 447 Urb->RequestTypeReservedBits = RequestType.B; 448 Urb->Request = Request; 449 Urb->Value = RequestValue; 450 Urb->Index = RequestIndex; 451 452 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, (PURB)Urb); 453 454 if (IsDeviceToHost && BufferLen) 455 { 456 RtlCopyMemory(TransferBuffer, Buffer, BufferLen); 457 } 458 459 if (Buffer) 460 { 461 ExFreePoolWithTag(Buffer, USB_HUB_TAG); 462 } 463 464 ExFreePoolWithTag(Urb, USB_HUB_TAG); 465 466 return Status; 467 } 468 469 NTSTATUS 470 NTAPI 471 USBH_SyncResetPort(IN PUSBHUB_FDO_EXTENSION HubExtension, 472 IN USHORT Port) 473 { 474 USB_PORT_STATUS_AND_CHANGE PortStatus; 475 KEVENT Event; 476 LARGE_INTEGER Timeout; 477 ULONG ResetRetry = 0; 478 NTSTATUS Status; 479 480 DPRINT("USBH_SyncResetPort: Port - %x\n", Port); 481 482 InterlockedIncrement(&HubExtension->PendingRequestCount); 483 484 KeWaitForSingleObject(&HubExtension->HubPortSemaphore, 485 Executive, 486 KernelMode, 487 FALSE, 488 NULL); 489 490 Status = USBH_SyncGetPortStatus(HubExtension, 491 Port, 492 &PortStatus, 493 sizeof(USB_PORT_STATUS_AND_CHANGE)); 494 495 if (NT_SUCCESS(Status) && 496 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0)) 497 { 498 Status = STATUS_UNSUCCESSFUL; 499 goto Exit; 500 } 501 502 HubExtension->HubFlags |= USBHUB_FDO_FLAG_RESET_PORT_LOCK; 503 504 while (TRUE) 505 { 506 BM_REQUEST_TYPE RequestType; 507 508 KeInitializeEvent(&Event, NotificationEvent, FALSE); 509 510 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent, 511 &Event); 512 513 RequestType.B = 0; 514 RequestType.Recipient = BMREQUEST_TO_DEVICE; 515 RequestType.Type = BMREQUEST_CLASS; 516 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE; 517 518 Status = USBH_Transact(HubExtension, 519 NULL, 520 0, 521 BMREQUEST_HOST_TO_DEVICE, 522 URB_FUNCTION_CLASS_OTHER, 523 RequestType, 524 USB_REQUEST_SET_FEATURE, 525 USBHUB_FEATURE_PORT_RESET, 526 Port); 527 528 Timeout.QuadPart = -5000 * 10000; 529 530 if (!NT_SUCCESS(Status)) 531 { 532 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent, 533 NULL); 534 535 USBH_Wait(10); 536 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK; 537 538 goto Exit; 539 } 540 541 Status = KeWaitForSingleObject(&Event, 542 Suspended, 543 KernelMode, 544 FALSE, 545 &Timeout); 546 547 if (Status != STATUS_TIMEOUT) 548 { 549 break; 550 } 551 552 Status = USBH_SyncGetPortStatus(HubExtension, 553 Port, 554 &PortStatus, 555 sizeof(USB_PORT_STATUS_AND_CHANGE)); 556 557 if (!NT_SUCCESS(Status) || 558 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) || 559 ResetRetry >= USBHUB_RESET_PORT_MAX_RETRY) 560 { 561 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent, 562 NULL); 563 564 USBH_Wait(10); 565 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK; 566 567 Status = STATUS_DEVICE_DATA_ERROR; 568 goto Exit; 569 } 570 571 ResetRetry++; 572 } 573 574 Status = USBH_SyncGetPortStatus(HubExtension, 575 Port, 576 &PortStatus, 577 sizeof(USB_PORT_STATUS_AND_CHANGE)); 578 579 if ((PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) && 580 NT_SUCCESS(Status) && 581 HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB) 582 { 583 Status = STATUS_DEVICE_DATA_ERROR; 584 } 585 586 USBH_Wait(10); 587 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK; 588 589 Exit: 590 591 KeReleaseSemaphore(&HubExtension->HubPortSemaphore, 592 LOW_REALTIME_PRIORITY, 593 1, 594 FALSE); 595 596 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 597 { 598 KeSetEvent(&HubExtension->PendingRequestEvent, 599 EVENT_INCREMENT, 600 FALSE); 601 } 602 603 return Status; 604 } 605 606 NTSTATUS 607 NTAPI 608 USBH_GetDeviceType(IN PUSBHUB_FDO_EXTENSION HubExtension, 609 IN PUSB_DEVICE_HANDLE DeviceHandle, 610 OUT USB_DEVICE_TYPE * OutDeviceType) 611 { 612 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation; 613 PUSB_DEVICE_INFORMATION_0 DeviceInfo; 614 SIZE_T DeviceInformationBufferLength; 615 USB_DEVICE_TYPE DeviceType = Usb11Device; 616 ULONG dummy; 617 NTSTATUS Status; 618 619 DPRINT("USBH_GetDeviceType: ... \n"); 620 621 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation; 622 623 if (!QueryDeviceInformation) 624 { 625 DPRINT1("USBH_GetDeviceType: no QueryDeviceInformation()\n"); 626 return STATUS_NOT_IMPLEMENTED; 627 } 628 629 DeviceInformationBufferLength = sizeof(USB_DEVICE_INFORMATION_0); 630 631 while (TRUE) 632 { 633 DeviceInfo = ExAllocatePoolWithTag(PagedPool, 634 DeviceInformationBufferLength, 635 USB_HUB_TAG); 636 637 if (!DeviceInfo) 638 { 639 DPRINT1("USBH_GetDeviceType: ExAllocatePoolWithTag() failed\n"); 640 Status = STATUS_INSUFFICIENT_RESOURCES; 641 break; 642 } 643 644 RtlZeroMemory(DeviceInfo, DeviceInformationBufferLength); 645 646 DeviceInfo->InformationLevel = 0; 647 648 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext, 649 DeviceHandle, 650 DeviceInfo, 651 DeviceInformationBufferLength, 652 &dummy); 653 654 if (Status != STATUS_BUFFER_TOO_SMALL) 655 { 656 if (NT_SUCCESS(Status)) 657 { 658 DeviceType = DeviceInfo->DeviceType; 659 } 660 661 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG); 662 break; 663 } 664 665 DeviceInformationBufferLength = DeviceInfo->ActualLength; 666 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG); 667 } 668 669 if (OutDeviceType) 670 { 671 *OutDeviceType = DeviceType; 672 DPRINT("USBH_GetDeviceType: DeviceType - %x\n", DeviceType); 673 } 674 675 return Status; 676 } 677 678 NTSTATUS 679 NTAPI 680 USBHUB_GetExtendedHubInfo(IN PUSBHUB_FDO_EXTENSION HubExtension, 681 IN PUSB_EXTHUB_INFORMATION_0 HubInfoBuffer) 682 { 683 PUSB_BUSIFFN_GET_EXTENDED_HUB_INFO GetExtendedHubInformation; 684 ULONG dummy = 0; 685 686 DPRINT("USBHUB_GetExtendedHubInfo: ... \n"); 687 688 GetExtendedHubInformation = HubExtension->BusInterface.GetExtendedHubInformation; 689 690 return GetExtendedHubInformation(HubExtension->BusInterface.BusContext, 691 HubExtension->LowerPDO, 692 HubInfoBuffer, 693 sizeof(USB_EXTHUB_INFORMATION_0), 694 &dummy); 695 } 696 697 PUSBHUB_FDO_EXTENSION 698 NTAPI 699 USBH_GetRootHubExtension(IN PUSBHUB_FDO_EXTENSION HubExtension) 700 { 701 PDEVICE_OBJECT Device; 702 PUSBHUB_FDO_EXTENSION RootHubExtension; 703 704 DPRINT("USBH_GetRootHubExtension: HubExtension - %p\n", HubExtension); 705 706 RootHubExtension = HubExtension; 707 708 if (HubExtension->LowerPDO != HubExtension->RootHubPdo) 709 { 710 Device = HubExtension->RootHubPdo; 711 712 do 713 { 714 Device = Device->AttachedDevice; 715 } 716 while (Device->DriverObject != HubExtension->Common.SelfDevice->DriverObject); 717 718 RootHubExtension = Device->DeviceExtension; 719 } 720 721 DPRINT("USBH_GetRootHubExtension: RootHubExtension - %p\n", RootHubExtension); 722 723 return RootHubExtension; 724 } 725 726 NTSTATUS 727 NTAPI 728 USBH_SyncGetRootHubPdo(IN PDEVICE_OBJECT DeviceObject, 729 IN OUT PDEVICE_OBJECT * OutPdo1, 730 IN OUT PDEVICE_OBJECT * OutPdo2) 731 { 732 KEVENT Event; 733 IO_STATUS_BLOCK IoStatusBlock; 734 PIRP Irp; 735 PIO_STACK_LOCATION IoStack; 736 NTSTATUS Status; 737 738 DPRINT("USBH_SyncGetRootHubPdo: ... \n"); 739 740 KeInitializeEvent(&Event, NotificationEvent, FALSE); 741 742 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, 743 DeviceObject, 744 NULL, 745 0, 746 NULL, 747 0, 748 TRUE, 749 &Event, 750 &IoStatusBlock); 751 752 if (!Irp) 753 { 754 return STATUS_INSUFFICIENT_RESOURCES; 755 } 756 757 IoStack = IoGetNextIrpStackLocation(Irp); 758 IoStack->Parameters.Others.Argument1 = OutPdo1; 759 IoStack->Parameters.Others.Argument2 = OutPdo2; 760 761 Status = IoCallDriver(DeviceObject, Irp); 762 763 if (Status == STATUS_PENDING) 764 { 765 KeWaitForSingleObject(&Event, 766 Suspended, 767 KernelMode, 768 FALSE, 769 NULL); 770 } 771 else 772 { 773 IoStatusBlock.Status = Status; 774 } 775 776 return IoStatusBlock.Status; 777 } 778 779 NTSTATUS 780 NTAPI 781 USBH_SyncGetHubCount(IN PDEVICE_OBJECT DeviceObject, 782 IN OUT PULONG OutHubCount) 783 { 784 KEVENT Event; 785 IO_STATUS_BLOCK IoStatusBlock; 786 PIRP Irp; 787 PIO_STACK_LOCATION IoStack; 788 NTSTATUS Status; 789 790 DPRINT("USBH_SyncGetHubCount: *OutHubCount - %x\n", *OutHubCount); 791 792 KeInitializeEvent(&Event, NotificationEvent, FALSE); 793 794 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_HUB_COUNT, 795 DeviceObject, 796 NULL, 797 0, 798 NULL, 799 0, 800 TRUE, 801 &Event, 802 &IoStatusBlock); 803 804 if (!Irp) 805 { 806 return STATUS_INSUFFICIENT_RESOURCES; 807 } 808 809 IoStack = IoGetNextIrpStackLocation(Irp); 810 IoStack->Parameters.Others.Argument1 = OutHubCount; 811 812 Status = IoCallDriver(DeviceObject, Irp); 813 814 if (Status == STATUS_PENDING) 815 { 816 KeWaitForSingleObject(&Event, 817 Suspended, 818 KernelMode, 819 FALSE, 820 NULL); 821 } 822 else 823 { 824 IoStatusBlock.Status = Status; 825 } 826 827 return IoStatusBlock.Status; 828 } 829 830 PUSB_DEVICE_HANDLE 831 NTAPI 832 USBH_SyncGetDeviceHandle(IN PDEVICE_OBJECT DeviceObject) 833 { 834 PIRP Irp; 835 KEVENT Event; 836 IO_STATUS_BLOCK IoStatusBlock; 837 PUSB_DEVICE_HANDLE DeviceHandle = NULL; 838 PIO_STACK_LOCATION IoStack; 839 840 DPRINT("USBH_SyncGetDeviceHandle: ... \n"); 841 842 KeInitializeEvent(&Event, NotificationEvent, FALSE); 843 844 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, 845 DeviceObject, 846 NULL, 847 0, 848 NULL, 849 0, 850 TRUE, 851 &Event, 852 &IoStatusBlock); 853 854 if (!Irp) 855 { 856 DPRINT1("USBH_SyncGetDeviceHandle: Irp - NULL!\n"); 857 return NULL; 858 } 859 860 IoStack = IoGetNextIrpStackLocation(Irp); 861 IoStack->Parameters.Others.Argument1 = &DeviceHandle; 862 863 if (IoCallDriver(DeviceObject, Irp) == STATUS_PENDING) 864 { 865 KeWaitForSingleObject(&Event, 866 Suspended, 867 KernelMode, 868 FALSE, 869 NULL); 870 } 871 872 return DeviceHandle; 873 } 874 875 NTSTATUS 876 NTAPI 877 USBH_GetDeviceDescriptor(IN PDEVICE_OBJECT DeviceObject, 878 IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor) 879 { 880 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb; 881 NTSTATUS Status; 882 883 DPRINT("USBH_GetDeviceDescriptor: ... \n"); 884 885 Urb = ExAllocatePoolWithTag(NonPagedPool, 886 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), 887 USB_HUB_TAG); 888 889 if (!Urb) 890 { 891 DPRINT1("USBH_SyncGetDeviceHandle: Urb - NULL!\n"); 892 return STATUS_INSUFFICIENT_RESOURCES; 893 } 894 895 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 896 897 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE; 898 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); 899 900 Urb->TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR); 901 Urb->TransferBuffer = HubDeviceDescriptor; 902 Urb->DescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; 903 904 Status = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb); 905 906 ExFreePoolWithTag(Urb, USB_HUB_TAG); 907 908 return Status; 909 } 910 911 NTSTATUS 912 NTAPI 913 USBH_SyncGetDeviceConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject, 914 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor, 915 IN ULONG NumberOfBytes, 916 IN PULONG OutLength) 917 { 918 PCOMMON_DEVICE_EXTENSION DeviceExtension; 919 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb; 920 NTSTATUS Status; 921 922 DPRINT("USBH_SyncGetDeviceConfigurationDescriptor: ... \n"); 923 924 DeviceExtension = DeviceObject->DeviceExtension; 925 926 if (OutLength) 927 { 928 *OutLength = 0; 929 } 930 931 Urb = ExAllocatePoolWithTag(NonPagedPool, 932 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), 933 USB_HUB_TAG); 934 935 if (!Urb) 936 { 937 return STATUS_INSUFFICIENT_RESOURCES; 938 } 939 940 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 941 942 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE; 943 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); 944 945 Urb->TransferBufferLength = NumberOfBytes; 946 Urb->TransferBuffer = ConfigDescriptor; 947 Urb->DescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE; 948 949 if (DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_HUB || 950 DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_PARENT) 951 { 952 Status = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb); 953 } 954 else 955 { 956 Status = USBH_SyncSubmitUrb(DeviceObject, (PURB)Urb); 957 } 958 959 if (OutLength) 960 { 961 *OutLength = Urb->TransferBufferLength; 962 } 963 964 if (Urb) 965 { 966 ExFreePoolWithTag(Urb, USB_HUB_TAG); 967 } 968 969 return Status; 970 } 971 972 NTSTATUS 973 NTAPI 974 USBH_GetConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject, 975 IN PUSB_CONFIGURATION_DESCRIPTOR * OutDescriptor) 976 { 977 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor; 978 ULONG ReturnedLen; 979 SIZE_T DescriptorLen; 980 NTSTATUS Status; 981 982 DPRINT("USBH_GetConfigurationDescriptor: ... \n"); 983 984 DescriptorLen = MAXUCHAR; 985 986 while (TRUE) 987 { 988 ConfigDescriptor = ExAllocatePoolWithTag(NonPagedPool, 989 DescriptorLen, 990 USB_HUB_TAG); 991 992 if (!ConfigDescriptor) 993 { 994 Status = STATUS_INSUFFICIENT_RESOURCES; 995 break; 996 } 997 998 Status = USBH_SyncGetDeviceConfigurationDescriptor(DeviceObject, 999 ConfigDescriptor, 1000 DescriptorLen, 1001 &ReturnedLen); 1002 1003 if (ReturnedLen < sizeof(USB_CONFIGURATION_DESCRIPTOR)) 1004 { 1005 Status = STATUS_DEVICE_DATA_ERROR; 1006 } 1007 1008 if (!NT_SUCCESS(Status)) 1009 { 1010 break; 1011 } 1012 1013 *OutDescriptor = ConfigDescriptor; 1014 1015 if (ConfigDescriptor->wTotalLength <= DescriptorLen) 1016 { 1017 break; 1018 } 1019 1020 DescriptorLen = ConfigDescriptor->wTotalLength; 1021 1022 ExFreePool(ConfigDescriptor); 1023 *OutDescriptor = NULL; 1024 } 1025 1026 if (NT_SUCCESS(Status)) 1027 { 1028 if (ReturnedLen < ConfigDescriptor->wTotalLength) 1029 { 1030 Status = STATUS_DEVICE_DATA_ERROR; 1031 } 1032 } 1033 else 1034 { 1035 if (ConfigDescriptor) 1036 { 1037 ExFreePool(ConfigDescriptor); 1038 } 1039 1040 *OutDescriptor = NULL; 1041 } 1042 1043 return Status; 1044 } 1045 1046 NTSTATUS 1047 NTAPI 1048 USBH_SyncGetHubDescriptor(IN PUSBHUB_FDO_EXTENSION HubExtension) 1049 { 1050 PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo; 1051 ULONG NumberPorts; 1052 PUSBHUB_PORT_DATA PortData; 1053 USHORT RequestValue; 1054 ULONG NumberOfBytes; 1055 NTSTATUS Status; 1056 PUSB_HUB_DESCRIPTOR HubDescriptor = NULL; 1057 ULONG ix; 1058 ULONG Retry; 1059 1060 DPRINT("USBH_SyncGetHubDescriptor: ... \n"); 1061 1062 ExtendedHubInfo = ExAllocatePoolWithTag(NonPagedPool, 1063 sizeof(USB_EXTHUB_INFORMATION_0), 1064 USB_HUB_TAG); 1065 1066 if (!ExtendedHubInfo) 1067 { 1068 Status = STATUS_INSUFFICIENT_RESOURCES; 1069 goto ErrorExit; 1070 } 1071 1072 RtlZeroMemory(ExtendedHubInfo, sizeof(USB_EXTHUB_INFORMATION_0)); 1073 1074 Status = USBHUB_GetExtendedHubInfo(HubExtension, ExtendedHubInfo); 1075 1076 if (!NT_SUCCESS(Status)) 1077 { 1078 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG); 1079 ExtendedHubInfo = NULL; 1080 } 1081 1082 NumberOfBytes = sizeof(USB_HUB_DESCRIPTOR); 1083 1084 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool, 1085 NumberOfBytes, 1086 USB_HUB_TAG); 1087 1088 if (!HubDescriptor) 1089 { 1090 Status = STATUS_INSUFFICIENT_RESOURCES; 1091 goto ErrorExit; 1092 } 1093 1094 RtlZeroMemory(HubDescriptor, NumberOfBytes); 1095 1096 RequestValue = 0; 1097 Retry = 0; 1098 1099 while (TRUE) 1100 { 1101 while (Retry <= 5) 1102 { 1103 BM_REQUEST_TYPE RequestType; 1104 1105 RequestType.B = 0; 1106 RequestType.Recipient = BMREQUEST_TO_DEVICE; 1107 RequestType.Type = BMREQUEST_STANDARD; 1108 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST; 1109 1110 Status = USBH_Transact(HubExtension, 1111 HubDescriptor, 1112 NumberOfBytes, 1113 BMREQUEST_DEVICE_TO_HOST, 1114 URB_FUNCTION_CLASS_DEVICE, 1115 RequestType, 1116 USB_REQUEST_GET_DESCRIPTOR, 1117 RequestValue, 1118 0); 1119 1120 if (NT_SUCCESS(Status)) 1121 { 1122 break; 1123 } 1124 1125 RequestValue = 0x2900; // Hub DescriptorType - 0x29 1126 1127 Retry++; 1128 } 1129 1130 if (HubDescriptor->bDescriptorLength <= NumberOfBytes) 1131 { 1132 break; 1133 } 1134 1135 NumberOfBytes = HubDescriptor->bDescriptorLength; 1136 ExFreePoolWithTag(HubDescriptor, USB_HUB_TAG); 1137 1138 if (Retry >= 5) 1139 { 1140 Status = STATUS_DEVICE_DATA_ERROR; 1141 HubDescriptor = NULL; 1142 goto ErrorExit; 1143 } 1144 1145 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool, 1146 NumberOfBytes, 1147 USB_HUB_TAG); 1148 1149 if (!HubDescriptor) 1150 { 1151 Status = STATUS_INSUFFICIENT_RESOURCES; 1152 goto ErrorExit; 1153 } 1154 1155 RtlZeroMemory(HubDescriptor, NumberOfBytes); 1156 } 1157 1158 NumberPorts = HubDescriptor->bNumberOfPorts; 1159 1160 if (HubExtension->PortData) 1161 { 1162 PortData = HubExtension->PortData; 1163 1164 for (ix = 0; ix < NumberPorts; ix++) 1165 { 1166 PortData[ix].PortStatus.AsUlong32 = 0; 1167 1168 if (ExtendedHubInfo) 1169 { 1170 PortData[ix].PortAttributes = ExtendedHubInfo->Port[ix].PortAttributes; 1171 } 1172 else 1173 { 1174 PortData[ix].PortAttributes = 0; 1175 } 1176 1177 PortData[ix].ConnectionStatus = NoDeviceConnected; 1178 1179 if (PortData[ix].DeviceObject != NULL) 1180 { 1181 PortData[ix].ConnectionStatus = DeviceConnected; 1182 } 1183 } 1184 } 1185 else 1186 { 1187 PortData = NULL; 1188 1189 if (HubDescriptor->bNumberOfPorts) 1190 { 1191 PortData = ExAllocatePoolWithTag(NonPagedPool, 1192 NumberPorts * sizeof(USBHUB_PORT_DATA), 1193 USB_HUB_TAG); 1194 } 1195 1196 if (!PortData) 1197 { 1198 Status = STATUS_INSUFFICIENT_RESOURCES; 1199 goto ErrorExit; 1200 } 1201 1202 RtlZeroMemory(PortData, NumberPorts * sizeof(USBHUB_PORT_DATA)); 1203 1204 for (ix = 0; ix < NumberPorts; ix++) 1205 { 1206 PortData[ix].ConnectionStatus = NoDeviceConnected; 1207 1208 if (ExtendedHubInfo) 1209 { 1210 PortData[ix].PortAttributes = ExtendedHubInfo->Port[ix].PortAttributes; 1211 } 1212 } 1213 } 1214 1215 if (!NT_SUCCESS(Status)) 1216 { 1217 goto ErrorExit; 1218 } 1219 1220 HubExtension->HubDescriptor = HubDescriptor; 1221 1222 HubExtension->PortData = PortData; 1223 1224 if (ExtendedHubInfo) 1225 { 1226 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG); 1227 } 1228 1229 return Status; 1230 1231 ErrorExit: 1232 1233 if (HubDescriptor) 1234 { 1235 ExFreePoolWithTag(HubDescriptor, USB_HUB_TAG); 1236 } 1237 1238 if (ExtendedHubInfo) 1239 { 1240 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG); 1241 } 1242 1243 return Status; 1244 } 1245 1246 NTSTATUS 1247 NTAPI 1248 USBH_SyncGetStringDescriptor(IN PDEVICE_OBJECT DeviceObject, 1249 IN UCHAR Index, 1250 IN USHORT LanguageId, 1251 IN PUSB_STRING_DESCRIPTOR Descriptor, 1252 IN ULONG NumberOfBytes, 1253 IN PULONG OutLength, 1254 IN BOOLEAN IsValidateLength) 1255 { 1256 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb; 1257 ULONG TransferedLength; 1258 NTSTATUS Status; 1259 1260 DPRINT("USBH_SyncGetStringDescriptor: Index - %x, LanguageId - %x\n", 1261 Index, 1262 LanguageId); 1263 1264 Urb = ExAllocatePoolWithTag(NonPagedPool, 1265 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), 1266 USB_HUB_TAG); 1267 1268 if (!Urb) 1269 { 1270 return STATUS_INSUFFICIENT_RESOURCES; 1271 } 1272 1273 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); 1274 1275 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE; 1276 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST); 1277 1278 Urb->TransferBuffer = Descriptor; 1279 Urb->TransferBufferLength = NumberOfBytes; 1280 1281 Urb->Index = Index; 1282 Urb->DescriptorType = USB_STRING_DESCRIPTOR_TYPE; 1283 Urb->LanguageId = LanguageId; 1284 1285 Status = USBH_SyncSubmitUrb(DeviceObject, (PURB)Urb); 1286 1287 if (!NT_SUCCESS(Status)) 1288 { 1289 ExFreePoolWithTag(Urb, USB_HUB_TAG); 1290 return Status; 1291 } 1292 1293 TransferedLength = Urb->TransferBufferLength; 1294 1295 if (TransferedLength > NumberOfBytes) 1296 { 1297 Status = STATUS_DEVICE_DATA_ERROR; 1298 } 1299 1300 if (!NT_SUCCESS(Status)) 1301 { 1302 ExFreePoolWithTag(Urb, USB_HUB_TAG); 1303 return Status; 1304 } 1305 1306 if (OutLength) 1307 { 1308 *OutLength = TransferedLength; 1309 } 1310 1311 if (IsValidateLength && TransferedLength != Descriptor->bLength) 1312 { 1313 Status = STATUS_DEVICE_DATA_ERROR; 1314 } 1315 1316 ExFreePoolWithTag(Urb, USB_HUB_TAG); 1317 1318 return Status; 1319 } 1320 1321 NTSTATUS 1322 NTAPI 1323 USBH_SyncGetStatus(IN PDEVICE_OBJECT DeviceObject, 1324 IN PUSHORT OutStatus, 1325 IN USHORT Function, 1326 IN USHORT RequestIndex) 1327 { 1328 struct _URB_CONTROL_GET_STATUS_REQUEST * Urb; 1329 NTSTATUS NtStatus; 1330 USHORT UsbStatus; 1331 1332 DPRINT("USBH_SyncGetStatus: ... \n"); 1333 1334 Urb = ExAllocatePoolWithTag(NonPagedPool, 1335 sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST), 1336 USB_HUB_TAG); 1337 1338 if (!Urb) 1339 { 1340 return STATUS_INSUFFICIENT_RESOURCES; 1341 } 1342 1343 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST)); 1344 1345 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST); 1346 Urb->Hdr.Function = Function; 1347 1348 Urb->TransferBuffer = &UsbStatus; 1349 Urb->TransferBufferLength = sizeof(UsbStatus); 1350 Urb->Index = RequestIndex; 1351 1352 NtStatus = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb); 1353 1354 *OutStatus = UsbStatus; 1355 1356 ExFreePoolWithTag(Urb, USB_HUB_TAG); 1357 1358 return NtStatus; 1359 } 1360 1361 NTSTATUS 1362 NTAPI 1363 USBH_SyncGetHubStatus(IN PUSBHUB_FDO_EXTENSION HubExtension, 1364 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus, 1365 IN ULONG Length) 1366 { 1367 BM_REQUEST_TYPE RequestType; 1368 1369 DPRINT("USBH_SyncGetHubStatus\n"); 1370 1371 RequestType.B = 0; 1372 RequestType.Recipient = BMREQUEST_TO_DEVICE; 1373 RequestType.Type = BMREQUEST_CLASS; 1374 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST; 1375 1376 return USBH_Transact(HubExtension, 1377 HubStatus, 1378 Length, 1379 BMREQUEST_DEVICE_TO_HOST, 1380 URB_FUNCTION_CLASS_DEVICE, 1381 RequestType, 1382 USB_REQUEST_GET_STATUS, 1383 0, 1384 0); 1385 } 1386 1387 NTSTATUS 1388 NTAPI 1389 USBH_SyncClearHubStatus(IN PUSBHUB_FDO_EXTENSION HubExtension, 1390 IN USHORT RequestValue) 1391 { 1392 BM_REQUEST_TYPE RequestType; 1393 1394 DPRINT("USBH_SyncClearHubStatus: RequestValue - %x\n", RequestValue); 1395 1396 RequestType.B = 0; 1397 RequestType.Recipient = BMREQUEST_TO_DEVICE; 1398 RequestType.Type = BMREQUEST_CLASS; 1399 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE; 1400 1401 return USBH_Transact(HubExtension, 1402 NULL, 1403 0, 1404 BMREQUEST_HOST_TO_DEVICE, 1405 URB_FUNCTION_CLASS_DEVICE, 1406 RequestType, 1407 USB_REQUEST_CLEAR_FEATURE, 1408 RequestValue, 1409 0); 1410 } 1411 1412 NTSTATUS 1413 NTAPI 1414 USBH_SyncGetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension, 1415 IN USHORT Port, 1416 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus, 1417 IN ULONG Length) 1418 { 1419 BM_REQUEST_TYPE RequestType; 1420 1421 DPRINT("USBH_SyncGetPortStatus: Port - %x\n", Port); 1422 1423 RequestType.B = 0; 1424 RequestType.Recipient = BMREQUEST_TO_OTHER; 1425 RequestType.Type = BMREQUEST_CLASS; 1426 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST; 1427 1428 return USBH_Transact(HubExtension, 1429 PortStatus, 1430 Length, 1431 BMREQUEST_DEVICE_TO_HOST, 1432 URB_FUNCTION_CLASS_OTHER, 1433 RequestType, 1434 USB_REQUEST_GET_STATUS, 1435 0, 1436 Port); 1437 } 1438 1439 1440 NTSTATUS 1441 NTAPI 1442 USBH_SyncClearPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension, 1443 IN USHORT Port, 1444 IN USHORT RequestValue) 1445 { 1446 BM_REQUEST_TYPE RequestType; 1447 1448 DPRINT("USBH_SyncClearPortStatus: Port - %x, RequestValue - %x\n", 1449 Port, 1450 RequestValue); 1451 1452 RequestType.B = 0; 1453 RequestType.Recipient = BMREQUEST_TO_OTHER; 1454 RequestType.Type = BMREQUEST_CLASS; 1455 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE; 1456 1457 return USBH_Transact(HubExtension, 1458 NULL, 1459 0, 1460 BMREQUEST_HOST_TO_DEVICE, 1461 URB_FUNCTION_CLASS_OTHER, 1462 RequestType, 1463 USB_REQUEST_CLEAR_FEATURE, 1464 RequestValue, 1465 Port); 1466 } 1467 1468 NTSTATUS 1469 NTAPI 1470 USBH_SyncPowerOnPort(IN PUSBHUB_FDO_EXTENSION HubExtension, 1471 IN USHORT Port, 1472 IN BOOLEAN IsWait) 1473 { 1474 PUSBHUB_PORT_DATA PortData; 1475 PUSB_HUB_DESCRIPTOR HubDescriptor; 1476 NTSTATUS Status = STATUS_SUCCESS; 1477 BM_REQUEST_TYPE RequestType; 1478 PUSB_PORT_STATUS_AND_CHANGE PortStatus; 1479 1480 DPRINT("USBH_SyncPowerOnPort: Port - %x, IsWait - %x\n", Port, IsWait); 1481 1482 ASSERT(Port > 0); 1483 PortData = &HubExtension->PortData[Port - 1]; 1484 PortStatus = &PortData->PortStatus; 1485 1486 if (PortStatus->PortStatus.Usb20PortStatus.CurrentConnectStatus == 1) 1487 { 1488 return Status; 1489 } 1490 1491 RequestType.B = 0; 1492 RequestType.Recipient = BMREQUEST_TO_DEVICE; 1493 RequestType.Type = BMREQUEST_CLASS; 1494 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE; 1495 1496 Status = USBH_Transact(HubExtension, 1497 NULL, 1498 0, 1499 BMREQUEST_HOST_TO_DEVICE, 1500 URB_FUNCTION_CLASS_OTHER, 1501 RequestType, 1502 USB_REQUEST_SET_FEATURE, 1503 USBHUB_FEATURE_PORT_POWER, 1504 Port); 1505 1506 if (NT_SUCCESS(Status)) 1507 { 1508 if (IsWait) 1509 { 1510 HubDescriptor = HubExtension->HubDescriptor; 1511 USBH_Wait(2 * HubDescriptor->bPowerOnToPowerGood); 1512 } 1513 1514 PortStatus->PortStatus.Usb20PortStatus.CurrentConnectStatus = 1; 1515 } 1516 1517 return Status; 1518 } 1519 1520 NTSTATUS 1521 NTAPI 1522 USBH_SyncPowerOnPorts(IN PUSBHUB_FDO_EXTENSION HubExtension) 1523 { 1524 PUSB_HUB_DESCRIPTOR HubDescriptor; 1525 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1526 USHORT Port; 1527 UCHAR NumberOfPorts; 1528 1529 DPRINT("USBH_SyncPowerOnPorts: ... \n"); 1530 1531 HubDescriptor = HubExtension->HubDescriptor; 1532 NumberOfPorts = HubDescriptor->bNumberOfPorts; 1533 1534 for (Port = 1; Port <= NumberOfPorts; ++Port) 1535 { 1536 Status = USBH_SyncPowerOnPort(HubExtension, Port, 0); 1537 1538 if (!NT_SUCCESS(Status)) 1539 { 1540 DPRINT1("USBH_SyncPowerOnPorts: USBH_SyncPowerOnPort() failed - %lX\n", 1541 Status); 1542 break; 1543 } 1544 } 1545 1546 USBH_Wait(2 * HubDescriptor->bPowerOnToPowerGood); 1547 1548 return Status; 1549 } 1550 1551 NTSTATUS 1552 NTAPI 1553 USBH_SyncDisablePort(IN PUSBHUB_FDO_EXTENSION HubExtension, 1554 IN USHORT Port) 1555 { 1556 PUSBHUB_PORT_DATA PortData; 1557 NTSTATUS Status; 1558 BM_REQUEST_TYPE RequestType; 1559 1560 DPRINT("USBH_SyncDisablePort ... \n"); 1561 1562 PortData = &HubExtension->PortData[Port - 1]; 1563 1564 RequestType.B = 0; 1565 RequestType.Recipient = BMREQUEST_TO_DEVICE; 1566 RequestType.Type = BMREQUEST_CLASS; 1567 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE; 1568 1569 Status = USBH_Transact(HubExtension, 1570 NULL, 1571 0, 1572 BMREQUEST_HOST_TO_DEVICE, 1573 URB_FUNCTION_CLASS_OTHER, 1574 RequestType, 1575 USB_REQUEST_CLEAR_FEATURE, 1576 USBHUB_FEATURE_PORT_ENABLE, 1577 Port); 1578 1579 if (NT_SUCCESS(Status)) 1580 { 1581 PortData->PortStatus.PortStatus.Usb20PortStatus.PortEnabledDisabled = 0; 1582 } 1583 1584 return Status; 1585 } 1586 1587 BOOLEAN 1588 NTAPI 1589 USBH_HubIsBusPowered(IN PDEVICE_OBJECT DeviceObject, 1590 IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor) 1591 { 1592 BOOLEAN Result; 1593 USHORT UsbStatus; 1594 NTSTATUS Status; 1595 1596 DPRINT("USBH_HubIsBusPowered: ... \n"); 1597 1598 Status = USBH_SyncGetStatus(DeviceObject, 1599 &UsbStatus, 1600 URB_FUNCTION_GET_STATUS_FROM_DEVICE, 1601 0); 1602 1603 if (!NT_SUCCESS(Status)) 1604 { 1605 Result = (HubConfigDescriptor->bmAttributes & USB_CONFIG_POWERED_MASK) 1606 == USB_CONFIG_BUS_POWERED; 1607 } 1608 else 1609 { 1610 Result = (UsbStatus & USB_GETSTATUS_SELF_POWERED) == 0; 1611 } 1612 1613 return Result; 1614 } 1615 1616 NTSTATUS 1617 NTAPI 1618 USBH_ChangeIndicationAckChangeComplete(IN PDEVICE_OBJECT DeviceObject, 1619 IN PIRP Irp, 1620 IN PVOID Context) 1621 { 1622 PUSBHUB_FDO_EXTENSION HubExtension; 1623 PVOID Event; 1624 USHORT Port; 1625 1626 HubExtension = Context; 1627 1628 DPRINT_SCE("USBH_ChangeIndicationAckChangeComplete: ... \n"); 1629 1630 ASSERT(HubExtension->Port > 0); 1631 Port = HubExtension->Port - 1; 1632 1633 HubExtension->PortData[Port].PortStatus = HubExtension->PortStatus; 1634 1635 Event = InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent, 1636 NULL); 1637 1638 if (Event) 1639 { 1640 KeSetEvent(Event, EVENT_INCREMENT, FALSE); 1641 } 1642 1643 USBH_SubmitStatusChangeTransfer(HubExtension); 1644 1645 if (!InterlockedDecrement(&HubExtension->ResetRequestCount)) 1646 { 1647 KeSetEvent(&HubExtension->ResetEvent, 1648 EVENT_INCREMENT, 1649 FALSE); 1650 } 1651 1652 return STATUS_MORE_PROCESSING_REQUIRED; 1653 } 1654 1655 NTSTATUS 1656 NTAPI 1657 USBH_ChangeIndicationAckChange(IN PUSBHUB_FDO_EXTENSION HubExtension, 1658 IN PIRP Irp, 1659 IN struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb, 1660 IN USHORT Port, 1661 IN USHORT RequestValue) 1662 { 1663 PIO_STACK_LOCATION IoStack; 1664 BM_REQUEST_TYPE RequestType; 1665 1666 DPRINT_SCE("USBH_ChangeIndicationAckChange: ... \n"); 1667 1668 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); 1669 Urb->Hdr.Function = URB_FUNCTION_CLASS_OTHER; 1670 Urb->Hdr.UsbdDeviceHandle = NULL; 1671 1672 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK; 1673 Urb->TransferBufferLength = 0; 1674 Urb->TransferBuffer = NULL; 1675 Urb->TransferBufferMDL = NULL; 1676 Urb->UrbLink = NULL; 1677 1678 RequestType.B = 0; 1679 RequestType.Recipient = BMREQUEST_TO_OTHER; 1680 RequestType.Type = BMREQUEST_CLASS; 1681 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE; 1682 1683 Urb->RequestTypeReservedBits = RequestType.B; 1684 Urb->Request = USB_REQUEST_CLEAR_FEATURE; 1685 Urb->Index = Port; 1686 Urb->Value = RequestValue; 1687 1688 IoInitializeIrp(Irp, 1689 IoSizeOfIrp(HubExtension->LowerDevice->StackSize), 1690 HubExtension->LowerDevice->StackSize); 1691 1692 IoStack = IoGetNextIrpStackLocation(Irp); 1693 1694 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 1695 IoStack->Parameters.Others.Argument1 = Urb; 1696 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; 1697 1698 IoSetCompletionRoutine(Irp, 1699 USBH_ChangeIndicationAckChangeComplete, 1700 HubExtension, 1701 TRUE, 1702 TRUE, 1703 TRUE); 1704 1705 return IoCallDriver(HubExtension->LowerDevice, Irp); 1706 } 1707 1708 NTSTATUS 1709 NTAPI 1710 USBH_ChangeIndicationProcessChange(IN PDEVICE_OBJECT DeviceObject, 1711 IN PIRP Irp, 1712 IN PVOID Context) 1713 { 1714 PUSBHUB_FDO_EXTENSION HubExtension; 1715 PUSBHUB_IO_WORK_ITEM WorkItem; 1716 USHORT RequestValue; 1717 1718 HubExtension = Context; 1719 1720 DPRINT_SCE("USBH_ChangeIndicationProcessChange: PortStatus - %lX\n", 1721 HubExtension->PortStatus.AsUlong32); 1722 1723 if ((NT_SUCCESS(Irp->IoStatus.Status) || 1724 USBD_SUCCESS(HubExtension->SCEWorkerUrb.Hdr.Status)) && 1725 (HubExtension->PortStatus.PortChange.Usb20PortChange.ResetChange || 1726 HubExtension->PortStatus.PortChange.Usb20PortChange.PortEnableDisableChange)) 1727 { 1728 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1729 { 1730 KeSetEvent(&HubExtension->PendingRequestEvent, 1731 EVENT_INCREMENT, 1732 FALSE); 1733 } 1734 1735 USBH_FreeWorkItem(HubExtension->WorkItemToQueue); 1736 1737 HubExtension->WorkItemToQueue = NULL; 1738 1739 if (HubExtension->PortStatus.PortChange.Usb20PortChange.ResetChange) 1740 { 1741 RequestValue = USBHUB_FEATURE_C_PORT_RESET; 1742 } 1743 else 1744 { 1745 RequestValue = USBHUB_FEATURE_C_PORT_ENABLE; 1746 } 1747 1748 USBH_ChangeIndicationAckChange(HubExtension, 1749 HubExtension->ResetPortIrp, 1750 &HubExtension->SCEWorkerUrb, 1751 HubExtension->Port, 1752 RequestValue); 1753 } 1754 else 1755 { 1756 ASSERT(HubExtension->WorkItemToQueue != NULL); 1757 1758 WorkItem = HubExtension->WorkItemToQueue; 1759 HubExtension->WorkItemToQueue = NULL; 1760 1761 USBH_QueueWorkItem(HubExtension, WorkItem); 1762 } 1763 1764 return STATUS_MORE_PROCESSING_REQUIRED; 1765 } 1766 1767 NTSTATUS 1768 NTAPI 1769 USBH_ChangeIndicationQueryChange(IN PUSBHUB_FDO_EXTENSION HubExtension, 1770 IN PIRP Irp, 1771 IN struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb, 1772 IN USHORT Port) 1773 { 1774 PUSBHUB_IO_WORK_ITEM WorkItem; 1775 NTSTATUS Status; 1776 PIO_STACK_LOCATION IoStack; 1777 BM_REQUEST_TYPE RequestType; 1778 1779 DPRINT_SCE("USBH_ChangeIndicationQueryChange: Port - %x\n", Port); 1780 1781 InterlockedIncrement(&HubExtension->PendingRequestCount); 1782 1783 if (!Port) 1784 { 1785 ASSERT(HubExtension->WorkItemToQueue != NULL); 1786 1787 WorkItem = HubExtension->WorkItemToQueue; 1788 HubExtension->WorkItemToQueue = NULL; 1789 1790 USBH_QueueWorkItem(HubExtension, WorkItem); 1791 1792 return STATUS_SUCCESS; 1793 } 1794 1795 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); 1796 Urb->Hdr.UsbdDeviceHandle = NULL; 1797 Urb->Hdr.Function = URB_FUNCTION_CLASS_OTHER; 1798 1799 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN; 1800 Urb->TransferBuffer = &HubExtension->PortStatus; 1801 Urb->TransferBufferLength = sizeof(HubExtension->PortStatus); 1802 Urb->TransferBufferMDL = NULL; 1803 Urb->UrbLink = NULL; 1804 1805 RequestType.B = 0; 1806 RequestType.Recipient = BMREQUEST_TO_OTHER; 1807 RequestType.Type = BMREQUEST_CLASS; 1808 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST; 1809 1810 Urb->RequestTypeReservedBits = RequestType.B; 1811 Urb->Request = USB_REQUEST_GET_STATUS; 1812 Urb->Value = 0; 1813 Urb->Index = Port; 1814 1815 HubExtension->Port = Port; 1816 1817 IoInitializeIrp(Irp, 1818 IoSizeOfIrp(HubExtension->LowerDevice->StackSize), 1819 HubExtension->LowerDevice->StackSize); 1820 1821 IoStack = IoGetNextIrpStackLocation(Irp); 1822 1823 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 1824 IoStack->Parameters.Others.Argument1 = Urb; 1825 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; 1826 1827 IoSetCompletionRoutine(Irp, 1828 USBH_ChangeIndicationProcessChange, 1829 HubExtension, 1830 TRUE, 1831 TRUE, 1832 TRUE); 1833 1834 Status = IoCallDriver(HubExtension->LowerDevice, Irp); 1835 1836 return Status; 1837 } 1838 1839 VOID 1840 NTAPI 1841 USBH_ProcessHubStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension, 1842 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus) 1843 { 1844 USB_HUB_CHANGE HubStatusChange; 1845 1846 DPRINT_SCE("USBH_ProcessHubStateChange: HubStatus - %lx\n", HubStatus->AsUlong32); 1847 1848 HubStatusChange = HubStatus->HubChange; 1849 1850 if (HubStatusChange.LocalPowerChange) 1851 { 1852 DPRINT1("USBH_ProcessHubStateChange: LocalPowerChange\n"); 1853 USBH_SyncClearHubStatus(HubExtension, 1854 USBHUB_FEATURE_C_HUB_LOCAL_POWER); 1855 } 1856 else if (HubStatusChange.OverCurrentChange) 1857 { 1858 USBH_SyncClearHubStatus(HubExtension, 1859 USBHUB_FEATURE_C_HUB_OVER_CURRENT); 1860 if (HubStatus->HubStatus.OverCurrent) 1861 { 1862 DPRINT1("USBH_ProcessHubStateChange: OverCurrent UNIMPLEMENTED. FIXME\n"); 1863 DbgBreakPoint(); 1864 } 1865 } 1866 } 1867 1868 VOID 1869 NTAPI 1870 USBH_ProcessPortStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension, 1871 IN USHORT Port, 1872 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus) 1873 { 1874 PUSBHUB_PORT_DATA PortData; 1875 USB_20_PORT_CHANGE PortStatusChange; 1876 PDEVICE_OBJECT PortDevice; 1877 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 1878 PVOID SerialNumber; 1879 PVOID DeviceHandle; 1880 USHORT RequestValue; 1881 KIRQL Irql; 1882 1883 DPRINT_SCE("USBH_ProcessPortStateChange ... \n"); 1884 1885 ASSERT(Port > 0); 1886 PortData = &HubExtension->PortData[Port - 1]; 1887 1888 PortStatusChange = PortStatus->PortChange.Usb20PortChange; 1889 1890 if (PortStatusChange.ConnectStatusChange) 1891 { 1892 PortData->PortStatus = *PortStatus; 1893 1894 USBH_SyncClearPortStatus(HubExtension, 1895 Port, 1896 USBHUB_FEATURE_C_PORT_CONNECTION); 1897 1898 PortData = &HubExtension->PortData[Port - 1]; 1899 1900 PortDevice = PortData->DeviceObject; 1901 1902 if (!PortDevice) 1903 { 1904 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations); 1905 return; 1906 } 1907 1908 PortExtension = PortDevice->DeviceExtension; 1909 1910 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_OVERCURRENT_PORT) 1911 { 1912 return; 1913 } 1914 1915 KeAcquireSpinLock(&HubExtension->RelationsWorkerSpinLock, &Irql); 1916 1917 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3) 1918 { 1919 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql); 1920 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations); 1921 return; 1922 } 1923 1924 PortData->DeviceObject = NULL; 1925 PortData->ConnectionStatus = NoDeviceConnected; 1926 1927 HubExtension->HubFlags |= USBHUB_FDO_FLAG_STATE_CHANGING; 1928 1929 InsertTailList(&HubExtension->PdoList, &PortExtension->PortLink); 1930 1931 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql); 1932 1933 SerialNumber = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, 1934 NULL); 1935 1936 if (SerialNumber) 1937 { 1938 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG); 1939 } 1940 1941 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle, 1942 NULL); 1943 1944 if (DeviceHandle) 1945 { 1946 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 1947 USBH_SyncDisablePort(HubExtension, Port); 1948 } 1949 1950 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations); 1951 } 1952 else if (PortStatusChange.PortEnableDisableChange) 1953 { 1954 RequestValue = USBHUB_FEATURE_C_PORT_ENABLE; 1955 PortData->PortStatus = *PortStatus; 1956 USBH_SyncClearPortStatus(HubExtension, Port, RequestValue); 1957 return; 1958 } 1959 else if (PortStatusChange.SuspendChange) 1960 { 1961 DPRINT1("USBH_ProcessPortStateChange: SuspendChange UNIMPLEMENTED. FIXME\n"); 1962 DbgBreakPoint(); 1963 } 1964 else if (PortStatusChange.OverCurrentIndicatorChange) 1965 { 1966 DPRINT1("USBH_ProcessPortStateChange: OverCurrentIndicatorChange UNIMPLEMENTED. FIXME\n"); 1967 DbgBreakPoint(); 1968 } 1969 else if (PortStatusChange.ResetChange) 1970 { 1971 RequestValue = USBHUB_FEATURE_C_PORT_RESET; 1972 PortData->PortStatus = *PortStatus; 1973 USBH_SyncClearPortStatus(HubExtension, Port, RequestValue); 1974 } 1975 } 1976 1977 NTSTATUS 1978 NTAPI 1979 USBH_GetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension, 1980 IN PULONG PortStatus) 1981 { 1982 PIRP Irp; 1983 PIO_STACK_LOCATION IoStack; 1984 NTSTATUS Status; 1985 KEVENT Event; 1986 IO_STATUS_BLOCK IoStatusBlock; 1987 1988 DPRINT("USBH_GetPortStatus ... \n"); 1989 1990 *PortStatus = 0; 1991 1992 KeInitializeEvent(&Event, NotificationEvent, FALSE); 1993 1994 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_PORT_STATUS, 1995 HubExtension->LowerDevice, 1996 NULL, 1997 0, 1998 NULL, 1999 0, 2000 TRUE, 2001 &Event, 2002 &IoStatusBlock); 2003 2004 if (!Irp) 2005 { 2006 return STATUS_INSUFFICIENT_RESOURCES; 2007 } 2008 2009 IoStack = IoGetNextIrpStackLocation(Irp); 2010 IoStack->Parameters.Others.Argument1 = PortStatus; 2011 2012 Status = IoCallDriver(HubExtension->LowerDevice, Irp); 2013 2014 if (Status == STATUS_PENDING) 2015 { 2016 KeWaitForSingleObject(&Event, 2017 Suspended, 2018 KernelMode, 2019 FALSE, 2020 NULL); 2021 } 2022 else 2023 { 2024 IoStatusBlock.Status = Status; 2025 } 2026 2027 return IoStatusBlock.Status; 2028 } 2029 2030 NTSTATUS 2031 NTAPI 2032 USBH_EnableParentPort(IN PUSBHUB_FDO_EXTENSION HubExtension) 2033 { 2034 PIRP Irp; 2035 NTSTATUS Status; 2036 KEVENT Event; 2037 IO_STATUS_BLOCK IoStatusBlock; 2038 2039 DPRINT("USBH_EnableParentPort ... \n"); 2040 2041 KeInitializeEvent(&Event, NotificationEvent, FALSE); 2042 2043 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_ENABLE_PORT, 2044 HubExtension->LowerDevice, 2045 NULL, 2046 0, 2047 NULL, 2048 0, 2049 TRUE, 2050 &Event, 2051 &IoStatusBlock); 2052 2053 if (!Irp) 2054 { 2055 return STATUS_INSUFFICIENT_RESOURCES; 2056 } 2057 2058 Status = IoCallDriver(HubExtension->LowerDevice, Irp); 2059 2060 if (Status == STATUS_PENDING) 2061 { 2062 KeWaitForSingleObject(&Event, 2063 Suspended, 2064 KernelMode, 2065 FALSE, 2066 NULL); 2067 } 2068 else 2069 { 2070 IoStatusBlock.Status = Status; 2071 } 2072 2073 return IoStatusBlock.Status; 2074 } 2075 2076 NTSTATUS 2077 NTAPI 2078 USBH_ResetInterruptPipe(IN PUSBHUB_FDO_EXTENSION HubExtension) 2079 { 2080 struct _URB_PIPE_REQUEST * Urb; 2081 NTSTATUS Status; 2082 2083 DPRINT("USBH_ResetInterruptPipe ... \n"); 2084 2085 Urb = ExAllocatePoolWithTag(NonPagedPool, 2086 sizeof(struct _URB_PIPE_REQUEST), 2087 USB_HUB_TAG); 2088 2089 if (Urb) 2090 { 2091 RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST)); 2092 2093 Urb->Hdr.Length = sizeof(struct _URB_PIPE_REQUEST); 2094 Urb->Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL; 2095 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle; 2096 2097 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, 2098 (PURB)Urb); 2099 2100 ExFreePoolWithTag(Urb, USB_HUB_TAG); 2101 } 2102 else 2103 { 2104 Status = STATUS_INSUFFICIENT_RESOURCES; 2105 } 2106 2107 if (NT_SUCCESS(Status)) 2108 { 2109 HubExtension->RequestErrors = 0; 2110 } 2111 2112 return Status; 2113 } 2114 2115 NTSTATUS 2116 NTAPI 2117 USBH_ResetHub(IN PUSBHUB_FDO_EXTENSION HubExtension) 2118 { 2119 NTSTATUS Status; 2120 ULONG PortStatusFlags = 0; 2121 2122 DPRINT("USBH_ResetHub: ... \n"); 2123 2124 Status = USBH_GetPortStatus(HubExtension, &PortStatusFlags); 2125 2126 if (!NT_SUCCESS(Status)) 2127 { 2128 return Status; 2129 } 2130 2131 if (!(PortStatusFlags & USBD_PORT_ENABLED)) 2132 { 2133 if (PortStatusFlags & USBD_PORT_CONNECTED) 2134 { 2135 USBH_EnableParentPort(HubExtension); 2136 } 2137 } 2138 2139 Status = USBH_ResetInterruptPipe(HubExtension); 2140 2141 return Status; 2142 } 2143 2144 VOID 2145 NTAPI 2146 USBH_ChangeIndicationWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 2147 IN PVOID Context) 2148 { 2149 PUSBHUB_FDO_EXTENSION LowerHubExtension; 2150 PUSBHUB_PORT_PDO_EXTENSION LowerPortExtension; 2151 PUSBHUB_STATUS_CHANGE_CONTEXT WorkItem; 2152 USB_PORT_STATUS_AND_CHANGE PortStatus; 2153 USB_HUB_STATUS_AND_CHANGE HubStatus; 2154 NTSTATUS Status; 2155 USHORT Port = 0; 2156 2157 DPRINT_SCE("USBH_ChangeIndicationWorker ... \n"); 2158 2159 WorkItem = Context; 2160 2161 KeWaitForSingleObject(&HubExtension->HubSemaphore, 2162 Executive, 2163 KernelMode, 2164 FALSE, 2165 NULL); 2166 2167 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING) 2168 { 2169 KeSetEvent(&HubExtension->StatusChangeEvent, 2170 EVENT_INCREMENT, 2171 FALSE); 2172 2173 goto Exit; 2174 } 2175 2176 if (!HubExtension->RequestErrors) 2177 { 2178 goto Enum; 2179 } 2180 2181 DPRINT_SCE("USBH_ChangeIndicationWorker: RequestErrors - %x\n", 2182 HubExtension->RequestErrors); 2183 2184 if (HubExtension->LowerPDO == HubExtension->RootHubPdo) 2185 { 2186 goto Enum; 2187 } 2188 2189 LowerPortExtension = HubExtension->LowerPDO->DeviceExtension; 2190 2191 if (LowerPortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D1_OR_D2) 2192 { 2193 goto Enum; 2194 } 2195 2196 LowerHubExtension = LowerPortExtension->HubExtension; 2197 2198 if (!LowerHubExtension) 2199 { 2200 goto Enum; 2201 } 2202 2203 Status = USBH_SyncGetPortStatus(LowerHubExtension, 2204 LowerPortExtension->PortNumber, 2205 &PortStatus, 2206 sizeof(USB_PORT_STATUS_AND_CHANGE)); 2207 2208 if (!NT_SUCCESS(Status) || 2209 !PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus) 2210 { 2211 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_REMOVED; 2212 2213 KeSetEvent(&HubExtension->StatusChangeEvent, 2214 EVENT_INCREMENT, 2215 FALSE); 2216 2217 goto Exit; 2218 } 2219 2220 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING)) 2221 { 2222 HubExtension->HubFlags |= USBHUB_FDO_FLAG_ESD_RECOVERING; 2223 2224 DPRINT1("USBH_ChangeIndicationWorker: USBHUB_FDO_FLAG_ESD_RECOVERING FIXME\n"); 2225 DbgBreakPoint(); 2226 2227 goto Exit; 2228 } 2229 2230 Enum: 2231 2232 if (WorkItem->IsRequestErrors) 2233 { 2234 USBH_ResetHub(HubExtension); 2235 } 2236 else 2237 { 2238 for (Port = 0; 2239 Port < HubExtension->HubDescriptor->bNumberOfPorts; 2240 Port++) 2241 { 2242 if (IsBitSet((PUCHAR)(WorkItem + 1), Port)) 2243 { 2244 break; 2245 } 2246 } 2247 2248 if (Port) 2249 { 2250 Status = USBH_SyncGetPortStatus(HubExtension, 2251 Port, 2252 &PortStatus, 2253 sizeof(PortStatus)); 2254 } 2255 else 2256 { 2257 Status = USBH_SyncGetHubStatus(HubExtension, 2258 &HubStatus, 2259 sizeof(HubStatus)); 2260 } 2261 2262 if (NT_SUCCESS(Status)) 2263 { 2264 if (Port) 2265 { 2266 USBH_ProcessPortStateChange(HubExtension, 2267 Port, 2268 &PortStatus); 2269 } 2270 else 2271 { 2272 USBH_ProcessHubStateChange(HubExtension, 2273 &HubStatus); 2274 } 2275 } 2276 else 2277 { 2278 HubExtension->RequestErrors++; 2279 2280 if (HubExtension->RequestErrors > USBHUB_MAX_REQUEST_ERRORS) 2281 { 2282 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 2283 goto Exit; 2284 } 2285 } 2286 } 2287 2288 USBH_SubmitStatusChangeTransfer(HubExtension); 2289 2290 Exit: 2291 2292 KeReleaseSemaphore(&HubExtension->HubSemaphore, 2293 LOW_REALTIME_PRIORITY, 2294 1, 2295 FALSE); 2296 2297 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 2298 { 2299 KeSetEvent(&HubExtension->PendingRequestEvent, 2300 EVENT_INCREMENT, 2301 FALSE); 2302 } 2303 2304 if (!InterlockedDecrement((PLONG)&HubExtension->ResetRequestCount)) 2305 { 2306 KeSetEvent(&HubExtension->ResetEvent, 2307 EVENT_INCREMENT, 2308 FALSE); 2309 2310 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEFER_CHECK_IDLE) 2311 { 2312 USBH_CheckHubIdle(HubExtension); 2313 } 2314 } 2315 } 2316 2317 NTSTATUS 2318 NTAPI 2319 USBH_ChangeIndication(IN PDEVICE_OBJECT DeviceObject, 2320 IN PIRP Irp, 2321 IN PVOID Context) 2322 { 2323 PUSBHUB_FDO_EXTENSION HubExtension; 2324 USBD_STATUS UrbStatus; 2325 BOOLEAN IsErrors = FALSE; 2326 PUSBHUB_IO_WORK_ITEM HubWorkItem; 2327 PUSBHUB_STATUS_CHANGE_CONTEXT HubWorkItemBuffer; 2328 USHORT NumPorts; 2329 USHORT Port; 2330 NTSTATUS Status; 2331 PVOID Bitmap; 2332 ULONG BufferLength; 2333 2334 HubExtension = Context; 2335 UrbStatus = HubExtension->SCEWorkerUrb.Hdr.Status; 2336 2337 DPRINT_SCE("USBH_ChangeIndication: IrpStatus - %x, UrbStatus - %x, HubFlags - %lX\n", 2338 Irp->IoStatus.Status, 2339 UrbStatus, 2340 HubExtension->HubFlags); 2341 2342 if (NT_ERROR(Irp->IoStatus.Status) || USBD_ERROR(UrbStatus) || 2343 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) || 2344 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING)) 2345 { 2346 HubExtension->RequestErrors++; 2347 2348 IsErrors = TRUE; 2349 2350 KeSetEvent(&HubExtension->StatusChangeEvent, 2351 EVENT_INCREMENT, 2352 FALSE); 2353 2354 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING || 2355 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED || 2356 HubExtension->RequestErrors > USBHUB_MAX_REQUEST_ERRORS || 2357 Irp->IoStatus.Status == STATUS_DELETE_PENDING) 2358 { 2359 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n", 2360 HubExtension->RequestErrors); 2361 2362 return STATUS_MORE_PROCESSING_REQUIRED; 2363 } 2364 2365 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n", 2366 HubExtension->RequestErrors); 2367 } 2368 else 2369 { 2370 HubExtension->RequestErrors = 0; 2371 } 2372 2373 BufferLength = sizeof(USBHUB_STATUS_CHANGE_CONTEXT) + 2374 HubExtension->SCEBitmapLength; 2375 2376 Status = USBH_AllocateWorkItem(HubExtension, 2377 &HubWorkItem, 2378 USBH_ChangeIndicationWorker, 2379 BufferLength, 2380 (PVOID *)&HubWorkItemBuffer, 2381 DelayedWorkQueue); 2382 2383 if (!NT_SUCCESS(Status)) 2384 { 2385 return STATUS_MORE_PROCESSING_REQUIRED; 2386 } 2387 2388 RtlZeroMemory(HubWorkItemBuffer, BufferLength); 2389 2390 HubWorkItemBuffer->IsRequestErrors = FALSE; 2391 2392 if (IsErrors) 2393 { 2394 HubWorkItemBuffer->IsRequestErrors = TRUE; 2395 } 2396 2397 if (InterlockedIncrement(&HubExtension->ResetRequestCount) == 1) 2398 { 2399 KeClearEvent(&HubExtension->ResetEvent); 2400 } 2401 2402 HubWorkItemBuffer->HubExtension = HubExtension; 2403 2404 HubExtension->WorkItemToQueue = HubWorkItem; 2405 2406 Bitmap = HubWorkItemBuffer + 1; 2407 2408 RtlCopyMemory(Bitmap, 2409 HubExtension->SCEBitmap, 2410 HubExtension->SCEBitmapLength); 2411 2412 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts; 2413 2414 for (Port = 0; Port <= NumPorts; ++Port) 2415 { 2416 if (IsBitSet(Bitmap, Port)) 2417 { 2418 break; 2419 } 2420 } 2421 2422 if (Port > NumPorts) 2423 { 2424 Port = 0; 2425 } 2426 2427 Status = USBH_ChangeIndicationQueryChange(HubExtension, 2428 HubExtension->ResetPortIrp, 2429 &HubExtension->SCEWorkerUrb, 2430 Port); 2431 2432 if (NT_ERROR(Status)) 2433 { 2434 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 2435 } 2436 2437 return STATUS_MORE_PROCESSING_REQUIRED; 2438 } 2439 2440 NTSTATUS 2441 NTAPI 2442 USBH_SubmitStatusChangeTransfer(IN PUSBHUB_FDO_EXTENSION HubExtension) 2443 { 2444 PIRP Irp; 2445 NTSTATUS Status; 2446 struct _URB_BULK_OR_INTERRUPT_TRANSFER * Urb; 2447 PIO_STACK_LOCATION IoStack; 2448 2449 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubExtension - %p, SCEIrp - %p\n", 2450 HubExtension, 2451 HubExtension->SCEIrp); 2452 2453 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_NOT_D0_STATE) 2454 { 2455 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: USBHUB_FDO_FLAG_NOT_D0_STATE\n"); 2456 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubFlags - %lX\n", 2457 HubExtension->HubFlags); 2458 2459 return STATUS_INVALID_DEVICE_STATE; 2460 } 2461 2462 Irp = HubExtension->SCEIrp; 2463 2464 if (!Irp) 2465 { 2466 return STATUS_INVALID_DEVICE_STATE; 2467 } 2468 2469 Urb = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *)&HubExtension->SCEWorkerUrb; 2470 2471 Urb->Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER); 2472 Urb->Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; 2473 Urb->Hdr.UsbdDeviceHandle = NULL; 2474 2475 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle; 2476 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK; 2477 Urb->TransferBuffer = HubExtension->SCEBitmap; 2478 Urb->TransferBufferLength = HubExtension->SCEBitmapLength; 2479 Urb->TransferBufferMDL = NULL; 2480 Urb->UrbLink = NULL; 2481 2482 IoInitializeIrp(Irp, 2483 IoSizeOfIrp(HubExtension->LowerDevice->StackSize), 2484 HubExtension->LowerDevice->StackSize); 2485 2486 IoStack = IoGetNextIrpStackLocation(Irp); 2487 2488 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 2489 IoStack->Parameters.Others.Argument1 = &HubExtension->SCEWorkerUrb; 2490 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; 2491 2492 IoSetCompletionRoutine(Irp, 2493 USBH_ChangeIndication, 2494 HubExtension, 2495 TRUE, 2496 TRUE, 2497 TRUE); 2498 2499 KeClearEvent(&HubExtension->StatusChangeEvent); 2500 2501 Status = IoCallDriver(HubExtension->LowerDevice, Irp); 2502 2503 return Status; 2504 } 2505 2506 NTSTATUS 2507 NTAPI 2508 USBD_CreateDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension, 2509 IN PUSB_DEVICE_HANDLE * OutDeviceHandle, 2510 IN USB_PORT_STATUS UsbPortStatus, 2511 IN USHORT Port) 2512 { 2513 PUSB_DEVICE_HANDLE HubDeviceHandle; 2514 PUSB_BUSIFFN_CREATE_USB_DEVICE CreateUsbDevice; 2515 2516 DPRINT("USBD_CreateDeviceEx: Port - %x, UsbPortStatus - 0x%04X\n", 2517 Port, 2518 UsbPortStatus.AsUshort16); 2519 2520 CreateUsbDevice = HubExtension->BusInterface.CreateUsbDevice; 2521 2522 if (!CreateUsbDevice) 2523 { 2524 return STATUS_NOT_IMPLEMENTED; 2525 } 2526 2527 HubDeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice); 2528 2529 return CreateUsbDevice(HubExtension->BusInterface.BusContext, 2530 OutDeviceHandle, 2531 HubDeviceHandle, 2532 UsbPortStatus.AsUshort16, 2533 Port); 2534 } 2535 2536 NTSTATUS 2537 NTAPI 2538 USBD_RemoveDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension, 2539 IN PUSB_DEVICE_HANDLE DeviceHandle, 2540 IN ULONG Flags) 2541 { 2542 PUSB_BUSIFFN_REMOVE_USB_DEVICE RemoveUsbDevice; 2543 2544 DPRINT("USBD_RemoveDeviceEx: DeviceHandle - %p, Flags - %X\n", 2545 DeviceHandle, 2546 Flags); 2547 2548 RemoveUsbDevice = HubExtension->BusInterface.RemoveUsbDevice; 2549 2550 if (!RemoveUsbDevice) 2551 { 2552 return STATUS_NOT_IMPLEMENTED; 2553 } 2554 2555 return RemoveUsbDevice(HubExtension->BusInterface.BusContext, 2556 DeviceHandle, 2557 Flags); 2558 } 2559 2560 NTSTATUS 2561 NTAPI 2562 USBD_InitializeDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension, 2563 IN PUSB_DEVICE_HANDLE DeviceHandle, 2564 IN PUCHAR DeviceDescriptorBuffer, 2565 IN ULONG DeviceDescriptorBufferLength, 2566 IN PUCHAR ConfigDescriptorBuffer, 2567 IN ULONG ConfigDescriptorBufferLength) 2568 { 2569 NTSTATUS Status; 2570 PUSB_BUSIFFN_INITIALIZE_USB_DEVICE InitializeUsbDevice; 2571 PUSB_BUSIFFN_GET_USB_DESCRIPTORS GetUsbDescriptors; 2572 2573 DPRINT("USBD_InitializeDeviceEx: ... \n"); 2574 2575 InitializeUsbDevice = HubExtension->BusInterface.InitializeUsbDevice; 2576 GetUsbDescriptors = HubExtension->BusInterface.GetUsbDescriptors; 2577 2578 if (!InitializeUsbDevice || !GetUsbDescriptors) 2579 { 2580 return STATUS_NOT_IMPLEMENTED; 2581 } 2582 2583 Status = InitializeUsbDevice(HubExtension->BusInterface.BusContext, 2584 DeviceHandle); 2585 2586 if (!NT_SUCCESS(Status)) 2587 { 2588 return Status; 2589 } 2590 2591 return GetUsbDescriptors(HubExtension->BusInterface.BusContext, 2592 DeviceHandle, 2593 DeviceDescriptorBuffer, 2594 &DeviceDescriptorBufferLength, 2595 ConfigDescriptorBuffer, 2596 &ConfigDescriptorBufferLength); 2597 } 2598 2599 VOID 2600 NTAPI 2601 USBHUB_SetDeviceHandleData(IN PUSBHUB_FDO_EXTENSION HubExtension, 2602 IN PDEVICE_OBJECT UsbDevicePdo, 2603 IN PVOID DeviceHandle) 2604 { 2605 PUSB_BUSIFFN_SET_DEVHANDLE_DATA SetDeviceHandleData; 2606 2607 DPRINT("USBHUB_SetDeviceHandleData ... \n"); 2608 2609 SetDeviceHandleData = HubExtension->BusInterface.SetDeviceHandleData; 2610 2611 if (!SetDeviceHandleData) 2612 { 2613 return; 2614 } 2615 2616 SetDeviceHandleData(HubExtension->BusInterface.BusContext, 2617 DeviceHandle, 2618 UsbDevicePdo); 2619 } 2620 2621 VOID 2622 NTAPI 2623 USBHUB_FlushAllTransfers(IN PUSBHUB_FDO_EXTENSION HubExtension) 2624 { 2625 PUSB_BUSIFFN_FLUSH_TRANSFERS FlushTransfers; 2626 2627 DPRINT("USBHUB_FlushAllTransfers ... \n"); 2628 2629 FlushTransfers = HubExtension->BusInterface.FlushTransfers; 2630 2631 if (FlushTransfers) 2632 { 2633 FlushTransfers(HubExtension->BusInterface.BusContext, NULL); 2634 } 2635 } 2636 2637 NTSTATUS 2638 NTAPI 2639 USBD_GetDeviceInformationEx(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2640 IN PUSBHUB_FDO_EXTENSION HubExtension, 2641 IN PUSB_NODE_CONNECTION_INFORMATION_EX Info, 2642 IN ULONG Length, 2643 IN PUSB_DEVICE_HANDLE DeviceHandle) 2644 { 2645 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation; 2646 PUSB_DEVICE_INFORMATION_0 DeviceInfo; 2647 SIZE_T DeviceInfoLength; 2648 PUSB_NODE_CONNECTION_INFORMATION_EX NodeInfo; 2649 SIZE_T NodeInfoLength; 2650 ULONG PipeNumber; 2651 ULONG dummy; 2652 NTSTATUS Status; 2653 2654 DPRINT("USBD_GetDeviceInformationEx ... \n"); 2655 2656 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation; 2657 2658 if (!QueryDeviceInformation) 2659 { 2660 Status = STATUS_NOT_IMPLEMENTED; 2661 return Status; 2662 } 2663 2664 DeviceInfoLength = sizeof(USB_DEVICE_INFORMATION_0); 2665 2666 while (TRUE) 2667 { 2668 DeviceInfo = ExAllocatePoolWithTag(PagedPool, 2669 DeviceInfoLength, 2670 USB_HUB_TAG); 2671 2672 if (!DeviceInfo) 2673 { 2674 return STATUS_INSUFFICIENT_RESOURCES; 2675 } 2676 2677 RtlZeroMemory(DeviceInfo, DeviceInfoLength); 2678 2679 DeviceInfo->InformationLevel = 0; 2680 2681 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext, 2682 DeviceHandle, 2683 DeviceInfo, 2684 DeviceInfoLength, 2685 &dummy); 2686 2687 if (Status != STATUS_BUFFER_TOO_SMALL) 2688 { 2689 break; 2690 } 2691 2692 DeviceInfoLength = DeviceInfo->ActualLength; 2693 2694 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG); 2695 } 2696 2697 NodeInfo = NULL; 2698 NodeInfoLength = 0; 2699 2700 if (NT_SUCCESS(Status)) 2701 { 2702 NodeInfoLength = (sizeof(USB_NODE_CONNECTION_INFORMATION_EX) - sizeof(USB_PIPE_INFO)) + 2703 DeviceInfo->NumberOfOpenPipes * sizeof(USB_PIPE_INFO); 2704 2705 NodeInfo = ExAllocatePoolWithTag(PagedPool, NodeInfoLength, USB_HUB_TAG); 2706 2707 if (!NodeInfo) 2708 { 2709 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG); 2710 return STATUS_INSUFFICIENT_RESOURCES; 2711 } 2712 2713 RtlZeroMemory(NodeInfo, NodeInfoLength); 2714 2715 NodeInfo->ConnectionIndex = Info->ConnectionIndex; 2716 2717 RtlCopyMemory(&NodeInfo->DeviceDescriptor, 2718 &DeviceInfo->DeviceDescriptor, 2719 sizeof(USB_DEVICE_DESCRIPTOR)); 2720 2721 NodeInfo->CurrentConfigurationValue = DeviceInfo->CurrentConfigurationValue; 2722 NodeInfo->Speed = DeviceInfo->DeviceSpeed; 2723 NodeInfo->DeviceIsHub = PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE; 2724 NodeInfo->DeviceAddress = DeviceInfo->DeviceAddress; 2725 NodeInfo->NumberOfOpenPipes = DeviceInfo->NumberOfOpenPipes; 2726 NodeInfo->ConnectionStatus = Info->ConnectionStatus; 2727 2728 for (PipeNumber = 0; 2729 PipeNumber < DeviceInfo->NumberOfOpenPipes; 2730 PipeNumber++) 2731 { 2732 RtlCopyMemory(&NodeInfo->PipeList[PipeNumber], 2733 &DeviceInfo->PipeList[PipeNumber], 2734 sizeof(USB_PIPE_INFO)); 2735 } 2736 } 2737 2738 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG); 2739 2740 if (NodeInfo) 2741 { 2742 if (NodeInfoLength <= Length) 2743 { 2744 Length = NodeInfoLength; 2745 } 2746 else 2747 { 2748 Status = STATUS_BUFFER_TOO_SMALL; 2749 } 2750 2751 RtlCopyMemory(Info, NodeInfo, Length); 2752 2753 ExFreePoolWithTag(NodeInfo, USB_HUB_TAG); 2754 } 2755 2756 return Status; 2757 } 2758 2759 NTSTATUS 2760 NTAPI 2761 USBD_RestoreDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension, 2762 IN OUT PUSB_DEVICE_HANDLE OldDeviceHandle, 2763 IN OUT PUSB_DEVICE_HANDLE NewDeviceHandle) 2764 { 2765 PUSB_BUSIFFN_RESTORE_DEVICE RestoreUsbDevice; 2766 NTSTATUS Status; 2767 2768 DPRINT("USBD_RestoreDeviceEx: HubExtension - %p, OldDeviceHandle - %p, NewDeviceHandle - %p\n", 2769 HubExtension, 2770 OldDeviceHandle, 2771 NewDeviceHandle); 2772 2773 RestoreUsbDevice = HubExtension->BusInterface.RestoreUsbDevice; 2774 2775 if (RestoreUsbDevice) 2776 { 2777 Status = RestoreUsbDevice(HubExtension->BusInterface.BusContext, 2778 OldDeviceHandle, 2779 NewDeviceHandle); 2780 } 2781 else 2782 { 2783 Status = STATUS_NOT_IMPLEMENTED; 2784 } 2785 2786 return Status; 2787 } 2788 2789 NTSTATUS 2790 NTAPI 2791 USBH_AllocateWorkItem(PUSBHUB_FDO_EXTENSION HubExtension, 2792 PUSBHUB_IO_WORK_ITEM * OutHubIoWorkItem, 2793 PUSBHUB_WORKER_ROUTINE WorkerRoutine, 2794 SIZE_T BufferLength, 2795 PVOID * OutHubWorkItemBuffer, 2796 WORK_QUEUE_TYPE Type) 2797 { 2798 PUSBHUB_IO_WORK_ITEM HubIoWorkItem; 2799 PIO_WORKITEM WorkItem; 2800 PVOID WorkItemBuffer; 2801 2802 DPRINT("USBH_AllocateWorkItem: ... \n"); 2803 2804 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_WITEM_INIT)) 2805 { 2806 return STATUS_INVALID_PARAMETER; 2807 } 2808 2809 HubIoWorkItem = ExAllocatePoolWithTag(NonPagedPool, 2810 sizeof(USBHUB_IO_WORK_ITEM), 2811 USB_HUB_TAG); 2812 2813 if (!HubIoWorkItem) 2814 { 2815 return STATUS_INSUFFICIENT_RESOURCES; 2816 } 2817 2818 RtlZeroMemory(HubIoWorkItem, sizeof(USBHUB_IO_WORK_ITEM)); 2819 2820 WorkItem = IoAllocateWorkItem(HubExtension->Common.SelfDevice); 2821 2822 HubIoWorkItem->HubWorkItem = WorkItem; 2823 2824 if (!WorkItem) 2825 { 2826 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG); 2827 return STATUS_INSUFFICIENT_RESOURCES; 2828 } 2829 2830 if (BufferLength && OutHubWorkItemBuffer) 2831 { 2832 WorkItemBuffer = ExAllocatePoolWithTag(NonPagedPool, 2833 BufferLength, 2834 USB_HUB_TAG); 2835 2836 HubIoWorkItem->HubWorkItemBuffer = WorkItemBuffer; 2837 2838 if (!WorkItemBuffer) 2839 { 2840 IoFreeWorkItem(HubIoWorkItem->HubWorkItem); 2841 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG); 2842 2843 return STATUS_INSUFFICIENT_RESOURCES; 2844 } 2845 2846 RtlZeroMemory(WorkItemBuffer, BufferLength); 2847 } 2848 else 2849 { 2850 HubIoWorkItem->HubWorkItemBuffer = NULL; 2851 } 2852 2853 HubIoWorkItem->HubWorkItemType = Type; 2854 HubIoWorkItem->HubExtension = HubExtension; 2855 HubIoWorkItem->HubWorkerRoutine = WorkerRoutine; 2856 2857 if (OutHubIoWorkItem) 2858 { 2859 *OutHubIoWorkItem = HubIoWorkItem; 2860 } 2861 2862 if (OutHubWorkItemBuffer) 2863 { 2864 *OutHubWorkItemBuffer = HubIoWorkItem->HubWorkItemBuffer; 2865 } 2866 2867 return STATUS_SUCCESS; 2868 } 2869 2870 VOID 2871 NTAPI 2872 USBH_Worker(IN PDEVICE_OBJECT DeviceObject, 2873 IN PVOID Context) 2874 { 2875 PUSBHUB_IO_WORK_ITEM HubIoWorkItem; 2876 PUSBHUB_FDO_EXTENSION HubExtension; 2877 KIRQL OldIrql; 2878 PIO_WORKITEM WorkItem; 2879 2880 DPRINT("USBH_Worker: HubIoWorkItem - %p\n", Context); 2881 2882 HubIoWorkItem = Context; 2883 2884 InterlockedDecrement(&HubIoWorkItem->HubWorkerQueued); 2885 2886 HubExtension = HubIoWorkItem->HubExtension; 2887 WorkItem = HubIoWorkItem->HubWorkItem; 2888 2889 HubIoWorkItem->HubWorkerRoutine(HubIoWorkItem->HubExtension, 2890 HubIoWorkItem->HubWorkItemBuffer); 2891 2892 KeAcquireSpinLock(&HubExtension->WorkItemSpinLock, &OldIrql); 2893 RemoveEntryList(&HubIoWorkItem->HubWorkItemLink); 2894 KeReleaseSpinLock(&HubExtension->WorkItemSpinLock, OldIrql); 2895 2896 if (HubIoWorkItem->HubWorkItemBuffer) 2897 { 2898 ExFreePoolWithTag(HubIoWorkItem->HubWorkItemBuffer, USB_HUB_TAG); 2899 } 2900 2901 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG); 2902 2903 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 2904 { 2905 KeSetEvent(&HubExtension->PendingRequestEvent, 2906 EVENT_INCREMENT, 2907 FALSE); 2908 } 2909 2910 IoFreeWorkItem(WorkItem); 2911 2912 DPRINT("USBH_Worker: HubIoWorkItem %p complete\n", Context); 2913 } 2914 2915 VOID 2916 NTAPI 2917 USBH_QueueWorkItem(IN PUSBHUB_FDO_EXTENSION HubExtension, 2918 IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem) 2919 { 2920 DPRINT("USBH_QueueWorkItem: ... \n"); 2921 2922 InterlockedIncrement(&HubExtension->PendingRequestCount); 2923 InterlockedIncrement(&HubIoWorkItem->HubWorkerQueued); 2924 2925 ExInterlockedInsertTailList(&HubExtension->WorkItemList, 2926 &HubIoWorkItem->HubWorkItemLink, 2927 &HubExtension->WorkItemSpinLock); 2928 2929 IoQueueWorkItem(HubIoWorkItem->HubWorkItem, 2930 USBH_Worker, 2931 HubIoWorkItem->HubWorkItemType, 2932 HubIoWorkItem); 2933 } 2934 2935 VOID 2936 NTAPI 2937 USBH_FreeWorkItem(IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem) 2938 { 2939 PIO_WORKITEM WorkItem; 2940 2941 DPRINT("USBH_FreeWorkItem: ... \n"); 2942 2943 WorkItem = HubIoWorkItem->HubWorkItem; 2944 2945 if (HubIoWorkItem->HubWorkItemBuffer) 2946 { 2947 ExFreePoolWithTag(HubIoWorkItem->HubWorkItemBuffer, USB_HUB_TAG); 2948 } 2949 2950 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG); 2951 2952 IoFreeWorkItem(WorkItem); 2953 } 2954 2955 VOID 2956 NTAPI 2957 USBHUB_RootHubCallBack(IN PVOID Context) 2958 { 2959 PUSBHUB_FDO_EXTENSION HubExtension; 2960 2961 DPRINT("USBHUB_RootHubCallBack: ... \n"); 2962 2963 HubExtension = Context; 2964 2965 if (HubExtension->SCEIrp) 2966 { 2967 HubExtension->HubFlags |= (USBHUB_FDO_FLAG_DO_ENUMERATION | 2968 USBHUB_FDO_FLAG_NOT_ENUMERATED); 2969 2970 USBH_SubmitStatusChangeTransfer(HubExtension); 2971 2972 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations); 2973 } 2974 else 2975 { 2976 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_ENUMERATION; 2977 } 2978 2979 KeSetEvent(&HubExtension->RootHubNotificationEvent, 2980 EVENT_INCREMENT, 2981 FALSE); 2982 } 2983 2984 NTSTATUS 2985 NTAPI 2986 USBD_RegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension) 2987 { 2988 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification; 2989 2990 DPRINT("USBD_RegisterRootHubCallBack: ... \n"); 2991 2992 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification; 2993 2994 if (!RootHubInitNotification) 2995 { 2996 return STATUS_NOT_IMPLEMENTED; 2997 } 2998 2999 KeClearEvent(&HubExtension->RootHubNotificationEvent); 3000 3001 return RootHubInitNotification(HubExtension->BusInterface.BusContext, 3002 HubExtension, 3003 USBHUB_RootHubCallBack); 3004 } 3005 3006 NTSTATUS 3007 NTAPI 3008 USBD_UnRegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension) 3009 { 3010 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification; 3011 NTSTATUS Status; 3012 3013 DPRINT("USBD_UnRegisterRootHubCallBack ... \n"); 3014 3015 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification; 3016 3017 if (!RootHubInitNotification) 3018 { 3019 return STATUS_NOT_IMPLEMENTED; 3020 } 3021 3022 Status = RootHubInitNotification(HubExtension->BusInterface.BusContext, 3023 NULL, 3024 NULL); 3025 3026 if (!NT_SUCCESS(Status)) 3027 { 3028 KeWaitForSingleObject(&HubExtension->RootHubNotificationEvent, 3029 Executive, 3030 KernelMode, 3031 FALSE, 3032 NULL); 3033 } 3034 3035 return Status; 3036 } 3037 3038 VOID 3039 NTAPI 3040 USBH_HubSetDWakeCompletion(IN PDEVICE_OBJECT DeviceObject, 3041 IN UCHAR MinorFunction, 3042 IN POWER_STATE PowerState, 3043 IN PVOID Context, 3044 IN PIO_STATUS_BLOCK IoStatus) 3045 { 3046 DPRINT("USBH_HubSetDWakeCompletion: ... \n"); 3047 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE); 3048 } 3049 3050 VOID 3051 NTAPI 3052 USBH_HubQueuePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, 3053 IN PLIST_ENTRY IdleList) 3054 { 3055 PDEVICE_OBJECT PortDevice; 3056 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 3057 PIRP IdleIrp; 3058 PIRP HubIdleIrp; 3059 ULONG NumPorts; 3060 ULONG Port; 3061 KIRQL Irql; 3062 3063 DPRINT("USBH_HubQueuePortIdleIrps ... \n"); 3064 3065 InitializeListHead(IdleList); 3066 3067 IoAcquireCancelSpinLock(&Irql); 3068 3069 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts; 3070 3071 for (Port = 0; Port < NumPorts; ++Port) 3072 { 3073 PortDevice = HubExtension->PortData[Port].DeviceObject; 3074 3075 if (PortDevice) 3076 { 3077 PortExtension = PortDevice->DeviceExtension; 3078 3079 IdleIrp = PortExtension->IdleNotificationIrp; 3080 PortExtension->IdleNotificationIrp = NULL; 3081 3082 if (IdleIrp && IoSetCancelRoutine(IdleIrp, NULL)) 3083 { 3084 DPRINT1("USBH_HubQueuePortIdleIrps: IdleIrp != NULL. FIXME\n"); 3085 DbgBreakPoint(); 3086 } 3087 } 3088 } 3089 3090 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST) 3091 { 3092 HubIdleIrp = HubExtension->PendingIdleIrp; 3093 HubExtension->PendingIdleIrp = NULL; 3094 } 3095 else 3096 { 3097 HubIdleIrp = NULL; 3098 } 3099 3100 IoReleaseCancelSpinLock(Irql); 3101 3102 if (HubIdleIrp) 3103 { 3104 USBH_HubCancelIdleIrp(HubExtension, HubIdleIrp); 3105 } 3106 } 3107 3108 VOID 3109 NTAPI 3110 USBH_HubCompleteQueuedPortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, 3111 IN PLIST_ENTRY IdleList, 3112 IN NTSTATUS NtStatus) 3113 { 3114 DPRINT("USBH_HubCompleteQueuedPortIdleIrps ... \n"); 3115 3116 while (!IsListEmpty(IdleList)) 3117 { 3118 DPRINT1("USBH_HubCompleteQueuedPortIdleIrps: IdleList not Empty. FIXME\n"); 3119 DbgBreakPoint(); 3120 } 3121 } 3122 3123 VOID 3124 NTAPI 3125 USBH_FlushPortPwrList(IN PUSBHUB_FDO_EXTENSION HubExtension) 3126 { 3127 PDEVICE_OBJECT PortDevice; 3128 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 3129 PLIST_ENTRY Entry; 3130 ULONG Port; 3131 3132 DPRINT("USBH_FlushPortPwrList ... \n"); 3133 3134 InterlockedIncrement((PLONG)&HubExtension->PendingRequestCount); 3135 3136 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 3137 Executive, 3138 KernelMode, 3139 FALSE, 3140 NULL); 3141 3142 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; ++Port) 3143 { 3144 PortDevice = HubExtension->PortData[Port].DeviceObject; 3145 3146 if (!PortDevice) 3147 { 3148 continue; 3149 } 3150 3151 PortExtension = PortDevice->DeviceExtension; 3152 3153 InterlockedExchange((PLONG)&PortExtension->StateBehindD2, 0); 3154 3155 while (TRUE) 3156 { 3157 Entry = ExInterlockedRemoveHeadList(&PortExtension->PortPowerList, 3158 &PortExtension->PortPowerListSpinLock); 3159 3160 if (!Entry) 3161 { 3162 break; 3163 } 3164 3165 DPRINT1("USBH_FlushPortPwrList: PortPowerList FIXME\n"); 3166 DbgBreakPoint(); 3167 } 3168 } 3169 3170 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 3171 LOW_REALTIME_PRIORITY, 3172 1, 3173 FALSE); 3174 3175 if (!InterlockedDecrement((PLONG)&HubExtension->PendingRequestCount)) 3176 { 3177 KeSetEvent(&HubExtension->PendingRequestEvent, 3178 EVENT_INCREMENT, 3179 FALSE); 3180 } 3181 } 3182 3183 VOID 3184 NTAPI 3185 USBH_HubCompletePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, 3186 IN NTSTATUS NtStatus) 3187 { 3188 LIST_ENTRY IdleList; 3189 3190 DPRINT("USBH_HubCompletePortIdleIrps ... \n"); 3191 3192 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 3193 { 3194 USBH_HubQueuePortIdleIrps(HubExtension, &IdleList); 3195 3196 USBH_HubCompleteQueuedPortIdleIrps(HubExtension, 3197 &IdleList, 3198 NtStatus); 3199 3200 USBH_FlushPortPwrList(HubExtension); 3201 } 3202 } 3203 3204 VOID 3205 NTAPI 3206 USBH_HubCancelIdleIrp(IN PUSBHUB_FDO_EXTENSION HubExtension, 3207 IN PIRP IdleIrp) 3208 { 3209 DPRINT("USBH_HubCancelIdleIrp ... \n"); 3210 3211 IoCancelIrp(IdleIrp); 3212 3213 if (InterlockedExchange(&HubExtension->IdleRequestLock, 1)) 3214 { 3215 IoFreeIrp(IdleIrp); 3216 } 3217 } 3218 3219 BOOLEAN 3220 NTAPI 3221 USBH_CheckIdleAbort(IN PUSBHUB_FDO_EXTENSION HubExtension, 3222 IN BOOLEAN IsWait, 3223 IN BOOLEAN IsExtCheck) 3224 { 3225 PDEVICE_OBJECT PdoDevice; 3226 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 3227 PUSBHUB_PORT_DATA PortData; 3228 ULONG Port; 3229 BOOLEAN Result = FALSE; 3230 3231 DPRINT("USBH_CheckIdleAbort: ... \n"); 3232 3233 InterlockedIncrement(&HubExtension->PendingRequestCount); 3234 3235 if (IsWait == TRUE) 3236 { 3237 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 3238 Executive, 3239 KernelMode, 3240 FALSE, 3241 NULL); 3242 } 3243 3244 PortData = HubExtension->PortData; 3245 3246 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++) 3247 { 3248 PdoDevice = PortData[Port].DeviceObject; 3249 3250 if (PdoDevice) 3251 { 3252 PortExtension = PdoDevice->DeviceExtension; 3253 3254 if (PortExtension->PoRequestCounter) 3255 { 3256 Result = TRUE; 3257 goto Wait; 3258 } 3259 } 3260 } 3261 3262 if (IsExtCheck == TRUE) 3263 { 3264 PortData = HubExtension->PortData; 3265 3266 for (Port = 0; 3267 Port < HubExtension->HubDescriptor->bNumberOfPorts; 3268 Port++) 3269 { 3270 PdoDevice = PortData[Port].DeviceObject; 3271 3272 if (PdoDevice) 3273 { 3274 PortExtension = PdoDevice->DeviceExtension; 3275 InterlockedExchange(&PortExtension->StateBehindD2, 0); 3276 } 3277 } 3278 } 3279 3280 Wait: 3281 3282 if (IsWait == TRUE) 3283 { 3284 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 3285 LOW_REALTIME_PRIORITY, 3286 1, 3287 FALSE); 3288 } 3289 3290 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 3291 { 3292 KeSetEvent(&HubExtension->PendingRequestEvent, 3293 EVENT_INCREMENT, 3294 FALSE); 3295 } 3296 3297 return Result; 3298 } 3299 3300 VOID 3301 NTAPI 3302 USBH_FdoWaitWakeIrpCompletion(IN PDEVICE_OBJECT DeviceObject, 3303 IN UCHAR MinorFunction, 3304 IN POWER_STATE PowerState, 3305 IN PVOID Context, 3306 IN PIO_STATUS_BLOCK IoStatus) 3307 { 3308 DPRINT("USBH_FdoWaitWakeIrpCompletion ... \n"); 3309 } 3310 3311 NTSTATUS 3312 NTAPI 3313 USBH_FdoSubmitWaitWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension) 3314 { 3315 POWER_STATE PowerState; 3316 NTSTATUS Status; 3317 PIRP Irp = NULL; 3318 KIRQL Irql; 3319 3320 DPRINT("USBH_FdoSubmitWaitWakeIrp: ... \n"); 3321 3322 PowerState.SystemState = HubExtension->SystemWake; 3323 HubExtension->HubFlags |= USBHUB_FDO_FLAG_PENDING_WAKE_IRP; 3324 3325 InterlockedIncrement(&HubExtension->PendingRequestCount); 3326 InterlockedExchange(&HubExtension->FdoWaitWakeLock, 0); 3327 3328 Status = PoRequestPowerIrp(HubExtension->LowerPDO, 3329 IRP_MN_WAIT_WAKE, 3330 PowerState, 3331 USBH_FdoWaitWakeIrpCompletion, 3332 HubExtension, 3333 &Irp); 3334 3335 IoAcquireCancelSpinLock(&Irql); 3336 3337 if (Status == STATUS_PENDING) 3338 { 3339 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP) 3340 { 3341 HubExtension->PendingWakeIrp = Irp; 3342 DPRINT("USBH_FdoSubmitWaitWakeIrp: PendingWakeIrp - %p\n", 3343 HubExtension->PendingWakeIrp); 3344 } 3345 } 3346 else 3347 { 3348 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP; 3349 3350 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 3351 { 3352 KeSetEvent(&HubExtension->PendingRequestEvent, 3353 EVENT_INCREMENT, 3354 FALSE); 3355 } 3356 } 3357 3358 IoReleaseCancelSpinLock(Irql); 3359 3360 return Status; 3361 } 3362 3363 VOID 3364 NTAPI 3365 USBH_FdoIdleNotificationCallback(IN PVOID Context) 3366 { 3367 PUSBHUB_FDO_EXTENSION HubExtension; 3368 PUSBHUB_PORT_DATA PortData; 3369 PDEVICE_OBJECT PortDevice; 3370 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 3371 PIRP Irp = NULL; 3372 PIRP IdleIrp; 3373 POWER_STATE PowerState; 3374 KEVENT Event; 3375 ULONG Port; 3376 PIO_STACK_LOCATION IoStack; 3377 PUSB_IDLE_CALLBACK_INFO CallbackInfo; 3378 BOOLEAN IsReady; 3379 KIRQL OldIrql; 3380 NTSTATUS Status; 3381 3382 HubExtension = Context; 3383 3384 DPRINT("USBH_FdoIdleNotificationCallback: HubExtension - %p, HubFlags - %lX\n", 3385 HubExtension, 3386 HubExtension->HubFlags); 3387 3388 if (HubExtension->HubFlags & (USBHUB_FDO_FLAG_ENUM_POST_RECOVER | 3389 USBHUB_FDO_FLAG_WAKEUP_START | 3390 USBHUB_FDO_FLAG_DEVICE_REMOVED | 3391 USBHUB_FDO_FLAG_STATE_CHANGING | 3392 USBHUB_FDO_FLAG_ESD_RECOVERING | 3393 USBHUB_FDO_FLAG_DEVICE_FAILED | 3394 USBHUB_FDO_FLAG_DEVICE_STOPPING)) 3395 { 3396 DbgBreakPoint(); 3397 return; 3398 } 3399 3400 HubExtension->HubFlags |= USBHUB_FDO_FLAG_GOING_IDLE; 3401 3402 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP)) 3403 { 3404 Status = USBH_FdoSubmitWaitWakeIrp(HubExtension); 3405 3406 if (Status != STATUS_PENDING) 3407 { 3408 DPRINT("Status != STATUS_PENDING. DbgBreakPoint()\n"); 3409 DbgBreakPoint(); 3410 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_GOING_IDLE; 3411 return; 3412 } 3413 } 3414 3415 InterlockedIncrement(&HubExtension->PendingRequestCount); 3416 3417 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 3418 Executive, 3419 KernelMode, 3420 FALSE, 3421 NULL); 3422 3423 PortData = HubExtension->PortData; 3424 IsReady = TRUE; 3425 3426 for (Port = 0; 3427 Port < HubExtension->HubDescriptor->bNumberOfPorts; 3428 Port++) 3429 { 3430 PortDevice = PortData[Port].DeviceObject; 3431 3432 if (PortDevice) 3433 { 3434 PortExtension = PortDevice->DeviceExtension; 3435 3436 IdleIrp = PortExtension->IdleNotificationIrp; 3437 3438 if (!IdleIrp) 3439 { 3440 IsReady = FALSE; 3441 goto IdleHub; 3442 } 3443 3444 IoStack = IoGetCurrentIrpStackLocation(IdleIrp); 3445 3446 CallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 3447 3448 if (!CallbackInfo) 3449 { 3450 IsReady = FALSE; 3451 goto IdleHub; 3452 } 3453 3454 if (!CallbackInfo->IdleCallback) 3455 { 3456 IsReady = FALSE; 3457 goto IdleHub; 3458 } 3459 3460 if (PortExtension->PendingSystemPoRequest) 3461 { 3462 IsReady = FALSE; 3463 goto IdleHub; 3464 } 3465 3466 if (InterlockedCompareExchange(&PortExtension->StateBehindD2, 3467 1, 3468 0)) 3469 { 3470 IsReady = FALSE; 3471 goto IdleHub; 3472 } 3473 3474 DPRINT("USBH_FdoIdleNotificationCallback: IdleContext - %p\n", 3475 CallbackInfo->IdleContext); 3476 3477 CallbackInfo->IdleCallback(CallbackInfo->IdleContext); 3478 3479 if (PortExtension->CurrentPowerState.DeviceState == PowerDeviceD0) 3480 { 3481 IsReady = FALSE; 3482 goto IdleHub; 3483 } 3484 } 3485 } 3486 3487 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING) && 3488 (USBH_CheckIdleAbort(HubExtension, FALSE, FALSE) == TRUE)) 3489 { 3490 IsReady = FALSE; 3491 } 3492 3493 IdleHub: 3494 3495 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 3496 LOW_REALTIME_PRIORITY, 3497 1, 3498 FALSE); 3499 3500 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 3501 { 3502 KeSetEvent(&HubExtension->PendingRequestEvent, 3503 EVENT_INCREMENT, 3504 FALSE); 3505 } 3506 3507 if (!IsReady || 3508 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_SUSPENDED)) 3509 { 3510 DPRINT1("USBH_FdoIdleNotificationCallback: HubFlags - %lX\n", 3511 HubExtension->HubFlags); 3512 3513 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED | 3514 USBHUB_FDO_FLAG_GOING_IDLE); 3515 3516 /* Aborting Idle for Hub */ 3517 IoAcquireCancelSpinLock(&OldIrql); 3518 3519 if (HubExtension->PendingIdleIrp) 3520 { 3521 Irp = HubExtension->PendingIdleIrp; 3522 HubExtension->PendingIdleIrp = NULL; 3523 } 3524 3525 IoReleaseCancelSpinLock(OldIrql); 3526 3527 if (Irp) 3528 { 3529 USBH_HubCancelIdleIrp(HubExtension, Irp); 3530 } 3531 3532 DbgBreakPoint(); 3533 USBH_HubCompletePortIdleIrps(HubExtension, STATUS_CANCELLED); 3534 } 3535 else 3536 { 3537 PowerState.DeviceState = HubExtension->DeviceWake; 3538 3539 KeWaitForSingleObject(&HubExtension->IdleSemaphore, 3540 Executive, 3541 KernelMode, 3542 FALSE, 3543 NULL); 3544 3545 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_GOING_IDLE; 3546 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_SUSPENSE; 3547 3548 KeInitializeEvent(&Event, NotificationEvent, FALSE); 3549 3550 DPRINT("USBH_FdoIdleNotificationCallback: LowerPdo - %p\n", 3551 HubExtension->LowerPDO); 3552 3553 DPRINT("USBH_FdoIdleNotificationCallback: PowerState.DeviceState - %x\n", 3554 PowerState.DeviceState); 3555 3556 Status = PoRequestPowerIrp(HubExtension->LowerPDO, 3557 IRP_MN_SET_POWER, 3558 PowerState, 3559 USBH_HubSetDWakeCompletion, 3560 &Event, 3561 NULL); 3562 3563 if (Status == STATUS_PENDING) 3564 { 3565 KeWaitForSingleObject(&Event, 3566 Executive, 3567 KernelMode, 3568 FALSE, 3569 NULL); 3570 } 3571 } 3572 } 3573 3574 VOID 3575 NTAPI 3576 USBH_CompletePortIdleIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 3577 IN PVOID Context) 3578 { 3579 PUSBHUB_IDLE_PORT_CONTEXT IdlePortContext; 3580 NTSTATUS NtStatus; 3581 NTSTATUS Status; 3582 BOOLEAN IsFlush = FALSE; 3583 3584 DPRINT("USBH_CompletePortIdleIrpsWorker ... \n"); 3585 3586 IdlePortContext = Context; 3587 NtStatus = IdlePortContext->Status; 3588 3589 USBH_HubCompleteQueuedPortIdleIrps(HubExtension, 3590 &IdlePortContext->PwrList, 3591 NtStatus); 3592 3593 DPRINT1("USBH_CompletePortIdleIrpsWorker: USBH_RegQueryFlushPortPowerIrpsFlag() UNIMPLEMENTED. FIXME\n"); 3594 Status = STATUS_NOT_IMPLEMENTED;// USBH_RegQueryFlushPortPowerIrpsFlag(&IsFlush); 3595 3596 if (NT_SUCCESS(Status)) 3597 { 3598 if (IsFlush) 3599 { 3600 USBH_FlushPortPwrList(HubExtension); 3601 } 3602 } 3603 } 3604 3605 VOID 3606 NTAPI 3607 USBH_IdleCompletePowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 3608 IN PVOID Context) 3609 { 3610 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer; 3611 3612 DPRINT("USBH_IdleCompletePowerHubWorker ... \n"); 3613 3614 if (HubExtension && 3615 HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 && 3616 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 3617 { 3618 USBH_HubSetD0(HubExtension); 3619 } 3620 3621 HubWorkItemBuffer = Context; 3622 3623 USBH_HubCompletePortIdleIrps(HubExtension, HubWorkItemBuffer->Status); 3624 3625 } 3626 3627 NTSTATUS 3628 NTAPI 3629 USBH_FdoIdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject, 3630 IN PIRP Irp, 3631 IN PVOID Context) 3632 { 3633 PUSBHUB_FDO_EXTENSION HubExtension; 3634 NTSTATUS NtStatus; 3635 PVOID IdleIrp; 3636 KIRQL Irql; 3637 NTSTATUS Status; 3638 PUSBHUB_IO_WORK_ITEM HubIoWorkItem; 3639 3640 IoAcquireCancelSpinLock(&Irql); 3641 3642 HubExtension = Context; 3643 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST; 3644 3645 IdleIrp = InterlockedExchangePointer((PVOID)&HubExtension->PendingIdleIrp, 3646 NULL); 3647 3648 DPRINT("USBH_FdoIdleNotificationRequestComplete: IdleIrp - %p\n", IdleIrp); 3649 3650 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 3651 { 3652 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 3653 } 3654 3655 IoReleaseCancelSpinLock(Irql); 3656 3657 NtStatus = Irp->IoStatus.Status; 3658 3659 DPRINT("USBH_FdoIdleNotificationRequestComplete: NtStatus - %lX\n", 3660 NtStatus); 3661 3662 if (!NT_SUCCESS(NtStatus) && 3663 NtStatus != STATUS_POWER_STATE_INVALID && 3664 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED) && 3665 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 3666 { 3667 DPRINT("USBH_FdoIdleNotificationRequestComplete: DeviceState - %x\n", 3668 HubExtension->CurrentPowerState.DeviceState); 3669 3670 if (HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0) 3671 { 3672 PUSBHUB_IDLE_PORT_CONTEXT HubWorkItemBuffer; 3673 3674 Status = USBH_AllocateWorkItem(HubExtension, 3675 &HubIoWorkItem, 3676 USBH_CompletePortIdleIrpsWorker, 3677 sizeof(USBHUB_IDLE_PORT_CONTEXT), 3678 (PVOID *)&HubWorkItemBuffer, 3679 DelayedWorkQueue); 3680 3681 if (NT_SUCCESS(Status)) 3682 { 3683 HubWorkItemBuffer->Status = NtStatus; 3684 3685 USBH_HubQueuePortIdleIrps(HubExtension, 3686 &HubWorkItemBuffer->PwrList); 3687 3688 USBH_QueueWorkItem(HubExtension, HubIoWorkItem); 3689 } 3690 } 3691 else 3692 { 3693 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer; 3694 3695 Status = USBH_AllocateWorkItem(HubExtension, 3696 &HubIoWorkItem, 3697 USBH_IdleCompletePowerHubWorker, 3698 sizeof(USBHUB_IDLE_HUB_CONTEXT), 3699 (PVOID *)&HubWorkItemBuffer, 3700 DelayedWorkQueue); 3701 3702 if (NT_SUCCESS(Status)) 3703 { 3704 HubWorkItemBuffer->Status = NtStatus; 3705 USBH_QueueWorkItem(HubExtension, HubIoWorkItem); 3706 } 3707 } 3708 } 3709 3710 if (IdleIrp || 3711 InterlockedExchange((PLONG)&HubExtension->IdleRequestLock, 1)) 3712 { 3713 DPRINT("USBH_FdoIdleNotificationRequestComplete: Irp - %p\n", Irp); 3714 IoFreeIrp(Irp); 3715 } 3716 3717 return STATUS_MORE_PROCESSING_REQUIRED; 3718 } 3719 3720 NTSTATUS 3721 NTAPI 3722 USBH_FdoSubmitIdleRequestIrp(IN PUSBHUB_FDO_EXTENSION HubExtension) 3723 { 3724 NTSTATUS Status; 3725 ULONG HubFlags; 3726 PDEVICE_OBJECT LowerPDO; 3727 PIRP Irp; 3728 PIO_STACK_LOCATION IoStack; 3729 KIRQL Irql; 3730 3731 DPRINT("USBH_FdoSubmitIdleRequestIrp: HubExtension - %p, PendingIdleIrp - %p\n", 3732 HubExtension, 3733 HubExtension->PendingIdleIrp); 3734 3735 if (HubExtension->PendingIdleIrp) 3736 { 3737 Status = STATUS_DEVICE_BUSY; 3738 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE); 3739 return Status; 3740 } 3741 3742 HubFlags = HubExtension->HubFlags; 3743 3744 if (HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING || 3745 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED) 3746 { 3747 HubExtension->HubFlags = HubFlags & ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST; 3748 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE); 3749 return STATUS_DEVICE_REMOVED; 3750 } 3751 3752 LowerPDO = HubExtension->LowerPDO; 3753 3754 HubExtension->IdleCallbackInfo.IdleCallback = USBH_FdoIdleNotificationCallback; 3755 HubExtension->IdleCallbackInfo.IdleContext = HubExtension; 3756 3757 Irp = IoAllocateIrp(LowerPDO->StackSize, FALSE); 3758 3759 if (!Irp) 3760 { 3761 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST; 3762 Status = STATUS_INSUFFICIENT_RESOURCES; 3763 3764 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE); 3765 return Status; 3766 } 3767 3768 IoStack = IoGetNextIrpStackLocation(Irp); 3769 3770 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 3771 3772 IoStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(USB_IDLE_CALLBACK_INFO); 3773 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION; 3774 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = &HubExtension->IdleCallbackInfo; 3775 3776 IoSetCompletionRoutine(Irp, 3777 USBH_FdoIdleNotificationRequestComplete, 3778 HubExtension, 3779 TRUE, 3780 TRUE, 3781 TRUE); 3782 3783 InterlockedIncrement(&HubExtension->PendingRequestCount); 3784 InterlockedExchange(&HubExtension->IdleRequestLock, 0); 3785 3786 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED | 3787 USBHUB_FDO_FLAG_GOING_IDLE); 3788 3789 Status = IoCallDriver(HubExtension->LowerPDO, Irp); 3790 3791 IoAcquireCancelSpinLock(&Irql); 3792 3793 if (Status == STATUS_PENDING && 3794 HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST) 3795 { 3796 HubExtension->PendingIdleIrp = Irp; 3797 } 3798 3799 IoReleaseCancelSpinLock(Irql); 3800 3801 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE); 3802 3803 return Status; 3804 } 3805 3806 VOID 3807 NTAPI 3808 USBH_CheckHubIdle(IN PUSBHUB_FDO_EXTENSION HubExtension) 3809 { 3810 PDEVICE_OBJECT PdoDevice; 3811 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 3812 PUSBHUB_PORT_DATA PortData; 3813 ULONG HubFlags; 3814 ULONG Port; 3815 KIRQL Irql; 3816 BOOLEAN IsHubIdle = FALSE; 3817 BOOLEAN IsAllPortsIdle; 3818 BOOLEAN IsHubCheck = TRUE; 3819 3820 DPRINT("USBH_CheckHubIdle: FIXME !!! HubExtension - %p\n", HubExtension); 3821 3822 return; //HACK: delete it line after fixing Power Manager!!! 3823 3824 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql); 3825 3826 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_CHECK_IDLE_LOCK) 3827 { 3828 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql); 3829 return; 3830 } 3831 3832 HubExtension->HubFlags |= USBHUB_FDO_FLAG_CHECK_IDLE_LOCK; 3833 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql); 3834 3835 if (USBH_GetRootHubExtension(HubExtension)->SystemPowerState.SystemState != PowerSystemWorking) 3836 { 3837 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql); 3838 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK; 3839 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql); 3840 return; 3841 } 3842 3843 HubFlags = HubExtension->HubFlags; 3844 DPRINT("USBH_CheckHubIdle: HubFlags - %lX\n", HubFlags); 3845 3846 if (!(HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) || 3847 !(HubFlags & USBHUB_FDO_FLAG_DO_ENUMERATION)) 3848 { 3849 goto Exit; 3850 } 3851 3852 if (HubFlags & USBHUB_FDO_FLAG_NOT_ENUMERATED || 3853 HubFlags & USBHUB_FDO_FLAG_ENUM_POST_RECOVER || 3854 HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED || 3855 HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING || 3856 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED || 3857 HubFlags & USBHUB_FDO_FLAG_STATE_CHANGING || 3858 HubFlags & USBHUB_FDO_FLAG_WAKEUP_START || 3859 HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING) 3860 { 3861 goto Exit; 3862 } 3863 3864 if (HubExtension->ResetRequestCount) 3865 { 3866 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEFER_CHECK_IDLE; 3867 goto Exit; 3868 } 3869 3870 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DEFER_CHECK_IDLE; 3871 3872 InterlockedIncrement(&HubExtension->PendingRequestCount); 3873 3874 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 3875 Executive, 3876 KernelMode, 3877 FALSE, 3878 NULL); 3879 3880 IoAcquireCancelSpinLock(&Irql); 3881 3882 IsAllPortsIdle = TRUE; 3883 3884 PortData = HubExtension->PortData; 3885 3886 for (Port = 0; 3887 Port < HubExtension->HubDescriptor->bNumberOfPorts; 3888 Port++) 3889 { 3890 PdoDevice = PortData[Port].DeviceObject; 3891 3892 if (PdoDevice) 3893 { 3894 PortExtension = PdoDevice->DeviceExtension; 3895 3896 if (!PortExtension->IdleNotificationIrp) 3897 { 3898 DPRINT("USBH_CheckHubIdle: PortExtension - %p\n", 3899 PortExtension); 3900 3901 IsAllPortsIdle = FALSE; 3902 IsHubCheck = FALSE; 3903 3904 break; 3905 } 3906 } 3907 } 3908 3909 if (IsHubCheck && 3910 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)) 3911 { 3912 KeClearEvent(&HubExtension->IdleEvent); 3913 HubExtension->HubFlags |= USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST; 3914 IsHubIdle = TRUE; 3915 } 3916 3917 IoReleaseCancelSpinLock(Irql); 3918 3919 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 3920 LOW_REALTIME_PRIORITY, 3921 1, 3922 FALSE); 3923 3924 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 3925 { 3926 KeSetEvent(&HubExtension->PendingRequestEvent, 3927 EVENT_INCREMENT, 3928 FALSE); 3929 } 3930 3931 DPRINT("USBH_CheckHubIdle: IsAllPortsIdle - %x, IsHubIdle - %x\n", 3932 IsAllPortsIdle, 3933 IsHubIdle); 3934 3935 if (IsAllPortsIdle && IsHubIdle) 3936 { 3937 USBH_FdoSubmitIdleRequestIrp(HubExtension); 3938 } 3939 3940 Exit: 3941 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql); 3942 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK; 3943 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql); 3944 } 3945 3946 VOID 3947 NTAPI 3948 USBH_CheckIdleWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 3949 IN PVOID Context) 3950 { 3951 DPRINT("USBH_CheckIdleWorker: ... \n"); 3952 USBH_CheckHubIdle(HubExtension); 3953 } 3954 3955 VOID 3956 NTAPI 3957 USBH_CheckIdleDeferred(IN PUSBHUB_FDO_EXTENSION HubExtension) 3958 { 3959 PUSBHUB_IO_WORK_ITEM HubIoWorkItem; 3960 NTSTATUS Status; 3961 3962 DPRINT("USBH_CheckIdleDeferred: HubExtension - %p\n", HubExtension); 3963 3964 Status = USBH_AllocateWorkItem(HubExtension, 3965 &HubIoWorkItem, 3966 USBH_CheckIdleWorker, 3967 0, 3968 NULL, 3969 DelayedWorkQueue); 3970 3971 DPRINT("USBH_CheckIdleDeferred: HubIoWorkItem - %p\n", HubIoWorkItem); 3972 3973 if (NT_SUCCESS(Status)) 3974 { 3975 USBH_QueueWorkItem(HubExtension, HubIoWorkItem); 3976 } 3977 } 3978 3979 VOID 3980 NTAPI 3981 USBH_PdoSetCapabilities(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension) 3982 { 3983 PUSBHUB_FDO_EXTENSION HubExtension; 3984 ULONG State; 3985 SYSTEM_POWER_STATE SystemPowerState; 3986 PDEVICE_POWER_STATE pDeviceState; 3987 3988 DPRINT("USBH_PdoSetCapabilities ... \n"); 3989 3990 HubExtension = PortExtension->HubExtension; 3991 3992 PortExtension->Capabilities.Size = 64; 3993 PortExtension->Capabilities.Version = 1; 3994 3995 PortExtension->Capabilities.Removable = 1; 3996 PortExtension->Capabilities.Address = PortExtension->PortNumber; 3997 3998 if (PortExtension->SerialNumber) 3999 { 4000 PortExtension->Capabilities.UniqueID = 1; 4001 } 4002 else 4003 { 4004 PortExtension->Capabilities.UniqueID = 0; 4005 } 4006 4007 PortExtension->Capabilities.RawDeviceOK = 0; 4008 4009 RtlCopyMemory(PortExtension->Capabilities.DeviceState, 4010 HubExtension->DeviceState, 4011 (PowerSystemMaximum + 2) * sizeof(POWER_STATE)); 4012 4013 PortExtension->Capabilities.DeviceState[1] = PowerDeviceD0; 4014 4015 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOTE_WAKEUP) 4016 { 4017 PortExtension->Capabilities.DeviceWake = PowerDeviceD2; 4018 4019 PortExtension->Capabilities.DeviceD1 = 1; 4020 PortExtension->Capabilities.DeviceD2 = 1; 4021 4022 PortExtension->Capabilities.WakeFromD0 = 1; 4023 PortExtension->Capabilities.WakeFromD1 = 1; 4024 PortExtension->Capabilities.WakeFromD2 = 1; 4025 4026 pDeviceState = &PortExtension->Capabilities.DeviceState[2]; 4027 4028 for (State = 2; State <= 5; State++) 4029 { 4030 SystemPowerState = State; 4031 4032 if (PortExtension->Capabilities.SystemWake < SystemPowerState) 4033 { 4034 *pDeviceState = PowerDeviceD3; 4035 } 4036 else 4037 { 4038 *pDeviceState = PowerDeviceD2; 4039 } 4040 4041 ++pDeviceState; 4042 } 4043 } 4044 else 4045 { 4046 PortExtension->Capabilities.DeviceWake = PowerDeviceD0; 4047 PortExtension->Capabilities.DeviceState[2] = PowerDeviceD3; 4048 PortExtension->Capabilities.DeviceState[3] = PowerDeviceD3; 4049 PortExtension->Capabilities.DeviceState[4] = PowerDeviceD3; 4050 PortExtension->Capabilities.DeviceState[5] = PowerDeviceD3; 4051 } 4052 } 4053 4054 NTSTATUS 4055 NTAPI 4056 USBH_ProcessDeviceInformation(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension) 4057 { 4058 PUSB_INTERFACE_DESCRIPTOR Pid; 4059 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor; 4060 NTSTATUS Status; 4061 4062 DPRINT("USBH_ProcessDeviceInformation ... \n"); 4063 4064 ConfigDescriptor = NULL; 4065 4066 RtlZeroMemory(&PortExtension->InterfaceDescriptor, 4067 sizeof(PortExtension->InterfaceDescriptor)); 4068 4069 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_HUB_DEVICE; 4070 4071 Status = USBH_GetConfigurationDescriptor(PortExtension->Common.SelfDevice, 4072 &ConfigDescriptor); 4073 4074 if (!NT_SUCCESS(Status)) 4075 { 4076 if (ConfigDescriptor) 4077 { 4078 ExFreePool(ConfigDescriptor); 4079 } 4080 4081 return Status; 4082 } 4083 4084 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REMOTE_WAKEUP; 4085 4086 if (ConfigDescriptor->bmAttributes & 0x20) 4087 { 4088 /* device configuration supports remote wakeup */ 4089 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REMOTE_WAKEUP; 4090 } 4091 4092 USBHUB_DumpingDeviceDescriptor(&PortExtension->DeviceDescriptor); 4093 USBHUB_DumpingConfiguration(ConfigDescriptor); 4094 4095 DPRINT_PNP("USBH_ProcessDeviceInformation: Class - %x, SubClass - %x, Protocol - %x\n", 4096 PortExtension->DeviceDescriptor.bDeviceClass, 4097 PortExtension->DeviceDescriptor.bDeviceSubClass, 4098 PortExtension->DeviceDescriptor.bDeviceProtocol); 4099 4100 DPRINT_PNP("USBH_ProcessDeviceInformation: bNumConfigurations - %x, bNumInterfaces - %x\n", 4101 PortExtension->DeviceDescriptor.bNumConfigurations, 4102 ConfigDescriptor->bNumInterfaces); 4103 4104 4105 /* Enumeration of USB Composite Devices (msdn): 4106 1) The device class field of the device descriptor (bDeviceClass) must contain a value of zero, 4107 or the class (bDeviceClass), subclass (bDeviceSubClass), and protocol (bDeviceProtocol) 4108 fields of the device descriptor must have the values 0xEF, 0x02 and 0x01 respectively, 4109 as explained in USB Interface Association Descriptor. 4110 2) The device must have multiple interfaces 4111 3) The device must have a single configuration. 4112 */ 4113 4114 if (((PortExtension->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_RESERVED) || 4115 (PortExtension->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_MISCELLANEOUS && 4116 PortExtension->DeviceDescriptor.bDeviceSubClass == 0x02 && 4117 PortExtension->DeviceDescriptor.bDeviceProtocol == 0x01)) && 4118 (ConfigDescriptor->bNumInterfaces > 1) && 4119 (PortExtension->DeviceDescriptor.bNumConfigurations < 2)) 4120 { 4121 DPRINT("USBH_ProcessDeviceInformation: Multi-Interface configuration\n"); 4122 4123 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_MULTI_INTERFACE; 4124 4125 if (ConfigDescriptor) 4126 { 4127 ExFreePool(ConfigDescriptor); 4128 } 4129 4130 return Status; 4131 } 4132 4133 Pid = USBD_ParseConfigurationDescriptorEx(ConfigDescriptor, 4134 ConfigDescriptor, 4135 -1, 4136 -1, 4137 -1, 4138 -1, 4139 -1); 4140 if (Pid) 4141 { 4142 RtlCopyMemory(&PortExtension->InterfaceDescriptor, 4143 Pid, 4144 sizeof(PortExtension->InterfaceDescriptor)); 4145 4146 if (Pid->bInterfaceClass == USB_DEVICE_CLASS_HUB) 4147 { 4148 PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_HUB_DEVICE | 4149 USBHUB_PDO_FLAG_REMOTE_WAKEUP); 4150 } 4151 } 4152 else 4153 { 4154 Status = STATUS_UNSUCCESSFUL; 4155 } 4156 4157 if (ConfigDescriptor) 4158 { 4159 ExFreePool(ConfigDescriptor); 4160 } 4161 4162 return Status; 4163 } 4164 4165 BOOLEAN 4166 NTAPI 4167 USBH_CheckDeviceIDUnique(IN PUSBHUB_FDO_EXTENSION HubExtension, 4168 IN USHORT idVendor, 4169 IN USHORT idProduct, 4170 IN PVOID SerialNumber, 4171 IN USHORT SN_DescriptorLength) 4172 { 4173 PDEVICE_OBJECT PortDevice; 4174 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 4175 ULONG Port; 4176 SIZE_T NumberBytes; 4177 4178 DPRINT("USBH_CheckDeviceIDUnique: idVendor - 0x%04X, idProduct - 0x%04X\n", 4179 idVendor, 4180 idProduct); 4181 4182 if (!HubExtension->HubDescriptor->bNumberOfPorts) 4183 { 4184 return TRUE; 4185 } 4186 4187 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++) 4188 { 4189 PortDevice = HubExtension->PortData[Port].DeviceObject; 4190 4191 if (PortDevice) 4192 { 4193 PortExtension = PortDevice->DeviceExtension; 4194 4195 if (PortExtension->DeviceDescriptor.idVendor == idVendor && 4196 PortExtension->DeviceDescriptor.idProduct == idProduct && 4197 PortExtension->SN_DescriptorLength == SN_DescriptorLength) 4198 { 4199 if (PortExtension->SerialNumber) 4200 { 4201 NumberBytes = RtlCompareMemory(PortExtension->SerialNumber, 4202 SerialNumber, 4203 SN_DescriptorLength); 4204 4205 if (NumberBytes == SN_DescriptorLength) 4206 { 4207 return FALSE; 4208 } 4209 } 4210 } 4211 } 4212 } 4213 4214 return TRUE; 4215 } 4216 4217 BOOLEAN 4218 NTAPI 4219 USBH_ValidateSerialNumberString(IN PUSHORT SerialNumberString) 4220 { 4221 USHORT ix; 4222 USHORT Symbol; 4223 4224 DPRINT("USBH_ValidateSerialNumberString: ... \n"); 4225 4226 for (ix = 0; SerialNumberString[ix] != UNICODE_NULL; ix++) 4227 { 4228 Symbol = SerialNumberString[ix]; 4229 4230 if (Symbol < 0x20 || Symbol > 0x7F || Symbol == 0x2C) // ',' 4231 { 4232 return FALSE; 4233 } 4234 } 4235 4236 return TRUE; 4237 } 4238 4239 4240 NTSTATUS 4241 NTAPI 4242 USBH_CheckDeviceLanguage(IN PDEVICE_OBJECT DeviceObject, 4243 IN USHORT LanguageId) 4244 { 4245 PUSB_STRING_DESCRIPTOR Descriptor; 4246 NTSTATUS Status; 4247 ULONG NumSymbols; 4248 ULONG ix; 4249 PWCHAR pSymbol; 4250 ULONG Length; 4251 4252 DPRINT("USBH_CheckDeviceLanguage: LanguageId - 0x%04X\n", LanguageId); 4253 4254 Descriptor = ExAllocatePoolWithTag(NonPagedPool, 4255 MAXIMUM_USB_STRING_LENGTH, 4256 USB_HUB_TAG); 4257 4258 if (!Descriptor) 4259 { 4260 return STATUS_INSUFFICIENT_RESOURCES; 4261 } 4262 4263 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH); 4264 4265 Status = USBH_SyncGetStringDescriptor(DeviceObject, 4266 0, 4267 0, 4268 Descriptor, 4269 MAXIMUM_USB_STRING_LENGTH, 4270 &Length, 4271 TRUE); 4272 4273 if (!NT_SUCCESS(Status) || 4274 Length < sizeof(USB_COMMON_DESCRIPTOR)) 4275 { 4276 goto Exit; 4277 } 4278 4279 NumSymbols = (Length - 4280 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / sizeof(WCHAR); 4281 4282 pSymbol = Descriptor->bString; 4283 4284 for (ix = 1; ix < NumSymbols; ix++) 4285 { 4286 if (*pSymbol == (WCHAR)LanguageId) 4287 { 4288 Status = STATUS_SUCCESS; 4289 goto Exit; 4290 } 4291 4292 pSymbol++; 4293 } 4294 4295 Status = STATUS_NOT_SUPPORTED; 4296 4297 Exit: 4298 ExFreePoolWithTag(Descriptor, USB_HUB_TAG); 4299 return Status; 4300 } 4301 4302 NTSTATUS 4303 NTAPI 4304 USBH_GetSerialNumberString(IN PDEVICE_OBJECT DeviceObject, 4305 IN LPWSTR * OutSerialNumber, 4306 IN PUSHORT OutDescriptorLength, 4307 IN USHORT LanguageId, 4308 IN UCHAR Index) 4309 { 4310 PUSB_STRING_DESCRIPTOR Descriptor; 4311 NTSTATUS Status; 4312 LPWSTR SerialNumberBuffer = NULL; 4313 UCHAR StringLength; 4314 UCHAR Length; 4315 4316 DPRINT("USBH_GetSerialNumberString: ... \n"); 4317 4318 *OutSerialNumber = NULL; 4319 *OutDescriptorLength = 0; 4320 4321 Descriptor = ExAllocatePoolWithTag(NonPagedPool, 4322 MAXIMUM_USB_STRING_LENGTH, 4323 USB_HUB_TAG); 4324 4325 if (!Descriptor) 4326 { 4327 return STATUS_INSUFFICIENT_RESOURCES; 4328 } 4329 4330 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH); 4331 4332 Status = USBH_CheckDeviceLanguage(DeviceObject, LanguageId); 4333 4334 if (!NT_SUCCESS(Status)) 4335 { 4336 goto Exit; 4337 } 4338 4339 Status = USBH_SyncGetStringDescriptor(DeviceObject, 4340 Index, 4341 LanguageId, 4342 Descriptor, 4343 MAXIMUM_USB_STRING_LENGTH, 4344 NULL, 4345 TRUE); 4346 4347 if (!NT_SUCCESS(Status) || 4348 Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR)) 4349 { 4350 Status = STATUS_INSUFFICIENT_RESOURCES; 4351 goto Exit; 4352 } 4353 4354 StringLength = Descriptor->bLength - 4355 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString); 4356 4357 Length = StringLength + sizeof(UNICODE_NULL); 4358 4359 SerialNumberBuffer = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 4360 4361 if (!SerialNumberBuffer) 4362 { 4363 goto Exit; 4364 } 4365 4366 RtlZeroMemory(SerialNumberBuffer, Length); 4367 RtlCopyMemory(SerialNumberBuffer, Descriptor->bString, StringLength); 4368 4369 *OutSerialNumber = SerialNumberBuffer; 4370 *OutDescriptorLength = Length; 4371 4372 Exit: 4373 ExFreePoolWithTag(Descriptor, USB_HUB_TAG); 4374 return Status; 4375 } 4376 4377 NTSTATUS 4378 NTAPI 4379 USBH_CreateDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 4380 IN USHORT Port, 4381 IN USB_PORT_STATUS UsbPortStatus, 4382 IN ULONG IsWait) 4383 { 4384 ULONG PdoNumber = 0; 4385 WCHAR CharDeviceName[64]; 4386 UNICODE_STRING DeviceName; 4387 PDEVICE_OBJECT DeviceObject = NULL; 4388 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 4389 PUSB_DEVICE_HANDLE DeviceHandle; 4390 LPWSTR SerialNumberBuffer; 4391 BOOLEAN IsHsDevice; 4392 BOOLEAN IsLsDevice; 4393 BOOLEAN IgnoringHwSerial = FALSE; 4394 NTSTATUS Status; 4395 UNICODE_STRING DestinationString; 4396 4397 DPRINT("USBH_CreateDevice: Port - %x, UsbPortStatus - %lX\n", 4398 Port, 4399 UsbPortStatus.AsUshort16); 4400 4401 do 4402 { 4403 RtlStringCbPrintfW(CharDeviceName, 4404 sizeof(CharDeviceName), 4405 L"\\Device\\USBPDO-%d", 4406 PdoNumber); 4407 4408 RtlInitUnicodeString(&DeviceName, CharDeviceName); 4409 4410 Status = IoCreateDevice(HubExtension->Common.SelfDevice->DriverObject, 4411 sizeof(USBHUB_PORT_PDO_EXTENSION), 4412 &DeviceName, 4413 FILE_DEVICE_USB, 4414 0, 4415 FALSE, 4416 &DeviceObject); 4417 4418 ++PdoNumber; 4419 } 4420 while (Status == STATUS_OBJECT_NAME_COLLISION); 4421 4422 if (!NT_SUCCESS(Status)) 4423 { 4424 ASSERT(Port > 0); 4425 HubExtension->PortData[Port-1].DeviceObject = DeviceObject; 4426 return Status; 4427 } 4428 4429 DeviceObject->StackSize = HubExtension->RootHubPdo2->StackSize; 4430 4431 PortExtension = DeviceObject->DeviceExtension; 4432 4433 DPRINT("USBH_CreateDevice: PortDevice - %p, <%wZ>\n", DeviceObject, &DeviceName); 4434 DPRINT("USBH_CreateDevice: PortExtension - %p\n", PortExtension); 4435 4436 RtlZeroMemory(PortExtension, sizeof(USBHUB_PORT_PDO_EXTENSION)); 4437 4438 PortExtension->Common.ExtensionType = USBH_EXTENSION_TYPE_PORT; 4439 PortExtension->Common.SelfDevice = DeviceObject; 4440 4441 PortExtension->HubExtension = HubExtension; 4442 PortExtension->RootHubExtension = HubExtension; 4443 4444 PortExtension->PortNumber = Port; 4445 PortExtension->CurrentPowerState.DeviceState = PowerDeviceD0; 4446 PortExtension->IgnoringHwSerial = FALSE; 4447 4448 KeInitializeSpinLock(&PortExtension->PortTimeoutSpinLock); 4449 4450 InitializeListHead(&PortExtension->PortPowerList); 4451 KeInitializeSpinLock(&PortExtension->PortPowerListSpinLock); 4452 4453 PortExtension->PoRequestCounter = 0; 4454 PortExtension->PendingSystemPoRequest = 0; 4455 PortExtension->PendingDevicePoRequest = 0; 4456 PortExtension->StateBehindD2 = 0; 4457 4458 SerialNumberBuffer = NULL; 4459 4460 IsHsDevice = UsbPortStatus.Usb20PortStatus.HighSpeedDeviceAttached; 4461 IsLsDevice = UsbPortStatus.Usb20PortStatus.LowSpeedDeviceAttached; 4462 4463 if (IsLsDevice == 0) 4464 { 4465 if (IsHsDevice) 4466 { 4467 PortExtension->PortPdoFlags = USBHUB_PDO_FLAG_PORT_HIGH_SPEED; 4468 } 4469 } 4470 else 4471 { 4472 PortExtension->PortPdoFlags = USBHUB_PDO_FLAG_PORT_LOW_SPEED; 4473 } 4474 4475 /* Initialize PortExtension->InstanceID */ 4476 RtlInitUnicodeString(&DestinationString, (PCWSTR)&PortExtension->InstanceID); 4477 DestinationString.MaximumLength = 4 * sizeof(WCHAR); 4478 Status = RtlIntegerToUnicodeString(Port, 10, &DestinationString); 4479 4480 DeviceObject->Flags |= DO_POWER_PAGABLE; 4481 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 4482 4483 if (!NT_SUCCESS(Status)) 4484 { 4485 DPRINT1("USBH_CreateDevice: IoCreateDevice() failed - %lX\n", Status); 4486 goto ErrorExit; 4487 } 4488 4489 Status = USBD_CreateDeviceEx(HubExtension, 4490 &PortExtension->DeviceHandle, 4491 UsbPortStatus, 4492 Port); 4493 4494 if (!NT_SUCCESS(Status)) 4495 { 4496 DPRINT1("USBH_CreateDevice: USBD_CreateDeviceEx() failed - %lX\n", Status); 4497 goto ErrorExit; 4498 } 4499 4500 Status = USBH_SyncResetPort(HubExtension, Port); 4501 4502 if (!NT_SUCCESS(Status)) 4503 { 4504 DPRINT1("USBH_CreateDevice: USBH_SyncResetPort() failed - %lX\n", Status); 4505 goto ErrorExit; 4506 } 4507 4508 if (IsWait) 4509 { 4510 USBH_Wait(50); 4511 } 4512 4513 Status = USBD_InitializeDeviceEx(HubExtension, 4514 PortExtension->DeviceHandle, 4515 (PUCHAR)&PortExtension->DeviceDescriptor, 4516 sizeof(USB_DEVICE_DESCRIPTOR), 4517 (PUCHAR)&PortExtension->ConfigDescriptor, 4518 sizeof(USB_CONFIGURATION_DESCRIPTOR)); 4519 4520 if (!NT_SUCCESS(Status)) 4521 { 4522 DPRINT1("USBH_CreateDevice: USBD_InitializeDeviceEx() failed - %lX\n", Status); 4523 PortExtension->DeviceHandle = NULL; 4524 goto ErrorExit; 4525 } 4526 4527 DPRINT1("USBH_RegQueryDeviceIgnoreHWSerNumFlag UNIMPLEMENTED. FIXME\n"); 4528 //Status = USBH_RegQueryDeviceIgnoreHWSerNumFlag(PortExtension->DeviceDescriptor.idVendor, 4529 // PortExtension->DeviceDescriptor.idProduct, 4530 // &IgnoringHwSerial); 4531 4532 if (TRUE)//Status == STATUS_OBJECT_NAME_NOT_FOUND) 4533 { 4534 IgnoringHwSerial = FALSE; 4535 } 4536 4537 if (IgnoringHwSerial) 4538 { 4539 PortExtension->IgnoringHwSerial = TRUE; 4540 } 4541 4542 if (PortExtension->DeviceDescriptor.iSerialNumber && 4543 !PortExtension->IgnoringHwSerial) 4544 { 4545 InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, NULL); 4546 4547 USBH_GetSerialNumberString(PortExtension->Common.SelfDevice, 4548 &SerialNumberBuffer, 4549 &PortExtension->SN_DescriptorLength, 4550 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 4551 PortExtension->DeviceDescriptor.iSerialNumber); 4552 4553 if (SerialNumberBuffer) 4554 { 4555 if (!USBH_ValidateSerialNumberString((PUSHORT)SerialNumberBuffer)) 4556 { 4557 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG); 4558 SerialNumberBuffer = NULL; 4559 } 4560 4561 if (SerialNumberBuffer && 4562 !USBH_CheckDeviceIDUnique(HubExtension, 4563 PortExtension->DeviceDescriptor.idVendor, 4564 PortExtension->DeviceDescriptor.idProduct, 4565 SerialNumberBuffer, 4566 PortExtension->SN_DescriptorLength)) 4567 { 4568 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG); 4569 SerialNumberBuffer = NULL; 4570 } 4571 } 4572 4573 InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, 4574 SerialNumberBuffer); 4575 } 4576 4577 Status = USBH_ProcessDeviceInformation(PortExtension); 4578 4579 USBH_PdoSetCapabilities(PortExtension); 4580 4581 if (NT_SUCCESS(Status)) 4582 { 4583 goto Exit; 4584 } 4585 4586 ErrorExit: 4587 4588 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_INIT_PORT_FAILED; 4589 4590 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle, 4591 NULL); 4592 4593 if (DeviceHandle) 4594 { 4595 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 4596 } 4597 4598 SerialNumberBuffer = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, 4599 NULL); 4600 4601 if (SerialNumberBuffer) 4602 { 4603 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG); 4604 } 4605 4606 Exit: 4607 4608 ASSERT(Port > 0); 4609 HubExtension->PortData[Port-1].DeviceObject = DeviceObject; 4610 return Status; 4611 } 4612 4613 NTSTATUS 4614 NTAPI 4615 USBH_ResetDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 4616 IN USHORT Port, 4617 IN BOOLEAN IsKeepDeviceData, 4618 IN BOOLEAN IsWait) 4619 { 4620 NTSTATUS Status; 4621 PUSBHUB_PORT_DATA PortData; 4622 PDEVICE_OBJECT PortDevice; 4623 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 4624 PVOID NewDeviceHandle; 4625 PVOID Handle; 4626 PVOID OldDeviceHandle; 4627 PUSB_DEVICE_HANDLE * DeviceHandle; 4628 USB_PORT_STATUS_AND_CHANGE PortStatus; 4629 4630 DPRINT("USBH_ResetDevice: HubExtension - %p, Port - %x, IsKeepDeviceData - %x, IsWait - %x\n", 4631 HubExtension, 4632 Port, 4633 IsKeepDeviceData, 4634 IsWait); 4635 4636 Status = USBH_SyncGetPortStatus(HubExtension, 4637 Port, 4638 &PortStatus, 4639 sizeof(USB_PORT_STATUS_AND_CHANGE)); 4640 4641 if (!NT_SUCCESS(Status) || 4642 !(PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus)) 4643 { 4644 return STATUS_UNSUCCESSFUL; 4645 } 4646 4647 InterlockedIncrement(&HubExtension->PendingRequestCount); 4648 4649 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 4650 Executive, 4651 KernelMode, 4652 FALSE, 4653 NULL); 4654 4655 ASSERT(Port > 0); 4656 PortData = &HubExtension->PortData[Port-1]; 4657 4658 PortDevice = PortData->DeviceObject; 4659 4660 if (!PortDevice) 4661 { 4662 Status = STATUS_INVALID_PARAMETER; 4663 4664 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 4665 LOW_REALTIME_PRIORITY, 4666 1, 4667 FALSE); 4668 4669 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 4670 { 4671 KeSetEvent(&HubExtension->PendingRequestEvent, 4672 EVENT_INCREMENT, 4673 FALSE); 4674 } 4675 4676 return Status; 4677 } 4678 4679 PortExtension = PortDevice->DeviceExtension; 4680 DeviceHandle = &PortExtension->DeviceHandle; 4681 4682 OldDeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle, 4683 NULL); 4684 4685 if (OldDeviceHandle) 4686 { 4687 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOVING_PORT_PDO)) 4688 { 4689 Status = USBD_RemoveDeviceEx(HubExtension, 4690 OldDeviceHandle, 4691 IsKeepDeviceData); 4692 4693 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REMOVING_PORT_PDO; 4694 } 4695 } 4696 else 4697 { 4698 OldDeviceHandle = NULL; 4699 } 4700 4701 if (!NT_SUCCESS(Status)) 4702 { 4703 goto ErrorExit; 4704 } 4705 4706 Status = USBH_SyncResetPort(HubExtension, Port); 4707 4708 if (!NT_SUCCESS(Status)) 4709 { 4710 goto ErrorExit; 4711 } 4712 4713 Status = USBH_SyncGetPortStatus(HubExtension, 4714 Port, 4715 &PortStatus, 4716 sizeof(USB_PORT_STATUS_AND_CHANGE)); 4717 4718 if (!NT_SUCCESS(Status)) 4719 { 4720 goto ErrorExit; 4721 } 4722 4723 Status = USBD_CreateDeviceEx(HubExtension, 4724 DeviceHandle, 4725 PortStatus.PortStatus, 4726 Port); 4727 4728 if (!NT_SUCCESS(Status)) 4729 { 4730 goto ErrorExit; 4731 } 4732 4733 Status = USBH_SyncResetPort(HubExtension, Port); 4734 4735 if (IsWait) 4736 { 4737 USBH_Wait(50); 4738 } 4739 4740 if (!NT_SUCCESS(Status)) 4741 { 4742 goto ErrorExit; 4743 } 4744 4745 Status = USBD_InitializeDeviceEx(HubExtension, 4746 *DeviceHandle, 4747 &PortExtension->DeviceDescriptor.bLength, 4748 sizeof(PortExtension->DeviceDescriptor), 4749 &PortExtension->ConfigDescriptor.bLength, 4750 sizeof(PortExtension->ConfigDescriptor)); 4751 4752 if (NT_SUCCESS(Status)) 4753 { 4754 if (IsKeepDeviceData) 4755 { 4756 Status = USBD_RestoreDeviceEx(HubExtension, 4757 OldDeviceHandle, 4758 *DeviceHandle); 4759 4760 if (!NT_SUCCESS(Status)) 4761 { 4762 Handle = InterlockedExchangePointer(DeviceHandle, NULL); 4763 4764 USBD_RemoveDeviceEx(HubExtension, Handle, 0); 4765 USBH_SyncDisablePort(HubExtension, Port); 4766 4767 Status = STATUS_NO_SUCH_DEVICE; 4768 } 4769 } 4770 else 4771 { 4772 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REMOVING_PORT_PDO; 4773 } 4774 4775 goto Exit; 4776 } 4777 4778 *DeviceHandle = NULL; 4779 4780 ErrorExit: 4781 4782 NewDeviceHandle = InterlockedExchangePointer(DeviceHandle, 4783 OldDeviceHandle); 4784 4785 if (NewDeviceHandle) 4786 { 4787 Status = USBD_RemoveDeviceEx(HubExtension, NewDeviceHandle, 0); 4788 } 4789 4790 Exit: 4791 4792 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 4793 LOW_REALTIME_PRIORITY, 4794 1, 4795 FALSE); 4796 4797 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 4798 { 4799 KeSetEvent(&HubExtension->PendingRequestEvent, 4800 EVENT_INCREMENT, 4801 FALSE); 4802 } 4803 4804 return Status; 4805 } 4806 4807 NTSTATUS 4808 NTAPI 4809 USBH_PdoDispatch(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 4810 IN PIRP Irp) 4811 { 4812 PIO_STACK_LOCATION IoStack; 4813 UCHAR MajorFunction; 4814 BOOLEAN ShouldCompleteIrp; 4815 ULONG ControlCode; 4816 NTSTATUS Status; 4817 4818 IoStack = IoGetCurrentIrpStackLocation(Irp); 4819 MajorFunction = IoStack->MajorFunction; 4820 4821 switch (MajorFunction) 4822 { 4823 case IRP_MJ_CREATE: 4824 case IRP_MJ_CLOSE: 4825 DPRINT("USBH_PdoDispatch: IRP_MJ_CREATE / IRP_MJ_CLOSE (%d)\n", 4826 MajorFunction); 4827 Status = STATUS_SUCCESS; 4828 USBH_CompleteIrp(Irp, Status); 4829 break; 4830 4831 case IRP_MJ_DEVICE_CONTROL: 4832 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode; 4833 DPRINT("USBH_PdoDispatch: IRP_MJ_DEVICE_CONTROL ControlCode - %x\n", 4834 ControlCode); 4835 4836 if (ControlCode == IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER) 4837 { 4838 Status = STATUS_NOT_SUPPORTED; 4839 USBH_CompleteIrp(Irp, Status); 4840 break; 4841 } 4842 4843 if (ControlCode == IOCTL_KS_PROPERTY) 4844 { 4845 DPRINT1("USBH_PdoDispatch: IOCTL_KS_PROPERTY FIXME\n"); 4846 DbgBreakPoint(); 4847 Status = STATUS_NOT_SUPPORTED; 4848 USBH_CompleteIrp(Irp, Status); 4849 break; 4850 } 4851 4852 Status = Irp->IoStatus.Status; 4853 USBH_CompleteIrp(Irp, Status); 4854 break; 4855 4856 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 4857 Status = USBH_PdoInternalControl(PortExtension, Irp); 4858 break; 4859 4860 case IRP_MJ_PNP: 4861 Status = USBH_PdoPnP(PortExtension, 4862 Irp, 4863 IoStack->MinorFunction, 4864 &ShouldCompleteIrp); 4865 4866 if (ShouldCompleteIrp) 4867 { 4868 USBH_CompleteIrp(Irp, Status); 4869 } 4870 4871 break; 4872 4873 case IRP_MJ_POWER: 4874 Status = USBH_PdoPower(PortExtension, Irp, IoStack->MinorFunction); 4875 break; 4876 4877 case IRP_MJ_SYSTEM_CONTROL: 4878 DPRINT1("USBH_PdoDispatch: USBH_SystemControl() UNIMPLEMENTED. FIXME\n"); 4879 //USBH_PortSystemControl(PortExtension, Irp); 4880 Status = Irp->IoStatus.Status; 4881 USBH_CompleteIrp(Irp, Status); 4882 break; 4883 4884 default: 4885 DPRINT("USBH_PdoDispatch: Unhandled MajorFunction - %d\n", MajorFunction); 4886 Status = Irp->IoStatus.Status; 4887 USBH_CompleteIrp(Irp, Status); 4888 break; 4889 } 4890 4891 return Status; 4892 } 4893 4894 NTSTATUS 4895 NTAPI 4896 USBH_FdoDispatch(IN PUSBHUB_FDO_EXTENSION HubExtension, 4897 IN PIRP Irp) 4898 { 4899 PIO_STACK_LOCATION IoStack; 4900 UCHAR MajorFunction; 4901 NTSTATUS Status; 4902 4903 IoStack = IoGetCurrentIrpStackLocation(Irp); 4904 4905 DPRINT("USBH_FdoDispatch: HubExtension - %p, Irp - %p, MajorFunction - %X\n", 4906 HubExtension, 4907 Irp, 4908 IoStack->MajorFunction); 4909 4910 MajorFunction = IoStack->MajorFunction; 4911 4912 switch (MajorFunction) 4913 { 4914 case IRP_MJ_CREATE: 4915 case IRP_MJ_CLOSE: 4916 Status = STATUS_SUCCESS; 4917 USBH_CompleteIrp(Irp, Status); 4918 break; 4919 4920 case IRP_MJ_DEVICE_CONTROL: 4921 Status = USBH_DeviceControl(HubExtension, Irp); 4922 break; 4923 4924 case IRP_MJ_PNP: 4925 Status = USBH_FdoPnP(HubExtension, Irp, IoStack->MinorFunction); 4926 break; 4927 4928 case IRP_MJ_POWER: 4929 Status = USBH_FdoPower(HubExtension, Irp, IoStack->MinorFunction); 4930 break; 4931 4932 case IRP_MJ_SYSTEM_CONTROL: 4933 DPRINT1("USBH_FdoDispatch: USBH_SystemControl() UNIMPLEMENTED. FIXME\n"); 4934 /* fall through */ 4935 4936 case IRP_MJ_INTERNAL_DEVICE_CONTROL: 4937 default: 4938 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 4939 break; 4940 } 4941 4942 return Status; 4943 } 4944 4945 NTSTATUS 4946 NTAPI 4947 USBH_AddDevice(IN PDRIVER_OBJECT DriverObject, 4948 IN PDEVICE_OBJECT LowerPDO) 4949 { 4950 PDEVICE_OBJECT DeviceObject; 4951 NTSTATUS Status; 4952 PUSBHUB_FDO_EXTENSION HubExtension; 4953 PDEVICE_OBJECT LowerDevice; 4954 4955 DPRINT("USBH_AddDevice: DriverObject - %p, LowerPDO - %p\n", 4956 DriverObject, 4957 LowerPDO); 4958 4959 DeviceObject = NULL; 4960 4961 Status = IoCreateDevice(DriverObject, 4962 sizeof(USBHUB_FDO_EXTENSION), 4963 NULL, 4964 0x8600, 4965 FILE_AUTOGENERATED_DEVICE_NAME, 4966 FALSE, 4967 &DeviceObject); 4968 4969 if (!NT_SUCCESS(Status)) 4970 { 4971 DPRINT1("USBH_AddDevice: IoCreateDevice() fail\n"); 4972 4973 if (DeviceObject) 4974 { 4975 IoDeleteDevice(DeviceObject); 4976 } 4977 4978 return Status; 4979 } 4980 4981 DPRINT("USBH_AddDevice: DeviceObject - %p\n", DeviceObject); 4982 4983 HubExtension = DeviceObject->DeviceExtension; 4984 RtlZeroMemory(HubExtension, sizeof(USBHUB_FDO_EXTENSION)); 4985 4986 HubExtension->Common.ExtensionType = USBH_EXTENSION_TYPE_HUB; 4987 4988 LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, LowerPDO); 4989 4990 if (!LowerDevice) 4991 { 4992 DPRINT1("USBH_AddDevice: IoAttachDeviceToDeviceStack() fail\n"); 4993 4994 if (DeviceObject) 4995 { 4996 IoDeleteDevice(DeviceObject); 4997 } 4998 4999 return STATUS_UNSUCCESSFUL; 5000 } 5001 5002 DPRINT("USBH_AddDevice: LowerDevice - %p\n", LowerDevice); 5003 5004 HubExtension->Common.SelfDevice = DeviceObject; 5005 5006 HubExtension->LowerPDO = LowerPDO; 5007 HubExtension->LowerDevice = LowerDevice; 5008 5009 KeInitializeSemaphore(&HubExtension->IdleSemaphore, 1, 1); 5010 5011 DeviceObject->Flags |= DO_POWER_PAGABLE; 5012 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 5013 5014 DPRINT("USBH_AddDevice: call IoWMIRegistrationControl() UNIMPLEMENTED. FIXME\n"); 5015 5016 return Status; 5017 } 5018 5019 VOID 5020 NTAPI 5021 USBH_DriverUnload(IN PDRIVER_OBJECT DriverObject) 5022 { 5023 DPRINT("USBH_DriverUnload: UNIMPLEMENTED\n"); 5024 5025 if (GenericUSBDeviceString) 5026 { 5027 ExFreePool(GenericUSBDeviceString); 5028 GenericUSBDeviceString = NULL; 5029 } 5030 } 5031 5032 NTSTATUS 5033 NTAPI 5034 USBH_HubDispatch(IN PDEVICE_OBJECT DeviceObject, 5035 IN PIRP Irp) 5036 { 5037 PCOMMON_DEVICE_EXTENSION DeviceExtension; 5038 ULONG ExtensionType; 5039 NTSTATUS Status; 5040 5041 5042 DeviceExtension = DeviceObject->DeviceExtension; 5043 ExtensionType = DeviceExtension->ExtensionType; 5044 5045 if (ExtensionType == USBH_EXTENSION_TYPE_HUB) 5046 { 5047 DPRINT("USBH_HubDispatch: DeviceObject - %p, Irp - %p\n", 5048 DeviceObject, 5049 Irp); 5050 5051 Status = USBH_FdoDispatch((PUSBHUB_FDO_EXTENSION)DeviceExtension, Irp); 5052 } 5053 else if (ExtensionType == USBH_EXTENSION_TYPE_PORT) 5054 { 5055 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 5056 UCHAR MajorFunction = IoStack->MajorFunction; 5057 BOOLEAN IsDprint = TRUE; 5058 5059 if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) 5060 { 5061 ULONG ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode; 5062 5063 if (ControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB) 5064 { 5065 IsDprint = FALSE; 5066 } 5067 } 5068 5069 if (IsDprint) 5070 { 5071 DPRINT("USBH_HubDispatch: DeviceObject - %p, Irp - %p\n", 5072 DeviceObject, 5073 Irp); 5074 } 5075 5076 Status = USBH_PdoDispatch((PUSBHUB_PORT_PDO_EXTENSION)DeviceExtension, Irp); 5077 } 5078 else 5079 { 5080 DPRINT1("USBH_HubDispatch: Unknown ExtensionType - %x\n", ExtensionType); 5081 DbgBreakPoint(); 5082 Status = STATUS_ASSERTION_FAILURE; 5083 } 5084 5085 return Status; 5086 } 5087 5088 NTSTATUS 5089 NTAPI 5090 USBH_RegQueryGenericUSBDeviceString(PVOID USBDeviceString) 5091 { 5092 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 5093 5094 DPRINT("USBH_RegQueryGenericUSBDeviceString ... \n"); 5095 5096 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 5097 5098 QueryTable[0].QueryRoutine = USBH_GetConfigValue; 5099 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; 5100 QueryTable[0].Name = L"GenericUSBDeviceString"; 5101 QueryTable[0].EntryContext = USBDeviceString; 5102 QueryTable[0].DefaultType = REG_NONE; 5103 QueryTable[0].DefaultData = 0; 5104 QueryTable[0].DefaultLength = 0; 5105 5106 return RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, 5107 L"usbflags", 5108 QueryTable, 5109 NULL, 5110 NULL); 5111 } 5112 5113 NTSTATUS 5114 NTAPI 5115 DriverEntry(IN PDRIVER_OBJECT DriverObject, 5116 IN PUNICODE_STRING RegistryPath) 5117 { 5118 DPRINT("USBHUB: DriverEntry - %wZ\n", RegistryPath); 5119 5120 DriverObject->DriverExtension->AddDevice = USBH_AddDevice; 5121 DriverObject->DriverUnload = USBH_DriverUnload; 5122 5123 DriverObject->MajorFunction[IRP_MJ_CREATE] = USBH_HubDispatch; 5124 DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBH_HubDispatch; 5125 5126 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBH_HubDispatch; 5127 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBH_HubDispatch; 5128 5129 DriverObject->MajorFunction[IRP_MJ_PNP] = USBH_HubDispatch; 5130 DriverObject->MajorFunction[IRP_MJ_POWER] = USBH_HubDispatch; 5131 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBH_HubDispatch; 5132 5133 USBH_RegQueryGenericUSBDeviceString(&GenericUSBDeviceString); 5134 5135 return STATUS_SUCCESS; 5136 } 5137 5138