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

commit faf6123150344a3843b7055ca327104332273736
Author:     George Bișoc <george.bi...@reactos.org>
AuthorDate: Tue Dec 17 23:22:39 2024 +0100
Commit:     George Bișoc <george.bi...@reactos.org>
CommitDate: Thu Jan 2 18:21:33 2025 +0100

    [CMBATT] Implement support for the _BIX method
    
    _BIX is basically _BIF but with more information added, such as cycle 
count, measurement capacity accuracy and whatnot.
    Starting with ACPI 4.0 _BIF is rendered obsolete and as a matter of fact a 
lot of modern hardware fill their ACPI machine data to _BIX.
    
    ReactOS must go forward and beyond, compatibility with _BIF is kept. NOTE 
that a machine can ONLY support one battery static information method!
    
    CORE-18969
    CORE-19452
---
 drivers/bus/acpi/cmbatt/cmbatt.c | 424 ++++++++++++++++++++++++++++++++-------
 drivers/bus/acpi/cmbatt/cmbatt.h |  55 ++++-
 drivers/bus/acpi/cmbatt/cmexec.c |  64 ++++++
 3 files changed, 469 insertions(+), 74 deletions(-)

diff --git a/drivers/bus/acpi/cmbatt/cmbatt.c b/drivers/bus/acpi/cmbatt/cmbatt.c
index cff0f8afd14..407fa149572 100644
--- a/drivers/bus/acpi/cmbatt/cmbatt.c
+++ b/drivers/bus/acpi/cmbatt/cmbatt.c
@@ -273,71 +273,276 @@ CmBattUnload(IN PDRIVER_OBJECT DriverObject)
     }
 }
 
+/**
+ * @brief
+ * Retrieves the static information of the battery.
+ *
+ * @param[in] DeviceExtension
+ * A pointer to a Control Method (CM) battery device extension.
+ * It is used for debugging purposes.
+ *
+ * @param[out] UseBix
+ * A pointer to a boolean value, returned to caller. This can return
+ * TRUE if this machine supports the _BIX method, FALSE otherwise.
+ *
+ * @param[out] BattInfo
+ * A pointer to a structure that contains the static info of the
+ * battery. ONLY ONE type of information is filled. See Remarks.
+ *
+ * @return
+ * Returns STATUS_INSUFFICIENT_RESOURCES if there is no enough
+ * memory to allocate for the static info buffer. Returns
+ * STATUS_SUCCESS if the operation has succeeded. Otherwise an
+ * error NTSTATUS code is returned.
+ *
+ * @remarks
+ * It is important to note that a machine can only support one method,
+ * _BIX or _BIF. Starting with ACPI 4.0, _BIF has become deprecated.
+ * The caller MUST INSPECT the boolean value, ExtendedData, in order
+ * to determine if the machine has returned the extended information
+ * data or not.
+ */
+static
+NTSTATUS
+CmBattGetBattStaticInfo(
+    _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    _Out_ PBOOLEAN UseBix,
+    _Outptr_ PACPI_BATT_STATIC_INFO *BattInfo)
+{
+    NTSTATUS Status;
+    ACPI_BIF_DATA BifData;
+    ACPI_BIX_DATA BixData;
+    PACPI_BATT_STATIC_INFO Info;
+
+    /* Allocate pool space for the static information */
+    Info = ExAllocatePoolZero(PagedPool,
+                              sizeof(*Info),
+                              CMBATT_BATT_STATIC_INFO_TAG);
+    if (Info == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Assume this machine supports the _BIX method */
+    *UseBix = TRUE;
+
+    /* Retrieve extended battery static info from _BIX method */
+    Status = CmBattGetBixData(DeviceExtension, &BixData);
+    if (!NT_SUCCESS(Status))
+    {
+        /*
+         * It failed. This can be expected because not every machine supports
+         * _BIX, especially the older machines which do not support ACPI 4.0.
+         * Fallback to _BIF at this point.
+         */
+        Status = CmBattGetBifData(DeviceExtension, &BifData);
+        if (!NT_SUCCESS(Status))
+        {
+            /* That failed too, time to punt */
+            ExFreePoolWithTag(Info, CMBATT_BATT_STATIC_INFO_TAG);
+            return Status;
+        }
+
+        /* Acknowledge the caller it will be going to use _BIF */
+        *UseBix = FALSE;
+        Info->BifData = BifData;
+    }
+    else
+    {
+        Info->BixData = BixData;
+    }
+
+    /* Return the battery static info to caller */
+    Info->ExtendedData = *UseBix;
+    *BattInfo = Info;
+    return Status;
+}
+
+/**
+ * @brief
+ * Verifies the extended battery information (_BIX) and translates
+ * such data to the BATTERY_INFORMATION structure.
+ *
+ * @param[in] DeviceExtension
+ * A pointer to a Control Method (CM) battery device extension.
+ * It is used to gather _BIX data.
+ *
+ * @param[in,out] Info
+ * A pointer to a structure of which this function fills in
+ * battery information that can be by other battery miniport
+ * drivers, such as the Composite Battery driver.
+ */
+static
+VOID
+CmBattVerifyBixData(
+    _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    _Inout_ PBATTERY_INFORMATION Info)
+{
+    ULONG DesignVoltage;
+    ACPI_BIX_DATA BixData = DeviceExtension->BattInfo.BixData;
+
+    /* Copy the battery info data */
+    Info->Technology = BixData.BatteryTechnology;
+    Info->CycleCount = BixData.CycleCount;
+    RtlCopyMemory(Info->Chemistry, BixData.BatteryType, 4);
+
+    /* Check if the power stats are reported in ampere or watts */
+    if (BixData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
+    {
+        /*
+         * 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.
+         */
+        DesignVoltage = BixData.DesignVoltage;
+        if ((DesignVoltage != BATTERY_UNKNOWN_VOLTAGE) && (DesignVoltage != 0))
+        {
+            /* Convert the design capacity */
+            Info->DesignedCapacity = CONVERT_BATT_INFO(BixData.DesignCapacity, 
DesignVoltage);
+
+            /* Convert the full charged capacity */
+            Info->FullChargedCapacity = 
CONVERT_BATT_INFO(BixData.LastFullCapacity, DesignVoltage);
+
+            /* Convert the low capacity alarm (DefaultAlert1) */
+            Info->DefaultAlert1 = CONVERT_BATT_INFO(BixData.DesignCapacityLow, 
DesignVoltage);
+
+            /* Convert the designed capacity warning alarm (DefaultAlert2) */
+            Info->DefaultAlert2 = 
CONVERT_BATT_INFO(BixData.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 = BixData.DesignCapacity;
+        Info->FullChargedCapacity = BixData.LastFullCapacity;
+        Info->DefaultAlert1 = BixData.DesignCapacityLow;
+        Info->DefaultAlert2 = BixData.DesignCapacityWarning;
+    }
+}
+
+/**
+ * @brief
+ * Verifies the battery information (_BIF) and translates
+ * such data to the BATTERY_INFORMATION structure.
+ *
+ * @param[in] DeviceExtension
+ * A pointer to a Control Method (CM) battery device extension.
+ * It is used to gather _BIF data.
+ *
+ * @param[in,out] Info
+ * A pointer to a structure of which this function fills in
+ * battery information that can be by other battery miniport
+ * drivers, such as the Composite Battery driver.
+ */
+static
+VOID
+CmBattVerifyBifData(
+    _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    _Inout_ PBATTERY_INFORMATION Info)
+{
+    ULONG DesignVoltage;
+    ACPI_BIF_DATA BifData = DeviceExtension->BattInfo.BifData;
+
+    /* Copy the battery info data, CycleCount is not supported in _BIF */
+    Info->Technology = BifData.BatteryTechnology;
+    Info->CycleCount = 0;
+    RtlCopyMemory(Info->Chemistry, BifData.BatteryType, 4);
+
+    /* Check if the power stats are reported in ampere or watts */
+    if (BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
+    {
+        /*
+         * 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.
+         */
+        DesignVoltage = BifData.DesignVoltage;
+        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;
+        Info->DefaultAlert2 = BifData.DesignCapacityWarning;
+    }
+}
+
 NTSTATUS
 NTAPI
 CmBattVerifyStaticInfo(
     _Inout_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
     _In_ ULONG BatteryTag)
 {
-    ACPI_BIF_DATA BifData;
-    ULONG DesignVoltage;
-    PBATTERY_INFORMATION Info = &DeviceExtension->BatteryInformation;
     NTSTATUS Status;
+    BOOLEAN UseBix;
+    PACPI_BATT_STATIC_INFO BattInfo;
+    PBATTERY_INFORMATION Info = &DeviceExtension->BatteryInformation;
 
-    Status = CmBattGetBifData(DeviceExtension, &BifData);
+    /* FIXME: This function is not fully implemented, more checks need to be 
implemented */
+    UNREFERENCED_PARAMETER(BatteryTag);
+
+    /* Retrieve the battery static info */
+    Status = CmBattGetBattStaticInfo(DeviceExtension, &UseBix, &BattInfo);
     if (NT_SUCCESS(Status))
     {
+        /* Initialize the battery information data */
         RtlZeroMemory(Info, sizeof(*Info));
         Info->Capabilities = BATTERY_SYSTEM_BATTERY;
-        Info->Technology = BifData.BatteryTechnology;
-        RtlCopyMemory(Info->Chemistry, BifData.BatteryType, 4);
-        // FIXME: take from _BIX method: Info->CycleCount
-        DeviceExtension->BifData = BifData;
-        DesignVoltage = DeviceExtension->BifData.DesignVoltage;
-
-        /* Check if the power stats are reported in ampere or watts */
-        if (BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
-        {
-            /*
-             * 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);
+        /* Copy the static information to the device extension of the battery 
*/
+        RtlCopyMemory(&DeviceExtension->BattInfo, BattInfo, sizeof(*BattInfo));
 
-                /* 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;
-            }
+        /* Check if the data from _BIX has to be used or not */
+        if (UseBix)
+        {
+            CmBattVerifyBixData(DeviceExtension, Info);
         }
         else
         {
-            /* The stats are in milli-watts, use them directly */
-            Info->DesignedCapacity = BifData.DesignCapacity;
-            Info->FullChargedCapacity = BifData.LastFullCapacity;
-            Info->DefaultAlert1 = BifData.DesignCapacityLow;
-            Info->DefaultAlert2 = BifData.DesignCapacityWarning;
+            CmBattVerifyBifData(DeviceExtension, Info);
         }
+
+        /* Free the static information buffer as we already copied it */
+        ExFreePoolWithTag(BattInfo, CMBATT_BATT_STATIC_INFO_TAG);
     }
 
     return Status;
@@ -530,20 +735,44 @@ CmBattIoctl(IN PDEVICE_OBJECT DeviceObject,
                 }
                 break;
 
-            case IOCTL_BATTERY_QUERY_BIF:
+            case IOCTL_BATTERY_QUERY_BIF_BIX:
 
-                /* Data is 1060 bytes long */
-                if (OutputBufferLength == sizeof(ACPI_BIF_DATA))
+                /* Return the battery static information to the caller 
depending on the supported ACPI method */
+                if (DeviceExtension->BattInfo.ExtendedData)
                 {
-                    /* Query it */
-                    Status = CmBattGetBifData(DeviceExtension,
-                                              Irp->AssociatedIrp.SystemBuffer);
-                    if (NT_SUCCESS(Status)) Irp->IoStatus.Information = 
sizeof(ACPI_BIF_DATA);
+                    if (OutputBufferLength == sizeof(ACPI_BIX_DATA))
+                    {
+                        /* Query it */
+                        Status = CmBattGetBixData(DeviceExtension,
+                                                  
Irp->AssociatedIrp.SystemBuffer);
+                        if (NT_SUCCESS(Status))
+                        {
+                            Irp->IoStatus.Information = sizeof(ACPI_BIX_DATA);
+                        }
+                    }
+                    else
+                    {
+                        /* Buffer size invalid */
+                        Status = STATUS_INVALID_BUFFER_SIZE;
+                    }
                 }
                 else
                 {
-                    /* Buffer size invalid */
-                    Status = STATUS_INVALID_BUFFER_SIZE;
+                    if (OutputBufferLength == sizeof(ACPI_BIF_DATA))
+                    {
+                        /* Query it */
+                        Status = CmBattGetBifData(DeviceExtension,
+                                                  
Irp->AssociatedIrp.SystemBuffer);
+                        if (NT_SUCCESS(Status))
+                        {
+                            Irp->IoStatus.Information = sizeof(ACPI_BIF_DATA);
+                        }
+                    }
+                    else
+                    {
+                        /* Buffer size invalid */
+                        Status = STATUS_INVALID_BUFFER_SIZE;
+                    }
                 }
                 break;
 
@@ -699,7 +928,7 @@ CmBattSetStatusNotify(IN PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
 {
     NTSTATUS Status;
     ACPI_BST_DATA BstData;
-    ULONG Capacity, NewTripPoint, TripPoint, DesignVoltage;
+    ULONG PowerUnit, Capacity, NewTripPoint, TripPoint, DesignVoltage;
     BOOLEAN Charging;
     PAGED_CODE();
     if (CmBattDebug & (CMBATT_ACPI_WARNING | CMBATT_GENERIC_INFO))
@@ -738,11 +967,22 @@ CmBattSetStatusNotify(IN PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
         NewTripPoint = BatteryNotify->LowCapacity;
     }
 
+    /* Is this machine supporting _BIX or _BIF? */
+    if (DeviceExtension->BattInfo.ExtendedData)
+    {
+        PowerUnit = DeviceExtension->BattInfo.BixData.PowerUnit;
+        DesignVoltage = DeviceExtension->BattInfo.BixData.DesignVoltage;
+    }
+    else
+    {
+        PowerUnit = DeviceExtension->BattInfo.BifData.PowerUnit;
+        DesignVoltage = DeviceExtension->BattInfo.BifData.DesignVoltage;
+    }
+
     /* Do we have data in Amps or Watts? */
-    if (DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
+    if (PowerUnit == ACPI_BATT_POWER_UNIT_AMPS)
     {
         /* We need the voltage to do the conversion */
-        DesignVoltage = DeviceExtension->BifData.DesignVoltage;
         if ((DesignVoltage != BATTERY_UNKNOWN_VOLTAGE) && (DesignVoltage))
         {
             /* Convert from mAh into Ah */
@@ -846,6 +1086,7 @@ CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
     ULONG PsrData = 0;
     NTSTATUS Status;
     ULONG BstState;
+    ULONG PowerUnit;
     ULONG DesignVoltage, PresentRate, RemainingCapacity;
     PAGED_CODE();
     if (CmBattDebug & CMBATT_GENERIC_INFO)
@@ -946,13 +1187,24 @@ CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
         DbgPrint("CmBattGetBatteryStatus: AC adapter is NOT connected\n");
     }
 
+    /* Is this machine supporting _BIX or _BIF? */
+    if (DeviceExtension->BattInfo.ExtendedData)
+    {
+        PowerUnit = DeviceExtension->BattInfo.BixData.PowerUnit;
+        DesignVoltage = DeviceExtension->BattInfo.BixData.DesignVoltage;
+    }
+    else
+    {
+        PowerUnit = DeviceExtension->BattInfo.BifData.PowerUnit;
+        DesignVoltage = DeviceExtension->BattInfo.BifData.DesignVoltage;
+    }
+
     /* 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)
+    if (PowerUnit == ACPI_BATT_POWER_UNIT_WATTS)
     {
         /* Get the data from the BST */
         DeviceExtension->RemainingCapacity = RemainingCapacity;
@@ -970,7 +1222,7 @@ CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION 
DeviceExtension,
             }
         }
     }
-    else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage != 0)) // 
Same as doing DeviceExtension->BifData.PowerUnit == ACPI_BATT_POWER_UNIT_AMPS
+    else if ((DesignVoltage != CM_UNKNOWN_VALUE) && (DesignVoltage != 0)) // 
Same as doing PowerUnit == ACPI_BATT_POWER_UNIT_AMPS
     {
         /* We have voltage data, what about capacity? */
         if (RemainingCapacity == CM_UNKNOWN_VALUE)
@@ -1180,7 +1432,14 @@ CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION 
FdoExtension,
         case BatteryDeviceName:
 
             /* Build the model number string */
-            RtlInitAnsiString(&TempString, FdoExtension->BifData.ModelNumber);
+            if (FdoExtension->BattInfo.ExtendedData)
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BixData.ModelNumber);
+            }
+            else
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BifData.ModelNumber);
+            }
 
             /* Convert it to Unicode */
             InfoString.Buffer = InfoBuffer;
@@ -1202,7 +1461,14 @@ CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION 
FdoExtension,
         case BatteryManufactureName:
 
             /* Build the OEM info string */
-            RtlInitAnsiString(&TempString, FdoExtension->BifData.OemInfo);
+            if (FdoExtension->BattInfo.ExtendedData)
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BixData.OemInfo);
+            }
+            else
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BifData.OemInfo);
+            }
 
             /* Convert it to Unicode */
             InfoString.Buffer = InfoBuffer;
@@ -1217,7 +1483,14 @@ CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION 
FdoExtension,
         case BatteryUniqueID:
 
             /* Build the serial number string */
-            RtlInitAnsiString(&TempString, FdoExtension->BifData.SerialNumber);
+            if (FdoExtension->BattInfo.ExtendedData)
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BixData.SerialNumber);
+            }
+            else
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BifData.SerialNumber);
+            }
 
             /* Convert it to Unicode */
             InfoString.Buffer = InfoBuffer;
@@ -1229,10 +1502,18 @@ CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION 
FdoExtension,
             TempString2.MaximumLength = sizeof(TempBuffer);
 
             /* Check if there's an OEM string */
-            if (FdoExtension->BifData.OemInfo[0])
+            if ((FdoExtension->BattInfo.ExtendedData && 
FdoExtension->BattInfo.BixData.OemInfo[0]) ||
+                FdoExtension->BattInfo.BifData.OemInfo[0])
             {
                 /* Build the OEM info string */
-                RtlInitAnsiString(&TempString, FdoExtension->BifData.OemInfo);
+                if (FdoExtension->BattInfo.ExtendedData)
+                {
+                    RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BixData.OemInfo);
+                }
+                else
+                {
+                    RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BifData.OemInfo);
+                }
 
                 /* Convert it to Unicode and append it */
                 RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0);
@@ -1240,7 +1521,14 @@ CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION 
FdoExtension,
             }
 
             /* Build the model number string */
-            RtlInitAnsiString(&TempString, FdoExtension->BifData.ModelNumber);
+            if (FdoExtension->BattInfo.ExtendedData)
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BixData.ModelNumber);
+            }
+            else
+            {
+                RtlInitAnsiString(&TempString, 
FdoExtension->BattInfo.BifData.ModelNumber);
+            }
 
             /* Convert it to Unicode and append it */
             RtlAnsiStringToUnicodeString(&TempString2, &TempString, 0);
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.h b/drivers/bus/acpi/cmbatt/cmbatt.h
index 4a4817916f6..e6ab5f029bd 100644
--- a/drivers/bus/acpi/cmbatt/cmbatt.h
+++ b/drivers/bus/acpi/cmbatt/cmbatt.h
@@ -26,7 +26,7 @@
 #define IOCTL_BATTERY_SET_TRIP_POINT \
     CTL_CODE(FILE_DEVICE_BATTERY, 0x104, METHOD_BUFFERED, FILE_READ_ACCESS) // 
0x294410
 
-#define IOCTL_BATTERY_QUERY_BIF \
+#define IOCTL_BATTERY_QUERY_BIF_BIX \
     CTL_CODE(FILE_DEVICE_BATTERY, 0x105, METHOD_BUFFERED, FILE_READ_ACCESS) // 
0x294414
 
 #define IOCTL_BATTERY_QUERY_BST \
@@ -85,6 +85,8 @@ typedef struct _ACPI_BST_DATA
 #define ACPI_BATT_POWER_UNIT_WATTS  0x0
 #define ACPI_BATT_POWER_UNIT_AMPS   0x1
 
+#define ASCIIZ_MAX_LENGTH   256
+
 typedef struct _ACPI_BIF_DATA
 {
     ULONG PowerUnit;
@@ -96,12 +98,46 @@ typedef struct _ACPI_BIF_DATA
     ULONG DesignCapacityLow;
     ULONG BatteryCapacityGranularity1;
     ULONG BatteryCapacityGranularity2;
-    CHAR ModelNumber[256];
-    CHAR SerialNumber[256];
-    CHAR BatteryType[256];
-    CHAR OemInfo[256];
+    CHAR ModelNumber[ASCIIZ_MAX_LENGTH];
+    CHAR SerialNumber[ASCIIZ_MAX_LENGTH];
+    CHAR BatteryType[ASCIIZ_MAX_LENGTH];
+    CHAR OemInfo[ASCIIZ_MAX_LENGTH];
 } ACPI_BIF_DATA, *PACPI_BIF_DATA;
 
+typedef struct _ACPI_BIX_DATA
+{
+    ULONG Revision;
+    ULONG PowerUnit;
+    ULONG DesignCapacity;
+    ULONG LastFullCapacity;
+    ULONG BatteryTechnology;
+    ULONG DesignVoltage;
+    ULONG DesignCapacityWarning;
+    ULONG DesignCapacityLow;
+    ULONG CycleCount;
+    ULONG Accuracy;
+    ULONG MaxSampleTime;
+    ULONG MinSampleTime;
+    ULONG MaxAverageInterval;
+    ULONG MinAverageInterval;
+    ULONG BatteryCapacityGranularity1;
+    ULONG BatteryCapacityGranularity2;
+    CHAR ModelNumber[ASCIIZ_MAX_LENGTH];
+    CHAR SerialNumber[ASCIIZ_MAX_LENGTH];
+    CHAR BatteryType[ASCIIZ_MAX_LENGTH];
+    CHAR OemInfo[ASCIIZ_MAX_LENGTH];
+    ULONG SwapCapability;
+} ACPI_BIX_DATA, *PACPI_BIX_DATA;
+
+typedef struct _ACPI_BATT_STATIC_INFO
+{
+    ACPI_BIF_DATA BifData;
+    ACPI_BIX_DATA BixData;
+    BOOLEAN ExtendedData;
+} ACPI_BATT_STATIC_INFO, *PACPI_BATT_STATIC_INFO;
+
+#define CMBATT_BATT_STATIC_INFO_TAG     'nItS'
+
 #define CMBATT_AR_NOTIFY            0x01
 #define CMBATT_AR_INSERT            0x02
 #define CMBATT_AR_REMOVE            0x04
@@ -132,7 +168,7 @@ typedef struct _CMBATT_DEVICE_EXTENSION
     ULONG TagData;
     ULONG Tag;
     ACPI_BST_DATA BstData;
-    ACPI_BIF_DATA BifData;
+    ACPI_BATT_STATIC_INFO BattInfo;
     ULONG Id;
     ULONG State;
     ULONG RemainingCapacity;
@@ -203,6 +239,13 @@ CmBattGetBifData(
     PACPI_BIF_DATA BifData
 );
 
+NTSTATUS
+NTAPI
+CmBattGetBixData(
+    _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    _Out_ PACPI_BIX_DATA BixData
+);
+
 NTSTATUS
 NTAPI
 CmBattSetTripPpoint(
diff --git a/drivers/bus/acpi/cmbatt/cmexec.c b/drivers/bus/acpi/cmbatt/cmexec.c
index b1d294ae9ef..b85b07709a3 100644
--- a/drivers/bus/acpi/cmbatt/cmexec.c
+++ b/drivers/bus/acpi/cmbatt/cmexec.c
@@ -445,6 +445,70 @@ CmBattGetBifData(PCMBATT_DEVICE_EXTENSION DeviceExtension,
                                  RTL_NUMBER_OF(BifFields));
 }
 
+/**
+ * @brief
+ * Retrieves the eXtended static battery information from the
+ * ACPI _BIX method.
+ *
+ * @param[in] DeviceExtension
+ * A pointer to a Control Method (CM) battery device extension.
+ * It is used to send the ACPI method evaluation operation
+ * to the ACPI driver of which it is attached to this CM battery.
+ *
+ * @param[out] BixData
+ * A pointer to a structure that contains the _BIX data fields,
+ * returned to caller.
+ *
+ * @return
+ * Returns STATUS_SUCCESS if the operation has succeeded successfully,
+ * otherwise a failure NTSTATUS code is returned.
+ */
+NTSTATUS
+NTAPI
+CmBattGetBixData(
+    _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension,
+    _Out_ PACPI_BIX_DATA BixData)
+{
+    ACPI_PACKAGE_FIELD BixFields[] = {
+        { "Revision", FALSE, &BixData->Revision },
+        { "PowerUnit", FALSE, &BixData->PowerUnit },
+        { "DesignCapacity", FALSE, &BixData->DesignCapacity },
+        { "LastFullCapacity", FALSE, &BixData->LastFullCapacity },
+        { "BatteryTechnology", FALSE, &BixData->BatteryTechnology },
+        { "DesignVoltage", FALSE, &BixData->DesignVoltage },
+        { "DesignCapacityWarning", FALSE, &BixData->DesignCapacityWarning },
+        { "DesignCapacityLow", FALSE, &BixData->DesignCapacityLow },
+        { "CycleCount", FALSE, &BixData->CycleCount },
+        { "Accuracy", FALSE, &BixData->Accuracy },
+        { "MaxSampleTime", FALSE, &BixData->MaxSampleTime },
+        { "MinSampleTime", FALSE, &BixData->MinSampleTime },
+        { "MaxAverageInterval", FALSE, &BixData->MaxAverageInterval },
+        { "MinAverageInterval", FALSE, &BixData->MinAverageInterval },
+        { "BatteryCapacityGranularity1", FALSE, 
&BixData->BatteryCapacityGranularity1 },
+        { "BatteryCapacityGranularity2", FALSE, 
&BixData->BatteryCapacityGranularity2 },
+        { "ModelNumber", TRUE, &BixData->ModelNumber },
+        { "SerialNumber", TRUE, &BixData->SerialNumber },
+        { "BatteryType", TRUE, &BixData->BatteryType },
+        { "OemInfo", TRUE, &BixData->OemInfo },
+        { "SwapCapability", FALSE, &BixData->SwapCapability },
+    };
+    PAGED_CODE();
+
+    if (CmBattDebug & CMBATT_ACPI_ENTRY_EXIT)
+    {
+        DbgPrint("CmBattGetBixData: Buffer (0x%x) Device %x Tid %x\n",
+                 BixData, DeviceExtension->DeviceId, KeGetCurrentThread());
+    }
+
+    /* Request the ACPI driver to get the _BIX data for us */
+    return CmBattCallAcpiPackage("CmBattGetBifData",
+                                 DeviceExtension,
+                                 'XIB_',
+                                 512,
+                                 BixFields,
+                                 RTL_NUMBER_OF(BixFields));
+}
+
 NTSTATUS
 NTAPI
 CmBattGetBstData(PCMBATT_DEVICE_EXTENSION DeviceExtension,

Reply via email to