Repository navigation
Conversation
Add memoryAddrWrite/memoryWrite/memoryWriteEnd and a CRC-checked ProfileSector that reads and edits the startup DPI of a stored profile. Every edit reseals the CRC-16/CCITT-FALSE, so a correct write reads back equal. The regression fixture is a PRO X SUPERLIGHT profile whose rewrite was verified on the device.
`openlogi diag onboard --set-default-dpi <DPI> [--profile N]` writes the DPI a gaming mouse runs at in onboard mode. Such a mouse wakes from sleep in onboard mode, so until the agent re-enters host mode it moves at its stored startup DPI. Storing the configured DPI there removes that burst. The write is checked against the sensor's DPI list, read back, and the active profile is re-selected so the mouse loads it.
[Medium impact] The PR appears safe to merge; no blocking findings remain.
|
Review follow-ups for the 0x8100 write: - The write takes the 0x0003 unit ID enumeration read for the chosen device and refuses any other device on the route before it touches 0x8100, so a receiver slot re-paired after selection keeps its flash. A device enumeration read no unit ID for cannot be written. - `diag onboard --set-default-dpi` holds the agent's instance lock from before selection until the write is read back, and refuses while an agent answers. The lock-then-probe sequence moves out of `diag hidpp` into `diag::exclude_agent`, guarded by an ast-grep rule. - A scripted PRO X SUPERLIGHT serves the measured profile and checks the exact start/chunks/end sequence, the padded last chunk of a 255-byte sector, the stored CRC, and that a replaced unit, an unsupported DPI and an unchanged one send no flash write. Swapping functions 6 and 7 fails it. The measured sector is one fixture file both crates read.
Only the test function was unix-gated, so on Windows its imports were unused, which -D warnings turns into an error.
Each request is already bounded by the channel's response timeout; the shared helper bounds the whole write too, so a stalled one fails with a clear message.
This branch has not been deployed
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
A G-series mouse wakes from sleep in onboard mode. Until the agent puts it back in host mode and writes the saved DPI, which takes a few seconds after the reconnect, it moves at the startup DPI stored in its onboard profile. If that DPI differs from the configured one, the cursor jumps after every wake-up.
On my PRO X SUPERLIGHT, G HUB had left profile 1 starting at 4950 DPI against a configured 1200. The agent log shows the gap:
The agent can only shorten that gap; the mouse always wakes on its stored profile. This PR adds the ability to change the stored startup DPI, and exposes it through
openlogi diag onboard --set-default-dpi. Before this,0x8100support was read-only.Changes
feature/onboard_profiles.rs)memoryAddrWrite(fn 6),memoryWrite(fn 7) andmemoryWriteEnd(fn 8).write_profilewrites one whole sector through the write-through calls, so an abandoned future can't stop a write halfway.ProfileSector. It is built only byread_profile, which reads the whole sector and checks its CRC-16/CCITT-FALSE, and it rejects an unknown profile format or an out-of-range default slot.set_default_dpipoints the default at a slot that already holds the value. Otherwise it replaces the value in the default slot, so the rest of the profile is kept.crccrate (CRC_16_IBM_3740) instead of a hand-rolled CRC.11, 12, 253, 254) and produce the CRC it stored (0x4682).HidppOperation::WriteOnboard, with its wire golden (21).set_onboard_default_dpi(route, OnboardDefaultDpi { unit, profile, dpi }).It first reads the
0x0003unit ID and refuses another device on the route, or one with no unit ID (DeviceNotFound), before any0x8100request. A receiver slot re-paired after selection keeps its flash.It checks
dpiagainst the sensor's0x2201list (DpiUnsupported).It writes nothing when the profile already starts there.
After a write it reads the sector back (
DpiNotAppliedon a mismatch) and re-selects the profile if it is active, so the mouse loads it.Tests use a scripted PRO X SUPERLIGHT serving the measured sector. They cover:
0x4682the device stored;Swapping functions 6 and 7 fails them. The measured sector is a single fixture file (
onboard_profiles/superlight_profile_1.bin) that both crates read.openlogi diag onboardgains--set-default-dpi <DPI>and--profile <N>. The profile defaults to the active one.diag hidppintodiag::exclude_agent, guarded by the ast-grep rulecli-diag-agent-exclusion-owner.USAGE.mddescribes the option, its refusals, and that the stored value survives power cycles and is not updated by later DPI changes.Wiring this into the agent, for example storing the configured DPI when it changes, is a separate decision because each write wears flash. I left it out of this PR.
Testing
Full local gate, because
Cargo.tomlandCargo.lockchanged. Branch sits onmasterat9ca7ef0.Rerun on the review fixes (
1bf5df30):For the first revision, a first
cargo test --workspacerun failed one test this branch does not touch:write::litra::hidpp_tests::a_read_after_a_notification_replaces_an_older_write_reading. It passed on rerun.After the second review (
48468483), the CLI's onboard test module is Unix-only. I reranfmt,ast-grep, Clippy and tests foropenlogi-cli/openlogi(198 passed), and cross-ran Clippy with-D warnings --all-targetson hidpp, core, device, hid and ipc forx86_64-pc-windows-gnuandaarch64-unknown-linux-musl. Both passed.openlogi-cliitself could not be cross-compiled for Windows here, becauseringneeds a MinGW C toolchain, so its Windows build was checked by reading the code only. Theclippy (windows)proxy was not run for the same reason.699c3b5e(test deadlines only) reran the onboard device tests (5 passed),fmt,ast-grep, andopenlogi-deviceClippy (-D warnings --all-targets) on the host,x86_64-pc-windows-gnuandaarch64-unknown-linux-musl. All passed.Not run: typos, MSRV, cargo-deny, and the Linux/Windows jobs.
Hardware verification. Tested on macOS 26.6.2 with an original PRO X SUPERLIGHT over its Lightspeed receiver. The agent was stopped during the write.
getInfo: profile format 4, sector size 255, 5 profiles.0x0001) held slots400/800/1600/3200/4950with default slot 4, and its CRCe576was valid.openlogi diag onboard --device "pro x" --set-default-dpi 1200:56 13→b0 04) and the CRC (e576→4682, valid) had changed.1200 → 1200and writes nothing.0x2201reports a live onboard DPI of 1200.OPENLOGI_PROFILE=dev):1200 → 1200without writing.InvalidArgumentand the sector was unchanged on re-read, so a bad call order does not damage flash.Refs #886