diff --git a/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md b/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md index 313bf6a2ee..1f4cc1e1e8 100644 --- a/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md +++ b/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md @@ -80,21 +80,24 @@ was cross-referenced (see §5 and §8). ### Two Architecture Decisions Resolved (v6.0) -1. **Unified input architecture**: Red Bear has had THREE input subsystems running in parallel - (`inputd` for Orbital, `evdevd` for Linux-compat, plus per-driver schemes). v6.0 collapses - this to **one input path** that all consumers (Orbital, KWin, redbear-compositor, libinput) - read from. See §3. +1. **Single evdev producer (no Orbital on the desktop)**: Red Bear has had THREE input subsystems + running in parallel (`inputd` for Orbital, `evdevd` as a bridge, plus per-driver schemes). The + user explicitly committed to **"we do not use Orbital and do not plan to use it. we aim for + wayland/kde."** So v6.0 collapses to **one input path** — drivers write Linux `struct input_event` + records to `/scheme/input/evdev`, `evdevd` exposes them as `/dev/input/eventN`, libinput (in-process + to KWin and to redbear-compositor) reads from there. `inputd` is deprecated for the desktop + config; it stays in the tree only as legacy. See §2. 2. **Compositor decision**: KWin is the canonical Wayland compositor. `redbear-compositor` (788-line Rust) is **not** extended to production quality — instead it serves only the - greeter phase. KWin takes over for the user session. See §4. + greeter phase. KWin takes over for the user session. See §3. ### Critical Path Phases (v6.0) | Phase | Name | Effort | Gate | |-------|------|--------|------| | 0 | Pre-flight: QML JIT + kf6-kdeclarative QML re-enable | 4-6 weeks | Qt6Quick works in QEMU | -| 1 | Unified input architecture: inputd + evdevd merge → `/scheme/input/events` | 1-2 weeks | evdevd reads from new unified scheme | +| 1 | Single evdev producer: drivers write `/scheme/input/evdev`, evdevd exposes `/dev/input/eventN`, libinput reads (inputd deprecated for desktop) | 1 week | evdevd reads from `/scheme/input/evdev`; libinput sees real events | | 2 | DRM atomic modeset + render node + PRIME real FDs + RESOURCE_MAP_BLOB | 2-3 weeks | redbear-compositor opens `renderD128` | | 3 | Mesa EGL Wayland fix (remove `-lorbital`, add `-lwayland-client`) | 1 week | Qt6 eglfs opens Wayland window | | 4 | redbear-compositor → libinput + kf6-kwayland protocol coverage | 2-3 weeks | Qt6 app runs under redbear-compositor | @@ -143,9 +146,9 @@ The 110 missing components include the most critical: **PipeWire**, **KWin full ### Bottom Line Red Bear OS has all the *foundations* of a desktop OS — kernel, ACPI, IRQ, low-level drivers, -DRM scheme, Mesa, Qt6, KF6 recipes, greeter, session broker. What's missing is a *single -coherent input stack* (inputd/evdevd are now dual), *KWin running as compositor* (the QML gate), -and *Plasma shell apps* (plasma-desktop, dolphin, etc.). +DRM scheme, Mesa, Qt6, KF6 recipes, greeter, session broker. What's missing is the *single +evdev producer and consumer* (Phase 1), *KWin running as compositor* (the QML gate, Phase 0), +and *Plasma shell apps* (plasma-desktop, dolphin, etc., Phase 7). The v6.0 plan commits to: - One unified input path (inputd + evdevd merged via shared scheme) @@ -197,38 +200,46 @@ Remaining gaps: --- -## 2. Unified Input Architecture (v6.0 — replaces inputd/evdevd split) +## 2. Single-Producer Input Architecture (v6.0) ### 2.1 The Problem -Red Bear OS has accumulated **three input subsystems** in parallel, each serving different -downstream consumers: +Red Bear OS has accumulated **three input subsystems** in parallel: ``` ps2d/usbhidd/i2c-hidd/intel-thc-hidd/virtio-inputd │ ├── orbclient::Event ──→ inputd (scheme:input) ──→ Orbital compositor - │ ──→ evdevd (converts orbclient → input_event) - │ │ - │ └─→ /dev/input/eventN │ - └── evdev_format ──→ ??? (no driver writes evdev directly yet) + └── (none, would need to write evdev) + ▲ + │ + evdevd (consumes inputd's orbclient events, re-emits as evdev) + │ + └─→ /dev/input/eventN ``` -**The inputd → evdevd bridge is wrong architecture.** evdevd is a Linux-compatibility shim that -takes Orbital's orbclient events and re-emits them as Linux evdev events. The conversion loses: -- Timestamps (orbclient `Event` has none) -- EV_ABS axis ranges (no absinfo) -- EV_SYN/SYN_DROPPED flow (orbclient has no SYN) -- Device ID/vendor/product (no metadata in orbclient) -- Real-time behavior (inputd round-trips through a scheme) +The v5.0 "dual-path" plan (drivers write to BOTH orbclient and evdev producers) was +initially proposed for v6.0, then **rejected** on review. The reasons: -**CachyOS reference**: kernel evdev → libinput (CLIENT LIBRARY) → compositor. libinput is NOT a -daemon. It reads `/dev/input/event*` devices directly. The CachyOS architecture has ONE input path. +1. **Doubles every driver's event-write code** — every key press, every mouse delta, + every button click has to be written twice +2. **Doubles the per-event syscall cost** — 2 writes instead of 1 +3. **Out-of-order risk** — if one producer is slower than the other, events get + misaligned between Orbital and KWin views of the same physical input +4. **No consumer actually needs Orbital on the desktop** — KWin + redbear-compositor + (for the greeter) are the only consumers on the desktop path. The user + explicitly committed: **"we do not use Orbital and do not plan to use it. + we aim for wayland/kde"** +5. **Extra translation hop loses metadata** — timestamps, EV_ABS axis ranges, + EV_SYN/SYN_DROPPED, vendor/product IDs, real-time ordering -### 2.2 The Unified Input Architecture +### 2.2 The Decision: Single evdev Producer -v6.0 introduces a **single input path** that all consumers read from: +**v6.0 commits to a single Linux evdev producer.** All input drivers write Linux +`struct input_event` records to one scheme. `evdevd` is a thin adapter from +that scheme to `/dev/input/eventN`. libinput (in-process to KWin and to +redbear-compositor during the greeter phase) reads from `/dev/input/event*`. ``` Hardware @@ -240,98 +251,98 @@ Hardware ├── virtio-inputd (QEMU virtio-input) │ ▼ -ALL drivers write to ONE of two scheme producers: + ONE producer: /scheme/input/evdev + (Linux struct input_event, 8 bytes per event: type, code, value) │ - ├── /scheme/input/orbclient (for Orbital compositor — ORBCLIENT format) - │ └─→ inputd (subsumes current inputd) → Orbital display server + ▼ + evdevd (pure scheme → /dev/input/eventN adapter) │ - └── /scheme/input/evdev (for KWin + libinput + redbear-compositor — LINUX EVDEV format) - └─→ /dev/input/eventN (via udev-shim) - └─→ libinput (in-process to KWin / redbear-compositor) - └─→ wl_seat events to Wayland clients - -Both producers are WRITTEN by the same input drivers — they are sibling destinations. + ▼ + /dev/input/eventN (Linux native evdev) + │ + ├── libinput (in-process to KWin) → KWin wl_seat → Wayland clients + ├── libinput (in-process to redbear-compositor) → greeter wl_seat (Qt6/QML UI) + └── Direct fd (Qt6 apps that don't use libinput) → KDE app input ``` -**Key changes:** +### 2.3 What This Means for Each Component -1. **Each input driver writes to BOTH producers** (dual-path). The conversion to evdev format - happens INSIDE each driver (using its own knowledge of the device: e.g. ps2d knows the scancode - table; usbhidd knows HID usage codes; virtio-inputd knows Linux evdev semantics natively). +| Component | Change | +|-----------|--------| +| `inputd` | **Deprecated for the desktop config.** Stays in the tree only as a historical Orbital daemon — never started by `redbear-full.toml` or `redbear-greeter-services.toml`. The `lib.rs` exposes the new `EvdevProducerHandle` for drivers that want to use it, and keeps the legacy `ProducerHandle` for any code that still uses Orbital. | +| `evdevd` | **Re-scoped to a pure scheme→/dev/input/eventN adapter.** Consumes from `/scheme/input/evdev` (the new single producer). Removes the orbclient consumer path. | +| `ps2d`, `usbhidd`, `i2c-hidd`, `intel-thc-hidd` | **Replace `ProducerHandle` with `EvdevProducerHandle`.** Convert orbclient scancodes/mouse-deltas to Linux evdev at the driver (where device knowledge lives). | +| `virtio-inputd` (v5.1) | **Use `EvdevProducerHandle` in Phase 5.2 expansion.** The driver already has Linux keycode semantics natively — translation is trivial. | +| `redbear-greeter` | Uses libinput or direct `/dev/input/event*` fd. Qt6 reads from these directly. No Orbital dependency. | +| KWin | Uses libinput (in-process). Reads from `/dev/input/event*`. Same as CachyOS. | +| `redbear-compositor` (greeter only) | Uses libinput (in-process). Same as CachyOS. | -2. **inputd is re-scoped** to be the Orbital-side multiplexer only. It consumes from - `/scheme/input/orbclient` and produces to Orbital. **It no longer has an evdev-format consumer.** +### 2.4 Driver-Side Implementation (v6.0 Phase 1) -3. **evdevd is re-scoped** to be a pure scheme-to-`/dev/input/eventN` adapter. It consumes from - `/scheme/input/evdev` and produces Linux evdev events. **It no longer translates orbclient events.** +| Driver | Current state | Required change | +|--------|--------------|-----------------| +| `ps2d` | Writes orbclient::Event with orbclient keycodes | Replace with `EvdevProducerHandle`. Convert orbclient `K_*` keycodes to Linux `KEY_*` keycodes (we have most of this table already). | +| `usbhidd` | Writes orbclient::Event with orbclient keycodes | Replace with `EvdevProducerHandle`. Convert HID usage codes to Linux keycodes. | +| `i2c-hidd` | Same as usbhidd (I2C HID is HID) | Replace with `EvdevProducerHandle`. | +| `intel-thc-hidd` | Same as usbhidd (Intel THC is HID) | Replace with `EvdevProducerHandle`. | +| `virtio-inputd` (v5.1) | Writes orbclient::Event | **Phase 5.2 expansion**: switch to `EvdevProducerHandle`. The driver already speaks Linux evdev natively. | +| `redbear-keymapd` | Consumes keymaps (not events) | No change. | -4. **redbear-compositor and KWin** consume from `/dev/input/event*` via libinput (client library) - or via direct evdev ioctls. +**Effort per driver**: 1-2 days. Total: **~1 week** (much smaller than the dual-path 1-2 weeks). -### 2.3 Driver-Side Implementation (v6.0 Phase 1) +### 2.5 Scheme API (v6.0) -| Driver | /scheme/input/orbclient writes | /scheme/input/evdev writes | -|--------|-------------------------------|-----------------------------| -| `ps2d` | Already does this (ProducerHandle) | **Add**: write evdev events with proper input_event struct (time/type/code/value) | -| `usbhidd` | Already does this (ProducerHandle) | **Add**: write evdev events with HID usage → Linux keycode mapping | -| `i2c-hidd` | Already does this | **Add**: same as usbhidd | -| `intel-thc-hidd` | Already does this | **Add**: same as usbhidd | -| `virtio-inputd` (v5.1) | Already does this (ProducerHandle) | **Add**: write evdev events (its native format — Phase 5.2 expansion) | -| `redbear-keymapd` | n/a | n/a (consumes keymaps, not events) | - -**Effort per driver**: 1-2 days each (3-5 files, ~100-200 lines). Total: 1-2 weeks for all 5 drivers. - -### 2.4 Scheme API (v6.0) - -**`/scheme/input/orbclient`** (replaces current `/scheme/input/producer`): -- Producers: `ProducerHandle::new()` returns File at `/scheme/input/orbclient` -- Consumer: inputd opens `/scheme/input/orbclient_consumer` and reads orbclient::Event (24 bytes each) -- Inputd then forwards to Orbital's `/scheme/display` consumer - -**`/scheme/input/evdev`** (replaces current evdevd's `input:consumer` input): +**`/scheme/input/evdev`** (new, single producer): - Producers: `EvdevProducerHandle::new()` returns File at `/scheme/input/evdev` -- Producer writes Linux `struct input_event` (24 bytes: u16 type, u16 code, s32 value, u32 time_sec, - u32 time_usec — wait, 16 bytes actually: type, code, value) on each event -- Consumer: evdevd opens `/scheme/input/evdev_consumer` and creates `/dev/input/eventN` files with EVIOC ioctls +- Wire format: 8 bytes per event — `u16 type, u16 code, i32 value` (the Linux `struct input_event` with no time fields; `evdevd` adds timestamps when the device is opened, just like CachyOS) +- Synchronization: producers MUST emit `EV_SYN / SYN_REPORT / value=0` between batches of events to mark a logical report boundary +- Consumer: `evdevd` opens `/scheme/input/evdev_consumer` and creates `/dev/input/eventN` files with full EVIOC ioctl support **`/dev/input/eventN`** (unchanged): -- Same Linux evdev interface as today -- libinput (in-process to KWin or compositor) opens these as fds and reads 16-byte `struct input_event` +- Standard Linux evdev interface +- libinput (in-process to KWin / redbear-compositor) opens these as fds and reads `struct input_event` - This is what CachyOS uses and what the Linux 7.1 kernel implements -### 2.5 Migration Plan (v6.0 Phase 1) +**`/scheme/input/producer`** (legacy, unchanged): +- Existing orbclient::Event producer +- Kept in the tree for any code that still needs to feed Orbital +- NOT used by desktop drivers or the desktop init configuration + +### 2.6 Migration Plan (v6.0 Phase 1) | Step | Files | Action | |------|-------|--------| -| 1.1 | New file `local/sources/base/drivers/inputd/src/evdev_producer.rs` | Add evdev-format producer to inputd | -| 1.2 | Modify `local/sources/base/drivers/input/ps2d/src/main.rs` | Add dual-write to `/scheme/input/evdev` | -| 1.3 | Modify `local/sources/base/drivers/input/usbhidd/src/main.rs` | Add dual-write to `/scheme/input/evdev` | -| 1.4 | Modify `local/sources/base/drivers/input/i2c-hidd/src/main.rs` | Add dual-write to `/scheme/input/evdev` | -| 1.5 | Modify `local/sources/base/drivers/input/intel-thc-hidd/src/main.rs` | Add dual-write to `/scheme/input/evdev` | -| 1.6 | Modify `local/recipes/drivers/virtio-inputd/source/src/main.rs` (Phase 5.2) | Use evdev producer (its native format) | -| 1.7 | Modify `local/recipes/system/evdevd/source/src/main.rs` | Remove orbclient consumer; add evdev scheme consumer | -| 1.8 | Modify `config/redbear-full.toml` | Add `input:evdev` to init (or already implied) | -| 1.9 | Modify `local/recipes/system/udev-shim/` | Update to expose new scheme paths | +| 1.1 | `local/sources/base/drivers/inputd/src/lib.rs` | ✅ DONE: added `EvdevProducerHandle`, `EvdevEvent`, `keycodes` module | +| 1.2 | `local/sources/base/drivers/input/ps2d/src/main.rs` + `state.rs` | Convert orbclient keycodes to Linux keycodes, replace `ProducerHandle` with `EvdevProducerHandle` | +| 1.3 | `local/sources/base/drivers/input/usbhidd/src/main.rs` | Same — convert HID usage to Linux keycodes | +| 1.4 | `local/sources/base/drivers/input/i2c-hidd/src/main.rs` | Same | +| 1.5 | `local/sources/base/drivers/input/intel-thc-hidd/src/main.rs` | Same | +| 1.6 | `local/recipes/drivers/virtio-inputd/source/src/main.rs` (Phase 5.2) | Use evdev producer (its native format) | +| 1.7 | `local/recipes/system/evdevd/source/src/main.rs` | Switch consumer from `/scheme/input/consumer` (orbclient) to `/scheme/input/evdev` (new single producer) | +| 1.8 | `config/redbear-full.toml` | Add `evdevd` to init services; remove `inputd` (it was never started here anyway) | +| 1.9 | `local/recipes/system/udev-shim/` | Update scheme mapping to expose new `/dev/input/eventN` from evdevd | -### 2.6 Verification (v6.0 Phase 1 Gate) +### 2.7 Verification (v6.0 Phase 1 Gate) -- [ ] `ps2d` writes evdev events with valid timestamps (monotonic, not zero) -- [ ] `usbhidd` evdev events have correct vendor/product ID (forwarded from USB descriptors) -- [ ] `evdevd` opens `/dev/input/event*` files with correct EVIOCGVERSION -- [ ] A test program (C) opens `/dev/input/event0` and reads events as `struct input_event` +- [ ] `ps2d` writes evdev events with valid Linux keycodes (KEY_* from input-event-codes.h) +- [ ] `usbhidd` evdev events have correct HID usage → Linux keycode mapping +- [ ] `evdevd` opens `/dev/input/event*` files with correct `EVIOCGVERSION` (returns EV_VERSION) +- [ ] A C test program opens `/dev/input/event0` and reads events as `struct input_event` - [ ] libinput test program opens the same device and reports "keyboard found" (or pointer) -- [ ] QEMU: pressing a key in PS/2 → libinput sees the event -- [ ] No regression: Orbital login still works via the orbclient path +- [ ] QEMU: pressing a key on PS/2 → libinput sees the event +- [ ] QEMU: keyboard arrow keys work in greeter (Qt6 reads from /dev/input/event*) +- [ ] QEMU: virtio-input keyboard works in greeter -### 2.7 Why This Matters +### 2.8 Why This Matters -The v6.0 unified architecture: -- **Matches CachyOS/Linux**: One kernel-evdev path that all consumers read +The v6.0 single-producer architecture: +- **Matches CachyOS/Linux exactly**: One kernel-evdev path that all consumers read - **Enables KWin**: KWin uses libinput which reads `/dev/input/event*` — same as CachyOS - **Enables Wayland clients**: redbear-compositor and KWin read from libinput -- **Preserves Orbital**: inputd continues to serve Orbital, no regression -- **Fixes metadata loss**: vendor/product ID, axis ranges, timestamps now flow through -- **Simplifies the code**: One consumer per input type, no bridge +- **Eliminates dual-write overhead**: drivers write ONCE +- **Eliminates metadata loss**: vendor/product ID, axis ranges, timestamps all flow through +- **Simplifies the code**: One producer, one consumer (`evdevd`), one path +- **Removes dependency on Orbital** for the desktop: inputd is dead code in redbear-full ---