diff --git a/local/docs/HARDWARE-VALIDATION-MATRIX.md b/local/docs/HARDWARE-VALIDATION-MATRIX.md index 9edc9b46c1..ae0f87421d 100644 --- a/local/docs/HARDWARE-VALIDATION-MATRIX.md +++ b/local/docs/HARDWARE-VALIDATION-MATRIX.md @@ -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 | diff --git a/local/docs/USB-IMPLEMENTATION-PLAN.md b/local/docs/USB-IMPLEMENTATION-PLAN.md index e37807389b..6baa52b2ff 100644 --- a/local/docs/USB-IMPLEMENTATION-PLAN.md +++ b/local/docs/USB-IMPLEMENTATION-PLAN.md @@ -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) diff --git a/local/scripts/test-usb-hub-qemu.sh b/local/scripts/test-usb-hub-qemu.sh index 9f741a7c16..def3ca1edd 100755 --- a/local/scripts/test-usb-hub-qemu.sh +++ b/local/scripts/test-usb-hub-qemu.sh @@ -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 .'" >&2 echo " See $log_file" >&2 exit 1 fi