📄 bulkpwr.c
字号:
deviceExtension = DeviceObject->DeviceExtension;
// This should have been reset in completion routine
BULKUSB_ASSERT( !deviceExtension->SelfPowerIrp );
if ( deviceExtension->CurrentDevicePowerState == PowerState.DeviceState )
return STATUS_SUCCESS; // nothing to do
BULKUSB_KdPrint( DBGLVL_HIGH,("Enter BulkUsb_SelfRequestPowerIrp() will request power irp to state %s\n",
BULKUSB_StringForDevState( PowerState.DeviceState )));
BulkUsb_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,
BulkUsb_PoSelfRequestCompletion,
DeviceObject,
NULL);
if ( ntStatus == STATUS_PENDING ) {
// status pending is the return code we wanted
// We only need to wait for completion if we're powering up
if ( (ULONG) PowerState.DeviceState < deviceExtension->PowerDownLevel ) {
NTSTATUS waitStatus;
waitStatus = KeWaitForSingleObject(
&deviceExtension->SelfRequestedPowerIrpEvent,
Suspended,
KernelMode,
FALSE,
NULL);
}
ntStatus = STATUS_SUCCESS;
deviceExtension->SelfPowerIrp = FALSE;
BULKUSB_KdPrint( DBGLVL_HIGH, ("BulkUsb_SelfRequestPowerIrp() SUCCESS\n IRP 0x%x to state %s\n",
pIrp, BULKUSB_StringForDevState(PowerState.DeviceState) ));
}
else {
// The return status was not STATUS_PENDING; any other codes must be considered in error here;
// i.e., it is not possible to get a STATUS_SUCCESS or any other non-error return from this call;
BULKUSB_KdPrint( DBGLVL_HIGH, ("BulkUsb_SelfRequestPowerIrp() to state %s FAILED, status = 0x%x\n",
BULKUSB_StringForDevState( PowerState.DeviceState ),ntStatus));
}
return ntStatus;
}
NTSTATUS
BulkUsb_PoSelfRequestCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
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 powerdown 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.
--*/
{
PDEVICE_OBJECT deviceObject = Context;
PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
NTSTATUS ntStatus = IoStatus->Status;
// we should not be in the midst of handling a system-generated power irp
BULKUSB_ASSERT( NULL == deviceExtension->PowerIrp );
// 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);
}
BulkUsb_DecrementIoCount(deviceObject);
BULKUSB_KdPrintCond( DBGLVL_HIGH, !NT_SUCCESS(ntStatus),("Exit BulkUsb_PoSelfRequestCompletion() FAILED, ntStatus = 0x%x\n", ntStatus ));
return ntStatus;
}
BOOLEAN
BulkUsb_SetDevicePowerState(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_POWER_STATE DeviceState
)
/*++
Routine Description:
This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState'
has been received by BulkUsb_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.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
BOOLEAN fRes = FALSE;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
switch (DeviceState) {
case PowerDeviceD3:
//
// Device will be going OFF,
// TODO: add any needed device-dependent code to save state here.
// ( We have nothing to do in this sample )
//
BULKUSB_KdPrint( DBGLVL_MEDIUM,("BulkUsb_SetDevicePowerState() PowerDeviceD3 (OFF)\n"));
deviceExtension->CurrentDevicePowerState = DeviceState;
break;
case PowerDeviceD1:
case PowerDeviceD2:
//
// power states D1,D2 translate to USB suspend
BULKUSB_KdPrint( DBGLVL_MEDIUM,("BulkUsb_SetDevicePowerState() %s\n",
BULKUSB_StringForDevState(DeviceState) ));
deviceExtension->CurrentDevicePowerState = DeviceState;
break;
case PowerDeviceD0:
BULKUSB_KdPrint( DBGLVL_MEDIUM,("BulkUsb_SetDevicePowerState() PowerDeviceD0 (ON)\n"));
// 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;
default:
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" Bogus DeviceState = %x\n", DeviceState));
}
return fRes;
}
NTSTATUS
BulkUsb_QueryCapabilities(
IN PDEVICE_OBJECT LowerDeviceObject,
IN PDEVICE_CAPABILITIES DeviceCapabilities
)
/*++
Routine Description:
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.
--*/
{
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;
//purnnamu:11/23/2001
//DeviceCapabilities->Removable =1;
//DeviceCapabilities->SurpriseRemovalOK=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,
BulkUsb_IrpCompletionRoutine,
&event, // pass the event as Context to completion routine
TRUE, // invoke on success
TRUE, // invoke on error
TRUE); // invoke on cancellation of the Irp
// 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;
ntStatus = IoCallDriver(LowerDeviceObject,
irp);
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" BulkUsb_QueryCapabilities() ntStatus from IoCallDriver to PCI = 0x%x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
// wait for irp to complete
KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
ntStatus = irp->IoStatus.Status;
}
// failed? this is probably a bug
BULKUSB_KdPrintCond( DBGLVL_DEFAULT,(!NT_SUCCESS(ntStatus)), ("BulkUsb_QueryCapabilities() failed\n"));
IoFreeIrp(irp);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -