hidinput.sg wires the HID driver output to the Lumen WM event model. HID_CAP_TOKEN (0x48494421, "HID!") is broker-held — no EL0 code can forge or supply it. Per-window key rings live at 0xA60000 (8 windows × 64B each). Keyboard char delivery, Alt+Tab focus cycling, and mouse dispatch via pointer.sg are all wired and QEMU raspi3b PASS. (36de866)
The capability gate
HID_CAP_TOKEN = 0x48494421 ("HID!" as ASCII). The broker holds this token and injects it at the HID driver seam. EL0 code receives event data but never the token itself. A call with the wrong token returns -1 and delivers no event. This is the same trust model used across sigilOS for sensitive I/O: AU_MIC_TOKEN (audio mic), HP_NET_TOKEN (network), ID_ELEV_TOKEN (identity elevation). The token is the boundary; EL0 stays on the results side.
Per-window key rings
The key ring region starts at 0xA60000. Eight windows, 64 bytes each. Layout per window:
offset 0 — write_head (u32, WM writes here)
offset 8 — read_head (u32, EL0 reads here)
offset 16 — char buf (48 bytes, circular SPSC)
The WM writes to the circular buffer and advances write_head. The focused window's EL0 app reads from read_head. SPSC — no lock needed in standalone; a real kernel implementation adds a futex for cross-core wakeup. Overflow is guarded: a full ring drops the incoming character (harness assertion #8 verifies the guard holds).
Keyboard dispatch
hid_kbd_dispatch is the entry point from the HID driver. Flow:
- Cap gate check: wrong
HID_CAP_TOKEN→ return-1. - Shift decode:
band(modifiers, 34)tests L-shift (bit 1) + R-shift (bit 5). Non-zero → shift active. - Alt+Tab: usage
0x2Bwith Alt modifier →wm_key(KEY_TAB)→ WM cycles focus to the next window. - Printable chars:
hid_char(usage, shift)maps HID usage to ASCII and writes to the focused window's ring. - Raw navigation: arrow keys, Esc, Fn →
wm_key(usage)for direct WM key delivery.
Mouse dispatch
hid_mouse_dispatch enforces the same cap gate (HID_CAP_TOKEN check first, return -1 on mismatch), then delegates to pt_dispatch() in pointer.sg. pointer.sg handles cursor clamping to screen bounds and WM pointer-down / drag / pointer-up routing, dispatching to whichever overlay or window owns the hit point.
12-assertion harness (hidinputtest.sg)
| # | Assertion |
|---|---|
| 1 | Ring init: write_head=0, read_head=0 |
| 2 | Ring write: write_head advances |
| 3 | Ring read: read_head advances, correct char returned |
| 4 | Ring pending: correct count returned |
| 5 | Cap gate: wrong token → -1, no event delivered |
| 6 | Cap gate: correct token → event routed |
| 7 | Char delivery: char appears in focused window's ring |
| 8 | Mouse cap gate: wrong token → -1 |
| 9 | Ring overflow guard: full ring drops char, heads unchanged |
| 10 | Focus switch: event routes to new focused window after Alt+Tab |
| 11 | Shift decode: uppercase char delivered with L-shift active |
| 12 | Mouse dispatch: pt_dispatch called with correct coords on valid token |
All 12 assertions PASS on QEMU raspi3b.