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 DPRINT_ENUM("USBH_FdoQueryBusRelations: Skip enumeration\n"); 1067 goto RelationsWorker; 1068 } 1069 1070 InterlockedIncrement(&HubExtension->PendingRequestCount); 1071 1072 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore, 1073 Executive, 1074 KernelMode, 1075 FALSE, 1076 NULL); 1077 1078 NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts; 1079 DPRINT_ENUM("USBH_FdoQueryBusRelations: NumberPorts - %x\n", NumberPorts); 1080 1081 Length = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + 1082 NumberPorts * sizeof(PDEVICE_OBJECT); 1083 1084 if (Irp->IoStatus.Information) 1085 { 1086 DPRINT1("FIXME: leaking old bus relations\n"); 1087 } 1088 1089 DeviceRelations = ExAllocatePoolWithTag(NonPagedPool, Length, USB_HUB_TAG); 1090 1091 if (!DeviceRelations) 1092 { 1093 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED; 1094 1095 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 1096 LOW_REALTIME_PRIORITY, 1097 1, 1098 FALSE); 1099 1100 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1101 { 1102 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 1103 } 1104 1105 Status = STATUS_INSUFFICIENT_RESOURCES; 1106 goto RelationsWorker; 1107 } 1108 1109 RtlZeroMemory(DeviceRelations, Length); 1110 1111 DeviceRelations->Count = 0; 1112 1113 EnumStart: 1114 1115 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING) 1116 { 1117 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED; 1118 1119 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 1120 LOW_REALTIME_PRIORITY, 1121 1, 1122 FALSE); 1123 1124 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1125 { 1126 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 1127 } 1128 1129 Status = STATUS_SUCCESS; 1130 goto RelationsWorker; 1131 } 1132 1133 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_ENUM_POST_RECOVER; 1134 1135 for (Port = 1; Port <= NumberPorts; Port++) 1136 { 1137 PortData = &HubExtension->PortData[Port - 1]; 1138 1139 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 1140 { 1141 continue; 1142 } 1143 1144 Status = USBH_SyncGetPortStatus(HubExtension, 1145 Port, 1146 &PortData->PortStatus, 1147 sizeof(USB_PORT_STATUS_AND_CHANGE)); 1148 1149 if (!NT_SUCCESS(Status)) 1150 { 1151 DPRINT_ENUM("USBH_FdoQueryBusRelations: Status - %X\n", Status); 1152 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 1153 DeviceRelations->Count = 0; 1154 goto EnumStart; 1155 } 1156 1157 DPRINT_ENUM("USBH_FdoQueryBusRelations: Port - %x, ConnectStatus - %x\n", 1158 Port, 1159 PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus); 1160 1161 PdoDevice = PortData->DeviceObject; 1162 1163 if (PortData->DeviceObject) 1164 { 1165 PdoExtension = PdoDevice->DeviceExtension; 1166 1167 if (PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_OVERCURRENT_PORT) 1168 { 1169 PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus = 1; 1170 } 1171 } 1172 1173 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 1174 { 1175 DPRINT1("USBH_FdoQueryBusRelations: DbgBreakPoint() \n"); 1176 DbgBreakPoint(); 1177 } 1178 1179 if (!PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus) 1180 { 1181 if (PdoDevice) 1182 { 1183 PdoExtension = PdoDevice->DeviceExtension; 1184 1185 PdoExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DELETE_PENDING; 1186 PdoExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1187 1188 SerialNumber = InterlockedExchangePointer((PVOID)&PdoExtension->SerialNumber, 1189 NULL); 1190 1191 if (SerialNumber) 1192 { 1193 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG); 1194 } 1195 1196 DeviceHandle = InterlockedExchangePointer(&PdoExtension->DeviceHandle, 1197 NULL); 1198 1199 if (DeviceHandle) 1200 { 1201 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 1202 USBH_SyncDisablePort(HubExtension, Port); 1203 } 1204 } 1205 1206 PortData->DeviceObject = NULL; 1207 PortData->ConnectionStatus = NoDeviceConnected; 1208 continue; 1209 } 1210 1211 if (PdoDevice) 1212 { 1213 ObReferenceObject(PdoDevice); 1214 1215 PdoDevice->Flags |= DO_POWER_PAGABLE; 1216 PdoDevice->Flags &= ~DO_DEVICE_INITIALIZING; 1217 1218 DeviceRelations->Objects[DeviceRelations->Count++] = PdoDevice; 1219 1220 PdoExtension = PdoDevice->DeviceExtension; 1221 PdoExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_POWER_D1_OR_D2; 1222 1223 continue; 1224 } 1225 1226 USBH_Wait(100); 1227 1228 NtStatus = USBH_SyncResetPort(HubExtension, Port); 1229 1230 if (!NT_SUCCESS(NtStatus)) 1231 { 1232 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB) 1233 { 1234 PortData->DeviceObject = NULL; 1235 PortData->ConnectionStatus = NoDeviceConnected; 1236 continue; 1237 } 1238 } 1239 else 1240 { 1241 NtStatus = USBH_SyncGetPortStatus(HubExtension, 1242 Port, 1243 &PortData->PortStatus, 1244 sizeof(USB_PORT_STATUS_AND_CHANGE)); 1245 1246 UsbPortStatus = PortData->PortStatus.PortStatus; 1247 1248 if (NT_SUCCESS(NtStatus)) 1249 { 1250 ULONG ix = 0; 1251 1252 for (NtStatus = USBH_CreateDevice(HubExtension, Port, UsbPortStatus, ix); 1253 !NT_SUCCESS(NtStatus); 1254 NtStatus = USBH_CreateDevice(HubExtension, Port, UsbPortStatus, ix)) 1255 { 1256 USBH_Wait(500); 1257 1258 if (ix >= 2) 1259 { 1260 break; 1261 } 1262 1263 if (PortData->DeviceObject) 1264 { 1265 IoDeleteDevice(PortData->DeviceObject); 1266 PortData->DeviceObject = NULL; 1267 PortData->ConnectionStatus = NoDeviceConnected; 1268 } 1269 1270 USBH_SyncResetPort(HubExtension, Port); 1271 1272 ix++; 1273 } 1274 1275 if (NT_SUCCESS(NtStatus)) 1276 { 1277 PdoExtension = PortData->DeviceObject->DeviceExtension; 1278 1279 if (!(PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_LOW_SPEED) && 1280 !(PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_HIGH_SPEED) && 1281 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)) 1282 { 1283 DPRINT1("USBH_FdoQueryBusRelations: FIXME USBH_DeviceIs2xDualMode()\n"); 1284 1285 if (0)//USBH_DeviceIs2xDualMode(PdoExtension)) 1286 { 1287 PdoExtension->PortPdoFlags |= USBHUB_PDO_FLAG_HS_USB1_DUALMODE; 1288 } 1289 } 1290 1291 ObReferenceObject(PortData->DeviceObject); 1292 1293 DeviceRelations->Objects[DeviceRelations->Count] = PortData->DeviceObject; 1294 1295 PortData->DeviceObject->Flags |= DO_POWER_PAGABLE; 1296 PortData->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1297 1298 DeviceRelations->Count++; 1299 1300 PortData->ConnectionStatus = DeviceConnected; 1301 1302 continue; 1303 } 1304 } 1305 } 1306 1307 PortData->ConnectionStatus = DeviceFailedEnumeration; 1308 1309 if (NT_ERROR(USBH_SyncDisablePort(HubExtension, Port))) 1310 { 1311 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED; 1312 } 1313 1314 if (PortData->DeviceObject) 1315 { 1316 ObReferenceObject(PortData->DeviceObject); 1317 PortData->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1318 DeviceRelations->Objects[DeviceRelations->Count++] = PortData->DeviceObject; 1319 } 1320 } 1321 1322 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED; 1323 1324 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore, 1325 LOW_REALTIME_PRIORITY, 1326 1, 1327 FALSE); 1328 1329 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 1330 { 1331 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); 1332 } 1333 1334 RelationsWorker: 1335 1336 Irp->IoStatus.Status = Status; 1337 1338 if (!NT_SUCCESS(Status)) 1339 { 1340 //Irp->IoStatus.Information = 0; 1341 1342 if (DeviceRelations) 1343 { 1344 ExFreePoolWithTag(DeviceRelations, USB_HUB_TAG); 1345 } 1346 1347 USBH_CompleteIrp(Irp, Status); 1348 1349 return Status; 1350 } 1351 1352 KeAcquireSpinLock(&HubExtension->RelationsWorkerSpinLock, &OldIrql); 1353 1354 if (DeviceRelations && DeviceRelations->Count) 1355 { 1356 for (Port = 0; Port < DeviceRelations->Count; Port++) 1357 { 1358 PdoDevice = DeviceRelations->Objects[Port]; 1359 Entry = HubExtension->PdoList.Flink; 1360 1361 while (Entry != &HubExtension->PdoList) 1362 { 1363 pdoExtension = CONTAINING_RECORD(Entry, 1364 USBHUB_PORT_PDO_EXTENSION, 1365 PortLink); 1366 1367 if (pdoExtension == PdoDevice->DeviceExtension) 1368 { 1369 PdoExt(PdoDevice)->EnumFlags |= USBHUB_ENUM_FLAG_GHOST_DEVICE; 1370 goto PortNext; 1371 } 1372 1373 Entry = Entry->Flink; 1374 } 1375 1376 PdoExt(PdoDevice)->EnumFlags |= USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1377 1378 PortNext:; 1379 } 1380 1381 for (Port = 0; Port < DeviceRelations->Count; Port++) 1382 { 1383 PdoDevice = DeviceRelations->Objects[Port]; 1384 1385 if (PdoExt(PdoDevice)->EnumFlags & USBHUB_ENUM_FLAG_GHOST_DEVICE) 1386 { 1387 for (GhostPort = Port; 1388 GhostPort < DeviceRelations->Count; 1389 GhostPort++) 1390 { 1391 DeviceRelations->Objects[GhostPort] = 1392 DeviceRelations->Objects[GhostPort + 1]; 1393 } 1394 1395 ObDereferenceObject(PdoDevice); 1396 1397 DeviceRelations->Count--; 1398 1399 if (PdoExt(PdoDevice)->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) 1400 { 1401 PdoExt(PdoDevice)->EnumFlags &= ~USBHUB_ENUM_FLAG_GHOST_DEVICE; 1402 } 1403 } 1404 } 1405 } 1406 1407 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1408 1409 InitializeListHead(&GhostPdoList); 1410 PdoList = &HubExtension->PdoList; 1411 1412 while (!IsListEmpty(PdoList)) 1413 { 1414 Entry = RemoveHeadList(PdoList); 1415 1416 PdoExtension = CONTAINING_RECORD(Entry, 1417 USBHUB_PORT_PDO_EXTENSION, 1418 PortLink); 1419 1420 PdoExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1421 1422 if (PdoExtension->EnumFlags & USBHUB_ENUM_FLAG_GHOST_DEVICE) 1423 { 1424 InsertTailList(&GhostPdoList, &PdoExtension->PortLink); 1425 } 1426 } 1427 1428 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, OldIrql); 1429 1430 while (!IsListEmpty(&GhostPdoList)) 1431 { 1432 Entry = RemoveHeadList(&GhostPdoList); 1433 1434 PdoExtension = CONTAINING_RECORD(Entry, 1435 USBHUB_PORT_PDO_EXTENSION, 1436 PortLink); 1437 1438 IoDeleteDevice(PdoExtension->Common.SelfDevice); 1439 } 1440 1441 return USBH_PassIrp(HubExtension->LowerDevice, Irp); 1442 } 1443 1444 NTSTATUS 1445 NTAPI 1446 USBH_FdoStopDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 1447 IN PIRP Irp) 1448 { 1449 DPRINT1("USBH_FdoStopDevice: UNIMPLEMENTED. FIXME\n"); 1450 DbgBreakPoint(); 1451 return STATUS_SUCCESS; 1452 } 1453 1454 NTSTATUS 1455 NTAPI 1456 USBH_FdoRemoveDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 1457 IN PIRP Irp) 1458 { 1459 PUSB_HUB_DESCRIPTOR HubDescriptor; 1460 PUSBHUB_PORT_DATA PortData; 1461 USHORT NumPorts; 1462 USHORT ix; 1463 PDEVICE_OBJECT PortDevice; 1464 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 1465 NTSTATUS Status; 1466 1467 DPRINT("USBH_FdoRemoveDevice: HubExtension - %p\n", HubExtension); 1468 1469 HubDescriptor = HubExtension->HubDescriptor; 1470 1471 if (HubDescriptor && HubExtension->PortData) 1472 { 1473 NumPorts = HubDescriptor->bNumberOfPorts; 1474 1475 for (ix = 0; ix < NumPorts; ++ix) 1476 { 1477 PortData = HubExtension->PortData + ix; 1478 1479 PortDevice = PortData->DeviceObject; 1480 1481 if (PortDevice) 1482 { 1483 PortData->PortStatus.AsUlong32 = 0; 1484 PortData->DeviceObject = NULL; 1485 1486 PortExtension = PortDevice->DeviceExtension; 1487 PortExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1488 1489 USBH_PdoRemoveDevice(PortExtension, HubExtension); 1490 } 1491 } 1492 } 1493 1494 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 1495 { 1496 USBH_FdoCleanup(HubExtension); 1497 } 1498 1499 if (HubExtension->PortData) 1500 { 1501 ExFreePoolWithTag(HubExtension->PortData, USB_HUB_TAG); 1502 HubExtension->PortData = NULL; 1503 } 1504 1505 DPRINT1("USBH_FdoRemoveDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n"); 1506 1507 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 1508 1509 IoDetachDevice(HubExtension->LowerDevice); 1510 IoDeleteDevice(HubExtension->Common.SelfDevice); 1511 1512 return Status; 1513 } 1514 1515 VOID 1516 NTAPI 1517 USBH_FdoSurpriseRemoveDevice(IN PUSBHUB_FDO_EXTENSION HubExtension, 1518 IN PIRP Irp) 1519 { 1520 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 1521 PUSBHUB_PORT_DATA PortData; 1522 ULONG NumberPorts; 1523 ULONG Port; 1524 1525 DPRINT("USBH_FdoSurpriseRemoveDevice: HubExtension - %p, Irp - %p\n", 1526 HubExtension, 1527 Irp); 1528 1529 if (!HubExtension->PortData || 1530 !HubExtension->HubDescriptor) 1531 { 1532 return; 1533 } 1534 1535 PortData = HubExtension->PortData; 1536 NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts; 1537 1538 for (Port = 0; Port < NumberPorts; Port++) 1539 { 1540 if (PortData[Port].DeviceObject) 1541 { 1542 PortExtension = PdoExt(PortData[Port].DeviceObject); 1543 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DELETE_PENDING; 1544 PortExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT; 1545 1546 PortData[Port].DeviceObject = NULL; 1547 PortData[Port].ConnectionStatus = NoDeviceConnected; 1548 } 1549 } 1550 } 1551 1552 NTSTATUS 1553 NTAPI 1554 USBH_PdoQueryId(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 1555 IN PIRP Irp) 1556 { 1557 ULONG IdType; 1558 WCHAR Buffer[200]; 1559 PWCHAR EndBuffer; 1560 size_t Remaining = sizeof(Buffer); 1561 size_t Length; 1562 PWCHAR Id = NULL; 1563 NTSTATUS Status = STATUS_SUCCESS; 1564 PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; 1565 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; 1566 1567 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; 1568 DeviceDescriptor = &PortExtension->DeviceDescriptor; 1569 InterfaceDescriptor = &PortExtension->InterfaceDescriptor; 1570 1571 RtlZeroMemory(Buffer, sizeof(Buffer)); 1572 1573 switch (IdType) 1574 { 1575 case BusQueryDeviceID: 1576 DPRINT("USBH_PdoQueryId: BusQueryDeviceID\n"); 1577 1578 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1579 { 1580 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n"); 1581 RtlStringCbPrintfExW(Buffer, 1582 Remaining, 1583 NULL, 1584 &Remaining, 1585 0, 1586 L"USB\\Vid_0000&Pid_0000"); 1587 } 1588 else 1589 { 1590 RtlStringCbPrintfExW(Buffer, 1591 Remaining, 1592 NULL, 1593 &Remaining, 1594 0, 1595 L"USB\\Vid_%04x&Pid_%04x", 1596 DeviceDescriptor->idVendor, 1597 DeviceDescriptor->idProduct); 1598 } 1599 1600 Length = sizeof(Buffer) - (Remaining - sizeof(UNICODE_NULL)); 1601 1602 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1603 1604 if (!Id) 1605 { 1606 break; 1607 } 1608 1609 RtlCopyMemory(Id, Buffer, Length); 1610 DPRINT("USBH_PdoQueryId: BusQueryDeviceID - %S\n", Id); 1611 break; 1612 1613 case BusQueryHardwareIDs: 1614 DPRINT("USBH_PdoQueryId: BusQueryHardwareIDs\n"); 1615 1616 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1617 { 1618 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n"); 1619 1620 RtlStringCbPrintfExW(Buffer, 1621 Remaining, 1622 NULL, 1623 &Remaining, 1624 0, 1625 L"USB\\UNKNOWN"); 1626 } 1627 else 1628 { 1629 RtlStringCbPrintfExW(Buffer, 1630 Remaining, 1631 &EndBuffer, 1632 &Remaining, 1633 0, 1634 L"USB\\Vid_%04x&Pid_%04x&Rev_%04x", 1635 DeviceDescriptor->idVendor, 1636 DeviceDescriptor->idProduct, 1637 DeviceDescriptor->bcdDevice); 1638 1639 EndBuffer++; 1640 Remaining -= sizeof(UNICODE_NULL); 1641 1642 RtlStringCbPrintfExW(EndBuffer, 1643 Remaining, 1644 NULL, 1645 &Remaining, 1646 0, 1647 L"USB\\Vid_%04x&Pid_%04x", 1648 DeviceDescriptor->idVendor, 1649 DeviceDescriptor->idProduct); 1650 } 1651 1652 Length = sizeof(Buffer) - (Remaining - 2 * sizeof(UNICODE_NULL)); 1653 1654 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1655 1656 if (!Id) 1657 { 1658 break; 1659 } 1660 1661 RtlCopyMemory(Id, Buffer, Length); 1662 1663 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1664 { 1665 DPRINT("USBH_PdoQueryId: BusQueryHardwareID - %S\n", Id); 1666 } 1667 else 1668 { 1669 USBHUB_DumpingIDs(Id); 1670 } 1671 1672 break; 1673 1674 case BusQueryCompatibleIDs: 1675 DPRINT("USBH_PdoQueryId: BusQueryCompatibleIDs\n"); 1676 1677 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1678 { 1679 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n"); 1680 1681 RtlStringCbPrintfExW(Buffer, 1682 Remaining, 1683 NULL, 1684 &Remaining, 1685 0, 1686 L"USB\\UNKNOWN"); 1687 } 1688 else if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_MULTI_INTERFACE) 1689 { 1690 RtlStringCbPrintfExW(Buffer, 1691 Remaining, 1692 &EndBuffer, 1693 &Remaining, 1694 0, 1695 L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x", 1696 InterfaceDescriptor->bInterfaceClass, 1697 InterfaceDescriptor->bInterfaceSubClass, 1698 InterfaceDescriptor->bInterfaceProtocol); 1699 1700 EndBuffer++; 1701 Remaining -= sizeof(UNICODE_NULL); 1702 1703 RtlStringCbPrintfExW(EndBuffer, 1704 Remaining, 1705 &EndBuffer, 1706 &Remaining, 1707 0, 1708 L"USB\\DevClass_%02x&SubClass_%02x", 1709 InterfaceDescriptor->bInterfaceClass, 1710 InterfaceDescriptor->bInterfaceSubClass); 1711 1712 EndBuffer++; 1713 Remaining -= sizeof(UNICODE_NULL); 1714 1715 RtlStringCbPrintfExW(EndBuffer, 1716 Remaining, 1717 &EndBuffer, 1718 &Remaining, 1719 0, 1720 L"USB\\DevClass_%02x", 1721 InterfaceDescriptor->bInterfaceClass); 1722 1723 EndBuffer++; 1724 Remaining -= sizeof(UNICODE_NULL); 1725 1726 RtlStringCbPrintfExW(EndBuffer, 1727 Remaining, 1728 NULL, 1729 &Remaining, 1730 0, 1731 L"USB\\COMPOSITE"); 1732 } 1733 else 1734 { 1735 RtlStringCbPrintfExW(Buffer, 1736 Remaining, 1737 &EndBuffer, 1738 &Remaining, 1739 0, 1740 L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", 1741 InterfaceDescriptor->bInterfaceClass, 1742 InterfaceDescriptor->bInterfaceSubClass, 1743 InterfaceDescriptor->bInterfaceProtocol); 1744 1745 EndBuffer++; 1746 Remaining -= sizeof(UNICODE_NULL); 1747 1748 RtlStringCbPrintfExW(EndBuffer, 1749 Remaining, 1750 &EndBuffer, 1751 &Remaining, 1752 0, 1753 L"USB\\Class_%02x&SubClass_%02x", 1754 InterfaceDescriptor->bInterfaceClass, 1755 InterfaceDescriptor->bInterfaceSubClass); 1756 1757 EndBuffer++; 1758 Remaining -= sizeof(UNICODE_NULL); 1759 1760 RtlStringCbPrintfExW(EndBuffer, 1761 Remaining, 1762 NULL, 1763 &Remaining, 1764 0, 1765 L"USB\\Class_%02x", 1766 InterfaceDescriptor->bInterfaceClass); 1767 } 1768 1769 Length = sizeof(Buffer) - (Remaining - 2 * sizeof(UNICODE_NULL)); 1770 1771 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1772 1773 if (!Id) 1774 { 1775 break; 1776 } 1777 1778 RtlCopyMemory(Id, Buffer, Length); 1779 1780 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED) 1781 { 1782 DPRINT("USBH_PdoQueryId: BusQueryCompatibleID - %S\n", Id); 1783 } 1784 else 1785 { 1786 USBHUB_DumpingIDs(Id); 1787 } 1788 1789 break; 1790 1791 case BusQueryInstanceID: 1792 DPRINT("USBH_PdoQueryId: BusQueryInstanceID\n"); 1793 1794 if (PortExtension->SerialNumber) 1795 { 1796 Id = ExAllocatePoolWithTag(PagedPool, 1797 PortExtension->SN_DescriptorLength, 1798 USB_HUB_TAG); 1799 1800 if (Id) 1801 { 1802 RtlZeroMemory(Id, PortExtension->SN_DescriptorLength); 1803 1804 RtlCopyMemory(Id, 1805 PortExtension->SerialNumber, 1806 PortExtension->SN_DescriptorLength); 1807 } 1808 } 1809 else 1810 { 1811 Length = sizeof(PortExtension->InstanceID) + 1812 sizeof(UNICODE_NULL); 1813 1814 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1815 1816 if (Id) 1817 { 1818 RtlZeroMemory(Id, Length); 1819 1820 RtlCopyMemory(Id, 1821 PortExtension->InstanceID, 1822 sizeof(PortExtension->InstanceID)); 1823 } 1824 } 1825 1826 DPRINT("USBH_PdoQueryId: BusQueryInstanceID - %S\n", Id); 1827 break; 1828 1829 default: 1830 DPRINT1("USBH_PdoQueryId: unknown query id type 0x%lx\n", IdType); 1831 return Irp->IoStatus.Status; 1832 } 1833 1834 Irp->IoStatus.Information = (ULONG_PTR)Id; 1835 1836 if (!Id) 1837 { 1838 Status = STATUS_INSUFFICIENT_RESOURCES; 1839 } 1840 1841 return Status; 1842 } 1843 1844 NTSTATUS 1845 NTAPI 1846 USBH_PdoQueryDeviceText(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 1847 IN PIRP Irp) 1848 { 1849 PDEVICE_OBJECT DeviceObject; 1850 PIO_STACK_LOCATION IoStack; 1851 DEVICE_TEXT_TYPE DeviceTextType; 1852 USHORT LanguageId; 1853 USHORT DefaultId; 1854 PUSB_STRING_DESCRIPTOR Descriptor; 1855 PWCHAR DeviceText; 1856 UCHAR iProduct = 0; 1857 NTSTATUS Status; 1858 size_t NumSymbols; 1859 size_t Length; 1860 1861 DPRINT("USBH_PdoQueryDeviceText ... \n"); 1862 1863 DeviceObject = PortExtension->Common.SelfDevice; 1864 IoStack = IoGetCurrentIrpStackLocation(Irp); 1865 DeviceTextType = IoStack->Parameters.QueryDeviceText.DeviceTextType; 1866 1867 if (DeviceTextType != DeviceTextDescription && 1868 DeviceTextType != DeviceTextLocationInformation) 1869 { 1870 return Irp->IoStatus.Status; 1871 } 1872 1873 LanguageId = LANGIDFROMLCID(IoStack->Parameters.QueryDeviceText.LocaleId); 1874 DefaultId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 1875 1876 if (!LanguageId) 1877 { 1878 LanguageId = DefaultId; 1879 } 1880 1881 iProduct = PortExtension->DeviceDescriptor.iProduct; 1882 1883 if (PortExtension->DeviceHandle && iProduct && 1884 !PortExtension->IgnoringHwSerial && 1885 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)) 1886 { 1887 Descriptor = ExAllocatePoolWithTag(NonPagedPool, 1888 MAXIMUM_USB_STRING_LENGTH, 1889 USB_HUB_TAG); 1890 1891 if (Descriptor) 1892 { 1893 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH); 1894 1895 for (Status = USBH_CheckDeviceLanguage(DeviceObject, LanguageId); 1896 ; 1897 Status = USBH_CheckDeviceLanguage(DeviceObject, DefaultId)) 1898 { 1899 if (NT_SUCCESS(Status)) 1900 { 1901 Status = USBH_SyncGetStringDescriptor(DeviceObject, 1902 iProduct, 1903 LanguageId, 1904 Descriptor, 1905 MAXIMUM_USB_STRING_LENGTH, 1906 NULL, 1907 TRUE); 1908 1909 if (NT_SUCCESS(Status)) 1910 { 1911 break; 1912 } 1913 } 1914 1915 if (LanguageId == DefaultId) 1916 { 1917 goto Exit; 1918 } 1919 1920 LanguageId = DefaultId; 1921 } 1922 1923 if (Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR)) 1924 { 1925 Status = STATUS_UNSUCCESSFUL; 1926 } 1927 1928 if (NT_SUCCESS(Status)) 1929 { 1930 Length = Descriptor->bLength - 1931 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString); 1932 1933 DeviceText = ExAllocatePoolWithTag(PagedPool, 1934 Length + sizeof(UNICODE_NULL), 1935 USB_HUB_TAG); 1936 1937 if (DeviceText) 1938 { 1939 RtlZeroMemory(DeviceText, Length + sizeof(UNICODE_NULL)); 1940 1941 RtlCopyMemory(DeviceText, Descriptor->bString, Length); 1942 1943 Irp->IoStatus.Information = (ULONG_PTR)DeviceText; 1944 1945 DPRINT("USBH_PdoQueryDeviceText: Descriptor->bString - %S\n", 1946 DeviceText); 1947 } 1948 else 1949 { 1950 Status = STATUS_INSUFFICIENT_RESOURCES; 1951 } 1952 } 1953 1954 Exit: 1955 1956 ExFreePoolWithTag(Descriptor, USB_HUB_TAG); 1957 1958 if (NT_SUCCESS(Status)) 1959 { 1960 return Status; 1961 } 1962 } 1963 else 1964 { 1965 Status = STATUS_INSUFFICIENT_RESOURCES; 1966 } 1967 } 1968 else 1969 { 1970 Status = STATUS_NOT_SUPPORTED; 1971 } 1972 1973 if (!GenericUSBDeviceString) 1974 { 1975 return Status; 1976 } 1977 1978 NumSymbols = wcslen(GenericUSBDeviceString); 1979 Length = (NumSymbols + 1) * sizeof(WCHAR); 1980 1981 DeviceText = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG); 1982 1983 if (!DeviceText) 1984 { 1985 return STATUS_INSUFFICIENT_RESOURCES; 1986 } 1987 1988 RtlZeroMemory(DeviceText, Length); 1989 1990 RtlCopyMemory(DeviceText, 1991 GenericUSBDeviceString, 1992 NumSymbols * sizeof(WCHAR)); 1993 1994 Irp->IoStatus.Information = (ULONG_PTR)DeviceText; 1995 1996 return STATUS_SUCCESS; 1997 } 1998 1999 NTSTATUS 2000 NTAPI 2001 USBH_SymbolicLink(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2002 IN const GUID * InterfaceClassGuid, 2003 IN BOOLEAN IsEnable) 2004 { 2005 NTSTATUS Status = STATUS_SUCCESS; 2006 PVOID NameBuffer; 2007 2008 DPRINT("USBH_SymbolicLink ... \n"); 2009 2010 if (IsEnable) 2011 { 2012 Status = IoRegisterDeviceInterface(PortExtension->Common.SelfDevice, 2013 InterfaceClassGuid, 2014 NULL, 2015 &PortExtension->SymbolicLinkName); 2016 2017 if (NT_SUCCESS(Status)) 2018 { 2019 USBH_SetPdoRegistryParameter(PortExtension->Common.SelfDevice, 2020 L"SymbolicName", 2021 PortExtension->SymbolicLinkName.Buffer, 2022 PortExtension->SymbolicLinkName.Length, 2023 REG_SZ, 2024 PLUGPLAY_REGKEY_DEVICE); 2025 2026 Status = IoSetDeviceInterfaceState(&PortExtension->SymbolicLinkName, 2027 TRUE); 2028 } 2029 } 2030 else 2031 { 2032 NameBuffer = PortExtension->SymbolicLinkName.Buffer; 2033 2034 if (NameBuffer) 2035 { 2036 Status = IoSetDeviceInterfaceState(&PortExtension->SymbolicLinkName, 2037 FALSE); 2038 2039 ExFreePool(PortExtension->SymbolicLinkName.Buffer); 2040 2041 PortExtension->SymbolicLinkName.Buffer = NULL; 2042 } 2043 } 2044 2045 return Status; 2046 } 2047 2048 NTSTATUS 2049 NTAPI 2050 USBH_RestoreDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2051 IN BOOLEAN IsKeepDeviceData) 2052 { 2053 PUSBHUB_FDO_EXTENSION HubExtension; 2054 PUSBHUB_PORT_DATA PortData; 2055 NTSTATUS Status; 2056 ULONG ix; 2057 2058 DPRINT("USBH_RestoreDevice ... \n"); 2059 2060 HubExtension = PortExtension->HubExtension; 2061 2062 if (!HubExtension) 2063 { 2064 Status = STATUS_UNSUCCESSFUL; 2065 return Status; 2066 } 2067 2068 ASSERT(PortExtension->PortNumber > 0); 2069 PortData = &HubExtension->PortData[PortExtension->PortNumber - 1]; 2070 2071 if (PortExtension->Common.SelfDevice != PortData->DeviceObject) 2072 { 2073 Status = STATUS_UNSUCCESSFUL; 2074 return Status; 2075 } 2076 2077 Status = USBH_SyncGetPortStatus(HubExtension, 2078 PortExtension->PortNumber, 2079 &PortData->PortStatus, 2080 sizeof(USB_PORT_STATUS_AND_CHANGE)); 2081 2082 if (NT_SUCCESS(Status)) 2083 { 2084 for (ix = 0; ix < 3; ix++) 2085 { 2086 Status = USBH_ResetDevice((PUSBHUB_FDO_EXTENSION)HubExtension, 2087 PortExtension->PortNumber, 2088 IsKeepDeviceData, 2089 ix == 0); 2090 2091 if (NT_SUCCESS(Status) || Status == STATUS_NO_SUCH_DEVICE) 2092 { 2093 break; 2094 } 2095 2096 USBH_Wait(1000); 2097 } 2098 } 2099 2100 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_POWER_D3; 2101 2102 if (NT_SUCCESS(Status)) 2103 { 2104 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESTORE_FAIL; 2105 } 2106 else 2107 { 2108 PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_INIT_PORT_FAILED | 2109 USBHUB_PDO_FLAG_PORT_RESTORE_FAIL); 2110 } 2111 2112 return Status; 2113 } 2114 2115 NTSTATUS 2116 NTAPI 2117 USBH_PdoStartDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2118 IN PIRP Irp) 2119 { 2120 PUSBHUB_FDO_EXTENSION HubExtension; 2121 const GUID * Guid; 2122 NTSTATUS Status; 2123 2124 DPRINT("USBH_PdoStartDevice: PortExtension - %p\n", PortExtension); 2125 2126 if (!PortExtension->HubExtension && 2127 PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3) 2128 { 2129 PortExtension->HubExtension = PortExtension->RootHubExtension; 2130 } 2131 2132 HubExtension = PortExtension->HubExtension; 2133 2134 if (HubExtension) 2135 { 2136 USBHUB_SetDeviceHandleData(HubExtension, 2137 PortExtension->Common.SelfDevice, 2138 PortExtension->DeviceHandle); 2139 } 2140 2141 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE) 2142 { 2143 Guid = &GUID_DEVINTERFACE_USB_HUB; 2144 } 2145 else 2146 { 2147 Guid = &GUID_DEVINTERFACE_USB_DEVICE; 2148 } 2149 2150 Status = USBH_SymbolicLink(PortExtension, Guid, TRUE); 2151 2152 if (NT_SUCCESS(Status)) 2153 { 2154 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REG_DEV_INTERFACE; 2155 } 2156 2157 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3) 2158 { 2159 Status = USBH_RestoreDevice(PortExtension, 0); 2160 } 2161 2162 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DEVICE_STARTED; 2163 2164 PortExtension->CurrentPowerState.DeviceState = PowerDeviceD0; 2165 2166 DPRINT1("USBH_PdoStartDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n"); 2167 2168 return Status; 2169 } 2170 2171 NTSTATUS 2172 NTAPI 2173 USBH_PdoRemoveDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2174 IN PUSBHUB_FDO_EXTENSION HubExtension) 2175 { 2176 NTSTATUS Status = STATUS_SUCCESS; 2177 PDEVICE_OBJECT PortDevice; 2178 PUSBHUB_PORT_PDO_EXTENSION PortExt; 2179 PUSBHUB_PORT_DATA PortData; 2180 PIRP IdleNotificationIrp; 2181 PIRP WakeIrp; 2182 PVOID DeviceHandle; 2183 PDEVICE_OBJECT Pdo; 2184 PVOID SerialNumber; 2185 USHORT Port; 2186 KIRQL Irql; 2187 2188 DPRINT("USBH_PdoRemoveDevice ... \n"); 2189 2190 PortDevice = PortExtension->Common.SelfDevice; 2191 PortExtension->HubExtension = NULL; 2192 2193 Port = PortExtension->PortNumber; 2194 ASSERT(Port > 0); 2195 2196 if (HubExtension && 2197 HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 && 2198 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) != 0) 2199 { 2200 USBH_HubSetD0(HubExtension); 2201 } 2202 2203 IoAcquireCancelSpinLock(&Irql); 2204 IdleNotificationIrp = PortExtension->IdleNotificationIrp; 2205 2206 if (IdleNotificationIrp) 2207 { 2208 PortExtension->IdleNotificationIrp = NULL; 2209 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION; 2210 2211 if (IdleNotificationIrp->Cancel) 2212 { 2213 IdleNotificationIrp = NULL; 2214 } 2215 2216 if (IdleNotificationIrp) 2217 { 2218 IoSetCancelRoutine(IdleNotificationIrp, NULL); 2219 } 2220 } 2221 2222 WakeIrp = PortExtension->PdoWaitWakeIrp; 2223 2224 if (WakeIrp) 2225 { 2226 PortExtension->PdoWaitWakeIrp = NULL; 2227 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_WAIT_WAKE; 2228 2229 if (WakeIrp->Cancel || !IoSetCancelRoutine(WakeIrp, NULL)) 2230 { 2231 WakeIrp = NULL; 2232 2233 ASSERT(HubExtension); 2234 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 2235 { 2236 KeSetEvent(&HubExtension->PendingRequestEvent, 2237 EVENT_INCREMENT, 2238 FALSE); 2239 } 2240 } 2241 } 2242 2243 IoReleaseCancelSpinLock(Irql); 2244 2245 if (IdleNotificationIrp) 2246 { 2247 IdleNotificationIrp->IoStatus.Status = STATUS_CANCELLED; 2248 IoCompleteRequest(IdleNotificationIrp, IO_NO_INCREMENT); 2249 } 2250 2251 if (WakeIrp) 2252 { 2253 ASSERT(HubExtension); 2254 USBH_CompletePowerIrp(HubExtension, WakeIrp, STATUS_CANCELLED); 2255 } 2256 2257 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_POWER_D3; 2258 2259 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE) 2260 { 2261 Status = USBH_SymbolicLink(PortExtension, NULL, FALSE); 2262 2263 if (NT_SUCCESS(Status)) 2264 { 2265 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE; 2266 } 2267 } 2268 2269 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle, 2270 NULL); 2271 2272 if (DeviceHandle) 2273 { 2274 ASSERT(HubExtension); 2275 Status = USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0); 2276 2277 if (HubExtension->PortData && 2278 HubExtension->PortData[Port - 1].DeviceObject == PortDevice) 2279 { 2280 USBH_SyncDisablePort(HubExtension, Port); 2281 } 2282 } 2283 2284 if (NT_SUCCESS(Status)) 2285 { 2286 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_DEVICE_STARTED; 2287 2288 if (HubExtension && HubExtension->PortData) 2289 { 2290 PortData = &HubExtension->PortData[Port - 1]; 2291 2292 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DELETE_PENDING) 2293 { 2294 Pdo = PortData->DeviceObject; 2295 2296 if (Pdo) 2297 { 2298 PortData->DeviceObject = NULL; 2299 PortData->ConnectionStatus = NoDeviceConnected; 2300 2301 if (PdoExt(Pdo)->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) 2302 { 2303 PortExt = PdoExt(Pdo); 2304 2305 InsertTailList(&HubExtension->PdoList, 2306 &PortExt->PortLink); 2307 } 2308 } 2309 } 2310 } 2311 2312 if (!(PortExtension->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) && 2313 !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_NOT_CONNECTED)) 2314 { 2315 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_NOT_CONNECTED; 2316 2317 SerialNumber = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, 2318 NULL); 2319 2320 if (SerialNumber) 2321 { 2322 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG); 2323 } 2324 2325 DPRINT1("USBH_PdoRemoveDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n"); 2326 2327 if (HubExtension) 2328 USBHUB_FlushAllTransfers(HubExtension); 2329 2330 IoDeleteDevice(PortDevice); 2331 } 2332 } 2333 2334 if (HubExtension) 2335 { 2336 DPRINT("USBH_PdoRemoveDevice: call USBH_CheckIdleDeferred()\n"); 2337 USBH_CheckIdleDeferred(HubExtension); 2338 } 2339 2340 return Status; 2341 } 2342 2343 NTSTATUS 2344 NTAPI 2345 USBH_PdoStopDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2346 IN PIRP Irp) 2347 { 2348 DPRINT1("USBH_PdoStopDevice: UNIMPLEMENTED. FIXME\n"); 2349 DbgBreakPoint(); 2350 return STATUS_SUCCESS; 2351 } 2352 2353 NTSTATUS 2354 NTAPI 2355 USBH_FdoPnP(IN PUSBHUB_FDO_EXTENSION HubExtension, 2356 IN PIRP Irp, 2357 IN UCHAR Minor) 2358 { 2359 NTSTATUS Status; 2360 PIO_STACK_LOCATION IoStack; 2361 DEVICE_RELATION_TYPE RelationsType; 2362 BOOLEAN IsCheckIdle; 2363 2364 DPRINT_PNP("USBH_FdoPnP: HubExtension - %p, Irp - %p, Minor - %X\n", 2365 HubExtension, 2366 Irp, 2367 Minor); 2368 2369 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST && 2370 (Minor == IRP_MN_REMOVE_DEVICE || Minor == IRP_MN_STOP_DEVICE)) 2371 { 2372 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_SUSPENDED; 2373 } 2374 2375 KeWaitForSingleObject(&HubExtension->IdleSemaphore, 2376 Executive, 2377 KernelMode, 2378 FALSE, 2379 NULL); 2380 2381 DPRINT_PNP("USBH_FdoPnP: HubFlags - %lX\n", HubExtension->HubFlags); 2382 2383 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_GOING_IDLE) 2384 { 2385 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_SUSPENDED; 2386 } 2387 2388 IoStack = IoGetCurrentIrpStackLocation(Irp); 2389 RelationsType = IoStack->Parameters.QueryDeviceRelations.Type; 2390 2391 if ((HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0) || 2392 !(HubExtension->HubFlags & (USBHUB_FDO_FLAG_DEVICE_STOPPED | USBHUB_FDO_FLAG_DEVICE_STARTED)) || 2393 (Minor == IRP_MN_QUERY_DEVICE_RELATIONS && RelationsType == TargetDeviceRelation)) 2394 { 2395 IsCheckIdle = FALSE; 2396 } 2397 else 2398 { 2399 DPRINT_PNP("USBH_FdoPnP: IsCheckIdle - TRUE\n"); 2400 IsCheckIdle = TRUE; 2401 USBH_HubSetD0(HubExtension); 2402 } 2403 2404 switch (Minor) 2405 { 2406 case IRP_MN_START_DEVICE: 2407 DPRINT_PNP("FDO IRP_MN_START_DEVICE\n"); 2408 IsCheckIdle = FALSE; 2409 Irp->IoStatus.Status = STATUS_SUCCESS; 2410 Status = USBH_FdoStartDevice(HubExtension, Irp); 2411 break; 2412 2413 case IRP_MN_QUERY_REMOVE_DEVICE: 2414 DPRINT_PNP("FDO IRP_MN_QUERY_REMOVE_DEVICE\n"); 2415 Irp->IoStatus.Status = STATUS_SUCCESS; 2416 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2417 break; 2418 2419 case IRP_MN_REMOVE_DEVICE: 2420 DPRINT_PNP("FDO IRP_MN_REMOVE_DEVICE\n"); 2421 IsCheckIdle = FALSE; 2422 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_REMOVED; 2423 Irp->IoStatus.Status = STATUS_SUCCESS; 2424 Status = USBH_FdoRemoveDevice(HubExtension, Irp); 2425 break; 2426 2427 case IRP_MN_CANCEL_REMOVE_DEVICE: 2428 DPRINT_PNP("FDO IRP_MN_CANCEL_REMOVE_DEVICE\n"); 2429 Irp->IoStatus.Status = STATUS_SUCCESS; 2430 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2431 break; 2432 2433 case IRP_MN_STOP_DEVICE: 2434 DPRINT_PNP("FDO IRP_MN_STOP_DEVICE\n"); 2435 IsCheckIdle = FALSE; 2436 Irp->IoStatus.Status = STATUS_SUCCESS; 2437 Status = USBH_FdoStopDevice(HubExtension, Irp); 2438 break; 2439 2440 case IRP_MN_QUERY_STOP_DEVICE: 2441 DPRINT_PNP("FDO IRP_MN_QUERY_STOP_DEVICE\n"); 2442 Irp->IoStatus.Status = STATUS_SUCCESS; 2443 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2444 break; 2445 2446 case IRP_MN_CANCEL_STOP_DEVICE: 2447 DPRINT_PNP("FDO IRP_MN_CANCEL_STOP_DEVICE\n"); 2448 Irp->IoStatus.Status = STATUS_SUCCESS; 2449 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2450 break; 2451 2452 case IRP_MN_QUERY_DEVICE_RELATIONS: 2453 DPRINT_PNP("FDO IRP_MN_QUERY_DEVICE_RELATIONS\n"); 2454 2455 if (RelationsType != BusRelations) 2456 { 2457 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2458 break; 2459 } 2460 2461 HubExtension->HubFlags |= USBHUB_FDO_FLAG_HUB_BUSY; 2462 2463 IsCheckIdle = TRUE; 2464 DPRINT_PNP("USBH_FdoPnP: IsCheckIdle - TRUE\n"); 2465 2466 Status = USBH_FdoQueryBusRelations(HubExtension, Irp); 2467 2468 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_HUB_BUSY; 2469 break; 2470 2471 case IRP_MN_QUERY_INTERFACE: 2472 DPRINT_PNP("FDO IRP_MN_QUERY_INTERFACE\n"); 2473 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2474 break; 2475 2476 case IRP_MN_QUERY_CAPABILITIES: 2477 DPRINT_PNP("FDO IRP_MN_QUERY_CAPABILITIES\n"); 2478 IoCopyCurrentIrpStackLocationToNext(Irp); 2479 2480 IoSetCompletionRoutine(Irp, 2481 USBH_QueryCapsComplete, 2482 HubExtension, 2483 TRUE, 2484 FALSE, 2485 FALSE); 2486 2487 Status = IoCallDriver(HubExtension->LowerDevice, Irp); 2488 break; 2489 2490 case IRP_MN_QUERY_RESOURCES: 2491 DPRINT_PNP("FDO IRP_MN_QUERY_RESOURCES\n"); 2492 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2493 break; 2494 2495 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 2496 DPRINT_PNP("FDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 2497 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2498 break; 2499 2500 case IRP_MN_QUERY_DEVICE_TEXT: 2501 DPRINT_PNP("FDO IRP_MN_QUERY_DEVICE_TEXT\n"); 2502 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2503 break; 2504 2505 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 2506 DPRINT_PNP("FDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 2507 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2508 break; 2509 2510 case IRP_MN_READ_CONFIG: 2511 DPRINT_PNP("FDO IRP_MN_READ_CONFIG\n"); 2512 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2513 break; 2514 2515 case IRP_MN_WRITE_CONFIG: 2516 DPRINT_PNP("FDO IRP_MN_WRITE_CONFIG\n"); 2517 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2518 break; 2519 2520 case IRP_MN_EJECT: 2521 DPRINT_PNP("FDO IRP_MN_EJECT\n"); 2522 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2523 break; 2524 2525 case IRP_MN_SET_LOCK: 2526 DPRINT_PNP("FDO IRP_MN_SET_LOCK\n"); 2527 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2528 break; 2529 2530 case IRP_MN_QUERY_ID: 2531 DPRINT_PNP("FDO IRP_MN_QUERY_ID\n"); 2532 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2533 break; 2534 2535 case IRP_MN_QUERY_PNP_DEVICE_STATE: 2536 DPRINT_PNP("FDO IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 2537 2538 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) 2539 { 2540 Irp->IoStatus.Information |= PNP_DEVICE_FAILED; 2541 } 2542 2543 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2544 break; 2545 2546 case IRP_MN_QUERY_BUS_INFORMATION: 2547 DPRINT_PNP("FDO IRP_MN_QUERY_BUS_INFORMATION\n"); 2548 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2549 break; 2550 2551 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 2552 DPRINT_PNP("FDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); 2553 Irp->IoStatus.Status = STATUS_SUCCESS; 2554 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2555 break; 2556 2557 case IRP_MN_SURPRISE_REMOVAL: 2558 DPRINT_PNP("FDO IRP_MN_SURPRISE_REMOVAL\n"); 2559 USBH_FdoSurpriseRemoveDevice(HubExtension, Irp); 2560 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2561 break; 2562 2563 default: 2564 DPRINT_PNP("FDO unknown IRP_MN_???\n"); 2565 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp); 2566 break; 2567 } 2568 2569 KeReleaseSemaphore(&HubExtension->IdleSemaphore, 2570 LOW_REALTIME_PRIORITY, 2571 1, 2572 FALSE); 2573 2574 if (IsCheckIdle) 2575 { 2576 DPRINT_PNP("USBH_FdoPnP: call USBH_CheckIdleDeferred()\n"); 2577 USBH_CheckIdleDeferred(HubExtension); 2578 } 2579 2580 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_STATE_CHANGING; 2581 2582 return Status; 2583 } 2584 2585 NTSTATUS 2586 NTAPI 2587 USBH_PdoPnP(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 2588 IN PIRP Irp, 2589 IN UCHAR Minor, 2590 OUT BOOLEAN * IsCompleteIrp) 2591 { 2592 NTSTATUS Status; 2593 PIO_STACK_LOCATION IoStack; 2594 PPNP_BUS_INFORMATION BusInfo; 2595 PDEVICE_CAPABILITIES DeviceCapabilities; 2596 USHORT Size; 2597 USHORT Version; 2598 PUSBHUB_FDO_EXTENSION HubExtension; 2599 PDEVICE_RELATIONS DeviceRelation; 2600 2601 DPRINT_PNP("USBH_PdoPnP: PortExtension - %p, Irp - %p, Minor - %X\n", 2602 PortExtension, 2603 Irp, 2604 Minor); 2605 2606 IoStack = IoGetCurrentIrpStackLocation(Irp); 2607 2608 *IsCompleteIrp = TRUE; 2609 2610 switch (Minor) 2611 { 2612 case IRP_MN_START_DEVICE: 2613 DPRINT_PNP("PDO IRP_MN_START_DEVICE\n"); 2614 return USBH_PdoStartDevice(PortExtension, Irp); 2615 2616 case IRP_MN_QUERY_REMOVE_DEVICE: 2617 DPRINT_PNP("PDO IRP_MN_QUERY_REMOVE_DEVICE\n"); 2618 return STATUS_SUCCESS; 2619 2620 case IRP_MN_REMOVE_DEVICE: 2621 DPRINT_PNP("PDO IRP_MN_REMOVE_DEVICE\n"); 2622 return USBH_PdoRemoveDevice(PortExtension, PortExtension->HubExtension); 2623 2624 case IRP_MN_CANCEL_REMOVE_DEVICE: 2625 DPRINT_PNP("PDO IRP_MN_CANCEL_REMOVE_DEVICE\n"); 2626 return STATUS_SUCCESS; 2627 2628 case IRP_MN_STOP_DEVICE: 2629 DPRINT_PNP("PDO IRP_MN_STOP_DEVICE\n"); 2630 return USBH_PdoStopDevice(PortExtension, Irp); 2631 2632 case IRP_MN_QUERY_STOP_DEVICE: 2633 DPRINT_PNP("PDO IRP_MN_QUERY_STOP_DEVICE\n"); 2634 return STATUS_SUCCESS; 2635 2636 case IRP_MN_CANCEL_STOP_DEVICE: 2637 DPRINT_PNP("PDO IRP_MN_CANCEL_STOP_DEVICE\n"); 2638 return STATUS_SUCCESS; 2639 2640 case IRP_MN_QUERY_DEVICE_RELATIONS: 2641 DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_RELATIONS\n"); 2642 2643 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 2644 { 2645 return Irp->IoStatus.Status; 2646 } 2647 2648 DeviceRelation = ExAllocatePoolWithTag(PagedPool, 2649 sizeof(DEVICE_RELATIONS), 2650 USB_HUB_TAG); 2651 2652 if (DeviceRelation) 2653 { 2654 RtlZeroMemory(DeviceRelation, sizeof(DEVICE_RELATIONS)); 2655 2656 DeviceRelation->Count = 1; 2657 DeviceRelation->Objects[0] = PortExtension->Common.SelfDevice; 2658 2659 ObReferenceObject(DeviceRelation->Objects[0]); 2660 2661 Status = STATUS_SUCCESS; 2662 } 2663 else 2664 { 2665 Status = STATUS_INSUFFICIENT_RESOURCES; 2666 } 2667 2668 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; 2669 break; 2670 2671 case IRP_MN_QUERY_INTERFACE: 2672 DPRINT_PNP("PDO IRP_MN_QUERY_INTERFACE\n"); 2673 2674 *IsCompleteIrp = 0; 2675 2676 if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType, 2677 &USB_BUS_INTERFACE_USBDI_GUID)) 2678 { 2679 IoStack->Parameters.QueryInterface.InterfaceSpecificData = PortExtension->DeviceHandle; 2680 } 2681 2682 HubExtension = PortExtension->HubExtension; 2683 2684 if (!HubExtension) 2685 { 2686 HubExtension = PortExtension->RootHubExtension; 2687 } 2688 2689 Status = USBH_PassIrp(HubExtension->RootHubPdo, Irp); 2690 break; 2691 2692 case IRP_MN_QUERY_CAPABILITIES: 2693 DPRINT_PNP("PDO IRP_MN_QUERY_CAPABILITIES\n"); 2694 2695 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 2696 2697 Size = DeviceCapabilities->Size; 2698 Version = DeviceCapabilities->Version; 2699 2700 RtlCopyMemory(DeviceCapabilities, 2701 &PortExtension->Capabilities, 2702 sizeof(DEVICE_CAPABILITIES)); 2703 2704 DeviceCapabilities->Size = Size; 2705 DeviceCapabilities->Version = Version; 2706 2707 /* All devices connected to a hub are removable */ 2708 DeviceCapabilities->Removable = 1; 2709 2710 Status = STATUS_SUCCESS; 2711 break; 2712 2713 case IRP_MN_QUERY_RESOURCES: 2714 DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCES\n"); 2715 Status = Irp->IoStatus.Status; 2716 break; 2717 2718 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 2719 DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 2720 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_ENUMERATED; 2721 2722 /* FIXME HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Enum\USB\ 2723 Vid_????&Pid_????\????????????\Device Parameters\ 2724 if (ExtPropDescSemaphore) 2725 */ 2726 2727 Status = STATUS_SUCCESS; 2728 break; 2729 2730 case IRP_MN_QUERY_DEVICE_TEXT: 2731 DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_TEXT\n"); 2732 return USBH_PdoQueryDeviceText(PortExtension, Irp); 2733 2734 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 2735 DPRINT_PNP("PDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 2736 Status = Irp->IoStatus.Status; 2737 break; 2738 2739 case IRP_MN_READ_CONFIG: 2740 DPRINT_PNP("PDO IRP_MN_READ_CONFIG\n"); 2741 DbgBreakPoint(); 2742 Status = Irp->IoStatus.Status; 2743 break; 2744 2745 case IRP_MN_WRITE_CONFIG: 2746 DPRINT_PNP("PDO IRP_MN_WRITE_CONFIG\n"); 2747 DbgBreakPoint(); 2748 Status = Irp->IoStatus.Status; 2749 break; 2750 2751 case IRP_MN_EJECT: 2752 DPRINT_PNP("PDO IRP_MN_EJECT\n"); 2753 DbgBreakPoint(); 2754 Status = Irp->IoStatus.Status; 2755 break; 2756 2757 case IRP_MN_SET_LOCK: 2758 DPRINT_PNP("PDO IRP_MN_SET_LOCK\n"); 2759 DbgBreakPoint(); 2760 Status = Irp->IoStatus.Status; 2761 break; 2762 2763 case IRP_MN_QUERY_ID: 2764 DPRINT_PNP("PDO IRP_MN_QUERY_ID\n"); 2765 return USBH_PdoQueryId(PortExtension, Irp); 2766 2767 case IRP_MN_QUERY_PNP_DEVICE_STATE: 2768 DPRINT_PNP("PDO IRP_MN_QUERY_PNP_DEVICE_STATE\n"); 2769 if (PortExtension->PortPdoFlags & (USBHUB_PDO_FLAG_INSUFFICIENT_PWR | 2770 USBHUB_PDO_FLAG_OVERCURRENT_PORT | 2771 USBHUB_PDO_FLAG_PORT_RESTORE_FAIL | 2772 USBHUB_PDO_FLAG_INIT_PORT_FAILED)) 2773 { 2774 Irp->IoStatus.Information |= PNP_DEVICE_FAILED; 2775 } 2776 2777 Status = STATUS_SUCCESS; 2778 break; 2779 2780 case IRP_MN_QUERY_BUS_INFORMATION: 2781 DPRINT_PNP("PDO IRP_MN_QUERY_BUS_INFORMATION\n"); 2782 2783 BusInfo = ExAllocatePoolWithTag(PagedPool, 2784 sizeof(PNP_BUS_INFORMATION), 2785 USB_HUB_TAG); 2786 2787 if (!BusInfo) 2788 { 2789 return STATUS_INSUFFICIENT_RESOURCES; 2790 } 2791 2792 RtlZeroMemory(BusInfo, sizeof(PNP_BUS_INFORMATION)); 2793 2794 RtlCopyMemory(&BusInfo->BusTypeGuid, 2795 &GUID_BUS_TYPE_USB, 2796 sizeof(BusInfo->BusTypeGuid)); 2797 2798 BusInfo->LegacyBusType = PNPBus; 2799 BusInfo->BusNumber = 0; 2800 2801 Irp->IoStatus.Information = (ULONG_PTR)BusInfo; 2802 Status = STATUS_SUCCESS; 2803 break; 2804 2805 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 2806 DPRINT_PNP("PDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n"); 2807 DbgBreakPoint(); 2808 Status = Irp->IoStatus.Status; 2809 break; 2810 2811 case IRP_MN_SURPRISE_REMOVAL: 2812 DPRINT_PNP("PDO IRP_MN_SURPRISE_REMOVAL\n"); 2813 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE) 2814 { 2815 Status = USBH_SymbolicLink(PortExtension, NULL, FALSE); 2816 2817 if (NT_SUCCESS(Status)) 2818 { 2819 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE; 2820 } 2821 } 2822 2823 Status = STATUS_SUCCESS; 2824 break; 2825 2826 default: 2827 DPRINT_PNP("PDO unknown IRP_MN_???\n"); 2828 Status = Irp->IoStatus.Status; 2829 break; 2830 } 2831 2832 return Status; 2833 } 2834