Files
voidkontrol/KREO-SWARM75-LINUX-CONTROL-SPEC.md

194 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Kreo Swarm 75 Linux control specification
**Status:** implementation-ready transport and capability specification; command
payloads still need an authenticated-device capture before any setting is
written. This document intentionally distinguishes observations from the
vendor's browser driver.
## 1. Identified hardware
The attached keyboard presents as:
| Field | Value |
| --- | --- |
| USB identity | `258a:010c` — BY Tech, product `Kreo Swarm` |
| USB revision | `bcdDevice=0x0300`; USB 2.0 full speed (12 Mb/s) |
| Current topology | bus 003, through USB hub port `3-2.3`; do not hard-code this path |
| USB configuration | two HID interfaces, remote wakeup advertised, 500 mA maximum declared |
| Kernel driver | `hid-generic` / `usbhid`; normal typing already works |
| Vendor controller match | Kreo Kontrol's current device table maps this exact VID/PID plus usage `0xff00:0x01` to the **`swarm75` / `bytech`** profile |
The receiver does not expose a serial number or a layout identifier. The
vendor match is strong evidence that this is a Swarm 75, but the application
must call it `Kreo Swarm 75 (signature match)` until it has completed the
device's authenticated handshake. It must not infer a specific colourway,
switch, or physical layout solely from `258a:010c`.
## 2. HID transport — observed on this laptop
The device has two USB HID interfaces and no interrupt OUT endpoint. Normal
key events arrive through interrupt IN; configuration is therefore expected
to use class `SET_REPORT` / `GET_REPORT` control transfers, exposed safely to
an application through **hidraw**.
| Interface | HID collection / report | Direction and size | Meaning |
| --- | --- | --- | --- |
| 0 | Boot keyboard (no report ID) | IN 8 bytes; OUT 1 byte | 6-key boot keyboard plus Num/Caps/Scroll/Compose/Kana host LED bits |
| 1 | ID 1 | IN, 3 bits | Generic Desktop system control: power, sleep, wake |
| 1 | ID 2 | IN, 16 bits | Consumer/media control usage |
| 1 | ID 3 | IN, 3 bytes | Vendor page `0xff00`, usage 1; meaning unknown |
| 1 | ID 4 | IN, 15-byte payload | 120-bit keyboard bitmap (a non-boot simultaneous-key path) |
| 1 | ID 5 | Feature, 5-byte payload | Vendor configuration channel; not yet associated with a command |
| 1 | ID 6 | IN 7-byte payload; Feature, 519-byte payload | Primary vendor configuration/readback channel |
| 1 | ID 7 | IN, 7-byte payload | Five-button mouse, X/Y, wheel, and AC Pan |
The descriptor is internally consistent with Linux's input devices:
`BY Tech Kreo Swarm Keyboard`, `System Control`, `Consumer Control`, and
`Mouse`. The standard keyboard LED output is live — the current NumLock LED
is `1` — but it is not RGB control.
### Linux access requirement
**Corrected by a read-only recheck on 2026-09-21:** the running kernel
`7.2.6_1` has `CONFIG_HIDRAW=y`, and both Swarm HID interfaces now have hidraw
nodes. The earlier `modprobe hidraw` failure did not establish missing
support: Linux defines `CONFIG_HIDRAW` as a boolean, not a separately loadable
module option (`CONFIG_HIDRAW=m` is not valid).
A native controller requires `CONFIG_HIDRAW=y` and a narrow udev policy
granting its device service access to the matching node. At the recheck,
interface 1 was `/dev/hidraw5`, owned by `root:root` with mode `0600`; the
desktop user could neither read nor write it. Node numbers are dynamic and
must not be hard-coded. Select interface 1 / usage `0xff00:0x01` and validate
the complete descriptor before enabling control. See the dated
[device evidence](docs/evidence/2026-09-21-swarm75.md) and
[Linux HID Kconfig](https://github.com/torvalds/linux/blob/master/drivers/hid/Kconfig).
Do **not** use libusb by detaching or unbinding `hid-generic`: that can take
the keyboard away from the desktop. A read-only libusb `GET_REPORT` attempt
while the kernel owns the interface returned `LIBUSB_ERROR_IO`; that is an
access-path limitation, not evidence that the feature reports are absent.
## 3. Supported customization
The following comes from the current, publicly delivered Kreo Kontrol
`bytech` driver instantiated for `swarm75` without a physical connection. It
is a precise UI/capability target, but each read/write must still be verified
against this keyboard after authentication.
| Area | Supported capability | Constraints to preserve in the Linux UI |
| --- | --- | --- |
| RGB | Per-key RGB; one custom-light frame; colour, mode, speed, brightness, LED enable | Brightness and speed are five levels (0–4 / 0–100%). No direction control. |
| Effects | Off, Fixed on, Respire, Rainbow, Flash away, Raindrops, Rainbow wheel, Ripples shining, Stars twinkle, Shadow disappear, Retro snake, Neon stream, Reaction, Sine wave, Retinue scanning, Rotating windmill, Colorful waterfall, Blossoming, Rotating storm, and a self-defined mode | The driver disagrees whether the self-defined raw ID is `19` or `277`; treat the mode value as protocol-owned, not a UI constant. |
| Colour mode | Monochrome and colourful | The two exported driver schemas use different raw values for `Colourful`; translate through the protocol adapter. |
| Key mapping | Keyboard, modifier, combination/shortcut, media, mouse, disabled, and macro bindings | Four layers: Base, Fn, Fn1, Fn2. The driver exposes 163 assignable key-function choices; map only controls present in the physical layout map. |
| Macros | 32 slots; up to 112 actions per slot; names up to 127 bytes; press/release actions and 0–65,535 ms delays | Execution types: fixed count, until released, until any key pressed, and toggle. Macro parsing and writes must be bounds-checked. |
| Typing controls | Debounce: 0/10/20/30/40 ms; tap-delay setting | No user-selectable NKRO, report-rate, OS-mode, or Win-lock setting in this model profile. Do not expose them. |
| Power | Battery level/charging status and idle sleep | Present the vendor's discrete choices: off, 30 s, 60 s, 120 s, 180 s, 300 s, 600 s, 900 s, 1,200 s, 1,800 s. |
| Maintenance | Per-layer reset and factory reset | Factory reset is explicitly atomic and destructive: always require a confirmation and create an export first. |
The vendor profile also declares support for authentication, layer reset,
multimedia shortcuts, and battery reporting; it declares **no** static
profiles, side LED writes, lighting direction, or advanced Hall-effect
features (rapid trigger, DKS, SOCD, etc.).
## 4. Protocol boundary and known command facts
Only the following facts are safe to rely on before a transaction capture:
1. Use the vendor-defined HID collection (`usagePage=0xff00`, `usage=0x01`)
and feature report ID 6. Its feature payload is exactly 519 bytes; reject
any shorter or longer message.
2. The official driver begins an authenticated session by sending feature
report 6 with a 519-byte frame whose prefix is
`82 01 00 01 00 06 00`, then reading feature report 6. This was captured
from the official driver against an in-memory transport, never sent to the
attached keyboard.
3. Kreo's client contains a named wired command vocabulary:
`SET_KEY=0x03`, `SET_PROFILE=0x04`, `SET_MACRO=0x05`,
`SET_CUSTOM_LIGHT=0x06`, `SET_LIGHT_COLOR=0x0a`, `RESET=0x11`,
`GET_ATTRIBUTES=0x82`, `GET_KEYS=0x83`, `GET_PROFILE=0x84`,
`GET_MACRO=0x85`, `GET_CUSTOM_LIGHT=0x86`, `GET_POWER=0x87`,
`GET_LIGHT_COLOR=0x8a`, and `GET_ADVANCED_KEY=0x92`.
4. Those command numbers and the vendor driver's 520-byte response framing
are a reverse-engineering reference, not proof that a frame is safe to
send to this firmware. The authentication derivation, exact payload
fields, checksums, and persistence semantics must be captured and tested.
The 5-byte feature report must remain unused until its purpose is known. The
application must never probe it by sending random values.
## 5. Minimum Linux implementation
Use one small privileged device service, not a GUI that directly opens USB:
```text
CLI / desktop UI
│ local IPC
swarm75d (single owner, policy + persistence)
│ hidraw feature reports only
Kreo Swarm 75 vendor collection
```
The service owns discovery, authentication, framing, serialization,
readback, and error recovery. The UI is unprivileged and renders only
capabilities returned by the service. Normal keyboard events remain owned by
the kernel/input stack; the controller must never grab `/dev/input/event*`.
Required service invariants:
- Match VID, PID, product name, interface, usage page, report IDs, and
feature sizes before enabling writes. A mismatch is an unsupported device,
not a best-effort match.
- One control session at a time. Treat disconnect, suspend, a failed
authentication, an unexpected report ID, timeout, or malformed length as a
failed transaction and reconnect before retrying.
- Read and save a complete configuration backup before the first write.
Serialize writes; validate every range and key-map entry locally; read back
and compare after every successful setting update.
- No auto-writes on discovery, reconnect, application start, or resume.
Keep factory reset behind a typed confirmation and provide an explicit
restore path.
- Persist only the user's desired configuration and protocol-independent
model. Do not persist raw report frames across firmware changes.
The first version should implement **read device info, lighting, key map,
macro read/write, debounce, sleep, export/import, and restore**. It should
omit firmware update, factory reset UI, and any option the authenticated
capability query does not advertise.
## 6. Bring-up and acceptance plan
1. Boot a kernel with hidraw enabled. Verify a matching hidraw node appears
without unbinding the keyboard and that typing/media/LEDs still work.
2. Capture a read-only official Kontrol session with usbmon or hidraw tracing:
device identification, authentication, attributes, key map, lighting,
macro, and battery reads. Redact no protocol bytes; they are device
commands, not user input.
3. Implement the same feature-report exchange in a test transport. Use the
captured frames as golden tests for exact length, ordering, checksum, and
timeout behaviour.
4. On hardware, authenticate and perform only readbacks. Compare the parsed
state with Kontrol and with the keyboard's Fn controls.
5. With an explicit user action, write a reversible global lighting change,
read it back, power-cycle/reconnect, and restore the saved configuration.
6. Repeat for one nonessential key mapping, one macro slot, debounce, and
sleep. Confirm that normal typing remains available throughout and that a
backup restore works after an interrupted write.
## 7. Evidence and reproducibility
- Live USB/HID probe, 2026-09-21: `lsusb -v -d 258a:010c` and
`sudo usbhid-dump -d 258a:010c -e descriptor`. The latter returned the two
report descriptors summarized above.
- Official Kreo support page: <https://kreo-tech.com/pages/kontrol>. It lists
Swarm 75/X and Swarm 65 as supported and describes browser-based RGB,
binding, and macro configuration.
- Official controller inspected: <https://kontrol.kreo-tech.com>. Its
`swarm75` `bytech` WASM module at the time of inspection had SHA-256
`28cecc21b761465c9da8aab0e188da49438dfee71622fae96c90278948d186c9`.
- The product family also advertises tri-mode connectivity and per-key RGB,
but this probe covers only the attached USB HID presentation. Bluetooth and
direct USB-C modes need separate discovery records and must not be assumed
protocol-compatible.