Merge PR #283 "[USBPORT] Transaction Translator (TT) support bringup"
[reactos.git] / drivers / usb / usbport / power.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort power handling functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbport.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 VOID
14 NTAPI
15 USBPORT_CompletePdoWaitWake(IN PDEVICE_OBJECT FdoDevice)
16 {
17 PUSBPORT_DEVICE_EXTENSION FdoExtension;
18 PDEVICE_OBJECT PdoDevice;
19 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
20 PIRP Irp;
21 KIRQL OldIrql;
22
23 DPRINT("USBPORT_CompletePdoWaitWake: ... \n");
24
25 FdoExtension = FdoDevice->DeviceExtension;
26 PdoDevice = FdoExtension->RootHubPdo;
27 PdoExtension = PdoDevice->DeviceExtension;
28
29 KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
30
31 Irp = PdoExtension->WakeIrp;
32
33 if (Irp && IoSetCancelRoutine(Irp, NULL))
34 {
35 PdoExtension->WakeIrp = NULL;
36 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
37
38 DPRINT("USBPORT_CompletePdoWaitWake: Complete Irp - %p\n", Irp);
39
40 Irp->IoStatus.Status = STATUS_SUCCESS;
41 Irp->IoStatus.Information = 0;
42 IoCompleteRequest(Irp, IO_NO_INCREMENT);
43
44 return;
45 }
46
47 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
48 }
49
50 VOID
51 NTAPI
52 USBPORT_HcWakeDpc(IN PRKDPC Dpc,
53 IN PVOID DeferredContext,
54 IN PVOID SystemArgument1,
55 IN PVOID SystemArgument2)
56 {
57 DPRINT("USBPORT_HcWakeDpc: ... \n");
58 USBPORT_CompletePdoWaitWake((PDEVICE_OBJECT)DeferredContext);
59 }
60
61 VOID
62 NTAPI
63 USBPORT_HcQueueWakeDpc(IN PDEVICE_OBJECT FdoDevice)
64 {
65 PUSBPORT_DEVICE_EXTENSION FdoExtension;
66
67 DPRINT("USBPORT_HcQueueWakeDpc: ... \n");
68
69 FdoExtension = FdoDevice->DeviceExtension;
70 KeInsertQueueDpc(&FdoExtension->HcWakeDpc, NULL, NULL);
71 }
72
73 VOID
74 NTAPI
75 USBPORT_CompletePendingIdleIrp(IN PDEVICE_OBJECT PdoDevice)
76 {
77 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
78 PDEVICE_OBJECT FdoDevice;
79 PUSBPORT_DEVICE_EXTENSION FdoExtension;
80 PIRP Irp;
81
82 DPRINT("USBPORT_CompletePendingIdleIrp: ... \n");
83
84 PdoExtension = PdoDevice->DeviceExtension;
85 FdoDevice = PdoExtension->FdoDevice;
86 FdoExtension = FdoDevice->DeviceExtension;
87
88 Irp = IoCsqRemoveNextIrp(&FdoExtension->IdleIoCsq, 0);
89
90 if (Irp)
91 {
92 InterlockedDecrement(&FdoExtension->IdleLockCounter);
93
94 DPRINT("USBPORT_CompletePendingIdleIrp: Complete Irp - %p\n", Irp);
95
96 Irp->IoStatus.Status = STATUS_CANCELLED;
97 Irp->IoStatus.Information = 0;
98 IoCompleteRequest(Irp, IO_NO_INCREMENT);
99 }
100 }
101
102 VOID
103 NTAPI
104 USBPORT_DoSetPowerD0(IN PDEVICE_OBJECT FdoDevice)
105 {
106 DPRINT("USBPORT_DoSetPowerD0: FIXME!\n");
107 return;
108 }
109
110 VOID
111 NTAPI
112 USBPORT_SuspendController(IN PDEVICE_OBJECT FdoDevice)
113 {
114 PUSBPORT_DEVICE_EXTENSION FdoExtension;
115 PUSBPORT_REGISTRATION_PACKET Packet;
116
117 DPRINT1("USBPORT_SuspendController \n");
118
119 FdoExtension = FdoDevice->DeviceExtension;
120 Packet = &FdoExtension->MiniPortInterface->Packet;
121
122 FdoExtension->TimerFlags |= USBPORT_TMFLAG_RH_SUSPENDED;
123
124 USBPORT_FlushController(FdoDevice);
125
126 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
127 {
128 return;
129 }
130
131 FdoExtension->TimerFlags |= USBPORT_TMFLAG_HC_SUSPENDED;
132
133 if (FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
134 {
135 FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_SUSPENDED;
136
137 USBPORT_Wait(FdoDevice, 10);
138 Packet->SuspendController(FdoExtension->MiniPortExt);
139 }
140
141 FdoExtension->Flags |= USBPORT_FLAG_HC_SUSPEND;
142 }
143
144 NTSTATUS
145 NTAPI
146 USBPORT_ResumeController(IN PDEVICE_OBJECT FdoDevice)
147 {
148 NTSTATUS Status = STATUS_UNSUCCESSFUL;
149 PUSBPORT_DEVICE_EXTENSION FdoExtension;
150 PUSBPORT_REGISTRATION_PACKET Packet;
151 KIRQL OldIrql;
152 MPSTATUS MpStatus;
153
154 DPRINT1("USBPORT_ResumeController: ... \n");
155
156 FdoExtension = FdoDevice->DeviceExtension;
157 Packet = &FdoExtension->MiniPortInterface->Packet;
158
159 if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
160 {
161 return Status;
162 }
163
164 KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
165
166 FdoExtension->TimerFlags &= ~(USBPORT_TMFLAG_HC_SUSPENDED |
167 USBPORT_TMFLAG_RH_SUSPENDED);
168
169 KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
170
171 if (!(FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED))
172 {
173 FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
174 return Status;
175 }
176
177 FdoExtension->MiniPortFlags &= ~USBPORT_MPFLAG_SUSPENDED;
178
179 if (!Packet->ResumeController(FdoExtension->MiniPortExt))
180 {
181 Status = USBPORT_Wait(FdoDevice, 100);
182
183 FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
184 return Status;
185 }
186
187 KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
188 FdoExtension->TimerFlags |= (USBPORT_TMFLAG_HC_SUSPENDED |
189 USBPORT_TMFLAG_HC_RESUME);
190 KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
191
192 USBPORT_MiniportInterrupts(FdoDevice, FALSE);
193
194 Packet->StopController(FdoExtension->MiniPortExt, 1);
195
196 USBPORT_NukeAllEndpoints(FdoDevice);
197
198 RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
199
200 RtlZeroMemory(FdoExtension->UsbPortResources.StartVA,
201 Packet->MiniPortResourcesSize);
202
203 FdoExtension->UsbPortResources.IsChirpHandled = TRUE;
204
205 MpStatus = Packet->StartController(FdoExtension->MiniPortExt,
206 &FdoExtension->UsbPortResources);
207
208 FdoExtension->UsbPortResources.IsChirpHandled = FALSE;
209
210 if (!MpStatus)
211 {
212 USBPORT_MiniportInterrupts(FdoDevice, TRUE);
213 }
214
215 KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
216
217 FdoExtension->TimerFlags &= ~(USBPORT_TMFLAG_HC_SUSPENDED |
218 USBPORT_TMFLAG_HC_RESUME |
219 USBPORT_TMFLAG_RH_SUSPENDED);
220
221 KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
222
223 Status = USBPORT_Wait(FdoDevice, 100);
224
225 FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
226
227 return Status;
228 }
229
230 NTSTATUS
231 NTAPI
232 USBPORT_PdoDevicePowerState(IN PDEVICE_OBJECT PdoDevice,
233 IN PIRP Irp)
234 {
235 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
236 PDEVICE_OBJECT FdoDevice;
237 PUSBPORT_DEVICE_EXTENSION FdoExtension;
238 PIO_STACK_LOCATION IoStack;
239 NTSTATUS Status = STATUS_SUCCESS;
240 POWER_STATE State;
241
242 PdoExtension = PdoDevice->DeviceExtension;
243 FdoDevice = PdoExtension->FdoDevice;
244 FdoExtension = FdoDevice->DeviceExtension;
245 IoStack = IoGetCurrentIrpStackLocation(Irp);
246
247 State = IoStack->Parameters.Power.State;
248
249 DPRINT1("USBPORT_PdoDevicePowerState: Irp - %p, State - %x\n",
250 Irp,
251 State.DeviceState);
252
253 if (State.DeviceState == PowerDeviceD0)
254 {
255 if (FdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0)
256 {
257 // FIXME FdoExtension->Flags
258 while (FdoExtension->SetPowerLockCounter)
259 {
260 USBPORT_Wait(FdoDevice, 10);
261 }
262
263 USBPORT_ResumeController(FdoDevice);
264
265 PdoExtension->CommonExtension.DevicePowerState = PowerDeviceD0;
266
267 USBPORT_CompletePdoWaitWake(FdoDevice);
268 USBPORT_CompletePendingIdleIrp(PdoDevice);
269 }
270 else
271 {
272 DPRINT1("USBPORT_PdoDevicePowerState: FdoExtension->Flags - %lx\n",
273 FdoExtension->Flags);
274
275 DbgBreakPoint();
276 Status = STATUS_UNSUCCESSFUL;
277 }
278 }
279 else if (State.DeviceState == PowerDeviceD1 ||
280 State.DeviceState == PowerDeviceD2 ||
281 State.DeviceState == PowerDeviceD3)
282 {
283 FdoExtension->TimerFlags |= USBPORT_TMFLAG_WAKE;
284 USBPORT_SuspendController(FdoDevice);
285 PdoExtension->CommonExtension.DevicePowerState = State.DeviceState;
286 }
287
288 return Status;
289 }
290
291 VOID
292 NTAPI
293 USBPORT_CancelPendingWakeIrp(IN PDEVICE_OBJECT PdoDevice,
294 IN PIRP Irp)
295 {
296 PUSBPORT_DEVICE_EXTENSION FdoExtension;
297 KIRQL OldIrql;
298 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
299
300 DPRINT("USBPORT_CancelPendingWakeIrp: ... \n");
301
302 IoReleaseCancelSpinLock(Irp->CancelIrql);
303 PdoExtension = PdoDevice->DeviceExtension;
304 FdoExtension = PdoExtension->FdoDevice->DeviceExtension;
305
306 KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
307
308 if (PdoExtension->WakeIrp == Irp)
309 {
310 PdoExtension->WakeIrp = NULL;
311 }
312
313 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
314
315 Irp->IoStatus.Status = STATUS_CANCELLED;
316 Irp->IoStatus.Information = 0;
317 IoCompleteRequest(Irp, IO_NO_INCREMENT);
318 }
319
320 NTSTATUS
321 NTAPI
322 USBPORT_PdoPower(IN PDEVICE_OBJECT PdoDevice,
323 IN PIRP Irp)
324 {
325 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
326 PDEVICE_OBJECT FdoDevice;
327 PIO_STACK_LOCATION IoStack;
328 PUSBPORT_DEVICE_EXTENSION FdoExtension;
329 NTSTATUS Status;
330 KIRQL OldIrql;
331
332 DPRINT("USBPORT_PdoPower: Irp - %p\n", Irp);
333
334 PdoExtension = PdoDevice->DeviceExtension;
335 FdoDevice = PdoExtension->FdoDevice;
336 FdoExtension = FdoDevice->DeviceExtension;
337 IoStack = IoGetCurrentIrpStackLocation(Irp);
338
339 Status = Irp->IoStatus.Status;
340
341 switch (IoStack->MinorFunction)
342 {
343 case IRP_MN_WAIT_WAKE:
344 DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE\n");
345
346 if (!(FdoExtension->Flags & USBPORT_FLAG_HC_STARTED))
347 {
348 /* The device does not support wake-up */
349 Status = STATUS_NOT_SUPPORTED;
350 break;
351 }
352
353 KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
354
355 IoSetCancelRoutine(Irp, USBPORT_CancelPendingWakeIrp);
356
357 /* Check if the IRP has been cancelled */
358 if (Irp->Cancel)
359 {
360 if (IoSetCancelRoutine(Irp, NULL))
361 {
362 /* IRP has been cancelled, release cancel spinlock */
363 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
364
365 DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - STATUS_CANCELLED\n");
366
367 /* IRP is cancelled */
368 Status = STATUS_CANCELLED;
369 break;
370 }
371 }
372
373 if (!PdoExtension->WakeIrp)
374 {
375 /* The driver received the IRP
376 and is waiting for the device to signal wake-up. */
377
378 DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - No WakeIrp\n");
379
380 IoMarkIrpPending(Irp);
381 PdoExtension->WakeIrp = Irp;
382
383 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
384 return STATUS_PENDING;
385 }
386 else
387 {
388 /* An IRP_MN_WAIT_WAKE request is already pending and must be
389 completed or canceled before another IRP_MN_WAIT_WAKE request
390 can be issued. */
391
392 if (IoSetCancelRoutine(Irp, NULL))
393 {
394 DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - STATUS_DEVICE_BUSY\n");
395
396 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
397 PoStartNextPowerIrp(Irp);
398 Status = STATUS_DEVICE_BUSY;
399 break;
400 }
401 else
402 {
403 ASSERT(FALSE);
404 KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
405 return Status;
406 }
407 }
408
409 case IRP_MN_POWER_SEQUENCE:
410 DPRINT("USBPORT_PdoPower: IRP_MN_POWER_SEQUENCE\n");
411 PoStartNextPowerIrp(Irp);
412 break;
413
414 case IRP_MN_SET_POWER:
415 DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER\n");
416
417 if (IoStack->Parameters.Power.Type == DevicePowerState)
418 {
419 DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER/DevicePowerState\n");
420 Status = USBPORT_PdoDevicePowerState(PdoDevice, Irp);
421 PoStartNextPowerIrp(Irp);
422 break;
423 }
424
425 DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER/SystemPowerState \n");
426
427 if (IoStack->Parameters.Power.State.SystemState == PowerSystemWorking)
428 {
429 FdoExtension->TimerFlags |= USBPORT_TMFLAG_WAKE;
430 }
431 else
432 {
433 FdoExtension->TimerFlags &= ~USBPORT_TMFLAG_WAKE;
434 }
435
436 Status = STATUS_SUCCESS;
437
438 PoStartNextPowerIrp(Irp);
439 break;
440
441 case IRP_MN_QUERY_POWER:
442 DPRINT("USBPORT_PdoPower: IRP_MN_QUERY_POWER\n");
443 Status = STATUS_SUCCESS;
444 PoStartNextPowerIrp(Irp);
445 break;
446
447 default:
448 DPRINT1("USBPORT_PdoPower: unknown IRP_MN_POWER!\n");
449 PoStartNextPowerIrp(Irp);
450 break;
451 }
452
453 Irp->IoStatus.Status = Status;
454 Irp->IoStatus.Information = 0;
455 IoCompleteRequest(Irp, IO_NO_INCREMENT);
456
457 return Status;
458 }
459
460 NTSTATUS
461 NTAPI
462 USBPORT_HcWake(IN PDEVICE_OBJECT FdoDevice,
463 IN PIRP Irp)
464 {
465 DPRINT1("USBPORT_HcWake: UNIMPLEMENTED. FIXME. \n");
466 return STATUS_SUCCESS;
467 }
468
469 NTSTATUS
470 NTAPI
471 USBPORT_DevicePowerState(IN PDEVICE_OBJECT FdoDevice,
472 IN PIRP Irp)
473 {
474 DPRINT1("USBPORT_DevicePowerState: UNIMPLEMENTED. FIXME. \n");
475 return STATUS_SUCCESS;
476 }
477
478 NTSTATUS
479 NTAPI
480 USBPORT_SystemPowerState(IN PDEVICE_OBJECT FdoDevice,
481 IN PIRP Irp)
482 {
483 DPRINT1("USBPORT_SystemPowerState: UNIMPLEMENTED. FIXME. \n");
484 return STATUS_SUCCESS;
485 }
486
487 NTSTATUS
488 NTAPI
489 USBPORT_FdoPower(IN PDEVICE_OBJECT FdoDevice,
490 IN PIRP Irp)
491 {
492 PUSBPORT_DEVICE_EXTENSION FdoExtension;
493 PIO_STACK_LOCATION IoStack;
494 NTSTATUS Status;
495
496 DPRINT("USBPORT_FdoPower: ... \n");
497
498 FdoExtension = FdoDevice->DeviceExtension;
499 IoStack = IoGetCurrentIrpStackLocation(Irp);
500
501 switch (IoStack->MinorFunction)
502 {
503 case IRP_MN_WAIT_WAKE:
504 DPRINT("USBPORT_FdoPower: IRP_MN_WAIT_WAKE\n");
505 Status = USBPORT_HcWake(FdoDevice, Irp);
506 return Status;
507
508 case IRP_MN_POWER_SEQUENCE:
509 DPRINT("USBPORT_FdoPower: IRP_MN_POWER_SEQUENCE\n");
510 break;
511
512 case IRP_MN_SET_POWER:
513 DPRINT("USBPORT_FdoPower: IRP_MN_SET_POWER\n");
514 if (IoStack->Parameters.Power.Type == DevicePowerState)
515 {
516 Status = USBPORT_DevicePowerState(FdoDevice, Irp);
517 }
518 else
519 {
520 Status = USBPORT_SystemPowerState(FdoDevice, Irp);
521 }
522
523 if (Status != STATUS_PENDING)
524 break;
525
526 return Status;
527
528 case IRP_MN_QUERY_POWER:
529 DPRINT("USBPORT_FdoPower: IRP_MN_QUERY_POWER\n");
530 Irp->IoStatus.Status = STATUS_SUCCESS;
531 break;
532
533 default:
534 DPRINT1("USBPORT_FdoPower: unknown IRP_MN_POWER!\n");
535 break;
536 }
537
538 IoCopyCurrentIrpStackLocationToNext(Irp);
539 PoStartNextPowerIrp(Irp);
540 return PoCallDriver(FdoExtension->CommonExtension.LowerDevice, Irp);
541 }
542
543 VOID
544 NTAPI
545 USBPORT_DoIdleNotificationCallback(IN PVOID Context)
546 {
547 PIO_STACK_LOCATION IoStack;
548 PDEVICE_OBJECT FdoDevice;
549 PUSBPORT_DEVICE_EXTENSION FdoExtension;
550 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
551 PIRP NextIrp;
552 LARGE_INTEGER CurrentTime = {{0, 0}};
553 PTIMER_WORK_QUEUE_ITEM IdleQueueItem;
554 PDEVICE_OBJECT PdoDevice;
555 PUSB_IDLE_CALLBACK_INFO IdleCallbackInfo;
556 KIRQL OldIrql;
557
558 DPRINT("USBPORT_DoIdleNotificationCallback \n");
559
560 IdleQueueItem = Context;
561
562 FdoDevice = IdleQueueItem->FdoDevice;
563 FdoExtension = FdoDevice->DeviceExtension;
564 PdoDevice = FdoExtension->RootHubPdo;
565 PdoExtension = PdoDevice->DeviceExtension;
566
567 KeQuerySystemTime(&CurrentTime);
568
569 if ((FdoExtension->IdleTime.QuadPart == 0) ||
570 (((CurrentTime.QuadPart - FdoExtension->IdleTime.QuadPart) / 10000) >= 500))
571 {
572 if (PdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0 &&
573 FdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0)
574 {
575 NextIrp = IoCsqRemoveNextIrp(&FdoExtension->IdleIoCsq, NULL);
576
577 if (NextIrp)
578 {
579 IoStack = IoGetCurrentIrpStackLocation(NextIrp);
580 IdleCallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
581
582 if (IdleCallbackInfo && IdleCallbackInfo->IdleCallback)
583 {
584 IdleCallbackInfo->IdleCallback(IdleCallbackInfo->IdleContext);
585 }
586
587 if (NextIrp->Cancel)
588 {
589 InterlockedDecrement(&FdoExtension->IdleLockCounter);
590
591 NextIrp->IoStatus.Status = STATUS_CANCELLED;
592 NextIrp->IoStatus.Information = 0;
593 IoCompleteRequest(NextIrp, IO_NO_INCREMENT);
594 }
595 else
596 {
597 IoCsqInsertIrp(&FdoExtension->IdleIoCsq, NextIrp, NULL);
598 }
599 }
600 }
601 }
602
603 KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
604 FdoExtension->TimerFlags &= ~USBPORT_TMFLAG_IDLE_QUEUEITEM_ON;
605 KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
606
607 ExFreePoolWithTag(IdleQueueItem, USB_PORT_TAG);
608 }
609
610 NTSTATUS
611 NTAPI
612 USBPORT_IdleNotification(IN PDEVICE_OBJECT PdoDevice,
613 IN PIRP Irp)
614 {
615 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
616 PDEVICE_OBJECT FdoDevice;
617 PUSBPORT_DEVICE_EXTENSION FdoExtension;
618 LONG LockCounter;
619 NTSTATUS Status = STATUS_PENDING;
620
621 DPRINT("USBPORT_IdleNotification: Irp - %p\n", Irp);
622
623 PdoExtension = PdoDevice->DeviceExtension;
624 FdoDevice = PdoExtension->FdoDevice;
625 FdoExtension = FdoDevice->DeviceExtension;
626
627 LockCounter = InterlockedIncrement(&FdoExtension->IdleLockCounter);
628
629 if (LockCounter != 0)
630 {
631 if (Status != STATUS_PENDING)
632 {
633 InterlockedDecrement(&FdoExtension->IdleLockCounter);
634
635 Irp->IoStatus.Status = Status;
636 Irp->IoStatus.Information = 0;
637 IoCompleteRequest(Irp, IO_NO_INCREMENT);
638
639 return Status;
640 }
641
642 Status = STATUS_DEVICE_BUSY;
643 }
644
645 if (Status != STATUS_PENDING)
646 {
647 InterlockedDecrement(&FdoExtension->IdleLockCounter);
648
649 Irp->IoStatus.Status = Status;
650 Irp->IoStatus.Information = 0;
651 IoCompleteRequest(Irp, IO_NO_INCREMENT);
652
653 return Status;
654 }
655
656 Irp->IoStatus.Status = STATUS_PENDING;
657 IoMarkIrpPending(Irp);
658
659 KeQuerySystemTime(&FdoExtension->IdleTime);
660
661 IoCsqInsertIrp(&FdoExtension->IdleIoCsq, Irp, 0);
662
663 return Status;
664 }
665
666 VOID
667 NTAPI
668 USBPORT_AdjustDeviceCapabilities(IN PDEVICE_OBJECT FdoDevice,
669 IN PDEVICE_OBJECT PdoDevice)
670 {
671 PUSBPORT_DEVICE_EXTENSION FdoExtension;
672 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
673 PDEVICE_CAPABILITIES Capabilities;
674
675 DPRINT("USBPORT_AdjustDeviceCapabilities: ... \n");
676
677 FdoExtension = FdoDevice->DeviceExtension;
678 PdoExtension = PdoDevice->DeviceExtension;
679 Capabilities = &PdoExtension->Capabilities;
680
681 RtlCopyMemory(Capabilities,
682 &FdoExtension->Capabilities,
683 sizeof(DEVICE_CAPABILITIES));
684
685 Capabilities->DeviceD1 = FALSE;
686 Capabilities->DeviceD2 = TRUE;
687
688 Capabilities->Removable = FALSE;
689 Capabilities->UniqueID = FALSE;
690
691 Capabilities->WakeFromD0 = TRUE;
692 Capabilities->WakeFromD1 = FALSE;
693 Capabilities->WakeFromD2 = TRUE;
694 Capabilities->WakeFromD3 = FALSE;
695
696 Capabilities->Address = 0;
697 Capabilities->UINumber = 0;
698
699 if (Capabilities->SystemWake == PowerSystemUnspecified)
700 Capabilities->SystemWake = PowerSystemWorking;
701
702 Capabilities->DeviceWake = PowerDeviceD2;
703
704 Capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
705 Capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
706 Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
707 Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
708 }