aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src/control.rs
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/control.rs
parent1ca5475010a1cae6ebc55a27948ca4320decd5cd (diff)
parent30d4d0e9d78681e16a68ff953c61b96c9863bfc6 (diff)
Merge branch 'embassy-rs:master' into qdec
Diffstat (limited to 'embassy-usb/src/control.rs')
-rw-r--r--embassy-usb/src/control.rs150
1 files changed, 2 insertions, 148 deletions
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}