aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src
diff options
context:
space:
mode:
authorHenrik Alsér <[email protected]>2022-05-12 15:24:46 +0200
committerGitHub <[email protected]>2022-05-12 15:24:46 +0200
commit0be9184efc8f814a19081c2176b8317bd5217f0f (patch)
tree5b9469de15c0a1cc6e106a9a7455602e3bfaad17 /embassy-usb/src
parent1ca5475010a1cae6ebc55a27948ca4320decd5cd (diff)
parent30d4d0e9d78681e16a68ff953c61b96c9863bfc6 (diff)
Merge branch 'embassy-rs:master' into qdec
Diffstat (limited to 'embassy-usb/src')
-rw-r--r--embassy-usb/src/builder.rs14
-rw-r--r--embassy-usb/src/control.rs150
-rw-r--r--embassy-usb/src/descriptor.rs1
-rw-r--r--embassy-usb/src/driver.rs21
-rw-r--r--embassy-usb/src/lib.rs335
5 files changed, 218 insertions, 303 deletions
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 8cf9c82a9..698a5f765 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -372,7 +372,6 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
372 372
373 fn endpoint_in( 373 fn endpoint_in(
374 &mut self, 374 &mut self,
375 ep_addr: Option<EndpointAddress>,
376 ep_type: EndpointType, 375 ep_type: EndpointType,
377 max_packet_size: u16, 376 max_packet_size: u16,
378 interval: u8, 377 interval: u8,
@@ -380,7 +379,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
380 let ep = self 379 let ep = self
381 .builder 380 .builder
382 .driver 381 .driver
383 .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) 382 .alloc_endpoint_in(ep_type, max_packet_size, interval)
384 .expect("alloc_endpoint_in failed"); 383 .expect("alloc_endpoint_in failed");
385 384
386 self.builder.config_descriptor.endpoint(ep.info()); 385 self.builder.config_descriptor.endpoint(ep.info());
@@ -390,7 +389,6 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
390 389
391 fn endpoint_out( 390 fn endpoint_out(
392 &mut self, 391 &mut self,
393 ep_addr: Option<EndpointAddress>,
394 ep_type: EndpointType, 392 ep_type: EndpointType,
395 max_packet_size: u16, 393 max_packet_size: u16,
396 interval: u8, 394 interval: u8,
@@ -398,7 +396,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
398 let ep = self 396 let ep = self
399 .builder 397 .builder
400 .driver 398 .driver
401 .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) 399 .alloc_endpoint_out(ep_type, max_packet_size, interval)
402 .expect("alloc_endpoint_out failed"); 400 .expect("alloc_endpoint_out failed");
403 401
404 self.builder.config_descriptor.endpoint(ep.info()); 402 self.builder.config_descriptor.endpoint(ep.info());
@@ -411,7 +409,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
411 /// Descriptors are written in the order builder functions are called. Note that some 409 /// Descriptors are written in the order builder functions are called. Note that some
412 /// classes care about the order. 410 /// classes care about the order.
413 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { 411 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn {
414 self.endpoint_in(None, EndpointType::Bulk, max_packet_size, 0) 412 self.endpoint_in(EndpointType::Bulk, max_packet_size, 0)
415 } 413 }
416 414
417 /// Allocate a BULK OUT endpoint and write its descriptor. 415 /// Allocate a BULK OUT endpoint and write its descriptor.
@@ -419,7 +417,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
419 /// Descriptors are written in the order builder functions are called. Note that some 417 /// Descriptors are written in the order builder functions are called. Note that some
420 /// classes care about the order. 418 /// classes care about the order.
421 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { 419 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut {
422 self.endpoint_out(None, EndpointType::Bulk, max_packet_size, 0) 420 self.endpoint_out(EndpointType::Bulk, max_packet_size, 0)
423 } 421 }
424 422
425 /// Allocate a INTERRUPT IN endpoint and write its descriptor. 423 /// Allocate a INTERRUPT IN endpoint and write its descriptor.
@@ -427,11 +425,11 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
427 /// Descriptors are written in the order builder functions are called. Note that some 425 /// Descriptors are written in the order builder functions are called. Note that some
428 /// classes care about the order. 426 /// classes care about the order.
429 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn { 427 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn {
430 self.endpoint_in(None, EndpointType::Interrupt, max_packet_size, interval) 428 self.endpoint_in(EndpointType::Interrupt, max_packet_size, interval)
431 } 429 }
432 430
433 /// Allocate a INTERRUPT OUT endpoint and write its descriptor. 431 /// Allocate a INTERRUPT OUT endpoint and write its descriptor.
434 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut { 432 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut {
435 self.endpoint_out(None, EndpointType::Interrupt, max_packet_size, interval) 433 self.endpoint_out(EndpointType::Interrupt, max_packet_size, interval)
436 } 434 }
437} 435}
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index ff42f9d78..12e5303c3 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -1,8 +1,5 @@
1use core::mem; 1use core::mem;
2 2
3use crate::descriptor::DescriptorWriter;
4use crate::driver::{self, EndpointError};
5
6use super::types::*; 3use super::types::*;
7 4
8/// Control request type. 5/// Control request type.
@@ -191,151 +188,8 @@ pub trait ControlHandler {
191 } 188 }
192 189
193 /// Called when a GET_DESCRIPTOR STRING control request is received. 190 /// Called when a GET_DESCRIPTOR STRING control request is received.
194 /// 191 fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&str> {
195 /// Write the response string somewhere (usually to `buf`, but you may use another buffer 192 let _ = (index, lang_id);
196 /// owned by yourself, or a static buffer), then return it.
197 fn get_string<'a>(
198 &'a mut self,
199 index: StringIndex,
200 lang_id: u16,
201 buf: &'a mut [u8],
202 ) -> Option<&'a str> {
203 let _ = (index, lang_id, buf);
204 None 193 None
205 } 194 }
206} 195}
207
208/// Typestate representing a ControlPipe in the DATA IN stage
209#[derive(Debug)]
210#[cfg_attr(feature = "defmt", derive(defmt::Format))]
211pub(crate) struct DataInStage {
212 pub(crate) length: usize,
213}
214
215/// Typestate representing a ControlPipe in the DATA OUT stage
216#[derive(Debug)]
217#[cfg_attr(feature = "defmt", derive(defmt::Format))]
218pub(crate) struct DataOutStage {
219 length: usize,
220}
221
222/// Typestate representing a ControlPipe in the STATUS stage
223#[derive(Debug)]
224#[cfg_attr(feature = "defmt", derive(defmt::Format))]
225pub(crate) struct StatusStage {}
226
227#[derive(Debug)]
228#[cfg_attr(feature = "defmt", derive(defmt::Format))]
229pub(crate) enum Setup {
230 DataIn(Request, DataInStage),
231 DataOut(Request, DataOutStage),
232}
233
234pub(crate) struct ControlPipe<C: driver::ControlPipe> {
235 control: C,
236}
237
238impl<C: driver::ControlPipe> ControlPipe<C> {
239 pub(crate) fn new(control: C) -> Self {
240 ControlPipe { control }
241 }
242
243 pub(crate) async fn setup(&mut self) -> Setup {
244 let req = self.control.setup().await;
245 trace!("control request: {:02x}", req);
246
247 match (req.direction, req.length) {
248 (UsbDirection::Out, n) => Setup::DataOut(
249 req,
250 DataOutStage {
251 length: usize::from(n),
252 },
253 ),
254 (UsbDirection::In, n) => Setup::DataIn(
255 req,
256 DataInStage {
257 length: usize::from(n),
258 },
259 ),
260 }
261 }
262
263 pub(crate) async fn data_out<'a>(
264 &mut self,
265 buf: &'a mut [u8],
266 stage: DataOutStage,
267 ) -> Result<(&'a [u8], StatusStage), EndpointError> {
268 if stage.length == 0 {
269 Ok((&[], StatusStage {}))
270 } else {
271 let req_length = stage.length;
272 let max_packet_size = self.control.max_packet_size();
273 let mut total = 0;
274
275 for chunk in buf.chunks_mut(max_packet_size) {
276 let size = self.control.data_out(chunk).await?;
277 total += size;
278 if size < max_packet_size || total == req_length {
279 break;
280 }
281 }
282
283 let res = &buf[0..total];
284 #[cfg(feature = "defmt")]
285 trace!(" control out data: {:02x}", res);
286 #[cfg(not(feature = "defmt"))]
287 trace!(" control out data: {:02x?}", res);
288
289 Ok((res, StatusStage {}))
290 }
291 }
292
293 pub(crate) async fn accept_in(&mut self, buf: &[u8], stage: DataInStage) {
294 #[cfg(feature = "defmt")]
295 trace!(" control in accept {:02x}", buf);
296 #[cfg(not(feature = "defmt"))]
297 trace!(" control in accept {:02x?}", buf);
298
299 let req_len = stage.length;
300 let len = buf.len().min(req_len);
301 let max_packet_size = self.control.max_packet_size();
302 let need_zlp = len != req_len && (len % usize::from(max_packet_size)) == 0;
303
304 let mut chunks = buf[0..len]
305 .chunks(max_packet_size)
306 .chain(need_zlp.then(|| -> &[u8] { &[] }));
307
308 while let Some(chunk) = chunks.next() {
309 match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
310 Ok(()) => {}
311 Err(e) => {
312 warn!("control accept_in failed: {:?}", e);
313 return;
314 }
315 }
316 }
317 }
318
319 pub(crate) async fn accept_in_writer(
320 &mut self,
321 req: Request,
322 stage: DataInStage,
323 f: impl FnOnce(&mut DescriptorWriter),
324 ) {
325 let mut buf = [0; 256];
326 let mut w = DescriptorWriter::new(&mut buf);
327 f(&mut w);
328 let pos = w.position().min(usize::from(req.length));
329 self.accept_in(&buf[..pos], stage).await
330 }
331
332 pub(crate) fn accept(&mut self, _: StatusStage) {
333 trace!(" control accept");
334 self.control.accept();
335 }
336
337 pub(crate) fn reject(&mut self) {
338 trace!(" control reject");
339 self.control.reject();
340 }
341}
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs
index dce326780..7f23fd921 100644
--- a/embassy-usb/src/descriptor.rs
+++ b/embassy-usb/src/descriptor.rs
@@ -244,6 +244,7 @@ impl<'a> DescriptorWriter<'a> {
244 } 244 }
245 245
246 /// Writes a string descriptor. 246 /// Writes a string descriptor.
247 #[allow(unused)]
247 pub(crate) fn string(&mut self, string: &str) { 248 pub(crate) fn string(&mut self, string: &str) {
248 let mut pos = self.position; 249 let mut pos = self.position;
249 250
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs
index e552dc7b6..57f2b0656 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb/src/driver.rs
@@ -14,7 +14,7 @@ pub trait Driver<'a> {
14 14
15 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device 15 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device
16 /// and class implementations to allocate endpoints, and can only be called before 16 /// and class implementations to allocate endpoints, and can only be called before
17 /// [`enable`](UsbBus::enable) is called. 17 /// [`start`](UsbBus::start) is called.
18 /// 18 ///
19 /// # Arguments 19 /// # Arguments
20 /// 20 ///
@@ -25,7 +25,6 @@ pub trait Driver<'a> {
25 /// * `interval` - Polling interval parameter for interrupt endpoints. 25 /// * `interval` - Polling interval parameter for interrupt endpoints.
26 fn alloc_endpoint_out( 26 fn alloc_endpoint_out(
27 &mut self, 27 &mut self,
28 ep_addr: Option<EndpointAddress>,
29 ep_type: EndpointType, 28 ep_type: EndpointType,
30 max_packet_size: u16, 29 max_packet_size: u16,
31 interval: u8, 30 interval: u8,
@@ -33,20 +32,20 @@ pub trait Driver<'a> {
33 32
34 fn alloc_endpoint_in( 33 fn alloc_endpoint_in(
35 &mut self, 34 &mut self,
36 ep_addr: Option<EndpointAddress>,
37 ep_type: EndpointType, 35 ep_type: EndpointType,
38 max_packet_size: u16, 36 max_packet_size: u16,
39 interval: u8, 37 interval: u8,
40 ) -> Result<Self::EndpointIn, EndpointAllocError>; 38 ) -> Result<Self::EndpointIn, EndpointAllocError>;
41 39
42 fn alloc_control_pipe( 40 /// Start operation of the USB device.
43 &mut self, 41 ///
44 max_packet_size: u16, 42 /// This returns the `Bus` and `ControlPipe` instances that are used to operate
45 ) -> Result<Self::ControlPipe, EndpointAllocError>; 43 /// the USB device. Additionally, this makes all the previously allocated endpoints
46 44 /// start operating.
47 /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so 45 ///
48 /// there is no need to perform a USB reset in this method. 46 /// This consumes the `Driver` instance, so it's no longer possible to allocate more
49 fn into_bus(self) -> Self::Bus; 47 /// endpoints.
48 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe);
50 49
51 /// Indicates that `set_device_address` must be called before accepting the corresponding 50 /// Indicates that `set_device_address` must be called before accepting the corresponding
52 /// control transfer, not after. 51 /// control transfer, not after.
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 3bfedc048..b135f5eb3 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -16,6 +16,7 @@ use embassy::util::{select, Either};
16use heapless::Vec; 16use heapless::Vec;
17 17
18use crate::descriptor_reader::foreach_endpoint; 18use crate::descriptor_reader::foreach_endpoint;
19use crate::driver::ControlPipe;
19 20
20use self::control::*; 21use self::control::*;
21use self::descriptor::*; 22use self::descriptor::*;
@@ -100,15 +101,19 @@ struct Interface<'d> {
100} 101}
101 102
102pub struct UsbDevice<'d, D: Driver<'d>> { 103pub struct UsbDevice<'d, D: Driver<'d>> {
104 control_buf: &'d mut [u8],
105 control: D::ControlPipe,
106 inner: Inner<'d, D>,
107}
108
109struct Inner<'d, D: Driver<'d>> {
103 bus: D::Bus, 110 bus: D::Bus,
104 handler: Option<&'d dyn DeviceStateHandler>, 111 handler: Option<&'d dyn DeviceStateHandler>,
105 control: ControlPipe<D::ControlPipe>,
106 112
107 config: Config<'d>, 113 config: Config<'d>,
108 device_descriptor: &'d [u8], 114 device_descriptor: &'d [u8],
109 config_descriptor: &'d [u8], 115 config_descriptor: &'d [u8],
110 bos_descriptor: &'d [u8], 116 bos_descriptor: &'d [u8],
111 control_buf: &'d mut [u8],
112 117
113 device_state: UsbDeviceState, 118 device_state: UsbDeviceState,
114 suspended: bool, 119 suspended: bool,
@@ -121,7 +126,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> {
121 126
122impl<'d, D: Driver<'d>> UsbDevice<'d, D> { 127impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
123 pub(crate) fn build( 128 pub(crate) fn build(
124 mut driver: D, 129 driver: D,
125 config: Config<'d>, 130 config: Config<'d>,
126 handler: Option<&'d dyn DeviceStateHandler>, 131 handler: Option<&'d dyn DeviceStateHandler>,
127 device_descriptor: &'d [u8], 132 device_descriptor: &'d [u8],
@@ -130,29 +135,28 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
130 interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, 135 interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
131 control_buf: &'d mut [u8], 136 control_buf: &'d mut [u8],
132 ) -> UsbDevice<'d, D> { 137 ) -> UsbDevice<'d, D> {
133 let control = driver 138 // Start the USB bus.
134 .alloc_control_pipe(config.max_packet_size_0 as u16)
135 .expect("failed to alloc control endpoint");
136
137 // Enable the USB bus.
138 // This prevent further allocation by consuming the driver. 139 // This prevent further allocation by consuming the driver.
139 let bus = driver.into_bus(); 140 let (bus, control) = driver.start(config.max_packet_size_0 as u16);
140 141
141 Self { 142 Self {
142 bus,
143 config,
144 handler,
145 control: ControlPipe::new(control),
146 device_descriptor,
147 config_descriptor,
148 bos_descriptor,
149 control_buf, 143 control_buf,
150 device_state: UsbDeviceState::Disabled, 144 control,
151 suspended: false, 145 inner: Inner {
152 remote_wakeup_enabled: false, 146 bus,
153 self_powered: false, 147 config,
154 pending_address: 0, 148 handler,
155 interfaces, 149 device_descriptor,
150 config_descriptor,
151 bos_descriptor,
152
153 device_state: UsbDeviceState::Disabled,
154 suspended: false,
155 remote_wakeup_enabled: false,
156 self_powered: false,
157 pending_address: 0,
158 interfaces,
159 },
156 } 160 }
157 } 161 }
158 162
@@ -176,42 +180,34 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
176 /// before calling any other `UsbDevice` methods to fully reset the 180 /// before calling any other `UsbDevice` methods to fully reset the
177 /// peripheral. 181 /// peripheral.
178 pub async fn run_until_suspend(&mut self) -> () { 182 pub async fn run_until_suspend(&mut self) -> () {
179 if self.device_state == UsbDeviceState::Disabled { 183 if self.inner.device_state == UsbDeviceState::Disabled {
180 self.bus.enable().await; 184 self.inner.bus.enable().await;
181 self.device_state = UsbDeviceState::Default; 185 self.inner.device_state = UsbDeviceState::Default;
182 186
183 if let Some(h) = &self.handler { 187 if let Some(h) = &self.inner.handler {
184 h.enabled(true); 188 h.enabled(true);
185 } 189 }
186 } 190 }
187 191
188 loop { 192 while !self.inner.suspended {
189 let control_fut = self.control.setup(); 193 let control_fut = self.control.setup();
190 let bus_fut = self.bus.poll(); 194 let bus_fut = self.inner.bus.poll();
191 match select(bus_fut, control_fut).await { 195 match select(bus_fut, control_fut).await {
192 Either::First(evt) => { 196 Either::First(evt) => self.inner.handle_bus_event(evt),
193 self.handle_bus_event(evt); 197 Either::Second(req) => self.handle_control(req).await,
194 if self.suspended {
195 return;
196 }
197 }
198 Either::Second(req) => match req {
199 Setup::DataIn(req, stage) => self.handle_control_in(req, stage).await,
200 Setup::DataOut(req, stage) => self.handle_control_out(req, stage).await,
201 },
202 } 198 }
203 } 199 }
204 } 200 }
205 201
206 /// Disables the USB peripheral. 202 /// Disables the USB peripheral.
207 pub async fn disable(&mut self) { 203 pub async fn disable(&mut self) {
208 if self.device_state != UsbDeviceState::Disabled { 204 if self.inner.device_state != UsbDeviceState::Disabled {
209 self.bus.disable().await; 205 self.inner.bus.disable().await;
210 self.device_state = UsbDeviceState::Disabled; 206 self.inner.device_state = UsbDeviceState::Disabled;
211 self.suspended = false; 207 self.inner.suspended = false;
212 self.remote_wakeup_enabled = false; 208 self.inner.remote_wakeup_enabled = false;
213 209
214 if let Some(h) = &self.handler { 210 if let Some(h) = &self.inner.handler {
215 h.enabled(false); 211 h.enabled(false);
216 } 212 }
217 } 213 }
@@ -221,9 +217,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
221 /// 217 ///
222 /// This future is cancel-safe. 218 /// This future is cancel-safe.
223 pub async fn wait_resume(&mut self) { 219 pub async fn wait_resume(&mut self) {
224 while self.suspended { 220 while self.inner.suspended {
225 let evt = self.bus.poll().await; 221 let evt = self.inner.bus.poll().await;
226 self.handle_bus_event(evt); 222 self.inner.handle_bus_event(evt);
227 } 223 }
228 } 224 }
229 225
@@ -236,11 +232,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
236 /// After dropping the future, [`UsbDevice::disable()`] should be called 232 /// After dropping the future, [`UsbDevice::disable()`] should be called
237 /// before calling any other `UsbDevice` methods to fully reset the peripheral. 233 /// before calling any other `UsbDevice` methods to fully reset the peripheral.
238 pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { 234 pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> {
239 if self.suspended && self.remote_wakeup_enabled { 235 if self.inner.suspended && self.inner.remote_wakeup_enabled {
240 self.bus.remote_wakeup().await?; 236 self.inner.bus.remote_wakeup().await?;
241 self.suspended = false; 237 self.inner.suspended = false;
242 238
243 if let Some(h) = &self.handler { 239 if let Some(h) = &self.inner.handler {
244 h.suspended(false); 240 h.suspended(false);
245 } 241 }
246 242
@@ -250,6 +246,88 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
250 } 246 }
251 } 247 }
252 248
249 async fn handle_control(&mut self, req: Request) {
250 trace!("control request: {:02x}", req);
251
252 match req.direction {
253 UsbDirection::In => self.handle_control_in(req).await,
254 UsbDirection::Out => self.handle_control_out(req).await,
255 }
256 }
257
258 async fn handle_control_in(&mut self, req: Request) {
259 let mut resp_length = req.length as usize;
260 let max_packet_size = self.control.max_packet_size();
261
262 // If we don't have an address yet, respond with max 1 packet.
263 // The host doesn't know our EP0 max packet size yet, and might assume
264 // a full-length packet is a short packet, thinking we're done sending data.
265 // See https://github.com/hathach/tinyusb/issues/184
266 const DEVICE_DESCRIPTOR_LEN: usize = 18;
267 if self.inner.pending_address == 0
268 && max_packet_size < DEVICE_DESCRIPTOR_LEN
269 && (max_packet_size as usize) < resp_length
270 {
271 trace!("received control req while not addressed: capping response to 1 packet.");
272 resp_length = max_packet_size;
273 }
274
275 match self.inner.handle_control_in(req, &mut self.control_buf) {
276 InResponse::Accepted(data) => {
277 let len = data.len().min(resp_length);
278 let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0;
279
280 let mut chunks = data[0..len]
281 .chunks(max_packet_size)
282 .chain(need_zlp.then(|| -> &[u8] { &[] }));
283
284 while let Some(chunk) = chunks.next() {
285 match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
286 Ok(()) => {}
287 Err(e) => {
288 warn!("control accept_in failed: {:?}", e);
289 return;
290 }
291 }
292 }
293 }
294 InResponse::Rejected => self.control.reject(),
295 }
296 }
297
298 async fn handle_control_out(&mut self, req: Request) {
299 let req_length = req.length as usize;
300 let max_packet_size = self.control.max_packet_size();
301 let mut total = 0;
302
303 for chunk in self.control_buf[..req_length].chunks_mut(max_packet_size) {
304 let size = match self.control.data_out(chunk).await {
305 Ok(x) => x,
306 Err(e) => {
307 warn!("usb: failed to read CONTROL OUT data stage: {:?}", e);
308 return;
309 }
310 };
311 total += size;
312 if size < max_packet_size || total == req_length {
313 break;
314 }
315 }
316
317 let data = &self.control_buf[0..total];
318 #[cfg(feature = "defmt")]
319 trace!(" control out data: {:02x}", data);
320 #[cfg(not(feature = "defmt"))]
321 trace!(" control out data: {:02x?}", data);
322
323 match self.inner.handle_control_out(req, data) {
324 OutResponse::Accepted => self.control.accept(),
325 OutResponse::Rejected => self.control.reject(),
326 }
327 }
328}
329
330impl<'d, D: Driver<'d>> Inner<'d, D> {
253 fn handle_bus_event(&mut self, evt: Event) { 331 fn handle_bus_event(&mut self, evt: Event) {
254 match evt { 332 match evt {
255 Event::Reset => { 333 Event::Reset => {
@@ -288,18 +366,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
288 } 366 }
289 } 367 }
290 368
291 async fn handle_control_out(&mut self, req: Request, stage: DataOutStage) { 369 fn handle_control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
292 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; 370 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
293 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; 371 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
294 372
295 let (data, stage) = match self.control.data_out(self.control_buf, stage).await {
296 Ok(data) => data,
297 Err(_) => {
298 warn!("usb: failed to read CONTROL OUT data stage.");
299 return;
300 }
301 };
302
303 match (req.request_type, req.recipient) { 373 match (req.request_type, req.recipient) {
304 (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { 374 (RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
305 (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { 375 (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
@@ -307,14 +377,14 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
307 if let Some(h) = &self.handler { 377 if let Some(h) = &self.handler {
308 h.remote_wakeup_enabled(false); 378 h.remote_wakeup_enabled(false);
309 } 379 }
310 self.control.accept(stage) 380 OutResponse::Accepted
311 } 381 }
312 (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { 382 (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
313 self.remote_wakeup_enabled = true; 383 self.remote_wakeup_enabled = true;
314 if let Some(h) = &self.handler { 384 if let Some(h) = &self.handler {
315 h.remote_wakeup_enabled(true); 385 h.remote_wakeup_enabled(true);
316 } 386 }
317 self.control.accept(stage) 387 OutResponse::Accepted
318 } 388 }
319 (Request::SET_ADDRESS, addr @ 1..=127) => { 389 (Request::SET_ADDRESS, addr @ 1..=127) => {
320 self.pending_address = addr as u8; 390 self.pending_address = addr as u8;
@@ -323,7 +393,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
323 if let Some(h) = &self.handler { 393 if let Some(h) = &self.handler {
324 h.addressed(self.pending_address); 394 h.addressed(self.pending_address);
325 } 395 }
326 self.control.accept(stage) 396 OutResponse::Accepted
327 } 397 }
328 (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { 398 (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => {
329 debug!("SET_CONFIGURATION: configured"); 399 debug!("SET_CONFIGURATION: configured");
@@ -344,10 +414,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
344 h.configured(true); 414 h.configured(true);
345 } 415 }
346 416
347 self.control.accept(stage) 417 OutResponse::Accepted
348 } 418 }
349 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { 419 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state {
350 UsbDeviceState::Default => self.control.accept(stage), 420 UsbDeviceState::Default => OutResponse::Accepted,
351 _ => { 421 _ => {
352 debug!("SET_CONFIGURATION: unconfigured"); 422 debug!("SET_CONFIGURATION: unconfigured");
353 self.device_state = UsbDeviceState::Addressed; 423 self.device_state = UsbDeviceState::Addressed;
@@ -363,15 +433,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
363 h.configured(false); 433 h.configured(false);
364 } 434 }
365 435
366 self.control.accept(stage) 436 OutResponse::Accepted
367 } 437 }
368 }, 438 },
369 _ => self.control.reject(), 439 _ => OutResponse::Rejected,
370 }, 440 },
371 (RequestType::Standard, Recipient::Interface) => { 441 (RequestType::Standard, Recipient::Interface) => {
372 let iface = match self.interfaces.get_mut(req.index as usize) { 442 let iface = match self.interfaces.get_mut(req.index as usize) {
373 Some(iface) => iface, 443 Some(iface) => iface,
374 None => return self.control.reject(), 444 None => return OutResponse::Rejected,
375 }; 445 };
376 446
377 match req.request { 447 match req.request {
@@ -380,7 +450,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
380 450
381 if new_altsetting >= iface.num_alt_settings { 451 if new_altsetting >= iface.num_alt_settings {
382 warn!("SET_INTERFACE: trying to select alt setting out of range."); 452 warn!("SET_INTERFACE: trying to select alt setting out of range.");
383 return self.control.reject(); 453 return OutResponse::Rejected;
384 } 454 }
385 455
386 iface.current_alt_setting = new_altsetting; 456 iface.current_alt_setting = new_altsetting;
@@ -402,55 +472,39 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
402 if let Some(handler) = &mut iface.handler { 472 if let Some(handler) = &mut iface.handler {
403 handler.set_alternate_setting(new_altsetting); 473 handler.set_alternate_setting(new_altsetting);
404 } 474 }
405 self.control.accept(stage) 475 OutResponse::Accepted
406 } 476 }
407 _ => self.control.reject(), 477 _ => OutResponse::Rejected,
408 } 478 }
409 } 479 }
410 (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { 480 (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) {
411 (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { 481 (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
412 let ep_addr = ((req.index as u8) & 0x8f).into(); 482 let ep_addr = ((req.index as u8) & 0x8f).into();
413 self.bus.endpoint_set_stalled(ep_addr, true); 483 self.bus.endpoint_set_stalled(ep_addr, true);
414 self.control.accept(stage) 484 OutResponse::Accepted
415 } 485 }
416 (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { 486 (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
417 let ep_addr = ((req.index as u8) & 0x8f).into(); 487 let ep_addr = ((req.index as u8) & 0x8f).into();
418 self.bus.endpoint_set_stalled(ep_addr, false); 488 self.bus.endpoint_set_stalled(ep_addr, false);
419 self.control.accept(stage) 489 OutResponse::Accepted
420 } 490 }
421 _ => self.control.reject(), 491 _ => OutResponse::Rejected,
422 }, 492 },
423 (RequestType::Class, Recipient::Interface) => { 493 (RequestType::Class, Recipient::Interface) => {
424 let iface = match self.interfaces.get_mut(req.index as usize) { 494 let iface = match self.interfaces.get_mut(req.index as usize) {
425 Some(iface) => iface, 495 Some(iface) => iface,
426 None => return self.control.reject(), 496 None => return OutResponse::Rejected,
427 }; 497 };
428 match &mut iface.handler { 498 match &mut iface.handler {
429 Some(handler) => match handler.control_out(req, data) { 499 Some(handler) => handler.control_out(req, data),
430 OutResponse::Accepted => self.control.accept(stage), 500 None => OutResponse::Rejected,
431 OutResponse::Rejected => self.control.reject(),
432 },
433 None => self.control.reject(),
434 } 501 }
435 } 502 }
436 _ => self.control.reject(), 503 _ => OutResponse::Rejected,
437 } 504 }
438 } 505 }
439 506
440 async fn handle_control_in(&mut self, req: Request, mut stage: DataInStage) { 507 fn handle_control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
441 // If we don't have an address yet, respond with max 1 packet.
442 // The host doesn't know our EP0 max packet size yet, and might assume
443 // a full-length packet is a short packet, thinking we're done sending data.
444 // See https://github.com/hathach/tinyusb/issues/184
445 const DEVICE_DESCRIPTOR_LEN: u8 = 18;
446 if self.pending_address == 0
447 && self.config.max_packet_size_0 < DEVICE_DESCRIPTOR_LEN
448 && (self.config.max_packet_size_0 as usize) < stage.length
449 {
450 trace!("received control req while not addressed: capping response to 1 packet.");
451 stage.length = self.config.max_packet_size_0 as _;
452 }
453
454 match (req.request_type, req.recipient) { 508 match (req.request_type, req.recipient) {
455 (RequestType::Standard, Recipient::Device) => match req.request { 509 (RequestType::Standard, Recipient::Device) => match req.request {
456 Request::GET_STATUS => { 510 Request::GET_STATUS => {
@@ -461,42 +515,41 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
461 if self.remote_wakeup_enabled { 515 if self.remote_wakeup_enabled {
462 status |= 0x0002; 516 status |= 0x0002;
463 } 517 }
464 self.control.accept_in(&status.to_le_bytes(), stage).await 518 buf[..2].copy_from_slice(&status.to_le_bytes());
519 InResponse::Accepted(&buf[..2])
465 } 520 }
466 Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, stage).await, 521 Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, buf),
467 Request::GET_CONFIGURATION => { 522 Request::GET_CONFIGURATION => {
468 let status = match self.device_state { 523 let status = match self.device_state {
469 UsbDeviceState::Configured => CONFIGURATION_VALUE, 524 UsbDeviceState::Configured => CONFIGURATION_VALUE,
470 _ => CONFIGURATION_NONE, 525 _ => CONFIGURATION_NONE,
471 }; 526 };
472 self.control.accept_in(&status.to_le_bytes(), stage).await 527 buf[0] = status;
528 InResponse::Accepted(&buf[..1])
473 } 529 }
474 _ => self.control.reject(), 530 _ => InResponse::Rejected,
475 }, 531 },
476 (RequestType::Standard, Recipient::Interface) => { 532 (RequestType::Standard, Recipient::Interface) => {
477 let iface = match self.interfaces.get_mut(req.index as usize) { 533 let iface = match self.interfaces.get_mut(req.index as usize) {
478 Some(iface) => iface, 534 Some(iface) => iface,
479 None => return self.control.reject(), 535 None => return InResponse::Rejected,
480 }; 536 };
481 537
482 match req.request { 538 match req.request {
483 Request::GET_STATUS => { 539 Request::GET_STATUS => {
484 let status: u16 = 0; 540 let status: u16 = 0;
485 self.control.accept_in(&status.to_le_bytes(), stage).await 541 buf[..2].copy_from_slice(&status.to_le_bytes());
542 InResponse::Accepted(&buf[..2])
486 } 543 }
487 Request::GET_INTERFACE => { 544 Request::GET_INTERFACE => {
488 self.control 545 buf[0] = iface.current_alt_setting;
489 .accept_in(&[iface.current_alt_setting], stage) 546 InResponse::Accepted(&buf[..1])
490 .await;
491 } 547 }
492 Request::GET_DESCRIPTOR => match &mut iface.handler { 548 Request::GET_DESCRIPTOR => match &mut iface.handler {
493 Some(handler) => match handler.get_descriptor(req, self.control_buf) { 549 Some(handler) => handler.get_descriptor(req, buf),
494 InResponse::Accepted(data) => self.control.accept_in(data, stage).await, 550 None => InResponse::Rejected,
495 InResponse::Rejected => self.control.reject(),
496 },
497 None => self.control.reject(),
498 }, 551 },
499 _ => self.control.reject(), 552 _ => InResponse::Rejected,
500 } 553 }
501 } 554 }
502 (RequestType::Standard, Recipient::Endpoint) => match req.request { 555 (RequestType::Standard, Recipient::Endpoint) => match req.request {
@@ -506,44 +559,40 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
506 if self.bus.endpoint_is_stalled(ep_addr) { 559 if self.bus.endpoint_is_stalled(ep_addr) {
507 status |= 0x0001; 560 status |= 0x0001;
508 } 561 }
509 self.control.accept_in(&status.to_le_bytes(), stage).await 562 buf[..2].copy_from_slice(&status.to_le_bytes());
563 InResponse::Accepted(&buf[..2])
510 } 564 }
511 _ => self.control.reject(), 565 _ => InResponse::Rejected,
512 }, 566 },
513 (RequestType::Class, Recipient::Interface) => { 567 (RequestType::Class, Recipient::Interface) => {
514 let iface = match self.interfaces.get_mut(req.index as usize) { 568 let iface = match self.interfaces.get_mut(req.index as usize) {
515 Some(iface) => iface, 569 Some(iface) => iface,
516 None => return self.control.reject(), 570 None => return InResponse::Rejected,
517 }; 571 };
518 572
519 match &mut iface.handler { 573 match &mut iface.handler {
520 Some(handler) => match handler.control_in(req, self.control_buf) { 574 Some(handler) => handler.control_in(req, buf),
521 InResponse::Accepted(data) => self.control.accept_in(data, stage).await, 575 None => InResponse::Rejected,
522 InResponse::Rejected => self.control.reject(),
523 },
524 None => self.control.reject(),
525 } 576 }
526 } 577 }
527 _ => self.control.reject(), 578 _ => InResponse::Rejected,
528 } 579 }
529 } 580 }
530 581
531 async fn handle_get_descriptor(&mut self, req: Request, stage: DataInStage) { 582 fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
532 let (dtype, index) = req.descriptor_type_index(); 583 let (dtype, index) = req.descriptor_type_index();
533 584
534 match dtype { 585 match dtype {
535 descriptor_type::BOS => self.control.accept_in(self.bos_descriptor, stage).await, 586 descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor),
536 descriptor_type::DEVICE => self.control.accept_in(self.device_descriptor, stage).await, 587 descriptor_type::DEVICE => InResponse::Accepted(self.device_descriptor),
537 descriptor_type::CONFIGURATION => { 588 descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor),
538 self.control.accept_in(self.config_descriptor, stage).await
539 }
540 descriptor_type::STRING => { 589 descriptor_type::STRING => {
541 if index == 0 { 590 if index == 0 {
542 self.control 591 buf[0] = 4; // len
543 .accept_in_writer(req, stage, |w| { 592 buf[1] = descriptor_type::STRING;
544 w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes()); 593 buf[2] = lang_id::ENGLISH_US as u8;
545 }) 594 buf[3] = (lang_id::ENGLISH_US >> 8) as u8;
546 .await 595 InResponse::Accepted(&buf[..4])
547 } else { 596 } else {
548 let s = match index { 597 let s = match index {
549 STRING_INDEX_MANUFACTURER => self.config.manufacturer, 598 STRING_INDEX_MANUFACTURER => self.config.manufacturer,
@@ -565,7 +614,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
565 if let Some(handler) = &mut iface.handler { 614 if let Some(handler) = &mut iface.handler {
566 let index = StringIndex::new(index); 615 let index = StringIndex::new(index);
567 let lang_id = req.index; 616 let lang_id = req.index;
568 handler.get_string(index, lang_id, self.control_buf) 617 handler.get_string(index, lang_id)
569 } else { 618 } else {
570 warn!("String requested to an interface with no handler."); 619 warn!("String requested to an interface with no handler.");
571 None 620 None
@@ -578,15 +627,29 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
578 }; 627 };
579 628
580 if let Some(s) = s { 629 if let Some(s) = s {
581 self.control 630 if buf.len() < 2 {
582 .accept_in_writer(req, stage, |w| w.string(s)) 631 panic!("control buffer too small");
583 .await 632 }
633
634 buf[1] = descriptor_type::STRING;
635 let mut pos = 2;
636 for c in s.encode_utf16() {
637 if pos >= buf.len() {
638 panic!("control buffer too small");
639 }
640
641 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
642 pos += 2;
643 }
644
645 buf[0] = pos as u8;
646 InResponse::Accepted(&buf[..pos])
584 } else { 647 } else {
585 self.control.reject() 648 InResponse::Rejected
586 } 649 }
587 } 650 }
588 } 651 }
589 _ => self.control.reject(), 652 _ => InResponse::Rejected,
590 } 653 }
591 } 654 }
592} 655}