UMBRA-1: Add DeviceSpecs for the full Razer Naga line (Trinity + 17 sibling PIDs) #7

Merged
David merged 1 commit from feat/naga-line-devicespecs-UMBRA-1 into main 2026-06-02 11:07:49 +02:00
Owner

UMBRA-1: Add DeviceSpecs for the full Razer Naga line (Trinity + 17 sibling PIDs)

Registers a DeviceSpec for every Razer Naga PID defined in OpenRazer's razermouse_driver.h (18 PIDs, VID 0x1532), one model file each under crates/umbra-hid/src/models/, wired into SUPPORTED in mod.rs. Every transaction id, lighting zone, effect kind, DPI txn, and battery/idle flag was read branch-by-branch from razermouse_driver.c (firmware/serial/dpi/poll/brightness/effect/charge/idle switches and the razer_mouse_probe attribute table).

Naga Trinity (0x0067), the worked example

Implements the three distinct transaction ids verified from the driver: 0xFF (firmware/serial/DPI/poll), 0x3F (matrix brightness), 0x1f (static effect). The static-effect mode-switch quirk is honored in Device::set_effect: it sends the mode-switch report (0x0f/0x02, arg[2]=0x08) and then the bespoke Trinity static report (0x0f/0x03), both on 0x1f, via the new commands::naga_trinity_mode_switch / naga_trinity_effect_static builders. Device::brightness_txn keeps brightness on 0x3F while the effect path stays on 0x1f. New led::ZERO (ZERO_LED) models the single unified matrix zone.

Wired/wireless splits

Naga Pro (0x008F/0x0090) and Naga V2 Pro (0x00A7/0x00A8) are split into separate wired and wireless specs per the existing *_pro_wired / *_pro_wireless convention; both variants carry BatterySpec + IdleSpec because the driver registers charge/idle for the wired PIDs too (same as the existing DeathAdder V2 Pro pair).

Edge-PID decisions (AC)

  • Naga Epic Chroma Dock (0x003F): INCLUDED. The driver registers it under the same razer_mouse_probe case as the Naga Epic Chroma (full DPI/poll/lighting/battery/idle attribute set), so it enumerates as a configurable endpoint umbra can talk to.
  • Naga V2 HyperSpeed receiver (0x00B4): INCLUDED. The driver registers a control attribute set (DPI, DPI stages, poll, charge, idle) on the receiver PID, so umbra can drive it; it exposes no onboard lighting, so lighting is omitted.

Faithful-modeling limits (documented per file)

Some legacy PIDs declare None for DPI and/or lighting rather than emit wrong wire bytes, because umbra does not yet ship the matching command builders:

  • Pre-Chroma Naga / Naga 2012 / Naga 2014 / Naga Hex / Naga Hex Red: legacy 1-byte DPI (set_dpi_xy_byte) and on/off set_led_state LEDs.
  • Naga Chroma, Naga Hex V2: mouse_extended_matrix lighting path (command class 0x03).
  • Naga Epic-family: classic set_led_state lighting path.

These PIDs are still recognized by umbra info (identity + polling, plus battery/idle for the Epic-family). The missing builders are noted in-code as follow-up work and should be filed as separate issues (tooling gap) before the affected lighting/DPI can be enabled.

DPI ceilings

The OpenRazer driver does not clamp DPI, so per-device DPI maxima are sensor-derived and documented as assumptions in each model file (e.g. Trinity 16000, Naga X 18000, Naga Pro 20000, Naga V2 Pro 30000). Reviewers can adjust against hardware.

Tests / checks

cargo build (full workspace), cargo clippy -p umbra-hid --all-targets -- -D warnings, and cargo fmt --check all pass clean. Added tests/protocol.rs coverage: Trinity split txns + bespoke static bytes + mode-switch, Naga X serial on 0x08, the Pro/V2 Pro battery split, and a guard asserting all 18 Naga PIDs resolve via models::lookup.

🤖 Generated with Claude Code

## UMBRA-1: Add DeviceSpecs for the full Razer Naga line (Trinity + 17 sibling PIDs) Registers a `DeviceSpec` for every Razer Naga PID defined in OpenRazer's `razermouse_driver.h` (18 PIDs, VID `0x1532`), one model file each under `crates/umbra-hid/src/models/`, wired into `SUPPORTED` in `mod.rs`. Every transaction id, lighting zone, effect kind, DPI txn, and battery/idle flag was read branch-by-branch from `razermouse_driver.c` (firmware/serial/dpi/poll/brightness/effect/charge/idle switches and the `razer_mouse_probe` attribute table). ### Naga Trinity (0x0067), the worked example Implements the three distinct transaction ids verified from the driver: `0xFF` (firmware/serial/DPI/poll), `0x3F` (matrix brightness), `0x1f` (static effect). The static-effect mode-switch quirk is honored in `Device::set_effect`: it sends the mode-switch report (`0x0f`/`0x02`, `arg[2]=0x08`) and then the bespoke Trinity static report (`0x0f`/`0x03`), both on `0x1f`, via the new `commands::naga_trinity_mode_switch` / `naga_trinity_effect_static` builders. `Device::brightness_txn` keeps brightness on `0x3F` while the effect path stays on `0x1f`. New `led::ZERO` (ZERO_LED) models the single unified matrix zone. ### Wired/wireless splits Naga Pro (`0x008F`/`0x0090`) and Naga V2 Pro (`0x00A7`/`0x00A8`) are split into separate wired and wireless specs per the existing `*_pro_wired` / `*_pro_wireless` convention; both variants carry `BatterySpec` + `IdleSpec` because the driver registers charge/idle for the wired PIDs too (same as the existing DeathAdder V2 Pro pair). ### Edge-PID decisions (AC) - Naga Epic Chroma Dock (`0x003F`): INCLUDED. The driver registers it under the same `razer_mouse_probe` case as the Naga Epic Chroma (full DPI/poll/lighting/battery/idle attribute set), so it enumerates as a configurable endpoint umbra can talk to. - Naga V2 HyperSpeed receiver (`0x00B4`): INCLUDED. The driver registers a control attribute set (DPI, DPI stages, poll, charge, idle) on the receiver PID, so umbra can drive it; it exposes no onboard lighting, so lighting is omitted. ### Faithful-modeling limits (documented per file) Some legacy PIDs declare `None` for DPI and/or lighting rather than emit wrong wire bytes, because umbra does not yet ship the matching command builders: - Pre-Chroma Naga / Naga 2012 / Naga 2014 / Naga Hex / Naga Hex Red: legacy 1-byte DPI (`set_dpi_xy_byte`) and on/off `set_led_state` LEDs. - Naga Chroma, Naga Hex V2: `mouse_extended_matrix` lighting path (command class `0x03`). - Naga Epic-family: classic `set_led_state` lighting path. These PIDs are still recognized by `umbra info` (identity + polling, plus battery/idle for the Epic-family). The missing builders are noted in-code as follow-up work and should be filed as separate issues (tooling gap) before the affected lighting/DPI can be enabled. ### DPI ceilings The OpenRazer driver does not clamp DPI, so per-device DPI maxima are sensor-derived and documented as assumptions in each model file (e.g. Trinity 16000, Naga X 18000, Naga Pro 20000, Naga V2 Pro 30000). Reviewers can adjust against hardware. ### Tests / checks `cargo build` (full workspace), `cargo clippy -p umbra-hid --all-targets -- -D warnings`, and `cargo fmt --check` all pass clean. Added `tests/protocol.rs` coverage: Trinity split txns + bespoke static bytes + mode-switch, Naga X serial on `0x08`, the Pro/V2 Pro battery split, and a guard asserting all 18 Naga PIDs resolve via `models::lookup`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(umbra-hid): add DeviceSpecs for the full Razer Naga line
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Failing after 15s
51c0c27916
Register a DeviceSpec for every Razer Naga PID defined in OpenRazer's razermouse_driver.h (18 PIDs, VID 0x1532), one model file each, so umbra info recognizes the devices and exposes the DPI / poll-rate / lighting / battery features the OpenRazer driver actually wires up. Every transaction id, lighting zone, effect kind, and battery/idle flag is read branch-by-branch from razermouse_driver.c.

Naga Trinity (0x0067) is implemented as the worked example with its three distinct transaction ids: 0xFF for firmware/serial/DPI/poll, 0x3F for matrix brightness, and 0x1f for the static effect. The driver's static-effect quirk is honored in Device::set_effect: a mode-switch report precedes a bespoke static report (commands::naga_trinity_mode_switch / naga_trinity_effect_static), and Device::brightness_txn drives brightness on 0x3F while the effect path stays on 0x1f.

Naga Pro (0x008F/0x0090) and Naga V2 Pro (0x00A7/0x00A8) are split into separate wired and wireless specs following the existing *_pro_wired / *_pro_wireless convention; both carry BatterySpec and IdleSpec since the driver registers charge/idle for the wired PIDs too.

Decisions recorded for the two edge PIDs (AC): the Naga Epic Chroma Dock (0x003F) and the Naga V2 HyperSpeed receiver (0x00B4) are both INCLUDED because razer_mouse_probe registers a control attribute set for each, so they enumerate as configurable endpoints umbra can talk to.

Faithful-modeling limits, documented per file: the five pre-Chroma devices (Naga, Naga 2012, Naga 2014, Naga Hex, Naga Hex Red) use legacy 1-byte DPI and on/off LED commands; Naga Chroma and Naga Hex V2 use the mouse-extended matrix path (class 0x03); the Epic-family uses the classic LED path. umbra ships none of those command builders, so the affected DPI/lighting fields are left None rather than emit wrong wire bytes; those PIDs are still recognized. DPI ceilings for the line are sensor-derived (the driver does not clamp DPI) and noted as assumptions in each file.

Adds led::ZERO (ZERO_LED) for unified single-matrix addressing, the two Naga Trinity command builders, README table rows for every new model, and protocol tests covering Trinity (split txns + bespoke static bytes), Naga X (serial on 0x08), the Pro/V2 Pro battery split, and registration of all 18 PIDs.

#UMBRA-1

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
David merged commit 1632c97201 into main 2026-06-02 11:07:49 +02:00
David deleted branch feat/naga-line-devicespecs-UMBRA-1 2026-06-02 11:07:49 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/umbra!7
No description provided.