Skip to content

Add K8850 per-key RGB LED support#175

Open
skarard wants to merge 2 commits intokriomant:masterfrom
skarard:feat/k8850-led-config
Open

Add K8850 per-key RGB LED support#175
skarard wants to merge 2 commits intokriomant:masterfrom
skarard:feat/k8850-led-config

Conversation

@skarard
Copy link
Copy Markdown

@skarard skarard commented Mar 10, 2026

Summary

  • Adds per-key RGB LED control for the K8850 (0x8850) 16-key + 3-knob keyboard
  • Supports 6 LED modes: off, static, reactive, ripple, rainbow-rows, rainbow-cols
  • Per-key color control via YAML config (leds section per layer) and CLI (led command)
  • Colors can be specified as named colors (red, green, blue, etc.) or hex #RRGGBB
  • LED types and parsing are self-contained in k8850.rs — shared files only pass through opaque serde_yaml::Value

Built on top of #174 (K8850 key binding support) — that PR should be merged first.

LED protocol

[0x03, 0xFE, 0xB0, layer, mode, R, G, B, 16× per-key RGB]
  • One 64-byte packet per layer (3 layers total)
  • Mode byte: 0=off, 1=static, 2=reactive, 3=ripple, 4=rainbow-rows, 5=rainbow-cols
  • Bytes 5-7: base color (R, G, B)
  • Bytes 8-55: 16 per-key colors (3 bytes each)

YAML config example

layers:
  - buttons: [...]
    knobs: [...]
    leds:
      mode: "static red"
      colors:
        - ["red", "#FF8000", "yellow", "green"]
        - ["cyan", "blue", "purple", "magenta"]
        - ["white", "#804000", "#008040", "#400080"]
        - ["#FF4040", "#40FF40", "#4040FF", "#C0C0C0"]

Known caveats

  • LED freeze/lock (firmware bug): The K8850 firmware has a bug where LEDs freeze after a variable amount of time (observed: 2s–2m18s across multiple tests). This is a pre-existing firmware bug unrelated to this tool — it occurs even after a fresh replug with no USB writes, purely from the firmware's own LED rendering. When frozen:
    • Animated modes (reactive, ripple, rainbow) stop animating
    • Changing layers does not update the LED state
    • Static-on and static-off modes are unaffected in practice, but per-layer LED colors will not update on layer switch while locked
    • A device replug is required to recover
    • This cannot be fixed in software without bootloader/firmware access
  • CLI led command overwrites all layers: Each led CLI call sends packets for all 3 layers, setting the target layer and zeroing the others. Use YAML config for multi-layer LED setups.
  • leds config is optional: Layers without a leds section are left unchanged. Configs without any leds sections skip LED protocol entirely.

Design

LED-specific types (LedMode, Color, parsers) are fully contained in k8850.rs. Shared files (config.rs, mod.rs, main.rs) only pass through an opaque serde_yaml::Value for the leds field, keeping the cross-cutting diff minimal and allowing other keyboard drivers to define their own LED formats in the future.

Hardware tested

All testing performed on XZKJ-16key_3knob (VID 0x514C / PID 0x8850) by @skarard:

  • CLI: static (named colors + hex #RRGGBB)
  • CLI: reactive, ripple, rainbow-rows, rainbow-cols, off
  • YAML: static per-key colors (named + hex)
  • YAML: reactive per-key colors
  • YAML: ripple per-key colors
  • YAML: multi-layer LEDs (layer 0=red, 1=green, 2=blue — confirmed via layer switch)
  • Keybindings + LEDs uploaded together in single config
  • LED freeze/lock confirmed (variable: 2s–2m18s, pre-existing firmware bug, replug recovers)

🤖 Generated with Claude Code — reviewed and hardware tested by @skarard

skarard and others added 2 commits March 10, 2026 15:58
The K8850 (VID 0x514C, PID 0x8850) uses a different key binding
protocol (0xFD command) than the K884x family (0xFE command).

Protocol details reverse-engineered via Frida HID captures of
mini_keyboard.exe and verified on hardware for all binding types:
keyboard, modifiers, macros, media, mouse, and knobs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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