mavpwr.c
来自「基于EP7312的MP3播放器源代码,包括MCU和PC端代码.」· C语言 代码 · 共 1,127 行 · 第 1/3 页
C
1,127 行
ntStatus = MavUsb_SelfRequestPowerIrp(DeviceObject, PowerState);
//
// Return the result.
//
return(ntStatus);
}
//****************************************************************************
//
// This routine is called by MavUsb_SelfSuspendOrActivate() to actually make
// the system request for a power down/up to PowerState. It first checks to
// see if we are already in Powerstate and immediately returns SUCCESS with no
// further processing if so.
//
// Arguments:
//
// DeviceObject - Pointer to the device object.
//
// PowerState - power state requested, e.g PowerDeviceD0.
//
// Return Value:
//
// The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_SelfRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject,
IN POWER_STATE PowerState)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PIRP pIrp = NULL;
//
// Get a pointer to the device extension.
//
deviceExtension = DeviceObject->DeviceExtension;
//
// If we are already in the correct power state, then do nothing.
//
if(deviceExtension->CurrentDevicePowerState == PowerState.DeviceState)
{
//
// Return success.
//
return(STATUS_SUCCESS);
}
//
// Increment the count of pending IRPs.
//
MavUsb_IncrementIoCount(DeviceObject);
//
// Flag we're handling a self-generated power IRP.
//
deviceExtension->SelfPowerIrp = TRUE;
//
// Actually request the IRP.
//
ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER, PowerState,
MavUsb_PoSelfRequestCompletion, DeviceObject,
NULL);
//
// Make sure that the status was pending.
//
if(ntStatus == STATUS_PENDING)
{
//
// We only need to wait for completion if we're powering up.
//
if((ULONG)PowerState.DeviceState < deviceExtension->PowerDownLevel)
{
//
// Wait for the IRP to complete.
//
KeWaitForSingleObject(&deviceExtension->SelfRequestedPowerIrpEvent,
Suspended, KernelMode, FALSE, NULL);
}
//
// Set the status to success.
//
ntStatus = STATUS_SUCCESS;
//
// Indicate that we are no longer processing a self-power IRP.
//
deviceExtension->SelfPowerIrp = FALSE;
}
//
// Return the status.
//
return(ntStatus);
}
//****************************************************************************
//
// This routine is called when the driver completes a self-originated power
// IRP that was generated by a call to BulkUsb_SelfSuspendOrActivate().
//
// We power down whenever the last pipe is closed and power up when the first
// pipe is opened.
//
// For power-up, we set an event in our FDO extension to signal this IRP done
// so the power request can be treated as a synchronous call.
//
// We need to know the device is powered up before opening the first pipe, for
// example.
//
// For power-down, we do not set the event, as no caller waits for power down
// complete.
//
// Arguments:
//
// DeviceObject - Pointer to the device object for the class device.
// (Physical Device Object)
//
// Context - Driver defined context, in this case our FDO (functional
// device object)
//
// Return Value:
//
// The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_PoSelfRequestCompletion(IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState, IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus)
{
PDEVICE_OBJECT deviceObject = Context;
PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
NTSTATUS ntStatus = IoStatus->Status;
//
// We only need to set the event if we're powering up; no caller waits on
// power down complete.
//
if((ULONG)PowerState.DeviceState < deviceExtension->PowerDownLevel)
{
//
// Trigger self-requested power IRP completed event; the caller is
// waiting for completion.
//
KeSetEvent(&deviceExtension->SelfRequestedPowerIrpEvent, 1, FALSE);
}
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(deviceObject);
//
// Return the IO completion status.
//
return(ntStatus);
}
//****************************************************************************
//
// This routine is called when an IRP_MN_SET_POWER of type 'DevicePowerState'
// has been received by MavUsb_ProcessPowerIrp().
//
// Arguments:
//
// DeviceObject - Pointer to the device object for the class device.
//
// DeviceState - Device specific power state to set the device in to.
//
// Return Value:
//
// For requests to DeviceState D0 (fully on), returns TRUE to signal caller
// that we must set a completion routine and finish there.
//
//****************************************************************************
BOOLEAN
MavUsb_SetDevicePowerState(IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_POWER_STATE DeviceState)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
BOOLEAN fRes = FALSE;
//
// Get a pointer to the device extension.
//
deviceExtension = DeviceObject->DeviceExtension;
//
// Determine the power state we are changing to.
//
switch(DeviceState)
{
//
// The device will be turning off.
//
case PowerDeviceD3:
{
//
// Set the device power state.
//
deviceExtension->CurrentDevicePowerState = DeviceState;
//
// We're done handling this power state.
//
break;
}
//
// Power states D1 and D2 translate to USB suspend.
//
case PowerDeviceD1:
case PowerDeviceD2:
{
//
// Set the device power state.
//
deviceExtension->CurrentDevicePowerState = DeviceState;
//
// We're done handling these power states.
//
break;
}
//
// The device will be turning on.
//
case PowerDeviceD0:
{
//
// We'll need to finish the rest in the completion routine; signal
// caller we're going to D0 and will need to set a completion
// routine.
//
fRes = TRUE;
//
// Caller will pass on to PDO (Physical Device Object).
//
break;
}
}
//
// Return the result.
//
return(fRes);
}
//****************************************************************************
//
// This routine generates an internal IRP from this driver to the lower
// portion of the driver stack to obtain information on the Device Object's
// capabilities. We are most interested in learning which system power states
// are to be mapped to which device power states for honoring IRP_MJ_SET_POWER
// IRPs.
//
// This is a blocking call which waits for the IRP completion routine to set
// an event on finishing.
//
// Arguments:
//
// LowerDeviceObject - DeviceObject beneath this driver in the stack.
//
// Return Value:
//
// NTSTATUS value from the IoCallDriver() call.
//
//****************************************************************************
NTSTATUS
MavUsb_QueryCapabilities(IN PDEVICE_OBJECT LowerDeviceObject,
IN PDEVICE_CAPABILITIES DeviceCapabilities)
{
PIO_STACK_LOCATION nextStack;
PIRP irp;
NTSTATUS ntStatus;
KEVENT event;
//
// This is a DDK-defined DBG-only macro that ASSERTS we are not running
// pageable code at higher than APC_LEVEL.
//
PAGED_CODE();
//
// Build an IRP for us to generate an internal query request to the PDO.
//
irp = IoAllocateIrp(LowerDeviceObject->StackSize, FALSE);
if(!irp)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Preinit the device capability structures appropriately.
//
RtlZeroMemory(DeviceCapabilities, sizeof(DEVICE_CAPABILITIES));
DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
DeviceCapabilities->Version = 1;
DeviceCapabilities->Address = -1;
DeviceCapabilities->UINumber = -1;
//
// IoGetNextIrpStackLocation gives a higher level driver access to the
// next-lower driver's I/O stack location in an IRP so the caller can set
// it up for the lower driver.
//
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->MajorFunction= IRP_MJ_PNP;
nextStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;
//
// Init an event to tell us when the completion routine's been called.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Set a completion routine so it can signal our event when the next lower
// driver is done with the IRP.
//
IoSetCompletionRoutine(irp, MavUsb_IrpCompletionRoutine, &event, TRUE,
TRUE, TRUE);
//
// Set our pointer to the DEVICE_CAPABILITIES struct.
//
nextStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
//
// Preset the IRP to report not supported.
//
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
//
// Pass the IRP to the lower level device object.
//
ntStatus = IoCallDriver(LowerDeviceObject, irp);
//
// See if we need to wait for the IRP to complete.
//
if(ntStatus == STATUS_PENDING)
{
//
// Wait for the IRP to complete.
//
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
//
// Get the status from the IRP.
//
ntStatus = irp->IoStatus.Status;
}
//
// Free the IRP.
//
IoFreeIrp(irp);
//
// Return the result.
//
return(ntStatus);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?