use alloc::sync::Arc;
use alloc::vec::Vec;
use core::fmt;
use super::descriptor::{ConfigurationDescriptor, DescriptorKind, Descriptors};
use super::{
Completion, DeviceAddress, Direction, EP0_RANK, Recipient, RequestKind, SetupPacket, Speed,
Status, UsbDevice, feature, request,
};
use crate::core::error::{Error, Result};
use crate::core::state::{Sink, Source};
use crate::core::sync::{LockRank, Mutex};
pub trait Function: Send + Sync + fmt::Debug {
fn descriptors(&self) -> &Descriptors;
fn speed(&self) -> Speed;
fn reset(&self) {}
fn configure(&self, value: u8) -> bool {
let _ = value;
true
}
fn control_in(&self, setup: SetupPacket) -> Option<Vec<u8>> {
let _ = setup;
None
}
fn control_out(&self, setup: SetupPacket, data: &[u8]) -> bool {
let _ = (setup, data);
false
}
fn endpoint_in(&self, endpoint: u8, dst: &mut [u8]) -> Completion {
let _ = (endpoint, dst);
Completion::stall()
}
fn endpoint_out(&self, endpoint: u8, src: &[u8]) -> Completion {
let _ = (endpoint, src);
Completion::stall()
}
fn peek_in(&self, endpoint: u8, dst: &mut [u8]) -> Completion {
let _ = (endpoint, dst);
Completion::nak()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
enum Stage {
#[default]
Idle,
DataIn,
DataOut,
StatusIn,
}
impl Stage {
const fn code(self) -> u8 {
match self {
Stage::Idle => 0,
Stage::DataIn => 1,
Stage::DataOut => 2,
Stage::StatusIn => 3,
}
}
const fn from_code(code: u8) -> Stage {
match code {
1 => Stage::DataIn,
2 => Stage::DataOut,
3 => Stage::StatusIn,
_ => Stage::Idle,
}
}
}
#[derive(Debug, Clone, Default)]
struct Ep0State {
address: u8,
pending_address: Option<u8>,
configuration: u8,
stage: Stage,
setup: SetupPacket,
buffer: Vec<u8>,
offset: usize,
stalled: bool,
halted: u32,
remote_wakeup: bool,
}
pub struct Endpoint0 {
function: Arc<dyn Function>,
state: Mutex<Ep0State>,
}
impl fmt::Debug for Endpoint0 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("Endpoint0");
s.field("function", &self.function);
match self.state.try_lock() {
Some(state) => s.field("state", &*state).finish(),
None => s.field("state", &"<in use>").finish(),
}
}
}
impl Endpoint0 {
#[must_use]
pub fn new(function: Arc<dyn Function>) -> Endpoint0 {
Endpoint0 {
function,
state: Mutex::with_rank(EP0_RANK, Ep0State::default()),
}
}
#[must_use]
pub fn function(&self) -> &Arc<dyn Function> {
&self.function
}
#[must_use]
pub fn address(&self) -> DeviceAddress {
DeviceAddress(self.state.lock().address)
}
#[must_use]
pub fn configuration(&self) -> u8 {
self.state.lock().configuration
}
#[must_use]
pub fn is_halted(&self, endpoint: u8) -> bool {
self.state.lock().halted & Ep0State::halt_bit(endpoint) != 0
}
pub fn bus_reset(&self) {
{
let mut state = self.state.lock();
*state = Ep0State::default();
}
self.function.reset();
}
pub fn setup(&self, packet: SetupPacket) -> Status {
let mut state = self.state.lock();
state.setup = packet;
state.buffer.clear();
state.offset = 0;
state.stalled = false;
state.stage = Stage::Idle;
let handled = match packet.kind() {
RequestKind::Standard => self.standard(&mut state, packet),
RequestKind::Class | RequestKind::Vendor => self.class(&mut state, packet),
RequestKind::Reserved => false,
};
if !handled {
state.stalled = true;
}
Status::Ack
}
pub fn read(&self, dst: &mut [u8]) -> Completion {
let mut state = self.state.lock();
if state.stalled {
return Completion::stall();
}
match state.stage {
Stage::DataIn => {
let remaining = state.buffer.len().saturating_sub(state.offset);
let n = remaining.min(dst.len());
dst[..n].copy_from_slice(&state.buffer[state.offset..state.offset + n]);
state.offset += n;
Completion::ack(n as u64)
}
Stage::StatusIn => {
if let Some(address) = state.pending_address.take() {
state.address = address;
}
state.stage = Stage::Idle;
Completion::ack(0)
}
Stage::Idle | Stage::DataOut => Completion::stall(),
}
}
pub fn write(&self, src: &[u8]) -> Completion {
let mut state = self.state.lock();
if state.stalled {
return Completion::stall();
}
match state.stage {
Stage::DataIn => {
state.stage = Stage::Idle;
Completion::ack(0)
}
Stage::DataOut => {
let want = usize::from(state.setup.length);
let room = want.saturating_sub(state.buffer.len());
let n = room.min(src.len());
state.buffer.extend_from_slice(&src[..n]);
if state.buffer.len() >= want || n < src.len() {
let setup = state.setup;
let data = core::mem::take(&mut state.buffer);
let accepted = match setup.kind() {
RequestKind::Standard => self.standard_out(&mut state, setup, &data),
RequestKind::Class | RequestKind::Vendor => {
self.function.control_out(setup, &data)
}
RequestKind::Reserved => false,
};
if accepted {
state.stage = Stage::StatusIn;
} else {
state.stalled = true;
}
}
Completion::ack(n as u64)
}
Stage::Idle | Stage::StatusIn => Completion::stall(),
}
}
pub fn save<S: Sink + ?Sized>(&self, w: &mut S) -> Result<()> {
let state = self.state.lock();
w.write_u8(state.address)?;
w.write_u8(state.pending_address.unwrap_or(0))?;
w.write_bool(state.pending_address.is_some())?;
w.write_u8(state.configuration)?;
w.write_u8(state.stage.code())?;
w.write_all(&state.setup.encode())?;
w.write_bytes(&state.buffer)?;
w.write_u64(state.offset as u64)?;
w.write_bool(state.stalled)?;
w.write_u32(state.halted)?;
w.write_bool(state.remote_wakeup)
}
pub fn load<'a, S: Source<'a> + ?Sized>(&self, r: &mut S) -> Result<()> {
let address = r.read_u8()?;
let pending = r.read_u8()?;
let has_pending = r.read_bool()?;
let configuration = r.read_u8()?;
let stage = Stage::from_code(r.read_u8()?);
let mut setup = [0u8; 8];
setup.copy_from_slice(r.take(8)?);
let buffer = r.read_bytes()?.to_vec();
let offset = r.read_u64()?;
let stalled = r.read_bool()?;
let halted = r.read_u32()?;
let remote_wakeup = r.read_bool()?;
let offset = usize::try_from(offset).map_err(|_| {
Error::State(alloc::string::String::from(
"usb: a control-stage offset larger than this host's address space",
))
})?;
if offset > buffer.len() {
return Err(Error::State(alloc::format!(
"usb: a control transfer {offset} bytes into a {}-byte buffer",
buffer.len()
)));
}
let mut state = self.state.lock();
*state = Ep0State {
address: address & DeviceAddress::MAX,
pending_address: has_pending.then_some(pending & DeviceAddress::MAX),
configuration,
stage,
setup: SetupPacket::decode(&setup),
buffer,
offset,
stalled,
halted,
remote_wakeup,
};
Ok(())
}
fn standard(&self, state: &mut Ep0State, packet: SetupPacket) -> bool {
if packet.direction() == Direction::In {
let Some(bytes) = self.standard_in(state, packet) else {
return false;
};
let want = usize::from(packet.length);
state.buffer = bytes;
state.buffer.truncate(want);
state.stage = if want == 0 {
Stage::StatusIn
} else {
Stage::DataIn
};
return true;
}
if packet.length == 0 {
if !self.standard_out(state, packet, &[]) {
return false;
}
state.stage = Stage::StatusIn;
return true;
}
false
}
fn standard_in(&self, state: &Ep0State, packet: SetupPacket) -> Option<Vec<u8>> {
let descriptors = self.function.descriptors();
match (packet.request, packet.recipient()) {
(request::GET_STATUS, Recipient::Device) => {
let self_powered = descriptors
.attributes_of(state.configuration)
.is_some_and(|a| a & ConfigurationDescriptor::SELF_POWERED != 0);
let status = u8::from(self_powered) | (u8::from(state.remote_wakeup) << 1);
Some(alloc::vec![status, 0])
}
(request::GET_STATUS, Recipient::Interface) => Some(alloc::vec![0, 0]),
(request::GET_STATUS, Recipient::Endpoint) => {
let halted = state.halted & Ep0State::halt_bit(packet.index as u8) != 0;
Some(alloc::vec![u8::from(halted), 0])
}
(request::GET_DESCRIPTOR, Recipient::Device) => {
let (kind, index) = packet.descriptor();
let kind = DescriptorKind(kind);
if kind.is_standard() {
descriptors.get(kind, index).map(<[u8]>::to_vec)
} else {
self.function.control_in(packet)
}
}
(request::GET_DESCRIPTOR, _) => self.function.control_in(packet),
(request::GET_CONFIGURATION, Recipient::Device) => {
Some(alloc::vec![state.configuration])
}
(request::GET_INTERFACE, Recipient::Interface) => {
Some(alloc::vec![0])
}
_ => None,
}
}
fn standard_out(&self, state: &mut Ep0State, packet: SetupPacket, data: &[u8]) -> bool {
let _ = data;
match (packet.request, packet.recipient()) {
(request::SET_ADDRESS, Recipient::Device) => {
if packet.value > u16::from(DeviceAddress::MAX) {
return false;
}
state.pending_address = Some(packet.value as u8);
true
}
(request::SET_CONFIGURATION, Recipient::Device) => {
let value = packet.value as u8;
if value != 0 && !self.function.descriptors().has_configuration_value(value) {
return false;
}
if !self.function.configure(value) {
return false;
}
state.configuration = value;
state.halted = 0;
true
}
(request::SET_INTERFACE, Recipient::Interface) => packet.value == 0,
(request::CLEAR_FEATURE, Recipient::Endpoint)
| (request::SET_FEATURE, Recipient::Endpoint) => {
if packet.value != feature::ENDPOINT_HALT {
return false;
}
let bit = Ep0State::halt_bit(packet.index as u8);
if packet.request == request::SET_FEATURE {
state.halted |= bit;
} else {
state.halted &= !bit;
}
true
}
(request::CLEAR_FEATURE, Recipient::Device)
| (request::SET_FEATURE, Recipient::Device) => match packet.value {
feature::DEVICE_REMOTE_WAKEUP => {
state.remote_wakeup = packet.request == request::SET_FEATURE;
true
}
feature::TEST_MODE => true,
_ => false,
},
_ => false,
}
}
fn class(&self, state: &mut Ep0State, packet: SetupPacket) -> bool {
if packet.direction() == Direction::In {
let Some(bytes) = self.function.control_in(packet) else {
return false;
};
let want = usize::from(packet.length);
state.buffer = bytes;
state.buffer.truncate(want);
state.stage = if want == 0 {
Stage::StatusIn
} else {
Stage::DataIn
};
return true;
}
if packet.length == 0 {
if !self.function.control_out(packet, &[]) {
return false;
}
state.stage = Stage::StatusIn;
return true;
}
state.stage = Stage::DataOut;
true
}
}
impl Ep0State {
const fn halt_bit(address: u8) -> u32 {
let number = (address & 0x0f) as u32;
if address & Direction::BIT != 0 {
1u32 << (number + 16)
} else {
1u32 << number
}
}
}
#[derive(Debug)]
pub struct Peripheral {
ep0: Endpoint0,
}
impl Peripheral {
#[must_use]
pub fn new(function: Arc<dyn Function>) -> Peripheral {
Peripheral {
ep0: Endpoint0::new(function),
}
}
#[must_use]
pub fn endpoint0(&self) -> &Endpoint0 {
&self.ep0
}
}
impl UsbDevice for Peripheral {
fn speed(&self) -> Speed {
self.ep0.function().speed()
}
fn address(&self) -> DeviceAddress {
self.ep0.address()
}
fn bus_reset(&self) {
self.ep0.bus_reset();
}
fn setup(&self, endpoint: u8, packet: SetupPacket) -> Status {
if endpoint != 0 {
return Status::Stall;
}
self.ep0.setup(packet)
}
fn transfer_in(&self, endpoint: u8, dst: &mut [u8]) -> Completion {
if endpoint == 0 {
return self.ep0.read(dst);
}
if self.ep0.is_halted(endpoint | Direction::BIT) {
return Completion::stall();
}
self.ep0.function().endpoint_in(endpoint, dst)
}
fn transfer_out(&self, endpoint: u8, src: &[u8]) -> Completion {
if endpoint == 0 {
return self.ep0.write(src);
}
if self.ep0.is_halted(endpoint) {
return Completion::stall();
}
self.ep0.function().endpoint_out(endpoint, src)
}
fn peek_in(&self, endpoint: u8, dst: &mut [u8]) -> Completion {
if endpoint == 0 {
let state = self.ep0.state.lock();
if state.stalled || state.stage != Stage::DataIn {
return Completion::nak();
}
let remaining = state.buffer.len().saturating_sub(state.offset);
let n = remaining.min(dst.len());
dst[..n].copy_from_slice(&state.buffer[state.offset..state.offset + n]);
return Completion::ack(n as u64);
}
self.ep0.function().peek_in(endpoint, dst)
}
}
const _: () = {
assert!(EP0_RANK.0 > LockRank::BUS.0);
assert!(EP0_RANK.0 < LockRank::DEVICE.0);
};