Skip to main content

usb_if/host/
hub.rs

1/// 寄存器宽度
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum RegWidth {
4    U8,
5    U16,
6    U32,
7    U64,
8}
9
10/// 内存屏障类型
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum MemoryBarrierType {
13    Read,
14    Write,
15    Full,
16}
17
18/// Hub 类请求
19///
20/// 参照 USB 2.0 规范表 11-15。
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum HubRequest {
23    GetHubDescriptor,
24    GetHubStatus,
25    SetHubFeature,
26    ClearHubFeature,
27    GetPortStatus,
28    SetPortFeature,
29    ClearPortFeature,
30    GetHubDescriptor16, // USB 3.0+
31}
32
33/// 端口特性选择器
34///
35/// 参照 USB 2.0 规范表 11-17。
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum PortFeature {
38    Connection = 0,
39    Enable = 1,
40    Suspend = 2,
41    OverCurrent = 3,
42    Reset = 4,
43    Power = 8,
44    LowSpeed = 9,
45    CConnection = 16,  // 清除连接变化
46    CEnable = 17,      // 清除使能变化
47    CSuspend = 18,     // 清除挂起变化
48    COverCurrent = 19, // 清除过流变化
49    CReset = 20,       // 清除复位完成
50}
51
52const USB_MAXCHILDREN: usize = 8;
53const DEVICE_BITMAP_BYTES: usize = (USB_MAXCHILDREN + 1 + 7).div_ceil(8);
54
55#[derive(Clone, Copy)]
56#[allow(non_snake_case)]
57#[repr(C, packed)]
58pub struct HubDescriptor {
59    pub bDescLength: u8,
60    pub bDescriptorType: u8,
61    pub bNbrPorts: u8,
62    wHubCharacteristics: u16,
63    pub bPwrOn2PwrGood: u8,
64    pub bHubContrCurrent: u8,
65    pub u: HubDescriptorVariant,
66}
67
68impl HubDescriptor {
69    pub fn hub_characteristics(&self) -> u16 {
70        u16::from_le(self.wHubCharacteristics)
71    }
72
73    /// 从字节数组创建 HubDescriptor 引用
74    ///
75    /// 如果数据长度不足或描述符类型不匹配,返回 None
76    pub fn from_bytes(data: &[u8]) -> Option<&Self> {
77        if data.is_empty() {
78            return None;
79        }
80
81        let length = data[0] as usize;
82        if data.len() < length {
83            return None;
84        }
85
86        // 检查描述符类型(0x29 = Hub 描述符)
87        if data.len() < 2 || data[1] != 0x29 {
88            return None;
89        }
90
91        // SAFETY: 已检查数据长度和类型,指针有效且对齐
92        Some(unsafe { &*(data.as_ptr() as *const HubDescriptor) })
93    }
94}
95
96#[derive(Clone, Copy)]
97#[repr(C, packed)]
98pub union HubDescriptorVariant {
99    pub hs: HighSpeedHubDescriptorTail,
100    pub ss: SuperSpeedHubDescriptorTail,
101}
102
103#[derive(Debug, Clone, Copy)]
104#[repr(C, packed)]
105pub struct HighSpeedHubDescriptorTail {
106    pub device_removable: [u8; DEVICE_BITMAP_BYTES],
107    pub port_pwr_ctrl_mask: [u8; DEVICE_BITMAP_BYTES],
108}
109
110#[allow(non_snake_case)]
111#[derive(Debug, Clone, Copy)]
112#[repr(C, packed)]
113pub struct SuperSpeedHubDescriptorTail {
114    pub bHubHdrDecLat: u8,
115    wHubDelay: u16,
116    device_removable: u16,
117}
118
119impl SuperSpeedHubDescriptorTail {
120    pub fn hub_delay(&self) -> u16 {
121        u16::from_le(self.wHubDelay)
122    }
123    pub fn device_removable(&self) -> u16 {
124        u16::from_le(self.device_removable)
125    }
126}
127
128/// Transaction Translator 信息
129///
130/// 用于高速 Hub 与低速/全速设备的通信。
131#[derive(Debug, Clone, Copy)]
132pub struct TtInfo {
133    /// TT 思考时间(单位:2 微秒)
134    pub think_time: u8,
135
136    /// 是否有多个 TT
137    pub multi_tt: bool,
138
139    /// TT 端口数量
140    pub num_ports: u8,
141}
142
143/// Hub 特性
144///
145/// 参照 USB 2.0 规范图 11-16。
146#[derive(Debug, Clone, Copy, PartialEq, Eq)]
147pub struct HubCharacteristics {
148    /// 电源切换模式
149    pub power_switching: PowerSwitchingMode,
150
151    /// 复合设备
152    pub compound_device: bool,
153
154    /// 过流保护模式
155    pub over_current_mode: OverCurrentMode,
156
157    /// 端口指示灯支持
158    pub port_indicators: bool,
159}
160
161/// 电源切换模式
162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163pub enum PowerSwitchingMode {
164    /// 所有端口同时供电
165    Ganged,
166
167    /// 每个端口独立控制
168    Individual,
169
170    /// 无电源控制(总是供电)
171    AlwaysPower,
172}
173
174/// 过流保护模式
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176pub enum OverCurrentMode {
177    /// 全局过流保护
178    Global,
179
180    /// 每个端口独立保护
181    Individual,
182}
183
184/// 端口状态
185///
186/// 参照 USB 2.0 规范表 11-21。
187#[derive(Debug, Clone, Copy)]
188pub struct PortStatus {
189    /// 当前连接状态
190    pub connected: bool,
191
192    /// 端口已启用
193    pub enabled: bool,
194
195    /// 已挂起
196    pub suspended: bool,
197
198    /// 过流检测
199    pub over_current: bool,
200
201    /// 复位中
202    pub resetting: bool,
203
204    /// 电源已开启
205    pub powered: bool,
206
207    /// 低速设备连接
208    pub low_speed: bool,
209
210    /// 高速设备连接
211    pub high_speed: bool,
212
213    /// 端口速度
214    pub speed: Speed,
215
216    /// 端口状态变化标志
217    pub change: PortStatusChange,
218}
219
220/// 端口状态变化标志
221#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub struct PortStatusChange {
223    /// 连接状态变化
224    pub connection_changed: bool,
225
226    /// 启用状态变化
227    pub enabled_changed: bool,
228
229    /// 复位完成
230    pub reset_complete: bool,
231
232    /// 挂起状态变化
233    pub suspend_changed: bool,
234
235    /// 过流状态变化
236    pub over_current_changed: bool,
237}
238
239/// USB 设备速度
240#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
241#[repr(u8)]
242pub enum Speed {
243    Low = 0,
244    #[default]
245    Full = 1,
246    High = 2,
247    Wireless = 3,
248    SuperSpeed = 4,
249    SuperSpeedPlus = 5,
250}
251
252impl From<u8> for Speed {
253    fn from(value: u8) -> Self {
254        match value {
255            0 => Speed::Low,
256            1 => Speed::Full,
257            2 => Speed::High,
258            3 => Speed::Wireless,
259            4 => Speed::SuperSpeed,
260            5 => Speed::SuperSpeedPlus,
261            _ => Speed::Full,
262        }
263    }
264}
265
266impl Speed {
267    /// 从 USB 2.0 Hub wPortStatus 解析速度
268    ///
269    /// 根据 USB 2.0 规范(第 11.24.2.7 节):
270    /// - Bit 9 (0x0200): Low Speed
271    /// - Bit 10 (0x0400): High Speed
272    /// - Bit 11 (0x0800): SuperSpeed (USB 3.0)
273    /// - 默认: Full Speed
274    pub fn from_usb2_hub_status(raw: u16) -> Self {
275        if (raw & 0x0200) != 0 {
276            Speed::Low
277        } else if (raw & 0x0400) != 0 {
278            Speed::High
279        } else if (raw & 0x0600) != 0 {
280            Speed::SuperSpeed
281        } else {
282            Speed::Full
283        }
284    }
285
286    /// 从 xHCI PORTSC PortSpeed 字段解析速度
287    ///
288    /// 根据 xHCI 规范(第 4.19.2 节):
289    /// - 1 = Full Speed
290    /// - 2 = Low Speed
291    /// - 3 = High Speed
292    /// - 4 = SuperSpeed
293    /// - 5 = SuperSpeedPlus
294    pub fn from_xhci_portsc(speed_value: u8) -> Self {
295        match speed_value {
296            1 => Speed::Full,
297            2 => Speed::Low,
298            3 => Speed::High,
299            4 => Speed::SuperSpeed,
300            5 => Speed::SuperSpeedPlus,
301            _ => Speed::Full, // Reserved/Unknown
302        }
303    }
304
305    /// 转换为 xHCI Slot Context 速度值
306    ///
307    /// 根据 xHCI 规范(第 6.2.2 节)Slot Context Speed 字段:
308    /// - 1 = Full Speed
309    /// - 2 = Low Speed
310    /// - 3 = High Speed
311    /// - 4 = Super Speed
312    pub fn to_xhci_slot_value(&self) -> u8 {
313        match self {
314            Speed::Full => 1,
315            Speed::Low => 2,
316            Speed::High => 3,
317            Speed::SuperSpeed => 4,
318            Speed::SuperSpeedPlus => 5,
319            Speed::Wireless => 3,
320        }
321    }
322
323    /// Convert to the raw PORTSC.PortSpeed encoding used by xHCI registers.
324    ///
325    /// Values follow xHCI 4.19.2: 1=FS, 2=LS, 3=HS, 4=SS, 5=SS+.
326    pub fn to_xhci_portsc_value(&self) -> u8 {
327        match self {
328            Speed::Full => 1,
329            Speed::Low => 2,
330            Speed::High => 3,
331            Speed::SuperSpeed => 4,
332            Speed::SuperSpeedPlus => 5,
333            Speed::Wireless => 3,
334        }
335    }
336
337    /// 判断是否需要 Transaction Translator
338    ///
339    /// 根据 xHCI 规范:
340    /// - LS/FS 设备连接在 HS Hub 上需要 TT
341    pub fn requires_tt(&self, hub_speed: Self) -> bool {
342        // 设备是 LS 或 FS,且 Hub 是 HS
343        matches!(self, Self::Low | Self::Full) && matches!(hub_speed, Self::High)
344    }
345
346    /// 判断设备是否为 Low Speed 或 Full Speed
347    pub fn is_low_or_full_speed(&self) -> bool {
348        matches!(self, Self::Low | Self::Full)
349    }
350}
351
352// ============================================================================
353// 辅助函数
354// ============================================================================
355
356impl HubCharacteristics {
357    /// 从描述符原始数据解析
358    ///
359    /// 参照 USB 2.0 规范图 11-16。
360    pub fn from_descriptor(value: u16) -> Self {
361        let power_switching = match value & 0x03 {
362            0x01 => PowerSwitchingMode::Ganged,
363            0x02 => PowerSwitchingMode::Individual,
364            _ => PowerSwitchingMode::AlwaysPower,
365        };
366
367        let compound_device = (value & 0x04) != 0;
368        let over_current_mode = if (value & 0x08) != 0 {
369            OverCurrentMode::Individual
370        } else {
371            OverCurrentMode::Global
372        };
373        let port_indicators = (value & 0x10) != 0;
374
375        Self {
376            power_switching,
377            compound_device,
378            over_current_mode,
379            port_indicators,
380        }
381    }
382
383    /// 转换为描述符原始数据
384    pub fn to_descriptor(&self) -> u16 {
385        let mut value = 0u16;
386
387        value |= match self.power_switching {
388            PowerSwitchingMode::Ganged => 0x01,
389            PowerSwitchingMode::Individual => 0x02,
390            PowerSwitchingMode::AlwaysPower => 0x00,
391        };
392
393        if self.compound_device {
394            value |= 0x04;
395        }
396
397        if matches!(self.over_current_mode, OverCurrentMode::Individual) {
398            value |= 0x08;
399        }
400
401        if self.port_indicators {
402            value |= 0x10;
403        }
404
405        value
406    }
407}
408
409#[cfg(test)]
410mod tests {
411    use super::*;
412
413    #[test]
414    fn test_hub_characteristics_roundtrip() {
415        let original = HubCharacteristics {
416            power_switching: PowerSwitchingMode::Individual,
417            compound_device: true,
418            over_current_mode: OverCurrentMode::Global,
419            port_indicators: true,
420        };
421
422        let descriptor = original.to_descriptor();
423        let decoded = HubCharacteristics::from_descriptor(descriptor);
424
425        assert_eq!(original.power_switching, decoded.power_switching);
426        assert_eq!(original.compound_device, decoded.compound_device);
427        assert_eq!(original.over_current_mode, decoded.over_current_mode);
428        assert_eq!(original.port_indicators, decoded.port_indicators);
429    }
430
431    #[test]
432    fn test_hub_descriptor_from_bytes() {
433        // 测试数据:4 端口 Hub
434        let data = [
435            0x09, // bDescLength = 9
436            0x29, // bDescriptorType = 0x29 (Hub)
437            0x04, // bNbrPorts = 4
438            0x12, 0x00, // wHubCharacteristics = 0x0012 (little-endian)
439            // Bits 1:0 = 10b -> Individual power switching
440            // Bit 2 = 0 -> Not a compound device
441            // Bit 3 = 1 -> Individual over-current protection
442            // Bit 4 = 0 -> No port indicators
443            0x32, // bPwrOn2PwrGood = 50 * 2ms = 100ms
444            0x64, // bHubContrCurrent = 100mA
445            0x00, // DeviceRemovable (端口 0-7 位图)
446            0x00, // Reserved
447        ];
448
449        let desc = HubDescriptor::from_bytes(&data).expect("Failed to parse");
450
451        assert_eq!(desc.bNbrPorts, 4);
452        assert_eq!(desc.bPwrOn2PwrGood, 50);
453        assert_eq!(desc.bHubContrCurrent, 100);
454
455        // 验证特性解析(wHubCharacteristics = 0x0012)
456        // Bits 1:0 = 10b -> Individual power switching
457        // Bit 2 = 0 -> Not a compound device
458        // Bit 3 = 1 -> Individual over-current protection
459        assert_eq!(desc.hub_characteristics(), 0x0012);
460    }
461
462    #[test]
463    fn test_hub_descriptor_invalid_length() {
464        let data = [0x09, 0x29]; // 太短
465        assert!(HubDescriptor::from_bytes(&data).is_none());
466    }
467
468    #[test]
469    fn test_hub_descriptor_invalid_type() {
470        let mut data = [0x09u8; 7];
471        data[1] = 0x01; // 错误的类型
472        assert!(HubDescriptor::from_bytes(&data).is_none());
473    }
474}