📄 usbfx2lk_power.cpp
字号:
PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT) Context;
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
POWER_STATE powerState;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: Entered...\n"));
switch (ioStack->MinorFunction) {
case IRP_MN_SET_POWER: {
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: IRP_MN_SET_POWER\n"));
//
// for SET_POWER we actually need to do some work...
//
//
// If the IRP failed for any reason, there is
// no reason to change any state.
//
if(!NT_SUCCESS(Irp->IoStatus.Status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_POWER_INFO,
("DevicePowerIoCompletionRoutine: Device Power Irp failed with status 0x%8.8x (%s)!\n",
Irp->IoStatus.Status, OsrNtStatusToString(Irp->IoStatus.Status)));
break;
}
powerState.DeviceState = ioStack->Parameters.Power.State.DeviceState;
//
// Powering up the device or staying at the same
// power state...
//
if(devExt->DevicePowerState >= powerState.DeviceState) {
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("DevicePowerIoCompletionRoutine: IRP_MN_SET_POWER Device powered up or stayed the same.\n"));
//
// Notify the power manager of the device power state change.
//
PoSetPowerState(DeviceObject,
DevicePowerState,
powerState);
devExt->DevicePowerState = powerState.DeviceState;
//
// Restore our state to STATE_STARTED
//
OsrUpdateDeviceState(devExt, STATE_STARTED);
//
// If we powered up and Wait Wake is Enabled, then Issue a
// Wait wake Request.
//
if(devExt->DevicePowerState == PowerDeviceD0 &&
devExt->WaitWakeEnable) {
IssueWaitWake(devExt);
}
//
// If we have gone to full power, and we are in an applicable state
// we need to restart the queues.
// OsrProcessQueuedRequests checks the power state for us before
// starting any queues.
//
OsrProcessQueuedRequests(devExt);
} else {
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO,
("DevicePowerIoCompletionRoutine: IRP_MN_SET_POWER Device powered down\n"));
}
//
// Update the power state in our device extension
//
devExt->DevicePowerState = powerState.DeviceState;
break;
}
default: {
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: %08.8x %s\n",
ioStack->MinorFunction,OsrMinorFunctionToString(ioStack->MajorFunction,ioStack->MinorFunction)));
break;
}
}
//
// Let the power manager know we are ready to handle
// the next DevicePowerState power IRP. Why did we
// wait until the Irp came back up before calling this
// routine? Well, it's actually pretty subtle.
// PoStartNextPowerIrp makes sure that we are only
// handling at most one D Irp and one S Irp at any
// time. We're handling a D Irp here so if we called
// PoStartNextPowerIrp on the way DOWN the stack, a
// request to power up could be coming UP the stack
// and a request to power down would be allowed to come
// DOWN the stack (or vice versa). We'd break the implied
// synchronization of only having one D Irp in the
// stack at any time, which could cause race conditions...
//
// Note that the failure case is different. If we need to
// fail an Irp in our OsrPower handler we can legally call
// PoStartNextPowerIrp and then complete the Irp with an
// error.
//
// Also note that if we receive a Power Irp with a minor
// function that we don't support we can also call
// PoStartNextPowerIrp in OsrPower and just pass the Irp
// down without a completion routine.
//
// Is it confusing enough yet?
//
PoStartNextPowerIrp(Irp);
//
// We're done with this request
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: Exiting!\n"));
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
//
// DevicePowerRequestCompletionRoutine
//
// Power request completion routine for device QUERY_POWER and SET_POWER IRPs.
//
// INPUTS:
//
// DeviceObject - Pointer to device object.
// MinorFunction - Power IRP's minor function code
// PowerState - The attempted device power state.
// Context - the device extension
// IoStatus - status block indicating the success or failure of the
// power IRP.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL <= DISPATCH_LEVEL
//
// CONTEXT:
//
// This routine is called in an arbitrary thread context
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID DevicePowerRequestCompletionRoutine(PDEVICE_OBJECT DeviceObject,UCHAR MinorFunction,
POWER_STATE PowerState,PVOID Context,PIO_STATUS_BLOCK IoStatus)
{
PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT) Context;
PIRP systemPowerIrp;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(MinorFunction);
UNREFERENCED_PARAMETER(PowerState);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerRequestCompletionRoutine: Entered...\n"));
//
// Get the system power IRP from our context
//
systemPowerIrp = devExt->SystemPowerIrp;
//
// This should not happen
//
ASSERT(NULL != systemPowerIrp);
//
// NULL out our temp storage for the IRP
//
devExt->SystemPowerIrp = NULL;
//
// Let the power manager know we are ready to handle
// the next SystemPowerState power IRP.
//
PoStartNextPowerIrp(systemPowerIrp);
//
// We complete the system power IRP here with the returned device
// power IRP's status. If any driver failed the device power IRP,
// the error is propagated to the system IRP this way.
//
systemPowerIrp->IoStatus.Status = IoStatus->Status;
//
// And we're done!
//
IoCompleteRequest(systemPowerIrp, IO_NO_INCREMENT);
//
// We're done with this request. We acquired the
// lock in OsrPower, so we'll use OsrPower as the
// tag here also
//
OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerRequestCompletionRoutine: Exiting!\n"));
}
///////////////////////////////////////////////////////////////////////////////
//
// IssueWaitWake
//
// This routine issues a WAIT_WAKE request in order enable the USB device
// to awaken in response to a user hitting the wake up button on the device.
//
// INPUTS:
//
// DevExt - Pointer to our Device Extension.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// This routine is called in an arbitrary thread context
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS IssueWaitWake(PUSBFX2LK_EXT DevExt)
{
NTSTATUS status;
POWER_STATE wakeState;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
VALID_DEVEXT(DevExt);
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE, ("IssueWaitWake: Entered\n"));
//
// Make sure that there is not a currently outstanding WaitWake request.
//
if(InterlockedExchange(&DevExt->FlagWWOutstanding, 1)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_WAIT_WAKE,
("IssueWaitWake: Wait Wake already outstanding, exit processing.\n"));
return STATUS_DEVICE_BUSY;
}
InterlockedExchange(&DevExt->FlagWWCancel, 0);
//
// Set up the System State from which the USB device is capable of waking
// up the system. Note that this information comes from the Device Capabilites
// information. This information must be filled in before we do the IssueWaitWake
// call.
//
wakeState.SystemState = DevExt->DeviceCapabilities.SystemWake;
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_WAIT_WAKE,
("IssueWaitWake: Issue Wait Wake for System state transition to %s\n",
OsrPrintSystemPowerState(wakeState.SystemState)));
//
// Request a Power Irp to deliver the Wait Wake Request.
status = PoRequestPowerIrp(DevExt->PhysicalDeviceObject,
IRP_MN_WAIT_WAKE,
wakeState,
(PREQUEST_POWER_COMPLETE) WaitWakeCallback,
DevExt,
&DevExt->WaitWakeIrp);
if(!NT_SUCCESS(status)) {
OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_WAIT_WAKE,
("IssueWaitWake: Device Power Irp failed with status 0x%8.8x (%s)!\n",
status, OsrNtStatusToString(status)));
InterlockedExchange(&DevExt->FlagWWOutstanding, 0);
}
//
// Retun the Status to the Caller.
//
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE, ("IssueWaitWake: Exit\n"));
return status;
}
///////////////////////////////////////////////////////////////////////////////
//
// CancelWaitWake
//
// This routine cancels an outstanding WAIT_WAKE request.
//
// INPUTS:
//
// DevExt - Pointer to our Device Extension.
//
// OUTPUTS:
//
// None.
//
// RETURNS:
//
// None.
//
// IRQL:
//
// This routine is called at IRQL == PASSIVE_LEVEL
//
// CONTEXT:
//
// This routine is called in an arbitrary thread context
//
// NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID CancelWaitWake(PUSBFX2LK_EXT DevExt)
{
PIRP Irp;
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE,("CancelWaitWake: Entered.\n"));
//
// Attempt to grab the WaitWake irp out of the Device Extension.
//
Irp = (PIRP) InterlockedExchangePointer((volatile PVOID*) &DevExt->WaitWakeIrp, NULL);
//
// See if we got the Irp, if we did, then we can try to cancel it.
//
if(Irp) {
OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_WAIT_WAKE,
("CancelWaitWake: Canceling Wait Wake Irp.\n"));
//
// Got the Irp, Cancel It.
//
IoCancelIrp(Irp);
//
// Indicate that the Irp was canceled so that the
// WaitWakeCompletion routine knows what is going on.
//
if(InterlockedExchange(&DevExt->FlagWWCancel, 1)) {
//
// Tell the Power Manager that we are ready to
// handle another Power Irp.
//
PoStartNextPowerIrp(Irp);
//
// Complete the Wait Wake Irp with a Canceled
// status.
//
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE,("CancelWaitWake: Exit.\n"));
}
///////////////////////////////////////////////////////////////////////////////
//
// WaitWakeCompletionRoutine
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -