aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src/lib.rs
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2022-03-29 20:26:30 -0400
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commit77e0aca03b89ebc5f1e93b6c64b6c91ca10cedd1 (patch)
treeb0b5982f3daddafa7bc36362adcddeae11b07023 /embassy-usb/src/lib.rs
parent1672fdc666188454a56b9369150e54420dc67078 (diff)
Move data chunking from the driver to the lib
Diffstat (limited to 'embassy-usb/src/lib.rs')
-rw-r--r--embassy-usb/src/lib.rs115
1 files changed, 92 insertions, 23 deletions
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 32b67a766..77a9c33be 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -55,7 +55,7 @@ pub const MAX_INTERFACE_COUNT: usize = 4;
55 55
56pub struct UsbDevice<'d, D: Driver<'d>> { 56pub struct UsbDevice<'d, D: Driver<'d>> {
57 bus: D::Bus, 57 bus: D::Bus,
58 control: D::ControlPipe, 58 control: ControlPipe<D::ControlPipe>,
59 59
60 config: Config<'d>, 60 config: Config<'d>,
61 device_descriptor: &'d [u8], 61 device_descriptor: &'d [u8],
@@ -92,7 +92,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
92 Self { 92 Self {
93 bus: driver, 93 bus: driver,
94 config, 94 config,
95 control, 95 control: ControlPipe {
96 control,
97 request: None,
98 },
96 device_descriptor, 99 device_descriptor,
97 config_descriptor, 100 config_descriptor,
98 bos_descriptor, 101 bos_descriptor,
@@ -140,32 +143,19 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
140 } 143 }
141 } 144 }
142 145
143 async fn control_in_accept_writer(
144 &mut self,
145 req: Request,
146 f: impl FnOnce(&mut DescriptorWriter),
147 ) {
148 let mut buf = [0; 256];
149 let mut w = DescriptorWriter::new(&mut buf);
150 f(&mut w);
151 let pos = w.position().min(usize::from(req.length));
152 self.control.accept_in(&buf[..pos]).await;
153 }
154
155 async fn handle_control_out(&mut self, req: Request) { 146 async fn handle_control_out(&mut self, req: Request) {
156 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; 147 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
157 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; 148 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
158 149
159 // If the request has a data state, we must read it. 150 // If the request has a data state, we must read it.
160 let data = if req.length > 0 { 151 let data = if req.length > 0 {
161 let size = match self.control.data_out(self.control_buf).await { 152 match self.control.data_out(self.control_buf).await {
162 Ok(size) => size, 153 Ok(data) => data,
163 Err(_) => { 154 Err(_) => {
164 warn!("usb: failed to read CONTROL OUT data stage."); 155 warn!("usb: failed to read CONTROL OUT data stage.");
165 return; 156 return;
166 } 157 }
167 }; 158 }
168 &self.control_buf[0..size]
169 } else { 159 } else {
170 &[] 160 &[]
171 }; 161 };
@@ -315,10 +305,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
315 descriptor_type::CONFIGURATION => self.control.accept_in(self.config_descriptor).await, 305 descriptor_type::CONFIGURATION => self.control.accept_in(self.config_descriptor).await,
316 descriptor_type::STRING => { 306 descriptor_type::STRING => {
317 if index == 0 { 307 if index == 0 {
318 self.control_in_accept_writer(req, |w| { 308 self.control
319 w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes()) 309 .accept_in_writer(req, |w| {
320 }) 310 w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes());
321 .await 311 })
312 .await
322 } else { 313 } else {
323 let s = match index { 314 let s = match index {
324 1 => self.config.manufacturer, 315 1 => self.config.manufacturer,
@@ -333,7 +324,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
333 }; 324 };
334 325
335 if let Some(s) = s { 326 if let Some(s) = s {
336 self.control_in_accept_writer(req, |w| w.string(s)).await; 327 self.control.accept_in_writer(req, |w| w.string(s)).await;
337 } else { 328 } else {
338 self.control.reject() 329 self.control.reject()
339 } 330 }
@@ -343,3 +334,81 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
343 } 334 }
344 } 335 }
345} 336}
337
338struct ControlPipe<C: driver::ControlPipe> {
339 control: C,
340 request: Option<Request>,
341}
342
343impl<C: driver::ControlPipe> ControlPipe<C> {
344 async fn setup(&mut self) -> Request {
345 assert!(self.request.is_none());
346 let req = self.control.setup().await;
347 self.request = Some(req);
348 req
349 }
350
351 async fn data_out<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], ReadError> {
352 let req = self.request.unwrap();
353 assert_eq!(req.direction, UsbDirection::Out);
354 assert!(req.length > 0);
355 let req_length = usize::from(req.length);
356
357 let max_packet_size = self.control.max_packet_size();
358 let mut total = 0;
359
360 for chunk in buf.chunks_mut(max_packet_size) {
361 let size = self.control.data_out(chunk).await?;
362 total += size;
363 if size < max_packet_size || total == req_length {
364 break;
365 }
366 }
367
368 Ok(&buf[0..total])
369 }
370
371 async fn accept_in(&mut self, buf: &[u8]) -> () {
372 #[cfg(feature = "defmt")]
373 debug!("control in accept {:x}", buf);
374 #[cfg(not(feature = "defmt"))]
375 debug!("control in accept {:x?}", buf);
376 let req = unwrap!(self.request);
377 assert!(req.direction == UsbDirection::In);
378
379 let req_len = usize::from(req.length);
380 let len = buf.len().min(req_len);
381 let max_packet_size = self.control.max_packet_size();
382 let need_zlp = len != req_len && (len % usize::from(max_packet_size)) == 0;
383
384 let mut chunks = buf[0..len]
385 .chunks(max_packet_size)
386 .chain(need_zlp.then(|| -> &[u8] { &[] }));
387
388 while let Some(chunk) = chunks.next() {
389 self.control.data_in(chunk, chunks.size_hint().0 == 0).await;
390 }
391
392 self.request = None;
393 }
394
395 async fn accept_in_writer(&mut self, req: Request, f: impl FnOnce(&mut DescriptorWriter)) {
396 let mut buf = [0; 256];
397 let mut w = DescriptorWriter::new(&mut buf);
398 f(&mut w);
399 let pos = w.position().min(usize::from(req.length));
400 self.accept_in(&buf[..pos]).await;
401 }
402
403 fn accept(&mut self) {
404 assert!(self.request.is_some());
405 self.control.accept();
406 self.request = None;
407 }
408
409 fn reject(&mut self) {
410 assert!(self.request.is_some());
411 self.control.reject();
412 self.request = None;
413 }
414}