https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ea8315ba567ea2bb607554145cb6597b78453ba7

commit ea8315ba567ea2bb607554145cb6597b78453ba7
Author:     George Bișoc <george.bi...@reactos.org>
AuthorDate: Sat Dec 14 15:52:43 2024 +0100
Commit:     George Bișoc <george.bi...@reactos.org>
CommitDate: Mon Dec 16 17:33:51 2024 +0100

    [CMBATT] Convert power statistics from mAh to mWh
    
    ReactOS (like any other OSes) expects power data to be represented in 
milliwatts per hour, not in milliamps per hour.
    Currently CMBATT defaults the stats to unknown values, if that's the case, 
and there are a bunch of machines that do report their data from _BIF ACPI 
method in ampere.
    
    CORE-18969
    CORE-19452
---
 drivers/bus/acpi/cmbatt/cmbatt.c | 48 ++++++++++++++++++++++++++++++++--------
 drivers/bus/acpi/cmbatt/cmbatt.h |  7 ++++++
 2 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/bus/acpi/cmbatt/cmbatt.c b/drivers/bus/acpi/cmbatt/cmbatt.c
index 3935a9c8150..452c2242317 100644
--- a/drivers/bus/acpi/cmbatt/cmbatt.c
+++ b/drivers/bus/acpi/cmbatt/cmbatt.c
@@ -275,10 +275,12 @@ CmBattUnload(IN PDRIVER_OBJECT DriverObject)
 
 NTSTATUS
 NTAPI
-CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION DeviceExtension,
-                       ULONG BatteryTag)
+CmBattVerifyStaticInfo(
+    _Inout_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    _In_ ULONG BatteryTag)
 {
     ACPI_BIF_DATA BifData;
+    ULONG DesignVoltage = DeviceExtension->BifData.DesignVoltage;
     PBATTERY_INFORMATION Info = &DeviceExtension->BatteryInformation;
     NTSTATUS Status;
 
@@ -292,16 +294,44 @@ CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
         // FIXME: take from _BIX method: Info->CycleCount
         DeviceExtension->BifData = BifData;
 
-        if (BifData.PowerUnit == 1)
+        /* Check if the power stats are reported in ampere or watts */
+        if (BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
         {
-            DPRINT1("FIXME: need to convert mAh into mWh\n");
-            Info->DesignedCapacity = BATTERY_UNKNOWN_CAPACITY;
-            Info->FullChargedCapacity = BATTERY_UNKNOWN_CAPACITY;
-            Info->DefaultAlert1 = BATTERY_UNKNOWN_CAPACITY;
-            Info->DefaultAlert2 = BATTERY_UNKNOWN_CAPACITY;
+            /*
+             * We have got power stats in milli-ampere but ReactOS expects the 
values
+             * to be reported in milli-watts, so we have to convert them.
+             * In order to do so we must expect the design voltage of the 
battery
+             * is not unknown.
+             */
+            if ((DesignVoltage != BATTERY_UNKNOWN_VOLTAGE) && (DesignVoltage 
!= 0))
+            {
+                /* Convert the design capacity */
+                Info->DesignedCapacity = 
CONVERT_BATT_INFO(BifData.DesignCapacity, DesignVoltage);
+
+                /* Convert the full charged capacity */
+                Info->FullChargedCapacity = 
CONVERT_BATT_INFO(BifData.LastFullCapacity, DesignVoltage);
+
+                /* Convert the low capacity alarm (DefaultAlert1) */
+                Info->DefaultAlert1 = 
CONVERT_BATT_INFO(BifData.DesignCapacityLow, DesignVoltage);
+
+                /* Convert the designed capacity warning alarm (DefaultAlert2) 
*/
+                Info->DefaultAlert2 = 
CONVERT_BATT_INFO(BifData.DesignCapacityWarning, DesignVoltage);
+            }
+            else
+            {
+                /*
+                 * Without knowing the nominal designed voltage of the battery
+                 * we cannot determine the power consumption of this battery.
+                 */
+                Info->DesignedCapacity = BATTERY_UNKNOWN_CAPACITY;
+                Info->FullChargedCapacity = BATTERY_UNKNOWN_CAPACITY;
+                Info->DefaultAlert1 = BATTERY_UNKNOWN_CAPACITY;
+                Info->DefaultAlert2 = BATTERY_UNKNOWN_CAPACITY;
+            }
         }
         else
         {
+            /* The stats are in milli-watts, use them directly */
             Info->DesignedCapacity = BifData.DesignCapacity;
             Info->FullChargedCapacity = BifData.LastFullCapacity;
             Info->DefaultAlert1 = BifData.DesignCapacityLow;
@@ -939,7 +969,7 @@ CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
             }
         }
     }
-    else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage))
+    else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage != 0)) // 
Same as doing DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS
     {
         /* We have voltage data, what about capacity? */
         if (RemainingCapacity == CM_UNKNOWN_VALUE)
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.h b/drivers/bus/acpi/cmbatt/cmbatt.h
index bb130208763..4a4817916f6 100644
--- a/drivers/bus/acpi/cmbatt/cmbatt.h
+++ b/drivers/bus/acpi/cmbatt/cmbatt.h
@@ -67,6 +67,13 @@ typedef enum _CMBATT_EXTENSION_TYPE
 #define CM_MAX_VALUE                0x7FFFFFFF
 #define CM_UNKNOWN_VALUE            0xFFFFFFFF
 
+#define CONVERT_MAH_TO_MWH(mA, Volts) (((mA) * (Volts) + 500) / 1000)
+
+#define CONVERT_BATT_INFO(Capacity, DesignVoltage) \
+    (((Capacity) != BATTERY_UNKNOWN_CAPACITY) \
+        ? CONVERT_MAH_TO_MWH((Capacity), (DesignVoltage)) \
+        : BATTERY_UNKNOWN_CAPACITY)
+
 typedef struct _ACPI_BST_DATA
 {
     ULONG State;

Reply via email to