diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-04-16 04:47:27 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-04-23 01:11:10 +0200 |
| commit | 092c2b7dfea146681cea01fd4e4105c21c62b61f (patch) | |
| tree | be32635e53177b36ef36939bcdd5eadcf3be3ab8 | |
| parent | ea0a701ebd142ea42e05e51e844bd53cc9bdf354 (diff) | |
usb: builtin handling of interface alternate settings
The stack reads its own descriptors to figure out which endpoints
are used in which alt settings, and enables/disables them as needed.
The ControlHandler has a callback so it can get notified of alternate
setting changes, which is purely informative (it doesn't have to do anything).
| -rw-r--r-- | embassy-nrf/src/usb.rs | 110 | ||||
| -rw-r--r-- | embassy-usb-hid/src/lib.rs | 21 | ||||
| -rw-r--r-- | embassy-usb/src/builder.rs | 23 | ||||
| -rw-r--r-- | embassy-usb/src/control.rs | 37 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor.rs | 4 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor_reader.rs | 110 | ||||
| -rw-r--r-- | embassy-usb/src/driver.rs | 10 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 188 | ||||
| -rw-r--r-- | embassy-usb/src/types.rs | 2 |
9 files changed, 358 insertions, 147 deletions
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs index b67201e67..c032b2cc5 100644 --- a/embassy-nrf/src/usb.rs +++ b/embassy-nrf/src/usb.rs | |||
| @@ -194,16 +194,12 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { | |||
| 194 | fn into_bus(self) -> Self::Bus { | 194 | fn into_bus(self) -> Self::Bus { |
| 195 | Bus { | 195 | Bus { |
| 196 | phantom: PhantomData, | 196 | phantom: PhantomData, |
| 197 | alloc_in: self.alloc_in, | ||
| 198 | alloc_out: self.alloc_out, | ||
| 199 | } | 197 | } |
| 200 | } | 198 | } |
| 201 | } | 199 | } |
| 202 | 200 | ||
| 203 | pub struct Bus<'d, T: Instance> { | 201 | pub struct Bus<'d, T: Instance> { |
| 204 | phantom: PhantomData<&'d mut T>, | 202 | phantom: PhantomData<&'d mut T>, |
| 205 | alloc_in: Allocator, | ||
| 206 | alloc_out: Allocator, | ||
| 207 | } | 203 | } |
| 208 | 204 | ||
| 209 | impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | 205 | impl<'d, T: Instance> driver::Bus for Bus<'d, T> { |
| @@ -264,7 +260,16 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 264 | if regs.events_usbreset.read().bits() != 0 { | 260 | if regs.events_usbreset.read().bits() != 0 { |
| 265 | regs.events_usbreset.reset(); | 261 | regs.events_usbreset.reset(); |
| 266 | regs.intenset.write(|w| w.usbreset().set()); | 262 | regs.intenset.write(|w| w.usbreset().set()); |
| 267 | self.set_configured(false); | 263 | |
| 264 | // Disable all endpoints except EP0 | ||
| 265 | regs.epinen.write(|w| unsafe { w.bits(0x01) }); | ||
| 266 | regs.epouten.write(|w| unsafe { w.bits(0x01) }); | ||
| 267 | READY_ENDPOINTS.store(In::mask(0), Ordering::Release); | ||
| 268 | for i in 1..=7 { | ||
| 269 | In::waker(i).wake(); | ||
| 270 | Out::waker(i).wake(); | ||
| 271 | } | ||
| 272 | |||
| 268 | return Poll::Ready(Event::Reset); | 273 | return Poll::Ready(Event::Reset); |
| 269 | } | 274 | } |
| 270 | 275 | ||
| @@ -297,57 +302,76 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 297 | } | 302 | } |
| 298 | 303 | ||
| 299 | #[inline] | 304 | #[inline] |
| 300 | fn set_configured(&mut self, configured: bool) { | 305 | fn set_address(&mut self, _addr: u8) { |
| 306 | // Nothing to do, the peripheral handles this. | ||
| 307 | } | ||
| 308 | |||
| 309 | fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) { | ||
| 310 | Driver::<T>::set_stalled(ep_addr, stalled) | ||
| 311 | } | ||
| 312 | |||
| 313 | fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { | ||
| 314 | Driver::<T>::is_stalled(ep_addr) | ||
| 315 | } | ||
| 316 | |||
| 317 | fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool) { | ||
| 301 | let regs = T::regs(); | 318 | let regs = T::regs(); |
| 302 | 319 | ||
| 303 | unsafe { | 320 | let i = ep_addr.index(); |
| 304 | if configured { | 321 | let mask = 1 << i; |
| 305 | // TODO: Initialize ISO buffers | ||
| 306 | 322 | ||
| 307 | regs.epinen.write(|w| w.bits(self.alloc_in.used.into())); | 323 | debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); |
| 308 | regs.epouten.write(|w| w.bits(self.alloc_out.used.into())); | ||
| 309 | 324 | ||
| 310 | for i in 1..8 { | 325 | match ep_addr.direction() { |
| 311 | let out_enabled = self.alloc_out.used & (1 << i) != 0; | 326 | UsbDirection::In => { |
| 327 | let mut was_enabled = false; | ||
| 328 | regs.epinen.modify(|r, w| { | ||
| 329 | let mut bits = r.bits(); | ||
| 330 | was_enabled = (bits & mask) != 0; | ||
| 331 | if enabled { | ||
| 332 | bits |= mask | ||
| 333 | } else { | ||
| 334 | bits &= !mask | ||
| 335 | } | ||
| 336 | unsafe { w.bits(bits) } | ||
| 337 | }); | ||
| 312 | 338 | ||
| 339 | let ready_mask = In::mask(i); | ||
| 340 | if enabled { | ||
| 341 | if !was_enabled { | ||
| 342 | READY_ENDPOINTS.fetch_or(ready_mask, Ordering::AcqRel); | ||
| 343 | } | ||
| 344 | } else { | ||
| 345 | READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel); | ||
| 346 | } | ||
| 347 | |||
| 348 | In::waker(i).wake(); | ||
| 349 | } | ||
| 350 | UsbDirection::Out => { | ||
| 351 | regs.epouten.modify(|r, w| { | ||
| 352 | let mut bits = r.bits(); | ||
| 353 | if enabled { | ||
| 354 | bits |= mask | ||
| 355 | } else { | ||
| 356 | bits &= !mask | ||
| 357 | } | ||
| 358 | unsafe { w.bits(bits) } | ||
| 359 | }); | ||
| 360 | |||
| 361 | let ready_mask = Out::mask(i); | ||
| 362 | if enabled { | ||
| 313 | // when first enabled, bulk/interrupt OUT endpoints will *not* receive data (the | 363 | // when first enabled, bulk/interrupt OUT endpoints will *not* receive data (the |
| 314 | // peripheral will NAK all incoming packets) until we write a zero to the SIZE | 364 | // peripheral will NAK all incoming packets) until we write a zero to the SIZE |
| 315 | // register (see figure 203 of the 52840 manual). To avoid that we write a 0 to the | 365 | // register (see figure 203 of the 52840 manual). To avoid that we write a 0 to the |
| 316 | // SIZE register | 366 | // SIZE register |
| 317 | if out_enabled { | 367 | regs.size.epout[i].reset(); |
| 318 | regs.size.epout[i].reset(); | 368 | } else { |
| 319 | } | 369 | READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel); |
| 320 | } | 370 | } |
| 321 | 371 | ||
| 322 | // IN endpoints (low bits) default to ready. | 372 | Out::waker(i).wake(); |
| 323 | // OUT endpoints (high bits) default to NOT ready, they become ready when data comes in. | ||
| 324 | READY_ENDPOINTS.store(0x0000FFFF, Ordering::Release); | ||
| 325 | } else { | ||
| 326 | // Disable all endpoints except EP0 | ||
| 327 | regs.epinen.write(|w| w.bits(0x01)); | ||
| 328 | regs.epouten.write(|w| w.bits(0x01)); | ||
| 329 | |||
| 330 | READY_ENDPOINTS.store(In::mask(0), Ordering::Release); | ||
| 331 | } | 373 | } |
| 332 | } | 374 | } |
| 333 | |||
| 334 | for i in 1..=7 { | ||
| 335 | In::waker(i).wake(); | ||
| 336 | Out::waker(i).wake(); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | #[inline] | ||
| 341 | fn set_device_address(&mut self, _addr: u8) { | ||
| 342 | // Nothing to do, the peripheral handles this. | ||
| 343 | } | ||
| 344 | |||
| 345 | fn set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool) { | ||
| 346 | Driver::<T>::set_stalled(ep_addr, stalled) | ||
| 347 | } | ||
| 348 | |||
| 349 | fn is_stalled(&mut self, ep_addr: EndpointAddress) -> bool { | ||
| 350 | Driver::<T>::is_stalled(ep_addr) | ||
| 351 | } | 375 | } |
| 352 | 376 | ||
| 353 | #[inline] | 377 | #[inline] |
diff --git a/embassy-usb-hid/src/lib.rs b/embassy-usb-hid/src/lib.rs index 48e15e86a..b9ba4f1e7 100644 --- a/embassy-usb-hid/src/lib.rs +++ b/embassy-usb-hid/src/lib.rs | |||
| @@ -438,6 +438,14 @@ impl<'d> ControlHandler for Control<'d> { | |||
| 438 | self.out_report_offset.store(0, Ordering::Release); | 438 | self.out_report_offset.store(0, Ordering::Release); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | fn get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { | ||
| 442 | match (req.value >> 8) as u8 { | ||
| 443 | HID_DESC_DESCTYPE_HID_REPORT => InResponse::Accepted(self.report_descriptor), | ||
| 444 | HID_DESC_DESCTYPE_HID => InResponse::Accepted(&self.hid_descriptor), | ||
| 445 | _ => InResponse::Rejected, | ||
| 446 | } | ||
| 447 | } | ||
| 448 | |||
| 441 | fn control_out(&mut self, req: embassy_usb::control::Request, data: &[u8]) -> OutResponse { | 449 | fn control_out(&mut self, req: embassy_usb::control::Request, data: &[u8]) -> OutResponse { |
| 442 | trace!("HID control_out {:?} {=[u8]:x}", req, data); | 450 | trace!("HID control_out {:?} {=[u8]:x}", req, data); |
| 443 | if let RequestType::Class = req.request_type { | 451 | if let RequestType::Class = req.request_type { |
| @@ -477,13 +485,8 @@ impl<'d> ControlHandler for Control<'d> { | |||
| 477 | 485 | ||
| 478 | fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { | 486 | fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { |
| 479 | trace!("HID control_in {:?}", req); | 487 | trace!("HID control_in {:?}", req); |
| 480 | match (req.request_type, req.request) { | 488 | match req.request { |
| 481 | (RequestType::Standard, Request::GET_DESCRIPTOR) => match (req.value >> 8) as u8 { | 489 | HID_REQ_GET_REPORT => { |
| 482 | HID_DESC_DESCTYPE_HID_REPORT => InResponse::Accepted(self.report_descriptor), | ||
| 483 | HID_DESC_DESCTYPE_HID => InResponse::Accepted(&self.hid_descriptor), | ||
| 484 | _ => InResponse::Rejected, | ||
| 485 | }, | ||
| 486 | (RequestType::Class, HID_REQ_GET_REPORT) => { | ||
| 487 | let size = match ReportId::try_from(req.value) { | 490 | let size = match ReportId::try_from(req.value) { |
| 488 | Ok(id) => self.request_handler.and_then(|x| x.get_report(id, buf)), | 491 | Ok(id) => self.request_handler.and_then(|x| x.get_report(id, buf)), |
| 489 | Err(_) => None, | 492 | Err(_) => None, |
| @@ -495,7 +498,7 @@ impl<'d> ControlHandler for Control<'d> { | |||
| 495 | InResponse::Rejected | 498 | InResponse::Rejected |
| 496 | } | 499 | } |
| 497 | } | 500 | } |
| 498 | (RequestType::Class, HID_REQ_GET_IDLE) => { | 501 | HID_REQ_GET_IDLE => { |
| 499 | if let Some(handler) = self.request_handler { | 502 | if let Some(handler) = self.request_handler { |
| 500 | let id = req.value as u8; | 503 | let id = req.value as u8; |
| 501 | let id = (id != 0).then(|| ReportId::In(id)); | 504 | let id = (id != 0).then(|| ReportId::In(id)); |
| @@ -510,7 +513,7 @@ impl<'d> ControlHandler for Control<'d> { | |||
| 510 | InResponse::Rejected | 513 | InResponse::Rejected |
| 511 | } | 514 | } |
| 512 | } | 515 | } |
| 513 | (RequestType::Class, HID_REQ_GET_PROTOCOL) => { | 516 | HID_REQ_GET_PROTOCOL => { |
| 514 | // UNSUPPORTED: Boot Protocol | 517 | // UNSUPPORTED: Boot Protocol |
| 515 | buf[0] = 1; | 518 | buf[0] = 1; |
| 516 | InResponse::Accepted(&buf[0..1]) | 519 | InResponse::Accepted(&buf[0..1]) |
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index 7e67b4ae6..c0aea9838 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | use heapless::Vec; | 1 | use heapless::Vec; |
| 2 | 2 | ||
| 3 | use crate::Interface; | ||
| 4 | |||
| 3 | use super::control::ControlHandler; | 5 | use super::control::ControlHandler; |
| 4 | use super::descriptor::{BosWriter, DescriptorWriter}; | 6 | use super::descriptor::{BosWriter, DescriptorWriter}; |
| 5 | use super::driver::{Driver, Endpoint}; | 7 | use super::driver::{Driver, Endpoint}; |
| @@ -121,11 +123,10 @@ impl<'a> Config<'a> { | |||
| 121 | pub struct Builder<'d, D: Driver<'d>> { | 123 | pub struct Builder<'d, D: Driver<'d>> { |
| 122 | config: Config<'d>, | 124 | config: Config<'d>, |
| 123 | handler: Option<&'d dyn DeviceStateHandler>, | 125 | handler: Option<&'d dyn DeviceStateHandler>, |
| 124 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, | 126 | interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, |
| 125 | control_buf: &'d mut [u8], | 127 | control_buf: &'d mut [u8], |
| 126 | 128 | ||
| 127 | driver: D, | 129 | driver: D, |
| 128 | next_interface_number: u8, | ||
| 129 | next_string_index: u8, | 130 | next_string_index: u8, |
| 130 | 131 | ||
| 131 | device_descriptor: DescriptorWriter<'d>, | 132 | device_descriptor: DescriptorWriter<'d>, |
| @@ -180,7 +181,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { | |||
| 180 | config, | 181 | config, |
| 181 | interfaces: Vec::new(), | 182 | interfaces: Vec::new(), |
| 182 | control_buf, | 183 | control_buf, |
| 183 | next_interface_number: 0, | ||
| 184 | next_string_index: 4, | 184 | next_string_index: 4, |
| 185 | 185 | ||
| 186 | device_descriptor, | 186 | device_descriptor, |
| @@ -234,7 +234,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { | |||
| 234 | ) -> FunctionBuilder<'_, 'd, D> { | 234 | ) -> FunctionBuilder<'_, 'd, D> { |
| 235 | let iface_count_index = if self.config.composite_with_iads { | 235 | let iface_count_index = if self.config.composite_with_iads { |
| 236 | self.config_descriptor.iad( | 236 | self.config_descriptor.iad( |
| 237 | InterfaceNumber::new(self.next_interface_number), | 237 | InterfaceNumber::new(self.interfaces.len() as _), |
| 238 | 0, | 238 | 0, |
| 239 | class, | 239 | class, |
| 240 | subclass, | 240 | subclass, |
| @@ -275,13 +275,15 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> { | |||
| 275 | self.builder.config_descriptor.buf[i] += 1; | 275 | self.builder.config_descriptor.buf[i] += 1; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | let number = self.builder.next_interface_number; | 278 | let number = self.builder.interfaces.len() as _; |
| 279 | self.builder.next_interface_number += 1; | 279 | let iface = Interface { |
| 280 | handler, | ||
| 281 | current_alt_setting: 0, | ||
| 282 | num_alt_settings: 0, | ||
| 283 | }; | ||
| 280 | 284 | ||
| 281 | if let Some(handler) = handler { | 285 | if self.builder.interfaces.push(iface).is_err() { |
| 282 | if self.builder.interfaces.push((number, handler)).is_err() { | 286 | panic!("max interface count reached") |
| 283 | panic!("max interface count reached") | ||
| 284 | } | ||
| 285 | } | 287 | } |
| 286 | 288 | ||
| 287 | InterfaceBuilder { | 289 | InterfaceBuilder { |
| @@ -318,6 +320,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> { | |||
| 318 | ) -> InterfaceAltBuilder<'_, 'd, D> { | 320 | ) -> InterfaceAltBuilder<'_, 'd, D> { |
| 319 | let number = self.next_alt_setting_number; | 321 | let number = self.next_alt_setting_number; |
| 320 | self.next_alt_setting_number += 1; | 322 | self.next_alt_setting_number += 1; |
| 323 | self.builder.interfaces[self.interface_number.0 as usize].num_alt_settings += 1; | ||
| 321 | 324 | ||
| 322 | self.builder.config_descriptor.interface_alt( | 325 | self.builder.config_descriptor.interface_alt( |
| 323 | self.interface_number, | 326 | self.interface_number, |
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs index 9300d8c4c..0b59451d5 100644 --- a/embassy-usb/src/control.rs +++ b/embassy-usb/src/control.rs | |||
| @@ -2,7 +2,6 @@ use core::mem; | |||
| 2 | 2 | ||
| 3 | use crate::descriptor::DescriptorWriter; | 3 | use crate::descriptor::DescriptorWriter; |
| 4 | use crate::driver::{self, EndpointError}; | 4 | use crate::driver::{self, EndpointError}; |
| 5 | use crate::DEFAULT_ALTERNATE_SETTING; | ||
| 6 | 5 | ||
| 7 | use super::types::*; | 6 | use super::types::*; |
| 8 | 7 | ||
| @@ -150,6 +149,10 @@ pub trait ControlHandler { | |||
| 150 | /// Called after a USB reset after the bus reset sequence is complete. | 149 | /// Called after a USB reset after the bus reset sequence is complete. |
| 151 | fn reset(&mut self) {} | 150 | fn reset(&mut self) {} |
| 152 | 151 | ||
| 152 | fn set_alternate_setting(&mut self, alternate_setting: u8) { | ||
| 153 | let _ = alternate_setting; | ||
| 154 | } | ||
| 155 | |||
| 153 | /// Called when a control request is received with direction HostToDevice. | 156 | /// Called when a control request is received with direction HostToDevice. |
| 154 | /// | 157 | /// |
| 155 | /// # Arguments | 158 | /// # Arguments |
| @@ -163,8 +166,8 @@ pub trait ControlHandler { | |||
| 163 | 166 | ||
| 164 | /// Called when a control request is received with direction DeviceToHost. | 167 | /// Called when a control request is received with direction DeviceToHost. |
| 165 | /// | 168 | /// |
| 166 | /// You should write the response to `resp`, then return `InResponse::Accepted(len)` | 169 | /// You should write the response somewhere (usually to `buf`, but you may use another buffer |
| 167 | /// with the length of the response. | 170 | /// owned by yourself, or a static buffer), then return `InResponse::Accepted(data)`. |
| 168 | /// | 171 | /// |
| 169 | /// # Arguments | 172 | /// # Arguments |
| 170 | /// | 173 | /// |
| @@ -174,23 +177,17 @@ pub trait ControlHandler { | |||
| 174 | InResponse::Rejected | 177 | InResponse::Rejected |
| 175 | } | 178 | } |
| 176 | 179 | ||
| 177 | fn set_interface(&mut self, alternate_setting: u16) -> OutResponse { | 180 | /// Called when a GET DESCRIPTOR control request is received on the interface. |
| 178 | if alternate_setting == u16::from(DEFAULT_ALTERNATE_SETTING) { | 181 | /// |
| 179 | OutResponse::Accepted | 182 | /// You should write the response somewhere (usually to `buf`, but you may use another buffer |
| 180 | } else { | 183 | /// owned by yourself, or a static buffer), then return `InResponse::Accepted(data)`. |
| 181 | OutResponse::Rejected | 184 | /// |
| 182 | } | 185 | /// # Arguments |
| 183 | } | 186 | /// |
| 184 | 187 | /// * `req` - The request from the SETUP packet. | |
| 185 | fn get_interface<'a>(&'a mut self, buf: &'a mut [u8]) -> InResponse<'a> { | 188 | fn get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> { |
| 186 | buf[0] = DEFAULT_ALTERNATE_SETTING; | 189 | let _ = (req, buf); |
| 187 | InResponse::Accepted(&buf[0..1]) | 190 | InResponse::Rejected |
| 188 | } | ||
| 189 | |||
| 190 | fn get_status<'a>(&'a mut self, buf: &'a mut [u8]) -> InResponse { | ||
| 191 | let status: u16 = 0; | ||
| 192 | buf[0..2].copy_from_slice(&status.to_le_bytes()); | ||
| 193 | InResponse::Accepted(&buf[0..2]) | ||
| 194 | } | 191 | } |
| 195 | } | 192 | } |
| 196 | 193 | ||
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs index b61dea4b4..dce326780 100644 --- a/embassy-usb/src/descriptor.rs +++ b/embassy-usb/src/descriptor.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | use super::builder::Config; | 1 | use super::builder::Config; |
| 2 | use super::{types::*, CONFIGURATION_VALUE, DEFAULT_ALTERNATE_SETTING}; | 2 | use super::{types::*, CONFIGURATION_VALUE}; |
| 3 | 3 | ||
| 4 | /// Standard descriptor types | 4 | /// Standard descriptor types |
| 5 | #[allow(missing_docs)] | 5 | #[allow(missing_docs)] |
| @@ -192,7 +192,7 @@ impl<'a> DescriptorWriter<'a> { | |||
| 192 | interface_protocol: u8, | 192 | interface_protocol: u8, |
| 193 | interface_string: Option<StringIndex>, | 193 | interface_string: Option<StringIndex>, |
| 194 | ) { | 194 | ) { |
| 195 | if alternate_setting == DEFAULT_ALTERNATE_SETTING { | 195 | if alternate_setting == 0 { |
| 196 | match self.num_interfaces_mark { | 196 | match self.num_interfaces_mark { |
| 197 | Some(mark) => self.buf[mark] += 1, | 197 | Some(mark) => self.buf[mark] += 1, |
| 198 | None => { | 198 | None => { |
diff --git a/embassy-usb/src/descriptor_reader.rs b/embassy-usb/src/descriptor_reader.rs new file mode 100644 index 000000000..0a12b566c --- /dev/null +++ b/embassy-usb/src/descriptor_reader.rs | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | use crate::descriptor::descriptor_type; | ||
| 2 | use crate::types::EndpointAddress; | ||
| 3 | |||
| 4 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
| 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 6 | pub struct ReadError; | ||
| 7 | |||
| 8 | pub struct Reader<'a> { | ||
| 9 | data: &'a [u8], | ||
| 10 | } | ||
| 11 | |||
| 12 | impl<'a> Reader<'a> { | ||
| 13 | pub fn new(data: &'a [u8]) -> Self { | ||
| 14 | Self { data } | ||
| 15 | } | ||
| 16 | |||
| 17 | pub fn eof(&self) -> bool { | ||
| 18 | self.data.is_empty() | ||
| 19 | } | ||
| 20 | |||
| 21 | pub fn read<const N: usize>(&mut self) -> Result<[u8; N], ReadError> { | ||
| 22 | let n = self.data.get(0..N).ok_or(ReadError)?; | ||
| 23 | self.data = &self.data[N..]; | ||
| 24 | Ok(n.try_into().unwrap()) | ||
| 25 | } | ||
| 26 | |||
| 27 | pub fn read_u8(&mut self) -> Result<u8, ReadError> { | ||
| 28 | Ok(u8::from_le_bytes(self.read()?)) | ||
| 29 | } | ||
| 30 | pub fn read_u16(&mut self) -> Result<u16, ReadError> { | ||
| 31 | Ok(u16::from_le_bytes(self.read()?)) | ||
| 32 | } | ||
| 33 | |||
| 34 | pub fn read_slice(&mut self, len: usize) -> Result<&'a [u8], ReadError> { | ||
| 35 | let res = self.data.get(0..len).ok_or(ReadError)?; | ||
| 36 | self.data = &self.data[len..]; | ||
| 37 | Ok(res) | ||
| 38 | } | ||
| 39 | |||
| 40 | pub fn read_descriptors(&mut self) -> DescriptorIter<'_, 'a> { | ||
| 41 | DescriptorIter { r: self } | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | pub struct DescriptorIter<'a, 'b> { | ||
| 46 | r: &'a mut Reader<'b>, | ||
| 47 | } | ||
| 48 | |||
| 49 | impl<'a, 'b> Iterator for DescriptorIter<'a, 'b> { | ||
| 50 | type Item = Result<(u8, Reader<'a>), ReadError>; | ||
| 51 | |||
| 52 | fn next(&mut self) -> Option<Self::Item> { | ||
| 53 | if self.r.eof() { | ||
| 54 | return None; | ||
| 55 | } | ||
| 56 | |||
| 57 | let len = match self.r.read_u8() { | ||
| 58 | Ok(x) => x, | ||
| 59 | Err(e) => return Some(Err(e)), | ||
| 60 | }; | ||
| 61 | let type_ = match self.r.read_u8() { | ||
| 62 | Ok(x) => x, | ||
| 63 | Err(e) => return Some(Err(e)), | ||
| 64 | }; | ||
| 65 | let data = match self.r.read_slice(len as usize - 2) { | ||
| 66 | Ok(x) => x, | ||
| 67 | Err(e) => return Some(Err(e)), | ||
| 68 | }; | ||
| 69 | |||
| 70 | Some(Ok((type_, Reader::new(data)))) | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
| 75 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 76 | pub struct EndpointInfo { | ||
| 77 | pub configuration: u8, | ||
| 78 | pub interface: u8, | ||
| 79 | pub interface_alt: u8, | ||
| 80 | pub ep_address: EndpointAddress, | ||
| 81 | } | ||
| 82 | |||
| 83 | pub fn foreach_endpoint(data: &[u8], mut f: impl FnMut(EndpointInfo)) -> Result<(), ReadError> { | ||
| 84 | let mut ep = EndpointInfo { | ||
| 85 | configuration: 0, | ||
| 86 | interface: 0, | ||
| 87 | interface_alt: 0, | ||
| 88 | ep_address: EndpointAddress::from(0), | ||
| 89 | }; | ||
| 90 | for res in Reader::new(data).read_descriptors() { | ||
| 91 | let (kind, mut r) = res?; | ||
| 92 | match kind { | ||
| 93 | descriptor_type::CONFIGURATION => { | ||
| 94 | let _total_length = r.read_u16()?; | ||
| 95 | let _total_length = r.read_u8()?; | ||
| 96 | ep.configuration = r.read_u8()?; | ||
| 97 | } | ||
| 98 | descriptor_type::INTERFACE => { | ||
| 99 | ep.interface = r.read_u8()?; | ||
| 100 | ep.interface_alt = r.read_u8()?; | ||
| 101 | } | ||
| 102 | descriptor_type::ENDPOINT => { | ||
| 103 | ep.ep_address = EndpointAddress::from(r.read_u8()?); | ||
| 104 | f(ep) | ||
| 105 | } | ||
| 106 | _ => {} | ||
| 107 | } | ||
| 108 | } | ||
| 109 | Ok(()) | ||
| 110 | } | ||
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs index cedd349fb..e552dc7b6 100644 --- a/embassy-usb/src/driver.rs +++ b/embassy-usb/src/driver.rs | |||
| @@ -79,17 +79,17 @@ pub trait Bus { | |||
| 79 | fn poll<'a>(&'a mut self) -> Self::PollFuture<'a>; | 79 | fn poll<'a>(&'a mut self) -> Self::PollFuture<'a>; |
| 80 | 80 | ||
| 81 | /// Sets the device USB address to `addr`. | 81 | /// Sets the device USB address to `addr`. |
| 82 | fn set_device_address(&mut self, addr: u8); | 82 | fn set_address(&mut self, addr: u8); |
| 83 | 83 | ||
| 84 | /// Sets the device configured state. | 84 | /// Enables or disables an endpoint. |
| 85 | fn set_configured(&mut self, configured: bool); | 85 | fn endpoint_set_enabled(&mut self, ep_addr: EndpointAddress, enabled: bool); |
| 86 | 86 | ||
| 87 | /// Sets or clears the STALL condition for an endpoint. If the endpoint is an OUT endpoint, it | 87 | /// Sets or clears the STALL condition for an endpoint. If the endpoint is an OUT endpoint, it |
| 88 | /// should be prepared to receive data again. Only used during control transfers. | 88 | /// should be prepared to receive data again. Only used during control transfers. |
| 89 | fn set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool); | 89 | fn endpoint_set_stalled(&mut self, ep_addr: EndpointAddress, stalled: bool); |
| 90 | 90 | ||
| 91 | /// Gets whether the STALL condition is set for an endpoint. Only used during control transfers. | 91 | /// Gets whether the STALL condition is set for an endpoint. Only used during control transfers. |
| 92 | fn is_stalled(&mut self, ep_addr: EndpointAddress) -> bool; | 92 | fn endpoint_is_stalled(&mut self, ep_addr: EndpointAddress) -> bool; |
| 93 | 93 | ||
| 94 | /// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the | 94 | /// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the |
| 95 | /// device. | 95 | /// device. |
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index 7cd00fbaf..acb26c60d 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -8,12 +8,15 @@ pub(crate) mod fmt; | |||
| 8 | mod builder; | 8 | mod builder; |
| 9 | pub mod control; | 9 | pub mod control; |
| 10 | pub mod descriptor; | 10 | pub mod descriptor; |
| 11 | mod descriptor_reader; | ||
| 11 | pub mod driver; | 12 | pub mod driver; |
| 12 | pub mod types; | 13 | pub mod types; |
| 13 | 14 | ||
| 14 | use embassy::util::{select, Either}; | 15 | use embassy::util::{select, Either}; |
| 15 | use heapless::Vec; | 16 | use heapless::Vec; |
| 16 | 17 | ||
| 18 | use crate::descriptor_reader::foreach_endpoint; | ||
| 19 | |||
| 17 | use self::control::*; | 20 | use self::control::*; |
| 18 | use self::descriptor::*; | 21 | use self::descriptor::*; |
| 19 | use self::driver::{Bus, Driver, Event}; | 22 | use self::driver::{Bus, Driver, Event}; |
| @@ -61,9 +64,6 @@ pub const CONFIGURATION_NONE: u8 = 0; | |||
| 61 | /// The bConfiguration value for the single configuration supported by this device. | 64 | /// The bConfiguration value for the single configuration supported by this device. |
| 62 | pub const CONFIGURATION_VALUE: u8 = 1; | 65 | pub const CONFIGURATION_VALUE: u8 = 1; |
| 63 | 66 | ||
| 64 | /// The default value for bAlternateSetting for all interfaces. | ||
| 65 | pub const DEFAULT_ALTERNATE_SETTING: u8 = 0; | ||
| 66 | |||
| 67 | pub const MAX_INTERFACE_COUNT: usize = 4; | 67 | pub const MAX_INTERFACE_COUNT: usize = 4; |
| 68 | 68 | ||
| 69 | /// A handler trait for changes in the device state of the [UsbDevice]. | 69 | /// A handler trait for changes in the device state of the [UsbDevice]. |
| @@ -87,6 +87,12 @@ pub trait DeviceStateHandler { | |||
| 87 | fn remote_wakeup_enabled(&self, _enabled: bool) {} | 87 | fn remote_wakeup_enabled(&self, _enabled: bool) {} |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | struct Interface<'d> { | ||
| 91 | handler: Option<&'d mut dyn ControlHandler>, | ||
| 92 | current_alt_setting: u8, | ||
| 93 | num_alt_settings: u8, | ||
| 94 | } | ||
| 95 | |||
| 90 | pub struct UsbDevice<'d, D: Driver<'d>> { | 96 | pub struct UsbDevice<'d, D: Driver<'d>> { |
| 91 | bus: D::Bus, | 97 | bus: D::Bus, |
| 92 | handler: Option<&'d dyn DeviceStateHandler>, | 98 | handler: Option<&'d dyn DeviceStateHandler>, |
| @@ -104,7 +110,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> { | |||
| 104 | self_powered: bool, | 110 | self_powered: bool, |
| 105 | pending_address: u8, | 111 | pending_address: u8, |
| 106 | 112 | ||
| 107 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, | 113 | interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, |
| 108 | } | 114 | } |
| 109 | 115 | ||
| 110 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | 116 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { |
| @@ -115,7 +121,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 115 | device_descriptor: &'d [u8], | 121 | device_descriptor: &'d [u8], |
| 116 | config_descriptor: &'d [u8], | 122 | config_descriptor: &'d [u8], |
| 117 | bos_descriptor: &'d [u8], | 123 | bos_descriptor: &'d [u8], |
| 118 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, | 124 | interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, |
| 119 | control_buf: &'d mut [u8], | 125 | control_buf: &'d mut [u8], |
| 120 | ) -> UsbDevice<'d, D> { | 126 | ) -> UsbDevice<'d, D> { |
| 121 | let control = driver | 127 | let control = driver |
| @@ -247,8 +253,12 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 247 | self.remote_wakeup_enabled = false; | 253 | self.remote_wakeup_enabled = false; |
| 248 | self.pending_address = 0; | 254 | self.pending_address = 0; |
| 249 | 255 | ||
| 250 | for (_, h) in self.interfaces.iter_mut() { | 256 | for iface in self.interfaces.iter_mut() { |
| 251 | h.reset(); | 257 | iface.current_alt_setting = 0; |
| 258 | if let Some(h) = &mut iface.handler { | ||
| 259 | h.reset(); | ||
| 260 | h.set_alternate_setting(0); | ||
| 261 | } | ||
| 252 | } | 262 | } |
| 253 | 263 | ||
| 254 | if let Some(h) = &self.handler { | 264 | if let Some(h) = &self.handler { |
| @@ -302,7 +312,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 302 | } | 312 | } |
| 303 | (Request::SET_ADDRESS, addr @ 1..=127) => { | 313 | (Request::SET_ADDRESS, addr @ 1..=127) => { |
| 304 | self.pending_address = addr as u8; | 314 | self.pending_address = addr as u8; |
| 305 | self.bus.set_device_address(self.pending_address); | 315 | self.bus.set_address(self.pending_address); |
| 306 | self.device_state = UsbDeviceState::Addressed; | 316 | self.device_state = UsbDeviceState::Addressed; |
| 307 | if let Some(h) = &self.handler { | 317 | if let Some(h) = &self.handler { |
| 308 | h.addressed(self.pending_address); | 318 | h.addressed(self.pending_address); |
| @@ -310,59 +320,110 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 310 | self.control.accept(stage) | 320 | self.control.accept(stage) |
| 311 | } | 321 | } |
| 312 | (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { | 322 | (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { |
| 323 | debug!("SET_CONFIGURATION: configured"); | ||
| 313 | self.device_state = UsbDeviceState::Configured; | 324 | self.device_state = UsbDeviceState::Configured; |
| 314 | self.bus.set_configured(true); | 325 | |
| 326 | // Enable all endpoints of selected alt settings. | ||
| 327 | foreach_endpoint(self.config_descriptor, |ep| { | ||
| 328 | let iface = &self.interfaces[ep.interface as usize]; | ||
| 329 | self.bus.endpoint_set_enabled( | ||
| 330 | ep.ep_address, | ||
| 331 | iface.current_alt_setting == ep.interface_alt, | ||
| 332 | ); | ||
| 333 | }) | ||
| 334 | .unwrap(); | ||
| 335 | |||
| 336 | // Notify handler. | ||
| 315 | if let Some(h) = &self.handler { | 337 | if let Some(h) = &self.handler { |
| 316 | h.configured(true); | 338 | h.configured(true); |
| 317 | } | 339 | } |
| 340 | |||
| 318 | self.control.accept(stage) | 341 | self.control.accept(stage) |
| 319 | } | 342 | } |
| 320 | (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { | 343 | (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { |
| 321 | UsbDeviceState::Default => self.control.accept(stage), | 344 | UsbDeviceState::Default => self.control.accept(stage), |
| 322 | _ => { | 345 | _ => { |
| 346 | debug!("SET_CONFIGURATION: unconfigured"); | ||
| 323 | self.device_state = UsbDeviceState::Addressed; | 347 | self.device_state = UsbDeviceState::Addressed; |
| 324 | self.bus.set_configured(false); | 348 | |
| 349 | // Disable all endpoints. | ||
| 350 | foreach_endpoint(self.config_descriptor, |ep| { | ||
| 351 | self.bus.endpoint_set_enabled(ep.ep_address, false); | ||
| 352 | }) | ||
| 353 | .unwrap(); | ||
| 354 | |||
| 355 | // Notify handler. | ||
| 325 | if let Some(h) = &self.handler { | 356 | if let Some(h) = &self.handler { |
| 326 | h.configured(false); | 357 | h.configured(false); |
| 327 | } | 358 | } |
| 359 | |||
| 328 | self.control.accept(stage) | 360 | self.control.accept(stage) |
| 329 | } | 361 | } |
| 330 | }, | 362 | }, |
| 331 | _ => self.control.reject(), | 363 | _ => self.control.reject(), |
| 332 | }, | 364 | }, |
| 365 | (RequestType::Standard, Recipient::Interface) => { | ||
| 366 | let iface = match self.interfaces.get_mut(req.index as usize) { | ||
| 367 | Some(iface) => iface, | ||
| 368 | None => return self.control.reject(), | ||
| 369 | }; | ||
| 370 | |||
| 371 | match req.request { | ||
| 372 | Request::SET_INTERFACE => { | ||
| 373 | let new_altsetting = req.value as u8; | ||
| 374 | |||
| 375 | if new_altsetting >= iface.num_alt_settings { | ||
| 376 | warn!("SET_INTERFACE: trying to select alt setting out of range."); | ||
| 377 | return self.control.reject(); | ||
| 378 | } | ||
| 379 | |||
| 380 | iface.current_alt_setting = new_altsetting; | ||
| 381 | |||
| 382 | // Enable/disable EPs of this interface as needed. | ||
| 383 | foreach_endpoint(self.config_descriptor, |ep| { | ||
| 384 | if ep.interface == req.index as u8 { | ||
| 385 | self.bus.endpoint_set_enabled( | ||
| 386 | ep.ep_address, | ||
| 387 | iface.current_alt_setting == ep.interface_alt, | ||
| 388 | ); | ||
| 389 | } | ||
| 390 | }) | ||
| 391 | .unwrap(); | ||
| 392 | |||
| 393 | // TODO check it is valid (not out of range) | ||
| 394 | // TODO actually enable/disable endpoints. | ||
| 395 | |||
| 396 | if let Some(handler) = &mut iface.handler { | ||
| 397 | handler.set_alternate_setting(new_altsetting); | ||
| 398 | } | ||
| 399 | self.control.accept(stage) | ||
| 400 | } | ||
| 401 | _ => self.control.reject(), | ||
| 402 | } | ||
| 403 | } | ||
| 333 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { | 404 | (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { |
| 334 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 405 | (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 335 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 406 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| 336 | self.bus.set_stalled(ep_addr, true); | 407 | self.bus.endpoint_set_stalled(ep_addr, true); |
| 337 | self.control.accept(stage) | 408 | self.control.accept(stage) |
| 338 | } | 409 | } |
| 339 | (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { | 410 | (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { |
| 340 | let ep_addr = ((req.index as u8) & 0x8f).into(); | 411 | let ep_addr = ((req.index as u8) & 0x8f).into(); |
| 341 | self.bus.set_stalled(ep_addr, false); | 412 | self.bus.endpoint_set_stalled(ep_addr, false); |
| 342 | self.control.accept(stage) | 413 | self.control.accept(stage) |
| 343 | } | 414 | } |
| 344 | _ => self.control.reject(), | 415 | _ => self.control.reject(), |
| 345 | }, | 416 | }, |
| 346 | (_, Recipient::Interface) => { | 417 | (RequestType::Class, Recipient::Interface) => { |
| 347 | let handler = self | 418 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 348 | .interfaces | 419 | Some(iface) => iface, |
| 349 | .iter_mut() | 420 | None => return self.control.reject(), |
| 350 | .find(|(i, _)| req.index == *i as _) | 421 | }; |
| 351 | .map(|(_, h)| h); | 422 | match &mut iface.handler { |
| 352 | 423 | Some(handler) => match handler.control_out(req, data) { | |
| 353 | match handler { | 424 | OutResponse::Accepted => self.control.accept(stage), |
| 354 | Some(handler) => { | 425 | OutResponse::Rejected => self.control.reject(), |
| 355 | let response = match (req.request_type, req.request) { | 426 | }, |
| 356 | (RequestType::Standard, Request::SET_INTERFACE) => { | ||
| 357 | handler.set_interface(req.value) | ||
| 358 | } | ||
| 359 | _ => handler.control_out(req, data), | ||
| 360 | }; | ||
| 361 | match response { | ||
| 362 | OutResponse::Accepted => self.control.accept(stage), | ||
| 363 | OutResponse::Rejected => self.control.reject(), | ||
| 364 | } | ||
| 365 | } | ||
| 366 | None => self.control.reject(), | 427 | None => self.control.reject(), |
| 367 | } | 428 | } |
| 368 | } | 429 | } |
| @@ -406,41 +467,54 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 406 | } | 467 | } |
| 407 | _ => self.control.reject(), | 468 | _ => self.control.reject(), |
| 408 | }, | 469 | }, |
| 470 | (RequestType::Standard, Recipient::Interface) => { | ||
| 471 | let iface = match self.interfaces.get_mut(req.index as usize) { | ||
| 472 | Some(iface) => iface, | ||
| 473 | None => return self.control.reject(), | ||
| 474 | }; | ||
| 475 | |||
| 476 | match req.request { | ||
| 477 | Request::GET_STATUS => { | ||
| 478 | let status: u16 = 0; | ||
| 479 | self.control.accept_in(&status.to_le_bytes(), stage).await | ||
| 480 | } | ||
| 481 | Request::GET_INTERFACE => { | ||
| 482 | self.control | ||
| 483 | .accept_in(&[iface.current_alt_setting], stage) | ||
| 484 | .await; | ||
| 485 | } | ||
| 486 | Request::GET_DESCRIPTOR => match &mut iface.handler { | ||
| 487 | Some(handler) => match handler.get_descriptor(req, self.control_buf) { | ||
| 488 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | ||
| 489 | InResponse::Rejected => self.control.reject(), | ||
| 490 | }, | ||
| 491 | None => self.control.reject(), | ||
| 492 | }, | ||
| 493 | _ => self.control.reject(), | ||
| 494 | } | ||
| 495 | } | ||
| 409 | (RequestType::Standard, Recipient::Endpoint) => match req.request { | 496 | (RequestType::Standard, Recipient::Endpoint) => match req.request { |
| 410 | Request::GET_STATUS => { | 497 | Request::GET_STATUS => { |
| 411 | let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into(); | 498 | let ep_addr: EndpointAddress = ((req.index as u8) & 0x8f).into(); |
| 412 | let mut status: u16 = 0x0000; | 499 | let mut status: u16 = 0x0000; |
| 413 | if self.bus.is_stalled(ep_addr) { | 500 | if self.bus.endpoint_is_stalled(ep_addr) { |
| 414 | status |= 0x0001; | 501 | status |= 0x0001; |
| 415 | } | 502 | } |
| 416 | self.control.accept_in(&status.to_le_bytes(), stage).await | 503 | self.control.accept_in(&status.to_le_bytes(), stage).await |
| 417 | } | 504 | } |
| 418 | _ => self.control.reject(), | 505 | _ => self.control.reject(), |
| 419 | }, | 506 | }, |
| 420 | (_, Recipient::Interface) => { | 507 | (RequestType::Class, Recipient::Interface) => { |
| 421 | let handler = self | 508 | let iface = match self.interfaces.get_mut(req.index as usize) { |
| 422 | .interfaces | 509 | Some(iface) => iface, |
| 423 | .iter_mut() | 510 | None => return self.control.reject(), |
| 424 | .find(|(i, _)| req.index == *i as _) | 511 | }; |
| 425 | .map(|(_, h)| h); | 512 | |
| 426 | 513 | match &mut iface.handler { | |
| 427 | match handler { | 514 | Some(handler) => match handler.control_in(req, self.control_buf) { |
| 428 | Some(handler) => { | 515 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, |
| 429 | let response = match (req.request_type, req.request) { | 516 | InResponse::Rejected => self.control.reject(), |
| 430 | (RequestType::Standard, Request::GET_STATUS) => { | 517 | }, |
| 431 | handler.get_status(self.control_buf) | ||
| 432 | } | ||
| 433 | (RequestType::Standard, Request::GET_INTERFACE) => { | ||
| 434 | handler.get_interface(self.control_buf) | ||
| 435 | } | ||
| 436 | _ => handler.control_in(req, self.control_buf), | ||
| 437 | }; | ||
| 438 | |||
| 439 | match response { | ||
| 440 | InResponse::Accepted(data) => self.control.accept_in(data, stage).await, | ||
| 441 | InResponse::Rejected => self.control.reject(), | ||
| 442 | } | ||
| 443 | } | ||
| 444 | None => self.control.reject(), | 518 | None => self.control.reject(), |
| 445 | } | 519 | } |
| 446 | } | 520 | } |
diff --git a/embassy-usb/src/types.rs b/embassy-usb/src/types.rs index 9d00e46cb..b8717ffa9 100644 --- a/embassy-usb/src/types.rs +++ b/embassy-usb/src/types.rs | |||
| @@ -106,7 +106,7 @@ pub struct EndpointInfo { | |||
| 106 | /// A handle for a USB interface that contains its number. | 106 | /// A handle for a USB interface that contains its number. |
| 107 | #[derive(Copy, Clone, Eq, PartialEq)] | 107 | #[derive(Copy, Clone, Eq, PartialEq)] |
| 108 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 108 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 109 | pub struct InterfaceNumber(u8); | 109 | pub struct InterfaceNumber(pub(crate) u8); |
| 110 | 110 | ||
| 111 | impl InterfaceNumber { | 111 | impl InterfaceNumber { |
| 112 | pub(crate) fn new(index: u8) -> InterfaceNumber { | 112 | pub(crate) fn new(index: u8) -> InterfaceNumber { |
