usb: P3-A complete — Linux hub.c enumeration state machine in usbhubd

Track base pointer to bd379e07 (usbhubd debounce/reset-wait/U0-wait/
wHubDelay + SET_ISOCH_DELAY, HubDescriptorV3 device_removable fix).

USB-IMPLEMENTATION-PLAN.md: P3-A marked CORE COMPLETE with the full
Linux equivalence inventory and documented follow-ups (USB 2.0 bitmaps,
SS.Inactive warm-reset loop, multi-TT, hub LPM). Hub gap-table row
updated (249 -> ~700 LoC with Linux state machine).

HARDWARE-VALIDATION-MATRIX.md: hub row updated — enumeration core
complete with 14 unit tests; runtime hub proof tracked under P8-B.
This commit is contained in:
2026-07-19 00:28:29 +09:00
parent efd745c073
commit bfd56bac7e
3 changed files with 55 additions and 21 deletions
+6 -1
View File
@@ -15,7 +15,12 @@
| AC97 | 🔲 | 🔲 | Basic driver |
| **Input** | | | |
| PS/2 | ✅ | 🔲 | QEMU keyboard/mouse work |
| USB HID | 🔲 | 🔲 | Hardened (P3), not validated on real HW |
| USB HID | | 🔲 | Keyboard/mouse autospawn via test-usb-qemu.sh (P1 hardening); not validated on real HW |
| **USB** | | | |
| xHCI host controller | ✅ | 🔲 | Interrupt-driven mode proven (test-xhci-irq-qemu.sh); 51-flag quirk table + HCCPARAMS2 gating (P2-A/B); 36-code error recovery (P2-C); not HW-validated |
| EHCI/UHCI/OHCI controllers | 🔲 | 🔲 | Compile clean; runtime enumeration proofs planned (P8-B) |
| USB storage (BOT) | ✅ | 🔲 | usbscsid autospawn + bounded sector readback proven (test-usb-storage-qemu.sh); guest-side write verify open |
| USB hub (non-root) | 🔲 | 🔲 | P3-A enumeration core complete (debounce/reset-wait/U0-wait/wHubDelay, 14 unit tests); runtime hub proof pending (P8-B test-usb-hub-qemu.sh) |
| **GPU/Display** | | | |
| VESA | ✅ | 🔲 | QEMU framebuffer works |
| virtio-gpu | ✅ | N/A | 2D only, QEMU |
+48 -19
View File
@@ -40,7 +40,7 @@ Where the v2 plan referenced Redox upstream commits, v3 references **Linux 7.1**
| Storage protocols | 1 (BOT) | 5+ (BOT, UAS, SAT, UASP, multi-LUN) | 4 missing |
| HID class features | Boot protocol only | Full report descriptor parsing, multi-touch, quirks | ~80% gap |
| Class drivers | 6 working (acm 133, ecm 261, audio 308, HID, storage, hub) | 80+ drivers | ~75 missing |
| Hub driver lines | 249 | 6,567 (hub.c) | ~95% gap |
| Hub driver lines | ~700 (usbhubd + port_ops) with Linux state machine | 6,567 (hub.c) | Enumeration core done (P3-A); interrupt EP/LED/TT gaps |
| xHCI quirks | 51 flags + ~85-entry canonical table (redox-driver-sys, P2-A); ~40 check sites in xhcid | 51 quirks | ✅ Done |
| Error recovery | All 36 codes with active recovery (P2-C core ✅); runtime injection tests open | Babble, transaction error, split error, clear-TT | Core done; validation gap |
| Power management | HW LPM substrate + U3 gate + PORTPMSC helpers (P2-B); per-device LPM, U1/U2, autosuspend missing | Runtime PM, U1/U2, LPM, autosuspend | Core missing |
@@ -316,31 +316,60 @@ stall injection, 10k random disconnects without panic).
**Why this matters:** The current usbhubd is 249 LoC doing basic port-change detection. Linux hub.c is 6,567 lines doing full enumeration. The gap is 95%.
### P3-A: Full enumeration sequence
### P3-A: Full enumeration sequence ✅ CORE COMPLETE (2026-07-18)
**Reference:** `local/reference/linux-7.1/drivers/usb/core/hub.c:1449` `hub_configure()` and `hub_port_connect()`.
**Tasks:**
**Status:** usbhubd (now ~700 LoC incl. `port_ops.rs`) implements the full
Linux port state machine with injected-side-effect, unit-tested ops
(14 tests). Enumeration of hub-attached devices remains delegated to
xhcid's `attach_device()` — architecturally correct (xhcid owns slot
allocation/addressing for root and hub ports alike).
1. Read hub descriptor (already done — `HubDescriptorV2` / `HubDescriptorV3`).
2. Power-on delay: `bPwrOn2PwrGood * 2ms` (USB 2.0 spec §7.1.6.1).
3. USB 3.0 hub initial state: wait for polling → U0 (tPollingLFPSTimeout = 360ms, polled 10×36ms).
4. Per-port enumeration:
- Reset signaling (USB 2 ≥10ms, USB 3 warm reset with PORT_WR)
- Wait for reset completion
- Read device descriptor (8 bytes → full 18 bytes)
- Set address
- Read configuration descriptors
- Configure endpoints
5. Hub-specific class requests for USB 3 hubs:
- `HUB_SET_DEPTH` (request 0x0C) — set hub tier depth
6. `wHubDelay` accumulation through the TT path (for split-transaction scheduling).
**Implemented (Linux hub.c equivalence):**
**Linux cross-reference:** `hub.c:1497-1521` for wHubDelay; `hub.c:3000-3300` for the full port-connect path.
1. ✅ Hub descriptor read (V2/V3) — pre-existing. **Fixed:** `HubDescriptorV3`
now reads the full 12-byte SS descriptor including `device_removable: u16`
(spec Table 10-15; previously under-read by 2 bytes; SS descriptors have
no PortPwrCtrlMask — stale TODO comment corrected). Non-removable ports
logged at startup.
2. ✅ Power-on delay `max(bPwrOn2PwrGood * 2ms, 100ms)` — pre-existing,
verified vs `hub_power_on_good_delay()` (hub.h:165-173).
3. ✅ USB 3.0 polling→U0 wait (`port_ops::wait_for_u0`) — after port
power-on, poll link state every 36 ms until out of Polling(7), 400 ms
ceiling (tPollingLFPSTimeout = 360 ms; Linux hub.c:1226 debounce path).
4. ✅ Per-port enumeration:
- Reset signaling + **completion wait** (`port_ops::wait_for_reset`) —
Linux `hub_port_wait_reset()` (hub.c:2953-3047): 10 ms polls until
RESET clears with CONNECTION set, escalate to 200 ms after two short
waits, 800 ms budget; then 50 ms TRSTRCY recovery (hub.c:3159) and
C_PORT_RESET clear. **Replaces** the previous bare `sleep(10ms)`.
- **Debounce** (`port_ops::debounce_until_connected`) — Linux
`hub_port_debounce_be_connected()` (hub.c:4696-4737): 25 ms polls,
connection stable for 100 ms, 2 s budget, change bit cleared in-loop.
- **Change-bit hygiene** — C_PORT_CONNECTION (debounce), C_PORT_RESET
(reset-wait), C_PORT_ENABLE (post-handling) all cleared per Linux
`port_event()` semantics; over-current recovery preserved.
- Address/descriptor/configuration — via xhcid `attach_device()`
(enable slot → address device → descriptors → driver spawn), the
same path as root-hub ports.
5. ✅ `HUB_SET_DEPTH` (0x0C) for USB 3 hubs — pre-existing.
6. ✅ `wHubDelay` chain accumulation — `port_ops::accumulate_hub_delay_ns`
(Linux hub.c:1507-1519: `wHubDelay + parent->hub_delay + 40ns`, cap
65535 ns). usbhubd walks the PortId ancestor chain fetching ancestor
V3 hub descriptors, then delivers the result to each newly attached
SuperSpeed child via `SET_ISOCH_DELAY` (USB 3.0 §9.4.11; Linux
message.c:1142-1158 — hubs and non-SS skipped; children inherit the
hub's accumulated delay verbatim per hub.c:5128-5129).
**Files:** `local/sources/base/drivers/usb/usbhubd/src/main.rs`
**Remaining (documented follow-ups):** USB 2.0 `device_removable`/
`PortPwrCtrlMask` variable-length bitmaps unparsed (separate fetch needed);
SS.Inactive warm-reset recovery loop (hub.c:5841-5868); multi-TT switching;
U1/U2 LPM on hub ports (P7); interrupt-EP usage on USB 3 hubs without one
(polling fallback works).
**Exit:** complete hub enumeration including power timing, USB 3 hub handling, and TT accumulation.
**Exit met:** complete hub enumeration including power timing, USB 3 hub
handling, and TT accumulation.
### P3-B: Hub interrupt-driven change detection