usb: recognize and configure hubs, power downstream ports (B4a)
First slice of hub support (docs/usb-hub.md), handled IN the xhci-bus because a device behind a hub is reached by the CONTROLLER via a route string in its slot context — topology only exists inside the driver that owns the controller. When the scan enumerates a class-9 device it now calls setupHub: read the hub descriptor for the downstream port count and TT arrangement, tell the controller the slot is a hub (Configure Endpoint with the slot add-flag sets the Hub bit, Number of Ports, and MTT/TT-Think-Time per xHCI 4.6.6), SET_HUB_DEPTH for a SuperSpeed hub so it can compose route strings, and SET_FEATURE PORT_POWER every downstream port. The Device gains topology fields (route string, root port, parent hub slot/port for the TT) and buildAddressInputContext now fills them, so the Address Device path is ready for downstream devices — those are enumerated in B4b. A root-port device gets route 0 and its own port as the chain root, unchanged behavior. Verified in QEMU with a hub on a second controller and a device behind it (a usb-hub QEMU case, since the boot controller's auto-assigned devices collide on the low ports): 'hub slot 1: 8 downstream ports powered (USB2 single-TT)'. Full suite 89/89. The user's SuperSpeed Genesys hub is the real-hardware target, flagged separately (QEMU's USB2 hub doesn't model the compound USB3 hub).
This commit is contained in:
@@ -235,6 +235,21 @@ fn bringUpPort(manager: runtime.ipc.Handle, engine: *library.Controller, port: u
|
||||
interface.registered_device_id = registered;
|
||||
}
|
||||
}
|
||||
|
||||
// A hub (class 9) is bus infrastructure the bus drives itself: configure it
|
||||
// and power its downstream ports (docs/usb-hub.md). Its interfaces are still
|
||||
// reported above, but no external class driver binds it.
|
||||
if (deviceIsHub(usb_device)) _ = engine.setupHub(usb_device);
|
||||
}
|
||||
|
||||
/// Whether an enumerated device is a hub — class 9 at the device or the
|
||||
/// interface level (a hub's single interface is class 9/0/0).
|
||||
fn deviceIsHub(usb_device: *const library.Device) bool {
|
||||
if (usb_device.device_descriptor.device_class == @intFromEnum(usb_ids.Class.hub)) return true;
|
||||
for (usb_device.interfaces[0..usb_device.interface_count]) |interface| {
|
||||
if (interface.class == @intFromEnum(usb_ids.Class.hub)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Tear down whatever was on `port` after an unplug: report each registered
|
||||
|
||||
Reference in New Issue
Block a user