fix(smartshift): stop runaway free-spin scroll and SmartShift control snap-back#333
Open
AprilNEA wants to merge 2 commits into
Open
fix(smartshift): stop runaway free-spin scroll and SmartShift control snap-back#333AprilNEA wants to merge 2 commits into
AprilNEA wants to merge 2 commits into
Conversation
…317) Three independent defects made the wheel scroll "insanely fast" and the SmartShift GUI controls snap back to defaults on MX Master 3s / 3 and MX Anywhere 3s. - set_status rejected a 0-valued auto_disengage / tunable_torque instead of treating 0 as the firmware's documented "do not change" sentinel (x2110 / x2111). On a device that reports tunable_torque == 0 (no tunable-torque hardware) every SmartShift write failed silently, so the panel optimistically showed the change then snapped back. 0 is now sent as preserve; the redundant set_mode_preserving_status / nonzero_smartshift_value helpers are gone and the toggle shares set_status. - The panel clamped a 0 readback to auto_disengage = 1 (~0.25 turn/s), which releases the ratchet into free-spin on the gentlest scroll. The friendly slider floor is raised to a usable 8 (~2 turn/s) and sub-floor / sentinel values normalise to the 16 default; the floor and default are single-sourced in openlogi-core, and a deserialize heal repairs already-persisted low thresholds on load so reapply pushes the good value on reconnect. - Native scroll inversion (0x2121) was re-written on every config reload, needless traffic that could race other writes. The write now short-circuits when the wheel already holds the desired (native, invert) state. Adds unit tests for the threshold clamp and the config heal.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three independent defects made the wheel scroll "insanely fast / unusable" and the SmartShift GUI controls (Permanent Ratchet, sensitivity slider) snap back to defaults on MX Master 3 / 3s and MX Anywhere 3s.
Root causes & fixes
1. SmartShift writes rejected the
0"do not change" sentinel → silent failure / snap-backset_statusvalidatedauto_disengage/tunable_torqueas non-zero and bailed out before the HID++ call. Per the x2110 / x2111setRatchetControlModespec,0means "do not change" (real values are0x01..=0xFF). On a device that reportstunable_torque == 0(no tunable-torque hardware, e.g. MX Anywhere 3s) every SmartShift write failed silently — the panel showed the change optimistically, then the confirm read snapped it back. Now0is sent as preserve; the redundantset_mode_preserving_status/nonzero_smartshift_valuehelpers are removed and the toggle sharesset_status.2. A
0readback clamped toauto_disengage = 1(≈0.25 turn/s) → constant free-spinThat threshold releases the ratchet into free-spin on the gentlest scroll, which reads as "insanely fast." The sensitivity slider floor is raised from
1to a usable8(≈2 turn/s); sub-floor / sentinel values normalise to the16default. The floor and default are single-sourced inopenlogi-core, and a deserialize-time heal repairs already-persisted low thresholds on load — so aconfig.tomlthat already holds a runaway value is fixed automatically on the next agent start (the values live in volatile RAM and the agent re-applies config on reconnect, #189).3. Native scroll inversion (
0x2121) rewritten on every config reloadreload_configfires on every DPI / SmartShift / binding edit, and each one re-wrote the wheel mode — needless HID++ traffic that could race other writes. The write now short-circuits when the wheel already holds the desired (native, invert) state.Notes
0xFF(permanent ratchet) and real thresholds ≥ 8 are untouched.0x2121write is now idempotent, the re-apply stays unconditional and just skips at the HID++ layer.Testing
low_auto_disengage_heals_to_default_on_load) and the panel threshold clamp.cargo testandcargo clippy --all-targets -- -D warningspass across the changed crates.auto_disengage = 1config heals to 16 on restart.Fixes #317