diff options
Diffstat (limited to 'embassy-usb/src')
| -rw-r--r-- | embassy-usb/src/builder.rs | 14 | ||||
| -rw-r--r-- | embassy-usb/src/control.rs | 150 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor.rs | 1 | ||||
| -rw-r--r-- | embassy-usb/src/driver.rs | 21 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 335 |
5 files changed, 218 insertions, 303 deletions
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index 8cf9c82a9..698a5f765 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs | |||
| @@ -372,7 +372,6 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 372 | 372 | ||
| 373 | fn endpoint_in( | 373 | fn endpoint_in( |
| 374 | &mut self, | 374 | &mut self, |
| 375 | ep_addr: Option<EndpointAddress>, | ||
| 376 | ep_type: EndpointType, | 375 | ep_type: EndpointType, |
| 377 | max_packet_size: u16, | 376 | max_packet_size: u16, |
| 378 | interval: u8, | 377 | interval: u8, |
| @@ -380,7 +379,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 380 | let ep = self | 379 | let ep = self |
| 381 | .builder | 380 | .builder |
| 382 | .driver | 381 | .driver |
| 383 | .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) | 382 | .alloc_endpoint_in(ep_type, max_packet_size, interval) |
| 384 | .expect("alloc_endpoint_in failed"); | 383 | .expect("alloc_endpoint_in failed"); |
| 385 | 384 | ||
| 386 | self.builder.config_descriptor.endpoint(ep.info()); | 385 | self.builder.config_descriptor.endpoint(ep.info()); |
| @@ -390,7 +389,6 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 390 | 389 | ||
| 391 | fn endpoint_out( | 390 | fn endpoint_out( |
| 392 | &mut self, | 391 | &mut self, |
| 393 | ep_addr: Option<EndpointAddress>, | ||
| 394 | ep_type: EndpointType, | 392 | ep_type: EndpointType, |
| 395 | max_packet_size: u16, | 393 | max_packet_size: u16, |
| 396 | interval: u8, | 394 | interval: u8, |
| @@ -398,7 +396,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 398 | let ep = self | 396 | let ep = self |
| 399 | .builder | 397 | .builder |
| 400 | .driver | 398 | .driver |
| 401 | .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) | 399 | .alloc_endpoint_out(ep_type, max_packet_size, interval) |
| 402 | .expect("alloc_endpoint_out failed"); | 400 | .expect("alloc_endpoint_out failed"); |
| 403 | 401 | ||
| 404 | self.builder.config_descriptor.endpoint(ep.info()); | 402 | self.builder.config_descriptor.endpoint(ep.info()); |
| @@ -411,7 +409,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 411 | /// Descriptors are written in the order builder functions are called. Note that some | 409 | /// Descriptors are written in the order builder functions are called. Note that some |
| 412 | /// classes care about the order. | 410 | /// classes care about the order. |
| 413 | pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { | 411 | pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { |
| 414 | self.endpoint_in(None, EndpointType::Bulk, max_packet_size, 0) | 412 | self.endpoint_in(EndpointType::Bulk, max_packet_size, 0) |
| 415 | } | 413 | } |
| 416 | 414 | ||
| 417 | /// Allocate a BULK OUT endpoint and write its descriptor. | 415 | /// Allocate a BULK OUT endpoint and write its descriptor. |
| @@ -419,7 +417,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 419 | /// Descriptors are written in the order builder functions are called. Note that some | 417 | /// Descriptors are written in the order builder functions are called. Note that some |
| 420 | /// classes care about the order. | 418 | /// classes care about the order. |
| 421 | pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { | 419 | pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { |
| 422 | self.endpoint_out(None, EndpointType::Bulk, max_packet_size, 0) | 420 | self.endpoint_out(EndpointType::Bulk, max_packet_size, 0) |
| 423 | } | 421 | } |
| 424 | 422 | ||
| 425 | /// Allocate a INTERRUPT IN endpoint and write its descriptor. | 423 | /// Allocate a INTERRUPT IN endpoint and write its descriptor. |
| @@ -427,11 +425,11 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { | |||
| 427 | /// Descriptors are written in the order builder functions are called. Note that some | 425 | /// Descriptors are written in the order builder functions are called. Note that some |
| 428 | /// classes care about the order. | 426 | /// classes care about the order. |
| 429 | pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn { | 427 | pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn { |
| 430 | self.endpoint_in(None, EndpointType::Interrupt, max_packet_size, interval) | 428 | self.endpoint_in(EndpointType::Interrupt, max_packet_size, interval) |
| 431 | } | 429 | } |
| 432 | 430 | ||
| 433 | /// Allocate a INTERRUPT OUT endpoint and write its descriptor. | 431 | /// Allocate a INTERRUPT OUT endpoint and write its descriptor. |
| 434 | pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut { | 432 | pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut { |
| 435 | self.endpoint_out(None, EndpointType::Interrupt, max_packet_size, interval) | 433 | self.endpoint_out(EndpointType::Interrupt, max_packet_size, interval) |
| 436 | } | 434 | } |
| 437 | } | 435 | } |
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 @@ | |||
| 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::*; |
| 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))] | ||
| 211 | pub(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))] | ||
| 218 | pub(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))] | ||
| 225 | pub(crate) struct StatusStage {} | ||
| 226 | |||
| 227 | #[derive(Debug)] | ||
| 228 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 229 | pub(crate) enum Setup { | ||
| 230 | DataIn(Request, DataInStage), | ||
| 231 | DataOut(Request, DataOutStage), | ||
| 232 | } | ||
| 233 | |||
| 234 | pub(crate) struct ControlPipe<C: driver::ControlPipe> { | ||
| 235 | control: C, | ||
| 236 | } | ||
| 237 | |||
| 238 | impl<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 | } | ||
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/driver.rs b/embassy-usb/src/driver.rs index e552dc7b6..57f2b0656 100644 --- a/embassy-usb/src/driver.rs +++ b/embassy-usb/src/driver.rs | |||
| @@ -14,7 +14,7 @@ pub trait Driver<'a> { | |||
| 14 | 14 | ||
| 15 | /// Allocates an endpoint and specified endpoint parameters. This method is called by the device | 15 | /// Allocates an endpoint and specified endpoint parameters. This method is called by the device |
| 16 | /// and class implementations to allocate endpoints, and can only be called before | 16 | /// and class implementations to allocate endpoints, and can only be called before |
| 17 | /// [`enable`](UsbBus::enable) is called. | 17 | /// [`start`](UsbBus::start) is called. |
| 18 | /// | 18 | /// |
| 19 | /// # Arguments | 19 | /// # Arguments |
| 20 | /// | 20 | /// |
| @@ -25,7 +25,6 @@ pub trait Driver<'a> { | |||
| 25 | /// * `interval` - Polling interval parameter for interrupt endpoints. | 25 | /// * `interval` - Polling interval parameter for interrupt endpoints. |
| 26 | fn alloc_endpoint_out( | 26 | fn alloc_endpoint_out( |
| 27 | &mut self, | 27 | &mut self, |
| 28 | ep_addr: Option<EndpointAddress>, | ||
| 29 | ep_type: EndpointType, | 28 | ep_type: EndpointType, |
| 30 | max_packet_size: u16, | 29 | max_packet_size: u16, |
| 31 | interval: u8, | 30 | interval: u8, |
| @@ -33,20 +32,20 @@ pub trait Driver<'a> { | |||
| 33 | 32 | ||
| 34 | fn alloc_endpoint_in( | 33 | fn alloc_endpoint_in( |
| 35 | &mut self, | 34 | &mut self, |
| 36 | ep_addr: Option<EndpointAddress>, | ||
| 37 | ep_type: EndpointType, | 35 | ep_type: EndpointType, |
| 38 | max_packet_size: u16, | 36 | max_packet_size: u16, |
| 39 | interval: u8, | 37 | interval: u8, |
| 40 | ) -> Result<Self::EndpointIn, EndpointAllocError>; | 38 | ) -> Result<Self::EndpointIn, EndpointAllocError>; |
| 41 | 39 | ||
| 42 | fn alloc_control_pipe( | 40 | /// Start operation of the USB device. |
| 43 | &mut self, | 41 | /// |
| 44 | max_packet_size: u16, | 42 | /// This returns the `Bus` and `ControlPipe` instances that are used to operate |
| 45 | ) -> Result<Self::ControlPipe, EndpointAllocError>; | 43 | /// the USB device. Additionally, this makes all the previously allocated endpoints |
| 46 | 44 | /// start operating. | |
| 47 | /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so | 45 | /// |
| 48 | /// there is no need to perform a USB reset in this method. | 46 | /// This consumes the `Driver` instance, so it's no longer possible to allocate more |
| 49 | fn into_bus(self) -> Self::Bus; | 47 | /// endpoints. |
| 48 | fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe); | ||
| 50 | 49 | ||
| 51 | /// Indicates that `set_device_address` must be called before accepting the corresponding | 50 | /// Indicates that `set_device_address` must be called before accepting the corresponding |
| 52 | /// control transfer, not after. | 51 | /// control transfer, not after. |
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index 3bfedc048..b135f5eb3 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -16,6 +16,7 @@ use embassy::util::{select, Either}; | |||
| 16 | use heapless::Vec; | 16 | use heapless::Vec; |
| 17 | 17 | ||
| 18 | use crate::descriptor_reader::foreach_endpoint; | 18 | use crate::descriptor_reader::foreach_endpoint; |
| 19 | use crate::driver::ControlPipe; | ||
| 19 | 20 | ||
| 20 | use self::control::*; | 21 | use self::control::*; |
| 21 | use self::descriptor::*; | 22 | use self::descriptor::*; |
| @@ -100,15 +101,19 @@ struct Interface<'d> { | |||
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | pub struct UsbDevice<'d, D: Driver<'d>> { | 103 | pub struct UsbDevice<'d, D: Driver<'d>> { |
| 104 | control_buf: &'d mut [u8], | ||
| 105 | control: D::ControlPipe, | ||
| 106 | inner: Inner<'d, D>, | ||
| 107 | } | ||
| 108 | |||
| 109 | struct Inner<'d, D: Driver<'d>> { | ||
| 103 | bus: D::Bus, | 110 | bus: D::Bus, |
| 104 | handler: Option<&'d dyn DeviceStateHandler>, | 111 | handler: Option<&'d dyn DeviceStateHandler>, |
| 105 | control: ControlPipe<D::ControlPipe>, | ||
| 106 | 112 | ||
| 107 | config: Config<'d>, | 113 | config: Config<'d>, |
| 108 | device_descriptor: &'d [u8], | 114 | device_descriptor: &'d [u8], |
| 109 | config_descriptor: &'d [u8], | 115 | config_descriptor: &'d [u8], |
| 110 | bos_descriptor: &'d [u8], | 116 | bos_descriptor: &'d [u8], |
| 111 | control_buf: &'d mut [u8], | ||
| 112 | 117 | ||
| 113 | device_state: UsbDeviceState, | 118 | device_state: UsbDeviceState, |
| 114 | suspended: bool, | 119 | suspended: bool, |
| @@ -121,7 +126,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> { | |||
| 121 | 126 | ||
| 122 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | 127 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { |
| 123 | pub(crate) fn build( | 128 | pub(crate) fn build( |
| 124 | mut driver: D, | 129 | driver: D, |
| 125 | config: Config<'d>, | 130 | config: Config<'d>, |
| 126 | handler: Option<&'d dyn DeviceStateHandler>, | 131 | handler: Option<&'d dyn DeviceStateHandler>, |
| 127 | device_descriptor: &'d [u8], | 132 | device_descriptor: &'d [u8], |
| @@ -130,29 +135,28 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 130 | interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, | 135 | interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, |
| 131 | control_buf: &'d mut [u8], | 136 | control_buf: &'d mut [u8], |
| 132 | ) -> UsbDevice<'d, D> { | 137 | ) -> UsbDevice<'d, D> { |
| 133 | let control = driver | 138 | // Start the USB bus. |
| 134 | .alloc_control_pipe(config.max_packet_size_0 as u16) | ||
| 135 | .expect("failed to alloc control endpoint"); | ||
| 136 | |||
| 137 | // Enable the USB bus. | ||
| 138 | // This prevent further allocation by consuming the driver. | 139 | // This prevent further allocation by consuming the driver. |
| 139 | let bus = driver.into_bus(); | 140 | let (bus, control) = driver.start(config.max_packet_size_0 as u16); |
| 140 | 141 | ||
| 141 | Self { | 142 | Self { |
| 142 | bus, | ||
| 143 | config, | ||
| 144 | handler, | ||
| 145 | control: ControlPipe::new(control), | ||
| 146 | device_descriptor, | ||
| 147 | config_descriptor, | ||
| 148 | bos_descriptor, | ||
| 149 | control_buf, | 143 | control_buf, |
| 150 | device_state: UsbDeviceState::Disabled, | 144 | control, |
| 151 | suspended: false, | 145 | inner: Inner { |
| 152 | remote_wakeup_enabled: false, | 146 | bus, |
| 153 | self_powered: false, | 147 | config, |
| 154 | pending_address: 0, | 148 | handler, |
| 155 | interfaces, | 149 | device_descriptor, |
| 150 | config_descriptor, | ||
| 151 | bos_descriptor, | ||
| 152 | |||
| 153 | device_state: UsbDeviceState::Disabled, | ||
| 154 | suspended: false, | ||
| 155 | remote_wakeup_enabled: false, | ||
| 156 | self_powered: false, | ||
| 157 | pending_address: 0, | ||
| 158 | interfaces, | ||
| 159 | }, | ||
| 156 | } | 160 | } |
| 157 | } | 161 | } |
| 158 | 162 | ||
| @@ -176,42 +180,34 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 176 | /// before calling any other `UsbDevice` methods to fully reset the | 180 | /// before calling any other `UsbDevice` methods to fully reset the |
| 177 | /// peripheral. | 181 | /// peripheral. |
| 178 | pub async fn run_until_suspend(&mut self) -> () { | 182 | pub async fn run_until_suspend(&mut self) -> () { |
| 179 | if self.device_state == UsbDeviceState::Disabled { | 183 | if self.inner.device_state == UsbDeviceState::Disabled { |
| 180 | self.bus.enable().await; | 184 | self.inner.bus.enable().await; |
| 181 | self.device_state = UsbDeviceState::Default; | 185 | self.inner.device_state = UsbDeviceState::Default; |
| 182 | 186 | ||
| 183 | if let Some(h) = &self.handler { | 187 | if let Some(h) = &self.inner.handler { |
| 184 | h.enabled(true); | 188 | h.enabled(true); |
| 185 | } | 189 | } |
| 186 | } | 190 | } |
| 187 | 191 | ||
| 188 | loop { | 192 | while !self.inner.suspended { |
| 189 | let control_fut = self.control.setup(); | 193 | let control_fut = self.control.setup(); |
| 190 | let bus_fut = self.bus.poll(); | 194 | let bus_fut = self.inner.bus.poll(); |
| 191 | match select(bus_fut, control_fut).await { | 195 | match select(bus_fut, control_fut).await { |
| 192 | Either::First(evt) => { | 196 | Either::First(evt) => self.inner.handle_bus_event(evt), |
| 193 | self.handle_bus_event(evt); | 197 | Either::Second(req) => self.handle_control(req).await, |
| 194 | if self.suspended { | ||
| 195 | return; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | Either::Second(req) => match req { | ||
| 199 | Setup::DataIn(req, stage) => self.handle_control_in(req, stage).await, | ||
| 200 | Setup::DataOut(req, stage) => self.handle_control_out(req, stage).await, | ||
| 201 | }, | ||
| 202 | } | 198 | } |
| 203 | } | 199 | } |
| 204 | } | 200 | } |
| 205 | 201 | ||
| 206 | /// Disables the USB peripheral. | 202 | /// Disables the USB peripheral. |
| 207 | pub async fn disable(&mut self) { | 203 | pub async fn disable(&mut self) { |
| 208 | if self.device_state != UsbDeviceState::Disabled { | 204 | if self.inner.device_state != UsbDeviceState::Disabled { |
| 209 | self.bus.disable().await; | 205 | self.inner.bus.disable().await; |
| 210 | self.device_state = UsbDeviceState::Disabled; | 206 | self.inner.device_state = UsbDeviceState::Disabled; |
| 211 | self.suspended = false; | 207 | self.inner.suspended = false; |
| 212 | self.remote_wakeup_enabled = false; | 208 | self.inner.remote_wakeup_enabled = false; |
| 213 | 209 | ||
| 214 | if let Some(h) = &self.handler { | 210 | if let Some(h) = &self.inner.handler { |
| 215 | h.enabled(false); | 211 | h.enabled(false); |
| 216 | } | 212 | } |
| 217 | } | 213 | } |
| @@ -221,9 +217,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 221 | /// | 217 | /// |
| 222 | /// This future is cancel-safe. | 218 | /// This future is cancel-safe. |
| 223 | pub async fn wait_resume(&mut self) { | 219 | pub async fn wait_resume(&mut self) { |
| 224 | while self.suspended { | 220 | while self.inner.suspended { |
| 225 | let evt = self.bus.poll().await; | 221 | let evt = self.inner.bus.poll().await; |
| 226 | self.handle_bus_event(evt); | 222 | self.inner.handle_bus_event(evt); |
| 227 | } | 223 | } |
| 228 | } | 224 | } |
| 229 | 225 | ||
| @@ -236,11 +232,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 236 | /// After dropping the future, [`UsbDevice::disable()`] should be called | 232 | /// After dropping the future, [`UsbDevice::disable()`] should be called |
| 237 | /// before calling any other `UsbDevice` methods to fully reset the peripheral. | 233 | /// before calling any other `UsbDevice` methods to fully reset the peripheral. |
| 238 | pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { | 234 | pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { |
| 239 | if self.suspended && self.remote_wakeup_enabled { | 235 | if self.inner.suspended && self.inner.remote_wakeup_enabled { |
| 240 | self.bus.remote_wakeup().await?; | 236 | self.inner.bus.remote_wakeup().await?; |
| 241 | self.suspended = false; | 237 | self.inner.suspended = false; |
| 242 | 238 | ||
| 243 | if let Some(h) = &self.handler { | 239 | if let Some(h) = &self.inner.handler { |
| 244 | h.suspended(false); | 240 | h.suspended(false); |
| 245 | } | 241 | } |
| 246 | 242 | ||
| @@ -250,6 +246,88 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 250 | } | 246 | } |
| 251 | } | 247 | } |
| 252 | 248 | ||
| 249 | async fn handle_control(&mut self, req: Request) { | ||
| 250 | trace!("control request: {:02x}", req); | ||
| 251 | |||
| 252 | match req.direction { | ||
| 253 | UsbDirection::In => self.handle_control_in(req).await, | ||
| 254 | UsbDirection::Out => self.handle_control_out(req).await, | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | async fn handle_control_in(&mut self, req: Request) { | ||
| 259 | let mut resp_length = req.length as usize; | ||
| 260 | let max_packet_size = self.control.max_packet_size(); | ||
| 261 | |||
| 262 | // If we don't have an address yet, respond with max 1 packet. | ||
| 263 | // The host doesn't know our EP0 max packet size yet, and might assume | ||
| 264 | // a full-length packet is a short packet, thinking we're done sending data. | ||
| 265 | // See https://github.com/hathach/tinyusb/issues/184 | ||
| 266 | const DEVICE_DESCRIPTOR_LEN: usize = 18; | ||
| 267 | if self.inner.pending_address == 0 | ||
| 268 | && max_packet_size < DEVICE_DESCRIPTOR_LEN | ||
| 269 | && (max_packet_size as usize) < resp_length | ||
| 270 | { | ||
| 271 | trace!("received control req while not addressed: capping response to 1 packet."); | ||
| 272 | resp_length = max_packet_size; | ||
| 273 | } | ||
| 274 | |||
| 275 | match self.inner.handle_control_in(req, &mut self.control_buf) { | ||
| 276 | InResponse::Accepted(data) => { | ||
| 277 | let len = data.len().min(resp_length); | ||
| 278 | let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0; | ||
| 279 | |||
| 280 | let mut chunks = data[0..len] | ||
| 281 | .chunks(max_packet_size) | ||
| 282 | .chain(need_zlp.then(|| -> &[u8] { &[] })); | ||
| 283 | |||
| 284 | while let Some(chunk) = chunks.next() { | ||
| 285 | match self.control.data_in(chunk, chunks.size_hint().0 == 0).await { | ||
| 286 | Ok(()) => {} | ||
| 287 | Err(e) => { | ||
| 288 | warn!("control accept_in failed: {:?}", e); | ||
| 289 | return; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | } | ||
| 293 | } | ||
| 294 | InResponse::Rejected => self.control.reject(), | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | async fn handle_control_out(&mut self, req: Request) { | ||
| 299 | let req_length = req.length as usize; | ||
| 300 | let max_packet_size = self.control.max_packet_size(); | ||
| 301 | let mut total = 0; | ||
| 302 | |||
| 303 | for chunk in self.control_buf[..req_length].chunks_mut(max_packet_size) { | ||
| 304 | let size = match self.control.data_out(chunk).await { | ||
| 305 | Ok(x) => x, | ||
| 306 | Err(e) => { | ||
| 307 | warn!("usb: failed to read CONTROL OUT data stage: {:?}", e); | ||
| 308 | return; | ||
| 309 | } | ||
| 310 | }; | ||
| 311 | total += size; | ||
| 312 | if size < max_packet_size || total == req_length { | ||
| 313 | break; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | let data = &self.control_buf[0..total]; | ||
| 318 | #[cfg(feature = "defmt")] | ||
| 319 | trace!(" control out data: {:02x}", data); | ||
| 320 | #[cfg(not(feature = "defmt"))] | ||
| 321 | trace!(" control out data: {:02x?}", data); | ||
| 322 | |||
| 323 | match self.inner.handle_control_out(req, data) { | ||
| 324 | OutResponse::Accepted => self.control.accept(), | ||
| 325 | OutResponse::Rejected => self.control.reject(), | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | impl<'d, D: Driver<'d>> Inner<'d, D> { | ||
| 253 | fn handle_bus_event(&mut self, evt: Event) { | 331 | fn handle_bus_event(&mut self, evt: Event) { |
| 254 | match evt { | 332 | match evt { |
| 255 | Event::Reset => { | 333 | Event::Reset => { |
| @@ -288,18 +366,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 288 | } | 366 | } |
| 289 | } | 367 | } |
| 290 | 368 | ||
| 291 | async fn handle_control_out(&mut self, req: Request, stage: DataOutStage) { | 369 | fn handle_control_out(&mut self, req: Request, data: &[u8]) -> OutResponse { |
| 292 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; | 370 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; |
| 293 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; | 371 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; |
| 294 | 372 | ||
| 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) { | 373 | match (req.request_type, req.recipient) { |
| 304 | (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { | 374 | (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { |
| 305 | (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { | 375 | (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { |
| @@ -307,14 +377,14 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 307 | if let Some(h) = &self.handler { | 377 | if let Some(h) = &self.handler { |
| 308 | h.remote_wakeup_enabled(false); | 378 | h.remote_wakeup_enabled(false); |
| 309 | } | 379 | } |
| 310 | self.control.accept(stage) | 380 | OutResponse::Accepted |
| 311 | } | 381 | } |
| 312 | (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { | 382 | (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { |
| 313 | self.remote_wakeup_enabled = true; | 383 | self.remote_wakeup_enabled = true; |
| 314 | if let Some(h) = &self.handler { | 384 | if let Some(h) = &self.handler { |
| 315 | h.remote_wakeup_enabled(true); | 385 | h.remote_wakeup_enabled(true); |
| 316 | } | 386 | } |
| 317 | self.control.accept(stage) | 387 | OutResponse::Accepted |
| 318 | } | 388 | } |
| 319 | (Request::SET_ADDRESS, addr @ 1..=127) => { | 389 | (Request::SET_ADDRESS, addr @ 1..=127) => { |
| 320 | self.pending_address = addr as u8; | 390 | self.pending_address = addr as u8; |
| @@ -323,7 +393,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 323 | if let Some(h) = &self.handler { | 393 | if let Some(h) = &self.handler { |
| 324 | h.addressed(self.pending_address); | 394 | h.addressed(self.pending_address); |
| 325 | } | 395 | } |
| 326 | self.control.accept(stage) | 396 | OutResponse::Accepted |
| 327 | } | 397 | } |
| 328 | (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { | 398 | (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { |
| 329 | debug!("SET_CONFIGURATION: configured"); | 399 | debug!("SET_CONFIGURATION: configured"); |
| @@ -344,10 +414,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 344 | h.configured(true); | 414 | h.configured(true); |
| 345 | } | 415 | } |
| 346 | 416 | ||
| 347 | self.control.accept(stage) | 417 | OutResponse::Accepted |
| 348 | } | 418 | } |
| 349 | (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { | 419 | (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { |
| 350 | UsbDeviceState::Default => self.control.accept(stage), | 420 | UsbDeviceState::Default => OutResponse::Accepted, |
| 351 | _ => { | 421 | _ => { |
| 352 | debug!("SET_CONFIGURATION: unconfigured"); | 422 | debug!("SET_CONFIGURATION: unconfigured"); |
| 353 | self.device_state = UsbDeviceState::Addressed; | 423 | self.device_state = UsbDeviceState::Addressed; |
| @@ -363,15 +433,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 363 | h.configured(false); | 433 | h.configured(false); |
| 364 | } | 434 | } |
| 365 | 435 | ||
| 366 | self.control.accept(stage) | 436 | OutResponse::Accepted |
| 367 | } | 437 | } |
| 368 | }, | 438 | }, |
| 369 | _ => self.control.reject(), | 439 | _ => OutResponse::Rejected, |
| 370 | }, | 440 | }, |
| 371 | (RequestType::Standard, Recipient::Interface) => { | 441 | (RequestType::Standard, Recipient::Interface) => { |
| 372 | let iface = match self.interfaces.get_mut(req.index as usize) { | 442 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 373 | Some(iface) => iface, | 443 | Some(iface) => iface, |
| 374 | None => return self.control.reject(), | 444 | None => return OutResponse::Rejected, |
| 375 | }; | 445 | }; |
| 376 | 446 | ||
| 377 | match req.request { | 447 | match req.request { |
| @@ -380,7 +450,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 380 | 450 | ||
| 381 | if new_altsetting >= iface.num_alt_settings { | 451 | if new_altsetting >= iface.num_alt_settings { |
| 382 | warn!("SET_INTERFACE: trying to select alt setting out of range."); | 452 | warn!("SET_INTERFACE: trying to select alt setting out of range."); |
| 383 | return self.control.reject(); | 453 | return OutResponse::Rejected; |
| 384 | } | 454 | } |
| 385 | 455 | ||
| 386 | iface.current_alt_setting = new_altsetting; | 456 | iface.current_alt_setting = new_altsetting; |
| @@ -402,55 +472,39 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 402 | if let Some(handler) = &mut iface.handler { | 472 | if let Some(handler) = &mut iface.handler { |
| 403 | handler.set_alternate_setting(new_altsetting); | 473 | handler.set_alternate_setting(new_altsetting); |
| 404 | } | 474 | } |
| 405 | self.control.accept(stage) | 475 | OutResponse::Accepted |
| 406 | } | 476 | } |
| 407 | _ => self.control.reject(), | 477 | _ => OutResponse::Rejected, |
| 408 | } | 478 | } |
| 409 | } | 479 | } |
| 410 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { | 480 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { |
| 411 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 481 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 412 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 482 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| 413 | self.bus.endpoint_set_stalled(ep_addr, true); | 483 | self.bus.endpoint_set_stalled(ep_addr, true); |
| 414 | self.control.accept(stage) | 484 | OutResponse::Accepted |
| 415 | } | 485 | } |
| 416 | (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 486 | (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 417 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 487 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| 418 | self.bus.endpoint_set_stalled(ep_addr, false); | 488 | self.bus.endpoint_set_stalled(ep_addr, false); |
| 419 | self.control.accept(stage) | 489 | OutResponse::Accepted |
| 420 | } | 490 | } |
| 421 | _ => self.control.reject(), | 491 | _ => OutResponse::Rejected, |
| 422 | }, | 492 | }, |
| 423 | (RequestType::Class, Recipient::Interface) => { | 493 | (RequestType::Class, Recipient::Interface) => { |
| 424 | let iface = match self.interfaces.get_mut(req.index as usize) { | 494 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 425 | Some(iface) => iface, | 495 | Some(iface) => iface, |
| 426 | None => return self.control.reject(), | 496 | None => return OutResponse::Rejected, |
| 427 | }; | 497 | }; |
| 428 | match &mut iface.handler { | 498 | match &mut iface.handler { |
| 429 | Some(handler) => match handler.control_out(req, data) { | 499 | Some(handler) => handler.control_out(req, data), |
| 430 | OutResponse::Accepted => self.control.accept(stage), | 500 | None => OutResponse::Rejected, |
| 431 | OutResponse::Rejected => self.control.reject(), | ||
| 432 | }, | ||
| 433 | None => self.control.reject(), | ||
| 434 | } | 501 | } |
| 435 | } | 502 | } |
| 436 | _ => self.control.reject(), | 503 | _ => OutResponse::Rejected, |
| 437 | } | 504 | } |
| 438 | } | 505 | } |
| 439 | 506 | ||
| 440 | async fn handle_control_in(&mut self, req: Request, mut stage: DataInStage) { | 507 | 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) { | 508 | match (req.request_type, req.recipient) { |
| 455 | (RequestType::Standard, Recipient::Device) => match req.request { | 509 | (RequestType::Standard, Recipient::Device) => match req.request { |
| 456 | Request::GET_STATUS => { | 510 | Request::GET_STATUS => { |
| @@ -461,42 +515,41 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 461 | if self.remote_wakeup_enabled { | 515 | if self.remote_wakeup_enabled { |
| 462 | status |= 0x0002; | 516 | status |= 0x0002; |
| 463 | } | 517 | } |
| 464 | self.control.accept_in(&status.to_le_bytes(), stage).await | 518 | buf[..2].copy_from_slice(&status.to_le_bytes()); |
| 519 | InResponse::Accepted(&buf[..2]) | ||
| 465 | } | 520 | } |
| 466 | Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, stage).await, | 521 | Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, buf), |
| 467 | Request::GET_CONFIGURATION => { | 522 | Request::GET_CONFIGURATION => { |
| 468 | let status = match self.device_state { | 523 | let status = match self.device_state { |
| 469 | UsbDeviceState::Configured => CONFIGURATION_VALUE, | 524 | UsbDeviceState::Configured => CONFIGURATION_VALUE, |
| 470 | _ => CONFIGURATION_NONE, | 525 | _ => CONFIGURATION_NONE, |
| 471 | }; | 526 | }; |
| 472 | self.control.accept_in(&status.to_le_bytes(), stage).await | 527 | buf[0] = status; |
| 528 | InResponse::Accepted(&buf[..1]) | ||
| 473 | } | 529 | } |
| 474 | _ => self.control.reject(), | 530 | _ => InResponse::Rejected, |
| 475 | }, | 531 | }, |
| 476 | (RequestType::Standard, Recipient::Interface) => { | 532 | (RequestType::Standard, Recipient::Interface) => { |
| 477 | let iface = match self.interfaces.get_mut(req.index as usize) { | 533 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 478 | Some(iface) => iface, | 534 | Some(iface) => iface, |
| 479 | None => return self.control.reject(), | 535 | None => return InResponse::Rejected, |
| 480 | }; | 536 | }; |
| 481 | 537 | ||
| 482 | match req.request { | 538 | match req.request { |
| 483 | Request::GET_STATUS => { | 539 | Request::GET_STATUS => { |
| 484 | let status: u16 = 0; | 540 | let status: u16 = 0; |
| 485 | self.control.accept_in(&status.to_le_bytes(), stage).await | 541 | buf[..2].copy_from_slice(&status.to_le_bytes()); |
| 542 | InResponse::Accepted(&buf[..2]) | ||
| 486 | } | 543 | } |
| 487 | Request::GET_INTERFACE => { | 544 | Request::GET_INTERFACE => { |
| 488 | self.control | 545 | buf[0] = iface.current_alt_setting; |
| 489 | .accept_in(&[iface.current_alt_setting], stage) | 546 | InResponse::Accepted(&buf[..1]) |
| 490 | .await; | ||
| 491 | } | 547 | } |
| 492 | Request::GET_DESCRIPTOR => match &mut iface.handler { | 548 | Request::GET_DESCRIPTOR => match &mut iface.handler { |
| 493 | Some(handler) => match handler.get_descriptor(req, self.control_buf) { | 549 | Some(handler) => handler.get_descriptor(req, buf), |
| 494 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | 550 | None => InResponse::Rejected, |
| 495 | InResponse::Rejected => self.control.reject(), | ||
| 496 | }, | ||
| 497 | None => self.control.reject(), | ||
| 498 | }, | 551 | }, |
| 499 | _ => self.control.reject(), | 552 | _ => InResponse::Rejected, |
| 500 | } | 553 | } |
| 501 | } | 554 | } |
| 502 | (RequestType::Standard, Recipient::Endpoint) => match req.request { | 555 | (RequestType::Standard, Recipient::Endpoint) => match req.request { |
| @@ -506,44 +559,40 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 506 | if self.bus.endpoint_is_stalled(ep_addr) { | 559 | if self.bus.endpoint_is_stalled(ep_addr) { |
| 507 | status |= 0x0001; | 560 | status |= 0x0001; |
| 508 | } | 561 | } |
| 509 | self.control.accept_in(&status.to_le_bytes(), stage).await | 562 | buf[..2].copy_from_slice(&status.to_le_bytes()); |
| 563 | InResponse::Accepted(&buf[..2]) | ||
| 510 | } | 564 | } |
| 511 | _ => self.control.reject(), | 565 | _ => InResponse::Rejected, |
| 512 | }, | 566 | }, |
| 513 | (RequestType::Class, Recipient::Interface) => { | 567 | (RequestType::Class, Recipient::Interface) => { |
| 514 | let iface = match self.interfaces.get_mut(req.index as usize) { | 568 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 515 | Some(iface) => iface, | 569 | Some(iface) => iface, |
| 516 | None => return self.control.reject(), | 570 | None => return InResponse::Rejected, |
| 517 | }; | 571 | }; |
| 518 | 572 | ||
| 519 | match &mut iface.handler { | 573 | match &mut iface.handler { |
| 520 | Some(handler) => match handler.control_in(req, self.control_buf) { | 574 | Some(handler) => handler.control_in(req, buf), |
| 521 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | 575 | None => InResponse::Rejected, |
| 522 | InResponse::Rejected => self.control.reject(), | ||
| 523 | }, | ||
| 524 | None => self.control.reject(), | ||
| 525 | } | 576 | } |
| 526 | } | 577 | } |
| 527 | _ => self.control.reject(), | 578 | _ => InResponse::Rejected, |
| 528 | } | 579 | } |
| 529 | } | 580 | } |
| 530 | 581 | ||
| 531 | async fn handle_get_descriptor(&mut self, req: Request, stage: DataInStage) { | 582 | fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { |
| 532 | let (dtype, index) = req.descriptor_type_index(); | 583 | let (dtype, index) = req.descriptor_type_index(); |
| 533 | 584 | ||
| 534 | match dtype { | 585 | match dtype { |
| 535 | descriptor_type::BOS => self.control.accept_in(self.bos_descriptor, stage).await, | 586 | descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor), |
| 536 | descriptor_type::DEVICE => self.control.accept_in(self.device_descriptor, stage).await, | 587 | descriptor_type::DEVICE => InResponse::Accepted(self.device_descriptor), |
| 537 | descriptor_type::CONFIGURATION => { | 588 | descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor), |
| 538 | self.control.accept_in(self.config_descriptor, stage).await | ||
| 539 | } | ||
| 540 | descriptor_type::STRING => { | 589 | descriptor_type::STRING => { |
| 541 | if index == 0 { | 590 | if index == 0 { |
| 542 | self.control | 591 | buf[0] = 4; // len |
| 543 | .accept_in_writer(req, stage, |w| { | 592 | buf[1] = descriptor_type::STRING; |
| 544 | w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes()); | 593 | buf[2] = lang_id::ENGLISH_US as u8; |
| 545 | }) | 594 | buf[3] = (lang_id::ENGLISH_US >> 8) as u8; |
| 546 | .await | 595 | InResponse::Accepted(&buf[..4]) |
| 547 | } else { | 596 | } else { |
| 548 | let s = match index { | 597 | let s = match index { |
| 549 | STRING_INDEX_MANUFACTURER => self.config.manufacturer, | 598 | STRING_INDEX_MANUFACTURER => self.config.manufacturer, |
| @@ -565,7 +614,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 565 | if let Some(handler) = &mut iface.handler { | 614 | if let Some(handler) = &mut iface.handler { |
| 566 | let index = StringIndex::new(index); | 615 | let index = StringIndex::new(index); |
| 567 | let lang_id = req.index; | 616 | let lang_id = req.index; |
| 568 | handler.get_string(index, lang_id, self.control_buf) | 617 | handler.get_string(index, lang_id) |
| 569 | } else { | 618 | } else { |
| 570 | warn!("String requested to an interface with no handler."); | 619 | warn!("String requested to an interface with no handler."); |
| 571 | None | 620 | None |
| @@ -578,15 +627,29 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 578 | }; | 627 | }; |
| 579 | 628 | ||
| 580 | if let Some(s) = s { | 629 | if let Some(s) = s { |
| 581 | self.control | 630 | if buf.len() < 2 { |
| 582 | .accept_in_writer(req, stage, |w| w.string(s)) | 631 | panic!("control buffer too small"); |
| 583 | .await | 632 | } |
| 633 | |||
| 634 | buf[1] = descriptor_type::STRING; | ||
| 635 | let mut pos = 2; | ||
| 636 | for c in s.encode_utf16() { | ||
| 637 | if pos >= buf.len() { | ||
| 638 | panic!("control buffer too small"); | ||
| 639 | } | ||
| 640 | |||
| 641 | buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes()); | ||
| 642 | pos += 2; | ||
| 643 | } | ||
| 644 | |||
| 645 | buf[0] = pos as u8; | ||
| 646 | InResponse::Accepted(&buf[..pos]) | ||
| 584 | } else { | 647 | } else { |
| 585 | self.control.reject() | 648 | InResponse::Rejected |
| 586 | } | 649 | } |
| 587 | } | 650 | } |
| 588 | } | 651 | } |
| 589 | _ => self.control.reject(), | 652 | _ => InResponse::Rejected, |
| 590 | } | 653 | } |
| 591 | } | 654 | } |
| 592 | } | 655 | } |
