Skip to content

feat(backlight): support HID++ 0x1982 - #470

Open
kirgene wants to merge 2 commits into
AprilNEA:masterfrom
kirgene:feat/backlight-0x1982
Open

feat(backlight): support HID++ 0x1982#470
kirgene wants to merge 2 commits into
AprilNEA:masterfrom
kirgene:feat/backlight-0x1982

Conversation

@kirgene

@kirgene kirgene commented Jul 27, 2026

Copy link
Copy Markdown

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:

$ openlogi backlight
device: MX KEYS S (slot 1 on receiver ...)
  current: enabled=true mode=automatic (ambient-light sensor) status=on (following ambient light) level=2/8

$ openlogi backlight off
device: MX KEYS S (slot 1 on receiver ...)
  current: enabled=true mode=automatic (ambient-light sensor) status=on (following ambient light) level=2/8
  read-back: enabled=false mode=automatic (ambient-light sensor) status=off (disabled by software) level=0/8

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.

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
kirgene force-pushed the feat/backlight-0x1982 branch from 90a751a to 4515d8b Compare July 27, 2026 07:44
@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown

Greptile Summary

Adds persistent HID++ 0x1982 keyboard-backlight control.

  • Introduces shared backlight mode, status, and state types.
  • Adds route-based backlight reads and enable/disable writes with read-back.
  • Adds the top-level openlogi backlight [status|off|on] command and parser tests.

Confidence Score: 3/5

The 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

Important Files Changed

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
Loading

Reviews (3): Last reviewed commit: "fix(backlight): document and surface the..." | Re-trigger Greptile

Comment thread crates/openlogi-hid/src/write/backlight.rs
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant