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
USBH_CompletePowerIrp(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PIRP Irp,IN NTSTATUS NtStatus)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
USBH_HubCancelWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PIRP Irp)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
USBH_HubESDRecoverySetD3Completion(IN PDEVICE_OBJECT DeviceObject,IN UCHAR MinorFunction,IN POWER_STATE PowerState,IN PVOID Context,IN PIO_STATUS_BLOCK IoStatus)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
USBH_HubSetD0(IN PUSBHUB_FDO_EXTENSION HubExtension)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
USBH_IdleCancelPowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PVOID Context)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
USBH_HubQueuePortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PLIST_ENTRY ListIrps)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
USBH_HubCompleteQueuedPortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PLIST_ENTRY ListIrps,IN NTSTATUS NtStatus)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
USBH_HubCompletePortWakeIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,IN NTSTATUS NtStatus)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
USBH_FdoPoRequestD0Completion(IN PDEVICE_OBJECT DeviceObject,IN UCHAR MinorFunction,IN POWER_STATE PowerState,IN PVOID Context,IN PIO_STATUS_BLOCK IoStatus)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
USBH_CompletePortWakeIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PVOID Context)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
USBH_FdoWWIrpIoCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)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
USBH_PowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)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
USBH_FdoDeferPoRequestCompletion(IN PDEVICE_OBJECT DeviceObject,IN UCHAR MinorFunction,IN POWER_STATE PowerState,IN PVOID Context,IN PIO_STATUS_BLOCK IoStatus)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
USBH_FdoPower(IN PUSBHUB_FDO_EXTENSION HubExtension,IN PIRP Irp,IN UCHAR Minor)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
USBH_PdoPower(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,IN PIRP Irp,IN UCHAR Minor)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