Skip to main content

usb_if/
endpoint.rs

1use alloc::vec::Vec;
2use core::ptr::NonNull;
3
4use crate::{descriptor::EndpointDescriptor, host::ControlSetup};
5pub use crate::{descriptor::EndpointType, transfer::Direction};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct EndpointAddress(u8);
9
10impl EndpointAddress {
11    pub const CONTROL: Self = Self(0);
12
13    pub const fn new(raw: u8) -> Self {
14        Self(raw)
15    }
16
17    pub const fn raw(self) -> u8 {
18        self.0
19    }
20
21    pub fn direction(self) -> Direction {
22        Direction::from_address(self.0)
23    }
24}
25
26impl From<u8> for EndpointAddress {
27    fn from(value: u8) -> Self {
28        Self::new(value)
29    }
30}
31
32impl From<EndpointAddress> for u8 {
33    fn from(value: EndpointAddress) -> Self {
34        value.raw()
35    }
36}
37
38#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct RequestId(u64);
40
41impl RequestId {
42    pub const fn new(raw: u64) -> Self {
43        Self(raw)
44    }
45
46    pub const fn raw(self) -> u64 {
47        self.0
48    }
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
52pub struct EndpointInfo {
53    pub address: EndpointAddress,
54    pub transfer_type: EndpointType,
55    pub direction: Direction,
56    pub max_packet_size: u16,
57    pub packets_per_microframe: usize,
58    pub interval: u8,
59}
60
61impl EndpointInfo {
62    pub const fn control() -> Self {
63        Self {
64            address: EndpointAddress::CONTROL,
65            transfer_type: EndpointType::Control,
66            direction: Direction::Out,
67            max_packet_size: 64,
68            packets_per_microframe: 1,
69            interval: 0,
70        }
71    }
72}
73
74impl From<&EndpointDescriptor> for EndpointInfo {
75    fn from(desc: &EndpointDescriptor) -> Self {
76        Self {
77            address: EndpointAddress::new(desc.address),
78            transfer_type: desc.transfer_type,
79            direction: desc.direction,
80            max_packet_size: desc.max_packet_size,
81            packets_per_microframe: desc.packets_per_microframe,
82            interval: desc.interval,
83        }
84    }
85}
86
87#[derive(Clone, Copy)]
88pub struct TransferBuffer {
89    pub ptr: NonNull<u8>,
90    pub len: usize,
91}
92
93unsafe impl Send for TransferBuffer {}
94unsafe impl Sync for TransferBuffer {}
95
96impl TransferBuffer {
97    pub fn from_mut_slice(slice: &mut [u8]) -> Option<Self> {
98        NonNull::new(slice.as_mut_ptr()).map(|ptr| Self {
99            ptr,
100            len: slice.len(),
101        })
102    }
103
104    pub fn from_slice(slice: &[u8]) -> Option<Self> {
105        NonNull::new(slice.as_ptr() as *mut u8).map(|ptr| Self {
106            ptr,
107            len: slice.len(),
108        })
109    }
110}
111
112#[derive(Clone)]
113pub enum TransferKind {
114    Control(ControlSetup),
115    Bulk,
116    Interrupt,
117    Isochronous { packet_lengths: Vec<usize> },
118}
119
120impl TransferKind {
121    pub fn get_control(&self) -> Option<&ControlSetup> {
122        match self {
123            TransferKind::Control(setup) => Some(setup),
124            _ => None,
125        }
126    }
127
128    pub fn iso_packet_lengths(&self) -> Option<&[usize]> {
129        match self {
130            TransferKind::Isochronous { packet_lengths } => Some(packet_lengths),
131            _ => None,
132        }
133    }
134}
135
136#[derive(Clone, Copy, Debug, PartialEq, Eq)]
137pub struct IsoPacketRequest {
138    pub length: usize,
139}
140
141#[derive(Clone)]
142pub enum TransferRequest {
143    Control {
144        setup: ControlSetup,
145        direction: Direction,
146        buffer: Option<TransferBuffer>,
147    },
148    Bulk {
149        direction: Direction,
150        buffer: Option<TransferBuffer>,
151    },
152    Interrupt {
153        direction: Direction,
154        buffer: Option<TransferBuffer>,
155    },
156    Isochronous {
157        direction: Direction,
158        buffer: Option<TransferBuffer>,
159        packets: Vec<IsoPacketRequest>,
160    },
161}
162
163impl TransferRequest {
164    pub fn control_in(setup: ControlSetup, buffer: &mut [u8]) -> Self {
165        Self::Control {
166            setup,
167            direction: Direction::In,
168            buffer: TransferBuffer::from_mut_slice(buffer),
169        }
170    }
171
172    pub fn control_out(setup: ControlSetup, buffer: &[u8]) -> Self {
173        Self::Control {
174            setup,
175            direction: Direction::Out,
176            buffer: TransferBuffer::from_slice(buffer),
177        }
178    }
179
180    pub fn bulk_in(buffer: &mut [u8]) -> Self {
181        Self::Bulk {
182            direction: Direction::In,
183            buffer: TransferBuffer::from_mut_slice(buffer),
184        }
185    }
186
187    pub fn bulk_out(buffer: &[u8]) -> Self {
188        Self::Bulk {
189            direction: Direction::Out,
190            buffer: TransferBuffer::from_slice(buffer),
191        }
192    }
193
194    pub fn interrupt_in(buffer: &mut [u8]) -> Self {
195        Self::Interrupt {
196            direction: Direction::In,
197            buffer: TransferBuffer::from_mut_slice(buffer),
198        }
199    }
200
201    pub fn interrupt_out(buffer: &[u8]) -> Self {
202        Self::Interrupt {
203            direction: Direction::Out,
204            buffer: TransferBuffer::from_slice(buffer),
205        }
206    }
207
208    pub fn iso_in(buffer: &mut [u8], packet_lengths: &[usize]) -> Self {
209        Self::Isochronous {
210            direction: Direction::In,
211            buffer: TransferBuffer::from_mut_slice(buffer),
212            packets: packet_lengths
213                .iter()
214                .copied()
215                .map(|length| IsoPacketRequest { length })
216                .collect(),
217        }
218    }
219
220    pub fn iso_out(buffer: &[u8], packet_lengths: &[usize]) -> Self {
221        Self::Isochronous {
222            direction: Direction::Out,
223            buffer: TransferBuffer::from_slice(buffer),
224            packets: packet_lengths
225                .iter()
226                .copied()
227                .map(|length| IsoPacketRequest { length })
228                .collect(),
229        }
230    }
231
232    pub fn direction(&self) -> Direction {
233        match self {
234            Self::Control { direction, .. }
235            | Self::Bulk { direction, .. }
236            | Self::Interrupt { direction, .. }
237            | Self::Isochronous { direction, .. } => *direction,
238        }
239    }
240
241    pub fn buffer(&self) -> Option<TransferBuffer> {
242        match self {
243            Self::Control { buffer, .. }
244            | Self::Bulk { buffer, .. }
245            | Self::Interrupt { buffer, .. }
246            | Self::Isochronous { buffer, .. } => *buffer,
247        }
248    }
249
250    pub fn iso_packets(&self) -> &[IsoPacketRequest] {
251        match self {
252            Self::Isochronous { packets, .. } => packets,
253            _ => &[],
254        }
255    }
256}
257
258impl From<TransferRequest> for (TransferKind, Direction, Option<TransferBuffer>) {
259    fn from(request: TransferRequest) -> Self {
260        match request {
261            TransferRequest::Control {
262                setup,
263                direction,
264                buffer,
265            } => (TransferKind::Control(setup), direction, buffer),
266            TransferRequest::Bulk { direction, buffer } => (TransferKind::Bulk, direction, buffer),
267            TransferRequest::Interrupt { direction, buffer } => {
268                (TransferKind::Interrupt, direction, buffer)
269            }
270            TransferRequest::Isochronous {
271                direction,
272                buffer,
273                packets,
274            } => (
275                TransferKind::Isochronous {
276                    packet_lengths: packets.into_iter().map(|packet| packet.length).collect(),
277                },
278                direction,
279                buffer,
280            ),
281        }
282    }
283}
284
285impl From<(TransferKind, Direction, Option<TransferBuffer>)> for TransferRequest {
286    fn from((kind, direction, buffer): (TransferKind, Direction, Option<TransferBuffer>)) -> Self {
287        match kind {
288            TransferKind::Control(setup) => Self::Control {
289                setup,
290                direction,
291                buffer,
292            },
293            TransferKind::Bulk => Self::Bulk { direction, buffer },
294            TransferKind::Interrupt => Self::Interrupt { direction, buffer },
295            TransferKind::Isochronous { packet_lengths } => Self::Isochronous {
296                direction,
297                buffer,
298                packets: packet_lengths
299                    .into_iter()
300                    .map(|length| IsoPacketRequest { length })
301                    .collect(),
302            },
303        }
304    }
305}
306
307#[derive(Clone, Copy, Debug, PartialEq, Eq)]
308pub enum TransferStatus {
309    Completed,
310    Stalled,
311    Cancelled,
312    Error,
313}
314
315#[derive(Clone, Copy, Debug, PartialEq, Eq)]
316pub struct IsoPacketResult {
317    pub requested_length: usize,
318    pub actual_length: usize,
319    pub status: TransferStatus,
320}
321
322#[derive(Clone, Debug)]
323pub struct TransferCompletion {
324    pub request_id: RequestId,
325    pub status: TransferStatus,
326    pub actual_length: usize,
327    pub iso_packets: Vec<IsoPacketResult>,
328}