1 // Copyright (c) 2004, Antony C. Roberts
3 // Use of this file is subject to the terms
4 // described in the LICENSE.TXT file that
5 // accompanies this file.
7 // Your use of this file indicates your
8 // acceptance of the terms described in
11 // http://www.freebt.net
22 // Handle power events
23 NTSTATUS NTAPI
FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
25 NTSTATUS ntStatus
= STATUS_SUCCESS
;
26 PIO_STACK_LOCATION irpStack
;
27 //PUNICODE_STRING tagString;
28 PDEVICE_EXTENSION deviceExtension
;
30 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
31 deviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
33 // We don't queue power Irps, we'll only check if the
34 // device was removed, otherwise we'll take appropriate
35 // action and send it to the next lower driver. In general
36 // drivers should not cause long delays while handling power
37 // IRPs. If a driver cannot handle a power IRP in a brief time,
38 // it should return STATUS_PENDING and queue all incoming
39 // IRPs until the IRP completes.
40 if (Removed
== deviceExtension
->DeviceState
)
43 // Even if a driver fails the IRP, it must nevertheless call
44 // PoStartNextPowerIrp to inform the Power Manager that it
45 // is ready to handle another power IRP.
46 PoStartNextPowerIrp(Irp
);
47 Irp
->IoStatus
.Status
= ntStatus
= STATUS_DELETE_PENDING
;
48 Irp
->IoStatus
.Information
= 0;
49 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
55 if (NotStarted
== deviceExtension
->DeviceState
)
57 // if the device is not started yet, pass it down
58 PoStartNextPowerIrp(Irp
);
59 IoSkipCurrentIrpStackLocation(Irp
);
61 return PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
65 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
66 FreeBT_IoIncrement(deviceExtension
);
68 switch(irpStack
->MinorFunction
)
70 case IRP_MN_SET_POWER
:
71 // The Power Manager sends this IRP for one of the
74 // 1) To notify drivers of a change to the system power state.
75 // 2) To change the power state of a device for which
76 // the Power Manager is performing idle detection.
78 // A driver sends IRP_MN_SET_POWER to change the power
79 // state of its device if it's a power policy owner for the
81 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n"));
82 IoMarkIrpPending(Irp
);
84 switch(irpStack
->Parameters
.Power
.Type
)
86 case SystemPowerState
:
87 HandleSystemSetPower(DeviceObject
, Irp
);
88 ntStatus
= STATUS_PENDING
;
91 case DevicePowerState
:
92 HandleDeviceSetPower(DeviceObject
, Irp
);
93 ntStatus
= STATUS_PENDING
;
100 case IRP_MN_QUERY_POWER
:
101 // The Power Manager sends a power IRP with the minor
102 // IRP code IRP_MN_QUERY_POWER to determine whether it
103 // can safely change to the specified system power state
104 // (S1-S5) and to allow drivers to prepare for such a change.
105 // If a driver can put its device in the requested state,
106 // it sets status to STATUS_SUCCESS and passes the IRP down.
107 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n"));
108 IoMarkIrpPending(Irp
);
110 switch(irpStack
->Parameters
.Power
.Type
)
112 case SystemPowerState
:
113 HandleSystemQueryPower(DeviceObject
, Irp
);
114 ntStatus
= STATUS_PENDING
;
117 case DevicePowerState
:
118 HandleDeviceQueryPower(DeviceObject
, Irp
);
119 ntStatus
= STATUS_PENDING
;
126 case IRP_MN_WAIT_WAKE
:
127 // The minor power IRP code IRP_MN_WAIT_WAKE provides
128 // for waking a device or waking the system. Drivers
129 // of devices that can wake themselves or the system
130 // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
131 // only to devices that always wake the system, such as
132 // the power-on switch.
133 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n"));
134 IoMarkIrpPending(Irp
);
135 IoCopyCurrentIrpStackLocationToNext(Irp
);
136 IoSetCompletionRoutine(
138 (PIO_COMPLETION_ROUTINE
)WaitWakeCompletionRoutine
,
144 PoStartNextPowerIrp(Irp
);
145 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
146 if(!NT_SUCCESS(ntStatus
))
148 FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n"));
152 ntStatus
= STATUS_PENDING
;
154 // push back the count HERE and NOT in completion routine
155 // a pending Wait Wake Irp should not impede stopping the device
156 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::"));
157 FreeBT_IoDecrement(deviceExtension
);
160 case IRP_MN_POWER_SEQUENCE
:
161 // A driver sends this IRP as an optimization to determine
162 // whether its device actually entered a specific power state.
163 // This IRP is optional. Power Manager cannot send this IRP.
164 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n"));
167 PoStartNextPowerIrp(Irp
);
168 IoSkipCurrentIrpStackLocation(Irp
);
169 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
170 if(!NT_SUCCESS(ntStatus
))
172 FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n"));
176 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
177 FreeBT_IoDecrement(deviceExtension
);
187 NTSTATUS NTAPI
HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
190 PDEVICE_EXTENSION deviceExtension
;
191 SYSTEM_POWER_STATE systemState
;
192 PIO_STACK_LOCATION irpStack
;
194 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Entered\n"));
196 // initialize variables
197 deviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
198 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
199 systemState
= irpStack
->Parameters
.Power
.State
.SystemState
;
201 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Query for system power state S%X\n"
202 "FBTUSB: HandleSystemQueryPower: Current system power state S%X\n",
204 deviceExtension
->SysPower
- 1));
206 // Fail a query for a power state incompatible with waking up the system
207 if ((deviceExtension
->WaitWakeEnable
) && (systemState
> deviceExtension
->DeviceCapabilities
.SystemWake
))
209 FreeBT_DbgPrint(1, ("FBTUSB: HandleSystemQueryPower: Query for an incompatible system power state\n"));
211 PoStartNextPowerIrp(Irp
);
212 Irp
->IoStatus
.Status
= ntStatus
= STATUS_INVALID_DEVICE_STATE
;
213 Irp
->IoStatus
.Information
= 0;
214 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
216 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower::"));
217 FreeBT_IoDecrement(deviceExtension
);
223 // if querying for a lower S-state, issue a wait-wake
224 if((systemState
> deviceExtension
->SysPower
) && (deviceExtension
->WaitWakeEnable
))
226 IssueWaitWake(deviceExtension
);
230 IoCopyCurrentIrpStackLocationToNext(Irp
);
231 IoSetCompletionRoutine(
233 (PIO_COMPLETION_ROUTINE
)SysPoCompletionRoutine
,
239 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
240 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Leaving\n"));
242 return STATUS_PENDING
;
246 NTSTATUS NTAPI
HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
249 PDEVICE_EXTENSION deviceExtension
;
250 SYSTEM_POWER_STATE systemState
;
251 PIO_STACK_LOCATION irpStack
;
253 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Entered\n"));
255 deviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
256 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
257 systemState
= irpStack
->Parameters
.Power
.State
.SystemState
;
259 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Set request for system power state S%X\n"
260 "FBTUSB: HandleSystemSetPower: Current system power state S%X\n",
262 deviceExtension
->SysPower
- 1));
264 IoCopyCurrentIrpStackLocationToNext(Irp
);
265 IoSetCompletionRoutine(
267 (PIO_COMPLETION_ROUTINE
)SysPoCompletionRoutine
,
273 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
274 FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Leaving\n"));
276 return STATUS_PENDING
;
280 NTSTATUS NTAPI
HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
283 PDEVICE_EXTENSION deviceExtension
;
284 PIO_STACK_LOCATION irpStack
;
285 DEVICE_POWER_STATE deviceState
;
287 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Entered\n"));
289 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
290 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
291 deviceState
= irpStack
->Parameters
.Power
.State
.DeviceState
;
293 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Query for device power state D%X\n"
294 "FBTUSB: HandleDeviceQueryPower: Current device power state D%X\n",
296 deviceExtension
->DevPower
- 1));
298 if (deviceExtension
->WaitWakeEnable
&& deviceState
> deviceExtension
->DeviceCapabilities
.DeviceWake
)
300 PoStartNextPowerIrp(Irp
);
301 Irp
->IoStatus
.Status
= ntStatus
= STATUS_INVALID_DEVICE_STATE
;
302 Irp
->IoStatus
.Information
= 0;
303 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
305 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
306 FreeBT_IoDecrement(deviceExtension
);
312 if (deviceState
< deviceExtension
->DevPower
)
314 ntStatus
= STATUS_SUCCESS
;
320 ntStatus
= HoldIoRequests(DeviceObject
, Irp
);
321 if(STATUS_PENDING
== ntStatus
)
329 // on error complete the Irp.
330 // on success pass it to the lower layers
331 PoStartNextPowerIrp(Irp
);
332 Irp
->IoStatus
.Status
= ntStatus
;
333 Irp
->IoStatus
.Information
= 0;
334 if(!NT_SUCCESS(ntStatus
))
336 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
342 IoSkipCurrentIrpStackLocation(Irp
);
343 ntStatus
=PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
347 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
348 FreeBT_IoDecrement(deviceExtension
);
350 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Leaving\n"));
357 NTSTATUS NTAPI
SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PDEVICE_EXTENSION DeviceExtension
)
360 PIO_STACK_LOCATION irpStack
;
362 ntStatus
= Irp
->IoStatus
.Status
;
363 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
365 FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Entered\n"));
367 // lower drivers failed this Irp
368 if(!NT_SUCCESS(ntStatus
))
370 PoStartNextPowerIrp(Irp
);
371 FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine::"));
372 FreeBT_IoDecrement(DeviceExtension
);
374 return STATUS_SUCCESS
;
378 // ..otherwise update the cached system power state (IRP_MN_SET_POWER)
379 if(irpStack
->MinorFunction
== IRP_MN_SET_POWER
)
381 DeviceExtension
->SysPower
= irpStack
->Parameters
.Power
.State
.SystemState
;
385 // queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
386 SendDeviceIrp(DeviceObject
, Irp
);
388 FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Leaving\n"));
390 return STATUS_MORE_PROCESSING_REQUIRED
;
394 VOID NTAPI
SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP SIrp
)
397 POWER_STATE powState
;
398 PDEVICE_EXTENSION deviceExtension
;
399 PIO_STACK_LOCATION irpStack
;
400 SYSTEM_POWER_STATE systemState
;
401 DEVICE_POWER_STATE devState
;
402 PPOWER_COMPLETION_CONTEXT powerContext
;
404 irpStack
= IoGetCurrentIrpStackLocation(SIrp
);
405 systemState
= irpStack
->Parameters
.Power
.State
.SystemState
;
406 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
408 FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n"));
410 // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
411 // we can choose deeper sleep states than our mapping but never choose
413 devState
= deviceExtension
->DeviceCapabilities
.DeviceState
[systemState
];
414 powState
.DeviceState
= devState
;
416 powerContext
= (PPOWER_COMPLETION_CONTEXT
) ExAllocatePool(NonPagedPool
, sizeof(POWER_COMPLETION_CONTEXT
));
419 FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n"));
420 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
426 powerContext
->DeviceObject
= DeviceObject
;
427 powerContext
->SIrp
= SIrp
;
429 // in win2k PoRequestPowerIrp can take fdo or pdo.
430 ntStatus
= PoRequestPowerIrp(
431 deviceExtension
->PhysicalDeviceObject
,
432 irpStack
->MinorFunction
,
434 (PREQUEST_POWER_COMPLETE
)DevPoCompletionRoutine
,
440 if (!NT_SUCCESS(ntStatus
))
444 ExFreePool(powerContext
);
448 PoStartNextPowerIrp(SIrp
);
449 SIrp
->IoStatus
.Status
= ntStatus
;
450 SIrp
->IoStatus
.Information
= 0;
451 IoCompleteRequest(SIrp
, IO_NO_INCREMENT
);
453 FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::"));
454 FreeBT_IoDecrement(deviceExtension
);
458 FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n"));
463 VOID NTAPI
DevPoCompletionRoutine(
464 IN PDEVICE_OBJECT DeviceObject
,
465 IN UCHAR MinorFunction
,
466 IN POWER_STATE PowerState
,
468 IN PIO_STATUS_BLOCK IoStatus
472 PDEVICE_EXTENSION deviceExtension
;
473 PPOWER_COMPLETION_CONTEXT powerContext
;
475 powerContext
= (PPOWER_COMPLETION_CONTEXT
) Context
;
476 sIrp
= powerContext
->SIrp
;
477 deviceExtension
= (PDEVICE_EXTENSION
) powerContext
->DeviceObject
->DeviceExtension
;
479 FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Entered\n"));
481 sIrp
->IoStatus
.Status
= IoStatus
->Status
;
482 PoStartNextPowerIrp(sIrp
);
483 sIrp
->IoStatus
.Information
= 0;
484 IoCompleteRequest(sIrp
, IO_NO_INCREMENT
);
486 FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine::"));
487 FreeBT_IoDecrement(deviceExtension
);
489 ExFreePool(powerContext
);
491 FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Leaving\n"));
495 NTSTATUS NTAPI
HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
499 POWER_STATE newState
;
500 PIO_STACK_LOCATION irpStack
;
501 PDEVICE_EXTENSION deviceExtension
;
502 DEVICE_POWER_STATE newDevState
,
505 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n"));
507 deviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
508 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
509 oldDevState
= deviceExtension
->DevPower
;
510 newState
= irpStack
->Parameters
.Power
.State
;
511 newDevState
= newState
.DeviceState
;
513 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n"
514 "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n",
516 deviceExtension
->DevPower
- 1));
518 if (newDevState
< oldDevState
)
521 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n"));
523 IoCopyCurrentIrpStackLocationToNext(Irp
);
524 IoSetCompletionRoutine(
526 (PIO_COMPLETION_ROUTINE
)FinishDevPoUpIrp
,
532 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
538 // newDevState >= oldDevState
540 // hold I/O if transition from D0 -> DX (X = 1, 2, 3)
541 // if transition from D1 or D2 to deeper sleep states,
542 // I/O queue is already on hold.
543 if(PowerDeviceD0
== oldDevState
&& newDevState
> oldDevState
)
545 // D0 -> DX transition
546 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n"));
548 ntStatus
= HoldIoRequests(DeviceObject
, Irp
);
549 if (!NT_SUCCESS(ntStatus
))
551 PoStartNextPowerIrp(Irp
);
552 Irp
->IoStatus
.Status
= ntStatus
;
553 Irp
->IoStatus
.Information
= 0;
554 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
556 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::"));
557 FreeBT_IoDecrement(deviceExtension
);
565 goto HandleDeviceSetPower_Exit
;
571 else if (PowerDeviceD0
== oldDevState
&& PowerDeviceD0
== newDevState
)
574 // unblock the queue which may have been blocked processing
576 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n"));
578 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
579 deviceExtension
->QueueState
= AllowRequests
;
580 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
582 ProcessQueuedRequests(deviceExtension
);
586 IoCopyCurrentIrpStackLocationToNext(Irp
);
587 IoSetCompletionRoutine(
589 (PIO_COMPLETION_ROUTINE
) FinishDevPoDnIrp
,
595 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
596 if(!NT_SUCCESS(ntStatus
))
598 FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n"));
604 HandleDeviceSetPower_Exit
:
606 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n"));
608 return STATUS_PENDING
;
612 NTSTATUS NTAPI
FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PDEVICE_EXTENSION DeviceExtension
)
616 FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Entered\n"));
618 ntStatus
= Irp
->IoStatus
.Status
;
619 if(Irp
->PendingReturned
)
621 IoMarkIrpPending(Irp
);
625 if(!NT_SUCCESS(ntStatus
))
627 PoStartNextPowerIrp(Irp
);
629 FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp::"));
630 FreeBT_IoDecrement(DeviceExtension
);
632 return STATUS_SUCCESS
;
636 SetDeviceFunctional(DeviceObject
, Irp
, DeviceExtension
);
638 FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Leaving\n"));
640 return STATUS_MORE_PROCESSING_REQUIRED
;
644 NTSTATUS NTAPI
SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PDEVICE_EXTENSION DeviceExtension
)
648 POWER_STATE newState
;
649 PIO_STACK_LOCATION irpStack
;
650 DEVICE_POWER_STATE newDevState
, oldDevState
;
652 ntStatus
= Irp
->IoStatus
.Status
;
653 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
654 newState
= irpStack
->Parameters
.Power
.State
;
655 newDevState
= newState
.DeviceState
;
656 oldDevState
= DeviceExtension
->DevPower
;
658 FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Entered\n"));
660 // update the cached state
661 DeviceExtension
->DevPower
= newDevState
;
663 // restore appropriate amount of state to our h/w
664 // this driver does not implement partial context
666 PoSetPowerState(DeviceObject
, DevicePowerState
, newState
);
667 if(PowerDeviceD0
== newDevState
)
669 KeAcquireSpinLock(&DeviceExtension
->DevStateLock
, &oldIrql
);
670 DeviceExtension
->QueueState
= AllowRequests
;
671 KeReleaseSpinLock(&DeviceExtension
->DevStateLock
, oldIrql
);
673 ProcessQueuedRequests(DeviceExtension
);
677 PoStartNextPowerIrp(Irp
);
678 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
679 Irp
->IoStatus
.Information
= 0;
680 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
682 FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional::"));
683 FreeBT_IoDecrement(DeviceExtension
);
685 FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Leaving\n"));
687 return STATUS_SUCCESS
;
691 NTSTATUS NTAPI
FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PDEVICE_EXTENSION DeviceExtension
)
694 POWER_STATE newState
;
695 PIO_STACK_LOCATION irpStack
;
697 FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Entered\n"));
699 ntStatus
= Irp
->IoStatus
.Status
;
700 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
701 newState
= irpStack
->Parameters
.Power
.State
;
703 if (NT_SUCCESS(ntStatus
) && irpStack
->MinorFunction
== IRP_MN_SET_POWER
)
705 FreeBT_DbgPrint(3, ("FBTUSB: updating cache..\n"));
706 DeviceExtension
->DevPower
= newState
.DeviceState
;
707 PoSetPowerState(DeviceObject
, DevicePowerState
, newState
);
711 PoStartNextPowerIrp(Irp
);
713 FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp::"));
714 FreeBT_IoDecrement(DeviceExtension
);
716 FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Leaving\n"));
718 return STATUS_SUCCESS
;
722 NTSTATUS NTAPI
HoldIoRequests(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
727 PDEVICE_EXTENSION deviceExtension
;
728 PWORKER_THREAD_CONTEXT context
;
730 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Entered\n"));
732 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
733 deviceExtension
->QueueState
= HoldRequests
;
735 context
= (PWORKER_THREAD_CONTEXT
) ExAllocatePool(NonPagedPool
, sizeof(WORKER_THREAD_CONTEXT
));
738 item
= IoAllocateWorkItem(DeviceObject
);
741 context
->DeviceObject
= DeviceObject
;
742 context
->WorkItem
= item
;
746 IoMarkIrpPending(Irp
);
747 IoQueueWorkItem(item
, HoldIoRequestsWorkerRoutine
, DelayedWorkQueue
, context
);
748 ntStatus
= STATUS_PENDING
;
754 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Failed to allocate memory for workitem\n"));
756 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
764 FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequests: Failed to alloc memory for worker thread context\n"));
765 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
769 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Leaving\n"));
775 VOID NTAPI
HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
)
779 PDEVICE_EXTENSION deviceExtension
;
780 PWORKER_THREAD_CONTEXT context
;
782 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Entered\n"));
784 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
785 context
= (PWORKER_THREAD_CONTEXT
) Context
;
786 irp
= (PIRP
) context
->Irp
;
788 // wait for I/O in progress to finish.
789 // the stop event is signalled when the counter drops to 1.
790 // invoke FreeBT_IoDecrement twice: once each for the S-Irp and D-Irp.
791 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
792 FreeBT_IoDecrement(deviceExtension
);
794 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
795 FreeBT_IoDecrement(deviceExtension
);
797 KeWaitForSingleObject(&deviceExtension
->StopEvent
, Executive
, KernelMode
, FALSE
, NULL
);
799 // Increment twice to restore the count
800 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
801 FreeBT_IoIncrement(deviceExtension
);
803 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
804 FreeBT_IoIncrement(deviceExtension
);
806 // now send the Irp down
807 IoCopyCurrentIrpStackLocationToNext(irp
);
808 IoSetCompletionRoutine(
810 (PIO_COMPLETION_ROUTINE
) FinishDevPoDnIrp
,
816 ntStatus
= PoCallDriver(deviceExtension
->TopOfStackDeviceObject
, irp
);
817 if(!NT_SUCCESS(ntStatus
))
819 FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequestsWorkerRoutine: Lower driver fail a power Irp\n"));
823 IoFreeWorkItem(context
->WorkItem
);
824 ExFreePool((PVOID
)context
);
826 FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Leaving\n"));
830 NTSTATUS NTAPI
QueueRequest(IN OUT PDEVICE_EXTENSION DeviceExtension
, IN PIRP Irp
)
835 FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Entered\n"));
837 ntStatus
= STATUS_PENDING
;
839 ASSERT(HoldRequests
== DeviceExtension
->QueueState
);
841 KeAcquireSpinLock(&DeviceExtension
->QueueLock
, &oldIrql
);
843 InsertTailList(&DeviceExtension
->NewRequestsQueue
, &Irp
->Tail
.Overlay
.ListEntry
);
844 IoMarkIrpPending(Irp
);
845 IoSetCancelRoutine(Irp
, CancelQueued
);
847 KeReleaseSpinLock(&DeviceExtension
->QueueLock
, oldIrql
);
849 FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Leaving\n"));
855 VOID NTAPI
CancelQueued(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
857 PDEVICE_EXTENSION deviceExtension
;
860 FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Entered\n"));
862 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
863 oldIrql
= Irp
->CancelIrql
;
865 // Release the cancel spin lock
866 IoReleaseCancelSpinLock(Irp
->CancelIrql
);
868 // Acquire the queue lock
869 KeAcquireSpinLockAtDpcLevel(&deviceExtension
->QueueLock
);
871 // Remove the cancelled Irp from queue and release the lock
872 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
874 KeReleaseSpinLock(&deviceExtension
->QueueLock
, oldIrql
);
876 // complete with STATUS_CANCELLED
877 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
878 Irp
->IoStatus
.Information
= 0;
879 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
881 FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Leaving\n"));
887 NTSTATUS NTAPI
IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension
)
892 FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Entered\n"));
894 if(InterlockedExchange(&DeviceExtension
->FlagWWOutstanding
, 1))
896 return STATUS_DEVICE_BUSY
;
900 InterlockedExchange(&DeviceExtension
->FlagWWCancel
, 0);
902 // lowest state from which this Irp will wake the system
903 poState
.SystemState
= DeviceExtension
->DeviceCapabilities
.SystemWake
;
904 ntStatus
= PoRequestPowerIrp(DeviceExtension
->PhysicalDeviceObject
,
907 (PREQUEST_POWER_COMPLETE
) WaitWakeCallback
,
909 &DeviceExtension
->WaitWakeIrp
);
911 if(!NT_SUCCESS(ntStatus
))
913 InterlockedExchange(&DeviceExtension
->FlagWWOutstanding
, 0);
917 FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Leaving\n"));
923 VOID NTAPI
CancelWaitWake(IN PDEVICE_EXTENSION DeviceExtension
)
927 FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Entered\n"));
929 Irp
= (PIRP
) InterlockedExchangePointer(&DeviceExtension
->WaitWakeIrp
, NULL
);
933 if(InterlockedExchange(&DeviceExtension
->FlagWWCancel
, 1))
935 PoStartNextPowerIrp(Irp
);
936 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
937 Irp
->IoStatus
.Information
= 0;
938 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
944 FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Leaving\n"));
948 NTSTATUS NTAPI
WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PDEVICE_EXTENSION DeviceExtension
)
950 FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Entered\n"));
951 if(Irp
->PendingReturned
)
953 IoMarkIrpPending(Irp
);
957 // Nullify the WaitWakeIrp pointer-the Irp is released
958 // as part of the completion process. If it's already NULL,
959 // avoid race with the CancelWaitWake routine.
960 if(InterlockedExchangePointer(&DeviceExtension
->WaitWakeIrp
, NULL
))
962 PoStartNextPowerIrp(Irp
);
964 return STATUS_SUCCESS
;
968 // CancelWaitWake has run.
969 // If FlagWWCancel != 0, complete the Irp.
970 // If FlagWWCancel == 0, CancelWaitWake completes it.
971 if(InterlockedExchange(&DeviceExtension
->FlagWWCancel
, 1))
973 PoStartNextPowerIrp(Irp
);
975 return STATUS_CANCELLED
;
979 FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Leaving\n"));
981 return STATUS_MORE_PROCESSING_REQUIRED
;
985 VOID NTAPI
WaitWakeCallback(
986 IN PDEVICE_OBJECT DeviceObject
,
987 IN UCHAR MinorFunction
,
988 IN POWER_STATE PowerState
,
990 IN PIO_STATUS_BLOCK IoStatus
)
993 POWER_STATE powerState
;
994 PDEVICE_EXTENSION deviceExtension
;
996 FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n"));
998 deviceExtension
= (PDEVICE_EXTENSION
) Context
;
1000 InterlockedExchange(&deviceExtension
->FlagWWOutstanding
, 0);
1002 if(!NT_SUCCESS(IoStatus
->Status
))
1008 // wake up the device
1009 if(deviceExtension
->DevPower
== PowerDeviceD0
)
1011 FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n"));
1017 FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::"));
1018 FreeBT_IoIncrement(deviceExtension
);
1020 powerState
.DeviceState
= PowerDeviceD0
;
1021 ntStatus
= PoRequestPowerIrp(deviceExtension
->PhysicalDeviceObject
,
1024 (PREQUEST_POWER_COMPLETE
) WWIrpCompletionFunc
,
1028 if(deviceExtension
->WaitWakeEnable
)
1030 IssueWaitWake(deviceExtension
);
1034 FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n"));
1041 PCHAR NTAPI
PowerMinorFunctionString (IN UCHAR MinorFunction
)
1043 switch (MinorFunction
)
1045 case IRP_MN_SET_POWER
:
1046 return "IRP_MN_SET_POWER\n";
1048 case IRP_MN_QUERY_POWER
:
1049 return "IRP_MN_QUERY_POWER\n";
1051 case IRP_MN_POWER_SEQUENCE
:
1052 return "IRP_MN_POWER_SEQUENCE\n";
1054 case IRP_MN_WAIT_WAKE
:
1055 return "IRP_MN_WAIT_WAKE\n";
1058 return "IRP_MN_?????\n";