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>
13 #define NDEBUG_USBHUB_POWER
18 USBH_CompletePowerIrp(IN PUSBHUB_FDO_EXTENSION HubExtension
,
22 DPRINT("USBH_CompletePowerIrp: HubExtension - %p, Irp - %p, NtStatus - %lX\n",
27 Irp
->IoStatus
.Status
= NtStatus
;
29 PoStartNextPowerIrp(Irp
);
31 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
33 KeSetEvent(&HubExtension
->PendingRequestEvent
,
38 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
43 USBH_HubCancelWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension
,
46 DPRINT("USBH_HubCancelWakeIrp: HubExtension - %p, Irp - %p\n",
52 if (InterlockedExchange((PLONG
)&HubExtension
->FdoWaitWakeLock
, 1))
54 PoStartNextPowerIrp(Irp
);
55 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
56 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
62 USBH_HubESDRecoverySetD3Completion(IN PDEVICE_OBJECT DeviceObject
,
63 IN UCHAR MinorFunction
,
64 IN POWER_STATE PowerState
,
66 IN PIO_STATUS_BLOCK IoStatus
)
68 DPRINT("USBH_HubESDRecoverySetD3Completion ... \n");
70 KeSetEvent((PRKEVENT
)Context
,
77 USBH_HubSetD0(IN PUSBHUB_FDO_EXTENSION HubExtension
)
79 PUSBHUB_FDO_EXTENSION RootHubDevExt
;
82 POWER_STATE PowerState
;
84 DPRINT("USBH_HubSetD0: HubExtension - %p\n", HubExtension
);
86 RootHubDevExt
= USBH_GetRootHubExtension(HubExtension
);
88 if (RootHubDevExt
->SystemPowerState
.SystemState
!= PowerSystemWorking
)
90 Status
= STATUS_INVALID_DEVICE_STATE
;
94 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST
)
96 DPRINT("USBH_HubSetD0: HubFlags - %lX\n", HubExtension
->HubFlags
);
98 KeWaitForSingleObject(&HubExtension
->IdleEvent
,
105 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
107 PowerState
.DeviceState
= PowerDeviceD0
;
109 Status
= PoRequestPowerIrp(HubExtension
->LowerPDO
,
112 USBH_HubESDRecoverySetD3Completion
,
116 if (Status
== STATUS_PENDING
)
118 Status
= KeWaitForSingleObject(&Event
,
125 while (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_WAKEUP_START
)
135 USBH_IdleCancelPowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension
,
138 PUSBHUB_IDLE_PORT_CANCEL_CONTEXT WorkItemIdlePower
;
141 DPRINT("USBH_IdleCancelPowerHubWorker: ... \n");
143 WorkItemIdlePower
= Context
;
146 HubExtension
->CurrentPowerState
.DeviceState
!= PowerDeviceD0
&&
147 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STARTED
)
149 USBH_HubSetD0(HubExtension
);
152 Irp
= WorkItemIdlePower
->Irp
;
153 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
155 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
160 USBH_HubQueuePortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension
,
161 IN PLIST_ENTRY ListIrps
)
163 PDEVICE_OBJECT PortDevice
;
164 PUSBHUB_PORT_PDO_EXTENSION PortExtension
;
170 DPRINT("USBH_HubQueuePortWakeIrps ... \n");
172 NumPorts
= HubExtension
->HubDescriptor
->bNumberOfPorts
;
174 InitializeListHead(ListIrps
);
176 IoAcquireCancelSpinLock(&OldIrql
);
178 for (Port
= 0; Port
< NumPorts
; ++Port
)
180 PortDevice
= HubExtension
->PortData
[Port
].DeviceObject
;
184 PortExtension
= PortDevice
->DeviceExtension
;
186 WakeIrp
= PortExtension
->PdoWaitWakeIrp
;
187 PortExtension
->PdoWaitWakeIrp
= NULL
;
191 DPRINT1("USBH_HubQueuePortWakeIrps: UNIMPLEMENTED. FIXME\n");
197 IoReleaseCancelSpinLock(OldIrql
);
202 USBH_HubCompleteQueuedPortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension
,
203 IN PLIST_ENTRY ListIrps
,
204 IN NTSTATUS NtStatus
)
206 DPRINT("USBH_HubCompleteQueuedPortWakeIrps ... \n");
208 while (!IsListEmpty(ListIrps
))
210 DPRINT1("USBH_HubCompleteQueuedPortWakeIrps: UNIMPLEMENTED. FIXME\n");
217 USBH_HubCompletePortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension
,
218 IN NTSTATUS NtStatus
)
222 DPRINT("USBH_HubCompletePortWakeIrps: NtStatus - %x\n", NtStatus
);
224 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STARTED
)
226 USBH_HubQueuePortWakeIrps(HubExtension
, &ListIrps
);
228 USBH_HubCompleteQueuedPortWakeIrps(HubExtension
,
236 USBH_FdoPoRequestD0Completion(IN PDEVICE_OBJECT DeviceObject
,
237 IN UCHAR MinorFunction
,
238 IN POWER_STATE PowerState
,
240 IN PIO_STATUS_BLOCK IoStatus
)
242 PUSBHUB_FDO_EXTENSION HubExtension
;
244 DPRINT("USBH_FdoPoRequestD0Completion ... \n");
246 HubExtension
= Context
;
248 USBH_HubCompletePortWakeIrps(HubExtension
, STATUS_SUCCESS
);
250 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_WAKEUP_START
;
252 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
254 KeSetEvent(&HubExtension
->PendingRequestEvent
,
262 USBH_CompletePortWakeIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension
,
265 DPRINT1("USBH_CompletePortWakeIrpsWorker: UNIMPLEMENTED. FIXME\n");
271 USBH_FdoWWIrpIoCompletion(IN PDEVICE_OBJECT DeviceObject
,
275 PUSBHUB_FDO_EXTENSION HubExtension
;
278 POWER_STATE PowerState
;
281 DPRINT("USBH_FdoWWIrpIoCompletion: DeviceObject - %p, Irp - %p\n",
285 HubExtension
= Context
;
287 Status
= Irp
->IoStatus
.Status
;
289 IoAcquireCancelSpinLock(&OldIrql
);
291 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP
;
293 WakeIrp
= InterlockedExchangePointer((PVOID
*)&HubExtension
->PendingWakeIrp
,
296 if (!InterlockedDecrement(&HubExtension
->PendingRequestCount
))
298 KeSetEvent(&HubExtension
->PendingRequestEvent
,
303 IoReleaseCancelSpinLock(OldIrql
);
305 DPRINT("USBH_FdoWWIrpIoCompletion: Status - %lX\n", Status
);
307 if (!NT_SUCCESS(Status
))
309 DPRINT1("USBH_FdoWWIrpIoCompletion: DbgBreakPoint() \n");
314 PowerState
.DeviceState
= PowerDeviceD0
;
316 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_WAKEUP_START
;
317 InterlockedIncrement(&HubExtension
->PendingRequestCount
);
319 Status
= STATUS_SUCCESS
;
321 PoRequestPowerIrp(HubExtension
->LowerPDO
,
324 USBH_FdoPoRequestD0Completion
,
331 if (!InterlockedExchange(&HubExtension
->FdoWaitWakeLock
, 1))
333 Status
= STATUS_MORE_PROCESSING_REQUIRED
;
337 DPRINT("USBH_FdoWWIrpIoCompletion: Status - %lX\n", Status
);
339 if (Status
!= STATUS_MORE_PROCESSING_REQUIRED
)
341 PoStartNextPowerIrp(Irp
);
349 USBH_PowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject
,
353 PUSBHUB_FDO_EXTENSION HubExtension
;
354 PIO_STACK_LOCATION IoStack
;
355 DEVICE_POWER_STATE OldDeviceState
;
357 POWER_STATE PowerState
;
359 DPRINT("USBH_PowerIrpCompletion: DeviceObject - %p, Irp - %p\n",
363 HubExtension
= Context
;
365 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
366 PowerState
= IoStack
->Parameters
.Power
.State
;
368 Status
= Irp
->IoStatus
.Status
;
369 DPRINT("USBH_PowerIrpCompletion: Status - %lX\n", Status
);
371 if (!NT_SUCCESS(Status
))
373 if (PowerState
.DeviceState
== PowerDeviceD0
)
375 PoStartNextPowerIrp(Irp
);
376 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_SET_D0_STATE
;
379 else if (PowerState
.DeviceState
== PowerDeviceD0
)
381 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_SET_D0_STATE
;
383 OldDeviceState
= HubExtension
->CurrentPowerState
.DeviceState
;
384 HubExtension
->CurrentPowerState
.DeviceState
= PowerDeviceD0
;
386 DPRINT("USBH_PowerIrpCompletion: OldDeviceState - %x\n", OldDeviceState
);
388 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_HIBERNATE_STATE
)
390 DPRINT1("USBH_PowerIrpCompletion: USBHUB_FDO_FLAG_HIBERNATE_STATE. FIXME\n");
394 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_HIBERNATE_STATE
;
396 if (OldDeviceState
== PowerDeviceD3
)
398 DPRINT1("USBH_PowerIrpCompletion: PowerDeviceD3. FIXME\n");
402 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPED
) &&
403 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DO_ENUMERATION
)
405 USBH_SubmitStatusChangeTransfer(HubExtension
);
408 DPRINT("USBH_PowerIrpCompletion: Status - %lX\n", Status
);
410 if (Status
!= STATUS_MORE_PROCESSING_REQUIRED
)
412 PoStartNextPowerIrp(Irp
);
422 USBH_FdoDeferPoRequestCompletion(IN PDEVICE_OBJECT DeviceObject
,
423 IN UCHAR MinorFunction
,
424 IN POWER_STATE PowerState
,
426 IN PIO_STATUS_BLOCK IoStatus
)
428 PUSBHUB_FDO_EXTENSION Extension
;
429 PUSBHUB_FDO_EXTENSION HubExtension
= NULL
;
431 PIO_STACK_LOCATION IoStack
;
433 DPRINT("USBH_FdoDeferPoRequestCompletion ... \n");
437 PowerIrp
= Extension
->PowerIrp
;
439 if (Extension
->Common
.ExtensionType
== USBH_EXTENSION_TYPE_HUB
)
441 HubExtension
= Context
;
444 IoStack
= IoGetCurrentIrpStackLocation(PowerIrp
);
446 if (IoStack
->Parameters
.Power
.State
.SystemState
== PowerSystemWorking
&&
447 HubExtension
&& HubExtension
->LowerPDO
== HubExtension
->RootHubPdo
)
449 HubExtension
->SystemPowerState
.SystemState
= PowerSystemWorking
;
450 USBH_CheckIdleDeferred(HubExtension
);
453 IoCopyCurrentIrpStackLocationToNext(PowerIrp
);
454 PoStartNextPowerIrp(PowerIrp
);
455 PoCallDriver(Extension
->LowerDevice
, PowerIrp
);
460 USBH_FdoPower(IN PUSBHUB_FDO_EXTENSION HubExtension
,
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
;
474 DPRINT_PWR("USBH_FdoPower: HubExtension - %p, Irp - %p, Minor - %X\n",
481 case IRP_MN_WAIT_WAKE
:
482 DPRINT_PWR("USBH_FdoPower: IRP_MN_WAIT_WAKE\n");
484 IoCopyCurrentIrpStackLocationToNext(Irp
);
486 IoSetCompletionRoutine(Irp
,
487 USBH_FdoWWIrpIoCompletion
,
493 PoStartNextPowerIrp(Irp
);
494 IoMarkIrpPending(Irp
);
495 PoCallDriver(HubExtension
->LowerDevice
, Irp
);
497 return STATUS_PENDING
;
499 case IRP_MN_POWER_SEQUENCE
:
500 DPRINT_PWR("USBH_FdoPower: IRP_MN_POWER_SEQUENCE\n");
503 case IRP_MN_SET_POWER
:
504 DPRINT_PWR("USBH_FdoPower: IRP_MN_SET_POWER\n");
506 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
507 DPRINT_PWR("USBH_FdoPower: IRP_MN_SET_POWER/DevicePowerState\n");
508 PowerState
= IoStack
->Parameters
.Power
.State
;
510 if (IoStack
->Parameters
.Power
.Type
== DevicePowerState
)
512 DPRINT_PWR("USBH_FdoPower: PowerState - %x\n",
513 PowerState
.DeviceState
);
515 if (HubExtension
->CurrentPowerState
.DeviceState
== PowerState
.DeviceState
)
517 IoCopyCurrentIrpStackLocationToNext(Irp
);
519 PoStartNextPowerIrp(Irp
);
520 IoMarkIrpPending(Irp
);
521 PoCallDriver(HubExtension
->LowerDevice
, Irp
);
523 return STATUS_PENDING
;
526 switch (PowerState
.DeviceState
)
529 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_SET_D0_STATE
))
531 HubExtension
->HubFlags
&= ~(USBHUB_FDO_FLAG_NOT_D0_STATE
|
532 USBHUB_FDO_FLAG_DEVICE_STOPPING
);
534 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_SET_D0_STATE
;
536 IoCopyCurrentIrpStackLocationToNext(Irp
);
538 IoSetCompletionRoutine(Irp
,
539 USBH_PowerIrpCompletion
,
547 IoCopyCurrentIrpStackLocationToNext(Irp
);
548 PoStartNextPowerIrp(Irp
);
551 IoMarkIrpPending(Irp
);
552 PoCallDriver(HubExtension
->LowerDevice
, Irp
);
553 return STATUS_PENDING
;
558 if (HubExtension
->ResetRequestCount
)
560 IoCancelIrp(HubExtension
->ResetPortIrp
);
562 KeWaitForSingleObject(&HubExtension
->ResetEvent
,
569 if (!(HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STOPPED
))
571 HubExtension
->HubFlags
|= (USBHUB_FDO_FLAG_NOT_D0_STATE
|
572 USBHUB_FDO_FLAG_DEVICE_STOPPING
);
574 IoCancelIrp(HubExtension
->SCEIrp
);
576 KeWaitForSingleObject(&HubExtension
->StatusChangeEvent
,
583 HubExtension
->CurrentPowerState
.DeviceState
= PowerState
.DeviceState
;
585 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DO_SUSPENSE
&&
586 USBH_CheckIdleAbort(HubExtension
, TRUE
, TRUE
) == TRUE
)
588 HubExtension
->HubFlags
&= ~(USBHUB_FDO_FLAG_NOT_D0_STATE
|
589 USBHUB_FDO_FLAG_DEVICE_STOPPING
);
591 HubExtension
->CurrentPowerState
.DeviceState
= PowerDeviceD0
;
593 USBH_SubmitStatusChangeTransfer(HubExtension
);
595 PoStartNextPowerIrp(Irp
);
597 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
598 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
600 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_DO_SUSPENSE
;
602 KeReleaseSemaphore(&HubExtension
->IdleSemaphore
,
603 LOW_REALTIME_PRIORITY
,
607 return STATUS_UNSUCCESSFUL
;
610 IoCopyCurrentIrpStackLocationToNext(Irp
);
612 IoSetCompletionRoutine(Irp
,
613 USBH_PowerIrpCompletion
,
619 PoStartNextPowerIrp(Irp
);
620 IoMarkIrpPending(Irp
);
621 PoCallDriver(HubExtension
->LowerDevice
, Irp
);
623 if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DO_SUSPENSE
)
625 HubExtension
->HubFlags
&= ~USBHUB_FDO_FLAG_DO_SUSPENSE
;
627 KeReleaseSemaphore(&HubExtension
->IdleSemaphore
,
628 LOW_REALTIME_PRIORITY
,
633 return STATUS_PENDING
;
636 DPRINT1("USBH_FdoPower: Unsupported PowerState.DeviceState\n");
643 if (PowerState
.SystemState
!= PowerSystemWorking
)
645 USBH_GetRootHubExtension(HubExtension
)->SystemPowerState
.SystemState
=
646 PowerState
.SystemState
;
649 if (PowerState
.SystemState
== PowerSystemHibernate
)
651 HubExtension
->HubFlags
|= USBHUB_FDO_FLAG_HIBERNATE_STATE
;
654 PortData
= HubExtension
->PortData
;
658 if (PortData
&& HubExtension
->HubDescriptor
)
661 Port
< HubExtension
->HubDescriptor
->bNumberOfPorts
;
664 PdoDevice
= PortData
[Port
].DeviceObject
;
668 PortExtension
= PdoDevice
->DeviceExtension
;
670 if (PortExtension
->CurrentPowerState
.DeviceState
!= PowerDeviceD3
)
672 IsAllPortsD3
= FALSE
;
679 if (PowerState
.SystemState
== PowerSystemWorking
)
681 DevicePwrState
.DeviceState
= PowerDeviceD0
;
683 else if (HubExtension
->HubFlags
& USBHUB_FDO_FLAG_PENDING_WAKE_IRP
||
686 DevicePwrState
.DeviceState
= HubExtension
->DeviceState
[PowerState
.SystemState
];
688 if (DevicePwrState
.DeviceState
== PowerDeviceUnspecified
)
695 DevicePwrState
.DeviceState
= PowerDeviceD3
;
698 if (DevicePwrState
.DeviceState
!= HubExtension
->CurrentPowerState
.DeviceState
&&
699 HubExtension
->HubFlags
& USBHUB_FDO_FLAG_DEVICE_STARTED
)
701 HubExtension
->PowerIrp
= Irp
;
703 IoMarkIrpPending(Irp
);
705 if (PoRequestPowerIrp(HubExtension
->LowerPDO
,
708 USBH_FdoDeferPoRequestCompletion
,
710 NULL
) == STATUS_PENDING
)
712 return STATUS_PENDING
;
715 IoCopyCurrentIrpStackLocationToNext(Irp
);
716 PoStartNextPowerIrp(Irp
);
717 PoCallDriver(HubExtension
->LowerDevice
, Irp
);
719 return STATUS_PENDING
;
724 HubExtension
->SystemPowerState
.SystemState
= PowerState
.SystemState
;
726 if (PowerState
.SystemState
== PowerSystemWorking
)
728 USBH_CheckIdleDeferred(HubExtension
);
731 IoCopyCurrentIrpStackLocationToNext(Irp
);
732 PoStartNextPowerIrp(Irp
);
734 return PoCallDriver(HubExtension
->LowerDevice
, Irp
);
739 case IRP_MN_QUERY_POWER
:
740 DPRINT_PWR("USBH_FdoPower: IRP_MN_QUERY_POWER\n");
744 DPRINT1("USBH_FdoPower: unknown IRP_MN_POWER!\n");
748 IoCopyCurrentIrpStackLocationToNext(Irp
);
749 PoStartNextPowerIrp(Irp
);
750 Status
= PoCallDriver(HubExtension
->LowerDevice
, Irp
);
757 USBH_PdoPower(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension
,
761 NTSTATUS Status
= Irp
->IoStatus
.Status
;
763 DPRINT_PWR("USBH_FdoPower: PortExtension - %p, Irp - %p, Minor - %X\n",
770 case IRP_MN_WAIT_WAKE
:
771 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_WAIT_WAKE\n");
772 PoStartNextPowerIrp(Irp
);
775 case IRP_MN_POWER_SEQUENCE
:
776 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_POWER_SEQUENCE\n");
777 PoStartNextPowerIrp(Irp
);
780 case IRP_MN_SET_POWER
:
781 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_SET_POWER\n");
782 PoStartNextPowerIrp(Irp
);
785 case IRP_MN_QUERY_POWER
:
786 DPRINT_PWR("USBHUB_PdoPower: IRP_MN_QUERY_POWER\n");
787 PoStartNextPowerIrp(Irp
);
791 DPRINT1("USBHUB_PdoPower: unknown IRP_MN_POWER!\n");
792 PoStartNextPowerIrp(Irp
);
796 Irp
->IoStatus
.Status
= Status
;
797 Irp
->IoStatus
.Information
= 0;
798 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);