You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
561 lines
13 KiB
561 lines
13 KiB
/***************************************************************************
|
|
|
|
Copyright (c) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
power.C
|
|
|
|
Abstract:
|
|
|
|
Power Routines for Smartcard Driver Utility Library
|
|
|
|
Environment:
|
|
|
|
Kernel Mode Only
|
|
|
|
Notes:
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
|
|
|
|
|
|
Revision History:
|
|
|
|
05/14/2002 : created
|
|
|
|
Authors:
|
|
|
|
Randy Aull
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
#include "pch.h"
|
|
|
|
NTSTATUS
|
|
ScUtil_Power(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
|
|
PIO_STACK_LOCATION irpStack;
|
|
|
|
ASSERT(pExt);
|
|
|
|
PAGED_CODE();
|
|
|
|
__try
|
|
{
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("Enter: ScUtil_Power\n"));
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
status = IoAcquireRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
__leave;
|
|
|
|
}
|
|
|
|
if ((irpStack->MinorFunction != IRP_MN_QUERY_POWER)
|
|
&& (irpStack->MinorFunction != IRP_MN_SET_POWER) ) {
|
|
// We don't handle these irps
|
|
PoStartNextPowerIrp(Irp);
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
status = PoCallDriver(pExt->LowerDeviceObject,
|
|
Irp);
|
|
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
|
|
__leave;
|
|
}
|
|
|
|
|
|
switch (irpStack->Parameters.Power.Type) {
|
|
case DevicePowerState:
|
|
status = ScUtilDevicePower(DeviceObject,
|
|
Irp);
|
|
break;
|
|
case SystemPowerState:
|
|
|
|
status = ScUtilSystemPower(DeviceObject,
|
|
Irp);
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("Exit: ScUtil_Power (0x%x)\n", status));
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ScUtilDevicePower(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Handles Device Power Irps
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
|
|
PIO_STACK_LOCATION stack;
|
|
BOOLEAN postWaitWake;
|
|
POWER_STATE state;
|
|
|
|
|
|
|
|
__try
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDevicePower Enter\n"));
|
|
|
|
stack = IoGetCurrentIrpStackLocation(Irp);
|
|
state.DeviceState = stack->Parameters.Power.State.DeviceState;
|
|
|
|
switch (stack->MinorFunction) {
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
//
|
|
// Since we can always wait for our irps to complete, so we just always succeed
|
|
//
|
|
|
|
StopIoctls(pExt);
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
status = PoCallDriver(pExt->LowerDeviceObject,
|
|
Irp);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
case IRP_MN_SET_POWER:
|
|
|
|
if (state.DeviceState < pExt->PowerState) {
|
|
|
|
//
|
|
// We are coming up!! We must let lower drivers power up before we do
|
|
//
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDevicePower Coming Up!\n"));
|
|
IoMarkIrpPending(Irp);
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
ScUtilDevicePowerUpCompletion,
|
|
pExt,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
status = PoCallDriver(pExt->LowerDeviceObject,
|
|
Irp);
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
} else {
|
|
|
|
//
|
|
// We are moving to a lower power state, so we handle it before
|
|
// passing it down
|
|
//
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDevicePower Going Down!\n"));
|
|
|
|
StopIoctls(pExt);
|
|
DecIoCount(pExt);
|
|
|
|
KeWaitForSingleObject(&pExt->OkToStop,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
status = pExt->SetPowerState(DeviceObject,
|
|
state.DeviceState,
|
|
&postWaitWake);
|
|
|
|
PoSetPowerState(DeviceObject,
|
|
DevicePowerState,
|
|
state);
|
|
|
|
pExt->PowerState = state.DeviceState;
|
|
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
status = PoCallDriver(pExt->LowerDeviceObject,
|
|
Irp);
|
|
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
|
|
|
|
}
|
|
break;
|
|
default:
|
|
// We shouldn't be here
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDevicePower Exit : 0x%x\n", status ));
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
ScUtilSystemPower(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Handles system power irps
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
|
|
|
|
|
|
__try
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemPower Enter\n" ));
|
|
|
|
IoMarkIrpPending(Irp);
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
ScUtilSystemPowerCompletion,
|
|
pExt,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
status = PoCallDriver(pExt->LowerDeviceObject,
|
|
Irp);
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemPower Exit : 0x%x\n", status ));
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
ScUtilSystemPowerCompletion(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp,
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Completion routine called after system power irp has been passed down the stack.
|
|
handles mapping system state to device state and requests the device power irp.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSCUTIL_EXTENSION pExt = (PSCUTIL_EXTENSION) Context;
|
|
PIO_STACK_LOCATION irpStack;
|
|
POWER_STATE state;
|
|
POWER_STATE systemState;
|
|
|
|
|
|
__try
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemPowerCompletion Enter\n" ));
|
|
|
|
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemPowerCompletion SIRP failed by lower driver\n" ));
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
IoCompleteRequest(Irp,
|
|
IO_NO_INCREMENT);
|
|
status = Irp->IoStatus.Status;
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
__leave;
|
|
}
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
systemState = irpStack->Parameters.Power.State;
|
|
state.DeviceState = pExt->DeviceCapabilities.DeviceState[systemState.SystemState];
|
|
|
|
if (systemState.DeviceState != PowerSystemWorking) {
|
|
|
|
// Wait for D IRP completion
|
|
status = PoRequestPowerIrp(DeviceObject,
|
|
irpStack->MinorFunction,
|
|
state,
|
|
ScUtilDeviceRequestCompletion,
|
|
(PVOID) Irp,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
PoStartNextPowerIrp(Irp);
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
__leave;
|
|
|
|
}
|
|
status = STATUS_MORE_PROCESSING_REQUIRED;
|
|
|
|
} else {
|
|
|
|
// Don't wait for completion of D irp to speed up resume time
|
|
status = PoRequestPowerIrp(DeviceObject,
|
|
irpStack->MinorFunction,
|
|
state,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
Irp->IoStatus.Status = status;
|
|
status = STATUS_PENDING;
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
} else {
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
}
|
|
|
|
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemPowerCompletion Exit : 0x%x\n", status ));
|
|
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ScUtilDeviceRequestCompletion(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
UCHAR MinorFunction,
|
|
POWER_STATE PowerState,
|
|
PVOID Context,
|
|
PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Completion routine called after device power irp completes.
|
|
Completes the system power irp.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
|
|
PIRP irp;
|
|
|
|
__try
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDeviceRequestCompletion Enter\n" ));
|
|
|
|
irp = (PIRP) Context;
|
|
|
|
PoStartNextPowerIrp(irp);
|
|
irp->IoStatus.Status = IoStatus->Status;
|
|
IoCompleteRequest(irp,
|
|
IO_NO_INCREMENT);
|
|
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
irp);
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDeviceRequestCompletion Exit : 0x%x\n", status ));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ScUtilDevicePowerUpCompletion(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp,
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Completion routine called after device irp for higher power state has been
|
|
passed down the stack.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
|
|
PIO_STACK_LOCATION irpStack;
|
|
BOOLEAN postWaitWake; // We don't really care about this
|
|
|
|
|
|
|
|
__try
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDevicePowerUpCompletion Enter\n" ));
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
status = pExt->SetPowerState(DeviceObject,
|
|
irpStack->Parameters.Power.State.DeviceState,
|
|
&postWaitWake);
|
|
|
|
pExt->PowerState = irpStack->Parameters.Power.State.DeviceState;
|
|
IncIoCount(pExt);
|
|
StartIoctls(pExt);
|
|
|
|
|
|
|
|
PoSetPowerState(DeviceObject,
|
|
DevicePowerState,
|
|
irpStack->Parameters.Power.State);
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
|
|
IoReleaseRemoveLock(pExt->RemoveLock,
|
|
Irp);
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("ScUtilDevicePowerUpCompletion Exit : 0x%x\n", status ));
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
|
|
}
|
|
|
|
|