1#![allow(dead_code)]
3#![allow(static_mut_refs)]
4
5use crate::kernel::net;
6use crate::kernel::reclock::RecoverableMutex;
7
8static USB_LOCK: RecoverableMutex<()> = RecoverableMutex::new(());
10
11pub fn force_release_locks(cid: i16) {
13 unsafe {
14 USB_LOCK.force_release_if_core(cid);
15 }
16}
17
18const USB_BASE: usize = 0x3F98_0000;
20
21const GOTGCTL: *mut u32 = USB_BASE as *mut u32;
23const GOTGINT: *mut u32 = (USB_BASE + 0x004) as *mut u32;
24const GAHBCFG: *mut u32 = (USB_BASE + 0x008) as *mut u32;
25const GUSBCFG: *mut u32 = (USB_BASE + 0x00C) as *mut u32;
26const GRSTCTL: *mut u32 = (USB_BASE + 0x010) as *mut u32;
27const GINTSTS: *mut u32 = (USB_BASE + 0x014) as *mut u32;
28const GINTMSK: *mut u32 = (USB_BASE + 0x018) as *mut u32;
29const GSNPSID: *mut u32 = (USB_BASE + 0x040) as *mut u32;
31const GHWCFG2: *mut u32 = (USB_BASE + 0x048) as *mut u32;
32const GRXSTSR: *mut u32 = (USB_BASE + 0x01C) as *mut u32;
33const GRXFSIZ: *mut u32 = (USB_BASE + 0x024) as *mut u32;
34const GNPTXFSIZ: *mut u32 = (USB_BASE + 0x028) as *mut u32;
35const GNPTXSTS: *mut u32 = (USB_BASE + 0x02C) as *mut u32;
36const HPTXFSIZ: *mut u32 = (USB_BASE + 0x100) as *mut u32;
37
38const HCFG: *mut u32 = (USB_BASE + 0x400) as *mut u32;
40const HFIR: *mut u32 = (USB_BASE + 0x404) as *mut u32;
41const HFNUM: *mut u32 = (USB_BASE + 0x408) as *mut u32;
42const HAINT: *mut u32 = (USB_BASE + 0x414) as *mut u32;
43const HAINTMSK: *mut u32 = (USB_BASE + 0x418) as *mut u32;
44const HPRT0: *mut u32 = (USB_BASE + 0x440) as *mut u32;
45const PCGCCTL: *mut u32 = (USB_BASE + 0xE00) as *mut u32;
47
48const HC_BASE: usize = USB_BASE + 0x500;
50fn hc_char(n: usize) -> *mut u32 {
51 (HC_BASE + n * 0x20) as *mut u32
52}
53fn hc_splt(n: usize) -> *mut u32 {
57 (HC_BASE + n * 0x20 + 0x04) as *mut u32
58}
59fn hc_int(n: usize) -> *mut u32 {
60 (HC_BASE + n * 0x20 + 0x08) as *mut u32
61}
62fn hc_intmsk(n: usize) -> *mut u32 {
63 (HC_BASE + n * 0x20 + 0x0C) as *mut u32
64}
65fn hc_tsiz(n: usize) -> *mut u32 {
66 (HC_BASE + n * 0x20 + 0x10) as *mut u32
67}
68fn hc_dma(n: usize) -> *mut u32 {
69 (HC_BASE + n * 0x20 + 0x14) as *mut u32
70}
71
72#[repr(C, packed)]
74#[derive(Copy, Clone, Debug)]
75pub struct UsbSetupPacket {
76 pub request_type: u8,
77 pub request: u8,
78 pub value: u16,
79 pub index: u16,
80 pub length: u16,
81}
82
83#[repr(C, packed)]
85#[derive(Copy, Clone, Debug)]
86pub struct RndisPacketMsg {
87 pub message_type: u32, pub message_length: u32, pub data_offset: u32, pub data_length: u32, pub oob_data_offset: u32, pub oob_data_length: u32, pub num_oob_data_elements: u32, pub packet_information_offset: u32, pub packet_information_length: u32, pub device_vc_handle: u32, pub reserved: u32, }
99
100#[repr(C, align(64))]
102struct DmaBuffer {
103 data: [u8; 2048],
104}
105
106static mut DMA_BUF: DmaBuffer = DmaBuffer { data: [0; 2048] };
107static mut SETUP_BUF: DmaBuffer = DmaBuffer { data: [0; 2048] };
108static mut RX_DMA_BUF: DmaBuffer = DmaBuffer { data: [0; 2048] };
111static mut ETH_RX_BUF: [u8; 2048] = [0; 2048];
112static mut ETH_RX_LEN: usize = 0;
113
114const MAX_HID_DEVICES: usize = 4;
115const HUB_DESCRIPTOR_TYPE: u16 = 0x2900;
116const HUB_FEATURE_PORT_RESET: u16 = 4;
117const HUB_FEATURE_PORT_POWER: u16 = 8;
118const HUB_FEATURE_C_PORT_CONNECTION: u16 = 16;
119const HUB_FEATURE_C_PORT_RESET: u16 = 20;
120
121#[derive(Copy, Clone, PartialEq, Eq, Debug)]
122pub enum UsbDeviceKind {
123 None,
124 Hub,
125 Keyboard,
126 Mouse,
127 Tablet,
128 CdcEthernet,
129}
130
131#[derive(Copy, Clone)]
132struct UsbHidDevice {
133 address: u8,
134 ep0_mps: u16,
135 hid_ep: u8,
136 hid_ep_size: u16,
137 interface_number: u8,
138 kind: UsbDeviceKind,
139 key_prev_state: [u8; 6],
140 shift_pressed: bool,
141 ctrl_pressed: bool,
142 alt_pressed: bool,
143 gui_pressed: bool,
144 data_toggle: u32,
146}
147
148impl UsbHidDevice {
149 const fn empty() -> Self {
150 Self {
151 address: 0,
152 ep0_mps: 8,
153 hid_ep: 0,
154 hid_ep_size: 8,
155 interface_number: 0,
156 kind: UsbDeviceKind::None,
157 key_prev_state: [0; 6],
158 shift_pressed: false,
159 ctrl_pressed: false,
160 alt_pressed: false,
161 gui_pressed: false,
162 data_toggle: 0,
163 }
164 }
165}
166
167pub struct EnumeratedDevice {
168 pub kind: UsbDeviceKind,
169 pub address: u8,
170 pub interface_number: u8,
171 pub ep0_mps: u16,
172 pub hid_ep: u8,
173 pub hid_ep_size: u16,
174 pub port_count: u8,
175 pub bulk_in_ep: u8,
176 pub bulk_out_ep: u8,
177 pub bulk_ep_size: u16,
178 pub data_interface_number: u8,
179 pub data_alt_setting: u8,
180 pub config_value: u8,
182 pub is_rndis: bool,
183 pub i_mac_address: u8,
184 pub mac_address: Option<[u8; 6]>,
185}
186
187impl EnumeratedDevice {
188 pub fn empty() -> Self {
189 Self {
190 kind: UsbDeviceKind::None,
191 address: 0,
192 interface_number: 0,
193 ep0_mps: 8,
194 hid_ep: 0,
195 hid_ep_size: 0,
196 port_count: 0,
197 bulk_in_ep: 0,
198 bulk_out_ep: 0,
199 bulk_ep_size: 64,
200 data_interface_number: 0,
201 data_alt_setting: 0,
202 config_value: 1,
203 is_rndis: false,
204 i_mac_address: 0,
205 mac_address: None,
206 }
207 }
208}
209
210static mut DEV_SPEED: u32 = 0; static mut DEV_ADDR: u8 = 0;
213static mut EP0_MPS: u16 = 8; static mut HID_EP_SIZE: u16 = 8; #[repr(align(64))]
216struct Align64<T>(T);
217
218static mut HID_DEVICES: Align64<[UsbHidDevice; MAX_HID_DEVICES]> = Align64([UsbHidDevice::empty(); MAX_HID_DEVICES]);
219static mut HID_DEVICE_COUNT: Align64<usize> = Align64(0);
220static mut HUB_ADDR: u8 = 0;
221static mut HUB_EP0_MPS: u16 = 8;
222static mut ETH_BULK_OUT_TOGGLE: u32 = 0;
223static mut ETH_BULK_IN_TOGGLE: u32 = 0;
224static mut HUB_PORT_COUNT: u8 = 0;
225static mut NEXT_DEVICE_ADDR: u8 = 1;
226
227static mut CURRENT_HUB_PORT: u8 = 0;
228static mut CURRENT_HUB_PORT_SPEED: u32 = 0; static mut DEV_SPEEDS: [u8; 16] = [0; 16]; static mut DEV_HUB_ADDRS: [u8; 16] = [0; 16]; static mut DEV_HUB_PORTS: [u8; 16] = [0; 16];
234
235fn delay_ms(ms: u32) {
237 let start = crate::kernel::timer::get_system_time_us();
241 let target = ms as u64 * 1000;
242 while crate::kernel::timer::get_system_time_us().wrapping_sub(start) < target {
243 unsafe {
244 core::arch::asm!("nop");
245 }
246 }
247}
248
249unsafe fn wait_bit_set(reg: *mut u32, mask: u32, timeout_ms: u32) -> bool {
253 let start = crate::kernel::timer::get_system_time_us();
254 let limit = timeout_ms as u64 * 1000;
255 loop {
256 if core::ptr::read_volatile(reg) & mask == mask {
257 return true;
258 }
259 if crate::kernel::timer::get_system_time_us().wrapping_sub(start) > limit {
260 return false;
261 }
262 }
263}
264
265unsafe fn wait_bit_clear(reg: *mut u32, mask: u32, timeout_ms: u32) -> bool {
267 let start = crate::kernel::timer::get_system_time_us();
268 let limit = timeout_ms as u64 * 1000;
269 loop {
270 if core::ptr::read_volatile(reg) & mask == 0 {
271 return true;
272 }
273 if crate::kernel::timer::get_system_time_us().wrapping_sub(start) > limit {
274 return false;
275 }
276 }
277}
278
279unsafe fn read_hprt0_safe() -> u32 {
284 let val = core::ptr::read_volatile(HPRT0);
285 val & !(0b0010_1110) }
287
288pub fn init() {
290 unsafe {
292 let initial_gusbcfg = core::ptr::read_volatile(GUSBCFG);
293 let initial_hprt0 = core::ptr::read_volatile(HPRT0);
294 let initial_hcfg = core::ptr::read_volatile(HCFG);
295 let initial_pcgcctl = core::ptr::read_volatile(PCGCCTL);
296 crate::warn!("[USB][DIAG] Initial state: GUSBCFG=0x{:08X} HPRT0=0x{:08X} HCFG=0x{:08X} PCGCCTL=0x{:08X}",
297 initial_gusbcfg, initial_hprt0, initial_hcfg, initial_pcgcctl);
298 }
299
300 match crate::kernel::mailbox::power_on_usb() {
302 Ok(()) => {}
303 Err(e) => crate::warn!("[USB] Mailbox USB power ON: FAILED ({})", e),
304 }
305 delay_ms(500);
306
307 unsafe {
308 reset_device_state();
309
310 core::ptr::write_volatile(PCGCCTL, 0);
313 delay_ms(10);
314
315 let mut usbcfg = core::ptr::read_volatile(GUSBCFG);
316
317 usbcfg &= !(1 << 20); usbcfg &= !(1 << 22); usbcfg &= !(1 << 4); usbcfg &= !(1 << 3); usbcfg &= !(1 << 17); usbcfg &= !(1 << 19); usbcfg |= 1 << 29; usbcfg &= !(1 << 30); usbcfg &= !(1 << 9); usbcfg &= !(1 << 8); core::ptr::write_volatile(GUSBCFG, usbcfg);
342 delay_ms(10);
343
344 let mut hcfg = core::ptr::read_volatile(HCFG);
346 hcfg &= !0x3; core::ptr::write_volatile(HCFG, hcfg);
348 delay_ms(10);
349
350 let ahb_idle_before = wait_bit_set(GRSTCTL, 1 << 31, 100); core::ptr::write_volatile(GRSTCTL, 1 << 0); let csftrst_cleared = wait_bit_clear(GRSTCTL, 1 << 0, 100); let ahb_idle_after = wait_bit_set(GRSTCTL, 1 << 31, 100);
355 crate::warn!(
356 "[USB] srst: ahb_idle={}/{} csftrst_clr={} GRSTCTL=0x{:08X}",
357 ahb_idle_before,
358 ahb_idle_after,
359 csftrst_cleared,
360 core::ptr::read_volatile(GRSTCTL)
361 );
362 delay_ms(100);
363
364 core::ptr::write_volatile(PCGCCTL, 0);
366 delay_ms(10);
367
368 let post_reset_usbcfg = core::ptr::read_volatile(GUSBCFG);
370 let post_reset_hcfg = core::ptr::read_volatile(HCFG);
371 crate::warn!(
372 "[USB][DIAG] Post-reset: GUSBCFG=0x{:08X} HCFG=0x{:08X}",
373 post_reset_usbcfg,
374 post_reset_hcfg
375 );
376
377 let mut usbcfg = post_reset_usbcfg;
381 usbcfg |= 1 << 29; usbcfg &= !(1 << 30); core::ptr::write_volatile(GUSBCFG, usbcfg);
385 delay_ms(10);
386
387 let mut hcfg = core::ptr::read_volatile(HCFG);
388 if (hcfg & 0x3) != 0 {
390 hcfg &= !0x3; core::ptr::write_volatile(HCFG, hcfg);
392 delay_ms(10);
393 }
394
395 let mut curmod_ok = false;
397 for _ in 0..100 {
398 let gintsts = core::ptr::read_volatile(GINTSTS);
399 if (gintsts & 1) != 0 {
400 curmod_ok = true;
402 break;
403 }
404 delay_ms(5);
405 }
406 if !curmod_ok {
407 crate::warn!(
408 "[USB] WARNING: Host Mode transition timed out (GINTSTS=0x{:08X})",
409 core::ptr::read_volatile(GINTSTS)
410 );
411 }
412
413 let mut ahbcfg = core::ptr::read_volatile(GAHBCFG);
415 ahbcfg |= 1 << 5; ahbcfg |= 1 << 4; ahbcfg &= !(3 << 1); ahbcfg |= 1 << 0; core::ptr::write_volatile(GAHBCFG, ahbcfg);
421 crate::warn!(
422 "[USB] GAHBCFG=0x{:08X} GINTMSK=0x{:08X}",
423 core::ptr::read_volatile(GAHBCFG),
424 (1u32 << 3) | (1 << 24) | (1 << 25) | (1 << 29)
425 );
426
427 core::ptr::write_volatile(GINTSTS, 0xFFFF_FFFF); core::ptr::write_volatile(GINTMSK, (1 << 3) | (1 << 24) | (1 << 25) | (1 << 29));
431
432 crate::info!("[USB] InitHost: restart PHY clock (PCGCCTL=0)...");
435 core::ptr::write_volatile(PCGCCTL, 0);
436
437 let mut hcfg = core::ptr::read_volatile(HCFG);
439 hcfg &= !0x3; core::ptr::write_volatile(HCFG, hcfg);
441 crate::warn!(
442 "[USB] HCFG=0x{:08X} FIFO RX/NP/P=1024/1024/1024",
443 core::ptr::read_volatile(HCFG)
444 );
445
446 core::ptr::write_volatile(GRXFSIZ, 1024);
449 core::ptr::write_volatile(GNPTXFSIZ, 1024 | (1024 << 16));
450 core::ptr::write_volatile(HPTXFSIZ, (1024 + 1024) | (1024 << 16));
451
452 core::ptr::write_volatile(GRSTCTL, (0x10 << 6) | (1 << 5)); let txflush = wait_bit_clear(GRSTCTL, 1 << 5, 100);
455 core::ptr::write_volatile(GRSTCTL, 1 << 4); let rxflush = wait_bit_clear(GRSTCTL, 1 << 4, 100);
457 if !txflush || !rxflush {
458 crate::warn!("[USB] FIFO flush TIMEOUT: tx={} rx={}", txflush, rxflush);
459 }
460
461 let hprt = read_hprt0_safe();
463 if (hprt & (1 << 12)) == 0 {
464 core::ptr::write_volatile(HPRT0, hprt | (1 << 12)); }
466 delay_ms(500);
467
468 crate::warn!("[USB] Waiting for device connection...");
470 let mut t = 20;
471 loop {
472 let v = core::ptr::read_volatile(HPRT0);
473 if (v & 1) != 0 {
474 crate::warn!("[USB] Device detected! HPRT0=0x{:08X}", v);
475 break;
476 }
477 delay_ms(100);
478 t -= 1;
479 if t == 0 {
480 crate::warn!("[USB] WARNING: No USB device detected.");
481 return;
482 }
483 }
484 delay_ms(1000); const RESET_RETRIES: u32 = 8;
487 let mut enabled = false;
488 let mut hprt_final = 0u32;
489 let mut last_reset_try = 0u32;
490 for reset_try in 0..RESET_RETRIES {
491 let v = read_hprt0_safe();
492 core::ptr::write_volatile(HPRT0, v | (1 << 12) | (1 << 8)); delay_ms(100);
494 let v = read_hprt0_safe();
495 core::ptr::write_volatile(HPRT0, (v | (1 << 12)) & !(1 << 8)); delay_ms(200);
497
498 hprt_final = core::ptr::read_volatile(HPRT0);
499 enabled = (hprt_final & (1 << 2)) != 0; last_reset_try = reset_try;
501
502 if !enabled {
503 delay_ms(50);
504 continue;
505 }
506
507 DEV_SPEED = (hprt_final >> 17) & 0x3; if DEV_SPEED == 0 {
509 break;
510 } delay_ms(50);
512 }
513 crate::warn!(
514 "[USB] reset×{}: HPRT0=0x{:08X} PrtSpd={} ({})",
515 last_reset_try + 1,
516 hprt_final,
517 DEV_SPEED,
518 match DEV_SPEED {
519 0 => "HS",
520 1 => "FS",
521 2 => "LS",
522 _ => "?",
523 }
524 );
525
526 if enabled {
527 DEV_SPEED = (hprt_final >> 17) & 0x3; {
530 let snpsid = core::ptr::read_volatile(GSNPSID);
531 let hwcfg2 = core::ptr::read_volatile(GHWCFG2);
532 let hfir = core::ptr::read_volatile(HFIR);
533 let hfnum1 = core::ptr::read_volatile(HFNUM) & 0x3FFF;
534 delay_ms(2);
535 let hfnum2 = core::ptr::read_volatile(HFNUM) & 0x3FFF;
536 crate::warn!(
537 "[USB][DIAG] SNPSID=0x{:08X} HWCFG2=0x{:08X} GUSBCFG=0x{:08X} HCFG=0x{:08X}",
538 snpsid,
539 hwcfg2,
540 core::ptr::read_volatile(GUSBCFG),
541 core::ptr::read_volatile(HCFG)
542 );
543 crate::warn!(
544 "[USB][DIAG] HFIR=0x{:08X} frame:{}->{} ({})",
545 hfir,
546 hfnum1,
547 hfnum2,
548 if hfnum2 != hfnum1 {
549 "SOF OK"
550 } else {
551 "SOF STUCK!"
552 }
553 );
554 }
555
556 {
572 let v = read_hprt0_safe();
573 core::ptr::write_volatile(HPRT0, v | (1 << 1) | (1 << 3) | (1 << 5));
574 let after = core::ptr::read_volatile(GINTSTS);
575 crate::warn!(
576 "[USB][DIAG] W1C cleared. HPRT0=0x{:08X} GINTSTS=0x{:08X}",
577 core::ptr::read_volatile(HPRT0),
578 after
579 );
580 }
581
582 enumerate_root_device();
584 } else {
585 crate::warn!(
586 "[USB] ERROR: Port did not enable after reset (500ms timeout). HPRT0=0x{:08X}",
587 hprt_final
588 );
589 }
590 }
591}
592
593unsafe fn reset_device_state() {
594 DEV_ADDR = 0;
595 EP0_MPS = 8;
596 HID_EP_SIZE = 8;
597 HID_DEVICE_COUNT.0 = 0;
598 HUB_ADDR = 0;
599 HUB_EP0_MPS = 8;
600 HUB_PORT_COUNT = 0;
601 NEXT_DEVICE_ADDR = 1;
602 CURRENT_HUB_PORT = 0;
603 CURRENT_HUB_PORT_SPEED = 0;
604 DEV_SPEEDS = [0; 16];
605 DEV_HUB_ADDRS = [0; 16];
606 DEV_HUB_PORTS = [0; 16];
607 for idx in 0..MAX_HID_DEVICES {
608 HID_DEVICES.0[idx] = UsbHidDevice::empty();
609 }
610}
611
612unsafe fn resolve_split_target(hub_addr_in: u8, port_in: u8) -> (u8, u8) {
617 let mut hub_addr = hub_addr_in;
618 let mut port = port_in;
619 for _ in 0..16 {
622 if hub_addr == 0 || DEV_SPEEDS[hub_addr as usize] == 2 {
623 break;
624 }
625 let parent_addr = DEV_HUB_ADDRS[hub_addr as usize];
626 let parent_port = DEV_HUB_PORTS[hub_addr as usize];
627 if parent_addr == 0 && parent_port == 0 {
628 break;
630 }
631 hub_addr = parent_addr;
632 port = parent_port;
633 }
634 (hub_addr, port)
635}
636
637unsafe fn select_control_target(address: u8, ep0_mps: u16) {
638 DEV_ADDR = address;
639 EP0_MPS = ep0_mps;
640}
641
642unsafe fn register_hid_device(device: EnumeratedDevice) {
643 if HID_DEVICE_COUNT.0 >= MAX_HID_DEVICES {
644 crate::debug!(
645 " WARNING: HID device table is full. Skipping address {}.",
646 device.address
647 );
648 return;
649 }
650
651 HID_DEVICES.0[HID_DEVICE_COUNT.0] = UsbHidDevice {
652 address: device.address,
653 ep0_mps: device.ep0_mps,
654 hid_ep: device.hid_ep,
655 hid_ep_size: device.hid_ep_size,
656 interface_number: device.interface_number,
657 kind: device.kind,
658 key_prev_state: [0; 6],
659 shift_pressed: false,
660 ctrl_pressed: false,
661 alt_pressed: false,
662 gui_pressed: false,
663 data_toggle: 0,
664 };
665 HID_DEVICE_COUNT.0 += 1;
666
667 let count_addr = &HID_DEVICE_COUNT.0 as *const usize as usize;
669 crate::kernel::mmu::clean_dcache_range(count_addr, core::mem::size_of_val(&HID_DEVICE_COUNT.0));
670 let devices_addr = HID_DEVICES.0.as_ptr() as usize;
671 crate::kernel::mmu::clean_dcache_range(devices_addr, core::mem::size_of_val(&HID_DEVICES.0));
672 core::arch::asm!("dsb sy", "isb", options(nostack));
673
674 let kind = match device.kind {
675 UsbDeviceKind::Keyboard => "keyboard",
676 UsbDeviceKind::Mouse => "mouse",
677 UsbDeviceKind::Tablet => "tablet",
678 _ => "unknown",
679 };
680 crate::warn!(
681 "[USB] Registered USB HID {} at address {} (EP {}, MPS {}).",
682 kind,
683 device.address,
684 device.hid_ep,
685 device.hid_ep_size
686 );
687}
688
689unsafe fn parse_config_descriptor(total_len: u16, device_class: u8) -> EnumeratedDevice {
690 let mut result = EnumeratedDevice::empty();
691 if total_len >= 9 {
696 result.config_value = DMA_BUF.data[5];
697 }
698 let mut current_kind = if device_class == 0x09 {
699 UsbDeviceKind::Hub
700 } else {
701 UsbDeviceKind::None
702 };
703 let mut current_interface = 0u8;
704 let mut current_alt = 0u8;
705 let mut current_if_class = 0u8;
707 let mut cdc_control_if = 0u8;
708 let mut cdc_data_if = 0u8;
709 let mut cdc_bulk_in = 0u8;
710 let mut cdc_bulk_out = 0u8;
711 let mut cdc_bulk_mps = 0u16;
712 let mut cdc_data_alt_setting = 0u8;
713 let mut cdc_detected = false;
714 let mut cdc_is_rndis = false;
715 let mut i = 0usize;
716
717 if current_kind == UsbDeviceKind::Hub {
718 result.kind = UsbDeviceKind::Hub;
719 }
720
721 while i < total_len as usize {
722 let desc_len = DMA_BUF.data[i] as usize;
723 if desc_len < 2 {
724 break;
725 }
726
727 let desc_type = DMA_BUF.data[i + 1];
728 if desc_type == 0x04 {
729 current_interface = DMA_BUF.data[i + 2];
730 let current_alt_setting = DMA_BUF.data[i + 3];
731 current_alt = current_alt_setting;
732 let if_class = DMA_BUF.data[i + 5];
733 let if_subclass = DMA_BUF.data[i + 6];
734 let if_protocol = DMA_BUF.data[i + 7];
735 let is_cdc_control = (if_class == 0x02 && matches!(if_subclass, 0x00 | 0x02 | 0x06))
736 || (if_class == 0xE0 && if_subclass == 0x01 && if_protocol == 0x03);
737 current_if_class = if_class;
738
739 if is_cdc_control {
740 cdc_detected = true;
741 cdc_control_if = current_interface;
742 cdc_is_rndis = if_class == 0xE0
747 || (if_class == 0x02 && if_subclass == 0x02 && if_protocol == 0xFF);
748 }
749 if if_class == 0x0A {
750 cdc_data_if = current_interface;
751 cdc_data_alt_setting = current_alt_setting;
752 }
753
754 current_kind = match if_class {
755 0x09 => UsbDeviceKind::Hub,
756 0x03 if if_protocol == 1 => UsbDeviceKind::Keyboard,
757 0x03 if if_protocol == 2 => UsbDeviceKind::Mouse,
758 0x03 if if_protocol == 0 => UsbDeviceKind::Tablet, 0x02 if matches!(if_subclass, 0x00 | 0x02 | 0x06) => UsbDeviceKind::CdcEthernet,
760 0xE0 if if_subclass == 0x01 && if_protocol == 0x03 => UsbDeviceKind::CdcEthernet,
761 _ => UsbDeviceKind::None,
762 };
763
764 if result.kind == UsbDeviceKind::None && current_kind != UsbDeviceKind::None {
765 result.kind = current_kind;
766 result.interface_number = current_interface;
767 if current_kind == UsbDeviceKind::Hub {
768 break;
769 }
770 }
771 } else if desc_type == 0x05
772 && (current_kind == UsbDeviceKind::Keyboard
773 || current_kind == UsbDeviceKind::Mouse
774 || current_kind == UsbDeviceKind::Tablet)
775 {
776 let ep_addr = DMA_BUF.data[i + 2];
777 let ep_attr = DMA_BUF.data[i + 3];
778 let raw_ep_size = ((DMA_BUF.data[i + 5] as u16) << 8 | (DMA_BUF.data[i + 4] as u16)) & 0x07FF;
779 let ep_size = raw_ep_size.min(64); if (ep_addr & 0x80) != 0 && (ep_attr & 0x3) == 0x3 {
781 result.kind = current_kind;
782 result.interface_number = current_interface;
783 result.hid_ep = ep_addr & 0x0F;
784 result.hid_ep_size = ep_size;
785 break;
786 }
787 } else if desc_type == 0x05 && cdc_detected && current_if_class == 0x0A {
788 let ep_addr = DMA_BUF.data[i + 2];
789 let ep_attr = DMA_BUF.data[i + 3];
790 let raw_ep_size = ((DMA_BUF.data[i + 5] as u16) << 8 | (DMA_BUF.data[i + 4] as u16)) & 0x07FF;
791 let ep_size = raw_ep_size.min(1024);
792 if (ep_attr & 0x3) == 0x2 {
793 if (ep_addr & 0x80) != 0 {
794 cdc_bulk_in = ep_addr & 0x0F;
795 cdc_bulk_mps = ep_size;
796 } else {
797 cdc_bulk_out = ep_addr & 0x0F;
798 cdc_bulk_mps = ep_size;
799 }
800 cdc_data_alt_setting = current_alt;
804 }
805 } else if desc_type == 0x24 && DMA_BUF.data[i + 2] == 0x0F {
806 if desc_len >= 4 {
808 result.i_mac_address = DMA_BUF.data[i + 3];
809 }
810 }
811
812 i += desc_len;
813 }
814
815 if cdc_detected && cdc_bulk_in != 0 && cdc_bulk_out != 0 {
816 result.kind = UsbDeviceKind::CdcEthernet;
817 result.interface_number = cdc_control_if;
818 result.data_interface_number = cdc_data_if;
819 result.data_alt_setting = cdc_data_alt_setting;
820 result.bulk_in_ep = cdc_bulk_in;
821 result.bulk_out_ep = cdc_bulk_out;
822 result.bulk_ep_size = cdc_bulk_mps;
823 result.is_rndis = cdc_is_rndis;
824 }
825
826 result
827}
828
829unsafe fn hub_get_port_count() -> Option<u8> {
830 select_control_target(HUB_ADDR, HUB_EP0_MPS);
831 let req = UsbSetupPacket {
832 request_type: 0xA0,
833 request: 0x06,
834 value: HUB_DESCRIPTOR_TYPE,
835 index: 0,
836 length: 9,
837 };
838 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
839 if usb_control_transfer(req, buf_phys, 9, true).is_err() {
840 return None;
841 }
842 Some(DMA_BUF.data[2])
843}
844
845unsafe fn hub_set_port_feature(port: u8, feature: u16) -> bool {
846 select_control_target(HUB_ADDR, HUB_EP0_MPS);
847 let req = UsbSetupPacket {
848 request_type: 0x23,
849 request: 0x03,
850 value: feature,
851 index: port as u16,
852 length: 0,
853 };
854 usb_control_transfer(req, 0, 0, false).is_ok()
855}
856
857unsafe fn hub_clear_port_feature(port: u8, feature: u16) -> bool {
858 select_control_target(HUB_ADDR, HUB_EP0_MPS);
859 let req = UsbSetupPacket {
860 request_type: 0x23,
861 request: 0x01,
862 value: feature,
863 index: port as u16,
864 length: 0,
865 };
866 usb_control_transfer(req, 0, 0, false).is_ok()
867}
868
869unsafe fn hub_get_port_status(port: u8) -> Option<u32> {
870 select_control_target(HUB_ADDR, HUB_EP0_MPS);
871 let req = UsbSetupPacket {
872 request_type: 0xA3,
873 request: 0x00,
874 value: 0,
875 index: port as u16,
876 length: 4,
877 };
878 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
879 if usb_control_transfer(req, buf_phys, 4, true).is_err() {
880 return None;
881 }
882
883 let status = DMA_BUF.data[0] as u32
884 | ((DMA_BUF.data[1] as u32) << 8)
885 | ((DMA_BUF.data[2] as u32) << 16)
886 | ((DMA_BUF.data[3] as u32) << 24);
887 Some(status)
888}
889
890unsafe fn hub_reset_port(port: u8) -> bool {
891 let _ = hub_clear_port_feature(port, HUB_FEATURE_C_PORT_CONNECTION);
892 let _ = hub_clear_port_feature(port, HUB_FEATURE_C_PORT_RESET);
893
894 if !hub_set_port_feature(port, HUB_FEATURE_PORT_RESET) {
895 return false;
896 }
897 delay_ms(100);
898 let _ = hub_clear_port_feature(port, HUB_FEATURE_C_PORT_RESET);
899 delay_ms(50);
900
901 for _ in 0..10 {
902 if let Some(status) = hub_get_port_status(port) {
903 if (status & 0x0003) == 0x0003 {
904 return true;
905 }
906 }
907 delay_ms(20);
908 }
909
910 false
911}
912
913unsafe fn enumerate_default_address_device(
914 new_address: u8,
915 label: &str,
916) -> Option<EnumeratedDevice> {
917 crate::info!("[USB] {}: starting enumeration on default address.", label);
918
919 select_control_target(0, 64);
920 HID_EP_SIZE = 8;
921
922 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
923 let req = UsbSetupPacket {
924 request_type: 0x80,
925 request: 0x06,
926 value: 0x0100,
927 index: 0,
928 length: 8,
929 };
930 if usb_control_transfer(req, buf_phys, 8, true).is_err() {
931 crate::warn!(
932 "[USB] {}: failed to read first device descriptor bytes.",
933 label
934 );
935 return None;
936 }
937
938 let ep0_mps = DMA_BUF.data[7] as u16;
939 crate::warn!(
940 "[USB] {}: max packet size = {} (parent hub_addr={} port={} speed={})",
941 label,
942 ep0_mps,
943 unsafe { HUB_ADDR },
944 unsafe { CURRENT_HUB_PORT },
945 unsafe { CURRENT_HUB_PORT_SPEED }
946 );
947 select_control_target(0, ep0_mps);
948
949 let set_addr_req = UsbSetupPacket {
950 request_type: 0x00,
951 request: 0x05,
952 value: new_address as u16,
953 index: 0,
954 length: 0,
955 };
956 if usb_control_transfer(set_addr_req, 0, 0, false).is_err() {
957 crate::info!("[USB] {}: failed to set address {}.", label, new_address);
958 return None;
959 }
960
961 delay_ms(20);
962 unsafe {
963 DEV_SPEEDS[new_address as usize] = CURRENT_HUB_PORT_SPEED as u8;
964 DEV_HUB_ADDRS[new_address as usize] = HUB_ADDR;
967 DEV_HUB_PORTS[new_address as usize] = CURRENT_HUB_PORT;
968 }
969 select_control_target(new_address, ep0_mps);
970
971 let req_full = UsbSetupPacket {
972 request_type: 0x80,
973 request: 0x06,
974 value: 0x0100,
975 index: 0,
976 length: 18,
977 };
978 if usb_control_transfer(req_full, buf_phys, 18, true).is_err() {
979 crate::info!("[USB] {}: failed to read full device descriptor.", label);
980 return None;
981 }
982
983 let vid = (DMA_BUF.data[9] as u16) << 8 | (DMA_BUF.data[8] as u16);
984 let pid = (DMA_BUF.data[11] as u16) << 8 | (DMA_BUF.data[10] as u16);
985 let class = DMA_BUF.data[4];
986 let subclass = DMA_BUF.data[5];
987 let protocol = DMA_BUF.data[6];
988 crate::info!(
989 "[USB] {}: VID=0x{:04X} PID=0x{:04X} CLASS=0x{:02X} SUB=0x{:02X} PROTO=0x{:02X}",
990 label,
991 vid,
992 pid,
993 class,
994 subclass,
995 protocol
996 );
997
998 let config_req = UsbSetupPacket {
999 request_type: 0x80,
1000 request: 0x06,
1001 value: 0x0200,
1002 index: 0,
1003 length: 9,
1004 };
1005 if usb_control_transfer(config_req, buf_phys, 9, true).is_err() {
1006 crate::info!(
1007 "[USB] {}: failed to read configuration descriptor header.",
1008 label
1009 );
1010 return None;
1011 }
1012
1013 let total_len = (DMA_BUF.data[3] as u16) << 8 | (DMA_BUF.data[2] as u16);
1014 let req_config_all = UsbSetupPacket {
1015 request_type: 0x80,
1016 request: 0x06,
1017 value: 0x0200,
1018 index: 0,
1019 length: total_len,
1020 };
1021 if usb_control_transfer(req_config_all, buf_phys, total_len as u32, true).is_err() {
1022 crate::info!(
1023 "[USB] {}: failed to read full configuration descriptor.",
1024 label
1025 );
1026 return None;
1027 }
1028
1029 let mut result = parse_config_descriptor(total_len, class);
1030
1031 let mut mac_opt: Option<[u8; 6]> = None;
1033 if result.i_mac_address != 0 {
1034 let req_str = UsbSetupPacket {
1035 request_type: 0x80,
1036 request: 0x06,
1037 value: 0x0300 | (result.i_mac_address as u16),
1038 index: 0x0409, length: 255,
1040 };
1041 if usb_control_transfer(req_str, buf_phys, 255, true).is_ok() {
1042 let str_len = DMA_BUF.data[0] as usize;
1043 if str_len >= 26 && DMA_BUF.data[1] == 0x03 {
1044 let mut mac = [0u8; 6];
1045 let mut valid = true;
1046 for j in 0..6 {
1047 let hi_char = DMA_BUF.data[2 + j * 4] as char;
1048 let lo_char = DMA_BUF.data[2 + j * 4 + 2] as char;
1049 let hi = hi_char.to_digit(16);
1050 let lo = lo_char.to_digit(16);
1051 if let (Some(h), Some(l)) = (hi, lo) {
1052 mac[j] = ((h << 4) | l) as u8;
1053 } else {
1054 valid = false;
1055 break;
1056 }
1057 }
1058 if valid {
1059 mac_opt = Some(mac);
1060 }
1061 }
1062 }
1063 }
1064
1065 result.address = new_address;
1066 result.ep0_mps = ep0_mps;
1067 result.mac_address = mac_opt;
1068
1069 let set_config_req = UsbSetupPacket {
1070 request_type: 0x00,
1071 request: 0x09,
1072 value: result.config_value.max(1) as u16, index: 0,
1074 length: 0,
1075 };
1076 if usb_control_transfer(set_config_req, 0, 0, false).is_err() {
1077 crate::debug!("[USB] {}: failed to activate configuration.", label);
1078 return None;
1079 }
1080 delay_ms(20);
1081
1082 match result.kind {
1083 UsbDeviceKind::Hub => {
1084 HUB_ADDR = new_address;
1085 HUB_EP0_MPS = ep0_mps;
1086 if let Some(port_count) = hub_get_port_count() {
1087 result.port_count = port_count;
1088 crate::debug!(
1089 "[USB] {}: identified as USB hub with {} port(s).",
1090 label,
1091 port_count
1092 );
1093 } else {
1094 crate::debug!("[USB] {}: failed to read hub descriptor.", label);
1095 return None;
1096 }
1097 }
1098 UsbDeviceKind::Keyboard | UsbDeviceKind::Mouse | UsbDeviceKind::Tablet => {
1099 let set_protocol_req = UsbSetupPacket {
1100 request_type: 0x21,
1101 request: 0x0B,
1102 value: 0,
1103 index: result.interface_number as u16,
1104 length: 0,
1105 };
1106 let _ = usb_control_transfer(set_protocol_req, 0, 0, false);
1107 let kind_str = match result.kind {
1108 UsbDeviceKind::Keyboard => "keyboard",
1109 UsbDeviceKind::Mouse => "mouse",
1110 UsbDeviceKind::Tablet => "tablet",
1111 _ => "unknown",
1112 };
1113 crate::debug!(
1114 "[USB] {}: identified as USB HID {} on interface {} endpoint {}.",
1115 label,
1116 kind_str,
1117 result.interface_number,
1118 result.hid_ep
1119 );
1120 }
1121 UsbDeviceKind::CdcEthernet => {
1122 if result.data_alt_setting != 0 {
1123 let set_interface_req = UsbSetupPacket {
1124 request_type: 0x01,
1125 request: 0x0B, value: result.data_alt_setting as u16,
1127 index: result.data_interface_number as u16,
1128 length: 0,
1129 };
1130 if usb_control_transfer(set_interface_req, 0, 0, false).is_err() {
1131 crate::debug!("[USB] {}: failed to set CDC-ECM data alternate setting.", label);
1132 return None;
1133 }
1134 }
1135
1136 if !result.is_rndis {
1137 let set_packet_filter_req = UsbSetupPacket {
1138 request_type: 0x21,
1139 request: 0x43,
1140 value: 0x000F, index: result.interface_number as u16,
1142 length: 0,
1143 };
1144 if usb_control_transfer(set_packet_filter_req, 0, 0, false).is_err() {
1145 crate::debug!("[USB] {}: CDC-ECM packet filter set failed.", label);
1146 }
1147 } else {
1148 let init_req = UsbSetupPacket {
1149 request_type: 0x21,
1150 request: 0x00, value: 0,
1152 index: result.interface_number as u16,
1153 length: 24,
1154 };
1155 let mut init_msg = [0u32; 6];
1156 init_msg[0] = 0x00000002; init_msg[1] = 24;
1158 init_msg[2] = 1;
1159 init_msg[3] = 1;
1160 init_msg[4] = 1;
1161 init_msg[5] = 1580; let init_ptr = &init_msg as *const u32 as *const u8;
1164 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
1165 unsafe {
1166 core::ptr::copy_nonoverlapping(init_ptr, DMA_BUF.data.as_mut_ptr(), 24);
1167 }
1168
1169 let init_ok = usb_control_transfer(init_req, buf_phys, 24, false).is_ok();
1170 crate::info!("[USB] RNDIS DIAG: INITIALIZE_MSG sent ok={}", init_ok);
1171
1172 delay_ms(10);
1174 let get_resp_req = UsbSetupPacket {
1175 request_type: 0xA1,
1176 request: 0x01, value: 0,
1178 index: result.interface_number as u16,
1179 length: 1024,
1180 };
1181 let resp_ok = usb_control_transfer(get_resp_req, buf_phys, 1024, true).is_ok();
1182 crate::info!("[USB] RNDIS DIAG: GET_RESPONSE ok={} head={:02x} {:02x} {:02x} {:02x} | {:02x} {:02x} {:02x} {:02x}",
1183 resp_ok,
1184 DMA_BUF.data[0], DMA_BUF.data[1], DMA_BUF.data[2], DMA_BUF.data[3],
1185 DMA_BUF.data[16], DMA_BUF.data[17], DMA_BUF.data[18], DMA_BUF.data[19]);
1186
1187 let _set_req = UsbSetupPacket {
1188 request_type: 0x21,
1189 request: 0x00,
1190 value: 0,
1191 index: result.interface_number as u16,
1192 length: 32,
1193 };
1194 let mut set_msg = [0u32; 8];
1195 set_msg[0] = 0x00000005; set_msg[1] = 32;
1197 set_msg[2] = 2;
1198 set_msg[3] = 0x0001010E; set_msg[6] = 0; set_msg[7] = 0x0000000F; let set_req = UsbSetupPacket {
1203 request_type: 0x21,
1204 request: 0x00, value: 0,
1206 index: result.interface_number as u16,
1207 length: 32,
1208 };
1209 unsafe {
1210 core::ptr::copy_nonoverlapping(
1211 set_msg.as_ptr() as *const u8,
1212 DMA_BUF.data.as_mut_ptr(),
1213 32,
1214 );
1215 }
1216 let set_ok = usb_control_transfer(set_req, buf_phys, 32, false).is_ok();
1217 crate::info!("[USB] RNDIS DIAG: SET_PACKET_FILTER sent ok={}", set_ok);
1218 if set_ok {
1219 delay_ms(10);
1220 let read_req = UsbSetupPacket {
1221 request_type: 0xA1,
1222 request: 0x01,
1223 value: 0,
1224 index: result.interface_number as u16,
1225 length: 64,
1226 };
1227 let r_ok = usb_control_transfer(read_req, buf_phys, 64, true).is_ok();
1228 crate::info!(
1229 "RNDIS DIAG: SET_RESPONSE ok={} status={:02x}{:02x}{:02x}{:02x}",
1230 r_ok,
1231 DMA_BUF.data[15],
1232 DMA_BUF.data[14],
1233 DMA_BUF.data[13],
1234 DMA_BUF.data[12]
1235 );
1236 }
1237 }
1238
1239 crate::debug!(
1240 "{}: identified as USB Ethernet {} (ctrl if {}, data if {} alt {}, bulk in {}, bulk out {}, mps {}).",
1241 label,
1242 if result.is_rndis { "RNDIS" } else { "CDC-ECM" },
1243 result.interface_number,
1244 result.data_interface_number,
1245 result.data_alt_setting,
1246 result.bulk_in_ep,
1247 result.bulk_out_ep,
1248 result.bulk_ep_size
1249 );
1250 let default_mac = [0x02, 0x00, 0xA1, 0xCE, 0x00, 0x01];
1251 let mac = result.mac_address.unwrap_or(default_mac);
1252 net::register_usb_ethernet(
1253 result.address,
1254 result.bulk_in_ep,
1255 result.bulk_out_ep,
1256 result.bulk_ep_size,
1257 result.is_rndis,
1258 mac,
1259 );
1260 }
1261 UsbDeviceKind::None => {
1262 crate::debug!("[USB] {}: unsupported USB device.", label);
1263 return None;
1264 }
1265 }
1266
1267 Some(result)
1268}
1269
1270unsafe fn enumerate_hub_children(depth: u8) {
1271 if depth >= 4 {
1273 crate::warn!("[USB] Hub nesting too deep ({}). Skipping.", depth);
1274 return;
1275 }
1276 crate::info!("[USB] Starting USB hub child enumeration (depth {})...", depth);
1277
1278 let my_hub_addr = HUB_ADDR;
1280 let my_hub_mps = HUB_EP0_MPS;
1281 let my_port_count = HUB_PORT_COUNT;
1282
1283 for port in 1..=my_port_count {
1284 let _ = hub_set_port_feature(port, HUB_FEATURE_PORT_POWER);
1285 }
1286 crate::info!("[USB] Waiting 1000ms for USB hub ports to settle...");
1287 delay_ms(1000); for port in 1..=my_port_count {
1290 let status = match hub_get_port_status(port) {
1291 Some(status) => status,
1292 None => {
1293 crate::debug!("[USB] Hub port {}: failed to read status.", port);
1294 continue;
1295 }
1296 };
1297
1298 if (status & 0x0001) == 0 {
1299 continue;
1300 }
1301
1302 crate::warn!(
1303 "[USB] Hub port {}: device connected. status=0x{:08X} speed={}",
1304 port,
1305 status,
1306 CURRENT_HUB_PORT_SPEED
1307 );
1308 if !hub_reset_port(port) {
1309 crate::warn!("[USB] Hub port {}: reset failed.", port);
1310 continue;
1311 }
1312
1313 delay_ms(100);
1315
1316 let status_post = match hub_get_port_status(port) {
1318 Some(s) => s,
1319 None => {
1320 crate::warn!("[USB] Hub port {}: failed to read status post-reset.", port);
1321 continue;
1322 }
1323 };
1324 unsafe {
1325 CURRENT_HUB_PORT_SPEED = (status_post >> 9) & 0x3;
1326 }
1327 crate::warn!(
1328 "[USB] Hub port {}: reset success. status=0x{:08X} speed={}",
1329 port,
1330 status_post,
1331 unsafe { CURRENT_HUB_PORT_SPEED }
1332 );
1333
1334 let child_addr = NEXT_DEVICE_ADDR + 1;
1335 let label_buf = [
1336 b'H',
1337 b'u',
1338 b'b',
1339 b' ',
1340 b'P',
1341 b'o',
1342 b'r',
1343 b't',
1344 b' ',
1345 b'0' + port,
1346 ];
1347 let label = unsafe { core::str::from_utf8_unchecked(&label_buf) };
1348
1349 unsafe {
1351 CURRENT_HUB_PORT = port;
1352 }
1353
1354 NEXT_DEVICE_ADDR = child_addr;
1359
1360 if let Some(child) = enumerate_default_address_device(child_addr, label) {
1361 match child.kind {
1362 UsbDeviceKind::Keyboard | UsbDeviceKind::Mouse | UsbDeviceKind::Tablet => {
1363 register_hid_device(child)
1364 }
1365 UsbDeviceKind::CdcEthernet => {
1366 crate::debug!("[USB] Hub port {}: USB Ethernet configured.", port)
1367 }
1368 UsbDeviceKind::Hub => {
1369 crate::warn!(
1372 "[USB] Hub port {}: nested hub (addr {}, {} ports). Enumerating children...",
1373 port,
1374 child.address,
1375 child.port_count
1376 );
1377 HUB_PORT_COUNT = child.port_count;
1378 enumerate_hub_children(depth + 1);
1379 HUB_ADDR = my_hub_addr;
1381 HUB_EP0_MPS = my_hub_mps;
1382 HUB_PORT_COUNT = my_port_count;
1383 }
1384 UsbDeviceKind::None => {}
1385 }
1386 } else {
1387 crate::warn!(
1388 "[USB] Hub port {}: enumeration failed (addr {} consumed).",
1389 port,
1390 child_addr
1391 );
1392 }
1393
1394 unsafe {
1396 CURRENT_HUB_PORT = 0;
1397 CURRENT_HUB_PORT_SPEED = 0;
1398 }
1399
1400 let _ = hub_clear_port_feature(port, HUB_FEATURE_C_PORT_CONNECTION);
1401 let _ = hub_clear_port_feature(port, HUB_FEATURE_C_PORT_RESET);
1402 }
1403
1404 crate::warn!(
1405 "[USB] Hub child enumeration completed. {} HID device(s) ready.",
1406 HID_DEVICE_COUNT.0
1407 );
1408}
1409
1410unsafe fn enumerate_root_device() {
1411 crate::info!("[USB] Starting USB Device Enumeration...");
1412
1413 if let Some(root) = enumerate_default_address_device(1, "Root Device") {
1414 NEXT_DEVICE_ADDR = 1;
1415 match root.kind {
1416 UsbDeviceKind::Hub => {
1417 HUB_PORT_COUNT = root.port_count;
1418 enumerate_hub_children(0);
1419 }
1420 UsbDeviceKind::Keyboard | UsbDeviceKind::Mouse | UsbDeviceKind::Tablet => {
1421 register_hid_device(root);
1422 crate::debug!("[USB] USB root HID enumeration completed.");
1423 }
1424 UsbDeviceKind::CdcEthernet => {
1425 crate::debug!("[USB] USB root Ethernet enumeration completed.");
1426 }
1427 UsbDeviceKind::None => {}
1428 }
1429 }
1430}
1431
1432unsafe fn handle_mouse_packet() {
1433 let btn = DMA_BUF.data[0];
1434 let dx = DMA_BUF.data[1];
1435 let dy = (-(DMA_BUF.data[2] as i8)) as u8;
1436
1437 let mut ps2_btn = 0x08;
1438 if (btn & 0x01) != 0 {
1439 ps2_btn |= 0x01;
1440 }
1441 if (btn & 0x02) != 0 {
1442 ps2_btn |= 0x02;
1443 }
1444 if (btn & 0x04) != 0 {
1445 ps2_btn |= 0x04;
1446 }
1447 if (dx as i8) < 0 {
1448 ps2_btn |= 0x10;
1449 }
1450 if (dy as i8) < 0 {
1451 ps2_btn |= 0x20;
1452 }
1453
1454 let _ = crate::kernel::interrupt::MOUSE_FIFO.lock().push(0xFE);
1455 let _ = crate::kernel::interrupt::MOUSE_FIFO
1456 .lock()
1457 .push(ps2_btn as u32);
1458 let _ = crate::kernel::interrupt::MOUSE_FIFO.lock().push(dx as u32);
1459 let _ = crate::kernel::interrupt::MOUSE_FIFO.lock().push(dy as u32);
1460}
1461
1462unsafe fn handle_tablet_packet(len: usize) {
1463 if len < 5 {
1464 return;
1465 }
1466
1467 let btn = DMA_BUF.data[0];
1468 let abs_x = (DMA_BUF.data[1] as u16) | ((DMA_BUF.data[2] as u16) << 8);
1469 let abs_y = (DMA_BUF.data[3] as u16) | ((DMA_BUF.data[4] as u16) << 8);
1470
1471 let wheel = if len >= 6 { DMA_BUF.data[5] as i8 } else { 0 };
1474 let _ = crate::kernel::interrupt::MOUSE_FIFO.lock().push(0xFC);
1475 let _ = crate::kernel::interrupt::MOUSE_FIFO.lock().push(btn as u32);
1476 let _ = crate::kernel::interrupt::MOUSE_FIFO
1477 .lock()
1478 .push(abs_x as u32);
1479 let _ = crate::kernel::interrupt::MOUSE_FIFO
1480 .lock()
1481 .push(abs_y as u32);
1482 let _ = crate::kernel::interrupt::MOUSE_FIFO
1483 .lock()
1484 .push(wheel as u32);
1485}
1486
1487unsafe fn handle_keyboard_packet(device: &mut UsbHidDevice) {
1488 let modifier = DMA_BUF.data[0];
1489 let shift_pressed = (modifier & 0x22) != 0;
1490 let ctrl_pressed = (modifier & 0x11) != 0; let alt_pressed = (modifier & 0x44) != 0; let gui_pressed = (modifier & 0x88) != 0; if shift_pressed != device.shift_pressed {
1495 device.shift_pressed = shift_pressed;
1496 let code = 0x2A;
1497 let p = if shift_pressed { code } else { code | 0x80 };
1498 let _ = crate::kernel::interrupt::KBD_FIFO.lock().push(p as u32);
1499 }
1500
1501 if ctrl_pressed != device.ctrl_pressed {
1502 device.ctrl_pressed = ctrl_pressed;
1503 let code = 0x1D; let p = if ctrl_pressed { code } else { code | 0x80 };
1505 let _ = crate::kernel::interrupt::KBD_FIFO.lock().push(p as u32);
1506 }
1507
1508 if alt_pressed != device.alt_pressed {
1509 device.alt_pressed = alt_pressed;
1510 let code = 0x38; let p = if alt_pressed { code } else { code | 0x80 };
1512 let _ = crate::kernel::interrupt::KBD_FIFO.lock().push(p as u32);
1513 }
1514
1515 if gui_pressed != device.gui_pressed {
1516 device.gui_pressed = gui_pressed;
1517 let code = 0x5B; let p = if gui_pressed { code } else { code | 0x80 };
1519 let _ = crate::kernel::interrupt::KBD_FIFO.lock().push(p as u32);
1520 }
1521
1522 for key_idx in 0..6 {
1523 let key = DMA_BUF.data[2 + key_idx];
1524 if key == 0 {
1525 continue;
1526 }
1527
1528 let mut is_new = true;
1529 for prev_idx in 0..6 {
1530 if device.key_prev_state[prev_idx] == key {
1531 is_new = false;
1532 break;
1533 }
1534 }
1535
1536 if is_new {
1537 if let Some(ps2_code) = hid_to_ps2(key) {
1538 let _ = crate::kernel::interrupt::KBD_FIFO
1539 .lock()
1540 .push(ps2_code as u32);
1541 }
1542 }
1543 }
1544
1545 for prev_idx in 0..6 {
1546 let prev_key = device.key_prev_state[prev_idx];
1547 if prev_key == 0 {
1548 continue;
1549 }
1550
1551 let mut is_released = true;
1552 for key_idx in 0..6 {
1553 if DMA_BUF.data[2 + key_idx] == prev_key {
1554 is_released = false;
1555 break;
1556 }
1557 }
1558
1559 if is_released {
1560 if let Some(ps2_code) = hid_to_ps2(prev_key) {
1561 let _ = crate::kernel::interrupt::KBD_FIFO
1562 .lock()
1563 .push((ps2_code | 0x80) as u32);
1564 }
1565 }
1566 }
1567
1568 for idx in 0..6 {
1569 device.key_prev_state[idx] = DMA_BUF.data[2 + idx];
1570 }
1571}
1572
1573unsafe fn usb_transfer(
1576 ch: usize,
1577 ep: u8,
1578 dev_addr: u8,
1579 ep_type: u8,
1580 pid: u32,
1581 dir_in: bool,
1582 buffer_phys: u32,
1583 len: u32,
1584 mps: u16,
1585 timeout_val: u32,
1586) -> Result<u32, ()> {
1587 if !dir_in || pid == 3 {
1589 if len > 0 {
1590 crate::kernel::mmu::clean_dcache_range(buffer_phys as usize, len as usize);
1591 } else if pid == 3 {
1592 crate::kernel::mmu::clean_dcache_range(buffer_phys as usize, 8); }
1594 } else if dir_in && len > 0 {
1595 crate::kernel::mmu::invalidate_dcache_range(buffer_phys as usize, len as usize);
1596 }
1597
1598 let is_split = unsafe {
1602 DEV_SPEED == 0 && (
1603 (dev_addr == 0 && HUB_ADDR > 0 && CURRENT_HUB_PORT > 0 && CURRENT_HUB_PORT_SPEED != 2) ||
1604 (dev_addr > 0 && DEV_HUB_ADDRS[dev_addr as usize] > 0 && DEV_SPEEDS[dev_addr as usize] != 2)
1605 )
1606 };
1607
1608 if !is_split {
1609 core::ptr::write_volatile(hc_splt(ch), 0);
1611
1612 core::ptr::write_volatile(hc_int(ch), 0x7FF);
1614 core::ptr::write_volatile(hc_intmsk(ch), 0x7FF);
1615 core::ptr::write_volatile(HAINTMSK, 0xFFFF);
1616
1617 let packet_count = if len == 0 {
1619 1
1620 } else {
1621 len.div_ceil(mps as u32)
1622 };
1623 let mut tsiz = len & 0x7FFFF;
1624 tsiz |= packet_count << 19;
1625 tsiz |= pid << 29; core::ptr::write_volatile(hc_tsiz(ch), tsiz);
1627
1628 let bus_addr = buffer_phys | 0xC0000000;
1630 core::ptr::write_volatile(hc_dma(ch), bus_addr);
1631
1632 let mut hcchar = mps as u32 & 0x7FF; hcchar |= (ep as u32 & 0xF) << 11; if dir_in {
1636 hcchar |= 1 << 15; }
1638 if DEV_SPEED == 2 {
1639 hcchar |= 1 << 17; }
1641 hcchar |= (ep_type as u32 & 0x3) << 18; hcchar |= 1 << 20; hcchar |= (dev_addr as u32 & 0x7F) << 22; if (core::ptr::read_volatile(HFNUM) & 1) != 0 {
1647 hcchar |= 1 << 29; }
1649 hcchar |= 1 << 31; core::ptr::write_volatile(hc_char(ch), hcchar);
1652
1653 core::arch::asm!("dsb sy", "isb", options(nostack));
1655
1656 let start_time = crate::kernel::timer::get_system_time_us();
1658 let timeout_us = timeout_val as u64;
1659 loop {
1660 core::arch::asm!("dsb sy", options(nostack));
1661 let hctrans = core::ptr::read_volatile(hc_char(ch));
1662 if (hctrans & (1 << 31)) == 0 {
1663 core::arch::asm!("dsb sy", options(nostack));
1664 let interrupts = core::ptr::read_volatile(hc_int(ch));
1665 if interrupts == 0 {
1666 if crate::kernel::timer::get_system_time_us().wrapping_sub(start_time) > timeout_us {
1669 crate::warn!("[USB] ch{} TIMEOUT while waiting for HCINT to populate", ch);
1670 return Err(());
1671 }
1672 continue;
1673 }
1674 if (interrupts & (1 << 0)) != 0 {
1675 let actual_size = len - (core::ptr::read_volatile(hc_tsiz(ch)) & 0x7FFFF);
1677 if dir_in && actual_size > 0 {
1678 crate::kernel::mmu::invalidate_dcache_range(
1679 buffer_phys as usize,
1680 actual_size as usize,
1681 );
1682 }
1683 return Ok(actual_size);
1684 }
1685 if (interrupts & (1 << 1)) != 0 {
1686 let ints2 = core::ptr::read_volatile(hc_int(ch));
1688 if (ints2 & (1 << 0)) != 0 {
1689 let actual_size = len - (core::ptr::read_volatile(hc_tsiz(ch)) & 0x7FFFF);
1690 if dir_in && actual_size > 0 {
1691 crate::kernel::mmu::invalidate_dcache_range(
1692 buffer_phys as usize,
1693 actual_size as usize,
1694 );
1695 }
1696 return Ok(actual_size);
1697 }
1698 if (ints2 & (1 << 4)) == 0 {
1699 if (ints2 & (1 << 3)) != 0 {
1701 crate::debug!(
1702 "[USB] Transfer STALL (hc_int=0x{:03X} is_split={} dir_in={} ep={} len={} dev_addr={})",
1703 ints2,
1704 is_split,
1705 dir_in as u8,
1706 ep,
1707 len,
1708 dev_addr
1709 );
1710 } else {
1711 crate::warn!(
1712 "[USB] Transfer failed: Channel Halted (hc_int=0x{:03X} is_split={} dir_in={} ep={} len={} dev_addr={})",
1713 ints2,
1714 is_split,
1715 dir_in as u8,
1716 ep,
1717 len,
1718 dev_addr
1719 );
1720 }
1721 }
1722 return Err(());
1723 }
1724 if (interrupts & (1 << 2)) != 0 {
1725 crate::warn!("[USB] ch{} AHB Error (hcint=0x{:03X})", ch, interrupts);
1727 return Err(());
1728 }
1729 if (interrupts & (1 << 3)) != 0 {
1730 crate::warn!("[USB] ch{} STALL (hcint=0x{:03X})", ch, interrupts);
1732 return Err(());
1733 }
1734 if (interrupts & (1 << 4)) != 0 {
1735 return Err(());
1737 }
1738 crate::warn!(
1741 "[USB] ch{} unexpected halt: hcint=0x{:03X} dir_in={} ep={} len={}",
1742 ch, interrupts, dir_in as u8, ep, len
1743 );
1744 return Err(());
1745 }
1746
1747 if crate::kernel::timer::get_system_time_us().wrapping_sub(start_time) > timeout_us {
1748 let mut char_val = core::ptr::read_volatile(hc_char(ch));
1750 char_val |= 1 << 30; char_val |= 1 << 31; core::ptr::write_volatile(hc_char(ch), char_val);
1753 let halt_start = crate::kernel::timer::get_system_time_us();
1756 loop {
1757 core::arch::asm!("dsb sy", options(nostack));
1758 if (core::ptr::read_volatile(hc_char(ch)) & (1 << 31)) == 0 {
1759 break;
1760 }
1761 if crate::kernel::timer::get_system_time_us().wrapping_sub(halt_start)
1762 > 1_000
1763 {
1764 break;
1765 }
1766 }
1767 let final_hcint = core::ptr::read_volatile(hc_int(ch));
1768 let final_hcchar = core::ptr::read_volatile(hc_char(ch));
1769 let chdis_ok = (final_hcchar & (1 << 31)) == 0;
1770 let final_gnptxsts = core::ptr::read_volatile(GNPTXSTS);
1771 let final_gintsts = core::ptr::read_volatile(GINTSTS);
1772 crate::warn!(
1773 "[USB] ch{} TIMEOUT: hcint=0x{:03X} hcchar=0x{:08X} chdis_ok={} gnptx=0x{:08X} gintsts=0x{:08X}",
1774 ch, final_hcint, final_hcchar, chdis_ok, final_gnptxsts, final_gintsts
1775 );
1776 return Err(());
1777 }
1778 }
1779 } else {
1780 let (hub_addr, port_addr) = unsafe {
1784 let (direct_hub_addr, direct_port) = if dev_addr > 0 {
1785 (
1786 DEV_HUB_ADDRS[dev_addr as usize],
1787 DEV_HUB_PORTS[dev_addr as usize],
1788 )
1789 } else {
1790 (HUB_ADDR, CURRENT_HUB_PORT)
1791 };
1792 resolve_split_target(direct_hub_addr, direct_port)
1793 };
1794
1795 let is_periodic = ep_type == 3;
1796 let mut sched = if is_periodic {
1797 frame_sched::FrameScheduler::new_periodic()
1798 } else {
1799 frame_sched::FrameScheduler::new_non_periodic()
1800 };
1801
1802 sched.start_split();
1803
1804 let start_time = crate::kernel::timer::get_system_time_us();
1805 let timeout_us = if is_periodic {
1809 (timeout_val as u64).min(5_000) } else {
1811 (timeout_val as u64).max(1_000_000)
1812 };
1813
1814 loop {
1815 if crate::kernel::timer::get_system_time_us().wrapping_sub(start_time) > timeout_us {
1816 let mut char_val = core::ptr::read_volatile(hc_char(ch));
1817 char_val |= 1 << 30; char_val |= 1 << 31; core::ptr::write_volatile(hc_char(ch), char_val);
1820 let halt_start = crate::kernel::timer::get_system_time_us();
1821 loop {
1822 core::arch::asm!("dsb sy", options(nostack));
1823 if (core::ptr::read_volatile(hc_char(ch)) & (1 << 31)) == 0 {
1824 break;
1825 }
1826 if crate::kernel::timer::get_system_time_us().wrapping_sub(halt_start)
1827 > 1_000
1828 {
1829 break;
1830 }
1831 }
1832 if !is_periodic {
1833 crate::warn!(
1834 "[USB] ch{} split TIMEOUT: hcint=0x{:03X} dir_in={} ep={} dev_addr={} hub_addr={} port={} state={:?} nak_restarts={}",
1835 ch,
1836 core::ptr::read_volatile(hc_int(ch)),
1837 dir_in as u8,
1838 ep,
1839 dev_addr,
1840 hub_addr,
1841 port_addr,
1842 sched.state,
1843 sched.nak_restarts
1844 );
1845 return Err(());
1846 } else {
1847 let hcint = core::ptr::read_volatile(hc_int(ch));
1848 if (hcint & 0x050) == 0 { crate::warn!("[USB] ch{} Periodic split TIMEOUT with error: hcint=0x{:03X} state={:?}", ch, hcint, sched.state);
1850 }
1851 return Ok(0); }
1853 }
1854
1855 let is_csplit = sched.complete_split();
1856
1857 let mut splt = 1 << 31; if is_csplit {
1860 splt |= 1 << 16; }
1862 splt |= 3 << 14; splt |= ((hub_addr as u32) & 0x7F) << 7;
1864 splt |= (port_addr as u32) & 0x7F;
1865 core::ptr::write_volatile(hc_splt(ch), splt);
1866
1867 core::ptr::write_volatile(hc_int(ch), 0x7FF);
1869 core::ptr::write_volatile(hc_intmsk(ch), 0x7FF);
1870 core::ptr::write_volatile(HAINTMSK, 0xFFFF);
1871
1872 let packet_count = if len == 0 {
1874 1
1875 } else {
1876 len.div_ceil(mps as u32)
1877 };
1878 let mut tsiz = len & 0x7FFFF;
1879 tsiz |= packet_count << 19;
1880 tsiz |= pid << 29;
1881 core::ptr::write_volatile(hc_tsiz(ch), tsiz);
1882
1883 let bus_addr = buffer_phys | 0xC0000000;
1884 core::ptr::write_volatile(hc_dma(ch), bus_addr);
1885
1886 sched.wait_for_frame();
1888
1889 let mut hcchar = mps as u32 & 0x7FF;
1891 hcchar |= (ep as u32 & 0xF) << 11;
1892 if dir_in {
1893 hcchar |= 1 << 15;
1894 }
1895 hcchar |= (ep_type as u32 & 0x3) << 18;
1898 if sched.is_odd_frame() {
1899 hcchar |= 1 << 29; }
1901 hcchar |= 1 << 20; hcchar |= (dev_addr as u32 & 0x7F) << 22;
1903 hcchar |= 1 << 31; core::ptr::write_volatile(hc_char(ch), hcchar);
1906
1907 core::arch::asm!("dsb sy", "isb", options(nostack));
1909
1910 let trans_start = crate::kernel::timer::get_system_time_us();
1912 let mut interrupts = 0;
1913 loop {
1914 core::arch::asm!("dsb sy", options(nostack));
1915 let hctrans = core::ptr::read_volatile(hc_char(ch));
1916 if (hctrans & (1 << 31)) == 0 {
1917 interrupts = core::ptr::read_volatile(hc_int(ch));
1918 if interrupts != 0 {
1919 break;
1920 }
1921 }
1922 if crate::kernel::timer::get_system_time_us().wrapping_sub(trans_start) > 50000 {
1923 break; }
1925 }
1926
1927 sched.transaction_complete(interrupts);
1929
1930 if sched.is_complete() {
1931 let actual_size = len - (core::ptr::read_volatile(hc_tsiz(ch)) & 0x7FFFF);
1932 if dir_in && actual_size > 0 {
1933 crate::kernel::mmu::invalidate_dcache_range(
1934 buffer_phys as usize,
1935 actual_size as usize,
1936 );
1937 }
1938 return Ok(actual_size);
1939 }
1940
1941 if sched.is_failed() {
1942 if !is_periodic {
1943 crate::warn!(
1944 "[USB] ch{} split transaction failed: status=0x{:03X} state={:?} ep={} dev_addr={} hub_addr={} port={} mps={} dir_in={} nak_restarts={}",
1945 ch,
1946 interrupts,
1947 sched.state,
1948 ep,
1949 dev_addr,
1950 hub_addr,
1951 port_addr,
1952 mps,
1953 dir_in as u8,
1954 sched.nak_restarts
1955 );
1956 return Err(());
1957 } else {
1958 if (interrupts & 0x050) == 0 {
1959 crate::warn!("[USB] ch{} Periodic split failed with error: hcint=0x{:03X} state={:?}", ch, interrupts, sched.state);
1960 }
1961 return Ok(0); }
1963 }
1964
1965 if !is_periodic {
1967 delay_ms(1);
1968 }
1969 }
1970 }
1971}
1972
1973unsafe fn usb_control_transfer(
1975 request: UsbSetupPacket,
1976 data_buf_phys: u32,
1977 data_len: u32,
1978 dir_in: bool,
1979) -> Result<u32, ()> {
1980 let req_type = request.request_type;
1982 let req_code = request.request;
1983 let req_value = request.value;
1984 let req_index = request.index;
1985 let req_length = request.length;
1986
1987 let setup_ptr = &request as *const UsbSetupPacket as *const u8;
1989 for i in 0..8 {
1990 SETUP_BUF.data[i] = core::ptr::read(setup_ptr.add(i));
1991 }
1992
1993 let mut outer = 3;
1998 let mut actual_len;
1999 'transfer: loop {
2000 let mut retry = 3;
2003 while retry > 0 {
2004 let setup_phys = &SETUP_BUF as *const DmaBuffer as u32;
2005 if usb_transfer(0, 0, DEV_ADDR, 0, 3, false, setup_phys, 8, EP0_MPS, 200000).is_ok() {
2006 break;
2007 }
2008 retry -= 1;
2009 delay_ms(5);
2010 }
2011 if retry == 0 {
2012 crate::warn!(
2013 "[USB] SETUP stage failed: req_type=0x{:02X} req=0x{:02X} val=0x{:04X} idx=0x{:04X} len={} dev_addr={}",
2014 req_type,
2015 req_code,
2016 req_value,
2017 req_index,
2018 req_length,
2019 DEV_ADDR
2020 );
2021 return Err(());
2022 }
2023
2024 actual_len = 0;
2026 if data_len > 0 {
2027 let mut retry = 7;
2028 let mut success = false;
2029 while retry > 0 {
2030 if usb_transfer(
2032 0,
2033 0,
2034 DEV_ADDR,
2035 0,
2036 2,
2037 dir_in,
2038 data_buf_phys,
2039 data_len,
2040 EP0_MPS,
2041 200000,
2042 )
2043 .is_ok()
2044 {
2045 if dir_in {
2046 actual_len = data_len;
2047 }
2048 success = true;
2049 break;
2050 }
2051 retry -= 1;
2052 delay_ms(5);
2053 }
2054 if !success {
2055 outer -= 1;
2056 if outer == 0 {
2057 crate::warn!(
2058 "[USB] DATA stage failed: req_type=0x{:02X} req=0x{:02X} val=0x{:04X} idx=0x{:04X} len={} dev_addr={}",
2059 req_type,
2060 req_code,
2061 req_value,
2062 req_index,
2063 req_length,
2064 DEV_ADDR
2065 );
2066 return Err(());
2067 }
2068 crate::warn!(
2069 "[USB] DATA stage failed; restarting control transfer from SETUP (remaining {})",
2070 outer
2071 );
2072 delay_ms(10);
2073 continue 'transfer;
2074 }
2075 }
2076 break 'transfer;
2077 }
2078
2079 let status_phys = &SETUP_BUF as *const DmaBuffer as u32; let mut retry = 100; let mut success = false;
2085 while retry > 0 {
2086 if usb_transfer(
2087 0,
2088 0,
2089 DEV_ADDR,
2090 0,
2091 2,
2092 !dir_in,
2093 status_phys,
2094 0,
2095 EP0_MPS,
2096 200000,
2097 )
2098 .is_ok()
2099 {
2100 success = true;
2101 break;
2102 }
2103 retry -= 1;
2104 delay_ms(5);
2105 }
2106 if !success {
2107 crate::warn!(
2108 "[USB] STATUS stage failed: req_type=0x{:02X} req=0x{:02X} val=0x{:04X} idx=0x{:04X} len={} dev_addr={}",
2109 req_type,
2110 req_code,
2111 req_value,
2112 req_index,
2113 req_length,
2114 DEV_ADDR
2115 );
2116 return Err(());
2117 }
2118
2119 Ok(actual_len)
2120}
2121
2122static mut POLL_DIVIDER: u32 = 0;
2123
2124pub fn poll() {
2127 unsafe {
2128 let _lock = USB_LOCK.lock();
2129 HID_POLL_CALLS.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
2130 let t_eth1 = crate::kernel::timer::get_system_time_us();
2162 poll_usb_ethernet_data_plane();
2163 HID_ETH_US.fetch_add(
2164 crate::kernel::timer::get_system_time_us().wrapping_sub(t_eth1) as u32,
2165 core::sync::atomic::Ordering::Relaxed,
2166 );
2167 let t_hid = crate::kernel::timer::get_system_time_us();
2171
2172 let count_addr = &HID_DEVICE_COUNT.0 as *const usize as usize;
2174 crate::kernel::mmu::invalidate_dcache_range(count_addr, core::mem::size_of_val(&HID_DEVICE_COUNT.0));
2175 let devices_addr = HID_DEVICES.0.as_ptr() as usize;
2176 crate::kernel::mmu::invalidate_dcache_range(devices_addr, core::mem::size_of_val(&HID_DEVICES.0));
2177 core::arch::asm!("dsb sy", "isb", options(nostack));
2178
2179 if HID_DEVICE_COUNT.0 == 0 {
2180 return; }
2182
2183 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
2185
2186 for idx in 0..HID_DEVICE_COUNT.0 {
2187 let device = &mut HID_DEVICES.0[idx];
2188 if device.address == 0 || device.hid_ep == 0 {
2189 continue;
2190 }
2191
2192 let pid = device.data_toggle;
2195 let res = usb_transfer(
2196 1,
2197 device.hid_ep,
2198 device.address,
2199 3,
2200 pid,
2201 true,
2202 buf_phys,
2203 device.hid_ep_size as u32,
2204 device.hid_ep_size,
2205 200000,
2206 );
2207
2208 if let Ok(len) = res {
2209 let recv_len = len as usize;
2210 if recv_len == 0 {
2211 continue;
2213 }
2214 device.data_toggle = if pid == 0 { 2 } else { 0 };
2216
2217 match device.kind {
2218 UsbDeviceKind::Mouse => handle_mouse_packet(),
2219 UsbDeviceKind::Tablet => handle_tablet_packet(len as usize),
2220 UsbDeviceKind::Keyboard => handle_keyboard_packet(device),
2221 _ => {}
2222 }
2223 }
2224 }
2225 HID_POLL_US.fetch_add(
2226 crate::kernel::timer::get_system_time_us().wrapping_sub(t_hid) as u32,
2227 core::sync::atomic::Ordering::Relaxed,
2228 );
2229 }
2230}
2231
2232pub static HID_POLL_CALLS: core::sync::atomic::AtomicU32 =
2234 core::sync::atomic::AtomicU32::new(0);
2235pub static HID_POLL_US: core::sync::atomic::AtomicU32 =
2237 core::sync::atomic::AtomicU32::new(0);
2238pub static HID_ETH_US: core::sync::atomic::AtomicU32 =
2240 core::sync::atomic::AtomicU32::new(0);
2241
2242pub static mut POLL_THREAD_ACTIVE: bool = false;
2251
2252pub fn poll_ethernet_data_plane_only() {
2270 if crate::kernel::scheduler::core_id() != 2 {
2281 return;
2282 }
2283 unsafe {
2284 let Some(_lock) = USB_LOCK.try_lock() else {
2317 ETH_POLL_LOCK_MISS.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
2318 return;
2319 };
2320 let t0 = crate::kernel::timer::get_system_time_us();
2327 ETH_POLL_CALLS.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
2328 poll_usb_ethernet_data_plane();
2329 ETH_POLL_US.fetch_add(
2330 crate::kernel::timer::get_system_time_us().wrapping_sub(t0) as u32,
2331 core::sync::atomic::Ordering::Relaxed,
2332 );
2333 }
2334}
2335
2336static mut RX_IN_FLIGHT_POLLS: u32 = 0;
2341
2342pub static ETH_POLL_CALLS: core::sync::atomic::AtomicU32 =
2344 core::sync::atomic::AtomicU32::new(0);
2345pub static ETH_POLL_US: core::sync::atomic::AtomicU32 =
2347 core::sync::atomic::AtomicU32::new(0);
2348pub static ETH_POLL_LOCK_MISS: core::sync::atomic::AtomicU32 =
2350 core::sync::atomic::AtomicU32::new(0);
2351
2352pub static TX_USB_OK: core::sync::atomic::AtomicU32 =
2360 core::sync::atomic::AtomicU32::new(0);
2361pub static TX_USB_FAIL: core::sync::atomic::AtomicU32 =
2362 core::sync::atomic::AtomicU32::new(0);
2363
2364pub static RX_FRAME_COUNT: core::sync::atomic::AtomicU32 =
2365 core::sync::atomic::AtomicU32::new(0);
2366
2367unsafe fn poll_usb_ethernet_data_plane() {
2368 let st = net::status();
2369 if !st.usb_eth_present
2370 || st.usb_eth_addr == 0
2371 || st.usb_eth_bulk_in == 0
2372 || st.usb_eth_bulk_out == 0
2373 {
2374 return;
2375 }
2376
2377 let mut tx_buf = [0u8; 1536];
2378 let max_chunk = 1536; while let Some(chunk_len) = net::nic_take_tx_ipv4_chunk(max_chunk, &mut tx_buf) {
2380 if chunk_len == 0 {
2381 break;
2382 }
2383
2384 if st.usb_eth_is_rndis {
2385 let header_len = 44;
2386 let total_len = header_len + chunk_len;
2387 let rndis_header = RndisPacketMsg {
2388 message_type: 0x00000001, message_length: total_len as u32,
2390 data_offset: 36, data_length: chunk_len as u32,
2392 oob_data_offset: 0,
2393 oob_data_length: 0,
2394 num_oob_data_elements: 0,
2395 packet_information_offset: 0,
2396 packet_information_length: 0,
2397 device_vc_handle: 0,
2398 reserved: 0,
2399 };
2400
2401 let header_ptr = &rndis_header as *const RndisPacketMsg as *const u8;
2402 core::ptr::copy_nonoverlapping(header_ptr, DMA_BUF.data.as_mut_ptr(), header_len);
2403 core::ptr::copy_nonoverlapping(
2404 tx_buf.as_ptr(),
2405 DMA_BUF.data.as_mut_ptr().add(header_len),
2406 chunk_len,
2407 );
2408
2409 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
2410 let pid = crate::kernel::usb_toggle::pid_from_toggle(ETH_BULK_OUT_TOGGLE);
2411 match usb_transfer(
2412 2,
2413 st.usb_eth_bulk_out,
2414 st.usb_eth_addr,
2415 2,
2416 pid,
2417 false,
2418 buf_phys,
2419 total_len as u32,
2420 st.usb_eth_mps,
2421 500_000,
2422 ) {
2423 Ok(_) => {
2424 crate::debug!("[USB] NET: USB OUT sent {} bytes (RNDIS)", total_len);
2425 }
2426 Err(_) => {
2427 crate::warn!("[USB] NET: USB OUT FAILED (RNDIS)!");
2428 break;
2429 }
2430 }
2431 if let Some(pc) = crate::kernel::usb_toggle::packet_count(total_len, st.usb_eth_mps as u32) {
2437 ETH_BULK_OUT_TOGGLE = crate::kernel::usb_toggle::advance_by_packets(
2438 ETH_BULK_OUT_TOGGLE,
2439 pc,
2440 crate::kernel::usb_toggle::TxnResult::Acked,
2441 );
2442 }
2443 } else {
2444 DMA_BUF.data[..chunk_len].copy_from_slice(&tx_buf[..chunk_len]);
2445 let buf_phys = &DMA_BUF as *const DmaBuffer as u32;
2446 let pid = crate::kernel::usb_toggle::pid_from_toggle(ETH_BULK_OUT_TOGGLE);
2447 match usb_transfer(
2448 2,
2449 st.usb_eth_bulk_out,
2450 st.usb_eth_addr,
2451 2,
2452 pid,
2453 false,
2454 buf_phys,
2455 chunk_len as u32,
2456 st.usb_eth_mps,
2457 500_000,
2458 ) {
2459 Ok(_) => {
2460 crate::debug!("[USB] NET: USB OUT sent {} bytes (CDC-ECM)", chunk_len);
2461 }
2462 Err(_) => {
2463 crate::warn!("[USB] NET: USB OUT FAILED (CDC-ECM)!");
2464 break;
2465 }
2466 }
2467 if let Some(pc) = crate::kernel::usb_toggle::packet_count(chunk_len, st.usb_eth_mps as u32) {
2470 ETH_BULK_OUT_TOGGLE = crate::kernel::usb_toggle::advance_by_packets(
2471 ETH_BULK_OUT_TOGGLE,
2472 pc,
2473 crate::kernel::usb_toggle::TxnResult::Acked,
2474 );
2475 }
2476 }
2477 }
2478
2479 const RX_LEN: u32 = 1600;
2486 static mut RX_IN_FLIGHT: bool = false;
2487 static mut RX_ABNORMAL_HALTS: u32 = 0;
2489
2490 let mut harvest_budget = 8u32;
2522 loop {
2523 if RX_IN_FLIGHT {
2524 let hcchar_v = core::ptr::read_volatile(hc_char(3));
2525 let ints = core::ptr::read_volatile(hc_int(3));
2526 let action = crate::kernel::usb_rx_state::decide(
2533 true,
2534 hcchar_v,
2535 ints,
2536 RX_IN_FLIGHT_POLLS,
2537 );
2538 if action == crate::kernel::usb_rx_state::RxAction::WaitInFlight {
2539 RX_IN_FLIGHT_POLLS = RX_IN_FLIGHT_POLLS.saturating_add(1);
2540 return;
2541 }
2542 if action == crate::kernel::usb_rx_state::RxAction::Rearm {
2545 RX_IN_FLIGHT_POLLS = 0;
2551 RX_IN_FLIGHT = false;
2552 }
2553 if RX_IN_FLIGHT_POLLS >= crate::kernel::usb_rx_state::MAX_IN_FLIGHT_POLLS {
2554 crate::warn!(
2555 "[USB][RX] channel stuck enabled for {} polls; forcing re-arm (HCCHAR=0x{:08x} HCINT=0x{:08x})",
2556 RX_IN_FLIGHT_POLLS,
2557 hcchar_v,
2558 ints
2559 );
2560 }
2561 RX_IN_FLIGHT_POLLS = 0;
2562 RX_IN_FLIGHT = false;
2563 if (ints & (1 << 0)) != 0 {
2564 let tsiz = core::ptr::read_volatile(hc_tsiz(3));
2572 let remaining = tsiz & 0x7FFFF;
2573 let recv_len = (RX_LEN - remaining) as usize;
2574
2575 let next_pid = (tsiz >> 29) & 3;
2590 ETH_BULK_IN_TOGGLE = crate::kernel::usb_toggle::toggle_from_pid(next_pid);
2592
2593 if recv_len > 0 {
2594 crate::kernel::mmu::invalidate_dcache_range(
2595 (&RX_DMA_BUF as *const DmaBuffer) as usize,
2596 recv_len,
2597 );
2598
2599 if st.usb_eth_is_rndis {
2600 if recv_len >= 44 {
2601 let msg = core::ptr::read_unaligned(
2602 RX_DMA_BUF.data.as_ptr() as *const RndisPacketMsg
2603 );
2604 let range = crate::kernel::usb_rndis::rndis_frame_range(
2609 recv_len,
2610 msg.message_type,
2611 msg.data_offset,
2612 msg.data_length,
2613 );
2614 if let Ok((abs_offset, frame_end)) = range {
2615 let data_len = frame_end - abs_offset;
2621 if true {
2622 let eth_frame =
2623 &RX_DMA_BUF.data[abs_offset..abs_offset + data_len];
2624 if eth_frame.len() >= 14 {
2625 crate::debug!(
2626 "[USB] NET: USB IN received {} bytes (RNDIS)",
2627 eth_frame.len()
2628 );
2629 RX_FRAME_COUNT.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
2630 let _ = net::ingest_nic_ethernet_frame(eth_frame);
2631 }
2632 }
2633 }
2634 }
2635 } else if recv_len >= 14 {
2636 crate::debug!("[USB] NET: USB IN received {} bytes (CDC-ECM)", recv_len);
2637 RX_FRAME_COUNT.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
2640 let _ = net::ingest_nic_ethernet_frame(&RX_DMA_BUF.data[..recv_len]);
2641 }
2642 }
2643 }
2644 else if action != crate::kernel::usb_rx_state::RxAction::Rearm {
2656 RX_ABNORMAL_HALTS = RX_ABNORMAL_HALTS.saturating_add(1);
2657 if RX_ABNORMAL_HALTS <= 8 || RX_ABNORMAL_HALTS.is_multiple_of(64) {
2658 crate::warn!(
2659 "[USB][DIAG] RX halted without XferCompl: HCINT=0x{:08x} (STALL={} XactErr={} DTERR={} BblErr={} FrmOvrun={}) count={}",
2660 ints,
2661 (ints >> 3) & 1,
2662 (ints >> 7) & 1,
2663 (ints >> 10) & 1,
2664 (ints >> 8) & 1,
2665 (ints >> 9) & 1,
2666 RX_ABNORMAL_HALTS
2667 );
2668 }
2669 }
2670 }
2671
2672 if !RX_IN_FLIGHT {
2673 let buf_phys = &RX_DMA_BUF as *const DmaBuffer as u32;
2675 crate::kernel::mmu::invalidate_dcache_range(buf_phys as usize, RX_LEN as usize);
2676 let pid = crate::kernel::usb_toggle::pid_from_toggle(ETH_BULK_IN_TOGGLE);
2677 core::ptr::write_volatile(hc_int(3), 0x7FF); let mps = st.usb_eth_mps as u32;
2679 let packet_count = RX_LEN.div_ceil(mps);
2680 let mut tsiz = RX_LEN & 0x7FFFF;
2681 tsiz |= packet_count << 19;
2682 tsiz |= pid << 29;
2683 core::ptr::write_volatile(hc_tsiz(3), tsiz);
2684 core::ptr::write_volatile(hc_dma(3), buf_phys);
2685 let mut hcchar_v = mps & 0x7FF;
2686 hcchar_v |= ((st.usb_eth_bulk_in as u32) & 0xF) << 11;
2687 hcchar_v |= 1 << 15; hcchar_v |= 2 << 18; hcchar_v |= 3 << 20; hcchar_v |= ((st.usb_eth_addr as u32) & 0x7F) << 22;
2691 hcchar_v |= 1 << 31; core::ptr::write_volatile(hc_char(3), hcchar_v);
2693 RX_IN_FLIGHT = true;
2694 }
2695
2696 harvest_budget -= 1;
2697 if harvest_budget == 0 {
2698 break;
2699 }
2700 } }
2702
2703fn hid_to_ps2(hid_code: u8) -> Option<u8> {
2705 let ps2 = match hid_code {
2706 0x1E => 0x02, 0x1F => 0x03, 0x20 => 0x04, 0x21 => 0x05, 0x22 => 0x06, 0x23 => 0x07, 0x24 => 0x08, 0x25 => 0x09, 0x26 => 0x0A, 0x27 => 0x0B, 0x2D => 0x0C, 0x2E => 0x0D, 0x2A => 0x0E, 0x2B => 0x0F, 0x04 => 0x1E, 0x05 => 0x30, 0x06 => 0x2E, 0x07 => 0x20, 0x08 => 0x12, 0x09 => 0x21, 0x0A => 0x22, 0x0B => 0x23, 0x0C => 0x17, 0x0D => 0x24, 0x0E => 0x25, 0x0F => 0x26, 0x10 => 0x32, 0x11 => 0x31, 0x12 => 0x18, 0x13 => 0x19, 0x14 => 0x10, 0x15 => 0x13, 0x16 => 0x1F, 0x17 => 0x14, 0x18 => 0x16, 0x19 => 0x2F, 0x1A => 0x11, 0x1B => 0x2D, 0x1C => 0x15, 0x1D => 0x2C, 0x2F => 0x1A, 0x30 => 0x1B, 0x2C => 0x39, 0x28 => 0x1C, 0x33 => 0x27, 0x34 => 0x28, 0x35 => 0x29, 0x31 => 0x2B, 0x36 => 0x33, 0x37 => 0x34, 0x38 => 0x35, 0x64 => 0x73, 0x87 => 0x73, 0x88 => 0x70, 0x89 => 0x7D, 0x8A => 0x79, 0x8B => 0x7B, 0x90 => 0x79, 0x91 => 0x7B, 0x52 => 0x48, 0x51 => 0x50, 0x50 => 0x4B, 0x4F => 0x4D, 0x4C => 0x53, 0x4A => 0x47, 0x4D => 0x4F, 0x4B => 0x49, 0x4E => 0x51, 0x29 => 0x01, 0x3A => 0x3B, 0x3B => 0x3C, 0x3C => 0x3D, 0x3D => 0x3E, 0x3E => 0x3F, 0x3F => 0x40, 0x40 => 0x41, 0x41 => 0x42, 0x42 => 0x43, 0x43 => 0x44, 0x44 => 0x57, 0x45 => 0x58, _ => return None,
2788 };
2789 Some(ps2)
2790}
2791
2792pub mod frame_sched {
2809 const INT_XFER_COMPLETE: u32 = 1 << 0;
2811 const INT_NAK: u32 = 1 << 4;
2812 const INT_ACK: u32 = 1 << 5;
2813 const INT_NYET: u32 = 1 << 6;
2814 const INT_XACT_ERR: u32 = 1 << 7;
2815
2816 const MAX_NAK_RESTARTS: u32 = 64;
2821
2822 const UFRAME_US: u64 = 125; const MAX_FRAME_NUMBER: u32 = 0x3FFF;
2824 const NPER_FRAME_UNSET: u32 = MAX_FRAME_NUMBER + 1; const PER_FRAME_UNSET: u32 = 8; #[inline]
2829 fn frame_number() -> u32 {
2830 unsafe { core::ptr::read_volatile(super::HFNUM) & 0xFFFF }
2831 }
2832
2833 fn udelay(us: u64) {
2835 let start = crate::kernel::timer::get_system_time_us();
2836 while crate::kernel::timer::get_system_time_us().wrapping_sub(start) < us {
2837 unsafe { core::arch::asm!("nop") };
2838 }
2839 }
2840
2841 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
2842 pub enum State {
2843 StartSplit,
2844 StartSplitComplete,
2845 CompleteSplit,
2846 CompleteRetry,
2847 CompleteSplitComplete,
2848 CompleteSplitFailed,
2849 Unknown,
2850 }
2851
2852 #[derive(Clone, Copy, PartialEq, Eq)]
2853 enum Kind {
2854 NoSplit { is_periodic: bool },
2856 NonPeriodic,
2858 Periodic,
2860 }
2861
2862 pub struct FrameScheduler {
2864 kind: Kind,
2865 pub state: State,
2866 tries: i32,
2867 next_frame: u32,
2868 pub nak_restarts: u32,
2870 xacterr_budget: i32,
2873 }
2874
2875 impl FrameScheduler {
2876 pub fn new_no_split(is_periodic: bool) -> Self {
2877 Self {
2878 kind: Kind::NoSplit { is_periodic },
2879 state: State::Unknown,
2880 tries: 0,
2881 next_frame: NPER_FRAME_UNSET,
2882 nak_restarts: 0,
2883 xacterr_budget: 3,
2884 }
2885 }
2886 pub fn new_non_periodic() -> Self {
2887 Self {
2888 kind: Kind::NonPeriodic,
2889 state: State::Unknown,
2890 tries: 0,
2891 next_frame: NPER_FRAME_UNSET,
2892 nak_restarts: 0,
2893 xacterr_budget: 3,
2894 }
2895 }
2896 pub fn new_periodic() -> Self {
2897 Self {
2898 kind: Kind::Periodic,
2899 state: State::Unknown,
2900 tries: 0,
2901 next_frame: PER_FRAME_UNSET,
2902 nak_restarts: 0,
2903 xacterr_budget: 3,
2904 }
2905 }
2906
2907 pub fn is_split(&self) -> bool {
2909 !matches!(self.kind, Kind::NoSplit { .. })
2910 }
2911 pub fn is_complete(&self) -> bool {
2913 self.state == State::CompleteSplitComplete
2914 }
2915 pub fn is_failed(&self) -> bool {
2917 self.state == State::CompleteSplitFailed
2918 }
2919
2920 pub fn start_split(&mut self) {
2922 match self.kind {
2923 Kind::NoSplit { .. } => {} Kind::NonPeriodic => {
2925 self.state = State::StartSplit;
2926 }
2927 Kind::Periodic => {
2928 self.state = State::StartSplit;
2929 self.next_frame = PER_FRAME_UNSET;
2930 }
2931 }
2932 }
2933
2934 pub fn complete_split(&mut self) -> bool {
2936 match self.kind {
2937 Kind::NoSplit { .. } => false,
2938 Kind::NonPeriodic => match self.state {
2939 State::StartSplitComplete => {
2940 udelay(3 * UFRAME_US);
2947 self.state = State::CompleteSplit;
2948 self.tries = 3;
2949 true
2950 }
2951 State::CompleteSplit | State::CompleteRetry => {
2952 udelay(5 * UFRAME_US);
2953 true
2954 }
2955 _ => false, },
2957 Kind::Periodic => match self.state {
2958 State::StartSplitComplete => {
2959 self.state = State::CompleteSplit;
2960 self.tries = if self.next_frame != 5 { 3 } else { 2 };
2961 self.next_frame = (self.next_frame + 2) & 7;
2962 true
2963 }
2964 State::CompleteRetry => {
2965 self.next_frame = (self.next_frame + 1) & 7;
2966 true
2967 }
2968 _ => false,
2969 },
2970 }
2971 }
2972
2973 pub fn transaction_complete(&mut self, status: u32) {
2975 match self.kind {
2976 Kind::NoSplit { .. } => {}
2977 Kind::NonPeriodic => match self.state {
2978 State::StartSplit => self.state = State::StartSplitComplete,
2979 State::CompleteSplit | State::CompleteRetry => {
2980 if status & INT_XFER_COMPLETE != 0 {
2981 self.state = State::CompleteSplitComplete;
2982 } else if status & (INT_NYET | INT_ACK) != 0 {
2983 if status & INT_NYET != 0 {
2984 self.state = State::CompleteRetry;
2985 } else {
2986 if self.tries == 0 {
2987 self.state = State::CompleteSplitFailed;
2988 } else {
2989 self.tries -= 1;
2990 self.state = State::CompleteRetry;
2991 }
2992 }
2993 } else if status & INT_NAK != 0 {
2994 if self.tries == 0 || self.nak_restarts >= MAX_NAK_RESTARTS {
3000 udelay(5 * UFRAME_US);
3001 self.state = State::CompleteSplitFailed;
3002 } else {
3003 self.tries -= 1;
3004 self.state = State::StartSplit;
3005 self.nak_restarts += 1;
3006 }
3007 } else {
3008 if self.xacterr_budget <= 0 {
3013 self.state = State::CompleteSplitFailed;
3014 } else {
3015 self.xacterr_budget -= 1;
3016 self.state = State::StartSplit;
3017 self.nak_restarts += 1;
3018 }
3019 }
3020 }
3021 _ => {}
3022 },
3023 Kind::Periodic => match self.state {
3024 State::StartSplit => self.state = State::StartSplitComplete,
3025 State::CompleteSplit | State::CompleteRetry => {
3026 if status & INT_XFER_COMPLETE != 0 {
3027 self.state = State::CompleteSplitComplete;
3028 } else if status & (INT_NYET | INT_ACK) != 0 {
3029 if status & INT_NYET != 0 {
3030 self.state = State::CompleteRetry;
3031 } else {
3032 if self.tries == 0 {
3033 self.state = State::CompleteSplitFailed;
3034 udelay(8 * UFRAME_US);
3035 } else {
3036 self.tries -= 1;
3037 self.state = State::CompleteRetry;
3038 }
3039 }
3040 } else if status & INT_NAK != 0 {
3041 udelay(5 * UFRAME_US);
3042 self.state = State::CompleteSplitFailed;
3043 } else {
3044 self.state = State::CompleteSplitFailed;
3045 }
3046 }
3047 _ => {}
3048 },
3049 }
3050 }
3051
3052 pub fn wait_for_frame(&mut self) {
3054 match self.kind {
3055 Kind::NoSplit { is_periodic } => {
3056 self.next_frame = (frame_number() + 1) & MAX_FRAME_NUMBER;
3057 if !is_periodic {
3058 while (frame_number() & MAX_FRAME_NUMBER) != self.next_frame {
3059 unsafe {
3060 core::arch::asm!("dsb sy", "isb", options(nostack));
3061 }
3062 }
3063 }
3064 }
3065 Kind::NonPeriodic => {} Kind::Periodic => {
3067 if self.next_frame == PER_FRAME_UNSET {
3068 self.next_frame = (frame_number() + 1) & 7;
3069 if self.next_frame == 6 {
3070 self.next_frame += 1; }
3072 }
3073 while (frame_number() & 7) != self.next_frame {
3074 unsafe {
3075 core::arch::asm!("dsb sy", "isb", options(nostack));
3076 }
3077 }
3078 }
3079 }
3080 }
3081
3082 pub fn is_odd_frame(&self) -> bool {
3084 match self.kind {
3085 Kind::NoSplit { .. } | Kind::Periodic => self.next_frame & 1 != 0,
3086 Kind::NonPeriodic => false,
3087 }
3088 }
3089 }
3090
3091 pub fn selftest() -> (usize, usize) {
3094 let mut pass = 0usize;
3095 let mut total = 0usize;
3096 macro_rules! check {
3097 ($cond:expr) => {{
3098 total += 1;
3099 if $cond {
3100 pass += 1;
3101 }
3102 }};
3103 }
3104
3105 {
3107 let mut s = FrameScheduler::new_non_periodic();
3108 check!(s.is_split());
3109 s.start_split();
3110 s.transaction_complete(INT_ACK); check!(s.complete_split()); s.transaction_complete(INT_XFER_COMPLETE); check!(s.is_complete());
3114 check!(!s.complete_split()); check!(!s.is_failed());
3116 }
3117
3118 {
3120 let mut s = FrameScheduler::new_non_periodic();
3121 s.start_split();
3122 s.transaction_complete(INT_ACK);
3123 check!(s.complete_split()); for _ in 0..10 {
3126 s.transaction_complete(INT_NYET);
3127 check!(s.complete_split());
3128 check!(!s.is_failed());
3129 check!(!s.is_complete());
3130 }
3131 }
3132
3133 {
3135 let mut s = FrameScheduler::new_non_periodic();
3136 s.start_split();
3137 s.transaction_complete(INT_ACK); check!(s.complete_split()); s.transaction_complete(INT_NAK); check!(!s.is_failed());
3141 check!(!s.complete_split()); s.transaction_complete(INT_ACK); check!(s.complete_split()); s.transaction_complete(INT_XFER_COMPLETE);
3145 check!(s.is_complete());
3146 }
3147
3148 {
3150 let mut s = FrameScheduler::new_non_periodic();
3151 s.start_split();
3152 let mut iters = 0u32;
3153 loop {
3154 s.transaction_complete(INT_ACK); if !s.complete_split() {
3156 break; }
3158 s.transaction_complete(INT_NAK); if s.is_failed() {
3160 break;
3161 }
3162 iters += 1;
3163 if iters > 1000 {
3164 break; }
3166 }
3167 check!(s.is_failed());
3168 check!((10..=MAX_NAK_RESTARTS + 1).contains(&iters));
3169 }
3170
3171 {
3173 let mut s = FrameScheduler::new_non_periodic();
3174 s.start_split();
3175 s.transaction_complete(INT_ACK);
3176 check!(s.complete_split()); s.transaction_complete(INT_XACT_ERR); check!(!s.is_failed());
3179 check!(!s.complete_split()); s.transaction_complete(INT_ACK);
3181 check!(s.complete_split());
3182 s.transaction_complete(INT_XFER_COMPLETE);
3183 check!(s.is_complete());
3184 }
3185
3186 {
3188 let mut s = FrameScheduler::new_non_periodic();
3189 s.start_split();
3190 s.transaction_complete(INT_ACK);
3191 for _ in 0..4 {
3192 check!(!s.is_failed());
3193 check!(s.complete_split());
3194 s.transaction_complete(INT_XACT_ERR);
3195 s.transaction_complete(INT_ACK); }
3197 check!(s.is_failed());
3198 }
3199
3200 {
3202 let mut s = FrameScheduler::new_periodic();
3203 check!(s.is_split());
3204 s.start_split();
3205 s.transaction_complete(INT_ACK); check!(s.complete_split()); s.transaction_complete(INT_XFER_COMPLETE);
3208 check!(s.is_complete());
3209 }
3210
3211 {
3213 let mut s = FrameScheduler::new_periodic();
3214 s.start_split();
3215 s.transaction_complete(INT_ACK);
3216 check!(s.complete_split());
3217 s.transaction_complete(INT_NAK); check!(s.is_failed());
3219 }
3220
3221 {
3223 let s = FrameScheduler::new_no_split(false);
3224 check!(!s.is_split());
3225 }
3226
3227 (pass, total)
3228 }
3229}