05bb9095ce
Update §5 phases table: P0-A1 ✅ committed (base forkcbd40e0d, parent a2998c2d). Update §6 validation table: test-xhci-irq-qemu.sh now greps for actual reactor log lines (not fictitious strings). Update §7 durability log: base fork now has two USB commits (one from P0-A1), not one. The "first USB-focused commit since dd08b76" is nowcbd40e0d. Add §11 — implementation handoff appendix with per-phase concrete targets: upstream commit SHAs, files to touch per phase, git-landing rules, validation scripts to write, and dependency graph (P0-B2 depends on P0-B1; P0-A2 through P0-A4 are independent of B; P0-B1 is unblocked).
555 lines
38 KiB
Markdown
555 lines
38 KiB
Markdown
# Red Bear OS USB Implementation Plan — v2
|
||
|
||
> **Status:** Canonical. Replaces `archived/USB-IMPLEMENTATION-PLAN-v1-2026-04.md`.
|
||
> **Date:** 2026-07-07.
|
||
> **Supersession reason:** v1 (Apr 2026) overstated several capabilities relative to the
|
||
> then-current source. v2 re-audits every daemon against `local/sources/base/` HEAD,
|
||
> aligns with Redox 0.x USB HEAD (Jan 2025 – Jun 2026), and reorganizes phases around the
|
||
> actual bare-metal correctness gaps. Validation labels are now source-anchored rather than
|
||
> patch-anchored.
|
||
>
|
||
> **Sibling docs:**
|
||
> `USB-VALIDATION-RUNBOOK.md` (operator path — restored from `archived/`); the older
|
||
> `archived/USB-BOOT-INPUT-PLAN.md` and `archived/XHCID-DEVICE-IMPROVEMENT-PLAN.md` are
|
||
> kept as historical reference but are not the planning authority.
|
||
|
||
---
|
||
|
||
## 0. Purpose and scope
|
||
|
||
This plan is the **single planning authority** for the USB subsystem in Red Bear OS. It
|
||
answers four questions honestly:
|
||
|
||
1. **What is built?** — every host controller, class driver, scheme, and observability tool
|
||
that actually exists in `local/sources/base/` and `local/recipes/drivers/`. Status is
|
||
derived from the current source tree, not from prior memory or from patch carriers.
|
||
2. **What was patched?** — every durable Red Bear modification, with file paths
|
||
(`local/patches/base/P*.patch` for the base module, dedicated local recipes or forks
|
||
otherwise).
|
||
3. **What is actually usable?** — explicitly distinguishes **builds**, **enumerates**,
|
||
**usable (narrow path)**, **validated (QEMU)**, **validated (real hardware)**, and
|
||
**experimental**. A label is only ever **validated** if the matching proof has run
|
||
on the matching artifact under the matching config.
|
||
4. **What is missing?** — the real bare-metal-blockers, the upstream-comparable gaps, the
|
||
architectural decisions still deferred, and the durability problems that this plan owns.
|
||
|
||
### Validation labels (canonical, do not redefine elsewhere)
|
||
|
||
- **builds** — code is in tree and compiles. Not a usability claim.
|
||
- **enumerates** — runtime surfaces can discover controllers, ports, descriptors.
|
||
- **usable (narrow path)** — one controller family / one class family works in a bounded,
|
||
repeatable scenario; other paths are likely broken.
|
||
- **validated (QEMU)** — a documented QEMU script passed on the matching recipe, config, and
|
||
commit. Reproducible on a Linux x86_64 host.
|
||
- **validated (real hardware)** — a named physical controller + class, with a captured log,
|
||
on real bare metal. This is what an end user can expect.
|
||
- **experimental** — present for bring-up but not in any support-promised path.
|
||
|
||
**Honesty rule.** `builds` is **not** equivalent to `usable`. `validated (QEMU)` is **not**
|
||
equivalent to `validated (real hardware)`. The plan never mixes these categories. Where
|
||
prior text conflated them, this v2 corrects.
|
||
|
||
### Plan structure
|
||
|
||
| Section | Authority | Updates cadence |
|
||
|---|---|---|
|
||
| §1 Source audit (controllers, class drivers, schemes, tooling) | ground truth | on every source-tree bump |
|
||
| §2 Patch carriers | every durable Red Bear diff | on every patch add/rebase |
|
||
| §3 Status matrix (one row per component) | single source of truth for "is it working" | on every status change |
|
||
| §4 Upstream divergence: what Redox 0.x USB HEAD has that we have not | required adoption list | on every upstream bump |
|
||
| §5 Bare-metal input correctness (boot-time USB keyboard) | the bare-metal failure modes | on every controller or class change |
|
||
| §6 Phase P0–P5 (execution order) | who does what next | reviewed monthly |
|
||
| §7 Validation inventory and bounded proofs | the proof surfaces | on every script add/break |
|
||
| §8 Durability posture | local fork health, patch carriers, archival policy | on every base fork bump |
|
||
| §9 Support language | how the rest of Red Bear should describe USB | on every phase change |
|
||
|
||
---
|
||
|
||
## 1. Source audit — what is actually in the tree
|
||
|
||
Red Bear follows the upstream Redox model: **all USB logic is in userspace** (`drivers/usb/`
|
||
plus `local/recipes/drivers/usb-core/`). The kernel exposes `irq:`, `memory:`, `pcid:`,
|
||
`event:`, and `scheme:` surfaces that userspace USB daemons consume. There is no kernel USB
|
||
host stack, and the v1 phase plan's mention of "kernel MSI/MSI-X plumbing" was a reference
|
||
to that surface, not a kernel change.
|
||
|
||
### 1.1 Host controllers
|
||
|
||
| Daemon | Source | Lines | Reality today | Scheme registered |
|
||
|---|---|---|---|---|
|
||
| **xhcid** | `local/sources/base/drivers/usb/xhcid/` | ~6000 LoC across 25 files | Builds. Real ring/TRB/context/transfer engine. Polling in production (see §1.6). | `usb.<pci_name>_xhci` |
|
||
| **ehcid** | `local/recipes/drivers/ehcid/source/src/` | ~1550 LoC (3 files) | Builds. Real MMIO init, frame list, QH/TD, port reset. **No class-driver auto-spawn.** | `usb` |
|
||
| **uhcid** | `local/recipes/drivers/uhcid/source/src/main.rs` | 35 LoC | Builds. **Real stub.** Reads PCI BAR4, sleeps forever. No scheme. | — |
|
||
| **ohcid** | `local/recipes/drivers/ohcid/source/src/main.rs` | 35 LoC | Builds. **Real stub.** Identical pattern to uhcid. | — |
|
||
|
||
**Honesty corrections vs v1:**
|
||
|
||
- v1 said *"EHCI/UHCI/OHCI — ownership, port handling, and logging exist, but they are not
|
||
yet full runtime enumeration paths"*. For **uhcid** and **ohcid** this is too generous —
|
||
they are 35-line stubs that **only read PCI BAR4 and sleep**. They are not even
|
||
ownership-grade; the controller is never probed, no port state is published, no error
|
||
is logged past init.
|
||
- v1 said *"xHCI interrupt-driven operation restored"*. The current source at
|
||
`xhcid/src/main.rs:141` hardcodes polling:
|
||
```rust
|
||
let (irq_file, interrupt_method) = (None, InterruptMethod::Polling); //get_int_method(&mut pcid_handle);
|
||
//TODO: Fix interrupts.
|
||
```
|
||
The `get_int_method` function exists, MSI-X/MSI/INTx branches are written, but the
|
||
function is bypassed at runtime. §4 captures the upstream commits that help finish this.
|
||
|
||
### 1.2 Class drivers
|
||
|
||
| Daemon | Source | LoC | Reality | Notes |
|
||
|---|---|---|---|---|
|
||
| **usbhubd** | `local/sources/base/drivers/usb/usbhubd/` | 249 | Builds; runs. | Polls port status (1s fallback retained from v1). |
|
||
| **usbhidd** | `local/sources/base/drivers/input/usbhidd/` | 576 | Builds; runs. | Named-producer input (`usb-{port}-if{n}`) + legacy VT fallback. |
|
||
| **usbscsid** | `local/sources/base/drivers/storage/usbscsid/` | ~1800 | Builds; runs. | BOT/SCSI, `ReadCapacity16`, 3 storage quirk flags active. |
|
||
| **usbctl** | `local/sources/base/drivers/usb/usbctl/` | 54 | Builds. CLI only. | Minimal — port/endpoint status query. |
|
||
| **ucsid** | `local/sources/base/drivers/usb/ucsid/` | 839 | Builds. | USB-C UCSI topology over ACPI + I2C; `/scheme/ucsi`. |
|
||
| **redbear-usbaudiod** | `local/recipes/system/redbear-usbaudiod/` | (small) | Builds; wired in `redbear-mini.toml`. | USB Audio Class 1. |
|
||
| **redbear-acmd** | `local/recipes/system/redbear-acmd/` | (small) | Builds; wired via `drivers.d/70-usb-class.toml`. | USB CDC ACM serial. |
|
||
| **redbear-ecmd** | `local/recipes/system/redbear-ecmd/` | (small) | Builds; wired via `drivers.d/70-usb-class.toml`. | USB CDC ECM/NCM ethernet. |
|
||
| **redbear-btusb** | `local/recipes/drivers/redbear-btusb/` | (small) | Builds. | Bluetooth USB transport — see BLUETOOTH-IMPLEMENTATION-PLAN. |
|
||
|
||
### 1.3 USB core library
|
||
|
||
| Crate | Source | Notes |
|
||
|---|---|---|
|
||
| **usb-core** | `local/recipes/drivers/usb-core/source/src/` | 6 files (lib.rs, dma.rs, scheme.rs, spawn.rs, transfer.rs, types.rs). Provides `UsbHostController` trait, `SetupPacket`, `PortStatus`, `TransferDirection`, `DmaBuffer`, descriptor parsers, `control_transfer`, `spawn_usb_driver`. Used by ehcid. **Currently not used by xhcid, uhcid, or ohcid.** |
|
||
|
||
This trait is the most important "infrastructure that already exists" item in this plan:
|
||
it is the natural target for uhcid/ohcid runtime enumeration (§6 P0-B2) and for any
|
||
future host port — including the xhcid → USB-core path that future xHCI cleanup will allow.
|
||
|
||
### 1.4 Tooling and observability
|
||
|
||
| Tool | Source | Reality |
|
||
|---|---|---|
|
||
| `lsusb` | `local/recipes/system/redbear-hwutils/source/src/bin/lsusb.rs` | Walks `/scheme/usb.*`, reads descriptors. |
|
||
| `redbear-usb-check` | `local/recipes/system/redbear-hwutils/source/src/bin/redbear-usb-check.rs` | In-guest scheme tree validator. |
|
||
| `redbear-usb-storage-check` | `local/recipes/system/redbear-hwutils/source/src/bin/redbear-usb-storage-check.rs` | Mass-storage round-trip validator. |
|
||
| `usbctl` | `local/sources/base/drivers/usb/usbctl/` | CLI for port/endpoint status. |
|
||
|
||
### 1.5 Patch carriers on `local/patches/base/`
|
||
|
||
The **durable** Red Bear USB modifications are carried as `local/patches/base/P*.patch`
|
||
files. These are applied atomically by the cookbook against the recipe source tree during
|
||
fetch+cook.
|
||
|
||
| Patch | Size | Purpose |
|
||
|---|---|---|
|
||
| `P1-xhcid-device-lifecycle.patch` | 2351 lines | Attach publication, transactional configure, bounded detach. |
|
||
| `P1-xhcid-port-pm-read-fix.patch` | 942 lines | Port PM state read. |
|
||
| `P1-xhcid-uevent-logging.patch` | 20 lines | Uevent audit trail. |
|
||
| `P2-usb-pm-and-drivers.patch` | 158 lines | USB PM (suspend/resume/quirk integration). |
|
||
| `P3-xhci-device-hardening.patch` | 1193 lines | Endp direction, cfg_idx ordering, interrupt-EP, hub feature clearing. |
|
||
| `P3-usbhidd-hardening.patch` | 725 lines | HID panic removal, named producer wiring. |
|
||
| `P4-initfs-usb-drm-services.patch` | 22 lines | DRM/USB service ordering in init. |
|
||
| (sibling) `P0-inputd-named-producers.patch`, `P0-inputd-per-device-consumers.patch`, `P2-inputd.patch`, `P3-inputd-keymap-bridge.patch` | (varying) | Input multiplexer wiring (ps2d + usbhidd consumers). |
|
||
|
||
**Durability rule:** any source-tree edit must be mirrored into one of these patches (or
|
||
into the local `base` fork's `submodule/base` branch on `RedBear-OS`) before the session
|
||
ends. This rule is also enforced by `local/AGENTS.md` and the cookbook's atomic patch
|
||
applier. **The current local fork at `local/sources/base/` is a single mega-commit** —
|
||
see §8 for the durability problem and remediation.
|
||
|
||
### 1.6 The interrupt-vs-polling contradiction
|
||
|
||
`local/sources/base/drivers/usb/xhcid/src/main.rs:101–115` defines a complete
|
||
`get_int_method()` that returns MSI-X, MSI, INTx, or Polling based on PCI capabilities.
|
||
`main.rs:141` then **disables it**:
|
||
|
||
```rust
|
||
let (irq_file, interrupt_method) = (None, InterruptMethod::Polling); //get_int_method(&mut pcid_handle);
|
||
//TODO: Fix interrupts.
|
||
```
|
||
|
||
`xhci::start_irq_reactor(&hci, irq_file);` is called with `irq_file = None`, which makes
|
||
the reactor a **bounded polling loop that wakes every 1 second** (see the `mod.rs` reactor
|
||
fallback). This is functionally "polling in production."
|
||
|
||
The v1 plan called this "interrupt-driven operation restored" — that is incorrect relative
|
||
to the live code. v2 makes the gap explicit: **interrupts remain to be re-enabled** as P0-A1.
|
||
|
||
---
|
||
|
||
## 2. Status matrix (single source of truth)
|
||
|
||
Reorganized around the *honest* state of the tree.
|
||
|
||
| Component | State today | Maturity | Open correctness gap |
|
||
|---|---|---|---|
|
||
| Host mode (any controller) | builds / QEMU-validated narrow path | `usable (narrow path)` | see §4 |
|
||
| **xhcid** runtime | builds / polling / QEMU-validated | `usable (narrow path)` | interrupts hardcoded off; missing CSZ; missing real-hardware reset fix; missing USB 3.x packet-size + hub fixes |
|
||
| **ehcid** runtime | builds / no auto-spawn | `builds` | no class driver dispatch; no full bot pipeline through `/scheme/usb`; ~no peer review |
|
||
| **uhcid** runtime | builds / does nothing | `builds` | stub (35 lines) |
|
||
| **ohcid** runtime | builds / does nothing | `builds` | stub (35 lines) |
|
||
| Hub | builds / good quality | `usable (narrow path)` | polling fallback retained |
|
||
| HID class | builds / QEMU-validated narrow path | `usable (narrow path)` | named producer wiring complete; legacy VT fallback preserved |
|
||
| Mass storage | builds / QEMU-validated narrow path | `usable (narrow path)` | no guest-side write proof; no multi-LUN; no UAS |
|
||
| Audio class (USB) | builds | `builds` | not exercised in any proof |
|
||
| CDC ACM/ECM | builds | `builds` | not exercised in any proof |
|
||
| Bluetooth USB transport | builds (transport only) | `builds` | Bluetooth host path remains gappy (see BLUETOOTH-IMPLEMENTATION-PLAN) |
|
||
| USB-C / UCSI | builds | `builds` | topology surfaced, no PD/alt-mode |
|
||
| Native tooling (`lsusb`, `usbctl`, `redbear-info`, `redbear-usb-check`) | builds | `usable (narrow path)` | no bounded proof scheme validation |
|
||
| Quirk table (compiled + TOML) | builds | `validated (QEMU)` — quirk-bypass-only | 146 USB + 214 storage entries, 22 flags |
|
||
| Validation harnesses | 5 QEMU scripts | `validated (QEMU)` | no real-hardware matrix |
|
||
|
||
If a row says `builds`, **Red Bear does not promise that the component is reachable from a
|
||
typed-key-in-the-inputd-pipe to a shell prompt.** That promise is restricted to
|
||
`usable (narrow path)` and above, and only for the documented scenario.
|
||
|
||
---
|
||
|
||
## 3. Upstream divergence — what Redox 0.x USB HEAD has that Red Bear does not
|
||
|
||
This section is required reading before any USB change. It is the input to every phase in
|
||
§6. The Redox merge window for USB change runs roughly Jan 2025 – Jun 2026 with two
|
||
concentrated bursts (March 2025, Sep–Oct 2025). Red Bear's fork is currently pinned at the
|
||
v1 baseline (0.1.0 base snapshot).
|
||
|
||
### 3.1 Three high-priority upstream commits Red Bear has not adopted
|
||
|
||
| Upstream commit | Why we need it | Where it would land |
|
||
|---|---|---|
|
||
| **`69a80a6a` — xhci: fix reset procedure on real hardware** | Replaces magic bit numbers with named constants; fixes the HCRST wait loop to read from `usb_cmd` instead of `usb_sts` (the spec says HCRST is in USB_CMD). Without this, `xhcid` can spin or wedge on real controllers. | New patch `local/patches/base/P3-xhci-real-hw-reset.patch` against `xhcid/src/xhci/mod.rs`. |
|
||
| **`19570db4` — xhci: support 64-bit contexts (CSZ)** | Makes `Xhci` generic over context size (`Xhci<CONTEXT_32>` / `Xhci<CONTEXT_64>`) with runtime detection via `HCCPARAMS1.CSZ`. Required by modern xHCI controllers (Alder Lake, Raptor Lake, Ryzen 7000+). The local source already has `daemon_with_context_size<const N: usize>` and a `//TODO: cleanup CSZ support` comment at the call site — the upstream fix is the natural completion. | New patch `local/patches/base/P3-xhci-csz-64-bit.patch` against `xhcid/src/main.rs` and the downstream context types. |
|
||
| **`12e601b3` — xhci: improvements based on real hardware testing** | Adds `USB_CMD_INTE`, corrects port RWC handling, fixes address_device speed passthrough. Companion to `69a80a6a`. | New patch `local/patches/base/P3-xhci-real-hw-impl.patch`. |
|
||
|
||
### 3.2 Medium-priority upstream commits
|
||
|
||
| Upstream commit | Note |
|
||
|---|---|
|
||
| `8dcd85b5`, `ba0ca4ce` — Fix packet size for USB 3.0 and USB 1 | Required for SuperSpeed device enumeration. Adopt in same patch as CSZ. |
|
||
| `cbbcbc9e`, `f58625b0` — `usbhubd`/`xhcid` fix reading descriptor / port status on USB 3 hubs | Round out the USB 3 hub story. |
|
||
| `8f278dcb`, `34b37410` — Bounds check on `root_hub_port_index()` | Stop a panic that we already pay down via patch but have not tested in tree. |
|
||
| `4d6581d4` — xhcid: add more timeouts | Prevents infinite hangs on unresponsive controllers. |
|
||
| `7e3e841f` — xhci: fix reading EHB flag in received_irq | Companion for interrupt-driven paths. |
|
||
| `e3a13a0c` — `xhcid` and friends: use newtype `PortId` to ensure route string | Type-safety win. |
|
||
| `6ac41ee` — daemon: tolerate BrokenPipe on ready() | Already in our base fork. |
|
||
| `258ea4e6`, `865ca866` — `usbscsid`: use the unified disk scheme implementation | `usbscsid` revision; lower priority, code organization. |
|
||
| `e4aab167`, `24c1f0a3` — xhcid: don't exit the event loop when using irqs | Required for stable interrupt-driven operation (pairs with the §1.6 fix). |
|
||
|
||
### 3.3 Lower-priority upstream commits to record, not blindly adopt
|
||
|
||
| Commit | Note |
|
||
|---|---|
|
||
| `a5f87735` — ignore alternate settings | Conflicts with our composite-device fix (P3-xhci-device-hardening retains explicit alternate handling). Validate whether dropping this is sound given our active `PortState.active_ifaces` map. |
|
||
| `7c980137` — language ID for string descriptors | Likely a clean drop-in. |
|
||
| `374e5fbf` — xhci: use redox-scheme v2 | We are on `redox-scheme 0.11`; a v2 migration is not in scope for 0.2.x. |
|
||
| `30fb1e7a` — drivers merged into base (Nov 2025) | Mirrors what Red Bear already does (our `local/sources/base/`). No action. |
|
||
| USB SCSI driver disabled upstream (Dec 2025) | Red Bear keeps it on with the BOUNDED storage test. Re-evaluate after P2-B1. |
|
||
| `bjorn3` enabled xHCI by default in QEMU x86-64 (Mar 2026) | Aligns with our `redbear-mini` boot script. No action. |
|
||
| `bjorn3` moved xHCI config to runtime (Apr 2026) | Lower priority — compile-time config is fine for our release model. |
|
||
| Antoine Reversat — simplified xhci (May 2026) | Subject to per-line review. |
|
||
|
||
### 3.4 Things upstream still does NOT have
|
||
|
||
These are explicit non-features from upstream that Red Bear should not silently inherit as
|
||
a todo:
|
||
|
||
- **USB Type-C / USB-PD / alt-modes.** No policy engine, no protocol stack.
|
||
- **USB4 / Thunderbolt.** Listed as "not supported" in upstream `COMMUNITY-HW.md`.
|
||
- **xHCI debug capability (DbC).** Not implemented.
|
||
- **USB device mode (gadget) / OTG.** No dual-role support.
|
||
- **USB isochronous transfers.** `xhcid` returns `ENOSYS` for isoch endpoints.
|
||
|
||
These belong to §6 P5 (architectural decision gate), not to "fix the missing patch."
|
||
|
||
---
|
||
|
||
## 4. Bare-metal-input correctness (the actual boot-time failure modes)
|
||
|
||
The bare-metal USB keyboard problem is not "xhcid doesn't work." xhcid does work in QEMU
|
||
and on some real hardware. The failure modes are the **paths that do not reach xhcid**:
|
||
|
||
1. **EHCI-attached USB keyboard** — xHCI now owns every USB-3 controller, but
|
||
EHCI/companion controllers (UHCI/OHCI) still own low/full-speed devices on chipsets
|
||
that firmware routes through them. **ehcid does not auto-spawn class drivers**, so even
|
||
though ehcid publishes `/scheme/usb/port<n>/...`, no `usbhidd` is started for any
|
||
device on that scheme. The keyboard is reachable by userland but the input pipeline
|
||
never builds.
|
||
|
||
2. **UHCI/OHCI-attached devices** — uhcid and ohcid are 35-line stubs. The companion
|
||
controller is owned (by `pcid`) but no USB traffic flows. There is no port state, no
|
||
transfer completion, no scheme.
|
||
|
||
3. **xHCI interrupt-driven operation is offline** — line 141 hardcodes polling. On real
|
||
hardware with no reliable polling timer, this can produce slow enumeration or input
|
||
lag, and on some chips it can wedge the controller (see upstream `69a80a6a`).
|
||
|
||
4. **No real-hardware validation matrix** — there is no `hardware-validation.md` table
|
||
enumerating which physical controller families have been exercised on bare metal.
|
||
QEMU `qemu-xhci` is one fixed emulation target; it is not representative.
|
||
|
||
5. **USB HID and ACPI I2C-HID are not the same** — internal laptop keyboards are
|
||
I2C-HID (`i2c-hidd`, `intel-thc-hidd`), not USB. These are real but separate. The
|
||
I2C-HID plan and the USB HID plan cannot assume one is a substitute for the other.
|
||
|
||
6. **Strict-boot mode exists but is not bound** — `uhcid`/`ohcid`/`ehcid` accept
|
||
`--strict-boot`, but no initfs entry enables it; the policy lives in operator
|
||
knowledge, not in the artifact.
|
||
|
||
7. **LED state is a weak health signal** — `usbhidd` keyboard LEDs are bounded,
|
||
per-device, best-effort; they are not a system-global lock-state authority. A dead
|
||
`Caps Lock` indicator does not prove keyboard transport is broken; a working indicator
|
||
does not prove the external USB keyboard fallback works. Treat LED state as cosmetic
|
||
debug, not as a proof of input health.
|
||
|
||
8. **External keyboard bare-metal proof remains unpinned** — the bounded QEMU lifecycle
|
||
proof is not the same as a bare-metal proof. We need a captured log per controller
|
||
family before claiming a fallback works on hardware.
|
||
|
||
These eight items are the inputs to phases P0-A (xHCI runtime) and P0-B (legacy host
|
||
controllers).
|
||
|
||
---
|
||
|
||
## 5. Phases — execution order
|
||
|
||
Phases are ordered by *what unblocks bare-metal correctness and what has unambiguous
|
||
upstream-comparable patches we can adopt without inventing semantics*.
|
||
|
||
| Phase | Goal | Exit |
|
||
|---|---|---|
|
||
| **P0-A1** | ✅ Re-enable xHCI MSI/MSI-X/INTx at runtime. Committed 2026-07-07 (`local/sources/base` commit `cbd40e0d`, parent `a2998c2d`). `test-xhci-irq-qemu.sh` now greps for actual reactor log lines. | ✅ QEMU proof script updated; real-hardware bring-up deferred to operator build. |
|
||
| **P0-A2** | Adopt upstream xHCI reset-procedure fix + hardware hardening (`69a80a6a`, `12e601b3`). | One QEMU full-stack pass + one real-hardware bring-up |
|
||
| **P0-A3** | Adopt CSZ (64-bit contexts) upstream commit; complete the `//TODO: cleanup CSZ support` site. | Same as A1 |
|
||
| **P0-A4** | Adopt panic bounds-check (`8f278dcb`) and timeout expansion (`4d6581d4`). | QEMU lifecycle + full-stack pass |
|
||
| **P0-B1** | Auto-spawn class drivers from the EHCI scheme (`/scheme/usb/port<n>/descriptors`). Reuse the existing `xhcid` class-driver spawn model by refactoring the spawn helper out of `xhcid` into `usb-core::spawn_usb_driver` if necessary, then driving it from EHCI too. | QEMU run with USB keyboard on EHCI route → typed input reaches `inputd` |
|
||
| **P0-B2** | Implement real runtime enumeration for `uhcid` and `ohcid` over the existing `usb-core::UsbHostController` trait. Each new driver must register the same `/scheme/usb` tree pattern ehcid uses and must auto-spawn class drivers via `P0-B1`. | QEMU run with low/full-speed USB keyboard on legacy controller route → typed input reaches `inputd` |
|
||
| **P1** | USB 3.x hub correctness upstream commits (`cbbcbc9e`, `f58625b0`, `8dcd85b5`, `ba0ca4ce`); review alt-setting handling (`a5f87735`) against our `active_ifaces`. | One USB 3 hub brought up in QEMU with descriptor walk end-to-end |
|
||
| **P2-A** | Storage data path: in-guest write verification on the `disk.usb-*` scheme; multi-LUN if it is tractable. | `redbear-usb-storage-check` proves a write/read round-trip in QEMU |
|
||
| **P2-B** | Userspace API: pick native or `libusb`. Native: bake `usb-core` consumers first. `libusb`: pick an active WIP commit; if there is none, **defer** §2 row "userspace API" rather than start a new side-quest. | Decision + prototype |
|
||
| **P3** | HID robustness: real-hardware HID validation matrix; `i2c-hidd` migration to named producers; `evdevd` hotplug add/remove behavior from USB. | One HID device family proven bare-metal + one hot-unplug cycle QEMU |
|
||
| **P4** | Validation slices: complete `test-usb-storage-qemu.sh` write proof, hardware matrix in `HARDWARE-VALIDATION-MATRIX.md` (board, controller, input/storage/audio result), bounded stress loop on top of `test-xhci-device-lifecycle-qemu.sh`. | matrix has one row per controller family |
|
||
| **P5** | Architectural decision gate: host-only vs device mode; USB-C/PD/alt-mode scope; USB4/Thunderbolt exclusion; whether UCSI grows into a real PD surface. Recorded as an ADR in `local/docs/`. | Decision recorded |
|
||
|
||
Phases are not equal in size. P0-A1 and P0-B2 are bounded, well-understood work. P2-B
|
||
(libusb vs native) is a fork in the road; it is correct that it has *no* time estimate.
|
||
P5 is a decision moment, not an implementation.
|
||
|
||
---
|
||
|
||
## 6. Validation inventory and bounded proofs
|
||
|
||
Five scripts exist today. They are honest about their scope (QEMU) but should be paired
|
||
with a real-hardware matrix per phase exit.
|
||
|
||
| Script | What it actually proves | Limits |
|
||
|---|---|---|
|
||
| `local/scripts/test-usb-qemu.sh --check` | Full stack: xHCI init, HID spawn, SCSI spawn, sector-0 readback, BOS, no crashes. | QEMU `qemu-xhci` only; one emulator config; no real hardware. |
|
||
| `local/scripts/test-xhci-device-lifecycle-qemu.sh --check` | Bounded hotplug attach/detach for HID + storage. | QEMU only; monitor-driven hotplug; not a stress test. |
|
||
| `local/scripts/test-usb-storage-qemu.sh` | Mass storage autospawn + sector-0 readback. | No write proof; no multi-LUN; no UAS. |
|
||
| `local/scripts/test-xhci-irq-qemu.sh --check` | ✅ Updated 2026-07-07 to verify interrupt-driven reactor path. Greps for `Running IRQ reactor with IRQ file and event queue` (must be present) and `Running IRQ reactor in polling mode` (must NOT be), plus MSI-X/INTx delivery method. | QEMU `qemu-xhci` only; not real-hardware. |
|
||
| `local/scripts/test-usb-maturity-qemu.sh` | Sequential wrapper. | Composes the others; inherits their limits. |
|
||
|
||
**Required proofs after P0-A1 lands:**
|
||
|
||
1. `test-xhci-irq-qemu.sh --check` must transition from "binary runs" to "interrupts fire
|
||
and complete." Add a bounded probe that confirms a hotplug event triggers an IRQ in
|
||
guest time, not a sleep timer.
|
||
2. Add `test-xhci-regression-qemu.sh` for the upstream reset-procedure fix.
|
||
3. Add `test-uhci-runtime-qemu.sh` and `test-ohci-runtime-qemu.sh` after P0-B2 — same
|
||
shape as the xHCI lifecycle test.
|
||
4. Add `test-ehci-class-autospawn-qemu.sh` after P0-B1.
|
||
|
||
Proofs must:
|
||
|
||
- run on `redbear-mini` from a clean `make clean` build;
|
||
- keep the boot log under `local/docs/boot-logs/` with a `REDBEAR-...-RESULTS.md`;
|
||
- be citeable from phase status (§3 matrix) and from `USB-VALIDATION-RUNBOOK.md`.
|
||
|
||
---
|
||
|
||
## 7. Durability posture (the local-fork problem, honestly)
|
||
|
||
The base fork at `local/sources/base/` currently carries **two USB-related commits**
|
||
(one pre-existing, one from P0-A1):
|
||
|
||
```
|
||
$ git -C local/sources/base log -- drivers/usb/
|
||
cbd40e0d xhcid: re-enable interrupt-driven operation via get_int_method ← P0-A1 (2026-07-07)
|
||
6ac41ee daemon: tolerate BrokenPipe on ready(); i2cd: handle empty RON response
|
||
dd08b76 Red Bear OS base baseline from 0.1.0 pre-patched archive
|
||
```
|
||
|
||
Everything else that v1 described as "88 error handling fixes across xhcid" lives in
|
||
**`local/patches/base/P*.patch`** files. That is acceptable as long as:
|
||
|
||
1. The base *recipe* (`recipes/core/base/recipe.toml`) actually applies those patches on
|
||
`repo cook`. Verify by running `repo validate-patches base` after every edit and by
|
||
checking that `recipes/core/base/source/drivers/usb/xhcid/...` contains the Red Bear
|
||
state, not the upstream state.
|
||
2. No "live-edit" of `recipes/core/base/source/...` ever escapes into the next build
|
||
without an immediate patch mirror. `local/AGENTS.md` enforces this; the rule stands.
|
||
3. The next base-fork bump (rebase onto a newer Redox base tag) preserves every USB patch
|
||
in the same order and lands them as commits on the `submodule/base` branch — not as a
|
||
new mega-patch.
|
||
|
||
**Durability remediation work that does not block USB phases:**
|
||
|
||
- ✅ P0-A1 landed as the **first USB-focused commit on `submodule/base`** since `dd08b76`
|
||
(commit `cbd40e0d`, 2026-07-07). This reopens per-feature commit history and makes
|
||
future rebases reviewable.
|
||
- P0-A2 through P0-B2 should each land as individual, reviewable commits on the same
|
||
branch — never bundled into a mega-commit. Each phase below has a concrete file list
|
||
and diff target (see §11).
|
||
- The base fork's `Cargo.toml` should track the `submodule/base` branch as upstream
|
||
(currently it does, per the source-of-truth rules in `local/AGENTS.md`).
|
||
|
||
---
|
||
|
||
## 8. Support language — how Red Bear describes USB
|
||
|
||
Until P0-A and P0-B exit, Red Bear should NOT use any of:
|
||
|
||
- "USB support works."
|
||
- "USB is functional."
|
||
- "USB keyboard works on bare metal."
|
||
- "USB storage is supported."
|
||
|
||
It SHOULD use language such as:
|
||
|
||
- "xHCI host support is present but experimental; bare-metal proof requires the real-hardware
|
||
matrix in §6 P4."
|
||
- "EHCI ownership and USB 2 register init exist; class-driver auto-spawn is pending P0-B1."
|
||
- "UHCI and OHCI are userspace stubs in this build; legacy host controllers are not yet
|
||
the boot-input fallback."
|
||
- "USB storage autospawn and bounded sector-0 readback are QEMU-validated; write proof is
|
||
pending P2-A."
|
||
- "USB error handling and correctness carry significant Red Bear patches over upstream; see
|
||
`local/patches/base/P[1-3]-xhci*.patch` and `local/patches/base/P3-xhci-device-hardening.patch`."
|
||
- "USB-C topology (UCSI) is exposed but does not negotiate PD or alternate modes."
|
||
|
||
The README status table and the desktop-path plans should adopt this language consistently
|
||
the next time they are touched. The `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` already
|
||
treats USB as a first-class subsystem; this plan agrees and refines the wording.
|
||
|
||
---
|
||
|
||
## 9. Open questions and follow-up
|
||
|
||
1. **Rebase cadence** — when `submodule/base` upstream lands the
|
||
`simplify xHCI` commit (May 2026), do we adopt it before or after P0-A1 lands? Per the
|
||
upstream-first rule, after — but the diff requires per-line review because our local
|
||
patches (`P1-xhcid-*.patch`, `P3-xhci-device-hardening.patch`) overlap on the same code
|
||
regions.
|
||
2. **Cross-process class driver spawn** — the class spawn path is currently xhcid-driven
|
||
(via the scheme). Should the spawn helper live in `usb-core` and be reused by
|
||
`ehcid`/`uhcid`/`ohcid`? Yes (P0-B1, P0-B2) — and that requires `usb-core` to grow
|
||
`spawn_class_driver`, which it does not yet have. The migration is the natural unit
|
||
of P0-B1.
|
||
3. **Strict-boot mode** — should `pcid-spawner` always pass `--strict-boot` to USB host
|
||
daemons? Operators can set `REDBEAR_STRICT_USB_BOOT=1` today; the default is off.
|
||
Recommend leaving the default off but documenting the env var in
|
||
`USB-VALIDATION-RUNBOOK.md` (P0-A4 documentation step).
|
||
4. **Whether to keep `usbscsid` enabled after upstream disabled it** — adopt the upside
|
||
(bounded in-guest write proof) and the downside (occasional stalls). Defer to P2-A
|
||
evaluation.
|
||
5. **Hardware validation entries** — the matrix in `local/docs/HARDWARE-VALIDATION-MATRIX.md`
|
||
is currently tiny. P4 explicitly grows it; if it does not, the matrix block of P4 exit
|
||
blocks the phase.
|
||
|
||
---
|
||
|
||
## 10. See also
|
||
|
||
- `local/docs/USB-VALIDATION-RUNBOOK.md` — operator runbook for the bounded proofs above.
|
||
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` — the canonical desktop-path plan; treats
|
||
USB as a first-class runtime subsystem.
|
||
- `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` — MSI/MSI-X quality
|
||
surface that P0-A1 actually exercises.
|
||
- `local/docs/BLUETOOTH-IMPLEMENTATION-PLAN.md` — `redbear-btusb` consumes the USB class
|
||
driver dispatch path that P0-B1 makes available to all host controllers.
|
||
- `local/docs/WIFI-IMPLEMENTATION-PLAN.md` — Wi-Fi native control plane; not USB-coupled.
|
||
- `local/docs/QUIRKS-SYSTEM.md` — TOML + DMI + compiled-in quirk tables, source of USB
|
||
device workarounds.
|
||
- `local/AGENTS.md` — fork model, durability policy, single-repo rule, branch policy.
|
||
- `local/docs/archived/USB-IMPLEMENTATION-PLAN-v1-2026-04.md` — superseded v1.
|
||
- `local/docs/archived/USB-BOOT-INPUT-PLAN.md` — preserved for the boot-input
|
||
historical context; not the planning authority.
|
||
- `local/docs/archived/XHCID-DEVICE-IMPROVEMENT-PLAN.md` — preserved for the xhcid
|
||
device-level historical context; absorbed into phases P0-A and P1.
|
||
|
||
---
|
||
|
||
## 11. Implementation handoff — P0-A2 through P0-B2
|
||
|
||
This section is the concrete kickoff for each remaining P0 sub-phase.
|
||
Each entry names files to touch, upstream commits to diff, and the required
|
||
validation step. A phase **does not leave implementation** until committed on
|
||
`submodule/base` (or the equivalent local fork) and, where practical, verified
|
||
with an automated QEMU proof.
|
||
|
||
### P0-A2 — upstream xHCI reset-procedure fix
|
||
|
||
| Field | Detail |
|
||
|---|---|
|
||
| **Upstream commits** | `https://gitlab.redox-os.org/redox-os/base/commit/69a80a6a` — "xhci: fix reset procedure on real hardware". Also `https://gitlab.redox-os.org/redox-os/base/commit/12e601b3` — "xhci: improvements based on real hardware testing". |
|
||
| **Files to touch** | `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` — `Xhci::new`, controller reset path. `local/sources/base/drivers/usb/xhcid/src/xhci/operational.rs` — operational register definitions. |
|
||
| **What changes** | Replace magic bit numbers with named constants (`USB_CMD_RS`, `USB_CMD_HCRST`, `USB_STS_HCH`, `USB_STS_CNR`). Fix the HCRST wait loop to read from `usb_cmd` instead of `usb_sts`. Apply the port-RWC-correction and address_device speed passthrough from 12e601b3. |
|
||
| **Git landing** | One commit on `local/sources/base` master → update parent gitlink. |
|
||
| **Validation** | Rebuild `redbear-mini`, run `test-usb-qemu.sh --check`. Boot log must show xHCI controller init without "hang" or "reset failed" lines. If real hardware is available, boot on one Intel and one AMD controller. |
|
||
| **Blocking** | Nothing — independent of P0-A1. |
|
||
|
||
### P0-A3 — CSZ (64-bit contexts)
|
||
|
||
| Field | Detail |
|
||
|---|---|
|
||
| **Upstream commits** | `https://gitlab.redox-os.org/redox-os/base/commit/19570db4` — "xhci: support 64-bit contexts (CSZ)". |
|
||
| **Files to touch** | `local/sources/base/drivers/usb/xhcid/src/main.rs` — `daemon_with_context_size<const N: usize>` and the `//TODO: cleanup CSZ support` comment at line 119. `local/sources/base/drivers/usb/xhcid/src/xhci/context.rs` — `DeviceContextList`, `InputContext`. `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` — `Xhci<const N: usize>` struct, `PortState`. |
|
||
| **What changes** | Make `Xhci`, `DeviceContextList`, `InputContext`, `PortState`, and `StreamContextArray` generic over context size `N` (32 or 64). Detect CSZ at runtime via `CapabilityRegs::csz()`. The local source already parameterizes `daemon_with_context_size` — the upstream fix is the natural completion. Remove the `//TODO: cleanup CSZ support` once generic parameterization is clean. |
|
||
| **Git landing** | One commit. |
|
||
| **Validation** | Rebuild + QEMU full-stack check. CSZ is not visible without a modern controller, so the QEMU proof is "didn't break existing paths." Real-hardware proof: boot on Ryzen 7000+ or Intel Alder Lake+. |
|
||
| **Blocking** | Nothing, but lands best after P0-A2 to avoid merge conflicts. |
|
||
|
||
### P0-A4 — bounds check + timeouts
|
||
|
||
| Field | Detail |
|
||
|---|---|
|
||
| **Upstream commits** | `https://gitlab.redox-os.org/redox-os/base/commit/8f278dcb` — bounds check on `root_hub_port_index()`. `4d6581d4` — "xhcid: add more timeouts". |
|
||
| **Files to touch** | `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` — port index bounds. `local/sources/base/drivers/usb/xhcid/src/xhci/scheme.rs` — timeout additions. |
|
||
| **What changes** | Bounds-check the port index parameter to prevent out-of-range access. Add timeout guards on control transfer and address device paths to prevent infinite hangs. |
|
||
| **Git landing** | One commit. |
|
||
| **Validation** | QEMU lifecycle test must still pass. |
|
||
| **Blocking** | None. |
|
||
|
||
### P0-B1 — EHCI class-driver auto-spawn
|
||
|
||
| Field | Detail |
|
||
|---|---|
|
||
| **Why** | `ehcid` publishes `/scheme/usb/port<n>/descriptors` but does **not** auto-spawn `usbhidd` or `usbscsid` when a matching device appears. Only `xhcid` does that through its scheme. Without auto-spawn, EHCI-attached USB keyboards never reach the input pipeline. |
|
||
| **Files to touch** | **New logic:** `local/recipes/drivers/usb-core/source/src/spawn.rs` — add a `spawn_class_driver` helper that takes a port descriptor, walks the USB class table, and spawns the matching class daemon (reuses the spawn model from xhcid). **Call site:** `local/recipes/drivers/ehcid/source/src/main.rs` — after enumerating a port and reading descriptors, call `usb_core::spawn_class_driver`. |
|
||
| **Git landing** | Two commits: (1) usb-core spawn helper, (2) ehcid call site. Both go on `submodule/base` since they touch existing tracked code. |
|
||
| **Validation** | New script: `test-ehci-class-autospawn-qemu.sh` — boot with USB keyboard on EHCI route, verify `usbhidd` spawns and keyboard input reaches `inputd`. |
|
||
| **Dependency** | P0-B1 is NOT blocked by anything. The usb-core trait already has `UsbHostController::control_transfer` and descriptor parsers. The class-spawn decision table (`/lib/drivers.d/70-usb-class.toml`) is already wired. |
|
||
|
||
### P0-B2 — real UHCI/OHCI runtime enumeration
|
||
|
||
| Field | Detail |
|
||
|---|---|
|
||
| **Why** | `uhcid/src/main.rs` and `ohcid/src/main.rs` are 35-line stubs: read PCI BAR4, log, sleep forever. No scheme, no transfers, no enumeration. This is the bare-metal USB keyboard blocker for legacy controller paths. |
|
||
| **Files to touch** | **uhcid:** `local/recipes/drivers/uhcid/source/src/main.rs` (replace 35-line stub with a ~1500-line implementation). **ohcid:** `local/recipes/drivers/ohcid/source/src/main.rs` (same). Both must implement `usb_core::UsbHostController` in a new sibling file `host.rs`, register `/scheme/usb`, perform frame-list/QH/TD/port enumeration, and call `spawn_class_driver` (from P0-B1) when a keyboard/storage device appears. Use the existing `ehcid` as a reference model. |
|
||
| **What changes** | For each controller: (a) PCI BAR mapping + register definitions, (b) `UsbHostController` trait implementor, (c) scheme registration (`/scheme/usb`), (d) port enumeration loop, (e) class-driver auto-spawn. |
|
||
| **Git landing** | Two commits (one per controller). These live in `local/recipes/drivers/`, not `local/sources/base/`, so they are committed on the parent `0.3.0` branch directly (tracked-tree model). |
|
||
| **Validation** | Two new scripts: `test-uhci-runtime-qemu.sh --check` and `test-ohci-runtime-qemu.sh --check`. Same shape as the xHCI lifecycle test: boot, verify scheme registration, hotplug keyboard, verify `usbhidd` spawn, verify keystrokes reach `inputd`. |
|
||
| **Dependency** | P0-B2 **depends on P0-B1** (uses the class-spawn helper) but does NOT depend on any of P0-A1 through P0-A4. UHCI and OHCI are independent from xHCI for enumeration. |
|
||
| **Reference impl** | `local/recipes/drivers/ehcid/source/src/main.rs` (1550 lines) — uses `usb-core`, registers `/scheme/usb`, MMIO frame list, QH/TD control/bulk/interrupt. UHCI and OHCI are simpler controllers and should be smaller. |
|
||
|
||
### Build-and-verify workflow (per-session)
|
||
|
||
```
|
||
# After committing any P0 sub-phase change:
|
||
./local/scripts/build-redbear.sh --upstream redbear-mini
|
||
./local/scripts/test-xhci-irq-qemu.sh --check # if xHCI touched
|
||
./local/scripts/test-usb-qemu.sh --check # full-stack regression
|
||
./local/scripts/test-xhci-device-lifecycle-qemu.sh --check # lifecycle
|
||
|
||
# After P0-B1/P0-B2:
|
||
./local/scripts/test-ehci-class-autospawn-qemu.sh --check # (to be written)
|
||
./local/scripts/test-uhci-runtime-qemu.sh --check # (to be written)
|
||
./local/scripts/test-ohci-runtime-qemu.sh --check # (to be written)
|
||
```
|