[Feature]: Decode OnboardProfiles (0x8100) event 1 - live DPI stage changes from the mouse
- 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 change their DPI stage on the hardware itself (the DPI button cycles the onboard profile's DPI slots). Nothing in OpenLogi can see that happen: `0x8100` is name-only on master, and the in-flight onboard-profiles work (#459 read/mode slice, #1002 read + write groundwork, #1146 G502 branch) decodes no events, so even once those land the GUI's DPI display goes stale the moment the user presses the DPI button. Polling `0x2201` only returns the resulting value, not which profile slot is active, and burns traffic on battery mice.
Measured on real hardware (G305, WPID 0x4074, profile_format_id 3, Lightspeed receiver 046d:c53f; raw frame traces available on request): the device broadcasts the change.
### Proposed solution
Decode `0x8100` event 1 in the onboard-profiles feature (the `EventSource` pattern from `wireless_device_status.rs` fits):
1. **Event 1 is "current DPI index changed".** Frame shape `[0x11, device_index, feature_index, 0x10, new_index, 0x00 ...]` - function nibble 1, `params[0]` = new 0-based index into the profile's DPI slot table. Observed `02`, `00`, `01` across three DPI-button presses. Mapping the index into the decoded profile's DPI slots gives a live "current DPI" readout with zero polling.
2. **Document the event that never comes:** `setCurrentProfile` (function 3) completes with no broadcast - confirmed in two capture sessions on different days. Code that waits for a profile-activated event after switching profiles will hang; reading `getCurrentProfile` back is the reliable confirmation. Worth a doc comment in the feature so nobody rediscovers this the hard way.
Both facts are G305-measured; the `--sector`/diag tooling from #1002 should make it easy to check whether the G502 family behaves the same.
### Alternatives considered
- Polling 0x2201 after the fact: returns the DPI value but not the active slot, races the press, and costs battery on wireless mice.
- G HUB shows the live stage; that is the bar to match.
### Related area(s)
- [x] GUI
- [ ] CLI
- [ ] Button actions / remapping
- [x] DPI
- [ ] SmartShift
- [ ] Per-application profiles
- [ ] Configuration (TOML)
- [ ] Auto-update
- [x] Other
### Additional context
Deliberately filed as its own issue rather than a review comment on #1002/#459 so it stays actionable regardless of how those PRs slice up the 0x8100 work. Related: #1193 (another implemented-but-unwired event, 0x8090 broadcast) - same EventSource wiring pattern would serve both.
Contributor guide
No contributing guide indexed for this repository
Research direction
Inspect the onboard-profiles feature and compare its event handling with wireless_device_status.rs and its EventSource pattern. Use the --sector/diag tooling and G305 traces to verify 0x8100 event 1 and its DPI-slot index mapping. Done means the GUI updates the live DPI stage without polling, and the feature documents that setCurrentProfile has no broadcast and must be confirmed by getCurrentProfile.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, desktop
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100