use core::cell::RefCell;
use core::sync::atomic::{AtomicPtr, Ordering};
use core::mem;
use core::ptr;
use crate::{Result, UsbDirection, UsbError};
use crate::endpoint::{Endpoint, EndpointDirection, EndpointType, EndpointAddress};
pub trait UsbBus: Sync + Sized {
fn alloc_ep(
&mut self,
ep_dir: UsbDirection,
ep_addr: Option<EndpointAddress>,
ep_type: EndpointType,
max_packet_size: u16,
interval: u8) -> Result<EndpointAddress>;
fn enable(&mut self);
fn reset(&self);
fn set_device_address(&self, addr: u8);
fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> Result<usize>;
fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> Result<usize>;
fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool);
fn is_stalled(&self, ep_addr: EndpointAddress) -> bool;
fn suspend(&self);
fn resume(&self);
fn poll(&self) -> PollResult;
fn force_reset(&self) -> Result<()> {
Err(UsbError::Unsupported)
}
}
struct AllocatorState {
next_interface_number: u8,
next_string_index: u8,
}
pub struct UsbBusAllocator<B: UsbBus> {
bus: RefCell<B>,
bus_ptr: AtomicPtr<B>,
state: RefCell<AllocatorState>,
}
impl<B: UsbBus> UsbBusAllocator<B> {
pub fn new(bus: B) -> UsbBusAllocator<B> {
UsbBusAllocator {
bus: RefCell::new(bus),
bus_ptr: AtomicPtr::new(ptr::null_mut()),
state: RefCell::new(AllocatorState {
next_interface_number: 0,
next_string_index: 4,
}),
}
}
pub(crate) fn freeze(&self) -> &B {
mem::forget(self.state.borrow_mut());
self.bus.borrow_mut().enable();
let mut bus_ref = self.bus.borrow_mut();
let bus_ptr_v = &mut *bus_ref as *mut B;
self.bus_ptr.store(bus_ptr_v, Ordering::SeqCst);
mem::forget(bus_ref);
unsafe { &*bus_ptr_v }
}
pub fn interface(&self) -> InterfaceNumber {
let mut state = self.state.borrow_mut();
let number = state.next_interface_number;
state.next_interface_number += 1;
InterfaceNumber(number)
}
pub fn string(&self) -> StringIndex {
let mut state = self.state.borrow_mut();
let index = state.next_string_index;
state.next_string_index += 1;
StringIndex(index)
}
pub fn alloc<'a, D: EndpointDirection>(
&self,
ep_addr: Option<EndpointAddress>,
ep_type: EndpointType,
max_packet_size: u16,
interval: u8) -> Result<Endpoint<'_, B, D>>
{
self.bus.borrow_mut()
.alloc_ep(
D::DIRECTION,
ep_addr, ep_type,
max_packet_size,
interval)
.map(|a| Endpoint::new(&self.bus_ptr, a, ep_type, max_packet_size, interval))
}
#[inline]
pub fn control<D: EndpointDirection>(&self, max_packet_size: u16) -> Endpoint<'_, B, D> {
self.alloc(None, EndpointType::Control, max_packet_size, 0).unwrap()
}
#[inline]
pub fn bulk<D: EndpointDirection>(&self, max_packet_size: u16) -> Endpoint<'_, B, D> {
self.alloc(None, EndpointType::Bulk, max_packet_size, 0).unwrap()
}
#[inline]
pub fn interrupt<D: EndpointDirection>(&self, max_packet_size: u16, interval: u8)
-> Endpoint<'_, B, D>
{
self.alloc(None, EndpointType::Interrupt, max_packet_size, interval).unwrap()
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct InterfaceNumber(u8);
impl From<InterfaceNumber> for u8 {
fn from(n: InterfaceNumber) -> u8 { n.0 }
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct StringIndex(u8);
impl StringIndex {
pub(crate) fn new(index: u8) -> StringIndex {
StringIndex(index)
}
}
impl From<StringIndex> for u8 {
fn from(i: StringIndex) -> u8 { i.0 }
}
pub enum PollResult {
None,
Reset,
Data {
ep_out: u16,
ep_in_complete: u16,
ep_setup: u16
},
Suspend,
Resume,
}