aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-04-16 04:47:27 +0200
committerDario Nieuwenhuis <[email protected]>2022-04-23 01:11:10 +0200
commit092c2b7dfea146681cea01fd4e4105c21c62b61f (patch)
treebe32635e53177b36ef36939bcdd5eadcf3be3ab8
parentea0a701ebd142ea42e05e51e844bd53cc9bdf354 (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.rs110
-rw-r--r--embassy-usb-hid/src/lib.rs21
-rw-r--r--embassy-usb/src/builder.rs23
-rw-r--r--embassy-usb/src/control.rs37
-rw-r--r--embassy-usb/src/descriptor.rs4
-rw-r--r--embassy-usb/src/descriptor_reader.rs110
-rw-r--r--embassy-usb/src/driver.rs10
-rw-r--r--embassy-usb/src/lib.rs188
-rw-r--r--embassy-usb/src/types.rs2
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
203pub struct Bus<'d, T: Instance> { 201pub 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
209impl<'d, T: Instance> driver::Bus for Bus<'d, T> { 205impl<'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 @@
1use heapless::Vec; 1use heapless::Vec;
2 2
3use crate::Interface;
4
3use super::control::ControlHandler; 5use super::control::ControlHandler;
4use super::descriptor::{BosWriter, DescriptorWriter}; 6use super::descriptor::{BosWriter, DescriptorWriter};
5use super::driver::{Driver, Endpoint}; 7use super::driver::{Driver, Endpoint};
@@ -121,11 +123,10 @@ impl<'a> Config<'a> {
121pub struct Builder<'d, D: Driver<'d>> { 123pub 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
3use crate::descriptor::DescriptorWriter; 3use crate::descriptor::DescriptorWriter;
4use crate::driver::{self, EndpointError}; 4use crate::driver::{self, EndpointError};
5use crate::DEFAULT_ALTERNATE_SETTING;
6 5
7use super::types::*; 6use 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 @@
1use super::builder::Config; 1use super::builder::Config;
2use super::{types::*, CONFIGURATION_VALUE, DEFAULT_ALTERNATE_SETTING}; 2use 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 @@
1use crate::descriptor::descriptor_type;
2use crate::types::EndpointAddress;
3
4#[derive(Copy, Clone, PartialEq, Eq, Debug)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub struct ReadError;
7
8pub struct Reader<'a> {
9 data: &'a [u8],
10}
11
12impl<'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
45pub struct DescriptorIter<'a, 'b> {
46 r: &'a mut Reader<'b>,
47}
48
49impl<'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))]
76pub struct EndpointInfo {
77 pub configuration: u8,
78 pub interface: u8,
79 pub interface_alt: u8,
80 pub ep_address: EndpointAddress,
81}
82
83pub 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;
8mod builder; 8mod builder;
9pub mod control; 9pub mod control;
10pub mod descriptor; 10pub mod descriptor;
11mod descriptor_reader;
11pub mod driver; 12pub mod driver;
12pub mod types; 13pub mod types;
13 14
14use embassy::util::{select, Either}; 15use embassy::util::{select, Either};
15use heapless::Vec; 16use heapless::Vec;
16 17
18use crate::descriptor_reader::foreach_endpoint;
19
17use self::control::*; 20use self::control::*;
18use self::descriptor::*; 21use self::descriptor::*;
19use self::driver::{Bus, Driver, Event}; 22use 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.
62pub const CONFIGURATION_VALUE: u8 = 1; 65pub const CONFIGURATION_VALUE: u8 = 1;
63 66
64/// The default value for bAlternateSetting for all interfaces.
65pub const DEFAULT_ALTERNATE_SETTING: u8 = 0;
66
67pub const MAX_INTERFACE_COUNT: usize = 4; 67pub 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
90struct Interface<'d> {
91 handler: Option<&'d mut dyn ControlHandler>,
92 current_alt_setting: u8,
93 num_alt_settings: u8,
94}
95
90pub struct UsbDevice<'d, D: Driver<'d>> { 96pub 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
110impl<'d, D: Driver<'d>> UsbDevice<'d, D> { 116impl<'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))]
109pub struct InterfaceNumber(u8); 109pub struct InterfaceNumber(pub(crate) u8);
110 110
111impl InterfaceNumber { 111impl InterfaceNumber {
112 pub(crate) fn new(index: u8) -> InterfaceNumber { 112 pub(crate) fn new(index: u8) -> InterfaceNumber {