[ros-diffs] [sir_richard] 46291: [CMBATT]: Implement CmBattGetBatteryStatus. See ACPI Specification 4.0B (10.2 Control Method Batteries, P.383).

sir_richard at svn.reactos.org sir_richard at svn.reactos.org
Sun Mar 21 04:14:13 CET 2010


Author: sir_richard
Date: Sun Mar 21 04:14:12 2010
New Revision: 46291

URL: http://svn.reactos.org/svn/reactos?rev=46291&view=rev
Log:
[CMBATT]: Implement CmBattGetBatteryStatus. See ACPI Specification 4.0B (10.2	Control Method Batteries, P.383).

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/cmbatt.c?rev=46291&r1=46290&r2=46291&view=diff
==============================================================================
--- 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 04:14:12 2010
@@ -18,6 +18,7 @@
 UNICODE_STRING GlobalRegistryPath;
 KTIMER CmBattWakeDpcTimerObject;
 KDPC CmBattWakeDpcObject;
+PDEVICE_OBJECT AcAdapterPdo;
  
 /* FUNCTIONS ******************************************************************/
 
@@ -182,11 +183,220 @@
 
 NTSTATUS
 NTAPI
-CmBattGetBatteryStatus(PCMBATT_DEVICE_EXTENSION DeviceExtension,
-                       ULONG BatteryTag)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
+                       IN ULONG Tag)
+{
+    ULONG PsrData = 0;
+    NTSTATUS Status;
+    ULONG BstState;
+    ULONG DesignVoltage, PresentRate, RemainingCapacity;
+    PAGED_CODE();
+    if (CmBattDebug & CMBATT_GENERIC_INFO)
+        DbgPrint("CmBattGetBatteryStatus - CmBatt (%08x) Tag (%d)\n", DeviceExtension, Tag);
+    
+    /* Validate ACPI data */    
+    Status = CmBattVerifyStaticInfo(DeviceExtension, Tag);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Check for delayed status notifications */
+    if (DeviceExtension->DelayNotification)
+    {
+        /* Process them now and don't do any other work */
+        CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS);
+        return Status;
+    }
+
+    /* Get _BST from ACPI */
+    Status = CmBattGetBstData(DeviceExtension, &DeviceExtension->BstData);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        InterlockedExchange(&DeviceExtension->ArLockValue, 0);
+        return Status;
+    }
+    
+    /* Clear current BST information */ 
+    DeviceExtension->State = 0;
+    DeviceExtension->RemainingCapacity = 0;
+    DeviceExtension->PresentVoltage = 0;
+    DeviceExtension->Rate = 0;
+
+    /* Get battery state */
+    BstState = DeviceExtension->BstData.State;
+    
+    /* Is the battery both charging and discharging? */
+    if ((BstState & ACPI_BATT_STAT_DISCHARG) && (BstState & ACPI_BATT_STAT_CHARGING) &&
+        (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)))
+            DbgPrint("************************ ACPI BIOS BUG ********************\n* "
+                     "CmBattGetBatteryStatus: Invalid state: _BST method returned 0x%08x for Battery State.\n"
+                     "* One battery cannot be charging and discharging at the same time.\n",
+                     BstState);
+    
+    /* Is the battery discharging? */   
+    if (BstState & ACPI_BATT_STAT_DISCHARG)
+    {
+        /* Set power state and check if it just started discharging now */
+        DeviceExtension->State |= BATTERY_DISCHARGING;
+        if (!(DeviceExtension->State & ACPI_BATT_STAT_DISCHARG))
+        {
+            /* Remember the time when the state changed */
+            DeviceExtension->InterruptTime = KeQueryInterruptTime();
+        }
+    }
+    else if (BstState & ACPI_BATT_STAT_CHARGING)
+    {
+        /* Battery is charging, update power state */
+        DeviceExtension->State |= (BATTERY_CHARGING | BATTERY_POWER_ON_LINE);
+    }
+    
+    /* Is the battery in a critical state? */
+    if (BstState & ACPI_BATT_STAT_CRITICAL) DeviceExtension->State |= BATTERY_CRITICAL;
+    
+    /* Read the voltage data */  
+    DeviceExtension->PresentVoltage = DeviceExtension->BstData.PresentVoltage;
+    
+    /* Check if we have an A/C adapter */
+    if (AcAdapterPdo)
+    {
+        /* Query information on it */
+        CmBattGetPsrData(AcAdapterPdo, &PsrData);
+    }
+    else
+    {
+        /* Otherwise, check if the battery is charging */
+        if (BstState & ACPI_BATT_STAT_CHARGING)
+        {
+            /* Then we'll assume there's a charger */
+            PsrData = 1;
+        }
+        else
+        {
+            /* Assume no charger */
+            PsrData = 0;        
+        }
+    }
+    
+    /* Is there a charger? */
+    if (PsrData)
+    {
+        /* Set the power state flag to reflect this */
+        DeviceExtension->State |= BATTERY_POWER_ON_LINE;
+        if (CmBattDebug & (CMBATT_GENERIC_INFO | CMBATT_GENERIC_STATUS))
+            DbgPrint("CmBattGetBatteryStatus: AC adapter is connected\n");
+    }
+    else if (CmBattDebug & (CMBATT_GENERIC_INFO | CMBATT_GENERIC_STATUS))
+    {
+        DbgPrint("CmBattGetBatteryStatus: AC adapter is NOT connected\n");        
+    }
+    
+    /* Get some data we'll need */
+    DesignVoltage = DeviceExtension->BifData.DesignVoltage;
+    PresentRate = DeviceExtension->BstData.PresentRate;
+    RemainingCapacity = DeviceExtension->BstData.RemainingCapacity;
+    
+    /* Check if we have battery data in Watts instead of Amps */
+    if (DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_WATTS)
+    {
+        /* Get the data from the BST */
+        DeviceExtension->RemainingCapacity = RemainingCapacity;
+        DeviceExtension->Rate = PresentRate;
+        
+        /* Check if the rate is invalid */
+        if (PresentRate > CM_MAX_VALUE)
+        {
+            /* Set an unknown rate and don't touch the old value */
+            DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;
+            if ((PresentRate != CM_UNKNOWN_VALUE) && (CmBattDebug & CMBATT_ACPI_WARNING))
+            {
+                DbgPrint("CmBattGetBatteryStatus - Rate is greater than CM_MAX_VALUE\n");
+                DbgPrint("----------------------   PresentRate = 0x%08x\n", PresentRate);
+            }
+        }
+    }
+    else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage))
+    {
+        /* We have voltage data, what about capacity? */
+        if (RemainingCapacity == CM_UNKNOWN_VALUE)
+        {
+            /* Unable to calculate it */
+            DeviceExtension->RemainingCapacity = BATTERY_UNKNOWN_CAPACITY;
+            if (CmBattDebug & CMBATT_ACPI_WARNING)
+            {
+                DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity \n");
+                DbgPrint("----------------------   RemainingCapacity = CM_UNKNOWN_VALUE\n");
+            }
+        }
+        else
+        {
+            /* Compute the capacity with the information we have */
+            DeviceExtension->RemainingCapacity = (DesignVoltage * RemainingCapacity + 500) / 1000;
+        }
+        
+        /* Check if we have a rate */
+        if (PresentRate != CM_UNKNOWN_VALUE)
+        {
+            /* Make sure the rate isn't too large */
+            if (PresentRate > (-500 / DesignVoltage))
+            {
+                /* It is, so set unknown state */
+                DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;
+                if (CmBattDebug & CMBATT_ACPI_WARNING)
+                {
+                    DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n");
+                    DbgPrint("----------------------   Overflow: PresentRate = 0x%08x\n", PresentRate);
+                }
+            }
+            
+            /* Compute the rate */
+            DeviceExtension->Rate = (PresentRate * DesignVoltage + 500) / 1000;
+        }
+        else
+        {
+            /* We don't have a rate, so set unknown value */
+            DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;        
+            if (CmBattDebug & CMBATT_ACPI_WARNING)
+            {
+                DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n");
+                DbgPrint("----------------------   Present Rate = CM_UNKNOWN_VALUE\n");
+            }
+        }
+    }
+    else
+    {
+        /* We have no rate, and no capacity, set unknown values */
+        DeviceExtension->Rate = BATTERY_UNKNOWN_RATE;
+        DeviceExtension->RemainingCapacity = BATTERY_UNKNOWN_CAPACITY;
+        if (CmBattDebug & CMBATT_ACPI_WARNING)
+        {
+            DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity and Rate \n");
+            DbgPrint("----------------------   DesignVoltage = 0x%08x\n", DesignVoltage);
+        }
+    }
+    
+    /* Check if we have an unknown rate */
+    if (DeviceExtension->Rate == BATTERY_UNKNOWN_RATE)
+    {
+        /* The battery is discharging but we don't know by how much... this is bad! */
+        if ((BstState & ACPI_BATT_STAT_DISCHARG) &&
+            (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)))
+            DbgPrint("CmBattGetBatteryStatus: battery rate is unkown when battery is not charging!\n");
+    }
+    else if (DeviceExtension->State & BATTERY_DISCHARGING)
+    {
+        /* The battery is discharging, so treat the rate as a negative rate */
+        DeviceExtension->Rate = -DeviceExtension->Rate;
+    }
+    else if (!(DeviceExtension->State & BATTERY_CHARGING) && (DeviceExtension->Rate))
+    {
+        /* We are not charging, not discharging, but have a rate? Ignore it! */
+        if (CmBattDebug & CMBATT_GENERIC_WARNING)
+            DbgPrint("CmBattGetBatteryStatus: battery is not charging or discharging, but rate = %x\n",
+                     DeviceExtension->Rate);
+        DeviceExtension->Rate = 0;
+    }
+     
+    /* Done */
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS

Modified: trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.h?rev=46291&r1=46290&r2=46291&view=diff
==============================================================================
--- 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 04:14:12 2010
@@ -29,11 +29,15 @@
     CmBattBattery
 } CMBATT_EXTENSION_TYPE;
 
+#define ACPI_BATT_NOTIFY_STATUS     0x80
+#define ACPI_BATT_NOTIFY_INFO       0x81
+
 #define ACPI_BATT_STAT_DISCHARG		0x0001
 #define ACPI_BATT_STAT_CHARGING		0x0002
 #define ACPI_BATT_STAT_CRITICAL		0x0004
-#define ACPI_BATT_STAT_NOT_PRESENT	0x0007
-#define ACPI_BATT_STAT_MAX		    0x0007
+
+#define CM_MAX_VALUE                0x7FFFFFFF
+#define CM_UNKNOWN_VALUE            0xFFFFFFFF
 
 typedef struct _ACPI_BST_DATA
 {
@@ -42,6 +46,9 @@
     ULONG RemainingCapacity;
     ULONG PresentVoltage;
 } ACPI_BST_DATA, *PACPI_BST_DATA;
+
+#define ACPI_BATT_POWER_UNIT_WATTS  0x0
+#define ACPI_BATT_POWER_UNIT_AMPS   0x1
 
 typedef struct _ACPI_BIF_DATA
 {
@@ -82,8 +89,8 @@
     BOOLEAN DelayedArFlag;
     PVOID ClassData;
     BOOLEAN Started;
-    BOOLEAN NotifySent;
-    ULONG ArLock;
+    BOOLEAN DelayNotification;
+    LONG ArLockValue;
     ULONG TagData;
     ULONG Tag;
     ULONG ModelNumberLength;
@@ -135,5 +142,19 @@
     PDEVICE_OBJECT DeviceObject,
     PIRP Irp
 );
- 
+
+NTSTATUS
+NTAPI
+CmBattGetBstData(
+    PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    PACPI_BST_DATA BstData
+);
+
+NTSTATUS
+NTAPI
+CmBattGetPsrData(
+    PDEVICE_OBJECT DeviceObject,
+    PULONG PsrData
+);
+
 /* EOF */




More information about the Ros-diffs mailing list