Files
RedBear-OS/local/docs/USB-IMPLEMENTATION-PLAN.md
T
vasilito 05bb9095ce docs: USB-IMPLEMENTATION-PLAN.md v2 — mark P0-A1 done + P0-A2..B2 handoff
Update §5 phases table: P0-A1  committed (base fork cbd40e0d, 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
now cbd40e0d.

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).
2026-07-07 00:44:31 +03:00

38 KiB
Raw Blame History

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 P0P5 (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:
    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:101115 defines a complete get_int_method() that returns MSI-X, MSI, INTx, or Polling based on PCI capabilities. main.rs:141 then disables it:

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, SepOct 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, f58625b0usbhubd/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.
e3a13a0cxhcid and friends: use newtype PortId to ensure route string Type-safety win.
6ac41ee — daemon: tolerate BrokenPipe on ready() Already in our base fork.
258ea4e6, 865ca866usbscsid: 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 bounduhcid/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 signalusbhidd 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.mdredbear-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.rsXhci::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.rsdaemon_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.rsDeviceContextList, InputContext. local/sources/base/drivers/usb/xhcid/src/xhci/mod.rsXhci<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)