Author: sir_richard
Date: Sun Mar 21 19:04:08 2010
New Revision: 46309
URL:
http://svn.reactos.org/svn/reactos?rev=46309&view=rev
Log:
[CMBATT]: Implement CmBattQueryTag and CmBattNotifyHandler for getting ACPI Battery
notifications, as per ACPI Spec and
http://www.microsoft.com/whdc/archive/ACPInotify.mspx.
Modified:
trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c
trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.h
Modified: trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/cmbatt/cm…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c [iso-8859-1] Sun Mar 21 19:04:08 2010
@@ -43,10 +43,117 @@
VOID
NTAPI
-CmBattNotifyHandler(PCMBATT_DEVICE_EXTENSION DeviceExtension,
- ULONG NotifyValue)
-{
- UNIMPLEMENTED;
+CmBattNotifyHandler(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ IN ULONG NotifyValue)
+{
+ 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 @@
NTSTATUS
NTAPI
-CmBattQueryTag(PCMBATT_DEVICE_EXTENSION DeviceExtension,
- PULONG BatteryTag)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+CmBattQueryTag(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ OUT PULONG Tag)
+{
+ 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
Modified: trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/cmbatt/cm…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.h [iso-8859-1] Sun Mar 21 19:04:08 2010
@@ -28,6 +28,15 @@
CmBattAcAdapter,
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 @@
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 @@
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 @@
PULONG PsrData
);
+NTSTATUS
+NTAPI
+CmBattGetStaData(
+ PDEVICE_OBJECT DeviceObject,
+ PULONG StaData
+);
+
/* EOF */