?? isopwr.c
字號(hào):
Return Value:
The function value is the final status from the operation.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PIRP pIrp = NULL;
deviceExtension = DeviceObject->DeviceExtension;
// This should have been reset in completion routine
ISOUSB_ASSERT( !deviceExtension->SelfPowerIrp );
if ( deviceExtension->CurrentDevicePowerState == PowerState.DeviceState )
return STATUS_SUCCESS; // nothing to do
ISOUSB_KdPrint( DBGLVL_HIGH,("Enter IsoUsb_SelfRequestPowerIrp() will request power irp to state %s\n",
ISOUSB_StringForDevState( PowerState.DeviceState )));
IsoUsb_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,
IsoUsb_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;
ISOUSB_KdPrint( DBGLVL_HIGH, ("IsoUsb_SelfRequestPowerIrp() SUCCESS\n IRP 0x%x to state %s\n",
pIrp, ISOUSB_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;
ISOUSB_KdPrint( DBGLVL_HIGH, ("IsoUsb_SelfRequestPowerIrp() to state %s FAILED, status = 0x%x\n",
ISOUSB_StringForDevState( PowerState.DeviceState ),ntStatus));
}
return ntStatus;
}
NTSTATUS
IsoUsb_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 IsoUsb_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
ISOUSB_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);
}
IsoUsb_DecrementIoCount(deviceObject);
ISOUSB_KdPrintCond( DBGLVL_HIGH, !NT_SUCCESS(ntStatus),("Exit IsoUsb_PoSelfRequestCompletion() FAILED, ntStatus = 0x%x\n", ntStatus ));
return ntStatus;
}
BOOLEAN
IsoUsb_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 IsoUsb_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 )
//
ISOUSB_KdPrint( DBGLVL_MEDIUM,("IsoUsb_SetDevicePowerState() PowerDeviceD3 (OFF)\n"));
deviceExtension->CurrentDevicePowerState = DeviceState;
break;
case PowerDeviceD1:
case PowerDeviceD2:
//
// power states D1,D2 translate to USB suspend
ISOUSB_KdPrint( DBGLVL_MEDIUM,("IsoUsb_SetDevicePowerState() %s\n",
ISOUSB_StringForDevState(DeviceState) ));
deviceExtension->CurrentDevicePowerState = DeviceState;
break;
case PowerDeviceD0:
ISOUSB_KdPrint( DBGLVL_MEDIUM,("IsoUsb_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:
ISOUSB_KdPrint( DBGLVL_MEDIUM,(" Bogus DeviceState = %x\n", DeviceState));
}
return fRes;
}
NTSTATUS
IsoUsb_QueryCapabilities(
IN PDEVICE_OBJECT PdoDeviceObject,
IN PDEVICE_CAPABILITIES DeviceCapabilities
)
/*++
Routine Description:
to obtain information on the Physical 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:
DeviceObject - Physical DeviceObject for this USB controller.
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(PdoDeviceObject->StackSize, FALSE);
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
// 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);
ISOUSB_ASSERT(nextStack != NULL);
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,
IsoUsb_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;
ntStatus = IoCallDriver(PdoDeviceObject,
irp);
ISOUSB_KdPrint( DBGLVL_MEDIUM,(" IsoUsb_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);
}
// failed? this is probably a bug
ISOUSB_KdPrintCond( DBGLVL_DEFAULT,(!NT_SUCCESS(ntStatus)), ("IsoUsb_QueryCapabilities() failed\n"));
IoFreeIrp(irp);
return ntStatus;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -