⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/drivers/usb/
transfer.rs

1//! USB transfer types and UHCI transfer descriptors
2//!
3//! Contains data structures for USB data transfers including:
4//! - USB transfer request types (Setup, In, Out)
5//! - UHCI Transfer Descriptors (TD) for hardware-level transfers
6//! - UHCI Queue Heads (QH) for scheduling transfers
7
8use alloc::vec::Vec;
9
10/// USB transfer types
11#[derive(Debug, Clone)]
12pub enum UsbTransfer {
13    Setup {
14        request_type: u8,
15        request: u8,
16        value: u16,
17        index: u16,
18        data: Vec<u8>,
19    },
20    In {
21        endpoint: u8,
22        length: usize,
23    },
24    Out {
25        endpoint: u8,
26        data: Vec<u8>,
27    },
28}
29
30/// UHCI Transfer Descriptor
31#[repr(C)]
32#[derive(Debug, Clone, Copy)]
33pub struct UhciTd {
34    /// Link pointer to next TD or QH
35    pub link_pointer: u32,
36    /// Control and status
37    pub control_status: u32,
38    /// Token (PID, device address, endpoint, data toggle)
39    pub token: u32,
40    /// Buffer pointer
41    pub buffer_pointer: u32,
42}
43
44impl Default for UhciTd {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl UhciTd {
51    pub const fn new() -> Self {
52        Self {
53            link_pointer: 1, // Terminate
54            control_status: 0,
55            token: 0,
56            buffer_pointer: 0,
57        }
58    }
59
60    /// Set up a SETUP packet TD
61    pub fn setup_packet(&mut self, device_addr: u8, endpoint: u8, data_toggle: bool, max_len: u16) {
62        self.token = 0x2D  // SETUP PID
63            | ((device_addr as u32 & 0x7F) << 8)
64            | ((endpoint as u32 & 0xF) << 15)
65            | (if data_toggle { 1 << 19 } else { 0 })
66            | ((max_len.saturating_sub(1) as u32 & 0x7FF) << 21);
67
68        self.control_status = (3 << 27)  // 3 errors allowed
69            | (1 << 23); // Active
70    }
71
72    /// Set up an IN packet TD
73    pub fn in_packet(&mut self, device_addr: u8, endpoint: u8, data_toggle: bool, max_len: u16) {
74        self.token = 0x69  // IN PID
75            | ((device_addr as u32 & 0x7F) << 8)
76            | ((endpoint as u32 & 0xF) << 15)
77            | (if data_toggle { 1 << 19 } else { 0 })
78            | ((max_len.saturating_sub(1) as u32 & 0x7FF) << 21);
79
80        self.control_status = (3 << 27)  // 3 errors allowed
81            | (1 << 23); // Active
82    }
83
84    /// Set up an OUT packet TD
85    pub fn out_packet(&mut self, device_addr: u8, endpoint: u8, data_toggle: bool, max_len: u16) {
86        self.token = 0xE1  // OUT PID
87            | ((device_addr as u32 & 0x7F) << 8)
88            | ((endpoint as u32 & 0xF) << 15)
89            | (if data_toggle { 1 << 19 } else { 0 })
90            | ((max_len.saturating_sub(1) as u32 & 0x7FF) << 21);
91
92        self.control_status = (3 << 27)  // 3 errors allowed
93            | (1 << 23); // Active
94    }
95
96    /// Check if TD is still active
97    pub fn is_active(&self) -> bool {
98        (self.control_status & (1 << 23)) != 0
99    }
100
101    /// Check if TD completed with error
102    pub fn has_error(&self) -> bool {
103        (self.control_status & (1 << 22)) != 0  // Stalled
104            || (self.control_status & (1 << 21)) != 0  // Data Buffer Error
105            || (self.control_status & (1 << 20)) != 0  // Babble Detected
106            || (self.control_status & (1 << 19)) != 0  // NAK Received
107            || (self.control_status & (1 << 18)) != 0  // CRC/Timeout Error
108            || (self.control_status & (1 << 17)) != 0 // Bitstuff Error
109    }
110
111    /// Get actual length transferred
112    pub fn actual_length(&self) -> u16 {
113        let len = ((self.control_status + 1) & 0x7FF) as u16;
114        if len == 0x7FF {
115            0
116        } else {
117            len
118        }
119    }
120}
121
122/// UHCI Queue Head
123#[repr(C)]
124#[derive(Debug, Clone, Copy)]
125pub struct UhciQh {
126    /// Horizontal link pointer (next QH)
127    pub head_link: u32,
128    /// Vertical link pointer (first TD)
129    pub element_link: u32,
130}
131
132impl Default for UhciQh {
133    fn default() -> Self {
134        Self::new()
135    }
136}
137
138impl UhciQh {
139    pub const fn new() -> Self {
140        Self {
141            head_link: 1,    // Terminate
142            element_link: 1, // Terminate
143        }
144    }
145}