AprilNEA / AprilNEA/OpenLogi

[Bug]: MX Master 2S thumb wheel rebinds never arm — no 0x2150 feature, and the 0x1b04 CID 0x00d7 fallback hijacks pointer movement

Open
#1,021 3 comments 4 reactions 0 assignees View on GitHub
area: hidpp platform: all type: bug
Dominant language
Rust
Stars
21k
Forks
675
Avg merge
2d 5h
Merged PRs (30d)
172

Description

### Pre-flight checklist

- [x] I searched [existing issues](https://github.com/AprilNEA/OpenLogi/issues?q=is%3Aissue) and this is not a duplicate.
- [x] I am on the latest release (v0.8.0) or a recent `master` build. The bug also reproduces on v0.7.10.
- [x] I quit Logi Options+ before running OpenLogi (uninstalled; OpenLogi is the only Logitech driver on this machine).

### Which part of OpenLogi?

Agent (HID++ capture session / gesture watcher)

### Device

MX Master 2S (046d:b019), tested over **both** Bluetooth BLE direct and Unifying receiver (`receiver:aa1d9dbd:slot:1`) — same behavior on both.

macOS 26.5.2 · OpenLogi v0.8.0 (auto-updated 2026-08-26 from v0.7.10, which reproduces identically)

### Summary

Thumb-wheel rotation rebinds (any action — VolumeUp/Down, horizontal scroll, etc.) never take effect on the MX Master 2S. Every other control works: side buttons, gesture button, DPI button (ToggleSmartShift). Every capture session logs:

```
control capture active index=N gesture_sources=1 dpi_buttons=1 buttons=0 thumbwheel=false
```

Reproduction matrix: v0.7.10 and v0.8.0 × BLE and Unifying × cold start / full restart / GUI preset hot-reload / minimal clean config — **all** end with `thumbwheel=false`. On 8/25 (still 0.7.10), all 18 capture-session records of the day are `thumbwheel=false` with zero config parse errors.

### What I ruled out

1. **Config loading is fine.** `config.toml` parses cleanly (verified with an external TOML parser), no `could not load config.toml` in agent logs, runtime device key matches the migrated schema-v6 key (`unit:9e43a1eb`). Strongest evidence: the DPI button executes my configured non-default action `ToggleSmartShift` (`SmartShift toggle → flipping wheel mode`) — so config → plan → dispatch works; only the thumb-wheel arm path doesn't fire.
2. **The plan layer is fine.** With a debug build instrumented at `thumbwheel_armed`, every session logs:
```
thumbwheel arm decision key=unit:9e43a1eb sensitivity=70 bindings_nondefault=true default_sensitivity=14 armed=true
```
So `spec.capture_thumbwheel = true` reaches the session layer correctly.
3. **HID++ read/write is healthy.** `diag dpi / smartshift / controls / features` all round-trip OK on both transports.

### Root cause (probe-level)

`arm_controls_into` arms the thumb wheel only when `root.get_feature(thumbwheel::FEATURE_ID /* 0x2150 */)` returns `Some`:

```
DEBUG openlogi_device::session::gesture: thumb wheel feature absent — skipping diversion feature=0x2150
```

A direct probe of the device shows:

- `get_feature(0x2150)` behaves inconsistently — sometimes returns `Some(index=0)` (false positive), sometimes `Ok(None)`; a full `diag features` enumeration does **not** list 0x2150. Conclusion: **the MX Master 2S firmware has no HID++ 0x2150 Thumbwheel feature** (that's Master 3/4 generation); its thumb wheel is exposed as a virtual control on 0x1b04 instead.
- `getCtrlIdInfo` for CID 0x00d7 returns:
```
cid=0x00d7 flags=DIVERTABLE | VIRTUAL_CONTROL | RAW_XY | FORCE_RAW_XY (raw_wheel=false)
```

### Fallback experiment (failed — do not repeat)

I tried arming CID 0x00d7 like a gesture source (`setCidReporting{diverted=true, raw_xy=true, force_raw_xy=true}`):

- The diversion write succeeds and `rawXYEvent`s (dx≠0) arrive while rolling.
- **But it hijacks the whole pointer pipeline**: all pointer deltas get consumed as the control's raw-XY reports — the cursor freezes and mouse movement becomes volume presses.

Conclusion: on 2S firmware, diverting the virtual thumb-wheel control does not yield a rotation-only channel; it diverts pointer motion itself. I restored the control's reporting afterwards; no lingering effects.

### Expected

Either (a) thumb-wheel rebinds work on the 2S via some other mechanism I couldn't find, or (b) if there is genuinely no usable channel, the GUI should hide/disable thumb-wheel presets for devices without the capability instead of offering bindings that can never fire.

Happy to run probes against my device if that helps — I have a debug build set up already.

### Attachments

- Agent state logs covering both versions: `~/.local/state/openlogi/agent.2026-08-25.log` (v0.7.10), `agent.2026-08-26.log` (v0.8.0)
- Possibly related: #887 (sensitivity ignored), #365 (single step only) — same area, more severe manifestation

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in openlogi_device::session::gesture at arm_controls_into and inspect the 0x2150 feature check alongside the 0x00d7 CID behavior. Reproduce the feature enumeration and getCtrlIdInfo probes on the MX Master 2S without diverting pointer movement; done means finding a safe thumb-wheel channel or ensuring unsupported devices do not offer thumb-wheel presets.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.