Skip to content

Commit 11143a1

Browse files
authored
Merge pull request #722 from embassy-rs/usb-altsettings
usb: builtin handling of interface alternate settings
2 parents afb4f86 + 7778b79 commit 11143a1

File tree

11 files changed

+426
-168
lines changed

11 files changed

+426
-168
lines changed

embassy-nrf/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ flavors = [
1717

1818
[features]
1919

20+
defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt"]
21+
2022
# Enable nightly-only features
2123
nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async"]
2224

embassy-nrf/src/usb.rs

Lines changed: 67 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,12 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
194194
fn into_bus(self) -> Self::Bus {
195195
Bus {
196196
phantom: PhantomData,
197-
alloc_in: self.alloc_in,
198-
alloc_out: self.alloc_out,
199197
}
200198
}
201199
}
202200

203201
pub struct Bus<'d, T: Instance> {
204202
phantom: PhantomData<&'d mut T>,
205-
alloc_in: Allocator,
206-
alloc_out: Allocator,
207203
}
208204

209205
impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
@@ -264,7 +260,16 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
264260
if regs.events_usbreset.read().bits() != 0 {
265261
regs.events_usbreset.reset();
266262
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+
268273
return Poll::Ready(Event::Reset);
269274
}
270275

@@ -297,57 +302,76 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
297302
}
298303

299304
#[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) {
301318
let regs = T::regs();
302319

303-
unsafe {
304-
if configured {
305-
// TODO: Initialize ISO buffers
320+
let i = ep_addr.index();
321+
let mask = 1 << i;
306322

307-
regs.epinen.write(|w| w.bits(self.alloc_in.used.into()));
308-
regs.epouten.write(|w| w.bits(self.alloc_out.used.into()));
323+
debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled);
309324

310-
for i in 1..8 {
311-
let out_enabled = self.alloc_out.used & (1 << i) != 0;
325+
match ep_addr.direction() {
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+
});
312338

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 {
313363
// when first enabled, bulk/interrupt OUT endpoints will *not* receive data (the
314364
// peripheral will NAK all incoming packets) until we write a zero to the SIZE
315365
// register (see figure 203 of the 52840 manual). To avoid that we write a 0 to the
316366
// SIZE register
317-
if out_enabled {
318-
regs.size.epout[i].reset();
319-
}
367+
regs.size.epout[i].reset();
368+
} else {
369+
READY_ENDPOINTS.fetch_and(!ready_mask, Ordering::AcqRel);
320370
}
321371

322-
// IN endpoints (low bits) default to ready.
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);
372+
Out::waker(i).wake();
331373
}
332374
}
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)
351375
}
352376

353377
#[inline]

embassy-usb-hid/src/lib.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ fn build<'d, D: Driver<'d>>(
112112
let len = config.report_descriptor.len();
113113

114114
let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE);
115-
let mut iface = func.interface(Some(control));
115+
let mut iface = func.interface();
116+
iface.handler(control);
116117
let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE);
117118

118119
// HID descriptor
@@ -438,6 +439,14 @@ impl<'d> ControlHandler for Control<'d> {
438439
self.out_report_offset.store(0, Ordering::Release);
439440
}
440441

442+
fn get_descriptor<'a>(&'a mut self, req: Request, _buf: &'a mut [u8]) -> InResponse<'a> {
443+
match (req.value >> 8) as u8 {
444+
HID_DESC_DESCTYPE_HID_REPORT => InResponse::Accepted(self.report_descriptor),
445+
HID_DESC_DESCTYPE_HID => InResponse::Accepted(&self.hid_descriptor),
446+
_ => InResponse::Rejected,
447+
}
448+
}
449+
441450
fn control_out(&mut self, req: embassy_usb::control::Request, data: &[u8]) -> OutResponse {
442451
trace!("HID control_out {:?} {=[u8]:x}", req, data);
443452
if let RequestType::Class = req.request_type {
@@ -477,13 +486,8 @@ impl<'d> ControlHandler for Control<'d> {
477486

478487
fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
479488
trace!("HID control_in {:?}", req);
480-
match (req.request_type, req.request) {
481-
(RequestType::Standard, Request::GET_DESCRIPTOR) => match (req.value >> 8) as u8 {
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) => {
489+
match req.request {
490+
HID_REQ_GET_REPORT => {
487491
let size = match ReportId::try_from(req.value) {
488492
Ok(id) => self.request_handler.and_then(|x| x.get_report(id, buf)),
489493
Err(_) => None,
@@ -495,7 +499,7 @@ impl<'d> ControlHandler for Control<'d> {
495499
InResponse::Rejected
496500
}
497501
}
498-
(RequestType::Class, HID_REQ_GET_IDLE) => {
502+
HID_REQ_GET_IDLE => {
499503
if let Some(handler) = self.request_handler {
500504
let id = req.value as u8;
501505
let id = (id != 0).then(|| ReportId::In(id));
@@ -510,7 +514,7 @@ impl<'d> ControlHandler for Control<'d> {
510514
InResponse::Rejected
511515
}
512516
}
513-
(RequestType::Class, HID_REQ_GET_PROTOCOL) => {
517+
HID_REQ_GET_PROTOCOL => {
514518
// UNSUPPORTED: Boot Protocol
515519
buf[0] = 1;
516520
InResponse::Accepted(&buf[0..1])

embassy-usb-serial/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
178178
let mut func = builder.function(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE);
179179

180180
// Control interface
181-
let mut iface = func.interface(Some(control));
181+
let mut iface = func.interface();
182+
iface.handler(control);
182183
let comm_if = iface.interface_number();
183184
let data_if = u8::from(comm_if) + 1;
184185
let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE);
@@ -218,7 +219,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
218219
let comm_ep = alt.endpoint_interrupt_in(8, 255);
219220

220221
// Data interface
221-
let mut iface = func.interface(None);
222+
let mut iface = func.interface();
222223
let data_if = iface.interface_number();
223224
let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE);
224225
let read_ep = alt.endpoint_bulk_out(max_packet_size);

embassy-usb/src/builder.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use heapless::Vec;
22

3+
use crate::{Interface, STRING_INDEX_CUSTOM_START};
4+
35
use super::control::ControlHandler;
46
use super::descriptor::{BosWriter, DescriptorWriter};
57
use super::driver::{Driver, Endpoint};
@@ -121,11 +123,10 @@ impl<'a> Config<'a> {
121123
pub struct Builder<'d, D: Driver<'d>> {
122124
config: Config<'d>,
123125
handler: Option<&'d dyn DeviceStateHandler>,
124-
interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
126+
interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
125127
control_buf: &'d mut [u8],
126128

127129
driver: D,
128-
next_interface_number: u8,
129130
next_string_index: u8,
130131

131132
device_descriptor: DescriptorWriter<'d>,
@@ -180,8 +181,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
180181
config,
181182
interfaces: Vec::new(),
182183
control_buf,
183-
next_interface_number: 0,
184-
next_string_index: 4,
184+
next_string_index: STRING_INDEX_CUSTOM_START,
185185

186186
device_descriptor,
187187
config_descriptor,
@@ -212,14 +212,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
212212
self.control_buf.len()
213213
}
214214

215-
/// Allocates a new string index.
216-
pub fn alloc_string(&mut self) -> StringIndex {
217-
let index = self.next_string_index;
218-
self.next_string_index += 1;
219-
220-
StringIndex::new(index)
221-
}
222-
223215
/// Add an USB function.
224216
///
225217
/// If [`Config::composite_with_iads`] is set, this will add an IAD descriptor
@@ -234,7 +226,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
234226
) -> FunctionBuilder<'_, 'd, D> {
235227
let iface_count_index = if self.config.composite_with_iads {
236228
self.config_descriptor.iad(
237-
InterfaceNumber::new(self.next_interface_number),
229+
InterfaceNumber::new(self.interfaces.len() as _),
238230
0,
239231
class,
240232
subclass,
@@ -267,21 +259,21 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
267259
/// Add an interface to the function.
268260
///
269261
/// Interface numbers are guaranteed to be allocated consecutively, starting from 0.
270-
pub fn interface(
271-
&mut self,
272-
handler: Option<&'d mut dyn ControlHandler>,
273-
) -> InterfaceBuilder<'_, 'd, D> {
262+
pub fn interface(&mut self) -> InterfaceBuilder<'_, 'd, D> {
274263
if let Some(i) = self.iface_count_index {
275264
self.builder.config_descriptor.buf[i] += 1;
276265
}
277266

278-
let number = self.builder.next_interface_number;
279-
self.builder.next_interface_number += 1;
267+
let number = self.builder.interfaces.len() as _;
268+
let iface = Interface {
269+
handler: None,
270+
current_alt_setting: 0,
271+
num_alt_settings: 0,
272+
num_strings: 0,
273+
};
280274

281-
if let Some(handler) = handler {
282-
if self.builder.interfaces.push((number, handler)).is_err() {
283-
panic!("max interface count reached")
284-
}
275+
if self.builder.interfaces.push(iface).is_err() {
276+
panic!("max interface count reached")
285277
}
286278

287279
InterfaceBuilder {
@@ -305,6 +297,19 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
305297
self.interface_number
306298
}
307299

300+
pub fn handler(&mut self, handler: &'d mut dyn ControlHandler) {
301+
self.builder.interfaces[self.interface_number.0 as usize].handler = Some(handler);
302+
}
303+
304+
/// Allocates a new string index.
305+
pub fn string(&mut self) -> StringIndex {
306+
let index = self.builder.next_string_index;
307+
self.builder.next_string_index += 1;
308+
self.builder.interfaces[self.interface_number.0 as usize].num_strings += 1;
309+
310+
StringIndex::new(index)
311+
}
312+
308313
/// Add an alternate setting to the interface and write its descriptor.
309314
///
310315
/// Alternate setting numbers are guaranteed to be allocated consecutively, starting from 0.
@@ -318,6 +323,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
318323
) -> InterfaceAltBuilder<'_, 'd, D> {
319324
let number = self.next_alt_setting_number;
320325
self.next_alt_setting_number += 1;
326+
self.builder.interfaces[self.interface_number.0 as usize].num_alt_settings += 1;
321327

322328
self.builder.config_descriptor.interface_alt(
323329
self.interface_number,

0 commit comments

Comments
 (0)