diff --git a/README.md b/README.md index 60d19411c5..d121ca4975 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ successfully on branch `0.3.1`. Graphics packages are frozen at latest upstream | KWin | ๐ŸŸก Builds successfully (redox-drm + Qt6 Wayland); runtime blocked by Qt6 Wayland crash in `wl_proxy_add_listener` | | KDE Plasma | ๐Ÿ”ด Runtime blocked by Qt6 Wayland null+8 crash โ€” depends on KWin | | Wiโ€‘Fi (Intel iwlwifi) | ๐ŸŸก VFIO/passthrough bounded runtime validation framework exists | -| USB / Bluetooth | ๐Ÿ”ด USB maturity work in progress; Bluetooth controller path planned | +| USB / Bluetooth | ๐ŸŸก xHCI mature in QEMU: 51-flag quirks, capability gating, 36-code error recovery, Linux hub enumeration state machine; storage BOT proven; hub runtime proof + UAS/HID expansion open; Bluetooth controller path planned | **Where help is most wanted:** Qt6 Wayland protocol crash โ€” the #1 blocker for graphical desktop ยท AMD/Intel GPU hardware validation on bare metal ยท USB controller maturity ยท Wiโ€‘Fi native control plane ยท cub AUR pipeline hardening ยท package maintainers for the growing recipe catalog ยท tlc VFS remote backends and archive support diff --git a/local/docs/USB-IMPLEMENTATION-PLAN.md b/local/docs/USB-IMPLEMENTATION-PLAN.md index 886e973fe2..b71b825ae3 100644 --- a/local/docs/USB-IMPLEMENTATION-PLAN.md +++ b/local/docs/USB-IMPLEMENTATION-PLAN.md @@ -371,30 +371,30 @@ U1/U2 LPM on hub ports (P7); interrupt-EP usage on USB 3 hubs without one **Exit met:** complete hub enumeration including power timing, USB 3 hub handling, and TT accumulation. -### P3-B: Hub interrupt-driven change detection +### P3-B: Hub interrupt-driven change detection โœ… COMPLETE (verified 2026-07-18) **Reference:** `linux-7.1/drivers/usb/core/hub.c:1000+` `hub_irq()`. -Current usbhubd polls at 100ms intervals. Linux uses hub interrupt endpoints (`USB_ENDPOINT_DIR_IN` + `USB_USAGE_TYPE_INTERRUPT`) for immediate change notification. +**Status:** Implemented (predates the P3-A pass; verified during it). +~~Current usbhubd polls at 100ms intervals~~ โ€” stale premise; usbhubd is +interrupt-driven today: -**Tasks:** +1. โœ… EP1 interrupt endpoint discovered and opened (`EndpointTy::Interrupt` + `EndpDirection::In`). +2. โœ… Status-change bitmap read via `transfer_read()`; per-bit port dispatch (Linux `hub_irq()` โ†’ `kick_hub_wq` equivalent). +3. โœ… Fallback to full polling (200 ms) only when EP1 is absent or fails โ€” matches the exit criterion for USB 3 hubs without interrupt endpoints. -1. Add interrupt endpoint configuration to usbhubd (USB hub interrupt endpoint is always EP1). -2. Subscribe to interrupt IN transfers for status change bitmap. -3. Fall back to polling only when interrupt endpoint is unavailable. +**Exit met:** interrupt-driven on USB 2 hubs; polling fallback otherwise. -**Exit:** interrupt-driven on USB 2 hubs; polling fallback on USB 3 hubs (which lack interrupt endpoints). - -### P3-C: Port LED control +### P3-C: Port LED control โœ… HUB-SIDE COMPLETE (verified 2026-07-18) **Reference:** `linux-7.1/drivers/usb/host/xhci-port.h:64-67` (PORT_LED_OFF/AMBER/GREEN). -**Tasks:** +**Status:** Hub-side done โ€” usbhubd sets `SetPortFeature(PORT_INDICATOR)` +on connected+enabled+!resetting ports in the event loop. -1. Expose hub port LED control via `SET_HUB_FEATURE(PORT_INDICATOR)`. -2. Implement in usbhidd keyboard LED sync (cross-couple with P5-C). - -**Exit:** port LEDs controllable via scheme. +**Remaining (P5-C scope, not P3):** keyboard LED state sync in usbhidd +(Caps/Num/Scroll Lock โ†’ HID SET_REPORT output), cross-coupled with the +input stack. --- diff --git a/local/scripts/test-usb-hub-qemu.sh b/local/scripts/test-usb-hub-qemu.sh new file mode 100755 index 0000000000..db1a710e80 --- /dev/null +++ b/local/scripts/test-usb-hub-qemu.sh @@ -0,0 +1,190 @@ +#!/usr/bin/env bash +# Launch or validate USB hub enumeration (P3-A state machine) in QEMU. +# +# Topology under test: +# qemu-xhci root port 1 โ†’ usb-hub (USB 2.0, 8 ports) +# โ””โ”€ hub port 2 โ†’ usb-kbd +# qemu-xhci root port 2 โ†’ usb-tablet (control case, direct attach) +# +# Validates: hub descriptor read, usbhubd spawn, EP1 change detection or +# polling fallback, power-on, debounce, reset-wait, attach delegation to +# xhcid, child enumeration behind the hub (usbhidd spawn), no panics. + +set -euo pipefail + +find_uefi_firmware() { + local candidates=( + "/usr/share/ovmf/x64/OVMF.4m.fd" + "/usr/share/OVMF/x64/OVMF.4m.fd" + "/usr/share/ovmf/x64/OVMF_CODE.4m.fd" + "/usr/share/OVMF/x64/OVMF_CODE.4m.fd" + "/usr/share/ovmf/OVMF.fd" + "/usr/share/OVMF/OVMF_CODE.fd" + "/usr/share/qemu/edk2-x86_64-code.fd" + ) + local path + for path in "${candidates[@]}"; do + if [[ -f "$path" ]]; then + printf '%s\n' "$path" + return 0 + fi + done + return 1 +} + +usage() { + cat <<'USAGE' +Usage: test-usb-hub-qemu.sh [--check] [config] + +Boot or validate USB hub enumeration (usbhubd P3-A state machine) on a +Red Bear image in QEMU. Defaults to redbear-mini. +USAGE +} + +check_mode=0 +config="redbear-mini" +for arg in "$@"; do + case "$arg" in + --help|-h|help) + usage + exit 0 + ;; + --check) + check_mode=1 + ;; + redbear-*) + config="$arg" + ;; + esac +done + +firmware="$(find_uefi_firmware)" || { + echo "ERROR: no usable x86_64 UEFI firmware found" >&2 + exit 1 +} + +arch="${ARCH:-$(uname -m)}" +image="build/$arch/$config/harddrive.img" +extra="build/$arch/$config/extra.img" + +if [[ ! -f "$image" ]]; then + echo "ERROR: missing image $image" >&2 + echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 + exit 1 +fi + +if [[ ! -f "$extra" ]]; then + truncate -s 1g "$extra" +fi + +pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true +sleep 1 + +if [[ "$check_mode" -eq 1 ]]; then + log_file="build/$arch/$config/usb-hub-check.log" + rm -f "$log_file" + set +e + timeout 180s qemu-system-x86_64 \ + -name "Red Bear OS x86_64" \ + -device qemu-xhci,id=xhci \ + -device usb-hub,bus=xhci.0,port=1 \ + -device usb-kbd,bus=xhci.0,port=1.2 \ + -device usb-tablet,bus=xhci.0,port=2 \ + -smp 4 \ + -m 2048 \ + -bios "$firmware" \ + -chardev stdio,id=debug,signal=off,mux=on \ + -serial chardev:debug \ + -mon chardev=debug \ + -machine q35 \ + -device ich9-intel-hda -device hda-output \ + -device virtio-net,netdev=net0 \ + -netdev user,id=net0 \ + -nographic -vga none \ + -drive file="$image",format=raw,if=none,id=drv0,snapshot=on \ + -device nvme,drive=drv0,serial=NVME_SERIAL \ + -drive file="$extra",format=raw,if=none,id=drv1,snapshot=on \ + -device nvme,drive=drv1,serial=NVME_EXTRA \ + -enable-kvm -cpu host \ + > "$log_file" 2>&1 + status=$? + set -e + + fail=0 + + # 1. xhcid detected the controller. + if ! grep -q "^.*XHCI " "$log_file"; then + echo "ERROR: xHCI controller not detected in boot log; see $log_file" >&2 + exit 1 + fi + + # 2. usbhubd spawned for the hub device. + if ! grep -q "USB HUB driver spawned" "$log_file"; then + echo "ERROR: usbhubd did not spawn for the QEMU usb-hub" >&2 + echo " Expected: 'USB HUB driver spawned'" >&2 + echo " See $log_file" >&2 + exit 1 + fi + + # 3. Hub descriptor read succeeded (QEMU usb-hub exposes 8 ports). + if ! grep -q "usbhubd: 8 port(s) detected" "$log_file"; then + echo "ERROR: hub descriptor read failed or wrong port count" >&2 + echo " Expected: 'usbhubd: 8 port(s) detected'" >&2 + grep -i "usbhubd" "$log_file" | tail -10 >&2 || true + echo " See $log_file" >&2 + exit 1 + fi + + # 4. Change detection is active (interrupt EP or polling fallback). + if ! grep -Eq "interrupt endpoint opened for change detection|no interrupt endpoint found, using polling|interrupt endpoint open failed .*falling back to polling" "$log_file"; then + echo "ERROR: usbhubd did not report a change-detection mode" >&2 + echo " See $log_file" >&2 + 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 "usbhidd: registered producer" "$log_file"; then + echo "ERROR: usbhidd did not register โ€” child enumeration behind hub failed" >&2 + echo " Expected: 'usbhidd: registered producer'" >&2 + echo " See $log_file" >&2 + exit 1 + fi + + # 6. No panics anywhere in the boot. + if grep -qiE "panic|RUST_BACKTRACE" "$log_file"; then + echo "ERROR: panic detected in boot log" >&2 + grep -iE "panic|RUST_BACKTRACE" "$log_file" | head -5 >&2 + echo " See $log_file" >&2 + exit 1 + fi + + echo "HUB_ENUMERATION=ok" + echo "HUB_LOG=$log_file" + echo "USB hub enumeration confirmed in $log_file" + exit 0 +fi + +exec qemu-system-x86_64 \ + -name "Red Bear OS x86_64" \ + -device qemu-xhci,id=xhci \ + -device usb-hub,bus=xhci.0,port=1 \ + -device usb-kbd,bus=xhci.0,port=1.2 \ + -device usb-tablet,bus=xhci.0,port=2 \ + -smp 4 \ + -m 2048 \ + -bios "$firmware" \ + -chardev stdio,id=debug,signal=off,mux=on \ + -serial chardev:debug \ + -mon chardev=debug \ + -machine q35 \ + -device ich9-intel-hda -device hda-output \ + -device virtio-net,netdev=net0 \ + -netdev user,id=net0 \ + -vga std \ + -drive file="$image",format=raw,if=none,id=drv0,snapshot=on \ + -device nvme,drive=drv0,serial=NVME_SERIAL \ + -drive file="$extra",format=raw,if=none,id=drv1,snapshot=on \ + -device nvme,drive=drv1,serial=NVME_EXTRA \ + -enable-kvm -cpu host diff --git a/local/sources/base b/local/sources/base index bd379e0771..9bbdc2cafa 160000 --- a/local/sources/base +++ b/local/sources/base @@ -1 +1 @@ -Subproject commit bd379e0771e7cfffdf2b74ccee207d3195a0544a +Subproject commit 9bbdc2cafabed4d227e1f74d9577c128bf3f72ea