aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb-driver/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-01-31 22:27:19 +0100
committerDario Nieuwenhuis <[email protected]>2023-01-31 22:27:19 +0100
commitca10fe7135d10084e38038f3cd433da39e505bea (patch)
tree075aca4a76caccd1bba95869c64bbb838969c8b1 /embassy-usb-driver/src
parent4c1946454874597c358e7c7d5bf555b687376a5b (diff)
usb: docs
Diffstat (limited to 'embassy-usb-driver/src')
-rw-r--r--embassy-usb-driver/src/lib.rs116
1 files changed, 77 insertions, 39 deletions
diff --git a/embassy-usb-driver/src/lib.rs b/embassy-usb-driver/src/lib.rs
index 64d647351..e8f71a2dc 100644
--- a/embassy-usb-driver/src/lib.rs
+++ b/embassy-usb-driver/src/lib.rs
@@ -1,6 +1,8 @@
1#![no_std] 1#![no_std]
2#![feature(async_fn_in_trait)] 2#![feature(async_fn_in_trait)]
3#![allow(incomplete_features)] 3#![allow(incomplete_features)]
4#![doc = include_str!("../README.md")]
5#![warn(missing_docs)]
4 6
5/// Direction of USB traffic. Note that in the USB standard the direction is always indicated from 7/// Direction of USB traffic. Note that in the USB standard the direction is always indicated from
6/// the perspective of the host, which is backward for devices, but the standard directions are used 8/// the perspective of the host, which is backward for devices, but the standard directions are used
@@ -95,46 +97,65 @@ impl EndpointAddress {
95 } 97 }
96} 98}
97 99
100/// Infomation for an endpoint.
98#[derive(Copy, Clone, Eq, PartialEq, Debug)] 101#[derive(Copy, Clone, Eq, PartialEq, Debug)]
99#[cfg_attr(feature = "defmt", derive(defmt::Format))] 102#[cfg_attr(feature = "defmt", derive(defmt::Format))]
100pub struct EndpointInfo { 103pub struct EndpointInfo {
104 /// Endpoint's address.
101 pub addr: EndpointAddress, 105 pub addr: EndpointAddress,
106 /// Endpoint's type.
102 pub ep_type: EndpointType, 107 pub ep_type: EndpointType,
108 /// Max packet size, in bytes.
103 pub max_packet_size: u16, 109 pub max_packet_size: u16,
104 pub interval: u8, 110 /// Polling interval, in milliseconds.
111 pub interval_ms: u8,
105} 112}
106 113
107/// Driver for a specific USB peripheral. Implement this to add support for a new hardware 114/// Main USB driver trait.
108/// platform. 115///
116/// Implement this to add support for a new hardware platform.
109pub trait Driver<'a> { 117pub trait Driver<'a> {
118 /// Type of the OUT endpoints for this driver.
110 type EndpointOut: EndpointOut + 'a; 119 type EndpointOut: EndpointOut + 'a;
120 /// Type of the IN endpoints for this driver.
111 type EndpointIn: EndpointIn + 'a; 121 type EndpointIn: EndpointIn + 'a;
122 /// Type of the control pipe for this driver.
112 type ControlPipe: ControlPipe + 'a; 123 type ControlPipe: ControlPipe + 'a;
124 /// Type for bus control for this driver.
113 type Bus: Bus + 'a; 125 type Bus: Bus + 'a;
114 126
115 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device 127 /// Allocates an OUT endpoint.
116 /// and class implementations to allocate endpoints, and can only be called before 128 ///
117 /// [`start`](Self::start) is called. 129 /// This method is called by the USB stack to allocate endpoints.
130 /// It can only be called before [`start`](Self::start) is called.
118 /// 131 ///
119 /// # Arguments 132 /// # Arguments
120 /// 133 ///
121 /// * `ep_addr` - A static endpoint address to allocate. If Some, the implementation should 134 /// * `ep_type` - the endpoint's type.
122 /// attempt to return an endpoint with the specified address. If None, the implementation
123 /// should return the next available one.
124 /// * `max_packet_size` - Maximum packet size in bytes. 135 /// * `max_packet_size` - Maximum packet size in bytes.
125 /// * `interval` - Polling interval parameter for interrupt endpoints. 136 /// * `interval_ms` - Polling interval parameter for interrupt endpoints.
126 fn alloc_endpoint_out( 137 fn alloc_endpoint_out(
127 &mut self, 138 &mut self,
128 ep_type: EndpointType, 139 ep_type: EndpointType,
129 max_packet_size: u16, 140 max_packet_size: u16,
130 interval: u8, 141 interval_ms: u8,
131 ) -> Result<Self::EndpointOut, EndpointAllocError>; 142 ) -> Result<Self::EndpointOut, EndpointAllocError>;
132 143
144 /// Allocates an IN endpoint.
145 ///
146 /// This method is called by the USB stack to allocate endpoints.
147 /// It can only be called before [`start`](Self::start) is called.
148 ///
149 /// # Arguments
150 ///
151 /// * `ep_type` - the endpoint's type.
152 /// * `max_packet_size` - Maximum packet size in bytes.
153 /// * `interval_ms` - Polling interval parameter for interrupt endpoints.
133 fn alloc_endpoint_in( 154 fn alloc_endpoint_in(
134 &mut self, 155 &mut self,
135 ep_type: EndpointType, 156 ep_type: EndpointType,
136 max_packet_size: u16, 157 max_packet_size: u16,
137 interval: u8, 158 interval_ms: u8,
138 ) -> Result<Self::EndpointIn, EndpointAllocError>; 159 ) -> Result<Self::EndpointIn, EndpointAllocError>;
139 160
140 /// Start operation of the USB device. 161 /// Start operation of the USB device.
@@ -146,35 +167,37 @@ pub trait Driver<'a> {
146 /// This consumes the `Driver` instance, so it's no longer possible to allocate more 167 /// This consumes the `Driver` instance, so it's no longer possible to allocate more
147 /// endpoints. 168 /// endpoints.
148 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe); 169 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe);
149
150 /// Indicates that `set_device_address` must be called before accepting the corresponding
151 /// control transfer, not after.
152 ///
153 /// The default value for this constant is `false`, which corresponds to the USB 2.0 spec, 9.4.6
154 const QUIRK_SET_ADDRESS_BEFORE_STATUS: bool = false;
155} 170}
156 171
172/// USB bus trait.
173///
174/// This trait provides methods that act on the whole bus. It is kept owned by
175/// the main USB task, and used to manage the bus.
157pub trait Bus { 176pub trait Bus {
158 /// Enables the USB peripheral. Soon after enabling the device will be reset, so 177 /// Enable the USB peripheral.
159 /// there is no need to perform a USB reset in this method.
160 async fn enable(&mut self); 178 async fn enable(&mut self);
161 179
162 /// Disables and powers down the USB peripheral. 180 /// Disable and powers down the USB peripheral.
163 async fn disable(&mut self); 181 async fn disable(&mut self);
164 182
183 /// Wait for a bus-related event.
184 ///
185 /// This method should asynchronously wait for an event to happen, then
186 /// return it. See [`Event`] for the list of events this method should return.
165 async fn poll(&mut self) -> Event; 187 async fn poll(&mut self) -> Event;
166 188
167 /// Enables or disables an endpoint. 189 /// Enable or disable an endpoint.
168 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool); 190 fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool);
169 191
170 /// Sets or clears the STALL condition for an endpoint. If the endpoint is an OUT endpoint, it 192 /// Set or clear the STALL condition for an endpoint.
171 /// should be prepared to receive data again. Only used during control transfers. 193 ///
194 /// If the endpoint is an OUT endpoint, it should be prepared to receive data again.
172 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool); 195 fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool);
173 196
174 /// Gets whether the STALL condition is set for an endpoint. Only used during control transfers. 197 /// Get whether the STALL condition is set for an endpoint.
175 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool; 198 fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool;
176 199
177 /// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the 200 /// Simulate a disconnect from the USB bus, causing the host to reset and re-enumerate the
178 /// device. 201 /// device.
179 /// 202 ///
180 /// The default implementation just returns `Unsupported`. 203 /// The default implementation just returns `Unsupported`.
@@ -187,7 +210,7 @@ pub trait Bus {
187 Err(Unsupported) 210 Err(Unsupported)
188 } 211 }
189 212
190 /// Initiates a remote wakeup of the host by the device. 213 /// Initiate a remote wakeup of the host by the device.
191 /// 214 ///
192 /// # Errors 215 /// # Errors
193 /// 216 ///
@@ -196,25 +219,27 @@ pub trait Bus {
196 async fn remote_wakeup(&mut self) -> Result<(), Unsupported>; 219 async fn remote_wakeup(&mut self) -> Result<(), Unsupported>;
197} 220}
198 221
222/// Endpoint trait, common for OUT and IN.
199pub trait Endpoint { 223pub trait Endpoint {
200 /// Get the endpoint address 224 /// Get the endpoint address
201 fn info(&self) -> &EndpointInfo; 225 fn info(&self) -> &EndpointInfo;
202 226
203 /// Waits for the endpoint to be enabled. 227 /// Wait for the endpoint to be enabled.
204 async fn wait_enabled(&mut self); 228 async fn wait_enabled(&mut self);
205} 229}
206 230
231/// OUT Endpoint trait.
207pub trait EndpointOut: Endpoint { 232pub trait EndpointOut: Endpoint {
208 /// Reads a single packet of data from the endpoint, and returns the actual length of 233 /// Read a single packet of data from the endpoint, and return the actual length of
209 /// the packet. 234 /// the packet.
210 /// 235 ///
211 /// This should also clear any NAK flags and prepare the endpoint to receive the next packet. 236 /// This should also clear any NAK flags and prepare the endpoint to receive the next packet.
212 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError>; 237 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError>;
213} 238}
214 239
215/// Trait for USB control pipe. 240/// USB control pipe trait.
216/// 241///
217/// The USB control pipe owns both OUT ep 0 and IN ep 0 in a single 242/// The USB control pipe owns both OUT endpoint 0 and IN endpoint 0 in a single
218/// unit, and manages them together to implement the control pipe state machine. 243/// unit, and manages them together to implement the control pipe state machine.
219/// 244///
220/// The reason this is a separate trait instead of using EndpointOut/EndpointIn is that 245/// The reason this is a separate trait instead of using EndpointOut/EndpointIn is that
@@ -232,6 +257,14 @@ pub trait EndpointOut: Endpoint {
232/// accept() or reject() 257/// accept() or reject()
233/// ``` 258/// ```
234/// 259///
260/// - control out for setting the device address:
261///
262/// ```not_rust
263/// setup()
264/// (...processing...)
265/// accept_set_address(addr) or reject()
266/// ```
267///
235/// - control out with len != 0: 268/// - control out with len != 0:
236/// 269///
237/// ```not_rust 270/// ```not_rust
@@ -280,26 +313,26 @@ pub trait ControlPipe {
280 /// Maximum packet size for the control pipe 313 /// Maximum packet size for the control pipe
281 fn max_packet_size(&self) -> usize; 314 fn max_packet_size(&self) -> usize;
282 315
283 /// Reads a single setup packet from the endpoint. 316 /// Read a single setup packet from the endpoint.
284 async fn setup(&mut self) -> [u8; 8]; 317 async fn setup(&mut self) -> [u8; 8];
285 318
286 /// Reads a DATA OUT packet into `buf` in response to a control write request. 319 /// Read a DATA OUT packet into `buf` in response to a control write request.
287 /// 320 ///
288 /// Must be called after `setup()` for requests with `direction` of `Out` 321 /// Must be called after `setup()` for requests with `direction` of `Out`
289 /// and `length` greater than zero. 322 /// and `length` greater than zero.
290 async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result<usize, EndpointError>; 323 async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result<usize, EndpointError>;
291 324
292 /// Sends a DATA IN packet with `data` in response to a control read request. 325 /// Send a DATA IN packet with `data` in response to a control read request.
293 /// 326 ///
294 /// If `last_packet` is true, the STATUS packet will be ACKed following the transfer of `data`. 327 /// If `last_packet` is true, the STATUS packet will be ACKed following the transfer of `data`.
295 async fn data_in(&mut self, data: &[u8], first: bool, last: bool) -> Result<(), EndpointError>; 328 async fn data_in(&mut self, data: &[u8], first: bool, last: bool) -> Result<(), EndpointError>;
296 329
297 /// Accepts a control request. 330 /// Accept a control request.
298 /// 331 ///
299 /// Causes the STATUS packet for the current request to be ACKed. 332 /// Causes the STATUS packet for the current request to be ACKed.
300 async fn accept(&mut self); 333 async fn accept(&mut self);
301 334
302 /// Rejects a control request. 335 /// Reject a control request.
303 /// 336 ///
304 /// Sets a STALL condition on the pipe to indicate an error. 337 /// Sets a STALL condition on the pipe to indicate an error.
305 async fn reject(&mut self); 338 async fn reject(&mut self);
@@ -311,8 +344,9 @@ pub trait ControlPipe {
311 async fn accept_set_address(&mut self, addr: u8); 344 async fn accept_set_address(&mut self, addr: u8);
312} 345}
313 346
347/// IN Endpoint trait.
314pub trait EndpointIn: Endpoint { 348pub trait EndpointIn: Endpoint {
315 /// Writes a single packet of data to the endpoint. 349 /// Write a single packet of data to the endpoint.
316 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError>; 350 async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError>;
317} 351}
318 352
@@ -338,18 +372,22 @@ pub enum Event {
338 PowerRemoved, 372 PowerRemoved,
339} 373}
340 374
375/// Allocating an endpoint failed.
376///
377/// This can be due to running out of endpoints, or out of endpoint memory,
378/// or because the hardware doesn't support the requested combination of features.
341#[derive(Copy, Clone, Eq, PartialEq, Debug)] 379#[derive(Copy, Clone, Eq, PartialEq, Debug)]
342#[cfg_attr(feature = "defmt", derive(defmt::Format))] 380#[cfg_attr(feature = "defmt", derive(defmt::Format))]
343pub struct EndpointAllocError; 381pub struct EndpointAllocError;
344 382
383/// Operation is unsupported by the driver.
345#[derive(Copy, Clone, Eq, PartialEq, Debug)] 384#[derive(Copy, Clone, Eq, PartialEq, Debug)]
346#[cfg_attr(feature = "defmt", derive(defmt::Format))] 385#[cfg_attr(feature = "defmt", derive(defmt::Format))]
347/// Operation is unsupported by the driver.
348pub struct Unsupported; 386pub struct Unsupported;
349 387
388/// Errors returned by [`EndpointIn::write`] and [`EndpointOut::read`]
350#[derive(Copy, Clone, Eq, PartialEq, Debug)] 389#[derive(Copy, Clone, Eq, PartialEq, Debug)]
351#[cfg_attr(feature = "defmt", derive(defmt::Format))] 390#[cfg_attr(feature = "defmt", derive(defmt::Format))]
352/// Errors returned by [`EndpointIn::write`] and [`EndpointOut::read`]
353pub enum EndpointError { 391pub enum EndpointError {
354 /// Either the packet to be written is too long to fit in the transmission 392 /// Either the packet to be written is too long to fit in the transmission
355 /// buffer or the received packet is too long to fit in `buf`. 393 /// buffer or the received packet is too long to fit in `buf`.