mavpwr.c
来自「基于EP7312的MP3播放器源代码,包括MCU和PC端代码.」· C语言 代码 · 共 1,127 行 · 第 1/3 页
C
1,127 行
}
//
// We're done handling the device power state change.
//
break;
}
}
//
// We're done with this IRP.
//
break;
}
//
// A power policy manager sends this IRP to determine whether it can
// change the system or device power state, typically to go to sleep.
//
case IRP_MN_QUERY_POWER:
{
//
// We do nothing special here, just let the PDO handle it.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
PoStartNextPowerIrp(Irp);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// We're done with this IRP.
//
break;
}
//
// Handle all other IRPs.
//
default:
{
//
// All unhandled power messages are passed on to the PDO.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
PoStartNextPowerIrp(Irp);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
}
}
//
// Return the status.
//
return(ntStatus);
}
//****************************************************************************
//
// This is the completion routine set in a call to PoRequestPowerIrp() that
// was made in MavUsb_ProcessPowerIrp() in response to receiving an
// IRP_MN_SET_POWER of type 'SystemPowerState' when the device was not in a
// compatible device power state. In this case, a pointer to the
// IRP_MN_SET_POWER IRP is saved into the FDO device extension
// (deviceExtension->PowerIrp), and then a call must be made to
// PoRequestPowerIrp() to put the device into a proper power state, and this
// routine is set as the completion routine.
//
// We decrement our pending io count and pass the saved IRP_MN_SET_POWER IRP
// on to the next driver.
//
// Arguments:
//
// DeviceObject - Pointer to the device object for the class device.
// Note that we must get our own device object from the
// Context.
//
// Context - Driver defined context, in this case our own functional
// device object (FDO).
//
// Return Value:
//
// The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_PoRequestCompletion(IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction, IN POWER_STATE PowerState,
IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
{
PIRP irp;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT deviceObject = Context;
NTSTATUS ntStatus;
//
// Get a pointer to the device extension.
//
deviceExtension = deviceObject->DeviceExtension;
//
// Get the IRP we saved for later processing in MavUsb_ProcessPowerIrp()
// when we decided to request the Power IRP that this routine is the
// completion routine for.
//
irp = deviceExtension->PowerIrp;
//
// We will return the status set by the PDO for the power request we're
// completing.
//
ntStatus = IoStatus->Status;
//
// We must pass down to the next driver in the stack.
//
IoCopyCurrentIrpStackLocationToNext(irp);
//
// Calling PoStartNextPowerIrp() indicates that the driver is finished
// with the previous power IRP, if any, and is ready to handle the next
// power IRP. It must be called for every power IRP. Although power IRPs
// are completed only once, typically by the lowest-level driver for a
// device, PoStartNextPowerIrp must be called for every stack location.
// Drivers must call PoStartNextPowerIrp while the current IRP stack
// location points to the current driver. Therefore, this routine must be
// called before IoCompleteRequest, IoSkipCurrentStackLocation, and
// PoCallDriver.
//
PoStartNextPowerIrp(irp);
//
// PoCallDriver is used to pass any power IRPs to the PDO instead of
// IoCallDriver. When passing a power IRP down to a lower-level driver,
// the caller should use IoSkipCurrentIrpStackLocation or
// IoCopyCurrentIrpStackLocationToNext to copy the IRP to the next stack
// location, then call PoCallDriver. Use
// IoCopyCurrentIrpStackLocationToNext if processing the IRP requires
// setting a completion routine, or IoSkipCurrentStackLocation if no
// completion routine is needed.
//
PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(deviceObject);
//
// We're done handling the saved IRP.
//
deviceExtension->PowerIrp = NULL;
//
// Return the status.
//
return(ntStatus);
}
//****************************************************************************
//
// This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState'
// has been received by MavUsb_ProcessPowerIrp(), and that routine has
// determined:
// 1) the request is for full powerup (to PowerDeviceD0), and
// 2) We are not already in that state
// A call is then made to PoRequestPowerIrp() with this routine set as the
// completion routine.
//
// Arguments:
//
// DeviceObject - Pointer to the device object for the class device.
//
// Irp - IRP completed.
//
// Context - Driver defined context.
//
// Return Value:
//
// The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_PowerIrp_Complete(IN PDEVICE_OBJECT NullDeviceObject, IN PIRP Irp,
IN PVOID Context)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
//
// Get a pointer to the the device object.
//
deviceObject = (PDEVICE_OBJECT)Context;
//
// Get a pointer to the device extension.
//
deviceExtension = deviceObject->DeviceExtension;
//
// If the lower driver returned PENDING, mark our stack location as pending
// also.
//
if(Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
//
// Get a pointer to the current location on the IRP stack.
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
//
// Now that we know we've let the lower drivers do what was needed to power
// up, we can set our device extension flags accordingly.
//
deviceExtension->CurrentDevicePowerState = PowerDeviceD0;
//
// Set the status in the IRP.
//
Irp->IoStatus.Status = ntStatus;
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(deviceObject);
//
// Return the status.
//
return(ntStatus);
}
//****************************************************************************
//
// Called on MavUsb_PnPAddDevice() to power down until needed (i.e., until a
// pipe is actually opened).
//
// Called on MavUsb_Create() to power up device to D0 before opening 1st pipe.
//
// Called on MavUsb_Close() to power down device if this is the last pipe.
//
// Arguments:
//
// DeviceObject - Pointer to the device object
//
// fSuspend - TRUE to Suspend, FALSE to activate.
//
// Return Value:
//
// If the operation is not attemtped, SUCCESS is returned.
//
// If the operation is attemtped, the value is the final status from the
// operation.
//
//****************************************************************************
NTSTATUS
MavUsb_SelfSuspendOrActivate(IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN fSuspend)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
POWER_STATE PowerState;
PDEVICE_EXTENSION deviceExtension;
//
// Get a pointer to the device extension.
//
deviceExtension = DeviceObject->DeviceExtension;
//
// Can't accept request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending.
//
if(!MavUsb_CanAcceptIoRequests(DeviceObject))
{
//
// Indicate that a delete is pending.
//
return(STATUS_DELETE_PENDING);
}
//
// Don't do anything if any System-generated Device PnP IRPs are pending.
//
if(deviceExtension->PowerIrp != NULL)
{
//
// Return success.
//
return(STATUS_SUCCESS);
}
//
// Don't do anything if any self-generated Device PnP IRPs are pending
//
if(deviceExtension->SelfPowerIrp)
{
//
// Return success.
//
return(STATUS_SUCCESS);
}
//
// Don't auto-suspend if any pipes are open.
//
if(fSuspend && (deviceExtension->OpenPipeCount != 0))
{
//
// Return success.
//
return(STATUS_SUCCESS);
}
//
// Don't auto-activate if no pipes are open.
//
if(!fSuspend && (deviceExtension->OpenPipeCount == 0))
{
//
// Return success.
//
return(STATUS_SUCCESS);
}
//
// Don't do anything if registry
// CurrentControlSet\Services\BulkUsb\Parameters\PowerDownLevel
// has been set to zero, PowerDeviceD0 (1), or a bogus high value.
//
if((deviceExtension->PowerDownLevel == PowerDeviceD0) ||
(deviceExtension->PowerDownLevel == PowerDeviceUnspecified) ||
(deviceExtension->PowerDownLevel >= PowerDeviceMaximum))
{
//
// Return success.
//
return(STATUS_SUCCESS);
}
//
// If we should suspend, then set our device state to the power down level.
//
if(fSuspend)
{
PowerState.DeviceState = deviceExtension->PowerDownLevel;
}
//
// Otherwise, set our device state to D0.
//
else
{
PowerState.DeviceState = PowerDeviceD0;
}
//
// Self request a power state change to the desired power state.
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?