From 0e948dd2a7332ff4b135dee95b645cf7b2d66f14 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Sun, 19 Jul 2026 19:11:36 +0900 Subject: [PATCH] usbhubd: gate port-indicator SetPortFeature on hub capability SetPortFeature(PORT_INDICATOR) was issued unconditionally for every connected+enabled port. QEMU's usb-hub does not advertise indicator support and NAKs the request indefinitely; with no control-transfer timeout the daemon hung before the post-enable debounce, so devices behind the hub never attached. Gate on wHubCharacteristics bit 7 (HUB_CHAR_PORTIND, USB 2.0 Table 11-13), matching Linux hub_configure's has_indicators check. --- drivers/usb/usbhubd/src/main.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/usb/usbhubd/src/main.rs b/drivers/usb/usbhubd/src/main.rs index e3775027c9..9eadf1e0ff 100644 --- a/drivers/usb/usbhubd/src/main.rs +++ b/drivers/usb/usbhubd/src/main.rs @@ -159,7 +159,7 @@ fn main() { .expect("Failed to find suitable configuration"); // Read hub descriptor - let (ports, usb_3, b_pwr_on_2_pwr_good, w_hub_delay, device_removable) = if desc.major_version() >= 3 { + let (ports, usb_3, b_pwr_on_2_pwr_good, w_hub_delay, device_removable, hub_characteristics) = if desc.major_version() >= 3 { let mut hub_desc = usb::HubDescriptorV3::default(); handle .device_request( @@ -179,6 +179,7 @@ fn main() { 10u8, u16::from(hub_desc.delay), hub_desc.device_removable, + hub_desc.characteristics, ) } else { let mut hub_desc = usb::HubDescriptorV2::default(); @@ -200,6 +201,7 @@ fn main() { // USB 2.0 device_removable bitmaps are variable-length and // not parsed (see hub.rs). 0u16, + hub_desc.characteristics, ) }; @@ -526,9 +528,14 @@ fn main() { continue; } - // Linux 7.1: port indicator — set amber during reset/power-on, - // green when enabled. Helps diagnose which port is active. - if snap.connected && snap.enabled && !snap.resetting { + // Gate on wHubCharacteristics bit 7 (HUB_CHAR_PORTIND, USB 2.0 + // Table 11-13; Linux hub_configure's has_indicators): a hub that + // does not advertise indicator support may NAK this request + // indefinitely, and these control transfers have no timeout. + const HUB_CHAR_PORTIND: u16 = 0x0080; + if snap.connected && snap.enabled && !snap.resetting + && (hub_characteristics & HUB_CHAR_PORTIND) != 0 + { let _ = set_feature(&handle, port, usb::HubPortFeature::PortIndicator); }