inputd: fix scheme name input/evdev -> input-evdev

Redox scheme names are flat identifiers; '/' is rejected by
RedoxScheme::new() causing inputd to panic at boot:
  initnsmgr.rs:301: Invalid scheme name: input/evdev

All consumers updated: EvdevProducerHandle (lib.rs), evdevd,
virtio-inputd, intel-thc-hidd, ps2d, usbhidd, i2c-hidd.
Plan doc updated (21 references).

Base fork commit: 4c1fa35c
This commit is contained in:
2026-06-10 10:42:38 +03:00
parent 326a6fdd52
commit c22147d673
6 changed files with 32 additions and 32 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ mode = 0o1777
# legacy `inputd -A 2` invocation. v6.0 inputd has no -A flag (it
# implements the single-producer evdev ring buffer). initfs already
# starts inputd in phase 1 (init.initfs.d/10_inputd.service) and
# registers /scheme/input/evdev; the rootfs second invocation would
# registers /scheme/input-evdev; the rootfs second invocation would
# just fail with "unrecognized argument".
[[files]]
path = "/etc/init.d/29_activate_console.service"
+22 -22
View File
@@ -84,7 +84,7 @@ was cross-referenced (see §5 and §8).
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
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.
@@ -97,7 +97,7 @@ was cross-referenced (see §5 and §8).
| Phase | Name | Effort | Gate |
|-------|------|--------|------|
| 0 | Pre-flight: QML JIT + kf6-kdeclarative QML re-enable | 4-6 weeks | Qt6Quick works in QEMU |
| 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 |
| 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 |
@@ -251,7 +251,7 @@ Hardware
├── virtio-inputd (QEMU virtio-input)
ONE producer: /scheme/input/evdev
ONE producer: /scheme/input-evdev
(Linux struct input_event, 8 bytes per event: type, code, value)
@@ -270,7 +270,7 @@ Hardware
| 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. |
| `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. |
@@ -292,11 +292,11 @@ Hardware
### 2.5 Scheme API (v6.0)
**`/scheme/input/evdev`** (new, single producer):
- Producers: `EvdevProducerHandle::new()` returns File at `/scheme/input/evdev`
**`/scheme/input-evdev`** (new, single producer):
- Producers: `EvdevProducerHandle::new()` returns File at `/scheme/input-evdev`
- 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
- Consumer: `evdevd` opens `/scheme/input-evdev_consumer` and creates `/dev/input/eventN` files with full EVIOC ioctl support
**`/dev/input/eventN`** (unchanged):
- Standard Linux evdev interface
@@ -313,14 +313,14 @@ Hardware
| Step | Files | Action |
|------|-------|--------|
| 1.1 | `local/sources/base/drivers/inputd/src/lib.rs` | ✅ DONE: added `EvdevProducerHandle`, `EvdevEvent`, `keycodes` module |
| 1.1b | `local/sources/base/drivers/inputd/src/main.rs` | ✅ DONE: restored inputd binary as a scheme daemon. Registers `/scheme/input/evdev` as a multi-writer single-reader ring buffer (64 KiB / 8192 events). 8-byte `EvdevEvent` records; partial writes rejected; overflow drops to bound latency. |
| 1.1b | `local/sources/base/drivers/inputd/src/main.rs` | ✅ DONE: restored inputd binary as a scheme daemon. Registers `/scheme/input-evdev` as a multi-writer single-reader ring buffer (64 KiB / 8192 events). 8-byte `EvdevEvent` records; partial writes rejected; overflow drops to bound latency. |
| 1.2 | `local/sources/base/drivers/input/ps2d/src/main.rs` + `state.rs` + `keymap.rs` | ✅ DONE: ps2d uses `EvdevProducerHandle`. PS/2 scancode sets 1, 2, 3 are mapped to Linux `KEY_*` constants (from `inputd::keycodes`) in `keymap.rs`. Mouse reports emit `EV_REL` (REL_X, REL_Y, REL_WHEEL, REL_HWHEEL) and `EV_KEY` (BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_SIDE, BTN_EXTRA) followed by `SYN_REPORT`. |
| 1.3 | `local/sources/base/drivers/input/usbhidd/src/main.rs` | ✅ DONE: usbhidd uses `EvdevProducerHandle` via `redbear-hid-core::translate`. HID usages are mapped to Linux evdev codes (`map_usage_to_evdev` in `redbear-hid-core/src/usage_table.rs`): `EV_KEY` (BTN_MOUSE/BTN_JOYSTICK), `EV_REL` (REL_X, REL_Y, REL_WHEEL, REL_HWHEEL), `EV_ABS` (ABS_X, ABS_Y, ABS_MT_*) followed by `SYN_REPORT`. |
| 1.4 | `local/sources/base/drivers/input/i2c-hidd/src/main.rs` + `input.rs` | ✅ DONE: I2C HID uses the same `redbear-hid-core::translate` path as usbhidd. `EvdevProducerHandle` writes 8-byte `EvdevEvent` records; keyboard and touchpad reports emit `EV_KEY`/`EV_ABS`/`EV_SYN` natively. |
| 1.5 | `local/sources/base/drivers/input/intel-thc-hidd/src/main.rs` + `input.rs` | ✅ DONE: Intel Touch Host Controller (THC) reuses the same `redbear-hid-core::translate` path. `EvdevProducerHandle` writes 8-byte `EvdevEvent` records following the same Linux evdev model. |
| 1.6 | `local/recipes/drivers/virtio-inputd/source/src/main.rs` | ✅ DONE: virtio-inputd was implemented natively in Linux-evdev format. Uses `EvdevProducerHandle` directly (`write_evdev_event` adapter at line 253), converting virtio input events to `EV_KEY`/`EV_REL`/`EV_ABS`/`EV_SYN`. No orbclient fallback needed. |
| 1.7 | `local/recipes/system/evdevd/source/src/main.rs` | ✅ DONE: evdevd already opens `/scheme/input/evdev` for reading (`InputConsumer::open`) and relays 8-byte events to `/dev/input/eventN` for libinput. |
| 1.8 | `config/redbear-full.toml` + `redbear-legacy-base.toml` + `init.initfs.d/10_inputd.service` | ✅ DONE: `10_evdevd.service` is defined in `redbear-mini.toml` (inherited by `redbear-full.toml`) and runs `evdevd` with `type = "oneshot_async"`. The initfs already starts `inputd` (registering `/scheme/input/evdev`) and the rootfs `29_activate_console.service` (which used to call `inputd -A 2`) is now overridden to a no-op in `redbear-legacy-base.toml` since v6.0 inputd has no `-A` flag. |
| 1.7 | `local/recipes/system/evdevd/source/src/main.rs` | ✅ DONE: evdevd already opens `/scheme/input-evdev` for reading (`InputConsumer::open`) and relays 8-byte events to `/dev/input/eventN` for libinput. |
| 1.8 | `config/redbear-full.toml` + `redbear-legacy-base.toml` + `init.initfs.d/10_inputd.service` | ✅ DONE: `10_evdevd.service` is defined in `redbear-mini.toml` (inherited by `redbear-full.toml`) and runs `evdevd` with `type = "oneshot_async"`. The initfs already starts `inputd` (registering `/scheme/input-evdev`) and the rootfs `29_activate_console.service` (which used to call `inputd -A 2`) is now overridden to a no-op in `redbear-legacy-base.toml` since v6.0 inputd has no `-A` flag. |
| 1.9 | `local/recipes/system/udev-shim/` | Pending: Update scheme mapping to expose new `/dev/input/eventN` from evdevd |
### 2.7 Verification (v6.0 Phase 1 Gate)
@@ -962,22 +962,22 @@ Total: 12-20 weeks with hardware access
The v5.0 plan proposed a "dual-path" input architecture (drivers write
to BOTH `inputd` and `evdevd` in parallel) so Orbital and Wayland clients
could coexist. The v6.0 design collapses this to **one** path: drivers
write Linux `struct input_event` records to `/scheme/input/evdev`, and
write Linux `struct input_event` records to `/scheme/input-evdev`, and
evdevd relays them to `/dev/input/eventN` for libinput. inputd stays
in the tree only as a historical Orbital daemon, but its **binary** is
now a real scheme daemon implementing the `/scheme/input/evdev` ring
now a real scheme daemon implementing the `/scheme/input-evdev` ring
buffer. This is the change the plan now calls **v6.0**.
| Change | Status | Notes |
|--------|--------|-------|
| Phase 1.1b: `inputd` binary as scheme daemon | ✅ **DONE** | Restored `inputd/src/main.rs` to register `/scheme/input/evdev` as a 64 KiB / 8192-event ring buffer. `Socket::nonblock()` + `register_sync_scheme` to register under the v6.0 scheme name. 8-byte `EvdevEvent` records with partial-write rejection and overflow-drop policy. |
| Phase 1.1: `EvdevProducerHandle` + `EvdevEvent` + `keycodes` | ✅ **DONE** (pre-existing) | inputd lib exposes `EvdevProducerHandle::new()` → opens `/scheme/input/evdev` for write. All Linux keycode constants in `inputd::keycodes` (KEY_ESC, KEY_A, KEY_LEFTCTRL, etc.). |
| Phase 1.1b: `inputd` binary as scheme daemon | ✅ **DONE** | Restored `inputd/src/main.rs` to register `/scheme/input-evdev` as a 64 KiB / 8192-event ring buffer. `Socket::nonblock()` + `register_sync_scheme` to register under the v6.0 scheme name. 8-byte `EvdevEvent` records with partial-write rejection and overflow-drop policy. |
| Phase 1.1: `EvdevProducerHandle` + `EvdevEvent` + `keycodes` | ✅ **DONE** (pre-existing) | inputd lib exposes `EvdevProducerHandle::new()` → opens `/scheme/input-evdev` for write. All Linux keycode constants in `inputd::keycodes` (KEY_ESC, KEY_A, KEY_LEFTCTRL, etc.). |
| Phase 1.2: ps2d → EvdevProducerHandle | ✅ **DONE** (pre-existing) | `ps2d/src/state.rs` uses `EvdevProducerHandle`. PS/2 scancode sets 1, 2, 3 → Linux `KEY_*` in `ps2d/src/keymap.rs`. Mouse reports emit `EV_REL` (REL_X, REL_Y, REL_WHEEL, REL_HWHEEL) and `EV_KEY` (BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_SIDE, BTN_EXTRA) followed by `SYN_REPORT`. |
| Phase 1.3: usbhidd → redbear-hid-core | ✅ **DONE** (pre-existing) | usbhidd uses `redbear_hid_core::translate::translate_report`. HID usages mapped to Linux evdev codes in `redbear-hid-core/src/usage_table.rs` (BTN_MOUSE, BTN_JOYSTICK, REL_X, REL_Y, REL_WHEEL, REL_HWHEEL, ABS_*). |
| Phase 1.4: i2c-hidd → redbear-hid-core | ✅ **DONE** (pre-existing) | Same path as usbhidd. |
| Phase 1.5: intel-thc-hidd → redbear-hid-core | ✅ **DONE** (pre-existing) | Same path as usbhidd. |
| Phase 1.6: virtio-inputd → EvdevProducerHandle | ✅ **DONE** (pre-existing) | virtio-inputd uses `EvdevProducerHandle` directly via `write_evdev_event` adapter (line 253). Converts virtio_input_event → EV_KEY/EV_REL/EV_ABS/EV_SYN. No orbclient fallback. |
| Phase 1.7: evdevd consumes from /scheme/input/evdev | ✅ **DONE** (pre-existing) | evdevd opens `/scheme/input/evdev` for reading and relays 8-byte events to `/dev/input/eventN` for libinput. |
| Phase 1.7: evdevd consumes from /scheme/input-evdev | ✅ **DONE** (pre-existing) | evdevd opens `/scheme/input-evdev` for reading and relays 8-byte events to `/dev/input/eventN` for libinput. |
| Phase 1.8: config wiring for evdevd in init | ✅ **DONE** | `redbear-mini.toml` defines `10_evdevd.service` (inherited by `redbear-full.toml`); runs `evdevd` as `oneshot_async`. Initfs `10_inputd.service` updated to register `input/evdev` scheme. Rootfs `29_activate_console.service` overridden in `redbear-legacy-base.toml` to skip the obsolete `inputd -A 2` invocation. |
| Phase 1.9: udev-shim `/dev/input/eventN` mapping | ✅ **DONE (pre-existing)** | `local/recipes/system/udev-shim/source/src/scheme.rs:132-149` probes `/scheme/evdev/eventN` paths and creates `/dev/input/eventN` nodes for libinput. Heuristic: event0=keyboard, event1=mouse, others=generic. |
| Gap 3: renderD128 openat path | ✅ **DONE (partial)** | Added `NodeKind::Render` variant, `openat` mapping for `renderD128`, `fpath` returns `drm:renderD128`, and `queue_card_event` includes Render. Mesa can now open the render node. |
@@ -987,7 +987,7 @@ buffer. This is the change the plan now calls **v6.0**.
| Phase 3.5: redbear-compositor page flip fix | ✅ **DONE** | Renamed `DrmOutput._file` to `drm_file`; `flip()` now uses `&self.drm_file.write_all(&buf)` instead of reopening `/scheme/drm/card0` on every call. |
| `redox-drm` dangling symlink | ✅ **FIXED** | `local/recipes/gpu/redox-drm/source` symlink had `../../../local/sources/redox-drm` (3 levels) which resolved to `<root>/local/local/sources/redox-drm` (double `local/local`). Fixed to `../../../../local/sources/redox-drm` (4 levels). |
| `build-redbear.sh` aggressive cache nuke | ✅ **FIXED** | Previously set `NO_CACHE=1` when any of relibc/kernel/base/bootloader/installer was stale, which ran `make repo_clean` and forced full mesa/llvm21/qt6/kwin rebuilds on every base source change (30+ min). Now only deletes the specific stale package's pkgar and target dir. |
| Stale `input/evdev` consumer blocking evdevd | ✅ **RESOLVED** | Before v6.0, evdevd crashed with `failed to open /scheme/input/evdev: No such device`. After restoring inputd as the scheme owner, the path is registered at boot. |
| Stale `input/evdev` consumer blocking evdevd | ✅ **RESOLVED** | Before v6.0, evdevd crashed with `failed to open /scheme/input-evdev: No such device`. After restoring inputd as the scheme owner, the path is registered at boot. |
| `evdevd` listed in `redbear-full.toml` | ✅ **DONE** (pre-existing) | `10_evdevd.service` is defined in `redbear-mini.toml` and inherited. |
| `udev-shim` exposes `/dev/input/eventN` | ✅ **DONE** (pre-existing) | `local/recipes/system/udev-shim` creates the `/dev/input/event*` symlinks from the evdevd scheme. |
| Phase 0: QML JIT gate (unblocks KWin + 12 KF6 packages) | 🔴 BLOCKED | Qt6Quick/QML engineering required. Estimated 4-6 weeks. |
@@ -1002,10 +1002,10 @@ buffer. This is the change the plan now calls **v6.0**.
```
drivers (ps2d, usbhidd, i2c-hidd, intel-thc-hidd, virtio-inputd)
└─ write Linux struct input_event to /scheme/input/evdev
└─ write Linux struct input_event to /scheme/input-evdev
(inputd binary — multi-writer, single-reader ring buffer)
evdevd (pure scheme → /dev/input/eventN adapter)
└─ read from /scheme/input/evdev
evdevd (pure scheme → /dev/input/eventN adapter)
└─ read from /scheme/input-evdev
└─ expose /dev/input/eventN with full EVIOC ioctl support
libinput (in-process to KWin)
└─ read from /dev/input/event* as Linux native evdev
@@ -1369,7 +1369,7 @@ The v6.0 plan was produced in this session (2026-06-08) after:
| Section | v5.1 | v6.0 | Why |
|---------|------|------|-----|
| Scope | "Console → Wayland desktop on QEMU" | "Console → Full KDE Plasma on AMD64" | v6.0 targets the full desktop, not just a Wayland proof |
| Input architecture | inputd (Orbital) + evdevd (bridge) | **Unified**: both write to /scheme/input/orbclient and /scheme/input/evdev in parallel | Resolves the inputd/evdevd proliferation; matches CachyOS |
| Input architecture | inputd (Orbital) + evdevd (bridge) | **Unified**: both write to /scheme/input/orbclient and /scheme/input-evdev in parallel | Resolves the inputd/evdevd proliferation; matches CachyOS |
| Compositor | "Extend redbear-compositor to production" | **KWin is primary; redbear-compositor is greeter-only** | Realistic — KWin is a multi-year effort to match by hand-rolling |
| QML gate | Acknowledge but defer (Phase 7) | **Phase 0 (pre-flight): fix QML JIT to unblock the rest** | Without QML, no KWin, no Plasma, no real desktop |
| Audio | audiod as native replacement | **PipeWire + wireplumber + audiod bridge** | Matches CachyOS; audiod alone is not enough for phonon4qt |
@@ -1469,7 +1469,7 @@ Per the **NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)** (commits `
### 18.6 Architectural decisions documented
- **v6.0 unified input**: single evdev producer at `/scheme/input/evdev` (inputd ring buffer), consumed by evdevd, exposed as `/dev/input/eventN` for libinput.
- **v6.0 unified input**: single evdev producer at `/scheme/input-evdev` (inputd ring buffer), consumed by evdevd, exposed as `/dev/input/eventN` for libinput.
- **v6.0 compositor decision**: KWin is primary; redbear-compositor is greeter-only.
- **NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)**: Rule 1 for in-tree components, Rule 2 for big external projects.
- **12 Red Bear forks established** as durable source-of-truth.
@@ -1496,7 +1496,7 @@ honest (not a "100% complete" misrepresentation).
**Two non-negotiable architecture decisions (v6.0):**
1. **Unified input architecture**: every input driver writes to BOTH `/scheme/input/orbclient`
(for Orbital) and `/scheme/input/evdev` (for KWin + libinput). No more inputd↔evdevd bridge
(for Orbital) and `/scheme/input-evdev` (for KWin + libinput). No more inputd↔evdevd bridge
that loses metadata.
2. **KWin is the primary compositor**: redbear-compositor (788-line Rust) is too small to
@@ -2,7 +2,7 @@
name = "virtio-inputd"
version = "0.2.3"
edition = "2024"
description = "virtio-input daemon v6.0 2026: reads virtio-input PCI events and writes Linux evdev events to /scheme/input/evdev"
description = "virtio-input daemon v6.0 2026: reads virtio-input PCI events and writes Linux evdev events to /scheme/input-evdev"
[[bin]]
name = "virtio-inputd"
@@ -13,7 +13,7 @@
//! 2. Negotiate `VIRTIO_F_VERSION_1`.
//! 3. Set up one event virtqueue with 64 DMA-allocated event buffers.
//! 4. Drain used buffers, decode `VirtioInputEvent`, write Linux evdev events
//! to `/scheme/input/evdev` via `EvdevProducerHandle`.
//! to `/scheme/input-evdev` via `EvdevProducerHandle`.
//! 5. Recycle drained buffers to the avail ring and kick.
//!
//! ## Wire format
@@ -459,7 +459,7 @@ fn run_device() -> Result<()> {
let mut producer = match EvdevProducerHandle::new() {
Ok(p) => p,
Err(e) => {
warn!("virtio-inputd: failed to open /scheme/input/evdev: {e} — events will be dropped");
warn!("virtio-inputd: failed to open /scheme/input-evdev: {e} — events will be dropped");
return Err(DriverError::Io(format!("evdev producer unavailable: {e}")));
}
};
@@ -92,11 +92,11 @@ impl InputConsumer {
let file = OpenOptions::new()
.read(true)
.custom_flags(O_NONBLOCK as i32)
.open("/scheme/input/evdev")
.open("/scheme/input-evdev")
.map_err(|e| {
format!(
"failed to open /scheme/input/evdev: {e} (is evdevd's single-producer scheme registered? \
inputd is no longer the desktop input multiplexer as of v6.0)"
"failed to open /scheme/input-evdev: {e} (is inputd's single-producer scheme registered? \
inputd registers as 'input-evdev' as of v6.0)"
)
})?;
@@ -135,7 +135,7 @@ impl InputConsumer {
}
}
Err(err) if err.kind() == ErrorKind::WouldBlock => break,
Err(err) => return Err(format!("failed to read /scheme/input/evdev: {err}")),
Err(err) => return Err(format!("failed to read /scheme/input-evdev: {err}")),
}
}
@@ -319,7 +319,7 @@ fn run() -> Result<(), String> {
let socket =
Socket::nonblock("evdev").map_err(|e| format!("failed to register evdev scheme: {}", e))?;
info!("evdevd: registered scheme:evdev");
info!("evdevd: v6.0 single-producer mode — consuming Linux struct input_event from /scheme/input/evdev");
info!("evdevd: v6.0 single-producer mode — consuming Linux struct input_event from /scheme/input-evdev");
#[cfg(target_os = "redox")]
{
Submodule local/sources/base updated: cffacf5918...4c1fa35c72