Skip to content

feat(hidpp): remap G502 X Plus extra buttons via 0x8110 - #1350

Open
CazzaCoder wants to merge 9 commits into
AprilNEA:masterfrom
CazzaCoder:feat/g502x-plus-button-spy
Open

CazzaCoder wants to merge 9 commits into
AprilNEA:masterfrom
CazzaCoder:feat/g502x-plus-button-spy

Conversation

@CazzaCoder

@CazzaCoder CazzaCoder commented Sep 11, 2026

Copy link
Copy Markdown

Summary

Changes

  • hidpp: SetMouseButtonMapping on 0x8110; minimal 0x8100 get/set mode (Onboard / Host).
  • cli / hid / device write: openlogi diag mouse-buttons [--watch] stays read/spy-only (no mode switch from the CLI).
  • core / ipc: ButtonId::{DpiShift,DpiUp,DpiDown,ProfileCycle} + SPY_BUTTONS (not in ALL); SpyModel / SPY_MODELS registry keyed by HID++ model id, with schema-5 unit-key resolution through persisted identity; 0x8110 earns the Buttons tab; PROTOCOL_VERSION 30 → 31.
  • device / agent-core: Host-mode capture session zeros armed mapping slots, mask-diffs spy events, restores mapping then onboard mode on stop/Drop; remapped G4/G5 are spy-owned (no 0x1b04); native DPI fallback for unbound G6–G8.
  • desktop / ui: synthetic G6–G9 hotspots gated on spy_overlay_for; silhouette uses model_key not the unit settings key; Host-mode pause note; keys in all 23 locale catalogs.

Adding another 0x8110 model later

  1. openlogi diag mouse-buttons --watch — record bit → official button. Do not copy another row.
  2. Add the HID++ model id to openlogi_core::binding::SPY_MODELS.
  3. Add the same key's bit table in openlogi-device session/gesture/spy.rs (SPY_BIT_TABLES).
  4. Add a silhouette overlay in desktop hotspots::spy_overlay_for.

Testing

  • cargo fmt --all -- --check
  • RUSTFLAGS="-D warnings" cargo clippy --workspace --all-targets -- -D warnings
  • RUSTFLAGS="-D warnings" cargo test --workspace
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items --exclude openlogi-ui --exclude openlogi-desktop --exclude openlogi-overlay --exclude openlogi-agent
  • cargo test -p openlogi-ipc --test wire_format (goldens unchanged; pin bumped to 31)
  • cargo test -p openlogi-ui locale
  • cargo xtask ci not run (macOS host; Linux/Windows CI jobs not reproduced locally)

Runtime-tested on the author's G502 X Plus Lightspeed (wpid=4099, model 04099). Quit /Applications/OpenLogi.app and its Agent/Overlay so the cargo agent owns the receiver; grant Input Monitoring / Accessibility to OpenLogi Agent Dev.

  1. Wake the mouse; OPENLOGI_PROFILE=dev cargo run -p openlogi -- list shows ● G502 X PLUS.
  2. Buttons tab shows G6–G9 (this mouse has no 0x1b04). MX mice do not grow DPI Up/Down.
  3. Bind G8 (DPI Up) to Mission Control. Press G8: Mission Control opens and the DPI indicator does not change.
  4. Bind G4/G5 to Previous/Next Desktop. Those clicks change Space and do not navigate Back/Forward.
  5. Bind G9 to a known action. Press G9: the action fires; lighting does not do the profile-cycle blink.
  6. Bind G6 to something momentary. Press/release: action on press; cursor speed does not sniper-drop unless that was the bound action.
  7. Leave G7 unbound while G8 is bound. Press G7: DPI steps down via software 0x2201.
  8. Clear G6–G9 back to default. After the session rearms, extras are firmware-native again.
  9. If remaps “eat” DPI after a crash, power-cycle the mouse — that means Drop restore is wrong.

Not runtime-tested on Windows (the #730 reporter's host) or on G502 X LS.

Honest limitation

While any Host-mode remap is active, onboard profiles are paused. That is required for SetMouseButtonMapping to apply. Unbound G9 cannot cycle onboard profiles until those bindings are cleared.

Fixes #730 (partial)

CazzaCoder and others added 5 commits September 11, 2026 12:06
SetMouseButtonMapping is what suppresses G6–G9 HID reports, and Host mode is what makes that mapping apply. The CLI dump/watch stays read/spy-only so diagnostics cannot leave a mouse in Host mode.

Co-authored-by: Cursor <cursoragent@cursor.com>
One customized G6–G9 button pauses onboard profiles so firmware DPI/profile no longer steal the press. Unbound siblings stay on 0x2201 software DPI, and session teardown restores mapping then onboard mode.

Co-authored-by: Cursor <cursoragent@cursor.com>
The G502 has no 0x1b04 depot slots, so the Buttons tab needs synthetic targets. The pause note is the honest Host-mode cost until those extras return to default.

Co-authored-by: Cursor <cursoragent@cursor.com>
This mouse has no 0x1b04, so remapped side buttons must be suppressed
in the 0x8110 mapping or the OS keeps seeing hardware Back/Forward.

Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve silhouette overlays from the HID++ model id so schema-5 unit
keys do not hide G6–G9, and show the pause note for any Host-mode remap.

Co-authored-by: Cursor <cursoragent@cursor.com>
@CazzaCoder
CazzaCoder marked this pull request as ready for review September 11, 2026 04:13
@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The current PR appears safe to merge; no outstanding correctness or repository-rule violations were identified.

Summary

This PR adds model-gated HID++ 0x8110 button remapping for the G502 X Plus.

  • Adds Host/Onboard mode control and capture-session rollback for spy-owned buttons.
  • Routes G6–G9 and customized G4/G5 through spy events while preserving native DPI behavior for unbound G6–G8.
  • Adds model-specific bindings, UI hotspots, diagnostics, localization, and IPC protocol version 31.
  • The fixes made after the previous review address the reported spy startup, partial rollback, long-press, DPI restoration, and task-retention issues.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
    B[Configured G502 X Plus binding] --> P[Capture plan selects spy buttons]
    P --> H[Enter HID++ Host mode]
    H --> S[Suppress armed HID mapping slots]
    S --> E[Receive 0x8110 spy masks]
    E --> D{Button configured?}
    D -->|Yes| A[Dispatch configured action]
    D -->|No, G6-G8| N[Apply native DPI fallback]
    D -->|No, other| I[Ignore spy event]
    A --> R[Session stop or rearm]
    N --> R
    I --> R
    R --> M[Restore mapping slots]
    M --> O[Return to Onboard mode]
Loading

Reviews (5) · Last reviewed commit: "Merge branch 'master' into feat/g502x-pl..."

Comment thread crates/openlogi-device/src/session/gesture.rs
Comment thread crates/openlogi-core/src/binding/spy.rs
Comment thread crates/openlogi-device/src/session/gesture.rs Outdated
A failed spy start or partial Host-mode write left mappings suppressed
with no 0x8110 stream, and click-less long presses never armed. Restore
firmware on those paths, wait for G6 DPI restore on session cancel, and
gate extras on any configured action.

Co-authored-by: Cursor <cursoragent@cursor.com>
@CazzaCoder

Copy link
Copy Markdown
Author

The G6 cancel finding (summary issue 3, no review thread) is also in 1b4e16f5: session cancel waits for any in-flight shift write, then restores saved DPI instead of try_lock + dropping the slot.

Comment thread crates/openlogi-agent-core/src/runtime.rs Outdated
Detached restore was aborted when the gesture runtime dropped, and a
late write could overwrite a replacement session's DPI. Cancel now
joins in-flight shift ops and restores inline before successor arming.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread crates/openlogi-agent-core/src/watchers/gesture/dispatch.rs Outdated
A capture session can last the whole device lifetime, so retaining every
JoinHandle until cancel made spy_ops grow with normal unbound DPI use.

Co-authored-by: Cursor <cursoragent@cursor.com>
@davidbudnick davidbudnick added type: feature New feature request area: hidpp HID++ protocol and device feature support platform: all Cross-platform issue labels Sep 14, 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.

[Device]: G502 X PLUS (wireless+USB) cant rebind buttons

2 participants