use core::future::Future; use super::types::*; /// Driver for a specific USB peripheral. Implement this to add support for a new hardware /// platform. pub trait Driver<'a> { type EndpointOut: EndpointOut + 'a; type EndpointIn: EndpointIn + 'a; type ControlPipe: ControlPipe + 'a; type Bus: Bus + 'a; /// Allocates an endpoint and specified endpoint parameters. This method is called by the device /// and class implementations to allocate endpoints, and can only be called before /// [`start`](UsbBus::start) is called. /// /// # Arguments /// /// * `ep_addr` - A static endpoint address to allocate. If Some, the implementation should /// attempt to return an endpoint with the specified address. If None, the implementation /// should return the next available one. /// * `max_packet_size` - Maximum packet size in bytes. /// * `interval` - Polling interval parameter for interrupt endpoints. fn alloc_endpoint_out( &mut self, ep_type: EndpointType, max_packet_size: u16, interval: u8, ) -> Result; fn alloc_endpoint_in( &mut self, ep_type: EndpointType, max_packet_size: u16, interval: u8, ) -> Result; /// Start operation of the USB device. /// /// This returns the `Bus` and `ControlPipe` instances that are used to operate /// the USB device. Additionally, this makes all the previously allocated endpoints /// start operating. /// /// This consumes the `Driver` instance, so it's no longer possible to allocate more /// endpoints. fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe); /// Indicates that `set_device_address` must be called before accepting the corresponding /// control transfer, not after. /// /// The default value for this constant is `false`, which corresponds to the USB 2.0 spec, 9.4.6 const QUIRK_SET_ADDRESS_BEFORE_STATUS: bool = false; } pub trait Bus { type EnableFuture<'a>: Future + 'a where Self: 'a; type DisableFuture<'a>: Future + 'a where Self: 'a; type PollFuture<'a>: Future + 'a where Self: 'a; type RemoteWakeupFuture<'a>: Future> + 'a where Self: 'a; /// Enables the USB peripheral. Soon after enabling the device will be reset, so /// there is no need to perform a USB reset in this method. fn enable(&mut self) -> Self::EnableFuture<'_>; /// Disables and powers down the USB peripheral. fn disable(&mut self) -> Self::DisableFuture<'_>; fn poll<'a>(&'a mut self) -> Self::PollFuture<'a>; /// Sets the device USB address to `addr`. fn set_address(&mut self, addr: u8); /// Enables or disables an endpoint. fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool); /// Sets or clears the STALL condition for an endpoint. If the endpoint is an OUT endpoint, it /// should be prepared to receive data again. Only used during control transfers. fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool); /// Gets whether the STALL condition is set for an endpoint. Only used during control transfers. fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool; /// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the /// device. /// /// The default implementation just returns `Unsupported`. /// /// # Errors /// /// * [`Unsupported`](crate::UsbError::Unsupported) - This UsbBus implementation doesn't support /// simulating a disconnect or it has not been enabled at creation time. fn force_reset(&mut self) -> Result<(), Unsupported> { Err(Unsupported) } /// Initiates a remote wakeup of the host by the device. /// /// # Errors /// /// * [`Unsupported`](crate::UsbError::Unsupported) - This UsbBus implementation doesn't support /// remote wakeup or it has not been enabled at creation time. fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_>; } pub trait Endpoint { type WaitEnabledFuture<'a>: Future + 'a where Self: 'a; /// Get the endpoint address fn info(&self) -> &EndpointInfo; /// Waits for the endpoint to be enabled. fn wait_enabled(&mut self) -> Self::WaitEnabledFuture<'_>; } pub trait EndpointOut: Endpoint { type ReadFuture<'a>: Future> + 'a where Self: 'a; /// Reads a single packet of data from the endpoint, and returns the actual length of /// the packet. /// /// This should also clear any NAK flags and prepare the endpoint to receive the next packet. fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a>; } pub trait ControlPipe { type SetupFuture<'a>: Future + 'a where Self: 'a; type DataOutFuture<'a>: Future> + 'a where Self: 'a; type DataInFuture<'a>: Future> + 'a where Self: 'a; type AcceptFuture<'a>: Future + 'a where Self: 'a; type RejectFuture<'a>: Future + 'a where Self: 'a; /// Maximum packet size for the control pipe fn max_packet_size(&self) -> usize; /// Reads a single setup packet from the endpoint. fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a>; /// Reads a DATA OUT packet into `buf` in response to a control write request. /// /// Must be called after `setup()` for requests with `direction` of `Out` /// and `length` greater than zero. fn data_out<'a>( &'a mut self, buf: &'a mut [u8], first: bool, last: bool, ) -> Self::DataOutFuture<'a>; /// Sends a DATA IN packet with `data` in response to a control read request. /// /// If `last_packet` is true, the STATUS packet will be ACKed following the transfer of `data`. fn data_in<'a>(&'a mut self, data: &'a [u8], first: bool, last: bool) -> Self::DataInFuture<'a>; /// Accepts a control request. /// /// Causes the STATUS packet for the current request to be ACKed. fn accept<'a>(&'a mut self) -> Self::AcceptFuture<'a>; /// Rejects a control request. /// /// Sets a STALL condition on the pipe to indicate an error. fn reject<'a>(&'a mut self) -> Self::RejectFuture<'a>; } pub trait EndpointIn: Endpoint { type WriteFuture<'a>: Future> + 'a where Self: 'a; /// Writes a single packet of data to the endpoint. fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a>; } #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Event returned by [`Bus::poll`]. pub enum Event { /// The USB reset condition has been detected. Reset, /// A USB suspend request has been detected or, in the case of self-powered devices, the device /// has been disconnected from the USB bus. Suspend, /// A USB resume request has been detected after being suspended or, in the case of self-powered /// devices, the device has been connected to the USB bus. Resume, } #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct EndpointAllocError; #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Operation is unsupported by the driver. pub struct Unsupported; #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Errors returned by [`EndpointIn::write`] and [`EndpointOut::read`] pub enum EndpointError { /// Either the packet to be written is too long to fit in the transmission /// buffer or the received packet is too long to fit in `buf`. BufferOverflow, /// The endpoint is disabled. Disabled, }