Skip to content

Conversation

@ZR233
Copy link
Member

@ZR233 ZR233 commented Jan 28, 2026

No description provided.

Copilot AI review requested due to automatic review settings January 28, 2026 04:59
@ZR233 ZR233 merged commit cb2df17 into main Jan 28, 2026
6 checks passed
@ZR233 ZR233 deleted the dev branch January 28, 2026 04:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors hub and device handling in the xHCI backend to use a richer topology representation and the Speed enum throughout, and introduces hub-depth and TT (Transaction Translator) awareness for LS/FS devices behind hubs.

Changes:

  • Adjusts usb_if::host::hub::Speed utilities, including decoding from wPortStatus and mapping to xHCI slot values.
  • Replaces the old RouteString abstraction with a Hub/HubInfo model that tracks parent hub, depth, port, speed, and TT characteristics, and reworks device addressing (DeviceAddressInfo and xHCI device enumeration) to derive route strings and TT info from this topology.
  • Updates hub backends (HubOp, XhciRootHub, HubDevice), kmod core (Core), and Cargo test aliases to align with the new model and support hub-depth configuration for SuperSpeed hubs.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
usb-if/src/host/hub.rs Adjusts USB2 hub status decoding (from_usb2_hub_status) and refines Speed ↔ xHCI value mappings; note the super-speed bitmask change.
usb-host/src/backend/ty/mod.rs Simplifies DeviceOp::update_hub and HubParams by removing the hub speed field, since hub speed is now tracked via HubInfo.
usb-host/src/backend/kmod/xhci/hub.rs Updates XhciRootHub to the new HubOp::init(HubInfo) -> HubInfo API and sets the root hub speed to SuperSpeedPlus.
usb-host/src/backend/kmod/xhci/host.rs Cleans up new_device by removing route-string-specific debug output that no longer applies.
usb-host/src/backend/kmod/xhci/device.rs Changes Device.port_speed from raw u8 to Speed, updates interval calculation to match on Speed, and reworks address/TT logic to use HubInfo topology and HubParams.
usb-host/src/backend/kmod/mod.rs Redefines DeviceAddressInfo to carry parent_hub, port_id, and a BTreeMap<Id<Hub>, HubInfo> instead of a RouteString and precomputed TT info; fixes the test-dwc alias to run the test_dwc test in the test_hub crate.
usb-host/src/backend/kmod/kcore.rs Introduces Core::hub_infos() and rewires device probing to build DeviceAddressInfo from PortChangeInfo and HubInfo, and to construct Hub instances with topology-aware HubInfo.
usb-host/src/backend/kmod/hub/mod.rs Replaces the old RouteString type with the Hub struct and HubInfo/UsbTt data structures, and updates HubOp to return an updated HubInfo from init.
usb-host/src/backend/kmod/hub/device.rs Extends hub configuration to derive TT think time/multi-TT from descriptors, build HubParams, and, for SuperSpeed external hubs, send a SET_HUB_DEPTH control request; integrates with the new HubInfo model.
.cargo/config.toml Points the test-dwc alias at the test_hub crate’s test_dwc test target so the alias actually runs existing tests.
Comments suppressed due to low confidence (1)

usb-if/src/host/hub.rs:283

  • from_usb2_hub_status's implementation and documentation no longer match and the new mask 0x0600 makes the SuperSpeed branch effectively unreachable. The comment above states that bit 11 (0x0800) indicates SuperSpeed, but the code now checks raw & 0x0600, which overlaps the LS/HS bits already handled in the earlier if/else if branches, so this condition will never be true for valid wPortStatus values and SuperSpeed ports will be incorrectly reported as Full. Please restore a correct mask (e.g. 0x0800) or otherwise align the bit decoding with the USB 2.0 spec, and keep the comment in sync with the implementation.
    /// 根据 USB 2.0 规范(第 11.24.2.7 节):
    /// - Bit 9 (0x0200): Low Speed
    /// - Bit 10 (0x0400): High Speed
    /// - Bit 11 (0x0800): SuperSpeed (USB 3.0)
    /// - 默认: Full Speed
    pub fn from_usb2_hub_status(raw: u16) -> Self {
        if (raw & 0x0200) != 0 {
            Speed::Low
        } else if (raw & 0x0400) != 0 {
            Speed::High
        } else if (raw & 0x0600) != 0 {
            Speed::SuperSpeed
        } else {
            Speed::Full
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to 76
pub struct Hub {
pub info: HubInfo,
pub backend: Box<dyn HubOp>,
}
impl Hub {
pub fn new(
backend: Box<dyn HubOp>,
infos: &BTreeMap<Id<Hub>, HubInfo>,
port_id: u8,
parent: Option<Id<Hub>>,
) -> Self {
let slot_id;
let mut hub_depth = 0;
if parent.is_none() {
hub_depth = -1;
slot_id = 0;
} else {
slot_id = backend.slot_id();
let mut current_parent = parent;
while let Some(p) = current_parent {
let parent = infos.get(&p).expect("parent hub info must exist");
if parent.hub_depth == -1 {
break;
}

hub_depth += 1;
current_parent = infos.get(&p).and_then(|info| info.parent);
}
}

let depth = target_depth.expect("route string is full");
let shift = (depth - 1) * 4;
let mask = 0x0F << shift;
self.0 = (self.0 & !mask) | (((hub_port as u32) & 0x0F) << shift);
}

pub fn route_port_ids(&self) -> impl Iterator<Item = u8> + '_ {
(0..5).filter_map(move |depth| {
let port = ((self.0 >> (depth * 4)) & 0x0F) as u8;
if port == 0 { None } else { Some(port) }
})
}

pub fn to_port_path_string(self, root_hub_port: u8) -> String {
let mut parts = vec![root_hub_port.to_string()];
for port in self.route_port_ids() {
parts.push(port.to_string());
}
parts.join(".")
}
}

impl Debug for RouteString {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut iter = self.route_port_ids();
if let Some(first) = iter.next() {
write!(f, "{first}")?;
for port in iter {
write!(f, ".{port}")?;
}
Self {
backend,
info: HubInfo {
parent,
port_id,
slot_id,
hub_depth,
speed: Speed::Full,
tt: UsbTt {
multi: false,
think_time_ns: 0,
},
},
}
Ok(())
}
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the RouteString type here breaks the #[cfg(test)] unit tests at the bottom of this file, which still reference RouteString (via use super::RouteString;). Those tests will now fail to compile because the type no longer exists; either update or remove the tests, or retain a minimal RouteString (possibly behind cfg(test)) to keep the test module valid.

Copilot uses AI. Check for mistakes.
Comment on lines +78 to 87
#[derive(Debug, Clone)]
pub struct HubInfo {
/// 若为 None, 则表示 Root Hub
pub parent: Option<Id<Hub>>,
/// Roothub 为 `None`
pub route_string: Option<RouteString>,
pub backend: Box<dyn HubOp>,
pub slot_id: u8,
pub hub_depth: isize,
pub speed: Speed,
pub port_id: u8,
pub tt: UsbTt,
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HubInfo.speed is initialized here to Speed::Full but is never updated for external hubs, even though it is later used in xhci::device::Device::address to find the first high-speed hub when setting TT information (matches!(parent_hub.speed, Speed::High)). As a result, parent_hub.speed stays Full for non-root hubs and the TT parent selection for LS/FS devices behind HS hubs will be wrong. Consider setting info.speed based on the hub's actual protocol/speed in HubDevice::configure (e.g. from device_protocol) so that the topology information in HubInfo is accurate.

Copilot uses AI. Check for mistakes.
Comment on lines 98 to +101
pub(crate) async fn init(&mut self, host: &mut Xhci, info: &DeviceAddressInfo) -> Result {
// Keep the raw PORTSC.PortSpeed encoding for interval calculations
self.port_speed = info.port_speed.to_xhci_portsc_value();
self.port_speed = info.port_speed;
// let speed = info.port_speed.to_xhci_portsc_value();
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment in Device::init still says "Keep the raw PORTSC.PortSpeed encoding for interval calculations", but port_speed has been changed to store the logical Speed enum instead of the raw xHCI PORTSC.PortSpeed value. This stale comment is now misleading and could cause future changes to assume port_speed is a raw encoding again; please update or remove the comment to reflect the new semantics.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant