diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-05-09 02:11:02 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-05-09 02:11:02 +0200 |
| commit | 7ed462a6575cba95e8f07d2d9516d5e7b33d7196 (patch) | |
| tree | ae0e68faea70a907bfb4488876ee179068f38f64 /embassy-usb | |
| parent | 2e104170de36295243608fbbebebdc6f52e8f8d0 (diff) | |
usb: simplify control in/out handlng, calling response from a single place.
Diffstat (limited to 'embassy-usb')
| -rw-r--r-- | embassy-usb/src/control.rs | 29 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor.rs | 1 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 270 |
3 files changed, 152 insertions, 148 deletions
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs index ff42f9d78..4fc65b6a5 100644 --- a/embassy-usb/src/control.rs +++ b/embassy-usb/src/control.rs | |||
| @@ -1,9 +1,7 @@ | |||
| 1 | use core::mem; | 1 | use core::mem; |
| 2 | 2 | ||
| 3 | use crate::descriptor::DescriptorWriter; | ||
| 4 | use crate::driver::{self, EndpointError}; | ||
| 5 | |||
| 6 | use super::types::*; | 3 | use super::types::*; |
| 4 | use crate::driver::{self, EndpointError}; | ||
| 7 | 5 | ||
| 8 | /// Control request type. | 6 | /// Control request type. |
| 9 | #[repr(u8)] | 7 | #[repr(u8)] |
| @@ -191,16 +189,8 @@ pub trait ControlHandler { | |||
| 191 | } | 189 | } |
| 192 | 190 | ||
| 193 | /// Called when a GET_DESCRIPTOR STRING control request is received. | 191 | /// Called when a GET_DESCRIPTOR STRING control request is received. |
| 194 | /// | 192 | 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 | 193 | 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 | 194 | None |
| 205 | } | 195 | } |
| 206 | } | 196 | } |
| @@ -316,19 +306,6 @@ impl<C: driver::ControlPipe> ControlPipe<C> { | |||
| 316 | } | 306 | } |
| 317 | } | 307 | } |
| 318 | 308 | ||
| 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) { | 309 | pub(crate) fn accept(&mut self, _: StatusStage) { |
| 333 | trace!(" control accept"); | 310 | trace!(" control accept"); |
| 334 | self.control.accept(); | 311 | self.control.accept(); |
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/lib.rs b/embassy-usb/src/lib.rs index 3bfedc048..690305885 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -100,15 +100,19 @@ struct Interface<'d> { | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | pub struct UsbDevice<'d, D: Driver<'d>> { | 102 | pub struct UsbDevice<'d, D: Driver<'d>> { |
| 103 | control_buf: &'d mut [u8], | ||
| 104 | control: ControlPipe<D::ControlPipe>, | ||
| 105 | inner: Inner<'d, D>, | ||
| 106 | } | ||
| 107 | |||
| 108 | struct Inner<'d, D: Driver<'d>> { | ||
| 103 | bus: D::Bus, | 109 | bus: D::Bus, |
| 104 | handler: Option<&'d dyn DeviceStateHandler>, | 110 | handler: Option<&'d dyn DeviceStateHandler>, |
| 105 | control: ControlPipe<D::ControlPipe>, | ||
| 106 | 111 | ||
| 107 | config: Config<'d>, | 112 | config: Config<'d>, |
| 108 | device_descriptor: &'d [u8], | 113 | device_descriptor: &'d [u8], |
| 109 | config_descriptor: &'d [u8], | 114 | config_descriptor: &'d [u8], |
| 110 | bos_descriptor: &'d [u8], | 115 | bos_descriptor: &'d [u8], |
| 111 | control_buf: &'d mut [u8], | ||
| 112 | 116 | ||
| 113 | device_state: UsbDeviceState, | 117 | device_state: UsbDeviceState, |
| 114 | suspended: bool, | 118 | suspended: bool, |
| @@ -139,20 +143,23 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 139 | let bus = driver.into_bus(); | 143 | let bus = driver.into_bus(); |
| 140 | 144 | ||
| 141 | Self { | 145 | Self { |
| 142 | bus, | ||
| 143 | config, | ||
| 144 | handler, | ||
| 145 | control: ControlPipe::new(control), | ||
| 146 | device_descriptor, | ||
| 147 | config_descriptor, | ||
| 148 | bos_descriptor, | ||
| 149 | control_buf, | 146 | control_buf, |
| 150 | device_state: UsbDeviceState::Disabled, | 147 | control: ControlPipe::new(control), |
| 151 | suspended: false, | 148 | inner: Inner { |
| 152 | remote_wakeup_enabled: false, | 149 | bus, |
| 153 | self_powered: false, | 150 | config, |
| 154 | pending_address: 0, | 151 | handler, |
| 155 | interfaces, | 152 | device_descriptor, |
| 153 | config_descriptor, | ||
| 154 | bos_descriptor, | ||
| 155 | |||
| 156 | device_state: UsbDeviceState::Disabled, | ||
| 157 | suspended: false, | ||
| 158 | remote_wakeup_enabled: false, | ||
| 159 | self_powered: false, | ||
| 160 | pending_address: 0, | ||
| 161 | interfaces, | ||
| 162 | }, | ||
| 156 | } | 163 | } |
| 157 | } | 164 | } |
| 158 | 165 | ||
| @@ -176,28 +183,60 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 176 | /// before calling any other `UsbDevice` methods to fully reset the | 183 | /// before calling any other `UsbDevice` methods to fully reset the |
| 177 | /// peripheral. | 184 | /// peripheral. |
| 178 | pub async fn run_until_suspend(&mut self) -> () { | 185 | pub async fn run_until_suspend(&mut self) -> () { |
| 179 | if self.device_state == UsbDeviceState::Disabled { | 186 | if self.inner.device_state == UsbDeviceState::Disabled { |
| 180 | self.bus.enable().await; | 187 | self.inner.bus.enable().await; |
| 181 | self.device_state = UsbDeviceState::Default; | 188 | self.inner.device_state = UsbDeviceState::Default; |
| 182 | 189 | ||
| 183 | if let Some(h) = &self.handler { | 190 | if let Some(h) = &self.inner.handler { |
| 184 | h.enabled(true); | 191 | h.enabled(true); |
| 185 | } | 192 | } |
| 186 | } | 193 | } |
| 187 | 194 | ||
| 188 | loop { | 195 | loop { |
| 189 | let control_fut = self.control.setup(); | 196 | let control_fut = self.control.setup(); |
| 190 | let bus_fut = self.bus.poll(); | 197 | let bus_fut = self.inner.bus.poll(); |
| 191 | match select(bus_fut, control_fut).await { | 198 | match select(bus_fut, control_fut).await { |
| 192 | Either::First(evt) => { | 199 | Either::First(evt) => { |
| 193 | self.handle_bus_event(evt); | 200 | self.inner.handle_bus_event(evt); |
| 194 | if self.suspended { | 201 | if self.inner.suspended { |
| 195 | return; | 202 | return; |
| 196 | } | 203 | } |
| 197 | } | 204 | } |
| 198 | Either::Second(req) => match req { | 205 | Either::Second(req) => match req { |
| 199 | Setup::DataIn(req, stage) => self.handle_control_in(req, stage).await, | 206 | Setup::DataIn(req, mut stage) => { |
| 200 | Setup::DataOut(req, stage) => self.handle_control_out(req, stage).await, | 207 | // If we don't have an address yet, respond with max 1 packet. |
| 208 | // The host doesn't know our EP0 max packet size yet, and might assume | ||
| 209 | // a full-length packet is a short packet, thinking we're done sending data. | ||
| 210 | // See https://github.com/hathach/tinyusb/issues/184 | ||
| 211 | const DEVICE_DESCRIPTOR_LEN: u8 = 18; | ||
| 212 | if self.inner.pending_address == 0 | ||
| 213 | && self.inner.config.max_packet_size_0 < DEVICE_DESCRIPTOR_LEN | ||
| 214 | && (self.inner.config.max_packet_size_0 as usize) < stage.length | ||
| 215 | { | ||
| 216 | trace!("received control req while not addressed: capping response to 1 packet."); | ||
| 217 | stage.length = self.inner.config.max_packet_size_0 as _; | ||
| 218 | } | ||
| 219 | |||
| 220 | match self.inner.handle_control_in(req, &mut self.control_buf) { | ||
| 221 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | ||
| 222 | InResponse::Rejected => self.control.reject(), | ||
| 223 | } | ||
| 224 | } | ||
| 225 | Setup::DataOut(req, stage) => { | ||
| 226 | let (data, stage) = | ||
| 227 | match self.control.data_out(self.control_buf, stage).await { | ||
| 228 | Ok(data) => data, | ||
| 229 | Err(_) => { | ||
| 230 | warn!("usb: failed to read CONTROL OUT data stage."); | ||
| 231 | return; | ||
| 232 | } | ||
| 233 | }; | ||
| 234 | |||
| 235 | match self.inner.handle_control_out(req, data) { | ||
| 236 | OutResponse::Accepted => self.control.accept(stage), | ||
| 237 | OutResponse::Rejected => self.control.reject(), | ||
| 238 | } | ||
| 239 | } | ||
| 201 | }, | 240 | }, |
| 202 | } | 241 | } |
| 203 | } | 242 | } |
| @@ -205,13 +244,13 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 205 | 244 | ||
| 206 | /// Disables the USB peripheral. | 245 | /// Disables the USB peripheral. |
| 207 | pub async fn disable(&mut self) { | 246 | pub async fn disable(&mut self) { |
| 208 | if self.device_state != UsbDeviceState::Disabled { | 247 | if self.inner.device_state != UsbDeviceState::Disabled { |
| 209 | self.bus.disable().await; | 248 | self.inner.bus.disable().await; |
| 210 | self.device_state = UsbDeviceState::Disabled; | 249 | self.inner.device_state = UsbDeviceState::Disabled; |
| 211 | self.suspended = false; | 250 | self.inner.suspended = false; |
| 212 | self.remote_wakeup_enabled = false; | 251 | self.inner.remote_wakeup_enabled = false; |
| 213 | 252 | ||
| 214 | if let Some(h) = &self.handler { | 253 | if let Some(h) = &self.inner.handler { |
| 215 | h.enabled(false); | 254 | h.enabled(false); |
| 216 | } | 255 | } |
| 217 | } | 256 | } |
| @@ -221,9 +260,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 221 | /// | 260 | /// |
| 222 | /// This future is cancel-safe. | 261 | /// This future is cancel-safe. |
| 223 | pub async fn wait_resume(&mut self) { | 262 | pub async fn wait_resume(&mut self) { |
| 224 | while self.suspended { | 263 | while self.inner.suspended { |
| 225 | let evt = self.bus.poll().await; | 264 | let evt = self.inner.bus.poll().await; |
| 226 | self.handle_bus_event(evt); | 265 | self.inner.handle_bus_event(evt); |
| 227 | } | 266 | } |
| 228 | } | 267 | } |
| 229 | 268 | ||
| @@ -236,11 +275,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 236 | /// After dropping the future, [`UsbDevice::disable()`] should be called | 275 | /// After dropping the future, [`UsbDevice::disable()`] should be called |
| 237 | /// before calling any other `UsbDevice` methods to fully reset the peripheral. | 276 | /// before calling any other `UsbDevice` methods to fully reset the peripheral. |
| 238 | pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { | 277 | pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { |
| 239 | if self.suspended && self.remote_wakeup_enabled { | 278 | if self.inner.suspended && self.inner.remote_wakeup_enabled { |
| 240 | self.bus.remote_wakeup().await?; | 279 | self.inner.bus.remote_wakeup().await?; |
| 241 | self.suspended = false; | 280 | self.inner.suspended = false; |
| 242 | 281 | ||
| 243 | if let Some(h) = &self.handler { | 282 | if let Some(h) = &self.inner.handler { |
| 244 | h.suspended(false); | 283 | h.suspended(false); |
| 245 | } | 284 | } |
| 246 | 285 | ||
| @@ -249,7 +288,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 249 | Err(RemoteWakeupError::InvalidState) | 288 | Err(RemoteWakeupError::InvalidState) |
| 250 | } | 289 | } |
| 251 | } | 290 | } |
| 291 | } | ||
| 252 | 292 | ||
| 293 | impl<'d, D: Driver<'d>> Inner<'d, D> { | ||
| 253 | fn handle_bus_event(&mut self, evt: Event) { | 294 | fn handle_bus_event(&mut self, evt: Event) { |
| 254 | match evt { | 295 | match evt { |
| 255 | Event::Reset => { | 296 | Event::Reset => { |
| @@ -288,18 +329,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 288 | } | 329 | } |
| 289 | } | 330 | } |
| 290 | 331 | ||
| 291 | async fn handle_control_out(&mut self, req: Request, stage: DataOutStage) { | 332 | fn handle_control_out(&mut self, req: Request, data: &[u8]) -> OutResponse { |
| 292 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; | 333 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; |
| 293 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; | 334 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; |
| 294 | 335 | ||
| 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) { | 336 | match (req.request_type, req.recipient) { |
| 304 | (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { | 337 | (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { |
| 305 | (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { | 338 | (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { |
| @@ -307,14 +340,14 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 307 | if let Some(h) = &self.handler { | 340 | if let Some(h) = &self.handler { |
| 308 | h.remote_wakeup_enabled(false); | 341 | h.remote_wakeup_enabled(false); |
| 309 | } | 342 | } |
| 310 | self.control.accept(stage) | 343 | OutResponse::Accepted |
| 311 | } | 344 | } |
| 312 | (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { | 345 | (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { |
| 313 | self.remote_wakeup_enabled = true; | 346 | self.remote_wakeup_enabled = true; |
| 314 | if let Some(h) = &self.handler { | 347 | if let Some(h) = &self.handler { |
| 315 | h.remote_wakeup_enabled(true); | 348 | h.remote_wakeup_enabled(true); |
| 316 | } | 349 | } |
| 317 | self.control.accept(stage) | 350 | OutResponse::Accepted |
| 318 | } | 351 | } |
| 319 | (Request::SET_ADDRESS, addr @ 1..=127) => { | 352 | (Request::SET_ADDRESS, addr @ 1..=127) => { |
| 320 | self.pending_address = addr as u8; | 353 | self.pending_address = addr as u8; |
| @@ -323,7 +356,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 323 | if let Some(h) = &self.handler { | 356 | if let Some(h) = &self.handler { |
| 324 | h.addressed(self.pending_address); | 357 | h.addressed(self.pending_address); |
| 325 | } | 358 | } |
| 326 | self.control.accept(stage) | 359 | OutResponse::Accepted |
| 327 | } | 360 | } |
| 328 | (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { | 361 | (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { |
| 329 | debug!("SET_CONFIGURATION: configured"); | 362 | debug!("SET_CONFIGURATION: configured"); |
| @@ -344,10 +377,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 344 | h.configured(true); | 377 | h.configured(true); |
| 345 | } | 378 | } |
| 346 | 379 | ||
| 347 | self.control.accept(stage) | 380 | OutResponse::Accepted |
| 348 | } | 381 | } |
| 349 | (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { | 382 | (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { |
| 350 | UsbDeviceState::Default => self.control.accept(stage), | 383 | UsbDeviceState::Default => OutResponse::Accepted, |
| 351 | _ => { | 384 | _ => { |
| 352 | debug!("SET_CONFIGURATION: unconfigured"); | 385 | debug!("SET_CONFIGURATION: unconfigured"); |
| 353 | self.device_state = UsbDeviceState::Addressed; | 386 | self.device_state = UsbDeviceState::Addressed; |
| @@ -363,15 +396,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 363 | h.configured(false); | 396 | h.configured(false); |
| 364 | } | 397 | } |
| 365 | 398 | ||
| 366 | self.control.accept(stage) | 399 | OutResponse::Accepted |
| 367 | } | 400 | } |
| 368 | }, | 401 | }, |
| 369 | _ => self.control.reject(), | 402 | _ => OutResponse::Rejected, |
| 370 | }, | 403 | }, |
| 371 | (RequestType::Standard, Recipient::Interface) => { | 404 | (RequestType::Standard, Recipient::Interface) => { |
| 372 | let iface = match self.interfaces.get_mut(req.index as usize) { | 405 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 373 | Some(iface) => iface, | 406 | Some(iface) => iface, |
| 374 | None => return self.control.reject(), | 407 | None => return OutResponse::Rejected, |
| 375 | }; | 408 | }; |
| 376 | 409 | ||
| 377 | match req.request { | 410 | match req.request { |
| @@ -380,7 +413,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 380 | 413 | ||
| 381 | if new_altsetting >= iface.num_alt_settings { | 414 | if new_altsetting >= iface.num_alt_settings { |
| 382 | warn!("SET_INTERFACE: trying to select alt setting out of range."); | 415 | warn!("SET_INTERFACE: trying to select alt setting out of range."); |
| 383 | return self.control.reject(); | 416 | return OutResponse::Rejected; |
| 384 | } | 417 | } |
| 385 | 418 | ||
| 386 | iface.current_alt_setting = new_altsetting; | 419 | iface.current_alt_setting = new_altsetting; |
| @@ -402,55 +435,39 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 402 | if let Some(handler) = &mut iface.handler { | 435 | if let Some(handler) = &mut iface.handler { |
| 403 | handler.set_alternate_setting(new_altsetting); | 436 | handler.set_alternate_setting(new_altsetting); |
| 404 | } | 437 | } |
| 405 | self.control.accept(stage) | 438 | OutResponse::Accepted |
| 406 | } | 439 | } |
| 407 | _ => self.control.reject(), | 440 | _ => OutResponse::Rejected, |
| 408 | } | 441 | } |
| 409 | } | 442 | } |
| 410 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { | 443 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { |
| 411 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 444 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 412 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 445 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| 413 | self.bus.endpoint_set_stalled(ep_addr, true); | 446 | self.bus.endpoint_set_stalled(ep_addr, true); |
| 414 | self.control.accept(stage) | 447 | OutResponse::Accepted |
| 415 | } | 448 | } |
| 416 | (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 449 | (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 417 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 450 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| 418 | self.bus.endpoint_set_stalled(ep_addr, false); | 451 | self.bus.endpoint_set_stalled(ep_addr, false); |
| 419 | self.control.accept(stage) | 452 | OutResponse::Accepted |
| 420 | } | 453 | } |
| 421 | _ => self.control.reject(), | 454 | _ => OutResponse::Rejected, |
| 422 | }, | 455 | }, |
| 423 | (RequestType::Class, Recipient::Interface) => { | 456 | (RequestType::Class, Recipient::Interface) => { |
| 424 | let iface = match self.interfaces.get_mut(req.index as usize) { | 457 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 425 | Some(iface) => iface, | 458 | Some(iface) => iface, |
| 426 | None => return self.control.reject(), | 459 | None => return OutResponse::Rejected, |
| 427 | }; | 460 | }; |
| 428 | match &mut iface.handler { | 461 | match &mut iface.handler { |
| 429 | Some(handler) => match handler.control_out(req, data) { | 462 | Some(handler) => handler.control_out(req, data), |
| 430 | OutResponse::Accepted => self.control.accept(stage), | 463 | None => OutResponse::Rejected, |
| 431 | OutResponse::Rejected => self.control.reject(), | ||
| 432 | }, | ||
| 433 | None => self.control.reject(), | ||
| 434 | } | 464 | } |
| 435 | } | 465 | } |
| 436 | _ => self.control.reject(), | 466 | _ => OutResponse::Rejected, |
| 437 | } | 467 | } |
| 438 | } | 468 | } |
| 439 | 469 | ||
| 440 | async fn handle_control_in(&mut self, req: Request, mut stage: DataInStage) { | 470 | 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) { | 471 | match (req.request_type, req.recipient) { |
| 455 | (RequestType::Standard, Recipient::Device) => match req.request { | 472 | (RequestType::Standard, Recipient::Device) => match req.request { |
| 456 | Request::GET_STATUS => { | 473 | Request::GET_STATUS => { |
| @@ -461,42 +478,41 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 461 | if self.remote_wakeup_enabled { | 478 | if self.remote_wakeup_enabled { |
| 462 | status |= 0x0002; | 479 | status |= 0x0002; |
| 463 | } | 480 | } |
| 464 | self.control.accept_in(&status.to_le_bytes(), stage).await | 481 | buf[..2].copy_from_slice(&status.to_le_bytes()); |
| 482 | InResponse::Accepted(&buf[..2]) | ||
| 465 | } | 483 | } |
| 466 | Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, stage).await, | 484 | Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, buf), |
| 467 | Request::GET_CONFIGURATION => { | 485 | Request::GET_CONFIGURATION => { |
| 468 | let status = match self.device_state { | 486 | let status = match self.device_state { |
| 469 | UsbDeviceState::Configured => CONFIGURATION_VALUE, | 487 | UsbDeviceState::Configured => CONFIGURATION_VALUE, |
| 470 | _ => CONFIGURATION_NONE, | 488 | _ => CONFIGURATION_NONE, |
| 471 | }; | 489 | }; |
| 472 | self.control.accept_in(&status.to_le_bytes(), stage).await | 490 | buf[0] = status; |
| 491 | InResponse::Accepted(&buf[..1]) | ||
| 473 | } | 492 | } |
| 474 | _ => self.control.reject(), | 493 | _ => InResponse::Rejected, |
| 475 | }, | 494 | }, |
| 476 | (RequestType::Standard, Recipient::Interface) => { | 495 | (RequestType::Standard, Recipient::Interface) => { |
| 477 | let iface = match self.interfaces.get_mut(req.index as usize) { | 496 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 478 | Some(iface) => iface, | 497 | Some(iface) => iface, |
| 479 | None => return self.control.reject(), | 498 | None => return InResponse::Rejected, |
| 480 | }; | 499 | }; |
| 481 | 500 | ||
| 482 | match req.request { | 501 | match req.request { |
| 483 | Request::GET_STATUS => { | 502 | Request::GET_STATUS => { |
| 484 | let status: u16 = 0; | 503 | let status: u16 = 0; |
| 485 | self.control.accept_in(&status.to_le_bytes(), stage).await | 504 | buf[..2].copy_from_slice(&status.to_le_bytes()); |
| 505 | InResponse::Accepted(&buf[..2]) | ||
| 486 | } | 506 | } |
| 487 | Request::GET_INTERFACE => { | 507 | Request::GET_INTERFACE => { |
| 488 | self.control | 508 | buf[0] = iface.current_alt_setting; |
| 489 | .accept_in(&[iface.current_alt_setting], stage) | 509 | InResponse::Accepted(&buf[..1]) |
| 490 | .await; | ||
| 491 | } | 510 | } |
| 492 | Request::GET_DESCRIPTOR => match &mut iface.handler { | 511 | Request::GET_DESCRIPTOR => match &mut iface.handler { |
| 493 | Some(handler) => match handler.get_descriptor(req, self.control_buf) { | 512 | Some(handler) => handler.get_descriptor(req, buf), |
| 494 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | 513 | None => InResponse::Rejected, |
| 495 | InResponse::Rejected => self.control.reject(), | ||
| 496 | }, | ||
| 497 | None => self.control.reject(), | ||
| 498 | }, | 514 | }, |
| 499 | _ => self.control.reject(), | 515 | _ => InResponse::Rejected, |
| 500 | } | 516 | } |
| 501 | } | 517 | } |
| 502 | (RequestType::Standard, Recipient::Endpoint) => match req.request { | 518 | (RequestType::Standard, Recipient::Endpoint) => match req.request { |
| @@ -506,44 +522,40 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 506 | if self.bus.endpoint_is_stalled(ep_addr) { | 522 | if self.bus.endpoint_is_stalled(ep_addr) { |
| 507 | status |= 0x0001; | 523 | status |= 0x0001; |
| 508 | } | 524 | } |
| 509 | self.control.accept_in(&status.to_le_bytes(), stage).await | 525 | buf[..2].copy_from_slice(&status.to_le_bytes()); |
| 526 | InResponse::Accepted(&buf[..2]) | ||
| 510 | } | 527 | } |
| 511 | _ => self.control.reject(), | 528 | _ => InResponse::Rejected, |
| 512 | }, | 529 | }, |
| 513 | (RequestType::Class, Recipient::Interface) => { | 530 | (RequestType::Class, Recipient::Interface) => { |
| 514 | let iface = match self.interfaces.get_mut(req.index as usize) { | 531 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 515 | Some(iface) => iface, | 532 | Some(iface) => iface, |
| 516 | None => return self.control.reject(), | 533 | None => return InResponse::Rejected, |
| 517 | }; | 534 | }; |
| 518 | 535 | ||
| 519 | match &mut iface.handler { | 536 | match &mut iface.handler { |
| 520 | Some(handler) => match handler.control_in(req, self.control_buf) { | 537 | Some(handler) => handler.control_in(req, buf), |
| 521 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | 538 | None => InResponse::Rejected, |
| 522 | InResponse::Rejected => self.control.reject(), | ||
| 523 | }, | ||
| 524 | None => self.control.reject(), | ||
| 525 | } | 539 | } |
| 526 | } | 540 | } |
| 527 | _ => self.control.reject(), | 541 | _ => InResponse::Rejected, |
| 528 | } | 542 | } |
| 529 | } | 543 | } |
| 530 | 544 | ||
| 531 | async fn handle_get_descriptor(&mut self, req: Request, stage: DataInStage) { | 545 | fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { |
| 532 | let (dtype, index) = req.descriptor_type_index(); | 546 | let (dtype, index) = req.descriptor_type_index(); |
| 533 | 547 | ||
| 534 | match dtype { | 548 | match dtype { |
| 535 | descriptor_type::BOS => self.control.accept_in(self.bos_descriptor, stage).await, | 549 | descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor), |
| 536 | descriptor_type::DEVICE => self.control.accept_in(self.device_descriptor, stage).await, | 550 | descriptor_type::DEVICE => InResponse::Accepted(self.device_descriptor), |
| 537 | descriptor_type::CONFIGURATION => { | 551 | descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor), |
| 538 | self.control.accept_in(self.config_descriptor, stage).await | ||
| 539 | } | ||
| 540 | descriptor_type::STRING => { | 552 | descriptor_type::STRING => { |
| 541 | if index == 0 { | 553 | if index == 0 { |
| 542 | self.control | 554 | buf[0] = 4; // len |
| 543 | .accept_in_writer(req, stage, |w| { | 555 | buf[1] = descriptor_type::STRING; |
| 544 | w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes()); | 556 | buf[2] = lang_id::ENGLISH_US as u8; |
| 545 | }) | 557 | buf[3] = (lang_id::ENGLISH_US >> 8) as u8; |
| 546 | .await | 558 | InResponse::Accepted(&buf[..4]) |
| 547 | } else { | 559 | } else { |
| 548 | let s = match index { | 560 | let s = match index { |
| 549 | STRING_INDEX_MANUFACTURER => self.config.manufacturer, | 561 | STRING_INDEX_MANUFACTURER => self.config.manufacturer, |
| @@ -565,7 +577,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 565 | if let Some(handler) = &mut iface.handler { | 577 | if let Some(handler) = &mut iface.handler { |
| 566 | let index = StringIndex::new(index); | 578 | let index = StringIndex::new(index); |
| 567 | let lang_id = req.index; | 579 | let lang_id = req.index; |
| 568 | handler.get_string(index, lang_id, self.control_buf) | 580 | handler.get_string(index, lang_id) |
| 569 | } else { | 581 | } else { |
| 570 | warn!("String requested to an interface with no handler."); | 582 | warn!("String requested to an interface with no handler."); |
| 571 | None | 583 | None |
| @@ -578,15 +590,29 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 578 | }; | 590 | }; |
| 579 | 591 | ||
| 580 | if let Some(s) = s { | 592 | if let Some(s) = s { |
| 581 | self.control | 593 | if buf.len() < 2 { |
| 582 | .accept_in_writer(req, stage, |w| w.string(s)) | 594 | panic!("control buffer too small"); |
| 583 | .await | 595 | } |
| 596 | |||
| 597 | buf[1] = descriptor_type::STRING; | ||
| 598 | let mut pos = 2; | ||
| 599 | for c in s.encode_utf16() { | ||
| 600 | if pos >= buf.len() { | ||
| 601 | panic!("control buffer too small"); | ||
| 602 | } | ||
| 603 | |||
| 604 | buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); | ||
| 605 | pos += 2; | ||
| 606 | } | ||
| 607 | |||
| 608 | buf[0] = pos as u8; | ||
| 609 | InResponse::Accepted(&buf[..pos]) | ||
| 584 | } else { | 610 | } else { |
| 585 | self.control.reject() | 611 | InResponse::Rejected |
| 586 | } | 612 | } |
| 587 | } | 613 | } |
| 588 | } | 614 | } |
| 589 | _ => self.control.reject(), | 615 | _ => InResponse::Rejected, |
| 590 | } | 616 | } |
| 591 | } | 617 | } |
| 592 | } | 618 | } |
