1 /* 2 * PROJECT: ReactOS USB Hub Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBHub plug and play 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_PNP 14 #define NDEBUG_USBHUB_ENUM 15 #include "dbg_uhub.h" 16 17 NTSTATUS 18 NTAPI 19 USBH_IrpCompletion(IN PDEVICE_OBJECT DeviceObject, 20 IN PIRP Irp, 21 IN PVOID Context) 22 { 23 PRKEVENT Event; 24 25 DPRINT("USBH_IrpCompletion: Irp - %p\n", Irp); 26 27 Event = Context; 28 KeSetEvent(Event, EVENT_INCREMENT, FALSE); 29 return STATUS_MORE_PROCESSING_REQUIRED; 30 } 31 32 NTSTATUS 33 NTAPI 34 USBH_HubPnPIrpComplete(IN PDEVICE_OBJECT DeviceObject, 35 IN PIRP Irp, 36 IN PVOID Context) 37 { 38 PUSBHUB_FDO_EXTENSION HubExtension; 39 40 DPRINT("USBH_HubPnPIrpComplete: Irp - %p\n", Irp); 41 42 HubExtension = Context; 43 44 if (!NT_SUCCESS(Irp->IoStatus.Status)) 45 { 46 DPRINT1("USBH_HubPnPIrpComplete: Irp failed - %lX\n", Irp->IoStatus.Status); 47 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 48 } 49 50 Irp->IoStatus.Status = STATUS_MORE_PROCESSING_REQUIRED; 51 52 KeSetEvent(&HubExtension->LowerDeviceEvent, EVENT_INCREMENT, FALSE); 53 54 return STATUS_MORE_PROCESSING_REQUIRED; 55 } 56 57 NTSTATUS 58 NTAPI 59 USBH_QueryCapsComplete(IN PDEVICE_OBJECT DeviceObject, 60 IN PIRP Irp, 61 IN PVOID Context) 62 { 63 PIO_STACK_LOCATION IoStack; 64 PDEVICE_CAPABILITIES Capabilities; 65 66 DPRINT("USBH_QueryCapsComplete: ... \n"); 67 68 ASSERT(NT_SUCCESS(Irp->IoStatus.Status)); 69 70 if (Irp->PendingReturned) 71 { 72 IoMarkIrpPending(Irp); 73 } 74 75 IoStack= IoGetCurrentIrpStackLocation(Irp); 76 Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 77 78 Capabilities->SurpriseRemovalOK = 1; 79 80 return STATUS_CONTINUE_COMPLETION; 81 } 82 83 NTSTATUS 84 NTAPI 85 USBHUB_GetBusInterface(IN PDEVICE_OBJECT DeviceObject, 86 OUT PUSB_BUS_INTERFACE_HUB_V5 BusInterface) 87 { 88 PIRP Irp; 89 NTSTATUS Status; 90 PIO_STACK_LOCATION IoStack; 91 KEVENT Event; 92 93 DPRINT("USBHUB_GetBusInterface: ... \n"); 94 95 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 96 97 if (!Irp) 98 { 99 DPRINT1("USBHUB_GetBusInterface: IoAllocateIrp() failed\n"); 100 return STATUS_INSUFFICIENT_RESOURCES; 101 } 102 103 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 104 105 KeInitializeEvent(&Event, NotificationEvent, FALSE); 106 107 IoSetCompletionRoutine(Irp, 108 USBH_IrpCompletion, 109 &Event, 110 TRUE, 111 TRUE, 112 TRUE); 113 114 IoStack = IoGetNextIrpStackLocation(Irp); 115 116 IoStack->MajorFunction = IRP_MJ_PNP; 117 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE; 118 119 IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_HUB_GUID; 120 IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_HUB_V5); 121 IoStack->Parameters.QueryInterface.Version = USB_BUSIF_HUB_VERSION_5; 122 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface; 123 IoStack->Parameters.QueryInterface.InterfaceSpecificData = DeviceObject; 124 125 Status = IoCallDriver(DeviceObject, Irp); 126 127 if (Status == STATUS_PENDING) 128 { 129 KeWaitForSingleObject(&Event, 130 Suspended, 131 KernelMode, 132 FALSE, 133 NULL); 134 135 Status = Irp->IoStatus.Status; 136 } 137 138 IoFreeIrp(Irp); 139 140 return Status; 141 } 142 143 NTSTATUS 144 NTAPI 145 USBHUB_GetBusInterfaceUSBDI(IN PDEVICE_OBJECT DeviceObject, 146 OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterfaceUSBDI) 147 { 148 PIRP Irp; 149 NTSTATUS Status; 150 PIO_STACK_LOCATION IoStack; 151 KEVENT Event; 152 153 DPRINT("USBHUB_GetBusInterfaceUSBDI: ... \n"); 154 155 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 156 157 if (!Irp) 158 { 159 DPRINT1("USBHUB_GetBusInterfaceUSBDI: IoAllocateIrp() failed\n"); 160 return STATUS_INSUFFICIENT_RESOURCES; 161 } 162 163 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 164 165 KeInitializeEvent(&Event, NotificationEvent, FALSE); 166 167 IoSetCompletionRoutine(Irp, 168 USBH_IrpCompletion, 169 &Event, 170 TRUE, 171 TRUE, 172 TRUE); 173 174 IoStack = IoGetNextIrpStackLocation(Irp); 175 176 IoStack->MajorFunction = IRP_MJ_PNP; 177 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE; 178 179 IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_USBDI_GUID; 180 IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V2); 181 IoStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_2; 182 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterfaceUSBDI; 183 IoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL; 184 185 Status = IoCallDriver(DeviceObject, Irp); 186 187 if (Status == STATUS_PENDING) 188 { 189 KeWaitForSingleObject(&Event, 190 Suspended, 191 KernelMode, 192 FALSE, 193 NULL); 194 195 Status = Irp->IoStatus.Status; 196 } 197 198 IoFreeIrp(Irp); 199 200 return Status; 201 } 202 203 VOID 204 NTAPI 205 USBH_QueryCapabilities(IN PDEVICE_OBJECT DeviceObject, 206 IN PDEVICE_CAPABILITIES DeviceCapabilities) 207 { 208 PIRP Irp; 209 PIO_STACK_LOCATION IoStack; 210 KEVENT Event; 211 212 DPRINT("USBH_QueryCapabilities: ... \n"); 213 214 RtlZeroMemory(DeviceCapabilities, sizeof(DEVICE_CAPABILITIES)); 215 216 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 217 218 if (!Irp) 219 { 220 DPRINT1("USBH_QueryCapabilities: IoAllocateIrp() failed\n"); 221 return; 222 } 223 224 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 225 226 KeInitializeEvent(&Event, NotificationEvent, FALSE); 227 228 IoSetCompletionRoutine(Irp, 229 USBH_IrpCompletion, 230 &Event, 231 TRUE, 232 TRUE, 233 TRUE); 234 235 IoStack = IoGetNextIrpStackLocation(Irp); 236 237 IoStack->MajorFunction = IRP_MJ_PNP; 238 IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES; 239 240 IoStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities; 241 IoStack->Parameters.DeviceCapabilities.Capabilities->Size = sizeof(DEVICE_CAPABILITIES); 242 IoStack->Parameters.DeviceCapabilities.Capabilities->Version = 1; 243 IoStack->Parameters.DeviceCapabilities.Capabilities->Address = MAXULONG; 244 IoStack->Parameters.DeviceCapabilities.Capabilities->UINumber = MAXULONG; 245 246 if (IoCallDriver(DeviceObject, Irp) == STATUS_PENDING) 247 { 248 KeWaitForSingleObject(&Event, 249 Suspended, 250 KernelMode, 251 FALSE, 252 NULL); 253 } 254 255 IoFreeIrp(Irp); 256 } 257 258 NTSTATUS 259 NTAPI 260 USBH_OpenConfiguration(IN PUSBHUB_FDO_EXTENSION HubExtension) 261 { 262 PUSB_INTERFACE_DESCRIPTOR Pid; 263 PURB Urb; 264 NTSTATUS Status; 265 USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; 266 267 DPRINT("USBH_OpenConfiguration ... \n"); 268 269 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB && 270 HubExtension->LowerPDO != HubExtension->RootHubPdo) 271 { 272 Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor, 273 HubExtension->HubConfigDescriptor, 274 -1, 275 -1, 276 USB_DEVICE_CLASS_HUB, 277 -1, 278 2); 279 280 if (Pid) 281 { 282 HubExtension->HubFlags |= USBHUB_FDO_FLAG_MULTIPLE_TTS; 283 } 284 else 285 { 286 Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor, 287 HubExtension->HubConfigDescriptor, 288 -1, 289 -1, 290 USB_DEVICE_CLASS_HUB, 291 -1, 292 1); 293 294 if (Pid) 295 { 296 goto Next; 297 } 298 299 Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor, 300 HubExtension->HubConfigDescriptor, 301 -1, 302 -1, 303 USB_DEVICE_CLASS_HUB, 304 -1, 305 0); 306 } 307 } 308 else 309 { 310 Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor, 311 HubExtension->HubConfigDescriptor, 312 -1, 313 -1, 314 USB_DEVICE_CLASS_HUB, 315 -1, 316 -1); 317 } 318 319 if (!Pid) 320 { 321 return STATUS_UNSUCCESSFUL; 322 } 323 324 Next: 325 326 if (Pid->bInterfaceClass != USB_DEVICE_CLASS_HUB) 327 { 328 return STATUS_UNSUCCESSFUL; 329 } 330 331 InterfaceList[0].InterfaceDescriptor = Pid; 332 333 Urb = USBD_CreateConfigurationRequestEx(HubExtension->HubConfigDescriptor, 334 InterfaceList); 335 336 if (!Urb) 337 { 338 return STATUS_INSUFFICIENT_RESOURCES; 339 } 340 341 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, Urb); 342 343 if (NT_SUCCESS(Status)) 344 { 345 RtlCopyMemory(&HubExtension->PipeInfo, 346 InterfaceList[0].Interface->Pipes, 347 sizeof(USBD_PIPE_INFORMATION)); 348 349 HubExtension->ConfigHandle = Urb->UrbSelectConfiguration.ConfigurationHandle; 350 } 351 352 ExFreePool(Urb); 353 354 return Status; 355 } 356 357 NTSTATUS 358 NTAPI 359 USBD_Initialize20Hub(IN PUSBHUB_FDO_EXTENSION HubExtension) 360 { 361 PUSB_BUSIFFN_INITIALIZE_20HUB Initialize20Hub; 362 ULONG TtCount; 363 PUSB_DEVICE_HANDLE DeviceHandle; 364 365 DPRINT("USBD_InitUsb2Hub ... \n"); 366 367 Initialize20Hub = HubExtension->BusInterface.Initialize20Hub; 368 369 if (!Initialize20Hub) 370 { 371 return STATUS_NOT_IMPLEMENTED; 372 } 373 374 TtCount = 1; 375 376 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_MULTIPLE_TTS) 377 { 378 TtCount = HubExtension->HubDescriptor->bNumberOfPorts; 379 } 380 381 DeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice); 382 383 return Initialize20Hub(HubExtension->BusInterface.BusContext, 384 DeviceHandle, 385 TtCount); 386 } 387 388 NTSTATUS 389 NTAPI 390 USBH_AbortInterruptPipe(IN PUSBHUB_FDO_EXTENSION HubExtension) 391 { 392 struct _URB_PIPE_REQUEST * Urb; 393 NTSTATUS Status; 394 395 DPRINT("USBH_AbortInterruptPipe: HubExtension - %p\n", HubExtension); 396 397 Urb = ExAllocatePoolWithTag(NonPagedPool, 398 sizeof(struct _URB_PIPE_REQUEST), 399 USB_HUB_TAG); 400 401 if (!Urb) 402 { 403 return STATUS_INSUFFICIENT_RESOURCES; 404 } 405 406 RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST)); 407 408 Urb->Hdr.Length = sizeof(struct _URB_PIPE_REQUEST); 409 Urb->Hdr.Function = URB_FUNCTION_ABORT_PIPE; 410 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle; 411 412 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, 413 (PURB)Urb); 414 415 if (NT_SUCCESS(Status)) 416 { 417 KeWaitForSingleObject(&HubExtension->StatusChangeEvent, 418 Suspended, 419 KernelMode, 420 FALSE, 421 NULL); 422 } 423 424 ExFreePoolWithTag(Urb, USB_HUB_TAG); 425 426 return Status; 427 } 428 429 VOID 430 NTAPI 431 USBH_FdoCleanup(IN PUSBHUB_FDO_EXTENSION HubExtension) 432 { 433 PIRP IdleIrp = NULL; 434 PIRP WakeIrp = NULL; 435 PUSBHUB_PORT_DATA PortData; 436 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 437 PIRP PortIdleIrp = NULL; 438 PIRP PortWakeIrp = NULL; 439 PVOID DeviceHandle; 440 NTSTATUS Status; 441 USHORT Port; 442 UCHAR NumberPorts; 443 KIRQL Irql; 444 445 DPRINT("USBH_FdoCleanup: HubExtension - %p\n", HubExtension); 446 447 USBD_UnRegisterRootHubCallBack(HubExtension); 448 449 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_STOPPING; 450 451 if (HubExtension->ResetRequestCount) 452 { 453 IoCancelIrp(HubExtension->ResetPortIrp); 454 455 KeWaitForSingleObject(&HubExtension->IdleEvent, 456 Suspended, 457 KernelMode, 458 FALSE, 459 NULL); 460 } 461 462 IoFreeIrp(HubExtension->ResetPortIrp); 463 464 HubExtension->ResetPortIrp = NULL; 465 466 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST) 467 { 468 KeWaitForSingleObject(&HubExtension->IdleEvent, 469 Suspended, 470 KernelMode, 471 FALSE, 472 NULL); 473 } 474 475 IoAcquireCancelSpinLock(&Irql); 476 477 if (HubExtension->PendingWakeIrp) 478 { 479 WakeIrp = HubExtension->PendingWakeIrp; 480 HubExtension->PendingWakeIrp = NULL; 481 } 482 483 if (HubExtension->PendingIdleIrp) 484 { 485 IdleIrp = HubExtension->PendingIdleIrp; 486 HubExtension->PendingIdleIrp = NULL; 487 } 488 489 IoReleaseCancelSpinLock(Irql); 490 491 if (WakeIrp) 492 { 493 USBH_HubCancelWakeIrp(HubExtension, WakeIrp); 494 } 495 496 USBH_HubCompletePortWakeIrps(HubExtension, STATUS_DELETE_PENDING); 497 498 if (IdleIrp) 499 { 500 USBH_HubCancelIdleIrp(HubExtension, IdleIrp); 501 } 502 503 if (InterlockedDecrement(&HubExtension->PendingRequestCount) > 0) 504 { 505 KeWaitForSingleObject(&HubExtension->PendingRequestEvent, 506 Suspended, 507 KernelMode, 508 FALSE, 509 NULL); 510 } 511 512 if (HubExtension->SCEIrp) 513 { 514 Status = USBH_AbortInterruptPipe(HubExtension); 515 516 if (!NT_SUCCESS(Status) && IoCancelIrp(HubExtension->SCEIrp)) 517 { 518 KeWaitForSingleObject(&HubExtension->StatusChangeEvent, 519 Suspended, 520 KernelMode, 521 FALSE, 522 NULL); 523 } 524 525 IoFreeIrp(HubExtension->SCEIrp); 526 527 HubExtension->SCEIrp = NULL; 528 } 529 530 if (!HubExtension->PortData || 531 !HubExtension->HubDescriptor) 532 { 533 goto Exit; 534 } 535 536 PortData = HubExtension->PortData; 537 NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts; 538 539 for (Port = 0; Port < NumberPorts; Port++) 540 { 541 if (PortData[Port].DeviceObject) 542 { 543 PortExtension = PortData[Port].DeviceObject->DeviceExtension; 544 545 IoAcquireCancelSpinLock(&Irql); 546 547 PortIdleIrp = PortExtension->IdleNotificationIrp; 548 549 if (PortIdleIrp) 550 { 551 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION; 552 PortExtension->IdleNotificationIrp = NULL; 553 554 if (PortIdleIrp->Cancel) 555 { 556 PortIdleIrp = NULL; 557 } 558 559 if (PortIdleIrp) 560 { 561 IoSetCancelRoutine(PortIdleIrp, NULL); 562 } 563 } 564 565 PortWakeIrp = PortExtension->PdoWaitWakeIrp; 566 567 if (PortWakeIrp) 568 { 569 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_WAIT_WAKE; 570 PortExtension->PdoWaitWakeIrp = NULL; 571 572 if (PortWakeIrp->Cancel || !IoSetCancelRoutine(PortWakeIrp, NULL)) 573 { 574 PortWakeIrp = NULL; 575 576 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 577 { 578 KeSetEvent(&HubExtension->PendingRequestEvent, 579 EVENT_INCREMENT, 580 FALSE); 581 } 582 } 583 } 584 585 IoReleaseCancelSpinLock(Irql); 586 587 if (PortIdleIrp) 588 { 589 PortIdleIrp->IoStatus.Status = STATUS_CANCELLED; 590 IoCompleteRequest(PortIdleIrp, IO_NO_INCREMENT); 591 } 592 593 if (PortWakeIrp) 594 { 595 USBH_CompletePowerIrp(HubExtension, 596 PortWakeIrp, 597 STATUS_CANCELLED); 598 } 599 600 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3)) 601 { 602 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle, 603 NULL); 604 605 if (DeviceHandle) 606 { 607 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 608 } 609 610 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_POWER_D3; 611 } 612 } 613 614 USBH_SyncDisablePort(HubExtension, Port + 1); 615 } 616 617 Exit: 618 619 if (HubExtension->SCEBitmap) 620 { 621 ExFreePoolWithTag(HubExtension->SCEBitmap, USB_HUB_TAG); 622 } 623 624 if (HubExtension->HubDescriptor) 625 { 626 ExFreePoolWithTag(HubExtension->HubDescriptor, USB_HUB_TAG); 627 } 628 629 if (HubExtension->HubConfigDescriptor) 630 { 631 ExFreePoolWithTag(HubExtension->HubConfigDescriptor, USB_HUB_TAG); 632 } 633 634 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DEVICE_STARTED; 635 636 HubExtension->HubDescriptor = NULL; 637 HubExtension->HubConfigDescriptor = NULL; 638 639 HubExtension->SCEIrp = NULL; 640 HubExtension->SCEBitmap = NULL; 641 } 642 643 NTSTATUS 644 NTAPI 645 USBH_StartHubFdoDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 646 IN PIRP Irp) 647 { 648 NTSTATUS Status; 649 ULONG DisableRemoteWakeup = 0; 650 ULONG HubCount = 0; 651 PUSB_DEVICE_HANDLE DeviceHandle; 652 USB_DEVICE_TYPE DeviceType; 653 DEVICE_CAPABILITIES DeviceCapabilities; 654 BOOLEAN IsBusPowered; 655 static WCHAR DisableWakeValueName[] = L"DisableRemoteWakeup"; 656 657 DPRINT("USBH_StartHubFdoDevice: ... \n"); 658 659 KeInitializeEvent(&HubExtension->IdleEvent, NotificationEvent, FALSE); 660 KeInitializeEvent(&HubExtension->ResetEvent, NotificationEvent, TRUE); 661 KeInitializeEvent(&HubExtension->PendingRequestEvent, NotificationEvent, FALSE); 662 KeInitializeEvent(&HubExtension->LowerDeviceEvent, NotificationEvent, FALSE); 663 KeInitializeEvent(&HubExtension->StatusChangeEvent, NotificationEvent, TRUE); 664 KeInitializeEvent(&HubExtension->RootHubNotificationEvent, 665 NotificationEvent, 666 TRUE); 667 668 KeInitializeSpinLock(&HubExtension->RelationsWorkerSpinLock); 669 KeInitializeSpinLock(&HubExtension->CheckIdleSpinLock); 670 671 KeInitializeSemaphore(&HubExtension->ResetDeviceSemaphore, 1, 1); 672 KeInitializeSemaphore(&HubExtension->HubPortSemaphore, 1, 1); 673 KeInitializeSemaphore(&HubExtension->HubSemaphore, 1, 1); 674 675 HubExtension->HubFlags = 0; 676 HubExtension->HubConfigDescriptor = NULL; 677 HubExtension->HubDescriptor = NULL; 678 HubExtension->SCEIrp = NULL; 679 HubExtension->SCEBitmap = NULL; 680 HubExtension->SystemPowerState.SystemState = PowerSystemWorking; 681 HubExtension->PendingRequestCount = 1; 682 HubExtension->ResetRequestCount = 0; 683 HubExtension->PendingIdleIrp = NULL; 684 HubExtension->PendingWakeIrp = NULL; 685 686 InitializeListHead(&HubExtension->PdoList); 687 688 HubExtension->HubFlags |= USBHUB_FDO_FLAG_WITEM_INIT; 689 InitializeListHead(&HubExtension->WorkItemList); 690 KeInitializeSpinLock(&HubExtension->WorkItemSpinLock); 691 692 IoCopyCurrentIrpStackLocationToNext(Irp); 693 694 IoSetCompletionRoutine(Irp, 695 USBH_HubPnPIrpComplete, 696 HubExtension, 697 TRUE, 698 TRUE, 699 TRUE); 700 701 if (IoCallDriver(HubExtension->LowerDevice, Irp) == STATUS_PENDING) 702 { 703 KeWaitForSingleObject(&HubExtension->LowerDeviceEvent, 704 Suspended, 705 KernelMode, 706 FALSE, 707 NULL); 708 } 709 710 HubExtension->RootHubPdo = NULL; 711 712 Status = USBH_SyncGetRootHubPdo(HubExtension->LowerDevice, 713 &HubExtension->RootHubPdo, 714 &HubExtension->RootHubPdo2); 715 716 if (!NT_SUCCESS(Status)) 717 { 718 DPRINT1("USBH_SyncGetRootHubPdo() failed - %lX\n", Status); 719 goto ErrorExit; 720 } 721 722 USBH_WriteFailReasonID(HubExtension->LowerPDO, USBHUB_FAIL_NO_FAIL); 723 724 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 725 { 726 DPRINT1("USBH_StartHubFdoDevice: USBHUB_FDO_FLAG_DEVICE_FAILED - TRUE\n"); 727 Status = STATUS_UNSUCCESSFUL; 728 goto ErrorExit; 729 } 730 731 HubExtension->HubFlags |= USBHUB_FDO_FLAG_REMOTE_WAKEUP; 732 733 Status = USBD_GetPdoRegistryParameter(HubExtension->LowerPDO, 734 &DisableRemoteWakeup, 735 sizeof(DisableRemoteWakeup), 736 DisableWakeValueName, 737 sizeof(DisableWakeValueName)); 738 739 if (NT_SUCCESS(Status) && DisableRemoteWakeup) 740 { 741 DPRINT("USBH_StartHubFdoDevice: DisableRemoteWakeup - TRUE\n"); 742 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_REMOTE_WAKEUP; 743 } 744 745 HubExtension->CurrentPowerState.DeviceState = PowerDeviceD0; 746 747 USBH_SyncGetHubCount(HubExtension->LowerDevice, 748 &HubCount); 749 750 Status = USBHUB_GetBusInterface(HubExtension->RootHubPdo, 751 &HubExtension->BusInterface); 752 753 if (!NT_SUCCESS(Status)) 754 { 755 DPRINT1("USBH_StartHubFdoDevice: USBHUB_GetBusInterface() failed - %lX\n", 756 Status); 757 goto ErrorExit; 758 } 759 760 Status = USBHUB_GetBusInterfaceUSBDI(HubExtension->LowerDevice, 761 &HubExtension->BusInterfaceUSBDI); 762 763 if (!NT_SUCCESS(Status)) 764 { 765 DPRINT1("USBH_StartHubFdoDevice: USBHUB_GetBusInterfaceUSBDI() failed - %lX\n", 766 Status); 767 goto ErrorExit; 768 } 769 770 DeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice); 771 772 if (DeviceHandle) 773 { 774 Status = USBH_GetDeviceType(HubExtension, DeviceHandle, &DeviceType); 775 776 if (!NT_SUCCESS(Status)) 777 { 778 DPRINT1("USBH_StartHubFdoDevice: USBH_GetDeviceType() failed - %lX\n", 779 Status); 780 781 goto ErrorExit; 782 } 783 784 if (DeviceType == Usb20Device) 785 { 786 HubExtension->HubFlags |= USBHUB_FDO_FLAG_USB20_HUB; 787 } 788 } 789 790 if (HubCount > USBHUB_MAX_CASCADE_LEVELS) 791 { 792 PUSBHUB_PORT_PDO_EXTENSION ParentPdoExtension; 793 PUSBHUB_FDO_EXTENSION ParentHubExtension; 794 USHORT ParentPort; 795 PUSBHUB_PORT_DATA PortData; 796 797 DPRINT1("USBH_StartHubFdoDevice: HubCount > 6 - %x\n", HubCount); 798 799 USBH_WriteFailReasonID(HubExtension->LowerPDO, 800 USBHUB_FAIL_NESTED_TOO_DEEPLY); 801 802 ParentPdoExtension = HubExtension->LowerPDO->DeviceExtension; 803 ParentHubExtension = ParentPdoExtension->HubExtension; 804 805 ParentPort = ParentPdoExtension->PortNumber - 1; 806 PortData = &ParentHubExtension->PortData[ParentPort]; 807 PortData->ConnectionStatus = DeviceHubNestedTooDeeply; 808 809 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 810 } 811 812 USBH_QueryCapabilities(HubExtension->LowerDevice, &DeviceCapabilities); 813 814 HubExtension->SystemWake = DeviceCapabilities.SystemWake; 815 HubExtension->DeviceWake = DeviceCapabilities.DeviceWake; 816 817 RtlCopyMemory(HubExtension->DeviceState, 818 &DeviceCapabilities.DeviceState, 819 POWER_SYSTEM_MAXIMUM * sizeof(DEVICE_POWER_STATE)); 820 821 Status = USBH_GetDeviceDescriptor(HubExtension->Common.SelfDevice, 822 &HubExtension->HubDeviceDescriptor); 823 824 if (!NT_SUCCESS(Status)) 825 { 826 DPRINT1("USBH_StartHubFdoDevice: USBH_GetDeviceDescriptor() failed - %lX\n", 827 Status); 828 goto ErrorExit; 829 } 830 831 Status = USBH_GetConfigurationDescriptor(HubExtension->Common.SelfDevice, 832 &HubExtension->HubConfigDescriptor); 833 834 if (!NT_SUCCESS(Status)) 835 { 836 DPRINT1("USBH_StartHubFdoDevice: USBH_GetConfigurationDescriptor() failed - %lX\n", 837 Status); 838 goto ErrorExit; 839 } 840 841 Status = USBH_SyncGetHubDescriptor(HubExtension); 842 843 if (!NT_SUCCESS(Status)) 844 { 845 DPRINT1("USBH_StartHubFdoDevice: USBH_SyncGetHubDescriptor() failed - %lX\n", 846 Status); 847 goto ErrorExit; 848 } 849 850 IsBusPowered = USBH_HubIsBusPowered(HubExtension->Common.SelfDevice, 851 HubExtension->HubConfigDescriptor); 852 853 if (IsBusPowered) 854 { 855 /* bus-powered hub is allowed a maximum of 100 mA only for each port */ 856 HubExtension->MaxPowerPerPort = 100; 857 858 /* can have 4 ports (4 * 100 mA) and 100 mA remains for itself; 859 expressed in 2 mA units (i.e., 250 = 500 mA). */ 860 HubExtension->HubConfigDescriptor->MaxPower = 250; 861 } 862 else 863 { 864 /* self-powered hub is allowed a maximum of 500 mA for each port */ 865 HubExtension->MaxPowerPerPort = 500; 866 } 867 868 Status = USBH_OpenConfiguration(HubExtension); 869 870 if (!NT_SUCCESS(Status)) 871 { 872 DPRINT1("USBH_StartHubFdoDevice: USBH_OpenConfiguration() failed - %lX\n", 873 Status); 874 goto ErrorExit; 875 } 876 877 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB) 878 { 879 Status = USBD_Initialize20Hub(HubExtension); 880 } 881 882 if (!NT_SUCCESS(Status)) 883 { 884 goto ErrorExit; 885 } 886 887 HubExtension->SCEIrp = IoAllocateIrp(HubExtension->Common.SelfDevice->StackSize, 888 FALSE); 889 890 HubExtension->ResetPortIrp = IoAllocateIrp(HubExtension->Common.SelfDevice->StackSize, 891 FALSE); 892 893 if (!HubExtension->SCEIrp || !HubExtension->ResetPortIrp) 894 { 895 Status = STATUS_INSUFFICIENT_RESOURCES; 896 goto ErrorExit; 897 } 898 899 HubExtension->SCEBitmapLength = HubExtension->PipeInfo.MaximumPacketSize; 900 901 HubExtension->SCEBitmap = ExAllocatePoolWithTag(NonPagedPool, 902 HubExtension->SCEBitmapLength, 903 USB_HUB_TAG); 904 905 if (!HubExtension->SCEBitmap) 906 { 907 Status = STATUS_INSUFFICIENT_RESOURCES; 908 goto ErrorExit; 909 } 910 911 RtlZeroMemory(HubExtension->SCEBitmap, HubExtension->SCEBitmapLength); 912 913 Status = USBH_SyncPowerOnPorts(HubExtension); 914 915 if (!NT_SUCCESS(Status)) 916 { 917 goto ErrorExit; 918 } 919 else 920 { 921 USHORT Port; 922 923 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_STARTED; 924 925 for (Port = 1; 926 Port <= HubExtension->HubDescriptor->bNumberOfPorts; 927 Port++) 928 { 929 USBH_SyncClearPortStatus(HubExtension, 930 Port, 931 USBHUB_FEATURE_C_PORT_CONNECTION); 932 } 933 } 934 935 if (HubExtension->LowerPDO == HubExtension->RootHubPdo) 936 { 937 USBD_RegisterRootHubCallBack(HubExtension); 938 } 939 else 940 { 941 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_ENUMERATION; 942 USBH_SubmitStatusChangeTransfer(HubExtension); 943 } 944 945 goto Exit; 946 947 ErrorExit: 948 949 if (HubExtension->HubDescriptor) 950 { 951 ExFreePoolWithTag(HubExtension->HubDescriptor, USB_HUB_TAG); 952 HubExtension->HubDescriptor = NULL; 953 } 954 955 if (HubExtension->SCEIrp) 956 { 957 IoFreeIrp(HubExtension->SCEIrp); 958 HubExtension->SCEIrp = NULL; 959 } 960 961 if (HubExtension->ResetPortIrp) 962 { 963 IoFreeIrp(HubExtension->ResetPortIrp); 964 HubExtension->ResetPortIrp = NULL; 965 } 966 967 if (HubExtension->SCEBitmap) 968 { 969 ExFreePoolWithTag(HubExtension->SCEBitmap, USB_HUB_TAG); 970 HubExtension->SCEBitmap = NULL; 971 } 972 973 if (HubExtension->HubConfigDescriptor) 974 { 975 ExFreePoolWithTag(HubExtension->HubConfigDescriptor, USB_HUB_TAG); 976 HubExtension->HubConfigDescriptor = NULL; 977 } 978 979 Exit: 980 981 USBH_CompleteIrp(Irp, Status); 982 983 return Status; 984 } 985 986 NTSTATUS 987 NTAPI 988 USBH_FdoStartDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 989 IN PIRP Irp) 990 { 991 NTSTATUS Status; 992 993 DPRINT("USBH_FdoStartDevice: HubExtension - %p\n", HubExtension); 994 995 HubExtension->RootHubPdo = NULL; 996 997 Status = USBH_SyncGetRootHubPdo(HubExtension->LowerDevice, 998 &HubExtension->RootHubPdo, 999 &HubExtension->RootHubPdo2); 1000 1001 if (NT_SUCCESS(Status)) 1002 { 1003 if (HubExtension->RootHubPdo) 1004 { 1005 Status = USBH_StartHubFdoDevice(HubExtension, Irp); 1006 } 1007 else 1008 { 1009 DPRINT1("USBH_FdoStartDevice: FIXME. start ParentDevice\n"); 1010 DbgBreakPoint(); 1011 } 1012 } 1013 else 1014 { 1015 DPRINT1("USBH_FdoStartDevice: FIXME. USBH_SyncGetRootHubPdo return - %lX\n", 1016 Status); 1017 1018 DbgBreakPoint(); 1019 USBH_CompleteIrp(Irp, Status); 1020 } 1021 1022 return Status; 1023 } 1024 1025 NTSTATUS 1026 NTAPI 1027 USBH_FdoQueryBusRelations(IN PUSBHUB_FDO_EXTENSION HubExtension, 1028 IN PIRP Irp) 1029 { 1030 PDEVICE_RELATIONS DeviceRelations = NULL; 1031 NTSTATUS Status = STATUS_SUCCESS; 1032 LIST_ENTRY GhostPdoList; 1033 KIRQL OldIrql; 1034 PLIST_ENTRY PdoList; 1035 UCHAR NumberPorts; 1036 USHORT Port; 1037 USHORT GhostPort; 1038 PUSBHUB_PORT_DATA PortData; 1039 PDEVICE_OBJECT PdoDevice; 1040 PUSBHUB_PORT_PDO_EXTENSION PdoExtension; 1041 PUSBHUB_PORT_PDO_EXTENSION pdoExtension; 1042 NTSTATUS NtStatus; 1043 PVOID SerialNumber; 1044 PVOID DeviceHandle; 1045 USB_PORT_STATUS UsbPortStatus; 1046 PLIST_ENTRY Entry; 1047 ULONG Length; 1048 1049 DPRINT_ENUM("USBH_FdoQueryBusRelations: HubFlags - %lX\n", 1050 HubExtension->HubFlags); 1051 1052 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)) 1053 { 1054 Status = STATUS_INVALID_DEVICE_STATE; 1055 goto RelationsWorker; 1056 } 1057 1058 if (!HubExtension->HubDescriptor) 1059 { 1060 Status = STATUS_UNSUCCESSFUL; 1061 goto RelationsWorker; 1062 } 1063 1064 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_ENUMERATION)) 1065 { 1066 // FIXME: this delay makes devices discovery during early boot more reliable 1067 LARGE_INTEGER Interval; 1068 Status = STATUS_SUCCESS; 1069 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations); 1070 Interval.QuadPart = -10000LL * 1000; // 1 sec. 1071 KeDelayExecutionThread(KernelMode, FALSE, &Interval); 1072 1073 DPRINT_ENUM("USBH_FdoQueryBusRelations: Skip enumeration\n"); 1074 goto RelationsWorker; 1075 } 1076 1077 InterlockedIncrement(&HubExtension->PendingRequestCount); 1078 1079 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 1080 Executive, 1081 KernelMode, 1082 FALSE, 1083 NULL); 1084 1085 NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts; 1086 DPRINT_ENUM("USBH_FdoQueryBusRelations: NumberPorts - %x\n", NumberPorts); 1087 1088 Length = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + 1089 NumberPorts * sizeof(PDEVICE_OBJECT); 1090 1091 if (Irp->IoStatus.Information) 1092 { 1093 DPRINT1("FIXME: leaking old bus relations\n"); 1094 } 1095 1096 DeviceRelations = ExAllocatePoolWithTag(NonPagedPool, Length, USB_HUB_TAG); 1097 1098 if (!DeviceRelations) 1099 { 1100 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED; 1101 1102 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 1103 LOW_REALTIME_PRIORITY, 1104 1, 1105 FALSE); 1106 1107 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1108 { 1109 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 1110 } 1111 1112 Status = STATUS_INSUFFICIENT_RESOURCES; 1113 goto RelationsWorker; 1114 } 1115 1116 RtlZeroMemory(DeviceRelations, Length); 1117 1118 DeviceRelations->Count = 0; 1119 1120 EnumStart: 1121 1122 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING) 1123 { 1124 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED; 1125 1126 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 1127 LOW_REALTIME_PRIORITY, 1128 1, 1129 FALSE); 1130 1131 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1132 { 1133 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 1134 } 1135 1136 Status = STATUS_SUCCESS; 1137 goto RelationsWorker; 1138 } 1139 1140 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_ENUM_POST_RECOVER; 1141 1142 for (Port = 1; Port <= NumberPorts; Port++) 1143 { 1144 PortData = &HubExtension->PortData[Port - 1]; 1145 1146 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 1147 { 1148 continue; 1149 } 1150 1151 Status = USBH_SyncGetPortStatus(HubExtension, 1152 Port, 1153 &PortData->PortStatus, 1154 sizeof(USB_PORT_STATUS_AND_CHANGE)); 1155 1156 if (!NT_SUCCESS(Status)) 1157 { 1158 DPRINT_ENUM("USBH_FdoQueryBusRelations: Status - %X\n", Status); 1159 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 1160 DeviceRelations->Count = 0; 1161 goto EnumStart; 1162 } 1163 1164 DPRINT_ENUM("USBH_FdoQueryBusRelations: Port - %x, ConnectStatus - %x\n", 1165 Port, 1166 PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus); 1167 1168 PdoDevice = PortData->DeviceObject; 1169 1170 if (PortData->DeviceObject) 1171 { 1172 PdoExtension = PdoDevice->DeviceExtension; 1173 1174 if (PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_OVERCURRENT_PORT) 1175 { 1176 PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus = 1; 1177 } 1178 } 1179 1180 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 1181 { 1182 DPRINT1("USBH_FdoQueryBusRelations: DbgBreakPoint() \n"); 1183 DbgBreakPoint(); 1184 } 1185 1186 if (!PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus) 1187 { 1188 if (PdoDevice) 1189 { 1190 PdoExtension = PdoDevice->DeviceExtension; 1191 1192 PdoExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DELETE_PENDING; 1193 PdoExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1194 1195 SerialNumber = InterlockedExchangePointer((PVOID)&PdoExtension->SerialNumber, 1196 NULL); 1197 1198 if (SerialNumber) 1199 { 1200 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG); 1201 } 1202 1203 DeviceHandle = InterlockedExchangePointer(&PdoExtension->DeviceHandle, 1204 NULL); 1205 1206 if (DeviceHandle) 1207 { 1208 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 1209 USBH_SyncDisablePort(HubExtension, Port); 1210 } 1211 } 1212 1213 PortData->DeviceObject = NULL; 1214 PortData->ConnectionStatus = NoDeviceConnected; 1215 continue; 1216 } 1217 1218 if (PdoDevice) 1219 { 1220 ObReferenceObject(PdoDevice); 1221 1222 PdoDevice->Flags |= DO_POWER_PAGABLE; 1223 PdoDevice->Flags &= ~DO_DEVICE_INITIALIZING; 1224 1225 DeviceRelations->Objects[DeviceRelations->Count++] = PdoDevice; 1226 1227 PdoExtension = PdoDevice->DeviceExtension; 1228 PdoExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_POWER_D1_OR_D2; 1229 1230 continue; 1231 } 1232 1233 USBH_Wait(100); 1234 1235 NtStatus = USBH_SyncResetPort(HubExtension, Port); 1236 1237 if (!NT_SUCCESS(NtStatus)) 1238 { 1239 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB) 1240 { 1241 PortData->DeviceObject = NULL; 1242 PortData->ConnectionStatus = NoDeviceConnected; 1243 continue; 1244 } 1245 } 1246 else 1247 { 1248 NtStatus = USBH_SyncGetPortStatus(HubExtension, 1249 Port, 1250 &PortData->PortStatus, 1251 sizeof(USB_PORT_STATUS_AND_CHANGE)); 1252 1253 UsbPortStatus = PortData->PortStatus.PortStatus; 1254 1255 if (NT_SUCCESS(NtStatus)) 1256 { 1257 ULONG ix = 0; 1258 1259 for (NtStatus = USBH_CreateDevice(HubExtension, Port, UsbPortStatus, ix); 1260 !NT_SUCCESS(NtStatus); 1261 NtStatus = USBH_CreateDevice(HubExtension, Port, UsbPortStatus, ix)) 1262 { 1263 USBH_Wait(500); 1264 1265 if (ix >= 2) 1266 { 1267 break; 1268 } 1269 1270 if (PortData->DeviceObject) 1271 { 1272 IoDeleteDevice(PortData->DeviceObject); 1273 PortData->DeviceObject = NULL; 1274 PortData->ConnectionStatus = NoDeviceConnected; 1275 } 1276 1277 USBH_SyncResetPort(HubExtension, Port); 1278 1279 ix++; 1280 } 1281 1282 if (NT_SUCCESS(NtStatus)) 1283 { 1284 PdoExtension = PortData->DeviceObject->DeviceExtension; 1285 1286 if (!(PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_LOW_SPEED) && 1287 !(PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_HIGH_SPEED) && 1288 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)) 1289 { 1290 DPRINT1("USBH_FdoQueryBusRelations: FIXME USBH_DeviceIs2xDualMode()\n"); 1291 1292 if (0)//USBH_DeviceIs2xDualMode(PdoExtension)) 1293 { 1294 PdoExtension->PortPdoFlags |= USBHUB_PDO_FLAG_HS_USB1_DUALMODE; 1295 } 1296 } 1297 1298 ObReferenceObject(PortData->DeviceObject); 1299 1300 DeviceRelations->Objects[DeviceRelations->Count] = PortData->DeviceObject; 1301 1302 PortData->DeviceObject->Flags |= DO_POWER_PAGABLE; 1303 PortData->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1304 1305 DeviceRelations->Count++; 1306 1307 PortData->ConnectionStatus = DeviceConnected; 1308 1309 continue; 1310 } 1311 } 1312 } 1313 1314 PortData->ConnectionStatus = DeviceFailedEnumeration; 1315 1316 if (NT_ERROR(USBH_SyncDisablePort(HubExtension, Port))) 1317 { 1318 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 1319 } 1320 1321 if (PortData->DeviceObject) 1322 { 1323 ObReferenceObject(PortData->DeviceObject); 1324 PortData->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1325 DeviceRelations->Objects[DeviceRelations->Count++] = PortData->DeviceObject; 1326 } 1327 } 1328 1329 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED; 1330 1331 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 1332 LOW_REALTIME_PRIORITY, 1333 1, 1334 FALSE); 1335 1336 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1337 { 1338 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 1339 } 1340 1341 RelationsWorker: 1342 1343 Irp->IoStatus.Status = Status; 1344 1345 if (!NT_SUCCESS(Status)) 1346 { 1347 //Irp->IoStatus.Information = 0; 1348 1349 if (DeviceRelations) 1350 { 1351 ExFreePoolWithTag(DeviceRelations, USB_HUB_TAG); 1352 } 1353 1354 USBH_CompleteIrp(Irp, Status); 1355 1356 return Status; 1357 } 1358 1359 KeAcquireSpinLock(&HubExtension->RelationsWorkerSpinLock, &OldIrql); 1360 1361 if (DeviceRelations && DeviceRelations->Count) 1362 { 1363 for (Port = 0; Port < DeviceRelations->Count; Port++) 1364 { 1365 PdoDevice = DeviceRelations->Objects[Port]; 1366 Entry = HubExtension->PdoList.Flink; 1367 1368 while (Entry != &HubExtension->PdoList) 1369 { 1370 pdoExtension = CONTAINING_RECORD(Entry, 1371 USBHUB_PORT_PDO_EXTENSION, 1372 PortLink); 1373 1374 if (pdoExtension == PdoDevice->DeviceExtension) 1375 { 1376 PdoExt(PdoDevice)->EnumFlags |= USBHUB_ENUM_FLAG_GHOST_DEVICE; 1377 goto PortNext; 1378 } 1379 1380 Entry = Entry->Flink; 1381 } 1382 1383 PdoExt(PdoDevice)->EnumFlags |= USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1384 1385 PortNext:; 1386 } 1387 1388 for (Port = 0; Port < DeviceRelations->Count; Port++) 1389 { 1390 PdoDevice = DeviceRelations->Objects[Port]; 1391 1392 if (PdoExt(PdoDevice)->EnumFlags & USBHUB_ENUM_FLAG_GHOST_DEVICE) 1393 { 1394 for (GhostPort = Port; 1395 GhostPort < DeviceRelations->Count; 1396 GhostPort++) 1397 { 1398 DeviceRelations->Objects[GhostPort] = 1399 DeviceRelations->Objects[GhostPort + 1]; 1400 } 1401 1402 ObDereferenceObject(PdoDevice); 1403 1404 DeviceRelations->Count--; 1405 1406 if (PdoExt(PdoDevice)->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) 1407 { 1408 PdoExt(PdoDevice)->EnumFlags &= ~USBHUB_ENUM_FLAG_GHOST_DEVICE; 1409 } 1410 } 1411 } 1412 } 1413 1414 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1415 1416 InitializeListHead(&GhostPdoList); 1417 PdoList = &HubExtension->PdoList; 1418 1419 while (!IsListEmpty(PdoList)) 1420 { 1421 Entry = RemoveHeadList(PdoList); 1422 1423 PdoExtension = CONTAINING_RECORD(Entry, 1424 USBHUB_PORT_PDO_EXTENSION, 1425 PortLink); 1426 1427 PdoExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1428 1429 if (PdoExtension->EnumFlags & USBHUB_ENUM_FLAG_GHOST_DEVICE) 1430 { 1431 InsertTailList(&GhostPdoList, &PdoExtension->PortLink); 1432 } 1433 } 1434 1435 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, OldIrql); 1436 1437 while (!IsListEmpty(&GhostPdoList)) 1438 { 1439 Entry = RemoveHeadList(&GhostPdoList); 1440 1441 PdoExtension = CONTAINING_RECORD(Entry, 1442 USBHUB_PORT_PDO_EXTENSION, 1443 PortLink); 1444 1445 IoDeleteDevice(PdoExtension->Common.SelfDevice); 1446 } 1447 1448 return USBH_PassIrp(HubExtension->LowerDevice, Irp); 1449 } 1450 1451 NTSTATUS 1452 NTAPI 1453 USBH_FdoStopDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 1454 IN PIRP Irp) 1455 { 1456 DPRINT1("USBH_FdoStopDevice: UNIMPLEMENTED. FIXME\n"); 1457 DbgBreakPoint(); 1458 return STATUS_SUCCESS; 1459 } 1460 1461 NTSTATUS 1462 NTAPI 1463 USBH_FdoRemoveDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 1464 IN PIRP Irp) 1465 { 1466 PUSB_HUB_DESCRIPTOR HubDescriptor; 1467 PUSBHUB_PORT_DATA PortData; 1468 USHORT NumPorts; 1469 USHORT ix; 1470 PDEVICE_OBJECT PortDevice; 1471 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 1472 NTSTATUS Status; 1473 1474 DPRINT("USBH_FdoRemoveDevice: HubExtension - %p\n", HubExtension); 1475 1476 HubDescriptor = HubExtension->HubDescriptor; 1477 1478 if (HubDescriptor && HubExtension->PortData) 1479 { 1480 NumPorts = HubDescriptor->bNumberOfPorts; 1481 1482 for (ix = 0; ix < NumPorts; ++ix) 1483 { 1484 PortData = HubExtension->PortData + ix; 1485 1486 PortDevice = PortData->DeviceObject; 1487 1488 if (PortDevice) 1489 { 1490 PortData->PortStatus.AsUlong32 = 0; 1491 PortData->DeviceObject = NULL; 1492 1493 PortExtension = PortDevice->DeviceExtension; 1494 PortExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1495 1496 USBH_PdoRemoveDevice(PortExtension, HubExtension); 1497 } 1498 } 1499 } 1500 1501 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 1502 { 1503 USBH_FdoCleanup(HubExtension); 1504 } 1505 1506 if (HubExtension->PortData) 1507 { 1508 ExFreePoolWithTag(HubExtension->PortData, USB_HUB_TAG); 1509 HubExtension->PortData = NULL; 1510 } 1511 1512 DPRINT1("USBH_FdoRemoveDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n"); 1513 1514 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 1515 1516 IoDetachDevice(HubExtension->LowerDevice); 1517 IoDeleteDevice(HubExtension->Common.SelfDevice); 1518 1519 return Status; 1520 } 1521 1522 VOID 1523 NTAPI 1524 USBH_FdoSurpriseRemoveDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 1525 IN PIRP Irp) 1526 { 1527 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 1528 PUSBHUB_PORT_DATA PortData; 1529 ULONG NumberPorts; 1530 ULONG Port; 1531 1532 DPRINT("USBH_FdoSurpriseRemoveDevice: HubExtension - %p, Irp - %p\n", 1533 HubExtension, 1534 Irp); 1535 1536 if (!HubExtension->PortData || 1537 !HubExtension->HubDescriptor) 1538 { 1539 return; 1540 } 1541 1542 PortData = HubExtension->PortData; 1543 NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts; 1544 1545 for (Port = 0; Port < NumberPorts; Port++) 1546 { 1547 if (PortData[Port].DeviceObject) 1548 { 1549 PortExtension = PdoExt(PortData[Port].DeviceObject); 1550 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DELETE_PENDING; 1551 PortExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1552 1553 PortData[Port].DeviceObject = NULL; 1554 PortData[Port].ConnectionStatus = NoDeviceConnected; 1555 } 1556 } 1557 } 1558 1559 NTSTATUS 1560 NTAPI 1561 USBH_PdoQueryId(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 1562 IN PIRP Irp) 1563 { 1564 ULONG IdType; 1565 WCHAR Buffer[200]; 1566 PWCHAR EndBuffer; 1567 size_t Remaining = sizeof(Buffer); 1568 size_t Length; 1569 PWCHAR Id = NULL; 1570 NTSTATUS Status = STATUS_SUCCESS; 1571 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; 1572 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; 1573 1574 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; 1575 DeviceDescriptor = &PortExtension->DeviceDescriptor; 1576 InterfaceDescriptor = &PortExtension->InterfaceDescriptor; 1577 1578 RtlZeroMemory(Buffer, sizeof(Buffer)); 1579 1580 switch (IdType) 1581 { 1582 case BusQueryDeviceID: 1583 DPRINT("USBH_PdoQueryId: BusQueryDeviceID\n"); 1584 1585 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1586 { 1587 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n"); 1588 RtlStringCbPrintfExW(Buffer, 1589 Remaining, 1590 NULL, 1591 &Remaining, 1592 0, 1593 L"USB\\Vid_0000&Pid_0000"); 1594 } 1595 else 1596 { 1597 RtlStringCbPrintfExW(Buffer, 1598 Remaining, 1599 NULL, 1600 &Remaining, 1601 0, 1602 L"USB\\Vid_%04x&Pid_%04x", 1603 DeviceDescriptor->idVendor, 1604 DeviceDescriptor->idProduct); 1605 } 1606 1607 Length = sizeof(Buffer) - (Remaining - sizeof(UNICODE_NULL)); 1608 1609 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1610 1611 if (!Id) 1612 { 1613 break; 1614 } 1615 1616 RtlCopyMemory(Id, Buffer, Length); 1617 DPRINT("USBH_PdoQueryId: BusQueryDeviceID - %S\n", Id); 1618 break; 1619 1620 case BusQueryHardwareIDs: 1621 DPRINT("USBH_PdoQueryId: BusQueryHardwareIDs\n"); 1622 1623 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1624 { 1625 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n"); 1626 1627 RtlStringCbPrintfExW(Buffer, 1628 Remaining, 1629 NULL, 1630 &Remaining, 1631 0, 1632 L"USB\\UNKNOWN"); 1633 } 1634 else 1635 { 1636 RtlStringCbPrintfExW(Buffer, 1637 Remaining, 1638 &EndBuffer, 1639 &Remaining, 1640 0, 1641 L"USB\\Vid_%04x&Pid_%04x&Rev_%04x", 1642 DeviceDescriptor->idVendor, 1643 DeviceDescriptor->idProduct, 1644 DeviceDescriptor->bcdDevice); 1645 1646 EndBuffer++; 1647 Remaining -= sizeof(UNICODE_NULL); 1648 1649 RtlStringCbPrintfExW(EndBuffer, 1650 Remaining, 1651 NULL, 1652 &Remaining, 1653 0, 1654 L"USB\\Vid_%04x&Pid_%04x", 1655 DeviceDescriptor->idVendor, 1656 DeviceDescriptor->idProduct); 1657 } 1658 1659 Length = sizeof(Buffer) - (Remaining - 2 * sizeof(UNICODE_NULL)); 1660 1661 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1662 1663 if (!Id) 1664 { 1665 break; 1666 } 1667 1668 RtlCopyMemory(Id, Buffer, Length); 1669 1670 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1671 { 1672 DPRINT("USBH_PdoQueryId: BusQueryHardwareID - %S\n", Id); 1673 } 1674 else 1675 { 1676 USBHUB_DumpingIDs(Id); 1677 } 1678 1679 break; 1680 1681 case BusQueryCompatibleIDs: 1682 DPRINT("USBH_PdoQueryId: BusQueryCompatibleIDs\n"); 1683 1684 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1685 { 1686 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n"); 1687 1688 RtlStringCbPrintfExW(Buffer, 1689 Remaining, 1690 NULL, 1691 &Remaining, 1692 0, 1693 L"USB\\UNKNOWN"); 1694 } 1695 else if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_MULTI_INTERFACE) 1696 { 1697 RtlStringCbPrintfExW(Buffer, 1698 Remaining, 1699 &EndBuffer, 1700 &Remaining, 1701 0, 1702 L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x", 1703 InterfaceDescriptor->bInterfaceClass, 1704 InterfaceDescriptor->bInterfaceSubClass, 1705 InterfaceDescriptor->bInterfaceProtocol); 1706 1707 EndBuffer++; 1708 Remaining -= sizeof(UNICODE_NULL); 1709 1710 RtlStringCbPrintfExW(EndBuffer, 1711 Remaining, 1712 &EndBuffer, 1713 &Remaining, 1714 0, 1715 L"USB\\DevClass_%02x&SubClass_%02x", 1716 InterfaceDescriptor->bInterfaceClass, 1717 InterfaceDescriptor->bInterfaceSubClass); 1718 1719 EndBuffer++; 1720 Remaining -= sizeof(UNICODE_NULL); 1721 1722 RtlStringCbPrintfExW(EndBuffer, 1723 Remaining, 1724 &EndBuffer, 1725 &Remaining, 1726 0, 1727 L"USB\\DevClass_%02x", 1728 InterfaceDescriptor->bInterfaceClass); 1729 1730 EndBuffer++; 1731 Remaining -= sizeof(UNICODE_NULL); 1732 1733 RtlStringCbPrintfExW(EndBuffer, 1734 Remaining, 1735 NULL, 1736 &Remaining, 1737 0, 1738 L"USB\\COMPOSITE"); 1739 } 1740 else 1741 { 1742 RtlStringCbPrintfExW(Buffer, 1743 Remaining, 1744 &EndBuffer, 1745 &Remaining, 1746 0, 1747 L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", 1748 InterfaceDescriptor->bInterfaceClass, 1749 InterfaceDescriptor->bInterfaceSubClass, 1750 InterfaceDescriptor->bInterfaceProtocol); 1751 1752 EndBuffer++; 1753 Remaining -= sizeof(UNICODE_NULL); 1754 1755 RtlStringCbPrintfExW(EndBuffer, 1756 Remaining, 1757 &EndBuffer, 1758 &Remaining, 1759 0, 1760 L"USB\\Class_%02x&SubClass_%02x", 1761 InterfaceDescriptor->bInterfaceClass, 1762 InterfaceDescriptor->bInterfaceSubClass); 1763 1764 EndBuffer++; 1765 Remaining -= sizeof(UNICODE_NULL); 1766 1767 RtlStringCbPrintfExW(EndBuffer, 1768 Remaining, 1769 NULL, 1770 &Remaining, 1771 0, 1772 L"USB\\Class_%02x", 1773 InterfaceDescriptor->bInterfaceClass); 1774 } 1775 1776 Length = sizeof(Buffer) - (Remaining - 2 * sizeof(UNICODE_NULL)); 1777 1778 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1779 1780 if (!Id) 1781 { 1782 break; 1783 } 1784 1785 RtlCopyMemory(Id, Buffer, Length); 1786 1787 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1788 { 1789 DPRINT("USBH_PdoQueryId: BusQueryCompatibleID - %S\n", Id); 1790 } 1791 else 1792 { 1793 USBHUB_DumpingIDs(Id); 1794 } 1795 1796 break; 1797 1798 case BusQueryInstanceID: 1799 DPRINT("USBH_PdoQueryId: BusQueryInstanceID\n"); 1800 1801 if (PortExtension->SerialNumber) 1802 { 1803 Id = ExAllocatePoolWithTag(PagedPool, 1804 PortExtension->SN_DescriptorLength, 1805 USB_HUB_TAG); 1806 1807 if (Id) 1808 { 1809 RtlZeroMemory(Id, PortExtension->SN_DescriptorLength); 1810 1811 RtlCopyMemory(Id, 1812 PortExtension->SerialNumber, 1813 PortExtension->SN_DescriptorLength); 1814 } 1815 } 1816 else 1817 { 1818 Length = sizeof(PortExtension->InstanceID) + 1819 sizeof(UNICODE_NULL); 1820 1821 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1822 1823 if (Id) 1824 { 1825 RtlZeroMemory(Id, Length); 1826 1827 RtlCopyMemory(Id, 1828 PortExtension->InstanceID, 1829 sizeof(PortExtension->InstanceID)); 1830 } 1831 } 1832 1833 DPRINT("USBH_PdoQueryId: BusQueryInstanceID - %S\n", Id); 1834 break; 1835 1836 default: 1837 DPRINT1("USBH_PdoQueryId: unknown query id type 0x%lx\n", IdType); 1838 return Irp->IoStatus.Status; 1839 } 1840 1841 Irp->IoStatus.Information = (ULONG_PTR)Id; 1842 1843 if (!Id) 1844 { 1845 Status = STATUS_INSUFFICIENT_RESOURCES; 1846 } 1847 1848 return Status; 1849 } 1850 1851 NTSTATUS 1852 NTAPI 1853 USBH_PdoQueryDeviceText(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 1854 IN PIRP Irp) 1855 { 1856 PDEVICE_OBJECT DeviceObject; 1857 PIO_STACK_LOCATION IoStack; 1858 DEVICE_TEXT_TYPE DeviceTextType; 1859 USHORT LanguageId; 1860 USHORT DefaultId; 1861 PUSB_STRING_DESCRIPTOR Descriptor; 1862 PWCHAR DeviceText; 1863 UCHAR iProduct = 0; 1864 NTSTATUS Status; 1865 size_t NumSymbols; 1866 size_t Length; 1867 1868 DPRINT("USBH_PdoQueryDeviceText ... \n"); 1869 1870 DeviceObject = PortExtension->Common.SelfDevice; 1871 IoStack = IoGetCurrentIrpStackLocation(Irp); 1872 DeviceTextType = IoStack->Parameters.QueryDeviceText.DeviceTextType; 1873 1874 if (DeviceTextType != DeviceTextDescription && 1875 DeviceTextType != DeviceTextLocationInformation) 1876 { 1877 return Irp->IoStatus.Status; 1878 } 1879 1880 LanguageId = LANGIDFROMLCID(IoStack->Parameters.QueryDeviceText.LocaleId); 1881 DefaultId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 1882 1883 if (!LanguageId) 1884 { 1885 LanguageId = DefaultId; 1886 } 1887 1888 iProduct = PortExtension->DeviceDescriptor.iProduct; 1889 1890 if (PortExtension->DeviceHandle && iProduct && 1891 !PortExtension->IgnoringHwSerial && 1892 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)) 1893 { 1894 Descriptor = ExAllocatePoolWithTag(NonPagedPool, 1895 MAXIMUM_USB_STRING_LENGTH, 1896 USB_HUB_TAG); 1897 1898 if (Descriptor) 1899 { 1900 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH); 1901 1902 for (Status = USBH_CheckDeviceLanguage(DeviceObject, LanguageId); 1903 ; 1904 Status = USBH_CheckDeviceLanguage(DeviceObject, DefaultId)) 1905 { 1906 if (NT_SUCCESS(Status)) 1907 { 1908 Status = USBH_SyncGetStringDescriptor(DeviceObject, 1909 iProduct, 1910 LanguageId, 1911 Descriptor, 1912 MAXIMUM_USB_STRING_LENGTH, 1913 NULL, 1914 TRUE); 1915 1916 if (NT_SUCCESS(Status)) 1917 { 1918 break; 1919 } 1920 } 1921 1922 if (LanguageId == DefaultId) 1923 { 1924 goto Exit; 1925 } 1926 1927 LanguageId = DefaultId; 1928 } 1929 1930 if (Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR)) 1931 { 1932 Status = STATUS_UNSUCCESSFUL; 1933 } 1934 1935 if (NT_SUCCESS(Status)) 1936 { 1937 Length = Descriptor->bLength - 1938 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString); 1939 1940 DeviceText = ExAllocatePoolWithTag(PagedPool, 1941 Length + sizeof(UNICODE_NULL), 1942 USB_HUB_TAG); 1943 1944 if (DeviceText) 1945 { 1946 RtlZeroMemory(DeviceText, Length + sizeof(UNICODE_NULL)); 1947 1948 RtlCopyMemory(DeviceText, Descriptor->bString, Length); 1949 1950 Irp->IoStatus.Information = (ULONG_PTR)DeviceText; 1951 1952 DPRINT("USBH_PdoQueryDeviceText: Descriptor->bString - %S\n", 1953 DeviceText); 1954 } 1955 else 1956 { 1957 Status = STATUS_INSUFFICIENT_RESOURCES; 1958 } 1959 } 1960 1961 Exit: 1962 1963 ExFreePoolWithTag(Descriptor, USB_HUB_TAG); 1964 1965 if (NT_SUCCESS(Status)) 1966 { 1967 return Status; 1968 } 1969 } 1970 else 1971 { 1972 Status = STATUS_INSUFFICIENT_RESOURCES; 1973 } 1974 } 1975 else 1976 { 1977 Status = STATUS_NOT_SUPPORTED; 1978 } 1979 1980 if (!GenericUSBDeviceString) 1981 { 1982 return Status; 1983 } 1984 1985 NumSymbols = wcslen(GenericUSBDeviceString); 1986 Length = (NumSymbols + 1) * sizeof(WCHAR); 1987 1988 DeviceText = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1989 1990 if (!DeviceText) 1991 { 1992 return STATUS_INSUFFICIENT_RESOURCES; 1993 } 1994 1995 RtlZeroMemory(DeviceText, Length); 1996 1997 RtlCopyMemory(DeviceText, 1998 GenericUSBDeviceString, 1999 NumSymbols * sizeof(WCHAR)); 2000 2001 Irp->IoStatus.Information = (ULONG_PTR)DeviceText; 2002 2003 return STATUS_SUCCESS; 2004 } 2005 2006 NTSTATUS 2007 NTAPI 2008 USBH_SymbolicLink(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2009 IN const GUID * InterfaceClassGuid, 2010 IN BOOLEAN IsEnable) 2011 { 2012 NTSTATUS Status = STATUS_SUCCESS; 2013 PVOID NameBuffer; 2014 2015 DPRINT("USBH_SymbolicLink ... \n"); 2016 2017 if (IsEnable) 2018 { 2019 Status = IoRegisterDeviceInterface(PortExtension->Common.SelfDevice, 2020 InterfaceClassGuid, 2021 NULL, 2022 &PortExtension->SymbolicLinkName); 2023 2024 if (NT_SUCCESS(Status)) 2025 { 2026 USBH_SetPdoRegistryParameter(PortExtension->Common.SelfDevice, 2027 L"SymbolicName", 2028 PortExtension->SymbolicLinkName.Buffer, 2029 PortExtension->SymbolicLinkName.Length, 2030 REG_SZ, 2031 PLUGPLAY_REGKEY_DEVICE); 2032 2033 Status = IoSetDeviceInterfaceState(&PortExtension->SymbolicLinkName, 2034 TRUE); 2035 } 2036 } 2037 else 2038 { 2039 NameBuffer = PortExtension->SymbolicLinkName.Buffer; 2040 2041 if (NameBuffer) 2042 { 2043 Status = IoSetDeviceInterfaceState(&PortExtension->SymbolicLinkName, 2044 FALSE); 2045 2046 ExFreePool(PortExtension->SymbolicLinkName.Buffer); 2047 2048 PortExtension->SymbolicLinkName.Buffer = NULL; 2049 } 2050 } 2051 2052 return Status; 2053 } 2054 2055 NTSTATUS 2056 NTAPI 2057 USBH_RestoreDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2058 IN BOOLEAN IsKeepDeviceData) 2059 { 2060 PUSBHUB_FDO_EXTENSION HubExtension; 2061 PUSBHUB_PORT_DATA PortData; 2062 NTSTATUS Status; 2063 ULONG ix; 2064 2065 DPRINT("USBH_RestoreDevice ... \n"); 2066 2067 HubExtension = PortExtension->HubExtension; 2068 2069 if (!HubExtension) 2070 { 2071 Status = STATUS_UNSUCCESSFUL; 2072 return Status; 2073 } 2074 2075 ASSERT(PortExtension->PortNumber > 0); 2076 PortData = &HubExtension->PortData[PortExtension->PortNumber - 1]; 2077 2078 if (PortExtension->Common.SelfDevice != PortData->DeviceObject) 2079 { 2080 Status = STATUS_UNSUCCESSFUL; 2081 return Status; 2082 } 2083 2084 Status = USBH_SyncGetPortStatus(HubExtension, 2085 PortExtension->PortNumber, 2086 &PortData->PortStatus, 2087 sizeof(USB_PORT_STATUS_AND_CHANGE)); 2088 2089 if (NT_SUCCESS(Status)) 2090 { 2091 for (ix = 0; ix < 3; ix++) 2092 { 2093 Status = USBH_ResetDevice((PUSBHUB_FDO_EXTENSION)HubExtension, 2094 PortExtension->PortNumber, 2095 IsKeepDeviceData, 2096 ix == 0); 2097 2098 if (NT_SUCCESS(Status) || Status == STATUS_NO_SUCH_DEVICE) 2099 { 2100 break; 2101 } 2102 2103 USBH_Wait(1000); 2104 } 2105 } 2106 2107 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_POWER_D3; 2108 2109 if (NT_SUCCESS(Status)) 2110 { 2111 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESTORE_FAIL; 2112 } 2113 else 2114 { 2115 PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_INIT_PORT_FAILED | 2116 USBHUB_PDO_FLAG_PORT_RESTORE_FAIL); 2117 } 2118 2119 return Status; 2120 } 2121 2122 NTSTATUS 2123 NTAPI 2124 USBH_PdoStartDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2125 IN PIRP Irp) 2126 { 2127 PUSBHUB_FDO_EXTENSION HubExtension; 2128 const GUID * Guid; 2129 NTSTATUS Status; 2130 2131 DPRINT("USBH_PdoStartDevice: PortExtension - %p\n", PortExtension); 2132 2133 if (!PortExtension->HubExtension && 2134 PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3) 2135 { 2136 PortExtension->HubExtension = PortExtension->RootHubExtension; 2137 } 2138 2139 HubExtension = PortExtension->HubExtension; 2140 2141 if (HubExtension) 2142 { 2143 USBHUB_SetDeviceHandleData(HubExtension, 2144 PortExtension->Common.SelfDevice, 2145 PortExtension->DeviceHandle); 2146 } 2147 2148 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE) 2149 { 2150 Guid = &GUID_DEVINTERFACE_USB_HUB; 2151 } 2152 else 2153 { 2154 Guid = &GUID_DEVINTERFACE_USB_DEVICE; 2155 } 2156 2157 Status = USBH_SymbolicLink(PortExtension, Guid, TRUE); 2158 2159 if (NT_SUCCESS(Status)) 2160 { 2161 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REG_DEV_INTERFACE; 2162 } 2163 2164 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3) 2165 { 2166 Status = USBH_RestoreDevice(PortExtension, 0); 2167 } 2168 2169 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DEVICE_STARTED; 2170 2171 PortExtension->CurrentPowerState.DeviceState = PowerDeviceD0; 2172 2173 DPRINT1("USBH_PdoStartDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n"); 2174 2175 return Status; 2176 } 2177 2178 NTSTATUS 2179 NTAPI 2180 USBH_PdoRemoveDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2181 IN PUSBHUB_FDO_EXTENSION HubExtension) 2182 { 2183 NTSTATUS Status = STATUS_SUCCESS; 2184 PDEVICE_OBJECT PortDevice; 2185 PUSBHUB_PORT_PDO_EXTENSION PortExt; 2186 PUSBHUB_PORT_DATA PortData; 2187 PIRP IdleNotificationIrp; 2188 PIRP WakeIrp; 2189 PVOID DeviceHandle; 2190 PDEVICE_OBJECT Pdo; 2191 PVOID SerialNumber; 2192 USHORT Port; 2193 KIRQL Irql; 2194 2195 DPRINT("USBH_PdoRemoveDevice ... \n"); 2196 2197 PortDevice = PortExtension->Common.SelfDevice; 2198 PortExtension->HubExtension = NULL; 2199 2200 Port = PortExtension->PortNumber; 2201 ASSERT(Port > 0); 2202 2203 if (HubExtension && 2204 HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 && 2205 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) != 0) 2206 { 2207 USBH_HubSetD0(HubExtension); 2208 } 2209 2210 IoAcquireCancelSpinLock(&Irql); 2211 IdleNotificationIrp = PortExtension->IdleNotificationIrp; 2212 2213 if (IdleNotificationIrp) 2214 { 2215 PortExtension->IdleNotificationIrp = NULL; 2216 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION; 2217 2218 if (IdleNotificationIrp->Cancel) 2219 { 2220 IdleNotificationIrp = NULL; 2221 } 2222 2223 if (IdleNotificationIrp) 2224 { 2225 IoSetCancelRoutine(IdleNotificationIrp, NULL); 2226 } 2227 } 2228 2229 WakeIrp = PortExtension->PdoWaitWakeIrp; 2230 2231 if (WakeIrp) 2232 { 2233 PortExtension->PdoWaitWakeIrp = NULL; 2234 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_WAIT_WAKE; 2235 2236 if (WakeIrp->Cancel || !IoSetCancelRoutine(WakeIrp, NULL)) 2237 { 2238 WakeIrp = NULL; 2239 2240 ASSERT(HubExtension); 2241 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 2242 { 2243 KeSetEvent(&HubExtension->PendingRequestEvent, 2244 EVENT_INCREMENT, 2245 FALSE); 2246 } 2247 } 2248 } 2249 2250 IoReleaseCancelSpinLock(Irql); 2251 2252 if (IdleNotificationIrp) 2253 { 2254 IdleNotificationIrp->IoStatus.Status = STATUS_CANCELLED; 2255 IoCompleteRequest(IdleNotificationIrp, IO_NO_INCREMENT); 2256 } 2257 2258 if (WakeIrp) 2259 { 2260 ASSERT(HubExtension); 2261 USBH_CompletePowerIrp(HubExtension, WakeIrp, STATUS_CANCELLED); 2262 } 2263 2264 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_POWER_D3; 2265 2266 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE) 2267 { 2268 Status = USBH_SymbolicLink(PortExtension, NULL, FALSE); 2269 2270 if (NT_SUCCESS(Status)) 2271 { 2272 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE; 2273 } 2274 } 2275 2276 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle, 2277 NULL); 2278 2279 if (DeviceHandle) 2280 { 2281 ASSERT(HubExtension); 2282 Status = USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 2283 2284 if (HubExtension->PortData && 2285 HubExtension->PortData[Port - 1].DeviceObject == PortDevice) 2286 { 2287 USBH_SyncDisablePort(HubExtension, Port); 2288 } 2289 } 2290 2291 if (NT_SUCCESS(Status)) 2292 { 2293 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_DEVICE_STARTED; 2294 2295 if (HubExtension && HubExtension->PortData) 2296 { 2297 PortData = &HubExtension->PortData[Port - 1]; 2298 2299 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DELETE_PENDING) 2300 { 2301 Pdo = PortData->DeviceObject; 2302 2303 if (Pdo) 2304 { 2305 PortData->DeviceObject = NULL; 2306 PortData->ConnectionStatus = NoDeviceConnected; 2307 2308 if (PdoExt(Pdo)->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) 2309 { 2310 PortExt = PdoExt(Pdo); 2311 2312 InsertTailList(&HubExtension->PdoList, 2313 &PortExt->PortLink); 2314 } 2315 } 2316 } 2317 } 2318 2319 if (!(PortExtension->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) && 2320 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_NOT_CONNECTED)) 2321 { 2322 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_NOT_CONNECTED; 2323 2324 SerialNumber = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, 2325 NULL); 2326 2327 if (SerialNumber) 2328 { 2329 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG); 2330 } 2331 2332 DPRINT1("USBH_PdoRemoveDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n"); 2333 2334 if (HubExtension) 2335 USBHUB_FlushAllTransfers(HubExtension); 2336 2337 IoDeleteDevice(PortDevice); 2338 } 2339 } 2340 2341 if (HubExtension) 2342 { 2343 DPRINT("USBH_PdoRemoveDevice: call USBH_CheckIdleDeferred()\n"); 2344 USBH_CheckIdleDeferred(HubExtension); 2345 } 2346 2347 return Status; 2348 } 2349 2350 NTSTATUS 2351 NTAPI 2352 USBH_PdoStopDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2353 IN PIRP Irp) 2354 { 2355 DPRINT1("USBH_PdoStopDevice: UNIMPLEMENTED. FIXME\n"); 2356 DbgBreakPoint(); 2357 return STATUS_SUCCESS; 2358 } 2359 2360 NTSTATUS 2361 NTAPI 2362 USBH_FdoPnP(IN PUSBHUB_FDO_EXTENSION HubExtension, 2363 IN PIRP Irp, 2364 IN UCHAR Minor) 2365 { 2366 NTSTATUS Status; 2367 PIO_STACK_LOCATION IoStack; 2368 DEVICE_RELATION_TYPE RelationsType; 2369 BOOLEAN IsCheckIdle; 2370 2371 DPRINT_PNP("USBH_FdoPnP: HubExtension - %p, Irp - %p, Minor - %X\n", 2372 HubExtension, 2373 Irp, 2374 Minor); 2375 2376 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST && 2377 (Minor == IRP_MN_REMOVE_DEVICE || Minor == IRP_MN_STOP_DEVICE)) 2378 { 2379 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_SUSPENDED; 2380 } 2381 2382 KeWaitForSingleObject(&HubExtension->IdleSemaphore, 2383 Executive, 2384 KernelMode, 2385 FALSE, 2386 NULL); 2387 2388 DPRINT_PNP("USBH_FdoPnP: HubFlags - %lX\n", HubExtension->HubFlags); 2389 2390 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_GOING_IDLE) 2391 { 2392 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_SUSPENDED; 2393 } 2394 2395 IoStack = IoGetCurrentIrpStackLocation(Irp); 2396 RelationsType = IoStack->Parameters.QueryDeviceRelations.Type; 2397 2398 if ((HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0) || 2399 !(HubExtension->HubFlags & (USBHUB_FDO_FLAG_DEVICE_STOPPED | USBHUB_FDO_FLAG_DEVICE_STARTED)) || 2400 (Minor == IRP_MN_QUERY_DEVICE_RELATIONS && RelationsType == TargetDeviceRelation)) 2401 { 2402 IsCheckIdle = FALSE; 2403 } 2404 else 2405 { 2406 DPRINT_PNP("USBH_FdoPnP: IsCheckIdle - TRUE\n"); 2407 IsCheckIdle = TRUE; 2408 USBH_HubSetD0(HubExtension); 2409 } 2410 2411 switch (Minor) 2412 { 2413 case IRP_MN_START_DEVICE: 2414 DPRINT_PNP("FDO IRP_MN_START_DEVICE\n"); 2415 IsCheckIdle = FALSE; 2416 Irp->IoStatus.Status = STATUS_SUCCESS; 2417 Status = USBH_FdoStartDevice(HubExtension, Irp); 2418 break; 2419 2420 case IRP_MN_QUERY_REMOVE_DEVICE: 2421 DPRINT_PNP("FDO IRP_MN_QUERY_REMOVE_DEVICE\n"); 2422 Irp->IoStatus.Status = STATUS_SUCCESS; 2423 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2424 break; 2425 2426 case IRP_MN_REMOVE_DEVICE: 2427 DPRINT_PNP("FDO IRP_MN_REMOVE_DEVICE\n"); 2428 IsCheckIdle = FALSE; 2429 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_REMOVED; 2430 Irp->IoStatus.Status = STATUS_SUCCESS; 2431 Status = USBH_FdoRemoveDevice(HubExtension, Irp); 2432 break; 2433 2434 case IRP_MN_CANCEL_REMOVE_DEVICE: 2435 DPRINT_PNP("FDO IRP_MN_CANCEL_REMOVE_DEVICE\n"); 2436 Irp->IoStatus.Status = STATUS_SUCCESS; 2437 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2438 break; 2439 2440 case IRP_MN_STOP_DEVICE: 2441 DPRINT_PNP("FDO IRP_MN_STOP_DEVICE\n"); 2442 IsCheckIdle = FALSE; 2443 Irp->IoStatus.Status = STATUS_SUCCESS; 2444 Status = USBH_FdoStopDevice(HubExtension, Irp); 2445 break; 2446 2447 case IRP_MN_QUERY_STOP_DEVICE: 2448 DPRINT_PNP("FDO IRP_MN_QUERY_STOP_DEVICE\n"); 2449 Irp->IoStatus.Status = STATUS_SUCCESS; 2450 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2451 break; 2452 2453 case IRP_MN_CANCEL_STOP_DEVICE: 2454 DPRINT_PNP("FDO IRP_MN_CANCEL_STOP_DEVICE\n"); 2455 Irp->IoStatus.Status = STATUS_SUCCESS; 2456 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2457 break; 2458 2459 case IRP_MN_QUERY_DEVICE_RELATIONS: 2460 DPRINT_PNP("FDO IRP_MN_QUERY_DEVICE_RELATIONS\n"); 2461 2462 if (RelationsType != BusRelations) 2463 { 2464 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2465 break; 2466 } 2467 2468 HubExtension->HubFlags |= USBHUB_FDO_FLAG_HUB_BUSY; 2469 2470 IsCheckIdle = TRUE; 2471 DPRINT_PNP("USBH_FdoPnP: IsCheckIdle - TRUE\n"); 2472 2473 Status = USBH_FdoQueryBusRelations(HubExtension, Irp); 2474 2475 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_HUB_BUSY; 2476 break; 2477 2478 case IRP_MN_QUERY_INTERFACE: 2479 DPRINT_PNP("FDO IRP_MN_QUERY_INTERFACE\n"); 2480 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2481 break; 2482 2483 case IRP_MN_QUERY_CAPABILITIES: 2484 DPRINT_PNP("FDO IRP_MN_QUERY_CAPABILITIES\n"); 2485 IoCopyCurrentIrpStackLocationToNext(Irp); 2486 2487 IoSetCompletionRoutine(Irp, 2488 USBH_QueryCapsComplete, 2489 HubExtension, 2490 TRUE, 2491 FALSE, 2492 FALSE); 2493 2494 Status = IoCallDriver(HubExtension->LowerDevice, Irp); 2495 break; 2496 2497 case IRP_MN_QUERY_RESOURCES: 2498 DPRINT_PNP("FDO IRP_MN_QUERY_RESOURCES\n"); 2499 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2500 break; 2501 2502 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 2503 DPRINT_PNP("FDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 2504 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2505 break; 2506 2507 case IRP_MN_QUERY_DEVICE_TEXT: 2508 DPRINT_PNP("FDO IRP_MN_QUERY_DEVICE_TEXT\n"); 2509 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2510 break; 2511 2512 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 2513 DPRINT_PNP("FDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 2514 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2515 break; 2516 2517 case IRP_MN_READ_CONFIG: 2518 DPRINT_PNP("FDO IRP_MN_READ_CONFIG\n"); 2519 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2520 break; 2521 2522 case IRP_MN_WRITE_CONFIG: 2523 DPRINT_PNP("FDO IRP_MN_WRITE_CONFIG\n"); 2524 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2525 break; 2526 2527 case IRP_MN_EJECT: 2528 DPRINT_PNP("FDO IRP_MN_EJECT\n"); 2529 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2530 break; 2531 2532 case IRP_MN_SET_LOCK: 2533 DPRINT_PNP("FDO IRP_MN_SET_LOCK\n"); 2534 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2535 break; 2536 2537 case IRP_MN_QUERY_ID: 2538 DPRINT_PNP("FDO IRP_MN_QUERY_ID\n"); 2539 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2540 break; 2541 2542 case IRP_MN_QUERY_PNP_DEVICE_STATE: 2543 DPRINT_PNP("FDO IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 2544 2545 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 2546 { 2547 Irp->IoStatus.Information |= PNP_DEVICE_FAILED; 2548 } 2549 2550 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2551 break; 2552 2553 case IRP_MN_QUERY_BUS_INFORMATION: 2554 DPRINT_PNP("FDO IRP_MN_QUERY_BUS_INFORMATION\n"); 2555 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2556 break; 2557 2558 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 2559 DPRINT_PNP("FDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); 2560 Irp->IoStatus.Status = STATUS_SUCCESS; 2561 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2562 break; 2563 2564 case IRP_MN_SURPRISE_REMOVAL: 2565 DPRINT_PNP("FDO IRP_MN_SURPRISE_REMOVAL\n"); 2566 USBH_FdoSurpriseRemoveDevice(HubExtension, Irp); 2567 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2568 break; 2569 2570 default: 2571 DPRINT_PNP("FDO unknown IRP_MN_???\n"); 2572 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2573 break; 2574 } 2575 2576 KeReleaseSemaphore(&HubExtension->IdleSemaphore, 2577 LOW_REALTIME_PRIORITY, 2578 1, 2579 FALSE); 2580 2581 if (IsCheckIdle) 2582 { 2583 DPRINT_PNP("USBH_FdoPnP: call USBH_CheckIdleDeferred()\n"); 2584 USBH_CheckIdleDeferred(HubExtension); 2585 } 2586 2587 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_STATE_CHANGING; 2588 2589 return Status; 2590 } 2591 2592 NTSTATUS 2593 NTAPI 2594 USBH_PdoPnP(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2595 IN PIRP Irp, 2596 IN UCHAR Minor, 2597 OUT BOOLEAN * IsCompleteIrp) 2598 { 2599 NTSTATUS Status; 2600 PIO_STACK_LOCATION IoStack; 2601 PPNP_BUS_INFORMATION BusInfo; 2602 PDEVICE_CAPABILITIES DeviceCapabilities; 2603 USHORT Size; 2604 USHORT Version; 2605 PUSBHUB_FDO_EXTENSION HubExtension; 2606 PDEVICE_RELATIONS DeviceRelation; 2607 2608 DPRINT_PNP("USBH_PdoPnP: PortExtension - %p, Irp - %p, Minor - %X\n", 2609 PortExtension, 2610 Irp, 2611 Minor); 2612 2613 IoStack = IoGetCurrentIrpStackLocation(Irp); 2614 2615 *IsCompleteIrp = TRUE; 2616 2617 switch (Minor) 2618 { 2619 case IRP_MN_START_DEVICE: 2620 DPRINT_PNP("PDO IRP_MN_START_DEVICE\n"); 2621 return USBH_PdoStartDevice(PortExtension, Irp); 2622 2623 case IRP_MN_QUERY_REMOVE_DEVICE: 2624 DPRINT_PNP("PDO IRP_MN_QUERY_REMOVE_DEVICE\n"); 2625 return STATUS_SUCCESS; 2626 2627 case IRP_MN_REMOVE_DEVICE: 2628 DPRINT_PNP("PDO IRP_MN_REMOVE_DEVICE\n"); 2629 return USBH_PdoRemoveDevice(PortExtension, PortExtension->HubExtension); 2630 2631 case IRP_MN_CANCEL_REMOVE_DEVICE: 2632 DPRINT_PNP("PDO IRP_MN_CANCEL_REMOVE_DEVICE\n"); 2633 return STATUS_SUCCESS; 2634 2635 case IRP_MN_STOP_DEVICE: 2636 DPRINT_PNP("PDO IRP_MN_STOP_DEVICE\n"); 2637 return USBH_PdoStopDevice(PortExtension, Irp); 2638 2639 case IRP_MN_QUERY_STOP_DEVICE: 2640 DPRINT_PNP("PDO IRP_MN_QUERY_STOP_DEVICE\n"); 2641 return STATUS_SUCCESS; 2642 2643 case IRP_MN_CANCEL_STOP_DEVICE: 2644 DPRINT_PNP("PDO IRP_MN_CANCEL_STOP_DEVICE\n"); 2645 return STATUS_SUCCESS; 2646 2647 case IRP_MN_QUERY_DEVICE_RELATIONS: 2648 DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_RELATIONS\n"); 2649 2650 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 2651 { 2652 return Irp->IoStatus.Status; 2653 } 2654 2655 DeviceRelation = ExAllocatePoolWithTag(PagedPool, 2656 sizeof(DEVICE_RELATIONS), 2657 USB_HUB_TAG); 2658 2659 if (DeviceRelation) 2660 { 2661 RtlZeroMemory(DeviceRelation, sizeof(DEVICE_RELATIONS)); 2662 2663 DeviceRelation->Count = 1; 2664 DeviceRelation->Objects[0] = PortExtension->Common.SelfDevice; 2665 2666 ObReferenceObject(DeviceRelation->Objects[0]); 2667 2668 Status = STATUS_SUCCESS; 2669 } 2670 else 2671 { 2672 Status = STATUS_INSUFFICIENT_RESOURCES; 2673 } 2674 2675 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; 2676 break; 2677 2678 case IRP_MN_QUERY_INTERFACE: 2679 DPRINT_PNP("PDO IRP_MN_QUERY_INTERFACE\n"); 2680 2681 *IsCompleteIrp = 0; 2682 2683 if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType, 2684 &USB_BUS_INTERFACE_USBDI_GUID)) 2685 { 2686 IoStack->Parameters.QueryInterface.InterfaceSpecificData = PortExtension->DeviceHandle; 2687 } 2688 2689 HubExtension = PortExtension->HubExtension; 2690 2691 if (!HubExtension) 2692 { 2693 HubExtension = PortExtension->RootHubExtension; 2694 } 2695 2696 Status = USBH_PassIrp(HubExtension->RootHubPdo, Irp); 2697 break; 2698 2699 case IRP_MN_QUERY_CAPABILITIES: 2700 DPRINT_PNP("PDO IRP_MN_QUERY_CAPABILITIES\n"); 2701 2702 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 2703 2704 Size = DeviceCapabilities->Size; 2705 Version = DeviceCapabilities->Version; 2706 2707 RtlCopyMemory(DeviceCapabilities, 2708 &PortExtension->Capabilities, 2709 sizeof(DEVICE_CAPABILITIES)); 2710 2711 DeviceCapabilities->Size = Size; 2712 DeviceCapabilities->Version = Version; 2713 2714 /* All devices connected to a hub are removable */ 2715 DeviceCapabilities->Removable = 1; 2716 2717 Status = STATUS_SUCCESS; 2718 break; 2719 2720 case IRP_MN_QUERY_RESOURCES: 2721 DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCES\n"); 2722 Status = Irp->IoStatus.Status; 2723 break; 2724 2725 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 2726 DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 2727 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_ENUMERATED; 2728 2729 /* FIXME HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Enum\USB\ 2730 Vid_????&Pid_????\????????????\Device Parameters\ 2731 if (ExtPropDescSemaphore) 2732 */ 2733 2734 Status = STATUS_SUCCESS; 2735 break; 2736 2737 case IRP_MN_QUERY_DEVICE_TEXT: 2738 DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_TEXT\n"); 2739 return USBH_PdoQueryDeviceText(PortExtension, Irp); 2740 2741 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 2742 DPRINT_PNP("PDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 2743 Status = Irp->IoStatus.Status; 2744 break; 2745 2746 case IRP_MN_READ_CONFIG: 2747 DPRINT_PNP("PDO IRP_MN_READ_CONFIG\n"); 2748 DbgBreakPoint(); 2749 Status = Irp->IoStatus.Status; 2750 break; 2751 2752 case IRP_MN_WRITE_CONFIG: 2753 DPRINT_PNP("PDO IRP_MN_WRITE_CONFIG\n"); 2754 DbgBreakPoint(); 2755 Status = Irp->IoStatus.Status; 2756 break; 2757 2758 case IRP_MN_EJECT: 2759 DPRINT_PNP("PDO IRP_MN_EJECT\n"); 2760 DbgBreakPoint(); 2761 Status = Irp->IoStatus.Status; 2762 break; 2763 2764 case IRP_MN_SET_LOCK: 2765 DPRINT_PNP("PDO IRP_MN_SET_LOCK\n"); 2766 DbgBreakPoint(); 2767 Status = Irp->IoStatus.Status; 2768 break; 2769 2770 case IRP_MN_QUERY_ID: 2771 DPRINT_PNP("PDO IRP_MN_QUERY_ID\n"); 2772 return USBH_PdoQueryId(PortExtension, Irp); 2773 2774 case IRP_MN_QUERY_PNP_DEVICE_STATE: 2775 DPRINT_PNP("PDO IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 2776 if (PortExtension->PortPdoFlags & (USBHUB_PDO_FLAG_INSUFFICIENT_PWR | 2777 USBHUB_PDO_FLAG_OVERCURRENT_PORT | 2778 USBHUB_PDO_FLAG_PORT_RESTORE_FAIL | 2779 USBHUB_PDO_FLAG_INIT_PORT_FAILED)) 2780 { 2781 Irp->IoStatus.Information |= PNP_DEVICE_FAILED; 2782 } 2783 2784 Status = STATUS_SUCCESS; 2785 break; 2786 2787 case IRP_MN_QUERY_BUS_INFORMATION: 2788 DPRINT_PNP("PDO IRP_MN_QUERY_BUS_INFORMATION\n"); 2789 2790 BusInfo = ExAllocatePoolWithTag(PagedPool, 2791 sizeof(PNP_BUS_INFORMATION), 2792 USB_HUB_TAG); 2793 2794 if (!BusInfo) 2795 { 2796 return STATUS_INSUFFICIENT_RESOURCES; 2797 } 2798 2799 RtlZeroMemory(BusInfo, sizeof(PNP_BUS_INFORMATION)); 2800 2801 RtlCopyMemory(&BusInfo->BusTypeGuid, 2802 &GUID_BUS_TYPE_USB, 2803 sizeof(BusInfo->BusTypeGuid)); 2804 2805 BusInfo->LegacyBusType = PNPBus; 2806 BusInfo->BusNumber = 0; 2807 2808 Irp->IoStatus.Information = (ULONG_PTR)BusInfo; 2809 Status = STATUS_SUCCESS; 2810 break; 2811 2812 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 2813 DPRINT_PNP("PDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); 2814 DbgBreakPoint(); 2815 Status = Irp->IoStatus.Status; 2816 break; 2817 2818 case IRP_MN_SURPRISE_REMOVAL: 2819 DPRINT_PNP("PDO IRP_MN_SURPRISE_REMOVAL\n"); 2820 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE) 2821 { 2822 Status = USBH_SymbolicLink(PortExtension, NULL, FALSE); 2823 2824 if (NT_SUCCESS(Status)) 2825 { 2826 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE; 2827 } 2828 } 2829 2830 Status = STATUS_SUCCESS; 2831 break; 2832 2833 default: 2834 DPRINT_PNP("PDO unknown IRP_MN_???\n"); 2835 Status = Irp->IoStatus.Status; 2836 break; 2837 } 2838 2839 return Status; 2840 } 2841