Skip to content

feat: wire up ModeStatus (0x8090) performance/endurance switching - #1201

Open
007hacky007 wants to merge 14 commits into
AprilNEA:masterfrom
007hacky007:feat/mode-status-wiring
Open

feat: wire up ModeStatus (0x8090) performance/endurance switching#1201
007hacky007 wants to merge 14 commits into
AprilNEA:masterfrom
007hacky007:feat/mode-status-wiring

Conversation

@007hacky007

Copy link
Copy Markdown

Summary

Wires the existing ModeStatusFeature (HID++ 0x8090, performance/endurance power mode) end to end, per the plan in #1193: the driver decodes the mode-change event, the agent serves read/write RPCs, the GUI gets a Performance-mode toggle on the Pointer tab, and the CLI gets a diag power-mode round-trip. All protocol behavior follows the G305 measurements in the issue: status0 bit 0, changed_mask0-only writes (a set touching changed_mask1 answers InvalidArgument), getDevConfig gating, and the 01 00 01 / 00 00 01 event-0 broadcasts.

Changes

  • hidpp: ModeStatusFeature gains an EventSource<ModeStatusEvent> plus a public ModeStatusEvent::decode shim (same shape as unified_battery); payload layout is marked reverse-engineered from G305 captures.
  • core: new hid::mode_status module with the IPC-facing PowerMode / PowerModeState; HidppOperation gains ReadPowerMode / WritePowerMode (appended, wire-safe).
  • device / hid: write/power_mode.rs with get_power_mode(_on) / set_power_mode(_on) (writes only changed_mask0), host-facade wrappers, and scripted-channel tests asserting the exact set bytes 01 00 01 00.
  • ipc: read_power_mode / set_power_mode appended to the trait, PROTOCOL_VERSION 29 -> 30, wire-format goldens extended (request variants 0x1a/0x1b, result encoding pinned).
  • agent: both RPCs served over the shared per-device channel runner; the mock agent seeds the Bolt mouse with a G305-shaped state (endurance, software switch only) so the GUI dev loop exercises the panel.
  • gui: a "Power mode" card on the Pointer tab with a Performance toggle, gated in-place like SmartShift (Load::Unsupported degradation, no Capabilities churn). The toggle disables when getDevConfig reports no software switch. Writes are optimistic with a confirming re-read; the resolved value is never persisted because the device keeps the mode across power cycles itself (verified in the issue) - deliberately no config.toml surface. Reads re-arm on selection/inventory changes, so every reconnect re-reads the mode as the issue recommends.
  • i18n: 8 new [pointer] keys across all 23 catalogs (best-effort translations; happy to take corrections).
  • cli: openlogi diag power-mode - read -> toggle -> read-back -> restore, --set performance|endurance to leave a mode applied, --device filter; device auto-selection keys on feature 0x8090.
  • docs: one diag power-mode line in USAGE.md.

The last commit fixes a pre-existing get_device_config byte-order bug the hardware run exposed (details under Testing).

Deliberate scope cuts (can follow up if wanted): no agent-side event consumption yet (the driver decode + shim make that a small follow-up in inventory/events.rs), no bindable button action, no report-rate UI interplay (OpenLogi does not wire 0x8060 today).

Screenshot

The card on a real G305 (Pointer tab, macOS), served by the agent over the new RPCs - endurance active, toggle live, with the macOS pointer-speed note:

Power mode card on a G305

Testing

  • cargo test -p openlogi-hidpp (event decode: post-set 01 00 01, power-on 00 00 01, non-zero function rejected)
  • cargo test -p openlogi-device (scripted-channel read + exact write bytes)
  • cargo test -p openlogi-ipc --test wire_format (new goldens + pinned v30)
  • cargo test -p openlogi-ui locale and cargo test -p openlogi-desktop i18n (23-catalog parity)
  • Full local gate: cargo fmt --all -- --check, cargo clippy --workspace --all-targets -- -D warnings (RUSTFLAGS="-D warnings"), cargo test --workspace, non-GUI rustdoc, typos --config .config/typos.toml .
  • Not run: cargo-deny, MSRV matrix, Linux/Windows clippy (no toolchains on this host)
  • Desktop app runtime-verified twice: against openlogi-agent-mock, and against the real agent + G305 over the receiver - the screenshot above is live hardware, read through the new read_power_mode RPC
  • Real-hardware verification (G305, WPID 0x4074, Lightspeed receiver): openlogi diag power-mode round-trip passes - reads Endurance, toggles to Performance, reads it back, restores Endurance. It also caught a latent driver bug on the first run: get_device_config decoded the capability bytes big-endian, shifting the G305's 0x02 (software switch) into the high byte and reporting no capabilities at all - which would have greyed out the GUI toggle on the exact device this feature targets. Fixed to read the byte the device answers (little-endian; the scripted fixture now mirrors the real reply) and re-verified: the diag reports software_switch=true hardware_switch=false, matching the issue's capture.

Field observation worth documenting: with macOS pointer acceleration enabled, switching to performance (report rate 8 ms -> 1 ms) makes the cursor feel slower at the same DPI - per-report deltas are 8x smaller and the OS acceleration curve gives small deltas less gain. Verified the sensor DPI itself is untouched by the mode switch (read 4400 in both modes on the G305). Not an OpenLogi bug, but it is the first thing a tester notices, so the card now carries a macOS-only caption explaining it (new pointer.power_mode_macos_pointer_note key in all catalogs).

Fixes #1193

@007hacky007
007hacky007 requested a review from AprilNEA as a code owner August 31, 2026 16:55
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

Greptile Summary

The PR wires HID++ ModeStatus power-mode support through the device, IPC, agent, desktop, and CLI layers.

  • Adds performance/endurance protocol decoding, reads, writes, and IPC representations.
  • Adds a Pointer-tab toggle with capability gating and confirming reads.
  • Adds a CLI power-mode diagnostic with restoration verification and extends localization and usage documentation.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/openlogi-cli/src/cmd/diag/power_mode.rs Adds read, set, toggle, confirming read, and verified restoration flows for the power-mode diagnostic.
crates/openlogi-device/src/write/power_mode.rs Implements device-facing ModeStatus reads and changed-mask-scoped writes.
crates/openlogi-hidpp/src/feature/mode_status.rs Extends the ModeStatus protocol wrapper with event decoding and write support.
crates/openlogi-ipc/src/ipc.rs Adds versioned power-mode read and write RPC methods.
crates/openlogi-desktop/src/state/power_mode.rs Adds optimistic power-mode state updates followed by device-confirming reads.
crates/openlogi-desktop/src/features/pointer/power_mode.rs Adds the Pointer-tab performance-mode control and capability-based disabled state.

Sequence Diagram

sequenceDiagram
    participant UI as Desktop / CLI
    participant IPC as Agent IPC
    participant Agent as Agent
    participant HID as HID++ ModeStatus
    UI->>IPC: ReadPowerMode / SetPowerMode
    IPC->>Agent: Route request to device runner
    Agent->>HID: getDevConfig / getModeStatus / setModeStatus
    HID-->>Agent: Mode and switch capabilities
    Agent-->>IPC: PowerModeState
    IPC-->>UI: Render or verify selected mode
Loading

Reviews (3): Last reviewed commit: "fix(cli): verify the power-mode restore ..." | Re-trigger Greptile

Comment thread crates/openlogi-cli/src/cmd/diag/power_mode.rs Outdated
Comment thread crates/openlogi-cli/src/cmd/diag/power_mode.rs Outdated
@davidbudnick davidbudnick added type: feature New feature request area: hidpp HID++ protocol and device feature support platform: all Cross-platform issue labels Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: hidpp HID++ protocol and device feature support platform: all Cross-platform issue type: feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Wire up ModeStatus (0x8090) - performance/endurance switching for G-series mice

2 participants