From 700b34fb609ad5d2c0e3cfece5c13a98e2c85caf Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 21 Sep 2026 05:00:08 +0000 Subject: [PATCH] Record supplied VoidKontrol specification and repository guidance --- AGENTS.md | 13 ++ KREO-SWARM75-LINUX-CONTROL-SPEC.md | 184 +++++++++++++++++++++++++++++ docs/agents/domain.md | 14 +++ docs/agents/issue-tracker.md | 27 +++++ docs/agents/triage-labels.md | 9 ++ 5 files changed, 247 insertions(+) create mode 100644 AGENTS.md create mode 100644 KREO-SWARM75-LINUX-CONTROL-SPEC.md create mode 100644 docs/agents/domain.md create mode 100644 docs/agents/issue-tracker.md create mode 100644 docs/agents/triage-labels.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..7ddca12 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,13 @@ +## Agent skills + +### Issue tracker + +Issues live in this project's Gitea Issues. See `docs/agents/issue-tracker.md`. + +### Triage labels + +The default five canonical triage labels are used. See `docs/agents/triage-labels.md`. + +### Domain docs + +This is a single-context repository. See `docs/agents/domain.md`. diff --git a/KREO-SWARM75-LINUX-CONTROL-SPEC.md b/KREO-SWARM75-LINUX-CONTROL-SPEC.md new file mode 100644 index 0000000..25e0daf --- /dev/null +++ b/KREO-SWARM75-LINUX-CONTROL-SPEC.md @@ -0,0 +1,184 @@ +# 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 + +This laptop's kernel does not provide `hidraw` (`modprobe hidraw` reports that +the module is absent). A native controller therefore requires a kernel with +`CONFIG_HIDRAW=y` or `CONFIG_HIDRAW=m`, plus a narrow udev rule granting the +controller service access to the matching hidraw node. It must select the +node that represents interface 1 / usage `0xff00:0x01`. + +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: . It lists + Swarm 75/X and Swarm 65 as supported and describes browser-based RGB, + binding, and macro configuration. +- Official controller inspected: . 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. diff --git a/docs/agents/domain.md b/docs/agents/domain.md new file mode 100644 index 0000000..859ca2f --- /dev/null +++ b/docs/agents/domain.md @@ -0,0 +1,14 @@ +# Domain Docs + +Before exploring, read root `CONTEXT.md` (or `CONTEXT-MAP.md` when present) and relevant `docs/adr/` decisions. If absent, proceed silently; domain-modeling creates them when a real terminology or decision need arises. + +This is a single-context layout: + +``` +/ +├── CONTEXT.md +├── docs/adr/ +└── src/ +``` + +Use defined glossary terms consistently, and explicitly flag conflicts with existing ADRs. diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md new file mode 100644 index 0000000..89041df --- /dev/null +++ b/docs/agents/issue-tracker.md @@ -0,0 +1,27 @@ +# Issue tracker: Gitea + +Issues and specs for this repo live as Gitea issues. Use the official [`tea`](https://gitea.com/gitea/tea) CLI for all operations. + +## Conventions + +- **Create an issue**: `tea issues create --title "..." --description "..."`. +- **Read an issue**: `tea issues `. +- **List issues**: `tea issues`; use `tea issues --state all` for all states and `tea issues --format json` for machine-readable output. +- **Comment on an issue**: `tea comment issue `. +- **Apply / remove labels**: `tea issues edit --add-labels "..."` / `--remove-labels "..."`. +- **Close**: `tea issues close `. +- **Pull requests**: use `tea pulls create`, `tea pulls `, and `tea pulls checkout `. + +Configure the Gitea instance with `tea login add`. `tea` uses repository context from the current clone when available. + +## Merge requests as a triage surface + +**Pull requests as a request surface: no.** + +## When a skill says "publish to the issue tracker" + +Create a Gitea issue. + +## When a skill says "fetch the relevant ticket" + +Run `tea issues `. diff --git a/docs/agents/triage-labels.md b/docs/agents/triage-labels.md new file mode 100644 index 0000000..442ff6b --- /dev/null +++ b/docs/agents/triage-labels.md @@ -0,0 +1,9 @@ +# Triage Labels + +| Canonical role | Tracker label | Meaning | +| --- | --- | --- | +| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue | +| `needs-info` | `needs-info` | Waiting on reporter for more information | +| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent | +| `ready-for-human` | `ready-for-human` | Requires human implementation | +| `wontfix` | `wontfix` | Will not be actioned |