1extern crate alloc;
9use alloc::alloc::{alloc, dealloc, Layout};
10use alloc::boxed::Box;
11use core::cell::RefCell;
12use core::pin::Pin;
13use core::ptr::{read_volatile, write_volatile};
14use core::slice;
15use critical_section::Mutex;
16
17use mips_mcu::fmt::virt_to_phys;
18use mips_mcu::PhysicalAddress;
19
20use crate::pac::USB;
21
22use usb_device as udev;
23use usb_device::bus::PollResult;
24use usb_device::bus::UsbBusAllocator;
25use usb_device::endpoint::{EndpointAddress, EndpointType};
26use usb_device::{Result, UsbDirection, UsbError};
27
28const EPREG_EPHSHK_MASK: u8 = 0x01;
30const EPREG_EPSTALL_MASK: u8 = 0x02;
31const EPREG_EPTXEN_MASK: u8 = 0x04;
32const EPREG_EPRXEN_MASK: u8 = 0x08;
33const EPREG_EPCONDIS_MASK: u8 = 0x10;
34
35const U1STAT_ENDPT_MASK : u32 = 0xf0;
37const U1STAT_ENDPT_POSITION: usize = 4;
38const U1STAT_DIR_MASK: u32 = 0x08;
39const U1STAT_DIR_POSITION: usize = 3;
40#[repr(C)]
44#[derive(Clone, Copy, Default)]
45struct BufferDescriptor {
46 flags: u16,
47 byte_count: u16,
48 buffer_address: PhysicalAddress,
49}
50
51const BD_UOWN: u16 = 0x80;
53const BD_DATA01: u16 = 0x40;
54const BD_DTS: u16 = 0x08;
57const BD_STALL: u16 = 0x04;
58
59const BD_PID_POS: usize = 2;
60const BD_PID_MSK: u16 = 0x3c;
61impl BufferDescriptor {
64 const fn new(flags: u16, byte_count: u16, buffer_address: PhysicalAddress) -> BufferDescriptor {
65 BufferDescriptor {
66 flags,
67 byte_count,
68 buffer_address,
69 }
70 }
71
72 const fn const_default() -> BufferDescriptor {
73 Self::new(0, 0, PhysicalAddress::from_usize(0))
74 }
75
76 fn flags(&self) -> u16 {
77 unsafe { read_volatile(&self.flags) }
78 }
79
80 fn set_flags(&mut self, flags: u16) {
81 unsafe { write_volatile(&mut self.flags, flags) };
82 }
83
84 fn set_byte_count(&mut self, byte_count: u16) {
85 unsafe { write_volatile(&mut self.byte_count, byte_count) };
86 }
87
88 fn set_buffer_address(&mut self, buffer_address: PhysicalAddress) {
89 unsafe { write_volatile(&mut self.buffer_address, buffer_address) };
91 }
92}
93
94const USB_PID_OUT : u8 = 0x1;
95const USB_PID_IN : u8 = 0x9;
96const USB_PID_SETUP: u8 = 0xd;
97
98const N_ENDPOINTS: usize = 16;
99
100#[repr(C, align(512))]
101union BufferDescriptorTable {
102 flat: [BufferDescriptor; 4 * N_ENDPOINTS],
103 ep_dir_ppbi: [[[BufferDescriptor; 2]; 2]; N_ENDPOINTS],
104}
105
106impl BufferDescriptorTable {
107 const fn new() -> BufferDescriptorTable {
108 BufferDescriptorTable {
109 flat: [BufferDescriptor::const_default(); 4 * N_ENDPOINTS],
110 }
111 }
112
113 fn as_raw(&mut self) -> *mut Self {
116 self as *mut Self
117 }
118}
119
120struct EndpointControlBlock {
121 next_odd: bool, data01: bool, stalled: bool,
124 armed_ctr: u8, complete_ctr: u8, next_complete_odd: bool,ep_type: EndpointType,
128 ep_size: u16, ep_buf: [*mut u8; 2], bd: *mut [BufferDescriptor; 2],
131}
132
133unsafe impl Send for EndpointControlBlock {}
134
135impl EndpointControlBlock {
136 fn alloc(
137 ep_size: u16,
138 ep_type: EndpointType,
139 ep_addr: EndpointAddress,
140 bd: *mut [BufferDescriptor; 2],
141 ) -> Result<EndpointControlBlock> {
142 let b0 = unsafe {
143 alloc(
144 Layout::from_size_align(ep_size as usize, 1)
145 .map_err(|_| UsbError::EndpointOverflow)?,
146 )
147 };
148 if b0.is_null() {
149 return Err(UsbError::EndpointOverflow);
150 }
151 let b1 = unsafe {
152 alloc(
153 Layout::from_size_align(ep_size as usize, 1)
154 .map_err(|_| UsbError::EndpointOverflow)?,
155 )
156 };
157 if b1.is_null() {
158 return Err(UsbError::EndpointOverflow);
159 }
160 let bd_pair: &mut [BufferDescriptor; 2] = unsafe { &mut *bd };
161 bd_pair[0].set_flags(0);
162 bd_pair[0].set_buffer_address(virt_to_phys(b0));
163 bd_pair[1].set_flags(0);
164 bd_pair[1].set_buffer_address(virt_to_phys(b1));
165
166 let ep = ep_addr.index();
168 let mut epreg = unsafe { UsbBus::read_epreg(ep) };
169 if ep_addr.is_in() {
170 epreg |= EPREG_EPTXEN_MASK;
171 } else {
172 epreg |= EPREG_EPRXEN_MASK;
173 }
174 epreg |= match ep_type {
175 EndpointType::Control => EPREG_EPHSHK_MASK,
176 EndpointType::Isochronous { synchronization: _, usage: _ } => EPREG_EPCONDIS_MASK,
177 EndpointType::Bulk | EndpointType::Interrupt => EPREG_EPCONDIS_MASK | EPREG_EPHSHK_MASK,
178 };
179 unsafe { UsbBus::write_epreg(ep, epreg) };
180 Ok(EndpointControlBlock {
181 next_odd: false,
182 data01: false,
183 stalled: false,
184 armed_ctr: 0,
185 complete_ctr: 0,
186 next_complete_odd: false,
187 ep_type,
188 ep_size,
189 ep_buf: [b0, b1],
190 bd,
191 })
192 }
193
194 fn can_arm(&mut self) -> Option<&mut [u8]> {
198 let bd: &mut BufferDescriptor = unsafe { &mut (*self.bd)[self.next_odd as usize] };
199 if bd.flags() & BD_UOWN == 0 {
200 unsafe {
201 Some(slice::from_raw_parts_mut(
202 self.ep_buf[self.next_odd as usize],
203 self.ep_size as usize,
204 ))
205 }
206 } else {
207 None
208 }
209 }
210
211 fn arm_generic(&mut self, len: usize, stall: bool) -> Result<usize> {
212 let bd: &mut BufferDescriptor = unsafe { &mut (*self.bd)[self.next_odd as usize] };
213 if len > self.ep_size as usize {
214 return Err(UsbError::BufferOverflow);
215 }
216 if self.armed_ctr + self.complete_ctr >= 2 {
217 return Err(UsbError::WouldBlock);
218 }
219 if self.stalled {
220 if stall {
221 return Err(UsbError::InvalidState);
222 }
223 self.stalled = false;
224 bd.set_flags(0);
225 }
226 bd.set_buffer_address(virt_to_phys(self.ep_buf[self.next_odd as usize]));
227 bd.set_byte_count(len as u16);
228 let is_iso_ep = matches!(self.ep_type, EndpointType::Isochronous { synchronization: _, usage: _ });
229 bd.set_flags( BD_UOWN |
230 if self.data01 { BD_DATA01 } else { 0 } |
231 if is_iso_ep { 0 } else { BD_DTS } |
232 if stall { BD_STALL } else { 0 } );
233 if stall {
234 self.stalled = true;
235 } else {
236 self.next_odd = !self.next_odd;
237 self.armed_ctr += 1;
238 }
239 if !is_iso_ep {
240 self.data01 = !self.data01;
241 }
242 Ok(len)
243 }
244
245 fn cancel(&mut self) {
255 self.next_complete_odd =
256 (self.next_complete_odd as usize ^ self.complete_ctr as usize) & 0x01 != 0;
257 self.complete_ctr = 0;
258 self.next_odd = (self.next_odd as usize ^ self.armed_ctr as usize) & 0x01 != 0;
259 self.armed_ctr = 0;
260 unsafe {
261 (*self.bd)[0].set_flags(0);
262 (*self.bd)[1].set_flags(0);
263 }
264 }
265
266 fn clear_completed(&mut self) {
267 self.next_complete_odd =
268 (self.next_complete_odd as usize ^ self.complete_ctr as usize) & 0x01 != 0;
269 self.complete_ctr = 0;
270 }
271
272 fn write(&mut self, buf: &[u8]) -> udev::Result<usize> {
273 let usb_buf = self.can_arm().ok_or(UsbError::WouldBlock)?;
274 if usb_buf.len() < buf.len() {
275 return Err(UsbError::BufferOverflow);
276 }
277 usb_buf[..buf.len()].copy_from_slice(buf);
278 self.arm_generic(buf.len(), false)
279 }
280
281 fn read(&mut self, buf: &mut [u8]) -> udev::Result<usize> {
282 if self.complete_ctr == 0 {
283 return Err(UsbError::WouldBlock);
284 }
285 let bd: &mut BufferDescriptor = unsafe { &mut (*self.bd)[self.next_complete_odd as usize] };
286
287 let byte_count = bd.byte_count as usize;
288 if byte_count > buf.len() {
289 return Err(UsbError::BufferOverflow);
290 }
291 let ptr = self.ep_buf[self.next_complete_odd as usize];
292 let slice = unsafe { slice::from_raw_parts(ptr, byte_count) };
293 buf[..byte_count].copy_from_slice(slice);
294 self.complete_ctr -= 1;
295
296 self.arm_generic(self.ep_size as usize, false)?;
297 self.next_complete_odd = !self.next_complete_odd;
298 Ok(byte_count)
299 }
300}
301
302impl Drop for EndpointControlBlock {
303 fn drop(&mut self) {
304 unsafe {
305 dealloc(
306 self.ep_buf[0],
307 Layout::from_size_align_unchecked(self.ep_size as usize, 1),
308 );
309 dealloc(
310 self.ep_buf[1],
311 Layout::from_size_align_unchecked(self.ep_size as usize, 1),
312 );
313 }
314 }
315}
316
317type Ecb = [[Option<EndpointControlBlock>; 2]; N_ENDPOINTS];
318
319struct UsbInner {
320 bdt: Pin<Box<BufferDescriptorTable>>,
321 usb: USB,
322 ecb: Ecb,
323 pr_out: u16,
324 pr_su: u16,
325}
326
327pub struct UsbBus(Mutex<RefCell<UsbInner>>);
329
330impl UsbBus {
331 pub fn new(usb: USB) -> UsbBusAllocator<Self> {
333 usb.u1con.write(unsafe { |w| w.bits(0) }); usb.u1ie.write(unsafe { |w| w.bits(0) });
335 usb.u1otgcon.write(unsafe { |w| w.bits(0) });
337 usb.u1pwrc.write(|w| w.usbpwr().bit(true));
338
339 for i in 0..=15 {
341 unsafe { Self::write_epreg(i, 0) };
342 }
343
344 let mut bdt = Box::pin(BufferDescriptorTable::new());
346 let dma_addr = virt_to_phys(bdt.as_raw()).address() as u32;
347 usb.u1bdtp3.write(unsafe { |w| w.bits(dma_addr >> 24) });
348 usb.u1bdtp2.write(unsafe { |w| w.bits(dma_addr >> 16) });
349 usb.u1bdtp1.write(unsafe { |w| w.bits(dma_addr >> 8) });
350
351 let bus = UsbBus(Mutex::new(RefCell::new(UsbInner {
352 bdt,
353 usb,
354 ecb: Ecb::default(),
355 pr_out: 0,
356 pr_su: 0,
357 })));
358 UsbBusAllocator::new(bus)
359 }
360
361 pub fn enable_sof_irq(&self) {
363 critical_section::with(|cs| {
364 let inner = self.0.borrow_ref_mut(cs);
365 inner.usb.u1ieset.write(|w| w.sofie().bit(true));
366 });
367 }
368
369 pub fn disable_sof_irq(&self) {
371 critical_section::with(|cs| {
372 let inner = self.0.borrow_ref_mut(cs);
373 inner.usb.u1ieclr.write(|w| w.sofie().bit(true));
374 });
375 }
376
377 unsafe fn write_epreg(ndx: usize, val: u8) {
379 let epregs = &((*USB::ptr()).u1ep0) as *const _ as usize;
380 let epreg = (epregs + 4 * 4 * ndx) as *mut u32;
381 write_volatile(epreg, val as u32);
382 }
383
384 unsafe fn read_epreg(ndx: usize) -> u8 {
386 let epregs = &((*USB::ptr()).u1ep0) as *const _ as usize;
387 let epreg = (epregs + 4 * 4 * ndx) as *mut u32;
388 read_volatile(epreg) as u8
389 }
390}
391
392impl Drop for UsbBus {
393 fn drop(&mut self) {
394 critical_section::with(|cs| {
395 let usb = &self.0.borrow_ref(cs).usb;
396 usb.u1ie.write(unsafe { |w| w.bits(0) });
397 usb.u1pwrc.write(unsafe { |w| w.bits(0) });
398 });
399 }
400}
401
402impl usb_device::bus::UsbBus for UsbBus {
403 fn alloc_ep(
407 &mut self,
408 ep_dir: UsbDirection,
409 ep_addr: Option<EndpointAddress>,
410 ep_type: EndpointType,
411 ep_size: u16,
412 _interval: u8,
413 ) -> Result<EndpointAddress> {
414 critical_section::with(|cs| {
415 let mut inner = self.0.borrow_ref_mut(cs);
416 let addr = if let Some(a) = ep_addr {
417 if a.direction() != ep_dir {
419 return Err(UsbError::InvalidEndpoint);
420 }
421 let ep = a.index();
423 if ep >= N_ENDPOINTS {
424 return Err(UsbError::EndpointOverflow);
425 }
426 let dir = (a.direction() as u8 >> 7) as usize;
428 if inner.ecb[ep][dir].is_some() {
429 return Err(UsbError::InvalidEndpoint);
430 }
431 a
432 } else {
433 let dir = (ep_dir as u8 >> 7) as usize;
435 let mut addr = None;
436 for ep in 1..N_ENDPOINTS {
437 if inner.ecb[ep][dir].is_none() {
438 addr = Some(EndpointAddress::from_parts(ep, ep_dir));
439 break;
440 }
441 }
442 match addr {
443 Some(a) => a,
444 None => return Err(UsbError::EndpointOverflow),
445 }
446 };
447 let ep = addr.index();
448 let dir = addr.direction() as usize >> 7;
449
450 let bd_pair = unsafe { &mut inner.bdt.ep_dir_ppbi[ep][dir] };
452 let ecb = EndpointControlBlock::alloc(ep_size, ep_type, addr, bd_pair)?;
453 inner.ecb[ep][dir] = Some(ecb);
454 if addr.is_out() {
456 let ecb = inner.ecb[ep][dir].as_mut().unwrap();
457 ecb.arm_generic(ep_size as usize, false)?;
458 }
459 Ok(addr)
460 })
461 }
462
463 fn enable(&mut self) {
464 critical_section::with(|cs| {
465 let inner = self.0.borrow_ref(cs);
466 inner.usb.u1ieset.write(|w| w
470 .trnie().bit(true)
471 .stallie().bit(true)
472 .urstie_detachie().bit(true));
473 inner.usb.u1con.write(|w| w.usben_sofen().bit(true));
474 })
475 }
476
477 fn reset(&self) {
478 critical_section::with(|cs| {
479 let mut inner = self.0.borrow_ref_mut(cs);
480 if let Some(ref mut ecb) = inner.ecb[0][0] {
481 ecb.clear_completed();
482 }
483 });
484 }
485
486 fn set_device_address(&self, addr: u8) {
487 critical_section::with(|cs| {
488 let inner = self.0.borrow_ref_mut(cs);
489 inner
490 .usb
491 .u1addr
492 .write(|w| unsafe { w.bits((addr & 0x7f) as u32) });
493 });
494 }
495
496 fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> udev::Result<usize> {
497 let ep = ep_addr.index();
498 if ep >= N_ENDPOINTS {
499 return Err(UsbError::InvalidEndpoint);
500 }
501 critical_section::with(|cs| {
502 let mut inner = self.0.borrow_ref_mut(cs);
503 let dir = ep_addr.is_in() as usize;
504 let ecb = inner.ecb[ep][dir]
505 .as_mut()
506 .ok_or(UsbError::InvalidEndpoint)?;
507 ecb.write(buf)
508 })
509 }
510
511 fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> udev::Result<usize> {
512 let ep = ep_addr.index();
513 if ep >= N_ENDPOINTS || ep_addr.direction() != UsbDirection::Out {
514 return Err(UsbError::InvalidEndpoint);
515 }
516 critical_section::with(|cs| {
517 let mut inner = self.0.borrow_ref_mut(cs);
518 let ecb = inner.ecb[ep][0].as_mut().ok_or(UsbError::InvalidEndpoint)?;
519 let len = ecb.read(buf)?;
520 inner.pr_out &= !(1 << ep);
521 inner.pr_su &= !(1 << ep);
522 Ok(len)
523 })
524 }
525
526 fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
527 if stalled {
528 let ep = ep_addr.index();
529 unsafe {
530 Self::write_epreg(ep, Self::read_epreg(ep) | EPREG_EPSTALL_MASK);
531 }
532 }
533 }
534
535 fn is_stalled(&self, _ep_addr: EndpointAddress) -> bool {
536 false
537 }
538
539 fn suspend(&self) {}
540
541 fn resume(&self) {}
542
543 fn poll(&self) -> PollResult {
544 critical_section::with(|cs| {
545 let mut inner = self.0.borrow_ref_mut(cs);
546 let mut pr_in = 0u16;
547 let u1eir = inner.usb.u1eir.read().bits();
548 if u1eir != 0 {
549 inner.usb.u1ir.write(|w| unsafe { w.bits(u1eir) });
550 }
551 inner.usb.u1ir.write(|w| w.sofif().bit(true));
552 while inner.usb.u1ir.read().trnif().bit() {
553 let u1stat = inner.usb.u1stat.read().bits(); inner.usb.u1ir.write(|w| w.trnif().bit(true)); let ep = ((u1stat & U1STAT_ENDPT_MASK) >> U1STAT_ENDPT_POSITION) as usize;
556 let dir = ((u1stat & U1STAT_DIR_MASK) >> U1STAT_DIR_POSITION) as usize;
557 let bdt_index = (u1stat >> 2) as usize;
558 let bd_flags = unsafe { inner.bdt.flat[bdt_index].flags() };
559 let pid = ((bd_flags & BD_PID_MSK) >> BD_PID_POS) as u8;
560 match pid {
562 USB_PID_OUT => {
563 if let Some(ref mut ecb) = inner.ecb[ep][dir] {
564 ecb.complete_ctr += 1;
565 ecb.armed_ctr -= 1;
566 }
567 inner.pr_out |= 1 << ep;
568 }
569 USB_PID_IN => {
570 pr_in |= 1 << ep;
571 if let Some(ref mut ecb) = inner.ecb[ep][dir] {
572 ecb.armed_ctr -= 1;
573 }
574 }
575 USB_PID_SETUP => {
576 if let Some(ref mut ecb_in) = inner.ecb[ep][1] {
578 ecb_in.cancel();
579 }
580 let ecb_out = inner.ecb[ep][0].as_mut().unwrap();
581 ecb_out.clear_completed();
583
584 ecb_out.complete_ctr += 1;
585 ecb_out.armed_ctr -= 1;
586 inner.pr_su |= 1 << ep;
587 inner.ecb[ep][0].as_mut().unwrap().data01 = true;
588 inner.ecb[ep][1].as_mut().unwrap().data01 = true;
589 inner.usb.u1conclr.write(|w| w.pktdis_tokbusy().bit(true));
592 }
593 _ => {}
594 }
595 }
596 if inner.usb.u1ir.read().urstif_detachif().bit() {
597 inner.usb.u1addr.write(unsafe { |w| w.bits(0) });
598 inner.usb.u1ir.write(|w| w.urstif_detachif().bit(true));
599 inner.pr_out = 0;
600 let ep0_out = inner.ecb[0][0].as_mut().unwrap();
601 let _ = ep0_out.arm_generic(ep0_out.ep_size as usize, false);
602
603 return PollResult::Reset;
604 }
605 if inner.usb.u1ir.read().stallif().bit() {
606 inner.usb.u1ep0clr.write(|w| w.epstall().bit(true));
607 inner.usb.u1ir.write(|w| w.stallif().bit(true));
608 }
609 if inner.pr_out != 0 || pr_in != 0 || inner.pr_su != 0 {
610 PollResult::Data {
611 ep_out: inner.pr_out,
612 ep_in_complete: pr_in,
613 ep_setup: inner.pr_su,
614 }
615 } else {
616 PollResult::None
617 }
618 })
619 }
620}