Skip to content

Commit 4011503

Browse files
committed
usb: Make driver generic over max interfaces
It would be nice if a default value could be used so old code would mostly just work, but defaults are not used while determining types so adding a default does nothing here. It would also be nice if we could calculate the number of interfaces needed at compile time, but I'll leave that as an exercise for later. rust-lang/rust#95486 rust-lang/rust#99727 rust-lang/rust#27336
1 parent 5b65b0e commit 4011503

File tree

19 files changed

+50
-48
lines changed

19 files changed

+50
-48
lines changed

embassy-usb-logger/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<const N: usize> UsbLogger<N> {
6767
config.device_protocol = 0x01;
6868
config.composite_with_iads = true;
6969

70-
let mut builder = Builder::new(
70+
let mut builder = Builder::<'d, D, 4>::new(
7171
driver,
7272
config,
7373
&mut state.device_descriptor,

embassy-usb/src/builder.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::control::ControlHandler;
44
use crate::descriptor::{BosWriter, DescriptorWriter};
55
use crate::driver::{Driver, Endpoint, EndpointType};
66
use crate::types::*;
7-
use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
7+
use crate::{DeviceStateHandler, Interface, UsbDevice, STRING_INDEX_CUSTOM_START};
88

99
#[derive(Debug, Copy, Clone)]
1010
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -118,10 +118,10 @@ impl<'a> Config<'a> {
118118
}
119119

120120
/// [`UsbDevice`] builder.
121-
pub struct Builder<'d, D: Driver<'d>> {
121+
pub struct Builder<'d, D: Driver<'d>, const I: usize> {
122122
config: Config<'d>,
123123
handler: Option<&'d dyn DeviceStateHandler>,
124-
interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
124+
interfaces: Vec<Interface<'d>, I>,
125125
control_buf: &'d mut [u8],
126126

127127
driver: D,
@@ -132,7 +132,7 @@ pub struct Builder<'d, D: Driver<'d>> {
132132
bos_descriptor: BosWriter<'d>,
133133
}
134134

135-
impl<'d, D: Driver<'d>> Builder<'d, D> {
135+
impl<'d, D: Driver<'d>, const I: usize> Builder<'d, D, I> {
136136
/// Creates a builder for constructing a new [`UsbDevice`].
137137
///
138138
/// `control_buf` is a buffer used for USB control request data. It should be sized
@@ -186,7 +186,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
186186
}
187187

188188
/// Creates the [`UsbDevice`] instance with the configuration in this builder.
189-
pub fn build(mut self) -> UsbDevice<'d, D> {
189+
pub fn build(mut self) -> UsbDevice<'d, D, I> {
190190
self.config_descriptor.end_configuration();
191191
self.bos_descriptor.end_bos();
192192

@@ -214,7 +214,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
214214
/// with the given class/subclass/protocol, associating all the child interfaces.
215215
///
216216
/// If it's not set, no IAD descriptor is added.
217-
pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D> {
217+
pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D, I> {
218218
let iface_count_index = if self.config.composite_with_iads {
219219
self.config_descriptor.iad(
220220
InterfaceNumber::new(self.interfaces.len() as _),
@@ -241,16 +241,16 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
241241
/// A function is a logical grouping of interfaces that perform a given USB function.
242242
/// If [`Config::composite_with_iads`] is set, each function will have an IAD descriptor.
243243
/// If not, functions will not be visible as descriptors.
244-
pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> {
245-
builder: &'a mut Builder<'d, D>,
244+
pub struct FunctionBuilder<'a, 'd, D: Driver<'d>, const I: usize> {
245+
builder: &'a mut Builder<'d, D, I>,
246246
iface_count_index: Option<usize>,
247247
}
248248

249-
impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
249+
impl<'a, 'd, D: Driver<'d>, const I: usize> FunctionBuilder<'a, 'd, D, I> {
250250
/// Add an interface to the function.
251251
///
252252
/// Interface numbers are guaranteed to be allocated consecutively, starting from 0.
253-
pub fn interface(&mut self) -> InterfaceBuilder<'_, 'd, D> {
253+
pub fn interface(&mut self) -> InterfaceBuilder<'_, 'd, D, I> {
254254
if let Some(i) = self.iface_count_index {
255255
self.builder.config_descriptor.buf[i] += 1;
256256
}
@@ -276,13 +276,13 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
276276
}
277277

278278
/// Interface builder.
279-
pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> {
280-
builder: &'a mut Builder<'d, D>,
279+
pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>, const I: usize> {
280+
builder: &'a mut Builder<'d, D, I>,
281281
interface_number: InterfaceNumber,
282282
next_alt_setting_number: u8,
283283
}
284284

285-
impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
285+
impl<'a, 'd, D: Driver<'d>, const I: usize> InterfaceBuilder<'a, 'd, D, I> {
286286
/// Get the interface number.
287287
pub fn interface_number(&self) -> InterfaceNumber {
288288
self.interface_number
@@ -306,7 +306,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
306306
/// Alternate setting numbers are guaranteed to be allocated consecutively, starting from 0.
307307
///
308308
/// The first alternate setting, with number 0, is the default one.
309-
pub fn alt_setting(&mut self, class: u8, subclass: u8, protocol: u8) -> InterfaceAltBuilder<'_, 'd, D> {
309+
pub fn alt_setting(&mut self, class: u8, subclass: u8, protocol: u8) -> InterfaceAltBuilder<'_, 'd, D, I> {
310310
let number = self.next_alt_setting_number;
311311
self.next_alt_setting_number += 1;
312312
self.builder.interfaces[self.interface_number.0 as usize].num_alt_settings += 1;
@@ -324,13 +324,13 @@ impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
324324
}
325325

326326
/// Interface alternate setting builder.
327-
pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> {
328-
builder: &'a mut Builder<'d, D>,
327+
pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>, const I: usize> {
328+
builder: &'a mut Builder<'d, D, I>,
329329
interface_number: InterfaceNumber,
330330
alt_setting_number: u8,
331331
}
332332

333-
impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
333+
impl<'a, 'd, D: Driver<'d>, const I: usize> InterfaceAltBuilder<'a, 'd, D, I> {
334334
/// Get the interface number.
335335
pub fn interface_number(&self) -> InterfaceNumber {
336336
self.interface_number

embassy-usb/src/class/cdc_acm.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,11 @@ impl<'d> ControlHandler for Control<'d> {
158158
impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
159159
/// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For
160160
/// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64.
161-
pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self {
161+
pub fn new<const I: usize>(
162+
builder: &mut Builder<'d, D, I>,
163+
state: &'d mut State<'d>,
164+
max_packet_size: u16,
165+
) -> Self {
162166
let control = state.control.write(Control { shared: &state.shared });
163167

164168
let control_shared = &state.shared;

embassy-usb/src/class/cdc_ncm/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ pub struct CdcNcmClass<'d, D: Driver<'d>> {
236236
}
237237

238238
impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
239-
pub fn new(
240-
builder: &mut Builder<'d, D>,
239+
pub fn new<const I: usize>(
240+
builder: &mut Builder<'d, D, I>,
241241
state: &'d mut State<'d>,
242242
mac_address: [u8; 6],
243243
max_packet_size: u16,

embassy-usb/src/class/hid.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ pub struct HidReaderWriter<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N
8484
writer: HidWriter<'d, D, WRITE_N>,
8585
}
8686

87-
fn build<'d, D: Driver<'d>>(
88-
builder: &mut Builder<'d, D>,
87+
fn build<'d, D: Driver<'d>, const I: usize>(
88+
builder: &mut Builder<'d, D, I>,
8989
state: &'d mut State<'d>,
9090
config: Config<'d>,
9191
with_out_endpoint: bool,
@@ -138,7 +138,7 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> HidReaderWrit
138138
/// This will allocate one IN and one OUT endpoints. If you only need writing (sending)
139139
/// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only.
140140
///
141-
pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
141+
pub fn new<const I: usize>(builder: &mut Builder<'d, D, I>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
142142
let (ep_out, ep_in, offset) = build(builder, state, config, true);
143143

144144
Self {
@@ -217,7 +217,7 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> {
217217
/// HID reports. A lower value means better throughput & latency, at the expense
218218
/// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for
219219
/// high performance uses, and a value of 255 is good for best-effort usecases.
220-
pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
220+
pub fn new<const I: usize>(builder: &mut Builder<'d, D, I>, state: &'d mut State<'d>, config: Config<'d>) -> Self {
221221
let (ep_out, ep_in, _offset) = build(builder, state, config, false);
222222

223223
assert!(ep_out.is_none());

embassy-usb/src/descriptor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl<'a> BosWriter<'a> {
313313
let blen = data.len();
314314

315315
if (start + blen + 3) > self.writer.buf.len() || (blen + 3) > 255 {
316-
panic!("Descriptor buffer full");
316+
panic!("BOS descriptor buffer full");
317317
}
318318

319319
self.writer.buf[start] = (blen + 3) as u8;

embassy-usb/src/lib.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ pub const CONFIGURATION_NONE: u8 = 0;
6565
/// The bConfiguration value for the single configuration supported by this device.
6666
pub const CONFIGURATION_VALUE: u8 = 1;
6767

68-
pub const MAX_INTERFACE_COUNT: usize = 4;
69-
7068
const STRING_INDEX_MANUFACTURER: u8 = 1;
7169
const STRING_INDEX_PRODUCT: u8 = 2;
7270
const STRING_INDEX_SERIAL_NUMBER: u8 = 3;
@@ -100,13 +98,13 @@ struct Interface<'d> {
10098
num_strings: u8,
10199
}
102100

103-
pub struct UsbDevice<'d, D: Driver<'d>> {
101+
pub struct UsbDevice<'d, D: Driver<'d>, const I: usize> {
104102
control_buf: &'d mut [u8],
105103
control: D::ControlPipe,
106-
inner: Inner<'d, D>,
104+
inner: Inner<'d, D, I>,
107105
}
108106

109-
struct Inner<'d, D: Driver<'d>> {
107+
struct Inner<'d, D: Driver<'d>, const I: usize> {
110108
bus: D::Bus,
111109
handler: Option<&'d dyn DeviceStateHandler>,
112110

@@ -128,20 +126,20 @@ struct Inner<'d, D: Driver<'d>> {
128126
/// If true, do a set_addr after finishing the current control req.
129127
set_address_pending: bool,
130128

131-
interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
129+
interfaces: Vec<Interface<'d>, I>,
132130
}
133131

134-
impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
132+
impl<'d, D: Driver<'d>, const I: usize> UsbDevice<'d, D, I> {
135133
pub(crate) fn build(
136134
driver: D,
137135
config: Config<'d>,
138136
handler: Option<&'d dyn DeviceStateHandler>,
139137
device_descriptor: &'d [u8],
140138
config_descriptor: &'d [u8],
141139
bos_descriptor: &'d [u8],
142-
interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
140+
interfaces: Vec<Interface<'d>, I>,
143141
control_buf: &'d mut [u8],
144-
) -> UsbDevice<'d, D> {
142+
) -> UsbDevice<'d, D, I> {
145143
// Start the USB bus.
146144
// This prevent further allocation by consuming the driver.
147145
let (bus, control) = driver.start(config.max_packet_size_0 as u16);
@@ -334,7 +332,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
334332
}
335333
}
336334

337-
impl<'d, D: Driver<'d>> Inner<'d, D> {
335+
impl<'d, D: Driver<'d>, const I: usize> Inner<'d, D, I> {
338336
async fn handle_bus_event(&mut self, evt: Event) {
339337
match evt {
340338
Event::Reset => {

examples/nrf/src/bin/usb_ethernet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ macro_rules! singleton {
3232
const MTU: usize = 1514;
3333

3434
#[embassy_executor::task]
35-
async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! {
35+
async fn usb_task(mut device: UsbDevice<'static, MyDriver, 4>) -> ! {
3636
device.run().await
3737
}
3838

examples/nrf/src/bin/usb_hid_keyboard.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ async fn main(_spawner: Spawner) {
5656

5757
let mut state = State::new();
5858

59-
let mut builder = Builder::new(
59+
let mut builder = Builder::<'_, _, 4>::new(
6060
driver,
6161
config,
6262
&mut device_descriptor,

examples/nrf/src/bin/usb_hid_mouse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) {
4848

4949
let mut state = State::new();
5050

51-
let mut builder = Builder::new(
51+
let mut builder = Builder::<'_, _, 4>::new(
5252
driver,
5353
config,
5454
&mut device_descriptor,

0 commit comments

Comments
 (0)