092c2b7dfe
The stack reads its own descriptors to figure out which endpoints are used in which alt settings, and enables/disables them as needed. The ControlHandler has a callback so it can get notified of alternate setting changes, which is purely informative (it doesn't have to do anything).
139 lines
3.8 KiB
Rust
139 lines
3.8 KiB
Rust
/// Direction of USB traffic. Note that in the USB standard the direction is always indicated from
|
|
/// the perspective of the host, which is backward for devices, but the standard directions are used
|
|
/// for consistency.
|
|
///
|
|
/// The values of the enum also match the direction bit used in endpoint addresses and control
|
|
/// request types.
|
|
#[repr(u8)]
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub enum UsbDirection {
|
|
/// Host to device (OUT)
|
|
Out = 0x00,
|
|
/// Device to host (IN)
|
|
In = 0x80,
|
|
}
|
|
|
|
impl From<u8> for UsbDirection {
|
|
fn from(value: u8) -> Self {
|
|
unsafe { core::mem::transmute(value & 0x80) }
|
|
}
|
|
}
|
|
|
|
/// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the
|
|
/// transfer bmAttributes transfer type bits.
|
|
#[repr(u8)]
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub enum EndpointType {
|
|
/// Control endpoint. Used for device management. Only the host can initiate requests. Usually
|
|
/// used only endpoint 0.
|
|
Control = 0b00,
|
|
/// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet.
|
|
Isochronous = 0b01,
|
|
/// Bulk endpoint. Used for large amounts of best-effort reliable data.
|
|
Bulk = 0b10,
|
|
/// Interrupt endpoint. Used for small amounts of time-critical reliable data.
|
|
Interrupt = 0b11,
|
|
}
|
|
|
|
/// Type-safe endpoint address.
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub struct EndpointAddress(u8);
|
|
|
|
impl From<u8> for EndpointAddress {
|
|
#[inline]
|
|
fn from(addr: u8) -> EndpointAddress {
|
|
EndpointAddress(addr)
|
|
}
|
|
}
|
|
|
|
impl From<EndpointAddress> for u8 {
|
|
#[inline]
|
|
fn from(addr: EndpointAddress) -> u8 {
|
|
addr.0
|
|
}
|
|
}
|
|
|
|
impl EndpointAddress {
|
|
const INBITS: u8 = UsbDirection::In as u8;
|
|
|
|
/// Constructs a new EndpointAddress with the given index and direction.
|
|
#[inline]
|
|
pub fn from_parts(index: usize, dir: UsbDirection) -> Self {
|
|
EndpointAddress(index as u8 | dir as u8)
|
|
}
|
|
|
|
/// Gets the direction part of the address.
|
|
#[inline]
|
|
pub fn direction(&self) -> UsbDirection {
|
|
if (self.0 & Self::INBITS) != 0 {
|
|
UsbDirection::In
|
|
} else {
|
|
UsbDirection::Out
|
|
}
|
|
}
|
|
|
|
/// Returns true if the direction is IN, otherwise false.
|
|
#[inline]
|
|
pub fn is_in(&self) -> bool {
|
|
(self.0 & Self::INBITS) != 0
|
|
}
|
|
|
|
/// Returns true if the direction is OUT, otherwise false.
|
|
#[inline]
|
|
pub fn is_out(&self) -> bool {
|
|
(self.0 & Self::INBITS) == 0
|
|
}
|
|
|
|
/// Gets the index part of the endpoint address.
|
|
#[inline]
|
|
pub fn index(&self) -> usize {
|
|
(self.0 & !Self::INBITS) as usize
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub struct EndpointInfo {
|
|
pub addr: EndpointAddress,
|
|
pub ep_type: EndpointType,
|
|
pub max_packet_size: u16,
|
|
pub interval: u8,
|
|
}
|
|
|
|
/// A handle for a USB interface that contains its number.
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub struct InterfaceNumber(pub(crate) u8);
|
|
|
|
impl InterfaceNumber {
|
|
pub(crate) fn new(index: u8) -> InterfaceNumber {
|
|
InterfaceNumber(index)
|
|
}
|
|
}
|
|
|
|
impl From<InterfaceNumber> for u8 {
|
|
fn from(n: InterfaceNumber) -> u8 {
|
|
n.0
|
|
}
|
|
}
|
|
|
|
/// A handle for a USB string descriptor that contains its index.
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
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
|
|
}
|
|
}
|