https://git.reactos.org/?p=reactos.git;a=commitdiff;h=faf6123150344a3843b70…
commit faf6123150344a3843b7055ca327104332273736
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Tue Dec 17 23:22:39 2024 +0100
Commit: George Bișoc <george.bisoc(a)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,