[CMBATT]: Implement CmBattQueryTag and CmBattNotifyHandler for getting ACPI Battery notifications, as per ACPI Spec and http://www.microsoft.com/whdc/archive/ACPInotify.mspx.

svn path=/trunk/; revision=46309
This commit is contained in:
Sir Richard 2010-03-21 18:04:08 +00:00
parent c825e8a684
commit 22bb1901b6
2 changed files with 187 additions and 10 deletions

View file

@ -43,10 +43,117 @@ CmBattWakeDpc(PKDPC Dpc,
VOID
NTAPI
CmBattNotifyHandler(PCMBATT_DEVICE_EXTENSION DeviceExtension,
ULONG NotifyValue)
CmBattNotifyHandler(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
IN ULONG NotifyValue)
{
UNIMPLEMENTED;
ULONG ArFlag;
PCMBATT_DEVICE_EXTENSION FdoExtension;
PDEVICE_OBJECT DeviceObject;
if (CmBattDebug & (CMBATT_ACPI_ASSERT | CMBATT_PNP_INFO))
DbgPrint("CmBattNotifyHandler: CmBatt 0x%08x Type %d Number %d Notify Value: %x\n",
DeviceExtension,
DeviceExtension->FdoType,
DeviceExtension->DeviceId,
NotifyValue);
/* Check what kind of notification was received */
switch (NotifyValue)
{
/* ACPI Specification says is sends a "Bus Check" when power source changes */
case ACPI_BUS_CHECK:
/* We treat it as possible physical change */
DeviceExtension->ArFlag |= (CMBATT_AR_NOTIFY | CMBATT_AR_INSERT);
if ((DeviceExtension->Tag) &&
(CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)))
DbgPrint("CmBattNotifyHandler: Received battery #%x insertion, but tag was not invalid.\n",
DeviceExtension->DeviceId);
break;
/* Status of the battery has changed */
case ACPI_BATT_NOTIFY_STATUS:
/* All we'll do is notify the class driver */
DeviceExtension->ArFlag |= CMBATT_AR_NOTIFY;
break;
/* Information on the battery has changed, such as physical presence */
case ACPI_DEVICE_CHECK:
case ACPI_BATT_NOTIFY_INFO:
/* Reset all state and let the class driver re-evaluate it all */
DeviceExtension->ArFlag |= (CMBATT_AR_NOTIFY |
CMBATT_AR_INSERT |
CMBATT_AR_REMOVE);
break;
default:
if (CmBattDebug & CMBATT_PNP_INFO)
DbgPrint("CmBattNotifyHandler: Unknown Notify Value: %x\n", NotifyValue);
}
/* Check if we're supposed to delay the notification till later */
if (DeviceExtension->DelayNotification)
{
/* We'll handle this when we get a status query later on */
if (CmBattDebug & CMBATT_PNP_INFO)
DbgPrint("CmBattNotifyHandler: Notification delayed: ARs = %01x\n",
DeviceExtension->ArFlag);
return;
}
/* We're going to handle this now */
if (CmBattDebug & CMBATT_PNP_INFO)
DbgPrint("CmBattNotifyHandler: Performing ARs: %01x\n", DeviceExtension->ArFlag);
/* Check if this is a battery or AC adapter notification */
if (DeviceExtension->FdoType == CmBattBattery)
{
/* Reset the current trip point */
DeviceExtension->TripPointValue = 0xFFFFFFFF;
/* Check what ARs have to be done */
ArFlag = DeviceExtension->ArFlag;
/* New battery inserted, reset lock value */
if (ArFlag & CMBATT_AR_INSERT) InterlockedExchange(&DeviceExtension->ArLockValue, 0);
/* Check if the battery may have been removed */
if (ArFlag & CMBATT_AR_REMOVE) DeviceExtension->Tag = 0;
/* Check if there's been any sort of change to the battery */
if (ArFlag & CMBATT_AR_NOTIFY)
{
/* We'll probably end up re-evaluating _BIF and _BST */
DeviceExtension->NotifySent = TRUE;
BatteryClassStatusNotify(DeviceExtension->ClassData);
}
}
else
{
/* The only known notification is AC/DC change */
if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
{
for (DeviceObject = DeviceExtension->FdoDeviceObject->DriverObject->DeviceObject;
DeviceObject;
DeviceObject = DeviceObject->NextDevice)
{
/* Is this a battery? */
FdoExtension = DeviceObject->DeviceExtension;
if (FdoExtension->FdoType == CmBattBattery)
{
/* Send a notification to the class driver */
FdoExtension->NotifySent = TRUE;
BatteryClassStatusNotify(FdoExtension->ClassData);
}
}
}
}
/* ARs have been processed */
DeviceExtension->ArFlag = 0;
}
VOID
@ -156,11 +263,61 @@ CmBattIoctl(PDEVICE_OBJECT DeviceObject,
NTSTATUS
NTAPI
CmBattQueryTag(PCMBATT_DEVICE_EXTENSION DeviceExtension,
PULONG BatteryTag)
CmBattQueryTag(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
OUT PULONG Tag)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
PDEVICE_OBJECT PdoDevice;
ULONG StaData;
ULONG NewTag;
NTSTATUS Status;
PAGED_CODE();
if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
DbgPrint("CmBattQueryTag - Tag (%d), Battery %x, Device %d\n",
*Tag, DeviceExtension, DeviceExtension->DeviceId);
/* Get PDO and clear notification flag */
PdoDevice = DeviceExtension->PdoDeviceObject;
DeviceExtension->NotifySent = 0;
/* Get _STA from PDO (we need the machine status, not the battery status) */
Status = CmBattGetStaData(PdoDevice, &StaData);
if (NT_SUCCESS(Status))
{
/* Is a battery present? */
if (StaData & ACPI_STA_BATTERY_PRESENT)
{
/* Do we not have a tag yet? */
if (!DeviceExtension->Tag)
{
/* Set the new tag value, reset tags if we reached the maximum */
NewTag = DeviceExtension->TagData;
if (DeviceExtension->TagData++ == 0xFFFFFFFF) NewTag = 1;
DeviceExtension->Tag = NewTag;
if (CmBattDebug & CMBATT_GENERIC_INFO)
DbgPrint("CmBattQueryTag - New Tag: (%d)\n", DeviceExtension->Tag);
/* Reset trip point data */
DeviceExtension->TripPointOld = 0;
DeviceExtension->TripPointValue = 0xFFFFFFFF;
/* Clear AR lock and set new interrupt time */
InterlockedExchange(&DeviceExtension->ArLockValue, 0);
DeviceExtension->InterruptTime = KeQueryInterruptTime();
}
}
else
{
/* No battery, so no tag */
DeviceExtension->Tag = 0;
Status = STATUS_NO_SUCH_DEVICE;
}
}
/* Return the tag and status result */
*Tag = DeviceExtension->Tag;
if (CmBattDebug & CMBATT_ACPI_WARNING)
DbgPrint("CmBattQueryTag: Returning Tag: 0x%x, status 0x%x\n", *Tag, Status);
return Status;
}
NTSTATUS

View file

@ -29,6 +29,15 @@ typedef enum _CMBATT_EXTENSION_TYPE
CmBattBattery
} CMBATT_EXTENSION_TYPE;
#define ACPI_BUS_CHECK 0x00
#define ACPI_DEVICE_CHECK 0x01
#define ACPI_STA_PRESENT 0x01
#define ACPI_STA_ENABLED 0x02
#define ACPI_STA_SHOW_UI 0x04
#define ACPI_STA_FUNCTIONAL 0x08
#define ACPI_STA_BATTERY_PRESENT 0x10
#define ACPI_BATT_NOTIFY_STATUS 0x80
#define ACPI_BATT_NOTIFY_INFO 0x81
@ -67,6 +76,10 @@ typedef struct _ACPI_BIF_DATA
CHAR OemInfo[256];
} ACPI_BIF_DATA, *PACPI_BIF_DATA;
#define CMBATT_AR_NOTIFY 0x01
#define CMBATT_AR_INSERT 0x02
#define CMBATT_AR_REMOVE 0x04
typedef struct _CMBATT_DEVICE_EXTENSION
{
CMBATT_EXTENSION_TYPE FdoType;
@ -85,11 +98,11 @@ typedef struct _CMBATT_DEVICE_EXTENSION
ULONG DeviceId;
PUNICODE_STRING DeviceName;
ACPI_INTERFACE_STANDARD2 AcpiInterface;
BOOLEAN DelayAr;
BOOLEAN DelayedArFlag;
BOOLEAN DelayNotification;
BOOLEAN ArFlag;
PVOID ClassData;
BOOLEAN Started;
BOOLEAN DelayNotification;
BOOLEAN NotifySent;
LONG ArLockValue;
ULONG TagData;
ULONG Tag;
@ -157,4 +170,11 @@ CmBattGetPsrData(
PULONG PsrData
);
NTSTATUS
NTAPI
CmBattGetStaData(
PDEVICE_OBJECT DeviceObject,
PULONG StaData
);
/* EOF */