[CMBATT]: Implement CmBattPowerCallback and CmBattWakeDpc to handle S0 entry/exit transitions which determine if we delay ACPI battery notifications to avoid wake, and the queuing of a DPC to handle processing the delayed ARs when we return to S0.

svn path=/trunk/; revision=46324
This commit is contained in:
Sir Richard 2010-03-21 21:07:01 +00:00
parent 37d10b143e
commit 3e76f1bac8

View file

@ -19,26 +19,120 @@ UNICODE_STRING GlobalRegistryPath;
KTIMER CmBattWakeDpcTimerObject;
KDPC CmBattWakeDpcObject;
PDEVICE_OBJECT AcAdapterPdo;
LARGE_INTEGER CmBattWakeDpcDelay;
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension,
PVOID Argument1,
PVOID Argument2)
CmBattPowerCallBack(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
IN ULONG Action,
IN ULONG Value)
{
UNIMPLEMENTED;
BOOLEAN Cancelled;
PDEVICE_OBJECT DeviceObject;
if (CmBattDebug & 0x10)
DbgPrint("CmBattPowerCallBack: action: %d, value: %d \n", Action, Value);
/* Check if a transition is going to happen */
if (Action == PO_CB_SYSTEM_STATE_LOCK)
{
/* We have just re-entered S0: call the wake DPC in 10 seconds */
if (Value == 0)
{
if (CmBattDebug & 0x10)
DbgPrint("CmBattPowerCallBack: Calling CmBattWakeDpc after 10 seconds.\n");
Cancelled = KeSetTimer(&CmBattWakeDpcTimerObject, CmBattWakeDpcDelay, &CmBattWakeDpcObject);
if (CmBattDebug & 0x10)
DbgPrint("CmBattPowerCallBack: timerCanceled = %d.\n", Cancelled);
}
else if (Value == 0)
{
/* We are exiting the S0 state: loop all devices to set the delay flag */
if (CmBattDebug & 0x10)
DbgPrint("CmBattPowerCallBack: Delaying Notifications\n");
for (DeviceObject = DeviceExtension->DeviceObject;
DeviceObject;
DeviceObject = DeviceObject->NextDevice)
{
/* Set the delay flag */
DeviceExtension = DeviceObject->DeviceExtension;
DeviceExtension->DelayNotification = TRUE;
}
}
else if (CmBattDebug & 0x10)
{
/* Unknown value */
DbgPrint("CmBattPowerCallBack: unknown argument2 = %08x\n");
}
}
}
VOID
NTAPI
CmBattWakeDpc(PKDPC Dpc,
PCMBATT_DEVICE_EXTENSION FdoExtension,
PVOID SystemArgument1,
PVOID SystemArgument2)
CmBattWakeDpc(IN PKDPC Dpc,
IN PCMBATT_DEVICE_EXTENSION FdoExtension,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
PDEVICE_OBJECT CurrentObject;
BOOLEAN AcNotify = FALSE;
PCMBATT_DEVICE_EXTENSION DeviceExtension;
ULONG ArFlag;
if (CmBattDebug & 2) DbgPrint("CmBattWakeDpc: Entered.\n");
/* Loop all device objects */
for (CurrentObject = FdoExtension->DeviceObject;
CurrentObject;
CurrentObject = CurrentObject->NextDevice)
{
/* Turn delay flag off, we're back in S0 */
DeviceExtension = CurrentObject->DeviceExtension;
DeviceExtension->DelayNotification = 0;
/* Check if this is an AC adapter */
if (DeviceExtension->FdoType == CmBattAcAdapter)
{
/* Was there a pending notify? */
if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
{
/* We'll send a notify on the next pass */
AcNotify = TRUE;
DeviceExtension->ArFlag = 0;
if (CmBattDebug & 0x20)
DbgPrint("CmBattWakeDpc: AC adapter notified\n");
}
}
}
/* Loop the device objects again */
for (CurrentObject = FdoExtension->DeviceObject;
CurrentObject;
CurrentObject = CurrentObject->NextDevice)
{
/* Check if this is a battery */
DeviceExtension = CurrentObject->DeviceExtension;
if (DeviceExtension->FdoType == CmBattBattery)
{
/* Check what ARs are pending */
ArFlag = DeviceExtension->ArFlag;
if (CmBattDebug & 0x20)
DbgPrint("CmBattWakeDpc: Performing delayed ARs: %01x\n", ArFlag);
/* Insert notification, clear the lock value */
if (ArFlag & CMBATT_AR_INSERT) InterlockedExchange(&DeviceExtension->ArLockValue, 0);
/* Removal, clear the battery tag */
if (ArFlag & CMBATT_AR_REMOVE) DeviceExtension->Tag = 0;
/* Notification (or AC/DC adapter change from first pass above) */
if ((ArFlag & CMBATT_AR_NOTIFY) || (AcNotify))
{
/* Notify the class driver */
BatteryClassStatusNotify(DeviceExtension->ClassData);
}
}
}
}
VOID