Skip to content

Commit 1cd3e0d

Browse files
committed
Constructing the control pipe from a user-provided buffer
1 parent ef539cb commit 1cd3e0d

File tree

7 files changed

+29
-18
lines changed

7 files changed

+29
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ interface.
1616
as this was not intended to be used in the public API.
1717
- If this is problematic, please open an issue in the main `usb-device` repository.
1818
* Changed handling of EP0 state to eliminate unexpected issues with device enumeration
19+
* [breaking] The control pipe is now provided in the `UsbDeviceBuilder` API to allow for user-provided control
20+
pipes. This makes it so that control pipes have configurable sizing.
1921

2022
## [0.3.1] - 2023-11-15
2123

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ rusb = "0.9.1"
2020
rand = "0.8.5"
2121

2222
[features]
23-
# Use a 256 byte buffer for control transfers instead of 128.
24-
control-buffer-256 = []
2523

2624
# Enable logging and tracing via the `log` crate
2725
log = ["dep:log"]

src/control_pipe.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,28 @@ enum ControlState {
2020
Error,
2121
}
2222

23-
// Maximum length of control transfer data stage in bytes. 128 bytes by default. You can define the
24-
// feature "control-buffer-256" to make it 256 bytes if you have larger control transfers.
25-
#[cfg(not(feature = "control-buffer-256"))]
26-
const CONTROL_BUF_LEN: usize = 128;
27-
#[cfg(feature = "control-buffer-256")]
28-
const CONTROL_BUF_LEN: usize = 256;
29-
3023
/// Buffers and parses USB control transfers.
3124
pub struct ControlPipe<'a, B: UsbBus> {
3225
ep_out: EndpointOut<'a, B>,
3326
ep_in: EndpointIn<'a, B>,
3427
state: ControlState,
35-
buf: [u8; CONTROL_BUF_LEN],
28+
buf: &'a mut [u8],
3629
static_in_buf: Option<&'static [u8]>,
3730
i: usize,
3831
len: usize,
3932
}
4033

4134
impl<B: UsbBus> ControlPipe<'_, B> {
42-
pub fn new<'a>(ep_out: EndpointOut<'a, B>, ep_in: EndpointIn<'a, B>) -> ControlPipe<'a, B> {
35+
pub fn new<'a>(
36+
buf: &'a mut [u8],
37+
ep_out: EndpointOut<'a, B>,
38+
ep_in: EndpointIn<'a, B>,
39+
) -> ControlPipe<'a, B> {
4340
ControlPipe {
4441
ep_out,
4542
ep_in,
4643
state: ControlState::Idle,
47-
buf: [0; CONTROL_BUF_LEN],
44+
buf,
4845
static_in_buf: None,
4946
i: 0,
5047
len: 0,

src/device.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@ pub const DEFAULT_ALTERNATE_SETTING: u8 = 0;
8282
type ClassList<'a, B> = [&'a mut dyn UsbClass<B>];
8383

8484
impl<B: UsbBus> UsbDevice<'_, B> {
85-
pub(crate) fn build<'a>(alloc: &'a UsbBusAllocator<B>, config: Config<'a>) -> UsbDevice<'a, B> {
85+
pub(crate) fn build<'a>(
86+
alloc: &'a UsbBusAllocator<B>,
87+
config: Config<'a>,
88+
control_buffer: &'a mut [u8],
89+
) -> UsbDevice<'a, B> {
8690
let control_out = alloc
8791
.alloc(
8892
Some(0x00.into()),
@@ -106,7 +110,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
106110
UsbDevice {
107111
bus,
108112
config,
109-
control: ControlPipe::new(control_out, control_in),
113+
control: ControlPipe::new(control_buffer, control_out, control_in),
110114
device_state: UsbDeviceState::Default,
111115
remote_wakeup_enabled: false,
112116
self_powered: false,

src/device_builder.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct UsbVidPid(pub u16, pub u16);
88
/// Used to build new [`UsbDevice`]s.
99
pub struct UsbDeviceBuilder<'a, B: UsbBus> {
1010
alloc: &'a UsbBusAllocator<B>,
11+
control_buffer: &'a mut [u8],
1112
config: Config<'a>,
1213
}
1314

@@ -82,9 +83,14 @@ impl<'a> StringDescriptors<'a> {
8283

8384
impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
8485
/// Creates a builder for constructing a new [`UsbDevice`].
85-
pub fn new(alloc: &'a UsbBusAllocator<B>, vid_pid: UsbVidPid) -> UsbDeviceBuilder<'a, B> {
86+
pub fn new(
87+
alloc: &'a UsbBusAllocator<B>,
88+
vid_pid: UsbVidPid,
89+
control_buffer: &'a mut [u8],
90+
) -> UsbDeviceBuilder<'a, B> {
8691
UsbDeviceBuilder {
8792
alloc,
93+
control_buffer,
8894
config: Config {
8995
device_class: 0x00,
9096
device_sub_class: 0x00,
@@ -105,7 +111,7 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
105111

106112
/// Creates the [`UsbDevice`] instance with the configuration in this builder.
107113
pub fn build(self) -> UsbDevice<'a, B> {
108-
UsbDevice::build(self.alloc, self.config)
114+
UsbDevice::build(self.alloc, self.config, self.control_buffer)
109115
}
110116

111117
builder_fields! {

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ pub mod endpoint;
137137
/// use usb_device::prelude::*;
138138
/// use usb_serial; // example class crate (not included)
139139
///
140+
/// static mut CONTROL_BUFFER: [u8; 128] = [0; 128];
141+
///
140142
/// // Create the device-specific USB peripheral driver. The exact name and arguments are device
141143
/// // specific, so check the documentation for your device driver crate.
142144
/// let usb_bus = device_specific_usb::UsbBus::new(...);
@@ -151,7 +153,7 @@ pub mod endpoint;
151153
/// // pair. Additional builder arguments can specify parameters such as device class code or
152154
/// // product name. If using an existing class, remember to check the class crate documentation
153155
/// // for correct values.
154-
/// let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x5824, 0x27dd))
156+
/// let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x5824, 0x27dd), unsafe { &mut CONTROL_BUFFER })
155157
/// .strings(&[StringDescriptors::new(LangID::EN)
156158
/// .product("Serial port")])
157159
/// .expect("Failed to set strings")

src/test_class.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ mod sizes {
2222
pub const INTERRUPT_ENDPOINT: u16 = 31;
2323
}
2424

25+
static mut CONTROL_BUFFER: [u8; 256] = [0; 256];
26+
2527
/// Test USB class for testing USB driver implementations. Supports various endpoint types and
2628
/// requests for testing USB peripheral drivers on actual hardware.
2729
pub struct TestClass<'a, B: UsbBus> {
@@ -112,7 +114,7 @@ impl<B: UsbBus> TestClass<'_, B> {
112114
&self,
113115
usb_bus: &'a UsbBusAllocator<B>,
114116
) -> UsbDeviceBuilder<'a, B> {
115-
UsbDeviceBuilder::new(usb_bus, UsbVidPid(VID, PID))
117+
UsbDeviceBuilder::new(usb_bus, UsbVidPid(VID, PID), unsafe { &mut CONTROL_BUFFER })
116118
.strings(&[StringDescriptors::default()
117119
.manufacturer(MANUFACTURER)
118120
.product(PRODUCT)

0 commit comments

Comments
 (0)