labfy-rgb/docs/protocol.md
2026-11-09 19:01:00 +01:00

65 lines
4 KiB
Markdown

# Accepted HID LampArray profile
Labfy RGB deliberately supports one exact 748-byte descriptor, on I2C HID
`0018:00000B05:00005570`. The corresponding fixture and SHA-256 are documented in
[tests/data/README.md](../tests/data/README.md). Device numbering is discovered
at runtime. The open fd is checked again through RAWINFO and descriptor ioctls
before any control report, so sysfs discovery alone is not trusted.
This profile uses Lighting and Illumination usage page `0x0059`. A second vendor
page `0xFF59` and its report IDs are not used. Report sizes below include the ID
byte. Multibyte integers are explicitly little endian.
| ID | Report | Bytes | Payload |
|---|---|---:|---|
| `0x41` | Array attributes | 23 | lamp count u16, dimensions/kind/minimum interval as five u32 |
| `0x42` | Lamp attributes request | 3 | lamp ID u16 |
| `0x43` | Lamp attributes response | 29 | ID u16, X/Y/Z/latency/purposes as five u32, RGBI maxima/programmability/input binding as six u8 |
| `0x44` | Multi update, unused by this implementation | 51 | count/flags, eight IDs and eight RGBI tuples |
| `0x45` | Range update | 10 | flags u8, start/end u16, R/G/B/I u8 |
| `0x46` | Array control | 2 | AutonomousMode u8 |
All relevant logical minima are zero. Count/IDs have a descriptor maximum of
65535, the u32 fields a maximum of 2147483647, and channel/attribute bytes a
maximum of 255. The descriptor allows flags through 8; the implementation emits
only the defined bit 0, LampUpdateComplete. AutonomousMode is limited to 0 or 1.
Semantic validation is stricter than descriptor widths: IsProgrammable must be
boolean, positions must fit the array bounds, and the accepted array has exactly
one logical lamp, ID 0. Missing RGB channels or unusable intensity are rejected
for color control. Zero RGBI can still be sent for off on a valid fixed-color lamp.
## Operation
1. GET `0x41` and require one logical lamp.
2. SET `42 00 00`, then GET `0x43`; check the returned lamp ID and attributes.
3. For color control, require programmable RGB with nonzero RGBI maxima.
4. SET `46 00` to take host control.
5. Wait the array's live minimum interval (3000 us on the tested machine).
6. SET `45 01 00 00 00 00 R G B I`, covering inclusive range [0,0].
7. Keep host control after success. Restore only on explicit `auto` or recovery.
The selector in step 2 **is a write**, even though it requests attributes rather
than a lighting change. `status` does not send this selector. `probe` does.
For an input color channel C in 0..255 and live maximum L, the wire value is
`(C * L + 127) / 255`. For intensity P in 0..100, it is `(P * L + 50) / 100`.
Products are bounded and use sufficient width. LevelCount is the maximum nonzero
intensity, not a count from which one should subtract one; zero means off.
The tested device declares 255 for all four maxima.
An error from the first attempted host-control SET onward causes exactly one SET
`46 01`. This includes a failed/short host SET whose effect may be ambiguous.
No SET is blindly retried. Original and restoration errors are reported separately.
Explicit `auto` needs identity/descriptor validation, but no RGB capability query
or successful cache access. Neither ioctl success nor cached mode is an optical
measurement. Abrupt termination can prevent recovery.
## Reference material
- [USB-IF HUTRR84: Lighting and Illumination](https://www.usb.org/sites/default/files/hutrr84_-_lighting_and_illumination_page.pdf), particularly color attributes, autonomous mode and range updates.
- [Linux hidraw documentation](https://docs.kernel.org/hid/hidraw.html).
- Linux [hidraw.c](https://github.com/torvalds/linux/blob/master/drivers/hid/hidraw.c) and [i2c-hid-core.c](https://github.com/torvalds/linux/blob/master/drivers/hid/i2c-hid/i2c-hid-core.c) for Feature request return semantics.
- The MIT reference implementations acknowledged in [THIRD_PARTY_NOTICES.md](../THIRD_PARTY_NOTICES.md).
Reports are encoded into byte arrays; native C structures, padding and host byte
order are never used as a persistent or wire format.