usb: hub-child enumeration proven end-to-end in QEMU + tighten hub test
The usb-kbd behind the QEMU usb-hub now enumerates fully: debounce -> port reset -> enable -> second debounce -> pre-attach -> attach -> ATTACH 5.2 -> slot 3 -> addressed -> descriptors read -> HID class match -> 'Loading subdriver "USB HID" for port 5.2' (class 3.1 proto 1, keyboard boot protocol). Root cause of the final stall: an unconditional SetPortFeature (PORT_INDICATOR) for every connected+enabled port NAK-hung on QEMU's indicator-less hub (no control-transfer timeout), blocking the flow before the post-enable debounce. Now gated on wHubCharacteristics.HUB_CHAR_PORTIND like Linux has_indicators. test-usb-hub-qemu.sh: check #5 now requires the hub-child subdriver line ('Loading subdriver "USB HID" for port <root>.<child>') so a root-port HID (tablet) can no longer satisfy it — closes a false- positive hole. Timeout raised to 360s for slow TT-path driver bring-up. Docs (plan P3-A runtime validation + matrix): full hub + hub-child chain recorded as QEMU-proven; remaining items (intermittent reactor startup race, slow TT-path Evaluate Context) noted.
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
| 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) | ✅ | 🔲 | Hub enumeration chain proven in QEMU (test-usb-hub-qemu.sh): descriptor, EP1 change detection, initial scan, debounce, reset→enable; hub-child device enumeration (kbd→HID) blocked on xhcid TT/debug path |
|
||||
| USB hub (non-root) | ✅ | 🔲 | Hub + hub-child enumeration proven in QEMU (test-usb-hub-qemu.sh): hub descriptor/EP1/scan/debounce/reset→enable, and usb-kbd behind hub enumerates to HID subdriver (class 3.1 keyboard); intermittent xhcid reactor startup race noted |
|
||||
| **GPU/Display** | | | |
|
||||
| VESA | ✅ | 🔲 | QEMU framebuffer works |
|
||||
| virtio-gpu | ✅ | N/A | 2D only, QEMU |
|
||||
|
||||
@@ -372,25 +372,27 @@ U1/U2 LPM on hub ports (P7); interrupt-EP usage on USB 3 hubs without one
|
||||
handling, and TT accumulation.
|
||||
|
||||
**Runtime validation (2026-07-19, `test-usb-hub-qemu.sh` on QEMU
|
||||
`usb-hub` + `usb-kbd` behind it):** the full usbhubd chain is proven at
|
||||
runtime — hub descriptor read (8 ports), EP1 interrupt-driven change
|
||||
detection, initial full port scan, connection debounce, port reset with
|
||||
completion wait, and port enable all observed in the boot log. The proof
|
||||
also surfaced and we fixed five latent bugs: the xhcid scheme refused
|
||||
port-dir opens for unenumerated hub children (attach bootstrap
|
||||
deadlock), a status-bitmap off-by-one (bit N−1 vs spec's bit N), a
|
||||
missing initial scan (daemon could block on EP1 before ever polling),
|
||||
an unbounded EP1 wait (state changes during synchronous waits produce
|
||||
no new interrupt), and a debounce that could deadlock on a hung
|
||||
C_PORT_CONNECTION clear (stability is now judged on connection state,
|
||||
with the change bit cleared post-attach). QEMU's hub stalls
|
||||
ClearPortFeature on change indicators — handled gracefully by the P2-C
|
||||
stall recovery (best-effort, no crash). **Remaining gap:** the hub-child
|
||||
device (usb-kbd) reaches `enabled: true` but does not complete
|
||||
enumeration to a HID driver — xhcid's hub-child attach path progresses
|
||||
only at debug level and needs TT/route investigation with debug
|
||||
logging. Also observed: an intermittent xhcid IRQ-reactor startup race
|
||||
(one boot showed no reactor start; retry passed).
|
||||
`usb-hub` + `usb-kbd` behind it):** the full chain is proven at runtime,
|
||||
for the hub AND for a device behind it. Hub: descriptor read (8 ports),
|
||||
EP1 interrupt-driven change detection, initial full port scan. Hub-child
|
||||
(usb-kbd): connection debounce → port reset with completion wait → port
|
||||
enable → attach → xHCI slot/address/descriptor enumeration → HID class
|
||||
match → `Loading subdriver "USB HID" for port 5.2` (class 3.1 proto 1,
|
||||
keyboard boot protocol). The proof surfaced and we fixed seven latent
|
||||
bugs: the xhcid scheme refused port-dir opens for unenumerated hub
|
||||
children (attach bootstrap deadlock), a status-bitmap off-by-one
|
||||
(bit N−1 vs spec's bit N), a missing initial scan (daemon could block
|
||||
on EP1 before ever polling), an unbounded EP1 wait (state changes during
|
||||
synchronous waits produce no new interrupt), a debounce that could
|
||||
deadlock on a hung C_PORT_CONNECTION clear (stability now judged on
|
||||
connection state, change bit cleared post-attach), an unconditional
|
||||
PORT_INDICATOR SetPortFeature that NAK-hung on indicator-less hubs
|
||||
(now gated on wHubCharacteristics.HUB_CHAR_PORTIND like Linux
|
||||
has_indicators), and QEMU's ClearPortFeature stall on change indicators
|
||||
(handled gracefully by P2-C stall recovery). **Remaining:** an
|
||||
intermittent xhcid IRQ-reactor startup race (some boots lose it; retry
|
||||
passes), and hub-child class-driver bring-up is slow on QEMU's emulated
|
||||
TT path (~13s for the hub-child Evaluate Context).
|
||||
|
||||
### P3-B: Hub interrupt-driven change detection ✅ COMPLETE (verified 2026-07-18)
|
||||
|
||||
|
||||
@@ -161,12 +161,14 @@ if [[ "$check_mode" -eq 1 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 5. HID class driver spawned — the usb-kbd sits BEHIND the hub, so
|
||||
# a registered producer proves the hub port enumeration chain
|
||||
# (power-on → debounce → reset-wait → attach → xhcid enumerate).
|
||||
if ! grep -q "registered producer" "$log_file"; then
|
||||
echo "ERROR: usbhidd did not register — child enumeration behind hub failed" >&2
|
||||
echo " Expected fragment: 'registered producer'" >&2
|
||||
# 5. Hub-child enumeration: the usb-kbd sits BEHIND the hub (QEMU port
|
||||
# 1.2, a dotted PortId). Requiring the hub-child subdriver line proves
|
||||
# the full chain (power-on → debounce → reset-wait → enable → attach →
|
||||
# xhcid enumerate → class match). A root-port HID (the tablet on port 2)
|
||||
# must NOT satisfy this — the match is on the hub-child "5.2" form.
|
||||
if ! grep -Eq 'Loading subdriver "USB HID" for port [0-9]+\.[0-9]+' "$log_file"; then
|
||||
echo "ERROR: hub-child (usb-kbd behind hub) did not enumerate to a HID driver" >&2
|
||||
echo " Expected: 'Loading subdriver \"USB HID\" for port <root>.<child>'" >&2
|
||||
echo " See $log_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user