Skip to content

fix(hidpp): correct UnifiedBattery (0x1004) charging status codes#330

Merged
AprilNEA merged 1 commit into
AprilNEA:masterfrom
PeronGH:fix/unified-battery-status-codes
Jun 29, 2026
Merged

fix(hidpp): correct UnifiedBattery (0x1004) charging status codes#330
AprilNEA merged 1 commit into
AprilNEA:masterfrom
PeronGH:fix/unified-battery-status-codes

Conversation

@PeronGH

@PeronGH PeronGH commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

The UnifiedBattery (0x1004) getStatus "battery status" byte (payload[2])
is decoded into BatteryStatus, but two values were mislabeled and three were
missing:

  • 2 was ChargingSlow — it is actually the final charging stage (nearly
    full), still charging.
  • 4 was Error — it is actually a below-optimal-speed recharge (the real
    "slow charge"), not an error.
  • 5/6/7 (invalid battery, thermal error, charging error) had no
    variants
    at all.

Because the enum stopped at 4, a device reporting 57 failed
BatteryStatus::try_from and get_battery_info returned
UnsupportedResponse — i.e. a thermal/charging-error state broke the whole
battery read rather than surfacing the error. A nearly-full charging device
showed "slow", and a genuinely slow charge showed "error".

Evidence

Cross-checked against two independent sources, which agree:

Linux drivers/hid/hid-logitech-hidpp.c (unified-battery switch (data[2])):

byte kernel this PR
0 discharging Discharging
1 recharging Charging
2 charge in final stage ChargingNearlyFull
3 charge complete Full
4 recharging below optimal speed ChargingSlow
5 invalid battery type InvalidBattery
6 thermal error ThermalError
7 other charging error ChargingError

Solaar (common.py BatteryStatus): 0 DISCHARGING, 1 RECHARGING, 2 ALMOST_FULL, 3 FULL, 4 SLOW_RECHARGE, 5 INVALID_BATTERY, 6 THERMAL_ERROR.

Changes

  • openlogi-hidpp (feature/unified_battery): rename 2ChargingNearlyFull,
    4ChargingSlow, add InvalidBattery / ThermalError / ChargingError
    (57).
  • openlogi-hid (mappings::map_battery_status): map the corrected variants to
    the existing core BatteryStatus — nearly-full → Charging, 57
    Error.

The openlogi-core domain BatteryStatus and all GUI/diagnostics code are
unchanged; this only corrects the wire decode and the bridge to it.

Testing

  • cargo fmt --all -- --check
  • cargo clippy -p openlogi-hid -- -D warnings
  • cargo test -p openlogi-hidpp (152) and cargo test -p openlogi-hid (60)

The full-workspace clippy/test gate was not run locally (it builds GPUI);
the change doesn't touch openlogi-gui, and the only cross-crate consumer of
the wire enum is openlogi-hid::mappings, which is covered above. CI will run
the full gate.

Note

This lands in the vendored openlogi-hidpp fork (0BSD, kept close to
lus/logy). The same fix likely applies upstream — happy to send it there too
if you'd prefer to keep the fork in lockstep.

@greptile-apps

greptile-apps Bot commented Jun 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes the UnifiedBattery (0x1004) BatteryStatus wire enum, which had two mislabeled discriminants (bytes 2 and 4 were swapped) and was missing three variants (bytes 5–7), causing try_from failures and surfacing device error states as UnsupportedResponse.

  • openlogi-hidpp: Renames ChargingSlow = 2ChargingNearlyFull and Error = 4ChargingSlow, and adds InvalidBattery = 5, ThermalError = 6, ChargingError = 7 — cross-referenced against both the Linux kernel HID-PP driver and Solaar.
  • openlogi-hid mappings: Bridges the corrected variants to the unchanged core BatteryStatusChargingNearlyFull folds into Charging, the three new error variants map to Error, and the #[non_exhaustive] wildcard arm is preserved.

Confidence Score: 5/5

Safe to merge — the change is a pure enum re-labeling and extension with no logic changes beyond the corrected wire mapping.

Both changed files are narrow in scope: one corrects discriminant labels and adds three new enum variants, the other updates the exhaustive bridge match accordingly. The #[non_exhaustive] wildcard arm in map_battery_status ensures forward compatibility. The correction is well-documented and cross-verified against two independent reference implementations. No data paths outside the battery status decode are touched.

No files require special attention.

Important Files Changed

Filename Overview
crates/openlogi-hidpp/src/feature/unified_battery/mod.rs Corrects BatteryStatus discriminant values 2 and 4 (previously swapped labels) and adds missing variants 5–7 (InvalidBattery, ThermalError, ChargingError) — fixes try_from failures for devices reporting error states.
crates/openlogi-hid/src/mappings.rs Updates map_battery_status bridge to handle the corrected enum — ChargingNearlyFull maps to Charging, and the three new error variants map to Error; wildcard fallback retained for non_exhaustive safety.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Device wire byte\n(0x1004 getStatus payload[2])"] --> B{BatteryStatus::try_from}
    B -->|0| C[Discharging]
    B -->|1| D[Charging]
    B -->|2| E[ChargingNearlyFull ✨]
    B -->|3| F[Full]
    B -->|4| G[ChargingSlow ✨]
    B -->|5| H[InvalidBattery ✨]
    B -->|6| I[ThermalError ✨]
    B -->|7| J[ChargingError ✨]
    B -->|other| K[Err — try_from failure]

    C --> M[map_battery_status]
    D --> M
    E --> M
    F --> M
    G --> M
    H --> M
    I --> M
    J --> M

    M -->|Discharging| N[core::BatteryStatus::Discharging]
    M -->|Charging, ChargingNearlyFull| O[core::BatteryStatus::Charging]
    M -->|ChargingSlow| P[core::BatteryStatus::ChargingSlow]
    M -->|Full| Q[core::BatteryStatus::Full]
    M -->|InvalidBattery, ThermalError, ChargingError| R[core::BatteryStatus::Error]
    M -->|_| S[core::BatteryStatus::Unknown]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["Device wire byte\n(0x1004 getStatus payload[2])"] --> B{BatteryStatus::try_from}
    B -->|0| C[Discharging]
    B -->|1| D[Charging]
    B -->|2| E[ChargingNearlyFull ✨]
    B -->|3| F[Full]
    B -->|4| G[ChargingSlow ✨]
    B -->|5| H[InvalidBattery ✨]
    B -->|6| I[ThermalError ✨]
    B -->|7| J[ChargingError ✨]
    B -->|other| K[Err — try_from failure]

    C --> M[map_battery_status]
    D --> M
    E --> M
    F --> M
    G --> M
    H --> M
    I --> M
    J --> M

    M -->|Discharging| N[core::BatteryStatus::Discharging]
    M -->|Charging, ChargingNearlyFull| O[core::BatteryStatus::Charging]
    M -->|ChargingSlow| P[core::BatteryStatus::ChargingSlow]
    M -->|Full| Q[core::BatteryStatus::Full]
    M -->|InvalidBattery, ThermalError, ChargingError| R[core::BatteryStatus::Error]
    M -->|_| S[core::BatteryStatus::Unknown]
Loading

Reviews (2): Last reviewed commit: "fix(hidpp): correct UnifiedBattery (0x10..." | Re-trigger Greptile

Comment thread crates/openlogi-hidpp/src/feature/unified_battery/mod.rs Outdated
The getStatus battery-status byte values 2 and 4 were mislabeled: 2 is the
final charging stage (nearly full) and 4 is a below-optimal-speed recharge —
not a slow charge and a generic error. Codes 5-7 (invalid battery, thermal
error, charging error) were missing entirely.

Align BatteryStatus with the Linux hid-logitech-hidpp unified-battery mapping
and Solaar, and update map_battery_status: the nearly-full stage maps to
Charging and 5-7 map to Error, leaving the core domain enum and GUI unchanged.
@PeronGH PeronGH force-pushed the fix/unified-battery-status-codes branch from 59eb3aa to 7fbb0d1 Compare June 28, 2026 07:01
@AprilNEA AprilNEA merged commit 64b9b16 into AprilNEA:master Jun 29, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants