OpenLogi

0x1001 · batteryVoltage

Battery state as a measured millivolt reading plus charging flags — the only battery source on many G-series wireless devices.

Reports a device's battery as a measured voltage plus a charging-flags byte. G-series wireless gaming devices (G915, G903 LIGHTSPEED, G502 LIGHTSPEED) expose 0x1001 and neither 0x1000 nor 0x1004, so without it the inventory probe finds no battery source for them at all.

Unlike its siblings the feature reports no percentage; OpenLogi estimates one from the voltage when it renders the battery indicator.

The wire layout is not in a public Logitech spec. The big-endian millivolt u16 followed by one flags byte was reverse-engineered; the decoding follows Solaar's decipher_battery_voltage and libratbag's consensus on the flag bits.

Spec: reverse-engineered — x1001 batteryVoltage. Used by: battery state on G-series wireless devices.

Function reference

The BatteryVoltageFeature wrapper (0x1001) exposes:

Methods

FunctionHID++ fnSignatureReturns
get_battery_info0()VoltageBatteryInfo

The method is async and returns Result<…, Hidpp20Error>. The broadcast event is not implemented.

Types

VoltageBatteryInfo

FieldTypeDescription
voltage_mvu16Measured battery voltage in millivolts — roughly 3500 (empty) to 4200 (full) for the single-cell Li-Po batteries these devices carry.
statusVoltageChargingStatusCharging state decoded from the flags byte.
criticalboolThe firmware's "charge level critical" marker (flags bit 5).

VoltageChargingStatus

VariantDescription
DischargingRunning on battery (bit 7 clear).
ChargingCharging at the standard rate.
ChargingFastCharging at a raised current (bit 3).
ChargingSlowCharging at reduced current (bit 4).
FullOn external power with charge complete (status bits 0b01).
NotChargingOn external power but not charging — a charge fault (status bits 0b10).

Decoding is total on purpose: a contradictory or future flag combination falls into the nearest charging bucket rather than failing, so a battery reading never vanishes over an unknown bit.

Wire format

get_battery_info (fn 0)

Request: [0x00, 0x00, 0x00] (no parameters)

Response (byte → field):

ByteFieldNotes
0–1voltage_mvbig-endian u16, millivolts
2flagscharging state, decoded below

Flags byte:

Bit(s)Meaning
7External power present. Clear → Discharging, and every other bit is meaningless.
0–1Charge status: 0b01 (or 0b11) → Full, 0b10NotCharging. Takes precedence over the rate bits.
3Fast charging → ChargingFast.
4Slow charging → ChargingSlow.
5critical — surfaced independently of the status.

Usage (Rust)

use hidpp::{device::Device, feature::battery_voltage::BatteryVoltageFeature};

// device: &mut Device, already created via Device::new(channel, index)
device.enumerate_features().await?;

if let Some(feat) = device.get_feature::<BatteryVoltageFeature>() {
    let info = feat.get_battery_info().await?;
    println!("{} mV — {:?} (critical: {})", info.voltage_mv, info.status, info.critical);
}

See also: 0x1004 unifiedBattery, 0x1000 batteryStatus.

On this page