[CMBATT]: Implement CmBattQueryTag and CmBattNotifyHandler for getting ACPI Battery...
authorSir Richard <sir_richard@svn.reactos.org>
Sun, 21 Mar 2010 18:04:08 +0000 (18:04 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sun, 21 Mar 2010 18:04:08 +0000 (18:04 +0000)
svn path=/trunk/; revision=46309

reactos/drivers/bus/acpi/cmbatt/cmbatt.c
reactos/drivers/bus/acpi/cmbatt/cmbatt.h

index 45903cb..2b69d27 100644 (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
index 34e580d..1ce38bd 100644 (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 */