diff options
author | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2022-04-06 03:02:13 +0200 |
---|---|---|
committer | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2022-04-06 05:38:11 +0200 |
commit | f6d11dfba56b2b04868e87a14d10395e1916306d (patch) | |
tree | 74d437fdc17b3e221df52a00029bd247ff77431c /embassy-usb | |
parent | b2e517bb2860b1ec35bb744b8a28efae50cb2d59 (diff) | |
download | embassy-f6d11dfba56b2b04868e87a14d10395e1916306d.zip |
usb: fix slow enumeration with EP0 max_packet_size of 8 or 16.
Diffstat (limited to 'embassy-usb')
-rw-r--r-- | embassy-usb/src/control.rs | 2 | ||||
-rw-r--r-- | embassy-usb/src/lib.rs | 15 |
2 files changed, 15 insertions, 2 deletions
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs index da48dcca..b15ba446 100644 --- a/embassy-usb/src/control.rs +++ b/embassy-usb/src/control.rs @@ -198,7 +198,7 @@ pub trait ControlHandler { #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct DataInStage { - length: usize, + pub(crate) length: usize, } /// Typestate representing a ControlPipe in the DATA OUT stage diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index cf8d1253..f833a86d 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs @@ -222,7 +222,20 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { } } - async fn handle_control_in(&mut self, req: Request, stage: DataInStage) { + async fn handle_control_in(&mut self, req: Request, mut stage: DataInStage) { + // If we don't have an address yet, respond with max 1 packet. + // The host doesn't know our EP0 max packet size yet, and might assume + // a full-length packet is a short packet, thinking we're done sending data. + // See https://github.com/hathach/tinyusb/issues/184 + const DEVICE_DESCRIPTOR_LEN: u8 = 18; + if self.pending_address == 0 + && self.config.max_packet_size_0 < DEVICE_DESCRIPTOR_LEN + && (self.config.max_packet_size_0 as usize) < stage.length + { + trace!("received control req while not addressed: capping response to 1 packet."); + stage.length = self.config.max_packet_size_0 as _; + } + match (req.request_type, req.recipient) { (RequestType::Standard, Recipient::Device) => match req.request { Request::GET_STATUS => { |