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

veridian_kernel/drivers/usb/
host.rs

1//! USB host controller trait and UHCI controller implementation
2//!
3//! Contains the [`UsbHostController`] trait that all USB host controllers must
4//! implement, along with the [`UhciController`] (Universal Host Controller
5//! Interface) implementation including register definitions and hardware
6//! transfer logic.
7
8use alloc::{string::String, vec, vec::Vec};
9
10use super::{
11    device::UsbPortStatus,
12    transfer::{UhciQh, UhciTd, UsbTransfer},
13    UsbSpeed,
14};
15use crate::error::KernelError;
16
17/// USB host controller trait
18pub trait UsbHostController: Send + Sync {
19    /// Get controller name
20    fn name(&self) -> &str;
21
22    /// Initialize the controller
23    fn init(&mut self) -> Result<(), KernelError>;
24
25    /// Reset the controller
26    fn reset(&mut self) -> Result<(), KernelError>;
27
28    /// Get number of ports
29    fn get_port_count(&self) -> u8;
30
31    /// Check port status
32    fn get_port_status(&self, port: u8) -> Result<UsbPortStatus, KernelError>;
33
34    /// Reset port
35    fn reset_port(&mut self, port: u8) -> Result<(), KernelError>;
36
37    /// Enable port
38    fn enable_port(&mut self, port: u8) -> Result<(), KernelError>;
39
40    /// Disable port
41    fn disable_port(&mut self, port: u8) -> Result<(), KernelError>;
42
43    /// Perform USB transfer
44    fn transfer(
45        &mut self,
46        device_address: u8,
47        transfer: UsbTransfer,
48    ) -> Result<Vec<u8>, KernelError>;
49
50    /// Set device address
51    fn set_device_address(&mut self, old_address: u8, new_address: u8) -> Result<(), KernelError>;
52}
53
54/// UHCI register offsets (per USB UHCI specification)
55#[allow(dead_code)] // Hardware register definitions
56mod uhci_regs {
57    pub const USBCMD: u16 = 0x00; // USB Command Register
58    pub const USBSTS: u16 = 0x02; // USB Status Register
59    pub const USBINTR: u16 = 0x04; // USB Interrupt Enable Register
60    pub const FRNUM: u16 = 0x06; // Frame Number Register
61    pub const FLBASEADD: u16 = 0x08; // Frame List Base Address Register
62    pub const SOFMOD: u16 = 0x0C; // Start of Frame Modify Register
63    pub const PORTSC1: u16 = 0x10; // Port 1 Status/Control
64    pub const PORTSC2: u16 = 0x12; // Port 2 Status/Control
65
66    // USBCMD bits
67    pub const CMD_RUN: u16 = 0x0001;
68    pub const CMD_HCRESET: u16 = 0x0002;
69    pub const CMD_GRESET: u16 = 0x0004;
70    pub const CMD_EGSM: u16 = 0x0008;
71    pub const CMD_FGR: u16 = 0x0010;
72    pub const CMD_SWDBG: u16 = 0x0020;
73    pub const CMD_CF: u16 = 0x0040;
74    pub const CMD_MAXP: u16 = 0x0080;
75
76    // USBSTS bits
77    pub const STS_USBINT: u16 = 0x0001;
78    pub const STS_ERROR: u16 = 0x0002;
79    pub const STS_RD: u16 = 0x0004;
80    pub const STS_HSE: u16 = 0x0008;
81    pub const STS_HCPE: u16 = 0x0010;
82    pub const STS_HCH: u16 = 0x0020;
83
84    // Port status bits
85    pub const PORT_CCS: u16 = 0x0001; // Current Connect Status
86    pub const PORT_CSC: u16 = 0x0002; // Connect Status Change
87    pub const PORT_PE: u16 = 0x0004; // Port Enable
88    pub const PORT_PEC: u16 = 0x0008; // Port Enable Change
89    pub const PORT_LS: u16 = 0x0030; // Line Status
90    pub const PORT_RD: u16 = 0x0040; // Resume Detect
91    pub const PORT_LSDA: u16 = 0x0100; // Low Speed Device Attached
92    pub const PORT_PR: u16 = 0x0200; // Port Reset
93    pub const PORT_SUSP: u16 = 0x1000; // Suspend
94}
95
96/// Simple UHCI host controller implementation
97pub struct UhciController {
98    base_address: u32,
99    port_count: u8,
100    name: String,
101    /// Frame list physical address (must be 4KB aligned)
102    frame_list_phys: u64,
103    /// Control QH for control transfers
104    control_qh_phys: u64,
105    /// Transfer descriptors buffer
106    td_buffer_phys: u64,
107    /// Data buffer for transfers
108    data_buffer_phys: u64,
109    /// Whether controller is initialized
110    initialized: bool,
111}
112
113impl UhciController {
114    pub fn new(base_address: u32) -> Self {
115        Self {
116            base_address,
117            port_count: 2, // UHCI typically has 2 ports
118            name: String::from("UHCI"),
119            frame_list_phys: 0,
120            control_qh_phys: 0,
121            td_buffer_phys: 0,
122            data_buffer_phys: 0,
123            initialized: false,
124        }
125    }
126
127    /// Read a 16-bit register
128    #[cfg(target_arch = "x86_64")]
129    fn read_reg16(&self, offset: u16) -> u16 {
130        use crate::arch::x86_64::inw;
131        // SAFETY: Reading a 16-bit I/O port at base_address + offset. The UHCI
132        // controller's I/O base address was obtained from PCI configuration space.
133        // We are in kernel mode with full I/O privilege.
134        unsafe { inw((self.base_address as u16).wrapping_add(offset)) }
135    }
136
137    #[cfg(not(target_arch = "x86_64"))]
138    fn read_reg16(&self, offset: u16) -> u16 {
139        // MMIO access for non-x86 architectures
140        let addr = (self.base_address as usize) + (offset as usize);
141        // SAFETY: MMIO read from the UHCI controller's memory-mapped register space.
142        // The base address was provided during controller initialization from PCI BAR.
143        // read_volatile prevents the compiler from reordering or eliding the access.
144        unsafe { core::ptr::read_volatile(addr as *const u16) }
145    }
146
147    /// Write a 16-bit register
148    #[cfg(target_arch = "x86_64")]
149    fn write_reg16(&self, offset: u16, value: u16) {
150        use crate::arch::x86_64::outw;
151        // SAFETY: Writing a 16-bit I/O port at base_address + offset. Same invariants
152        // as read_reg16: valid UHCI I/O base from PCI, kernel mode with I/O privilege.
153        unsafe { outw((self.base_address as u16).wrapping_add(offset), value) }
154    }
155
156    #[cfg(not(target_arch = "x86_64"))]
157    fn write_reg16(&self, offset: u16, value: u16) {
158        // MMIO access for non-x86 architectures
159        let addr = (self.base_address as usize) + (offset as usize);
160        // SAFETY: MMIO write to the UHCI controller's register space. Same invariants
161        // as read_reg16: valid base from PCI BAR, write_volatile for proper ordering.
162        unsafe { core::ptr::write_volatile(addr as *mut u16, value) }
163    }
164
165    /// Read a 32-bit register
166    /// Completes the register-width API alongside
167    /// read_reg16/write_reg16/write_reg32.
168    #[allow(dead_code)] // Register-width API completeness
169    #[cfg(target_arch = "x86_64")]
170    fn read_reg32(&self, offset: u16) -> u32 {
171        use crate::arch::x86_64::inl;
172        // SAFETY: Reading a 32-bit I/O port. Same invariants as read_reg16.
173        unsafe { inl((self.base_address as u16).wrapping_add(offset)) }
174    }
175
176    /// Completes the register-width API alongside
177    /// read_reg16/write_reg16/write_reg32.
178    #[allow(dead_code)] // Register-width API completeness
179    #[cfg(not(target_arch = "x86_64"))]
180    fn read_reg32(&self, offset: u16) -> u32 {
181        let addr = (self.base_address as usize) + (offset as usize);
182        // SAFETY: MMIO read of 32-bit register. Same invariants as read_reg16.
183        unsafe { core::ptr::read_volatile(addr as *const u32) }
184    }
185
186    /// Write a 32-bit register
187    #[cfg(target_arch = "x86_64")]
188    fn write_reg32(&self, offset: u16, value: u32) {
189        use crate::arch::x86_64::outl;
190        // SAFETY: Writing a 32-bit I/O port. Same invariants as write_reg16.
191        unsafe { outl((self.base_address as u16).wrapping_add(offset), value) }
192    }
193
194    #[cfg(not(target_arch = "x86_64"))]
195    fn write_reg32(&self, offset: u16, value: u32) {
196        let addr = (self.base_address as usize) + (offset as usize);
197        // SAFETY: MMIO write of 32-bit register. Same invariants as write_reg16.
198        unsafe { core::ptr::write_volatile(addr as *mut u32, value) }
199    }
200
201    /// Read port status register
202    fn read_port_status(&self, port: u8) -> u16 {
203        let offset = if port == 1 {
204            uhci_regs::PORTSC1
205        } else {
206            uhci_regs::PORTSC2
207        };
208        self.read_reg16(offset)
209    }
210
211    /// Write port status register
212    fn write_port_status(&self, port: u8, value: u16) {
213        let offset = if port == 1 {
214            uhci_regs::PORTSC1
215        } else {
216            uhci_regs::PORTSC2
217        };
218        self.write_reg16(offset, value);
219    }
220
221    /// Allocate controller data structures
222    fn allocate_structures(&mut self) -> Result<(), KernelError> {
223        // Allocate frame list (1024 entries * 4 bytes = 4KB, must be 4KB aligned)
224        let frame_list_pages =
225            crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
226                requested: 4096,
227                available: 0,
228            })?;
229        let frame_list_frame = frame_list_pages.first().ok_or(KernelError::OutOfMemory {
230            requested: 4096,
231            available: 0,
232        })?;
233        self.frame_list_phys = frame_list_frame.as_addr().as_u64();
234
235        // Clear frame list
236        let frame_list_ptr = self.frame_list_phys as *mut u32;
237        // SAFETY: frame_list_phys was just allocated as a full 4KB page (1024 u32
238        // entries). write_volatile ensures proper ordering for hardware-visible
239        // memory.
240        unsafe {
241            for i in 0..1024 {
242                core::ptr::write_volatile(frame_list_ptr.add(i), 1); // Terminate
243            }
244        }
245
246        // Allocate control QH
247        let qh_pages =
248            crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
249                requested: 4096,
250                available: 0,
251            })?;
252        let qh_frame = qh_pages.first().ok_or(KernelError::OutOfMemory {
253            requested: 4096,
254            available: 0,
255        })?;
256        self.control_qh_phys = qh_frame.as_addr().as_u64();
257
258        // Initialize control QH
259        let qh_ptr = self.control_qh_phys as *mut UhciQh;
260        // SAFETY: control_qh_phys points to a freshly allocated 4KB page, which is
261        // large enough for a UhciQh (8 bytes). write_volatile for
262        // hardware-visible memory.
263        unsafe {
264            core::ptr::write_volatile(qh_ptr, UhciQh::new());
265        }
266
267        // Point frame list entries to control QH
268        // SAFETY: frame_list_ptr still points to the same 4KB-aligned page allocated
269        // above. We write the physical address of the control QH with the QH
270        // type bit (bit 1) set per the UHCI specification.
271        unsafe {
272            for i in 0..1024 {
273                // QH pointer with QH bit set (bit 1)
274                core::ptr::write_volatile(frame_list_ptr.add(i), (self.control_qh_phys as u32) | 2);
275            }
276        }
277
278        // Allocate TD buffer (4KB for multiple TDs)
279        let td_pages =
280            crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
281                requested: 4096,
282                available: 0,
283            })?;
284        let td_frame = td_pages.first().ok_or(KernelError::OutOfMemory {
285            requested: 4096,
286            available: 0,
287        })?;
288        self.td_buffer_phys = td_frame.as_addr().as_u64();
289
290        // Clear TD buffer
291        // SAFETY: td_buffer_phys was just allocated as a full 4KB page. write_bytes
292        // zeroes the entire page to initialize all transfer descriptors.
293        unsafe {
294            core::ptr::write_bytes(self.td_buffer_phys as *mut u8, 0, 4096);
295        }
296
297        // Allocate data buffer for transfers
298        let data_pages =
299            crate::mm::allocate_pages(1, None).map_err(|_| KernelError::OutOfMemory {
300                requested: 4096,
301                available: 0,
302            })?;
303        let data_frame = data_pages.first().ok_or(KernelError::OutOfMemory {
304            requested: 4096,
305            available: 0,
306        })?;
307        self.data_buffer_phys = data_frame.as_addr().as_u64();
308
309        Ok(())
310    }
311
312    /// Wait for transfer completion with timeout
313    fn wait_for_transfer(&self, td_ptr: *mut UhciTd, timeout_ms: u32) -> Result<(), KernelError> {
314        let mut elapsed = 0u32;
315        let poll_interval = 1; // 1ms per poll
316
317        while elapsed < timeout_ms {
318            // SAFETY: td_ptr points into the TD buffer page allocated by
319            // allocate_structures. read_volatile ensures we see the latest
320            // hardware-written status bits.
321            let td = unsafe { core::ptr::read_volatile(td_ptr) };
322
323            if !td.is_active() {
324                if td.has_error() {
325                    return Err(KernelError::HardwareError {
326                        device: "uhci",
327                        code: 1,
328                    });
329                }
330                return Ok(());
331            }
332
333            // Simple delay (should use proper timer in production)
334            for _ in 0..1000 {
335                core::hint::spin_loop();
336            }
337            elapsed += poll_interval;
338        }
339
340        Err(KernelError::Timeout {
341            operation: "usb transfer",
342            duration_ms: timeout_ms as u64,
343        })
344    }
345}
346
347impl UsbHostController for UhciController {
348    fn name(&self) -> &str {
349        &self.name
350    }
351
352    fn init(&mut self) -> Result<(), KernelError> {
353        crate::println!(
354            "[USB] Initializing UHCI controller at 0x{:x}",
355            self.base_address
356        );
357
358        // Skip initialization if base address is 0 (no hardware)
359        if self.base_address == 0 {
360            crate::println!("[USB] UHCI: No hardware present, using software emulation");
361            self.initialized = true;
362            return Ok(());
363        }
364
365        // Allocate data structures
366        self.allocate_structures()?;
367
368        // Reset controller
369        self.reset()?;
370
371        // Set frame list base address
372        self.write_reg32(uhci_regs::FLBASEADD, self.frame_list_phys as u32);
373
374        // Set SOF timing (default value)
375        self.write_reg16(uhci_regs::SOFMOD, 64);
376
377        // Clear frame number
378        self.write_reg16(uhci_regs::FRNUM, 0);
379
380        // Clear status register by writing 1s to clear bits
381        self.write_reg16(uhci_regs::USBSTS, 0x003F);
382
383        // Enable interrupts (USB interrupt, error, resume detect)
384        self.write_reg16(uhci_regs::USBINTR, 0x000F);
385
386        // Start the controller (run, configure flag, max packet = 64)
387        self.write_reg16(
388            uhci_regs::USBCMD,
389            uhci_regs::CMD_RUN | uhci_regs::CMD_CF | uhci_regs::CMD_MAXP,
390        );
391
392        // Wait for controller to start
393        for _ in 0..100 {
394            let status = self.read_reg16(uhci_regs::USBSTS);
395            if (status & uhci_regs::STS_HCH) == 0 {
396                break; // Controller is running
397            }
398            core::hint::spin_loop();
399        }
400
401        // Enable power on all ports
402        for port in 1..=self.port_count {
403            let _status = self.read_port_status(port);
404            // Port power is always on in UHCI (no explicit control)
405            crate::println!("[USB] Port {} initial status: 0x{:04x}", port, _status);
406        }
407
408        self.initialized = true;
409        crate::println!("[USB] UHCI controller initialized");
410
411        Ok(())
412    }
413
414    fn reset(&mut self) -> Result<(), KernelError> {
415        if self.base_address == 0 {
416            return Ok(());
417        }
418
419        // Stop the controller first
420        let cmd = self.read_reg16(uhci_regs::USBCMD);
421        self.write_reg16(uhci_regs::USBCMD, cmd & !uhci_regs::CMD_RUN);
422
423        // Wait for halt
424        for _ in 0..100 {
425            let status = self.read_reg16(uhci_regs::USBSTS);
426            if (status & uhci_regs::STS_HCH) != 0 {
427                break;
428            }
429            core::hint::spin_loop();
430        }
431
432        // Global reset
433        self.write_reg16(uhci_regs::USBCMD, uhci_regs::CMD_GRESET);
434
435        // Wait at least 10ms for reset
436        for _ in 0..10000 {
437            core::hint::spin_loop();
438        }
439
440        // Clear global reset
441        self.write_reg16(uhci_regs::USBCMD, 0);
442
443        // Host controller reset
444        self.write_reg16(uhci_regs::USBCMD, uhci_regs::CMD_HCRESET);
445
446        // Wait for reset to complete
447        for _ in 0..100 {
448            let cmd = self.read_reg16(uhci_regs::USBCMD);
449            if (cmd & uhci_regs::CMD_HCRESET) == 0 {
450                break;
451            }
452            core::hint::spin_loop();
453        }
454
455        crate::println!("[USB] UHCI controller reset complete");
456        Ok(())
457    }
458
459    fn get_port_count(&self) -> u8 {
460        self.port_count
461    }
462
463    fn get_port_status(&self, port: u8) -> Result<UsbPortStatus, KernelError> {
464        if port == 0 || port > self.port_count {
465            return Err(KernelError::InvalidArgument {
466                name: "port",
467                value: "out of range",
468            });
469        }
470
471        // Return empty status for software emulation mode
472        if self.base_address == 0 {
473            return Ok(UsbPortStatus {
474                connected: false,
475                enabled: false,
476                suspended: false,
477                reset: false,
478                speed: UsbSpeed::Full,
479                power: true,
480            });
481        }
482
483        let status = self.read_port_status(port);
484
485        Ok(UsbPortStatus {
486            connected: (status & uhci_regs::PORT_CCS) != 0,
487            enabled: (status & uhci_regs::PORT_PE) != 0,
488            suspended: (status & uhci_regs::PORT_SUSP) != 0,
489            reset: (status & uhci_regs::PORT_PR) != 0,
490            speed: if (status & uhci_regs::PORT_LSDA) != 0 {
491                UsbSpeed::Low
492            } else {
493                UsbSpeed::Full
494            },
495            power: true, // UHCI ports are always powered
496        })
497    }
498
499    fn reset_port(&mut self, port: u8) -> Result<(), KernelError> {
500        if port == 0 || port > self.port_count {
501            return Err(KernelError::InvalidArgument {
502                name: "port",
503                value: "out of range",
504            });
505        }
506
507        if self.base_address == 0 {
508            return Ok(());
509        }
510
511        let current = self.read_port_status(port);
512
513        // Set port reset bit
514        self.write_port_status(port, current | uhci_regs::PORT_PR);
515
516        // Wait at least 50ms for reset
517        for _ in 0..50000 {
518            core::hint::spin_loop();
519        }
520
521        // Clear port reset bit
522        let current = self.read_port_status(port);
523        self.write_port_status(port, current & !uhci_regs::PORT_PR);
524
525        // Wait for reset to complete
526        for _ in 0..1000 {
527            core::hint::spin_loop();
528        }
529
530        // Clear status change bits by writing 1s
531        let status = self.read_port_status(port);
532        self.write_port_status(port, status | uhci_regs::PORT_CSC | uhci_regs::PORT_PEC);
533
534        crate::println!("[USB] Port {} reset complete", port);
535        Ok(())
536    }
537
538    fn enable_port(&mut self, port: u8) -> Result<(), KernelError> {
539        if port == 0 || port > self.port_count {
540            return Err(KernelError::InvalidArgument {
541                name: "port",
542                value: "out of range",
543            });
544        }
545
546        if self.base_address == 0 {
547            return Ok(());
548        }
549
550        let current = self.read_port_status(port);
551
552        // Enable port
553        self.write_port_status(port, current | uhci_regs::PORT_PE);
554
555        // Verify port is enabled
556        let status = self.read_port_status(port);
557        if (status & uhci_regs::PORT_PE) != 0 {
558            crate::println!("[USB] Port {} enabled", port);
559            Ok(())
560        } else {
561            Err(KernelError::HardwareError {
562                device: "uhci",
563                code: 2,
564            })
565        }
566    }
567
568    fn disable_port(&mut self, port: u8) -> Result<(), KernelError> {
569        if port == 0 || port > self.port_count {
570            return Err(KernelError::InvalidArgument {
571                name: "port",
572                value: "out of range",
573            });
574        }
575
576        if self.base_address == 0 {
577            return Ok(());
578        }
579
580        let current = self.read_port_status(port);
581
582        // Disable port
583        self.write_port_status(port, current & !uhci_regs::PORT_PE);
584
585        crate::println!("[USB] Port {} disabled", port);
586        Ok(())
587    }
588
589    fn transfer(
590        &mut self,
591        device_address: u8,
592        transfer: UsbTransfer,
593    ) -> Result<Vec<u8>, KernelError> {
594        // Software emulation mode - return simulated responses
595        if self.base_address == 0 || !self.initialized {
596            return match transfer {
597                UsbTransfer::Setup { data, value, .. } => {
598                    // Simulate GET_DESCRIPTOR response
599                    if (value >> 8) == 1 {
600                        // Device descriptor
601                        let mut response = vec![0u8; data.len().min(18)];
602                        if response.len() >= 18 {
603                            response[0] = 18; // bLength
604                            response[1] = 1; // bDescriptorType
605                            response[2] = 0x10; // bcdUSB low
606                            response[3] = 0x02; // bcdUSB high (USB 2.0)
607                            response[4] = 0; // bDeviceClass
608                            response[5] = 0; // bDeviceSubClass
609                            response[6] = 0; // bDeviceProtocol
610                            response[7] = 64; // bMaxPacketSize0
611                            response[8] = 0x34; // idVendor low
612                            response[9] = 0x12; // idVendor high
613                            response[10] = 0x78; // idProduct low
614                            response[11] = 0x56; // idProduct high
615                            response[12] = 0x00; // bcdDevice low
616                            response[13] = 0x01; // bcdDevice high
617                            response[14] = 0; // iManufacturer
618                            response[15] = 0; // iProduct
619                            response[16] = 0; // iSerialNumber
620                            response[17] = 1; // bNumConfigurations
621                        }
622                        Ok(response)
623                    } else {
624                        Ok(vec![0u8; data.len()])
625                    }
626                }
627                UsbTransfer::In { length, .. } => Ok(vec![0u8; length]),
628                UsbTransfer::Out { .. } => Ok(Vec::new()),
629            };
630        }
631
632        // Hardware transfer implementation
633        let td_ptr = self.td_buffer_phys as *mut UhciTd;
634        let data_ptr = self.data_buffer_phys as *mut u8;
635        let qh_ptr = self.control_qh_phys as *mut UhciQh;
636
637        match transfer {
638            UsbTransfer::Setup {
639                request_type,
640                request,
641                value,
642                index,
643                data,
644            } => {
645                // Build setup packet (8 bytes)
646                let setup_packet = [
647                    request_type,
648                    request,
649                    (value & 0xFF) as u8,
650                    ((value >> 8) & 0xFF) as u8,
651                    (index & 0xFF) as u8,
652                    ((index >> 8) & 0xFF) as u8,
653                    (data.len() & 0xFF) as u8,
654                    ((data.len() >> 8) & 0xFF) as u8,
655                ];
656
657                // SAFETY: td_ptr, data_ptr, and qh_ptr all point into pages allocated
658                // by allocate_structures(). The TD buffer can hold at least 3 TDs (48 bytes
659                // out of 4096). The data buffer is a full 4KB page. We write the setup
660                // packet (8 bytes) to data_ptr, configure 3 TDs for the SETUP/DATA/STATUS
661                // phases per the UHCI specification, then read the response from the data
662                // buffer at offset 64. copy_nonoverlapping is safe because source and
663                // destination do not overlap and lengths are within allocated bounds.
664                unsafe {
665                    // Copy setup packet to data buffer
666                    core::ptr::copy_nonoverlapping(setup_packet.as_ptr(), data_ptr, 8);
667
668                    // Setup TD for SETUP phase
669                    let setup_td = &mut *td_ptr;
670                    setup_td.setup_packet(device_address, 0, false, 8);
671                    setup_td.buffer_pointer = self.data_buffer_phys as u32;
672                    setup_td.link_pointer = (self.td_buffer_phys as u32 + 16) | 4; // Next TD, depth first
673
674                    // Data TD for IN phase (if reading)
675                    let data_td = &mut *td_ptr.add(1);
676                    let response_len = data.len().min(64) as u16;
677                    data_td.in_packet(device_address, 0, true, response_len);
678                    data_td.buffer_pointer = (self.data_buffer_phys + 64) as u32;
679                    data_td.link_pointer = (self.td_buffer_phys as u32 + 32) | 4; // Next TD
680
681                    // Status TD for OUT phase (zero-length OUT)
682                    let status_td = &mut *td_ptr.add(2);
683                    status_td.out_packet(device_address, 0, true, 0);
684                    status_td.buffer_pointer = 0;
685                    status_td.link_pointer = 1; // Terminate
686
687                    // Point QH to first TD
688                    let qh = &mut *qh_ptr;
689                    qh.element_link = self.td_buffer_phys as u32; // TD pointer (bit 1 = 0 for TD)
690
691                    // Wait for transfer completion
692                    self.wait_for_transfer(td_ptr.add(2), 1000)?;
693
694                    // Read response data
695                    let actual_len = (*td_ptr.add(1)).actual_length() as usize;
696                    let mut response = vec![0u8; actual_len.min(data.len())];
697                    core::ptr::copy_nonoverlapping(
698                        (self.data_buffer_phys + 64) as *const u8,
699                        response.as_mut_ptr(),
700                        response.len(),
701                    );
702
703                    Ok(response)
704                }
705            }
706
707            UsbTransfer::In { endpoint, length } => {
708                let transfer_len = length.min(4096) as u16;
709
710                // SAFETY: Same allocated pages as the Setup case. We configure a single
711                // IN TD pointing to the data buffer, wait for completion, then copy the
712                // received data. actual_len is capped at 4096 by transfer_len.
713                unsafe {
714                    let in_td = &mut *td_ptr;
715                    in_td.in_packet(device_address, endpoint, false, transfer_len);
716                    in_td.buffer_pointer = self.data_buffer_phys as u32;
717                    in_td.link_pointer = 1; // Terminate
718
719                    let qh = &mut *qh_ptr;
720                    qh.element_link = self.td_buffer_phys as u32;
721
722                    self.wait_for_transfer(td_ptr, 1000)?;
723
724                    let actual_len = (*td_ptr).actual_length() as usize;
725                    let mut response = vec![0u8; actual_len];
726                    core::ptr::copy_nonoverlapping(data_ptr, response.as_mut_ptr(), actual_len);
727
728                    Ok(response)
729                }
730            }
731
732            UsbTransfer::Out { endpoint, data } => {
733                let transfer_len = data.len().min(4096);
734
735                // SAFETY: Same allocated pages as Setup/In cases. We copy outgoing data
736                // to the data buffer (transfer_len capped at 4096), configure the OUT TD,
737                // and wait for hardware completion.
738                unsafe {
739                    // Copy data to buffer
740                    core::ptr::copy_nonoverlapping(data.as_ptr(), data_ptr, transfer_len);
741
742                    let out_td = &mut *td_ptr;
743                    out_td.out_packet(device_address, endpoint, false, transfer_len as u16);
744                    out_td.buffer_pointer = self.data_buffer_phys as u32;
745                    out_td.link_pointer = 1; // Terminate
746
747                    let qh = &mut *qh_ptr;
748                    qh.element_link = self.td_buffer_phys as u32;
749
750                    self.wait_for_transfer(td_ptr, 1000)?;
751
752                    Ok(Vec::new())
753                }
754            }
755        }
756    }
757
758    fn set_device_address(&mut self, old_address: u8, new_address: u8) -> Result<(), KernelError> {
759        // SET_ADDRESS is a control transfer
760        let transfer = UsbTransfer::Setup {
761            request_type: 0x00, // Host to device, standard, device
762            request: 0x05,      // SET_ADDRESS
763            value: new_address as u16,
764            index: 0,
765            data: Vec::new(),
766        };
767
768        // Send to old address (or address 0 for new devices)
769        self.transfer(old_address, transfer)?;
770
771        // Wait for device to switch addresses (at least 2ms per USB spec)
772        for _ in 0..2000 {
773            core::hint::spin_loop();
774        }
775
776        crate::println!(
777            "[USB] Device address changed from {} to {}",
778            old_address,
779            new_address
780        );
781
782        Ok(())
783    }
784}