Haiku Battery Telemetry: From ACPI Methods to PowerStatus
Trace Haiku's ACPI battery driver, device ioctls, and PowerStatus presentation to diagnose missing or misleading laptop battery telemetry.
Haiku’s battery display is the end of a telemetry path, not an independent measurement instrument. On an ACPI system, firmware methods describe battery state and static characteristics; Haiku’s kernel driver evaluates those methods and exposes device information; the PowerStatus application presents the resulting values. A blank icon, an implausible percentage, or a stale-looking estimate can originate at any layer. Tracing the boundaries is more useful than treating the Deskbar icon as a direct firmware reading.
The implementation details below are based on the Haiku source tree and its published release notes. They describe the inspected upstream implementation, not a guarantee that all hardware, firmware, or Haiku releases expose identical behavior. ACPI firmware quality and device support vary; an unreported field should not be invented from a neighboring laptop’s output.
Start with the visible contract
PowerStatus is Haiku’s status application for power information. The project’s R1/beta release notes specifically mention improvements for systems with multiple batteries, runtime battery removal, and batteries charging or discharging at different times or rates. That is an important operational clue: a machine may expose more than one battery device, and the UI must reconcile distinct per-device states rather than assume one pack.
When investigating a report, capture the Haiku version/build, machine model, firmware revision, AC connection, observed battery count, displayed state, and whether the problem follows insertion/removal or a charge transition. A percentage alone is not enough. Preserve what the system reports before comparing it with an external meter or firmware setup screen; those may represent different quantities or update intervals.
The ACPI methods behind the driver
The current Haiku ACPI battery driver source evaluates _BST for dynamic battery status. Its implementation also attempts _BIX for extended/static information and falls back to _BIF when evaluation of _BIX fails. These are ACPI namespace methods provided by firmware. The driver translates their results into Haiku’s internal structures, including state, current rate, remaining capacity, and voltage fields. The source handles unknown sentinel values rather than treating every returned integer as a valid measurement.
That boundary is diagnostically useful. If the driver cannot discover a device, the problem is earlier than the UI. If the device exists but a firmware method returns unusable values, the app may faithfully display a limited result. If the driver data is sensible but the UI is not refreshing, investigate the application/notification path. The available upstream code does not prove which of these conditions applies to a particular computer; it provides a map of what to inspect.
The extended information includes a power-unit indicator. Haiku’s private device header defines the ACPI unit distinction as milliwatts versus milliamps. A rate in mA is not directly comparable to one in mW without voltage context. Likewise, capacity fields should not be assumed to be percentages solely because a UI displays a percent. Firmware fields can be unknown, vendor-specific in quality, or internally inconsistent. Keep any conversion tied to the unit and field definitions in the inspected source.
Driver devices and ioctl boundaries
The driver names battery nodes under /dev/power/acpi_battery/ using an indexed path. The private Haiku header defines device operations including GET_BATTERY_INFO, GET_EXTENDED_BATTERY_INFO, WATCH_BATTERY, and STOP_WATCHING_BATTERY. The ACPIDriverInterface implementation opens a device and asks for current and extended information through the GET ioctls. The driver exposes separate watch operations, but the inspected application interface does not call WATCH_BATTERY; do not infer its use from the header definitions alone.
This suggests a layered diagnosis:
- Does the kernel publish an ACPI battery device node?
- Can the interface open it and retrieve basic information?
- Are extended fields available, and do their units/unknown values make sense?
- Does PowerStatus poll and broadcast updated data, and does the driver’s separate watch capability apply to the path being investigated?
- Does the displayed aggregate still make sense when multiple devices are present?
Do not manually write to a private device node or send undocumented ioctl values while investigating. The names and numeric definitions are implementation interfaces, not a public promise for third-party utilities. A safe report can include read-only UI observations and logs, plus source-version references, without issuing device-control requests of its own.
PowerStatus is a consumer, not the authority
In the inspected ACPIDriverInterface source, the application discovers battery devices by walking the driver’s device directory and creates an interface object for each device it can initialize. Its application-side watcher calls the battery update path and broadcasts a UI update every two seconds. This is distinct from the driver’s WATCH_BATTERY ioctl capability, which this interface does not invoke. The displayed value is therefore not necessarily updated in the exact instant a firmware method changes; the application polling interval is part of the observed latency.
The application’s calculations and presentation are downstream of the values it receives. The source contains logic for refreshing extended information when capacity transitions suggest a battery may have been inserted or removed. Comments in implementation code can explain the author’s interpretation, but they do not establish that every platform emits the same event sequence. For field diagnosis, distinguish “PowerStatus did not refresh,” “the driver returned no device,” and “the firmware returned a value that changed.”
An estimate of remaining time is especially easy to overinterpret. It is derived from available capacity and rate data; those values can fluctuate with firmware reporting, charging policy, load, temperature, and battery condition. Treat the estimate as a UI projection, not a calibrated discharge test. Validate a suspected defect through repeat observations under documented conditions, not a single snapshot.
A safe, reproducible troubleshooting record
Without changing firmware settings or writing to device nodes, collect:
| Field | Why it matters |
|---|---|
| Haiku build and architecture | Source behavior can differ between releases and builds. |
Device paths visible under /dev/power/acpi_battery/ |
Separates device discovery from display. |
| PowerStatus state and timestamp | Makes refresh delay observable. |
| AC connection and controlled state transition | Provides context for charge/discharge changes. |
| Battery count and per-pack behavior | Exposes multi-battery aggregation issues. |
| Firmware-reported unknown/implausible fields | Avoids inventing values from the UI. |
| Relevant system log and reproduction steps | Helps distinguish driver errors from application behavior. |
Use the same observation interval when comparing two builds. If the problem is intermittent, note time and state rather than repeatedly forcing charge/discharge cycles. Do not open the chassis or disconnect an internal battery merely to reproduce a telemetry symptom. If the user-visible value appears stuck, first compare it with a fresh observation after the documented update interval and check whether device presence changed.
When reporting a bug, state the narrowest verified claim: for example, “the battery device node exists, but PowerStatus continues displaying the previous capacity after AC connection,” rather than “ACPI is broken.” Include sanitized logs and the exact Haiku revision. If the issue appears in the driver’s conversion of firmware values, point to the method and field involved and explain the unit. If the raw source and presentation differ, preserve evidence from both layers before proposing a code change.
Interpret absence and disagreement carefully
No battery node can mean the machine lacks a supported ACPI battery device, firmware does not expose one in the expected namespace, or the driver did not bind; it does not prove the physical battery is absent. A node with unknown capacity is not the same as a zero-capacity battery. A percentage that differs from another operating system can arise from different ACPI interpretation, cached updates, or vendor firmware, not necessarily a Haiku calculation bug.
The practical goal is to identify the earliest layer where observable data stops matching expectations. The upstream source gives maintainers a route from ACPI method to device interface to application refresh. It does not justify a hardware-wide claim, a firmware override, or an assumption that one reading is ground truth. Keep tests read-only, compare equivalent measurements, and attach the smallest evidence set that reproduces the discrepancy.
Related:
- Haiku Kernel Semaphores: Counting, Timeouts, and Safe Shutdown
- Haiku BMediaEventLooper: Timed Events in Media Nodes
Sources:
- Haiku ACPI battery driver source - ACPI method evaluation, driver device naming, and battery information handling.
- Haiku PowerStatus ACPI driver interface - device discovery, ioctls, watcher, and application-side refresh behavior.
- Haiku PowerStatus view source - battery aggregation, capacity presentation, and remaining-time calculation from capacity and rate.
- Haiku private power-management device header - ioctl and data-structure definitions in the inspected source.
- Haiku R1/beta6 release notes - documented PowerStatus improvements for multiple batteries, removal, and charge-rate differences.