Skip to content

Commit 3345027

Browse files
committed
Add enumerations and allocator for isochronous endpoints
1 parent b6037b0 commit 3345027

File tree

3 files changed

+94
-11
lines changed

3 files changed

+94
-11
lines changed

src/bus.rs

Lines changed: 36 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,37 @@ 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. Must be 1 to 16,
258+
/// calculated as 2^(interval-1), see USB 2.0 section 9.6.6.
259+
///
260+
/// # Panics
261+
///
262+
/// Panics if endpoint allocation fails, because running out of endpoints or memory is not
263+
/// feasibly recoverable.
264+
#[inline]
265+
pub fn isochronous<D: EndpointDirection>(
266+
&self,
267+
synchronization: IsochronousSynchronizationType,
268+
usage: IsochronousUsageType,
269+
payload_size: u16,
270+
interval: u8,
271+
) -> Endpoint<'_, B, D> {
272+
self.alloc(
273+
None,
274+
EndpointType::Isochronous((synchronization, usage)),
275+
payload_size,
276+
interval,
277+
)
278+
.expect("alloc_ep failed")
279+
}
280+
247281
/// Allocates a bulk endpoint.
248282
///
249283
/// # Arguments
@@ -263,6 +297,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
263297
/// Allocates an interrupt endpoint.
264298
///
265299
/// * `max_packet_size` - Maximum packet size in bytes. Cannot exceed 64 bytes.
300+
/// * `interval` - Polling interval.
266301
///
267302
/// # Panics
268303
///

src/descriptor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,8 @@ impl DescriptorWriter<'_> {
275275
self.write(
276276
descriptor_type::ENDPOINT,
277277
&[
278-
endpoint.address().into(), // bEndpointAddress
279-
endpoint.ep_type() as u8, // bmAttributes
278+
endpoint.address().into(), // bEndpointAddress
279+
endpoint.ep_type().to_bm_attributes(), // bmAttributes
280280
mps as u8,
281281
(mps >> 8) as u8, // wMaxPacketSize
282282
endpoint.interval(), // bInterval

src/endpoint.rs

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

33-
/// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the
34-
/// transfer bmAttributes transfer type bits.
35-
#[repr(u8)]
33+
/// Isochronous transfers employ one of three synchronization schemes. See USB 2.0 spec 5.12.4.1.
34+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
35+
pub enum IsochronousSynchronizationType {
36+
/// Synchronization is not implemented for this endpoint.
37+
NoSynchronization,
38+
/// Source and Sink sample clocks are free running.
39+
Asynchronous,
40+
/// Source sample clock is locked to Sink, Sink sample clock is locked to data flow.
41+
Adaptive,
42+
/// Source and Sink sample clocks are locked to USB SOF.
43+
Synchronous,
44+
}
45+
46+
/// Intended use of an isochronous endpoint, see USB 2.0 spec sections 5.12 and 9.6.6.
47+
/// Associations between data and feedback endpoints are described in section 9.6.6.
48+
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
49+
pub enum IsochronousUsageType {
50+
/// Endpoint is used for isochronous data.
51+
Data,
52+
/// Feedback for synchronization.
53+
Feedback,
54+
/// Endpoint is data and provides implicit feedback for synchronization.
55+
ImplicitFeedbackData,
56+
}
57+
58+
/// USB endpoint transfer type.
3659
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
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)