1 /* 2 * PROJECT: ReactOS USB Hub Driver 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: USBHub power handling 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_POWER 14 #include "dbg_uhub.h" 15 16 VOID 17 NTAPI 18 USBH_CompletePowerIrp(IN PUSBHUB_FDO_EXTENSION HubExtension, 19 IN PIRP Irp, 20 IN NTSTATUS NtStatus) 21 { 22 DPRINT("USBH_CompletePowerIrp: HubExtension - %p, Irp - %p, NtStatus - %lX\n", 23 HubExtension, 24 Irp, 25 NtStatus); 26 27 Irp->IoStatus.Status = NtStatus; 28 29 PoStartNextPowerIrp(Irp); 30 31 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 32 { 33 KeSetEvent(&HubExtension->PendingRequestEvent, 34 EVENT_INCREMENT, 35 FALSE); 36 } 37 38 IoCompleteRequest(Irp, IO_NO_INCREMENT); 39 } 40 41 VOID 42 NTAPI 43 USBH_HubCancelWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension, 44 IN PIRP Irp) 45 { 46 DPRINT("USBH_HubCancelWakeIrp: HubExtension - %p, Irp - %p\n", 47 HubExtension, 48 Irp); 49 50 IoCancelIrp(Irp); 51 52 if (InterlockedExchange((PLONG)&HubExtension->FdoWaitWakeLock, 1)) 53 { 54 PoStartNextPowerIrp(Irp); 55 Irp->IoStatus.Status = STATUS_CANCELLED; 56 IoCompleteRequest(Irp, IO_NO_INCREMENT); 57 } 58 } 59 60 VOID 61 NTAPI 62 USBH_HubESDRecoverySetD3Completion(IN PDEVICE_OBJECT DeviceObject, 63 IN UCHAR MinorFunction, 64 IN POWER_STATE PowerState, 65 IN PVOID Context, 66 IN PIO_STATUS_BLOCK IoStatus) 67 { 68 DPRINT("USBH_HubESDRecoverySetD3Completion ... \n"); 69 70 KeSetEvent((PRKEVENT)Context, 71 EVENT_INCREMENT, 72 FALSE); 73 } 74 75 NTSTATUS 76 NTAPI 77 USBH_HubSetD0(IN PUSBHUB_FDO_EXTENSION HubExtension) 78 { 79 PUSBHUB_FDO_EXTENSION RootHubDevExt; 80 NTSTATUS Status; 81 KEVENT Event; 82 POWER_STATE PowerState; 83 84 DPRINT("USBH_HubSetD0: HubExtension - %p\n", HubExtension); 85 86 RootHubDevExt = USBH_GetRootHubExtension(HubExtension); 87 88 if (RootHubDevExt->SystemPowerState.SystemState != PowerSystemWorking) 89 { 90 Status = STATUS_INVALID_DEVICE_STATE; 91 return Status; 92 } 93 94 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST) 95 { 96 DPRINT("USBH_HubSetD0: HubFlags - %lX\n", HubExtension->HubFlags); 97 98 KeWaitForSingleObject(&HubExtension->IdleEvent, 99 Suspended, 100 KernelMode, 101 FALSE, 102 NULL); 103 } 104 105 KeInitializeEvent(&Event, NotificationEvent, FALSE); 106 107 PowerState.DeviceState = PowerDeviceD0; 108 109 Status = PoRequestPowerIrp(HubExtension->LowerPDO, 110 IRP_MN_SET_POWER, 111 PowerState, 112 USBH_HubESDRecoverySetD3Completion, 113 &Event, 114 NULL); 115 116 if (Status == STATUS_PENDING) 117 { 118 Status = KeWaitForSingleObject(&Event, 119 Suspended, 120 KernelMode, 121 FALSE, 122 NULL); 123 } 124 125 while (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAKEUP_START) 126 { 127 USBH_Wait(10); 128 } 129 130 return Status; 131 } 132 133 VOID 134 NTAPI 135 USBH_IdleCancelPowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 136 IN PVOID Context) 137 { 138 PUSBHUB_IDLE_PORT_CANCEL_CONTEXT WorkItemIdlePower; 139 PIRP Irp; 140 141 DPRINT("USBH_IdleCancelPowerHubWorker: ... \n"); 142 143 WorkItemIdlePower = Context; 144 145 if (HubExtension && 146 HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 && 147 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 148 { 149 USBH_HubSetD0(HubExtension); 150 } 151 152 Irp = WorkItemIdlePower->Irp; 153 Irp->IoStatus.Status = STATUS_CANCELLED; 154 155 IoCompleteRequest(Irp, IO_NO_INCREMENT); 156 } 157 158 VOID 159 NTAPI 160 USBH_HubQueuePortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, 161 IN PLIST_ENTRY ListIrps) 162 { 163 PDEVICE_OBJECT PortDevice; 164 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 165 USHORT NumPorts; 166 USHORT Port; 167 PIRP WakeIrp; 168 KIRQL OldIrql; 169 170 DPRINT("USBH_HubQueuePortWakeIrps ... \n"); 171 172 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts; 173 174 InitializeListHead(ListIrps); 175 176 IoAcquireCancelSpinLock(&OldIrql); 177 178 for (Port = 0; Port < NumPorts; ++Port) 179 { 180 PortDevice = HubExtension->PortData[Port].DeviceObject; 181 182 if (PortDevice) 183 { 184 PortExtension = PortDevice->DeviceExtension; 185 186 WakeIrp = PortExtension->PdoWaitWakeIrp; 187 PortExtension->PdoWaitWakeIrp = NULL; 188 189 if (WakeIrp) 190 { 191 DPRINT1("USBH_HubQueuePortWakeIrps: UNIMPLEMENTED. FIXME\n"); 192 DbgBreakPoint(); 193 } 194 } 195 } 196 197 IoReleaseCancelSpinLock(OldIrql); 198 } 199 200 VOID 201 NTAPI 202 USBH_HubCompleteQueuedPortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, 203 IN PLIST_ENTRY ListIrps, 204 IN NTSTATUS NtStatus) 205 { 206 DPRINT("USBH_HubCompleteQueuedPortWakeIrps ... \n"); 207 208 while (!IsListEmpty(ListIrps)) 209 { 210 DPRINT1("USBH_HubCompleteQueuedPortWakeIrps: UNIMPLEMENTED. FIXME\n"); 211 DbgBreakPoint(); 212 } 213 } 214 215 VOID 216 NTAPI 217 USBH_HubCompletePortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, 218 IN NTSTATUS NtStatus) 219 { 220 LIST_ENTRY ListIrps; 221 222 DPRINT("USBH_HubCompletePortWakeIrps: NtStatus - %x\n", NtStatus); 223 224 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 225 { 226 USBH_HubQueuePortWakeIrps(HubExtension, &ListIrps); 227 228 USBH_HubCompleteQueuedPortWakeIrps(HubExtension, 229 &ListIrps, 230 NtStatus); 231 } 232 } 233 234 VOID 235 NTAPI 236 USBH_FdoPoRequestD0Completion(IN PDEVICE_OBJECT DeviceObject, 237 IN UCHAR MinorFunction, 238 IN POWER_STATE PowerState, 239 IN PVOID Context, 240 IN PIO_STATUS_BLOCK IoStatus) 241 { 242 PUSBHUB_FDO_EXTENSION HubExtension; 243 244 DPRINT("USBH_FdoPoRequestD0Completion ... \n"); 245 246 HubExtension = Context; 247 248 USBH_HubCompletePortWakeIrps(HubExtension, STATUS_SUCCESS); 249 250 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAKEUP_START; 251 252 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 253 { 254 KeSetEvent(&HubExtension->PendingRequestEvent, 255 EVENT_INCREMENT, 256 FALSE); 257 } 258 } 259 260 VOID 261 NTAPI 262 USBH_CompletePortWakeIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension, 263 IN PVOID Context) 264 { 265 DPRINT1("USBH_CompletePortWakeIrpsWorker: UNIMPLEMENTED. FIXME\n"); 266 DbgBreakPoint(); 267 } 268 269 NTSTATUS 270 NTAPI 271 USBH_FdoWWIrpIoCompletion(IN PDEVICE_OBJECT DeviceObject, 272 IN PIRP Irp, 273 IN PVOID Context) 274 { 275 PUSBHUB_FDO_EXTENSION HubExtension; 276 NTSTATUS Status; 277 KIRQL OldIrql; 278 POWER_STATE PowerState; 279 PIRP WakeIrp; 280 281 DPRINT("USBH_FdoWWIrpIoCompletion: DeviceObject - %p, Irp - %p\n", 282 DeviceObject, 283 Irp); 284 285 HubExtension = Context; 286 287 Status = Irp->IoStatus.Status; 288 289 IoAcquireCancelSpinLock(&OldIrql); 290 291 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP; 292 293 WakeIrp = InterlockedExchangePointer((PVOID *)&HubExtension->PendingWakeIrp, 294 NULL); 295 296 if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) 297 { 298 KeSetEvent(&HubExtension->PendingRequestEvent, 299 EVENT_INCREMENT, 300 FALSE); 301 } 302 303 IoReleaseCancelSpinLock(OldIrql); 304 305 DPRINT("USBH_FdoWWIrpIoCompletion: Status - %lX\n", Status); 306 307 if (!NT_SUCCESS(Status)) 308 { 309 DPRINT1("USBH_FdoWWIrpIoCompletion: DbgBreakPoint() \n"); 310 DbgBreakPoint(); 311 } 312 else 313 { 314 PowerState.DeviceState = PowerDeviceD0; 315 316 HubExtension->HubFlags |= USBHUB_FDO_FLAG_WAKEUP_START; 317 InterlockedIncrement(&HubExtension->PendingRequestCount); 318 319 Status = STATUS_SUCCESS; 320 321 PoRequestPowerIrp(HubExtension->LowerPDO, 322 IRP_MN_SET_POWER, 323 PowerState, 324 USBH_FdoPoRequestD0Completion, 325 (PVOID)HubExtension, 326 NULL); 327 } 328 329 if (!WakeIrp) 330 { 331 if (!InterlockedExchange(&HubExtension->FdoWaitWakeLock, 1)) 332 { 333 Status = STATUS_MORE_PROCESSING_REQUIRED; 334 } 335 } 336 337 DPRINT("USBH_FdoWWIrpIoCompletion: Status - %lX\n", Status); 338 339 if (Status != STATUS_MORE_PROCESSING_REQUIRED) 340 { 341 PoStartNextPowerIrp(Irp); 342 } 343 344 return Status; 345 } 346 347 NTSTATUS 348 NTAPI 349 USBH_PowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject, 350 IN PIRP Irp, 351 IN PVOID Context) 352 { 353 PUSBHUB_FDO_EXTENSION HubExtension; 354 PIO_STACK_LOCATION IoStack; 355 DEVICE_POWER_STATE OldDeviceState; 356 NTSTATUS Status; 357 POWER_STATE PowerState; 358 359 DPRINT("USBH_PowerIrpCompletion: DeviceObject - %p, Irp - %p\n", 360 DeviceObject, 361 Irp); 362 363 HubExtension = Context; 364 365 IoStack = IoGetCurrentIrpStackLocation(Irp); 366 PowerState = IoStack->Parameters.Power.State; 367 368 Status = Irp->IoStatus.Status; 369 DPRINT("USBH_PowerIrpCompletion: Status - %lX\n", Status); 370 371 if (!NT_SUCCESS(Status)) 372 { 373 if (PowerState.DeviceState == PowerDeviceD0) 374 { 375 PoStartNextPowerIrp(Irp); 376 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_SET_D0_STATE; 377 } 378 } 379 else if (PowerState.DeviceState == PowerDeviceD0) 380 { 381 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_SET_D0_STATE; 382 383 OldDeviceState = HubExtension->CurrentPowerState.DeviceState; 384 HubExtension->CurrentPowerState.DeviceState = PowerDeviceD0; 385 386 DPRINT("USBH_PowerIrpCompletion: OldDeviceState - %x\n", OldDeviceState); 387 388 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_HIBERNATE_STATE) 389 { 390 DPRINT1("USBH_PowerIrpCompletion: USBHUB_FDO_FLAG_HIBERNATE_STATE. FIXME\n"); 391 DbgBreakPoint(); 392 } 393 394 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_HIBERNATE_STATE; 395 396 if (OldDeviceState == PowerDeviceD3) 397 { 398 DPRINT1("USBH_PowerIrpCompletion: PowerDeviceD3. FIXME\n"); 399 DbgBreakPoint(); 400 } 401 402 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED) && 403 HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_ENUMERATION) 404 { 405 USBH_SubmitStatusChangeTransfer(HubExtension); 406 } 407 408 DPRINT("USBH_PowerIrpCompletion: Status - %lX\n", Status); 409 410 if (Status != STATUS_MORE_PROCESSING_REQUIRED) 411 { 412 PoStartNextPowerIrp(Irp); 413 return Status; 414 } 415 } 416 417 return Status; 418 } 419 420 VOID 421 NTAPI 422 USBH_FdoDeferPoRequestCompletion(IN PDEVICE_OBJECT DeviceObject, 423 IN UCHAR MinorFunction, 424 IN POWER_STATE PowerState, 425 IN PVOID Context, 426 IN PIO_STATUS_BLOCK IoStatus) 427 { 428 PUSBHUB_FDO_EXTENSION Extension; 429 PUSBHUB_FDO_EXTENSION HubExtension = NULL; 430 PIRP PowerIrp; 431 PIO_STACK_LOCATION IoStack; 432 433 DPRINT("USBH_FdoDeferPoRequestCompletion ... \n"); 434 435 Extension = Context; 436 437 PowerIrp = Extension->PowerIrp; 438 439 if (Extension->Common.ExtensionType == USBH_EXTENSION_TYPE_HUB) 440 { 441 HubExtension = Context; 442 } 443 444 IoStack = IoGetCurrentIrpStackLocation(PowerIrp); 445 446 if (IoStack->Parameters.Power.State.SystemState == PowerSystemWorking && 447 HubExtension && HubExtension->LowerPDO == HubExtension->RootHubPdo) 448 { 449 HubExtension->SystemPowerState.SystemState = PowerSystemWorking; 450 USBH_CheckIdleDeferred(HubExtension); 451 } 452 453 IoCopyCurrentIrpStackLocationToNext(PowerIrp); 454 PoStartNextPowerIrp(PowerIrp); 455 PoCallDriver(Extension->LowerDevice, PowerIrp); 456 } 457 458 NTSTATUS 459 NTAPI 460 USBH_FdoPower(IN PUSBHUB_FDO_EXTENSION HubExtension, 461 IN PIRP Irp, 462 IN UCHAR Minor) 463 { 464 NTSTATUS Status; 465 PIO_STACK_LOCATION IoStack; 466 POWER_STATE PowerState; 467 POWER_STATE DevicePwrState; 468 BOOLEAN IsAllPortsD3; 469 PUSBHUB_PORT_DATA PortData; 470 PDEVICE_OBJECT PdoDevice; 471 PUSBHUB_PORT_PDO_EXTENSION PortExtension; 472 ULONG Port; 473 474 DPRINT_PWR("USBH_FdoPower: HubExtension - %p, Irp - %p, Minor - %X\n", 475 HubExtension, 476 Irp, 477 Minor); 478 479 switch (Minor) 480 { 481 case IRP_MN_WAIT_WAKE: 482 DPRINT_PWR("USBH_FdoPower: IRP_MN_WAIT_WAKE\n"); 483 484 IoCopyCurrentIrpStackLocationToNext(Irp); 485 486 IoSetCompletionRoutine(Irp, 487 USBH_FdoWWIrpIoCompletion, 488 HubExtension, 489 TRUE, 490 TRUE, 491 TRUE); 492 493 PoStartNextPowerIrp(Irp); 494 IoMarkIrpPending(Irp); 495 PoCallDriver(HubExtension->LowerDevice, Irp); 496 497 return STATUS_PENDING; 498 499 case IRP_MN_POWER_SEQUENCE: 500 DPRINT_PWR("USBH_FdoPower: IRP_MN_POWER_SEQUENCE\n"); 501 break; 502 503 case IRP_MN_SET_POWER: 504 DPRINT_PWR("USBH_FdoPower: IRP_MN_SET_POWER\n"); 505 506 IoStack = IoGetCurrentIrpStackLocation(Irp); 507 DPRINT_PWR("USBH_FdoPower: IRP_MN_SET_POWER/DevicePowerState\n"); 508 PowerState = IoStack->Parameters.Power.State; 509 510 if (IoStack->Parameters.Power.Type == DevicePowerState) 511 { 512 DPRINT_PWR("USBH_FdoPower: PowerState - %x\n", 513 PowerState.DeviceState); 514 515 if (HubExtension->CurrentPowerState.DeviceState == PowerState.DeviceState) 516 { 517 IoCopyCurrentIrpStackLocationToNext(Irp); 518 519 PoStartNextPowerIrp(Irp); 520 IoMarkIrpPending(Irp); 521 PoCallDriver(HubExtension->LowerDevice, Irp); 522 523 return STATUS_PENDING; 524 } 525 526 switch (PowerState.DeviceState) 527 { 528 case PowerDeviceD0: 529 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_SET_D0_STATE)) 530 { 531 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_NOT_D0_STATE | 532 USBHUB_FDO_FLAG_DEVICE_STOPPING); 533 534 HubExtension->HubFlags |= USBHUB_FDO_FLAG_SET_D0_STATE; 535 536 IoCopyCurrentIrpStackLocationToNext(Irp); 537 538 IoSetCompletionRoutine(Irp, 539 USBH_PowerIrpCompletion, 540 HubExtension, 541 TRUE, 542 TRUE, 543 TRUE); 544 } 545 else 546 { 547 IoCopyCurrentIrpStackLocationToNext(Irp); 548 PoStartNextPowerIrp(Irp); 549 } 550 551 IoMarkIrpPending(Irp); 552 PoCallDriver(HubExtension->LowerDevice, Irp); 553 return STATUS_PENDING; 554 555 case PowerDeviceD1: 556 case PowerDeviceD2: 557 case PowerDeviceD3: 558 if (HubExtension->ResetRequestCount) 559 { 560 IoCancelIrp(HubExtension->ResetPortIrp); 561 562 KeWaitForSingleObject(&HubExtension->ResetEvent, 563 Executive, 564 KernelMode, 565 FALSE, 566 NULL); 567 } 568 569 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) 570 { 571 HubExtension->HubFlags |= (USBHUB_FDO_FLAG_NOT_D0_STATE | 572 USBHUB_FDO_FLAG_DEVICE_STOPPING); 573 574 IoCancelIrp(HubExtension->SCEIrp); 575 576 KeWaitForSingleObject(&HubExtension->StatusChangeEvent, 577 Executive, 578 KernelMode, 579 FALSE, 580 NULL); 581 } 582 583 HubExtension->CurrentPowerState.DeviceState = PowerState.DeviceState; 584 585 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_SUSPENSE && 586 USBH_CheckIdleAbort(HubExtension, TRUE, TRUE) == TRUE) 587 { 588 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_NOT_D0_STATE | 589 USBHUB_FDO_FLAG_DEVICE_STOPPING); 590 591 HubExtension->CurrentPowerState.DeviceState = PowerDeviceD0; 592 593 USBH_SubmitStatusChangeTransfer(HubExtension); 594 595 PoStartNextPowerIrp(Irp); 596 597 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 598 IoCompleteRequest(Irp, IO_NO_INCREMENT); 599 600 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DO_SUSPENSE; 601 602 KeReleaseSemaphore(&HubExtension->IdleSemaphore, 603 LOW_REALTIME_PRIORITY, 604 1, 605 FALSE); 606 607 return STATUS_UNSUCCESSFUL; 608 } 609 610 IoCopyCurrentIrpStackLocationToNext(Irp); 611 612 IoSetCompletionRoutine(Irp, 613 USBH_PowerIrpCompletion, 614 HubExtension, 615 TRUE, 616 TRUE, 617 TRUE); 618 619 PoStartNextPowerIrp(Irp); 620 IoMarkIrpPending(Irp); 621 PoCallDriver(HubExtension->LowerDevice, Irp); 622 623 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_SUSPENSE) 624 { 625 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DO_SUSPENSE; 626 627 KeReleaseSemaphore(&HubExtension->IdleSemaphore, 628 LOW_REALTIME_PRIORITY, 629 1, 630 FALSE); 631 } 632 633 return STATUS_PENDING; 634 635 default: 636 DPRINT1("USBH_FdoPower: Unsupported PowerState.DeviceState\n"); 637 DbgBreakPoint(); 638 break; 639 } 640 } 641 else 642 { 643 if (PowerState.SystemState != PowerSystemWorking) 644 { 645 USBH_GetRootHubExtension(HubExtension)->SystemPowerState.SystemState = 646 PowerState.SystemState; 647 } 648 649 if (PowerState.SystemState == PowerSystemHibernate) 650 { 651 HubExtension->HubFlags |= USBHUB_FDO_FLAG_HIBERNATE_STATE; 652 } 653 654 PortData = HubExtension->PortData; 655 656 IsAllPortsD3 = TRUE; 657 658 if (PortData && HubExtension->HubDescriptor) 659 { 660 for (Port = 0; 661 Port < HubExtension->HubDescriptor->bNumberOfPorts; 662 Port++) 663 { 664 PdoDevice = PortData[Port].DeviceObject; 665 666 if (PdoDevice) 667 { 668 PortExtension = PdoDevice->DeviceExtension; 669 670 if (PortExtension->CurrentPowerState.DeviceState != PowerDeviceD3) 671 { 672 IsAllPortsD3 = FALSE; 673 break; 674 } 675 } 676 } 677 } 678 679 if (PowerState.SystemState == PowerSystemWorking) 680 { 681 DevicePwrState.DeviceState = PowerDeviceD0; 682 } 683 else if (HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP || 684 !IsAllPortsD3) 685 { 686 DevicePwrState.DeviceState = HubExtension->DeviceState[PowerState.SystemState]; 687 688 if (DevicePwrState.DeviceState == PowerDeviceUnspecified) 689 { 690 goto Exit; 691 } 692 } 693 else 694 { 695 DevicePwrState.DeviceState = PowerDeviceD3; 696 } 697 698 if (DevicePwrState.DeviceState != HubExtension->CurrentPowerState.DeviceState && 699 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) 700 { 701 HubExtension->PowerIrp = Irp; 702 703 IoMarkIrpPending(Irp); 704 705 if (PoRequestPowerIrp(HubExtension->LowerPDO, 706 IRP_MN_SET_POWER, 707 DevicePwrState, 708 USBH_FdoDeferPoRequestCompletion, 709 (PVOID)HubExtension, 710 NULL) == STATUS_PENDING) 711 { 712 return STATUS_PENDING; 713 } 714 715 IoCopyCurrentIrpStackLocationToNext(Irp); 716 PoStartNextPowerIrp(Irp); 717 PoCallDriver(HubExtension->LowerDevice, Irp); 718 719 return STATUS_PENDING; 720 } 721 722 Exit: 723 724 HubExtension->SystemPowerState.SystemState = PowerState.SystemState; 725 726 if (PowerState.SystemState == PowerSystemWorking) 727 { 728 USBH_CheckIdleDeferred(HubExtension); 729 } 730 731 IoCopyCurrentIrpStackLocationToNext(Irp); 732 PoStartNextPowerIrp(Irp); 733 734 return PoCallDriver(HubExtension->LowerDevice, Irp); 735 } 736 737 break; 738 739 case IRP_MN_QUERY_POWER: 740 DPRINT_PWR("USBH_FdoPower: IRP_MN_QUERY_POWER\n"); 741 break; 742 743 default: 744 DPRINT1("USBH_FdoPower: unknown IRP_MN_POWER!\n"); 745 break; 746 } 747 748 IoCopyCurrentIrpStackLocationToNext(Irp); 749 PoStartNextPowerIrp(Irp); 750 Status = PoCallDriver(HubExtension->LowerDevice, Irp); 751 752 return Status; 753 } 754 755 NTSTATUS 756 NTAPI 757 USBH_PdoPower(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, 758 IN PIRP Irp, 759 IN UCHAR Minor) 760 { 761 NTSTATUS Status = Irp->IoStatus.Status; 762 763 DPRINT_PWR("USBH_FdoPower: PortExtension - %p, Irp - %p, Minor - %X\n", 764 PortExtension, 765 Irp, 766 Minor); 767 768 switch (Minor) 769 { 770 case IRP_MN_WAIT_WAKE: 771 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_WAIT_WAKE\n"); 772 PoStartNextPowerIrp(Irp); 773 break; 774 775 case IRP_MN_POWER_SEQUENCE: 776 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_POWER_SEQUENCE\n"); 777 PoStartNextPowerIrp(Irp); 778 break; 779 780 case IRP_MN_SET_POWER: 781 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_SET_POWER\n"); 782 PoStartNextPowerIrp(Irp); 783 break; 784 785 case IRP_MN_QUERY_POWER: 786 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_QUERY_POWER\n"); 787 PoStartNextPowerIrp(Irp); 788 break; 789 790 default: 791 DPRINT1("USBHUB_PdoPower: unknown IRP_MN_POWER!\n"); 792 PoStartNextPowerIrp(Irp); 793 break; 794 } 795 796 Irp->IoStatus.Status = Status; 797 Irp->IoStatus.Information = 0; 798 IoCompleteRequest(Irp, IO_NO_INCREMENT); 799 800 return Status; 801 } 802