https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b0680d65feeed36b931e7…
commit b0680d65feeed36b931e77f7ef861e8799725bc6
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sat Dec 14 13:48:46 2024 +0100
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Tue Dec 17 14:23:33 2024 +0100
[BATTC] Signal the wait battery tag event when notifying Battery Class
BatteryClassStatusNotify is used by battery miniport drivers to notify the Battery Class of a status change. This can either be a battery status change or battery tag assignation, depending on what the device extension (namely the composite battery) waits for.
We do have implementation for EVENT_BATTERY_STATUS but not for EVENT_BATTERY_TAG. What happens is when BatteryClassIoctl fails to query the battery tag because it has not yet been assigned, the thread is stuck on waiting for the event object to be signaled, forever.
This tipically happens when a timeout of -1 (meaning the calling thread must wait indefinitely) is supplied. The composite battery driver (COMPBATT) is responsible to signal the Battery Class when a CM (Control Method) ACPI battery receives a tag, which then this function will signal the event.
CORE-18969
CORE-19452
---
drivers/battery/battc/battc.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/battery/battc/battc.c b/drivers/battery/battc/battc.c
index 84ae9df061e..e724f720b5f 100644
--- a/drivers/battery/battc/battc.c
+++ b/drivers/battery/battc/battc.c
@@ -76,11 +76,13 @@ BatteryClassQueryWmiDataBlock(PVOID ClassData,
BCLASSAPI
NTSTATUS
NTAPI
-BatteryClassStatusNotify(PVOID ClassData)
+BatteryClassStatusNotify(
+ _In_ PVOID ClassData)
{
PBATTERY_CLASS_DATA BattClass;
PBATTERY_WAIT_STATUS BattWait;
BATTERY_STATUS BattStatus;
+ ULONG Tag;
NTSTATUS Status;
DPRINT("Received battery status notification from %p\n", ClassData);
@@ -99,7 +101,14 @@ BatteryClassStatusNotify(PVOID ClassData)
{
case EVENT_BATTERY_TAG:
ExReleaseFastMutex(&BattClass->Mutex);
- DPRINT1("Waiting for battery is UNIMPLEMENTED!\n");
+ Status = BattClass->MiniportInfo.QueryTag(BattClass->MiniportInfo.Context,
+ &Tag);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ ExAcquireFastMutex(&BattClass->Mutex);
+ KeSetEvent(&BattClass->WaitEvent, IO_NO_INCREMENT, FALSE);
+ ExReleaseFastMutex(&BattClass->Mutex);
break;
case EVENT_BATTERY_STATUS:
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f3dd15ad64b4d37e807ff…
commit f3dd15ad64b4d37e807ffafacb419ddd914df995
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Mon Dec 16 22:09:02 2024 +0100
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Mon Dec 16 22:09:02 2024 +0100
[CMBATT] Grab the design voltage after the BIF data gets copied
There was a risk of accessing invalid data as the design voltage was grabbed before the read BIF data was copied into the device extension.
---
drivers/bus/acpi/cmbatt/cmbatt.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/bus/acpi/cmbatt/cmbatt.c b/drivers/bus/acpi/cmbatt/cmbatt.c
index 452c2242317..cff0f8afd14 100644
--- a/drivers/bus/acpi/cmbatt/cmbatt.c
+++ b/drivers/bus/acpi/cmbatt/cmbatt.c
@@ -280,7 +280,7 @@ CmBattVerifyStaticInfo(
_In_ ULONG BatteryTag)
{
ACPI_BIF_DATA BifData;
- ULONG DesignVoltage = DeviceExtension->BifData.DesignVoltage;
+ ULONG DesignVoltage;
PBATTERY_INFORMATION Info = &DeviceExtension->BatteryInformation;
NTSTATUS Status;
@@ -293,6 +293,7 @@ CmBattVerifyStaticInfo(
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)
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ea8315ba567ea2bb60755…
commit ea8315ba567ea2bb607554145cb6597b78453ba7
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sat Dec 14 15:52:43 2024 +0100
Commit: George Bișoc <george.bisoc(a)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;