feat(backlight): support HID++ 0x1982 - #470
Open
kirgene wants to merge 2 commits into
Open
Conversation
The MX Keys family's white backlight sits behind 0x1982, which is separate from the RGB features (0x8070/0x8080) that set_keyboard_color drives, so Capabilities::lighting doesn't cover it and diag lighting can't reach it. Adds get_backlight/set_backlight_enabled in openlogi-hid on top of the existing 0x1982 wrapper, plus an `openlogi backlight [status|off|on]` command. The write is a read-modify-write so mode, effect, level and the fade durations survive a toggle. TemporaryManual maps to Automatic since setBacklightConfig can't write it. Kept the command top-level instead of under diag because setBacklightConfig writes to NVM, and diag is documented as not touching persistent state. The new HidppOperation variants are appended so the bincode indices and wire goldens don't shift. Tested on an MX Keys S over a Bolt receiver.
kirgene
force-pushed
the
feat/backlight-0x1982
branch
from
July 27, 2026 07:44
90a751a to
4515d8b
Compare
Greptile SummaryAdds persistent HID++ 0x1982 keyboard-backlight control.
Confidence Score: 3/5The PR is not yet safe to merge because toggling a backlight in TemporaryManual mode still replaces the user's selected mode with Automatic. The current write path always maps TemporaryManual to Automatic and sends the write; the newly added CLI note explains the mutation but does not prevent the previously reported behavior. Files Needing Attention: crates/openlogi-hid/src/write/backlight.rs; crates/openlogi-cli/src/cmd/backlight.rs
|
| Filename | Overview |
|---|---|
| crates/openlogi-hid/src/write/backlight.rs | Implements HID++ 0x1982 state mapping, route-based reads, persistent enable writes, and post-write read-back. |
| crates/openlogi-hid/src/backlight.rs | Defines serializable IPC-facing backlight mode, status, and snapshot types. |
| crates/openlogi-cli/src/cmd/backlight.rs | Adds device selection, state display, and persistent on/off command handling. |
| crates/openlogi-hid/src/write/error.rs | Appends operation identifiers for backlight reads and writes. |
| crates/openlogi-cli/src/lib.rs | Adds parsing coverage for default status, off, device filtering, and invalid actions. |
Sequence Diagram
sequenceDiagram
participant User
participant CLI as openlogi backlight
participant HID as openlogi-hid
participant Device as HID++ 0x1982 device
User->>CLI: status / off / on
CLI->>HID: get_backlight(route)
HID->>Device: getBacklightConfig + getBacklightInfo
Device-->>HID: configuration and current state
HID-->>CLI: BacklightState
opt off or on
CLI->>HID: set_backlight_enabled(route, enabled)
HID->>Device: getBacklightConfig
Device-->>HID: existing configuration
HID->>Device: setBacklightConfig
HID->>Device: getBacklightConfig + getBacklightInfo
Device-->>HID: read-back state
HID-->>CLI: BacklightState
end
Reviews (3): Last reviewed commit: "fix(backlight): document and surface the..." | Re-trigger Greptile
setBacklightConfig cannot write TemporaryManual, so a toggle from that mode necessarily lands somewhere else and the doc comment's claim that every other field survives was wrong. Say what actually happens instead of widening the claim. Automatic stays the target rather than PermanentManual: holding the level would turn an adjustment the user made from the backlight keys, which the firmware itself calls temporary, into a persistent NVM setting. The CLI now prints a note when the pre-write mode is TemporaryManual so the mode change does not read as a side effect of the enable bit.
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.
The MX Keys backlight is HID++ 0x1982. The wrapper for it already exists in openlogi-hidpp but nothing calls it, BacklightFeature only shows up in the feature registry. Capabilities::lighting tracks 0x8070/0x8080 and stays false for these keyboards, and diag lighting drives only those two, so there's no path to the backlight on an MX Keys S.
This wires it up: openlogi-hid::backlight for the IPC-facing types (same shape as smartshift), openlogi-hid::write::backlight with route-based get_backlight and set_backlight_enabled, and an
openlogi backlight [status|off|on]command.set_backlight_enabled reads getBacklightConfig first and writes everything except the enable bit back unchanged, so mode, effect, level and the three fade-out durations survive a toggle. The effect goes out as the 0xff "do not change" sentinel. TemporaryManual maps to Automatic on the way back down since setBacklightConfig can't write it.
I put the command at top level rather than under diag because setBacklightConfig writes to NVM, and diag.rs describes itself as diagnosis that doesn't touch persistent state. Can move it if you'd rather.
The two new HidppOperation variants are appended, so bincode variant indices don't shift and the wire_format goldens still pass.
Tested on an MX Keys S behind a Bolt receiver:
Unit tests cover the enum mapping and the CLI parsing.
No GUI changes. The panel would need a different shape than the RGB colour picker, so that seemed like a separate PR.