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}