Skip to content

Commit 50116d4

Browse files
committed
Add enumerations and allocator for isochronous endpoints
1 parent d0b201e commit 50116d4

File tree

3 files changed

+94
-10
lines changed

3 files changed

+94
-10
lines changed

src/bus.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::endpoint::{Endpoint, EndpointAddress, EndpointDirection, EndpointType};
1+
use crate::endpoint::{
2+
Endpoint, EndpointAddress, EndpointDirection, EndpointType, IsochronousSynchronizationType,
3+
IsochronousUsageType,
4+
};
25
use crate::{Result, UsbDirection, UsbError};
36
use core::cell::RefCell;
47
use core::mem;
@@ -244,6 +247,38 @@ impl<B: UsbBus> UsbBusAllocator<B> {
244247
.expect("alloc_ep failed")
245248
}
246249

250+
/// Allocates an isochronous endpoint.
251+
///
252+
/// # Arguments
253+
///
254+
/// * `synchronization` - Type of synchronization used by the endpoint
255+
/// * `usage` - Whether the endpoint is data, explicit feedback, or data+implicit feedback
256+
/// * `payload_size` - Payload size in bytes.
257+
/// * `interval` - Interval for polling, expressed in frames/microframes.
258+
///
259+
/// See USB 2.0 section 9.6.6.
260+
///
261+
/// # Panics
262+
///
263+
/// Panics if endpoint allocation fails, because running out of endpoints or memory is not
264+
/// feasibly recoverable.
265+
#[inline]
266+
pub fn isochronous<D: EndpointDirection>(
267+
&self,
268+
synchronization: IsochronousSynchronizationType,
269+
usage: IsochronousUsageType,
270+
payload_size: u16,
271+
interval: u8,
272+
) -> Endpoint<'_, B, D> {
273+
self.alloc(
274+
None,
275+
EndpointType::Isochronous((synchronization, usage)),
276+
payload_size,
277+
interval,
278+
)
279+
.expect("alloc_ep failed")
280+
}
281+
247282
/// Allocates a bulk endpoint.
248283
///
249284
/// # Arguments
@@ -263,6 +298,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
263298
/// Allocates an interrupt endpoint.
264299
///
265300
/// * `max_packet_size` - Maximum packet size in bytes. Cannot exceed 64 bytes.
301+
/// * `interval` - Polling interval.
266302
///
267303
/// # Panics
268304
///

src/descriptor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ impl DescriptorWriter<'_> {
324324
let mps = endpoint.max_packet_size();
325325

326326
buf[0] = endpoint.address().into();
327-
buf[1] = endpoint.ep_type() as u8;
327+
buf[1] = endpoint.ep_type().to_bm_attributes();
328328
buf[2] = mps as u8;
329329
buf[3] = (mps >> 8) as u8;
330330
buf[4] = endpoint.interval();

src/endpoint.rs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,69 @@ pub type EndpointOut<'a, B> = Endpoint<'a, B, Out>;
2929
/// A device-to-host (IN) endpoint.
3030
pub type EndpointIn<'a, B> = Endpoint<'a, B, In>;
3131

32-
/// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the
33-
/// transfer bmAttributes transfer type bits.
34-
#[repr(u8)]
32+
/// Isochronous transfers employ one of three synchronization schemes. See USB 2.0 spec 5.12.4.1.
33+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
34+
pub enum IsochronousSynchronizationType {
35+
/// Synchronization is not implemented for this endpoint.
36+
NoSynchronization,
37+
/// Source and Sink sample clocks are free running.
38+
Asynchronous,
39+
/// Source sample clock is locked to Sink, Sink sample clock is locked to data flow.
40+
Adaptive,
41+
/// Source and Sink sample clocks are locked to USB SOF.
42+
Synchronous,
43+
}
44+
45+
/// Intended use of an isochronous endpoint, see USB 2.0 spec sections 5.12 and 9.6.6.
46+
/// Associations between data and feedback endpoints are described in section 9.6.6.
47+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
48+
pub enum IsochronousUsageType {
49+
/// Endpoint is used for isochronous data.
50+
Data,
51+
/// Feedback for synchronization.
52+
Feedback,
53+
/// Endpoint is data and provides implicit feedback for synchronization.
54+
ImplicitFeedbackData,
55+
}
56+
57+
/// USB endpoint transfer type.
3558
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
3659
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3760
pub enum EndpointType {
3861
/// Control endpoint. Used for device management. Only the host can initiate requests. Usually
3962
/// used only endpoint 0.
40-
Control = 0b00,
41-
/// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet.
42-
Isochronous = 0b01,
63+
Control,
64+
/// Isochronous endpoint. Used for time-critical unreliable data.
65+
Isochronous((IsochronousSynchronizationType, IsochronousUsageType)),
4366
/// Bulk endpoint. Used for large amounts of best-effort reliable data.
44-
Bulk = 0b10,
67+
Bulk,
4568
/// Interrupt endpoint. Used for small amounts of time-critical reliable data.
46-
Interrupt = 0b11,
69+
Interrupt,
70+
}
71+
72+
impl EndpointType {
73+
/// Format EndpointType for use in bmAttributes transfer type field USB 2.0 spec section 9.6.6
74+
pub fn to_bm_attributes(&self) -> u8 {
75+
match self {
76+
EndpointType::Control => 0b00,
77+
EndpointType::Isochronous((sync_type, usage_type)) => {
78+
let sync_bits = match sync_type {
79+
IsochronousSynchronizationType::NoSynchronization => 0b00,
80+
IsochronousSynchronizationType::Asynchronous => 0b01,
81+
IsochronousSynchronizationType::Adaptive => 0b10,
82+
IsochronousSynchronizationType::Synchronous => 0b11,
83+
};
84+
let usage_bits = match usage_type {
85+
IsochronousUsageType::Data => 0b00,
86+
IsochronousUsageType::Feedback => 0b01,
87+
IsochronousUsageType::ImplicitFeedbackData => 0b10,
88+
};
89+
(usage_bits << 4) | (sync_bits << 2) | 0b01
90+
}
91+
EndpointType::Bulk => 0b10,
92+
EndpointType::Interrupt => 0b11,
93+
}
94+
}
4795
}
4896

4997
/// Handle for a USB endpoint. The endpoint direction is constrained by the `D` type argument, which

0 commit comments

Comments
 (0)