use core::cell::RefCell; use core::marker::PhantomData; use core::pin::Pin; use usb_device::bus::UsbBus; use usb_device::class::UsbClass; use usb_device::device::UsbDevice; use crate::interrupt; use crate::usb_serial::{ReadInterface, UsbSerial, WriteInterface}; use crate::util::peripheral::{PeripheralMutex, PeripheralState}; pub struct State<'bus, B, T> where B: UsbBus, T: ClassSet, { device: UsbDevice<'bus, B>, pub(crate) classes: T, } pub struct Usb<'bus, B, T> where B: UsbBus, T: ClassSet, { // Don't you dare moving out `PeripheralMutex` inner: RefCell>>, } impl<'bus, B, T> Usb<'bus, B, T> where B: UsbBus, T: ClassSet, { pub fn new>( device: UsbDevice<'bus, B>, class_set: S, irq: interrupt::OTG_FSInterrupt, ) -> Self { let state = State { device, classes: class_set.into_class_set(), }; let mutex = PeripheralMutex::new(state, irq); Self { inner: RefCell::new(mutex), } } pub fn start(self: Pin<&mut Self>) { let this = unsafe { self.get_unchecked_mut() }; let mut mutex = this.inner.borrow_mut(); let mutex = unsafe { Pin::new_unchecked(&mut *mutex) }; // Use inner to register the irq mutex.with(|_, _| {}); } } impl<'bus, 'c, B, T> Usb<'bus, B, T> where B: UsbBus, T: ClassSet + SerialState<'bus, 'c, B, Index0>, { pub fn take_serial_0<'a>( self: Pin<&'a Self>, ) -> ( ReadInterface<'a, 'bus, 'c, Index0, B, T>, WriteInterface<'a, 'bus, 'c, Index0, B, T>, ) { let this = self.get_ref(); let r = ReadInterface { inner: &this.inner, _buf_lifetime: PhantomData, _index: PhantomData, }; let w = WriteInterface { inner: &this.inner, _buf_lifetime: PhantomData, _index: PhantomData, }; (r, w) } } impl<'bus, 'c, B, T> Usb<'bus, B, T> where B: UsbBus, T: ClassSet + SerialState<'bus, 'c, B, Index1>, { pub fn take_serial_1<'a>( self: Pin<&'a Self>, ) -> ( ReadInterface<'a, 'bus, 'c, Index1, B, T>, WriteInterface<'a, 'bus, 'c, Index1, B, T>, ) { let this = self.get_ref(); let r = ReadInterface { inner: &this.inner, _buf_lifetime: PhantomData, _index: PhantomData, }; let w = WriteInterface { inner: &this.inner, _buf_lifetime: PhantomData, _index: PhantomData, }; (r, w) } } impl<'bus, B, T> PeripheralState for State<'bus, B, T> where B: UsbBus, T: ClassSet, { type Interrupt = interrupt::OTG_FSInterrupt; fn on_interrupt(&mut self) { self.classes.poll_all(&mut self.device); } } pub trait ClassSet { fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool; } pub trait IntoClassSet> { fn into_class_set(self) -> C; } pub struct ClassSet1 where B: UsbBus, C1: UsbClass, { class: C1, _bus: PhantomData, } pub struct ClassSet2 where B: UsbBus, C1: UsbClass, C2: UsbClass, { class1: C1, class2: C2, _bus: PhantomData, } pub struct Index0; pub struct Index1; impl ClassSet for ClassSet1 where B: UsbBus, C1: UsbClass, { fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool { device.poll(&mut [&mut self.class]) } } impl ClassSet for ClassSet2 where B: UsbBus, C1: UsbClass, C2: UsbClass, { fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool { device.poll(&mut [&mut self.class1, &mut self.class2]) } } impl IntoClassSet> for C1 where B: UsbBus, C1: UsbClass, { fn into_class_set(self) -> ClassSet1 { ClassSet1 { class: self, _bus: PhantomData, } } } impl IntoClassSet> for (C1, C2) where B: UsbBus, C1: UsbClass, C2: UsbClass, { fn into_class_set(self) -> ClassSet2 { ClassSet2 { class1: self.0, class2: self.1, _bus: PhantomData, } } } pub trait SerialState<'bus, 'a, B: UsbBus, I> { fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B>; } impl<'bus, 'a, B: UsbBus> SerialState<'bus, 'a, B, Index0> for ClassSet1> { fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B> { &mut self.class } } impl<'bus, 'a, B, C2> SerialState<'bus, 'a, B, Index0> for ClassSet2, C2> where B: UsbBus, C2: UsbClass, { fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B> { &mut self.class1 } } impl<'bus, 'a, B, C1> SerialState<'bus, 'a, B, Index1> for ClassSet2> where B: UsbBus, C1: UsbClass, { fn get_serial(&mut self) -> &mut UsbSerial<'bus, 'a, B> { &mut self.class2 } }