From b801592dc31b6ad3839fb2d84bb8893702a3d84f Mon Sep 17 00:00:00 2001 From: Matt Johnston <matt@ucc.asn.au> Date: Wed, 24 May 2023 00:21:46 +0800 Subject: [PATCH] Implement BufRead for CDCRead, fix Write impl --- embassy/demos/picow/src/usbserial.rs | 73 ++++++++++++++++++---------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/embassy/demos/picow/src/usbserial.rs b/embassy/demos/picow/src/usbserial.rs index 4bd7f73..272f582 100644 --- a/embassy/demos/picow/src/usbserial.rs +++ b/embassy/demos/picow/src/usbserial.rs @@ -12,7 +12,8 @@ use embassy_usb::class::cdc_acm::{self, CdcAcmClass, State}; use embassy_usb::Builder; use embassy_usb_driver::Driver; -use embedded_io::{asynch, Io}; +use embedded_io::{asynch, Io, asynch::BufRead}; + use heapless::Vec; use sunset::*; @@ -112,40 +113,58 @@ impl<'a, D: Driver<'a>> asynch::Read for CDCRead<'a, '_, D> { async fn read(&mut self, ret: &mut [u8]) -> sunset::Result<usize> { debug_assert!(self.start < self.end || self.end == 0); - // return existing content first - if self.end > 0 { - let l = ret.len().min(self.end - self.start); - ret.copy_from_slice(&self.buf[self.start..self.start + l]); - self.start += l; - if self.start == self.end { - self.start = 0; - self.end = 0; - } - return Ok(l); + if self.end == 0 && ret.len() > self.buf.len() { + // perform an unbuffered read if possible, saves a copy + let n = self + .cdc + .read_packet(ret) + .await + .map_err(|_| sunset::Error::ChannelEOF)?; + info!("direct read_packet {:?}", &ret[..n]); + return Ok(n) } - debug_assert!(self.start == 0); - debug_assert!(self.end == 0); - - let (r, buffered) = if ret.len() >= self.buf.len() { - // read in-place - (self.cdc.read_packet(ret).await, false) - } else { - // ret is too small, use buffer - (self.cdc.read_packet(self.buf.as_mut()).await, true) - }; + let b = self.fill_buf().await?; + let n = ret.len().min(b.len()); + info!("buf read {:?}, rl {} bl {}", &b[..n], ret.len(), b.len()); + (&mut ret[..n]).copy_from_slice(&b[..n]); + self.consume(n); + return Ok(n) + } +} +impl<'a, D: Driver<'a>> asynch::BufRead for CDCRead<'a, '_, D> { + async fn fill_buf(&mut self) -> sunset::Result<&[u8]> { + debug_assert!(self.start < self.end || self.end == 0); - let n = r.map_err(|_| sunset::Error::ChannelEOF)?; + if self.end == 0 { + debug_assert!(self.start == 0); + let n = self + .cdc + .read_packet(self.buf.as_mut()) + .await + .map_err(|_| sunset::Error::ChannelEOF)?; + info!("buf read_packet {:?}", &self.buf[..n]); - if n == 0 { - return Err(sunset::Error::ChannelEOF); + self.end = n; } + debug_assert!(self.end > 0); + info!("fill {}..{}", self.start, self.end); + + return Ok(&self.buf[self.start..self.end]); + } + + fn consume(&mut self, amt: usize) { + debug_assert!(self.start < self.end || self.end == 0); + + debug_assert!(amt <= (self.end - self.start)); - if buffered { - ret.copy_from_slice(&self.buf[..n]); + self.start += amt; + if self.start >= self.end { + self.start = 0; + self.end = 0; } - Ok(n) + info!("consumed {}, {}..{}", amt, self.start, self.end); } } -- GitLab