[Feature]: Wire up ModeStatus (0x8090) - performance/endurance switching for G-series mice
- Dominant language
- Rust
- Stars
- 21k
- Forks
- 675
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 172
Description
### Pre-flight checklist
- [x] I searched existing issues and the [Roadmap](https://github.com/AprilNEA/OpenLogi#roadmap), and this isn't already tracked.
### Problem / motivation
G-series mice with HID++ `0x8090 ModeStatus` (G305 and friends) have a performance/endurance power mode that decides polling behavior and battery life (Logitech quotes about 250 hours vs about 9 months on the G305). Today OpenLogi cannot show or change it, so users still need G HUB for this one switch.
The groundwork already exists: `crates/openlogi-hidpp/src/feature/mode_status.rs` implements `get_mode_status`, `set_mode_status`, `set_performance_mode` and `get_device_config`, registered for `0x8090` - but nothing consumes it. There are no call sites outside the feature crate: the agent never reads the mode, the GUI has no toggle, the CLI has no command. (Not a duplicate of #459, which is `0x8100` onboard-vs-host mode - a different mode.)
### Proposed solution
Wire the existing driver end to end: agent reads mode + capabilities on connect, GUI gets a Performance/Endurance toggle (shown when `get_device_config` reports SOFTWARE_SWITCH), CLI gets a diag/set command.
I traced the feature against real hardware (G305, WPID 0x4074, FW RQM68.02.B0021, Lightspeed receiver 046d:c53f); raw request/reply logs available on request. The measured behavior the wiring needs to respect:
1. Encoding matches the crate: `status0` bit 0, set = performance, clear = endurance.
2. `status1` bit 0 is rejected: a set with `changed_mask1 = 0x01` answers HID++ error 2 (InvalidArgument). Use `changed_mask0` only.
3. `getDevConfig` returns `0x02` on the G305: software switch only, no hardware switch.
4. The mode rewrites `0x8060 AdjustableReportRate`: endurance -> performance changes the supported list from `[8]` ms to `[1, 2, 4, 8]` ms and the current rate from 8 to 1 ms (and back on restore). Any report-rate UI must re-read the list and current rate after a mode change, and distinguish the rate stored in the onboard profile sector from the effective rate the mode allows.
5. The setting persists across power cycles (verified by switching the mouse off and on: `status0` still read `01`, rate list still `[1, 2, 4, 8]`). Caveat: one power-on broadcast in my logs showed the bit cleared after it had been left set earlier the same day, so read the mode on every reconnect rather than trusting cached state.
6. The device broadcasts `0x8090` event 0 with params `(status0, status1, changed_mask)`: observed `01 00 01` right after a successful set and `00 00 01` on power-on, alongside the `0x1D4B` reconnection broadcast. The driver currently decodes no events; without event 0 the UI goes stale when the mode changes elsewhere. Same `EventSource` pattern as `wireless_device_status.rs` would fit.
### Alternatives considered
- G HUB: works, but running it defeats the point of OpenLogi.
- Keeping the mouse permanently in one mode: the G305 ships in endurance mode, so without this switch users silently never get the 1 ms polling the hardware supports.
- Solaar exposes the raw feature on Linux; nothing comparable exists for macOS/Windows.
### Related area(s)
- [x] GUI
- [x] CLI
- [ ] Button actions / remapping
- [x] DPI
- [ ] SmartShift
- [ ] Per-application profiles
- [ ] Configuration (TOML)
- [ ] Auto-update
- [x] Other
### Additional context
All numbers above are from HID++ frame captures on my own hardware. Happy to share the full traces or to test a branch on the G305.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with crates/openlogi-hidpp/src/feature/mode_status.rs and compare event decoding with wireless_device_status.rs. Trace how the agent, GUI, and CLI consume the existing feature APIs; verify reconnect reads, event updates, and mode-dependent report-rate data, with the toggle and diagnostic/set command working on supported devices.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, cli, desktop
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100