use std::{fmt::Display, io};
mod control;
#[allow(unused)]
pub(crate) use control::{request_type, SETUP_PACKET_SIZE};
pub use control::{ControlIn, ControlOut, ControlType, Direction, Recipient};
mod buffer;
pub(crate) use buffer::Allocator;
pub use buffer::Buffer;
pub(crate) mod internal;
use crate::{descriptors::TransferType, platform};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TransferError {
Cancelled,
Stall,
Disconnected,
Fault,
InvalidArgument,
Unknown(u32),
}
impl Display for TransferError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TransferError::Cancelled => write!(f, "transfer was cancelled"),
TransferError::Stall => write!(f, "endpoint stalled"),
TransferError::Disconnected => write!(f, "device disconnected"),
TransferError::Fault => write!(f, "hardware fault or protocol violation"),
TransferError::InvalidArgument => write!(f, "invalid or unsupported argument"),
TransferError::Unknown(e) => {
write!(f, "unknown (")?;
platform::format_os_error_code(f, *e)?;
write!(f, ")")
}
}
}
}
impl std::error::Error for TransferError {}
impl From<TransferError> for io::Error {
fn from(value: TransferError) -> Self {
match value {
TransferError::Cancelled => io::Error::new(io::ErrorKind::Interrupted, value),
TransferError::Stall => io::Error::new(io::ErrorKind::ConnectionReset, value),
TransferError::Disconnected => io::Error::new(io::ErrorKind::ConnectionAborted, value),
TransferError::Fault => io::Error::other(value),
TransferError::InvalidArgument => io::Error::new(io::ErrorKind::InvalidInput, value),
TransferError::Unknown(_) => io::Error::other(value),
}
}
}
mod private {
pub trait Sealed {}
}
pub trait EndpointDirection: private::Sealed + Send + Sync {
const DIR: Direction;
}
pub enum In {}
impl private::Sealed for In {}
impl EndpointDirection for In {
const DIR: Direction = Direction::In;
}
pub enum Out {}
impl private::Sealed for Out {}
impl EndpointDirection for Out {
const DIR: Direction = Direction::Out;
}
pub trait EndpointType: private::Sealed + Send + Sync + Unpin {
const TYPE: TransferType;
}
pub trait BulkOrInterrupt: EndpointType {}
pub enum Bulk {}
impl private::Sealed for Bulk {}
impl EndpointType for Bulk {
const TYPE: TransferType = TransferType::Bulk;
}
impl BulkOrInterrupt for Bulk {}
pub enum Interrupt {}
impl private::Sealed for Interrupt {}
impl EndpointType for Interrupt {
const TYPE: TransferType = TransferType::Interrupt;
}
impl BulkOrInterrupt for Interrupt {}
#[derive(Debug)]
pub struct Completion {
pub buffer: Buffer,
pub actual_len: usize,
pub status: Result<(), TransferError>,
}
impl Completion {
pub fn into_result(self) -> Result<Buffer, TransferError> {
self.status.map(|()| self.buffer)
}
}