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

4 KiB

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. 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

Reports are encoded into byte arrays; native C structures, padding and host byte order are never used as a persistent or wire format.