aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2022-03-29 15:09:24 -0400
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commit13370c28db244edd24029d6066ac9e448bd419c9 (patch)
tree4728f35654af719466c52446ae3bd9fb58524793
parentc53bb7394a20e180e2ac7e81cc468025018bd1da (diff)
Add a control_buf to UsbDevice
-rw-r--r--embassy-usb/src/builder.rs14
-rw-r--r--embassy-usb/src/control.rs2
-rw-r--r--embassy-usb/src/lib.rs10
-rw-r--r--examples/nrf/src/bin/usb/cdc_acm.rs19
-rw-r--r--examples/nrf/src/bin/usb/main.rs2
5 files changed, 33 insertions, 14 deletions
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index dfd36bdb3..0c118b782 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -120,6 +120,7 @@ impl<'a> Config<'a> {
120pub struct UsbDeviceBuilder<'d, D: Driver<'d>> { 120pub struct UsbDeviceBuilder<'d, D: Driver<'d>> {
121 config: Config<'d>, 121 config: Config<'d>,
122 interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, 122 interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
123 control_buf: &'d mut [u8],
123 124
124 bus: D, 125 bus: D,
125 next_interface_number: u8, 126 next_interface_number: u8,
@@ -133,12 +134,17 @@ pub struct UsbDeviceBuilder<'d, D: Driver<'d>> {
133 134
134impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { 135impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
135 /// Creates a builder for constructing a new [`UsbDevice`]. 136 /// Creates a builder for constructing a new [`UsbDevice`].
137 ///
138 /// `control_buf` is a buffer used for USB control request data. It should be sized
139 /// large enough for the length of the largest control request (in or out)
140 /// anticipated by any class added to the device.
136 pub fn new( 141 pub fn new(
137 bus: D, 142 bus: D,
138 config: Config<'d>, 143 config: Config<'d>,
139 device_descriptor_buf: &'d mut [u8], 144 device_descriptor_buf: &'d mut [u8],
140 config_descriptor_buf: &'d mut [u8], 145 config_descriptor_buf: &'d mut [u8],
141 bos_descriptor_buf: &'d mut [u8], 146 bos_descriptor_buf: &'d mut [u8],
147 control_buf: &'d mut [u8],
142 ) -> Self { 148 ) -> Self {
143 // Magic values specified in USB-IF ECN on IADs. 149 // Magic values specified in USB-IF ECN on IADs.
144 if config.composite_with_iads 150 if config.composite_with_iads
@@ -170,6 +176,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
170 bus, 176 bus,
171 config, 177 config,
172 interfaces: Vec::new(), 178 interfaces: Vec::new(),
179 control_buf,
173 next_interface_number: 0, 180 next_interface_number: 0,
174 next_string_index: 4, 181 next_string_index: 4,
175 182
@@ -191,6 +198,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
191 self.config_descriptor.into_buf(), 198 self.config_descriptor.into_buf(),
192 self.bos_descriptor.writer.into_buf(), 199 self.bos_descriptor.writer.into_buf(),
193 self.interfaces, 200 self.interfaces,
201 self.control_buf,
194 ) 202 )
195 } 203 }
196 204
@@ -202,6 +210,12 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
202 InterfaceNumber::new(number) 210 InterfaceNumber::new(number)
203 } 211 }
204 212
213 /// Returns the size of the control request data buffer. Can be used by
214 /// classes to validate the buffer is large enough for their needs.
215 pub fn control_buf_len(&self) -> usize {
216 self.control_buf.len()
217 }
218
205 /// Allocates a new interface number, with a handler that will be called 219 /// Allocates a new interface number, with a handler that will be called
206 /// for all the control requests directed to it. 220 /// for all the control requests directed to it.
207 pub fn alloc_interface_with_handler( 221 pub fn alloc_interface_with_handler(
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index 195b218dc..19c2c6776 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -164,7 +164,7 @@ pub trait ControlHandler {
164 /// # Arguments 164 /// # Arguments
165 /// 165 ///
166 /// * `req` - The request from the SETUP packet. 166 /// * `req` - The request from the SETUP packet.
167 fn control_in(&mut self, req: Request) -> InResponse<'_> { 167 fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
168 InResponse::Rejected 168 InResponse::Rejected
169 } 169 }
170} 170}
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 5a82f5cae..a4b7dda30 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -61,6 +61,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> {
61 device_descriptor: &'d [u8], 61 device_descriptor: &'d [u8],
62 config_descriptor: &'d [u8], 62 config_descriptor: &'d [u8],
63 bos_descriptor: &'d [u8], 63 bos_descriptor: &'d [u8],
64 control_buf: &'d mut [u8],
64 65
65 device_state: UsbDeviceState, 66 device_state: UsbDeviceState,
66 remote_wakeup_enabled: bool, 67 remote_wakeup_enabled: bool,
@@ -78,6 +79,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
78 config_descriptor: &'d [u8], 79 config_descriptor: &'d [u8],
79 bos_descriptor: &'d [u8], 80 bos_descriptor: &'d [u8],
80 interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, 81 interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>,
82 control_buf: &'d mut [u8],
81 ) -> Self { 83 ) -> Self {
82 let control = driver 84 let control = driver
83 .alloc_control_pipe(config.max_packet_size_0 as u16) 85 .alloc_control_pipe(config.max_packet_size_0 as u16)
@@ -94,6 +96,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
94 device_descriptor, 96 device_descriptor,
95 config_descriptor, 97 config_descriptor,
96 bos_descriptor, 98 bos_descriptor,
99 control_buf,
97 device_state: UsbDeviceState::Default, 100 device_state: UsbDeviceState::Default,
98 remote_wakeup_enabled: false, 101 remote_wakeup_enabled: false,
99 self_powered: false, 102 self_powered: false,
@@ -204,10 +207,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
204 _ => self.control.reject(), 207 _ => self.control.reject(),
205 }, 208 },
206 (RequestType::Class, Recipient::Interface) => { 209 (RequestType::Class, Recipient::Interface) => {
207 let mut buf = [0; 128];
208 let data = if req.length > 0 { 210 let data = if req.length > 0 {
209 let size = self.control.data_out(&mut buf).await.unwrap(); 211 let size = self.control.data_out(self.control_buf).await.unwrap();
210 &buf[0..size] 212 &self.control_buf[0..size]
211 } else { 213 } else {
212 &[] 214 &[]
213 }; 215 };
@@ -284,7 +286,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
284 .find(|(i, _)| req.index == *i as _) 286 .find(|(i, _)| req.index == *i as _)
285 .map(|(_, h)| h); 287 .map(|(_, h)| h);
286 match handler { 288 match handler {
287 Some(handler) => match handler.control_in(req) { 289 Some(handler) => match handler.control_in(req, self.control_buf) {
288 InResponse::Accepted(data) => self.control.accept_in(data).await, 290 InResponse::Accepted(data) => self.control.accept_in(data).await,
289 InResponse::Rejected => self.control.reject(), 291 InResponse::Rejected => self.control.reject(),
290 }, 292 },
diff --git a/examples/nrf/src/bin/usb/cdc_acm.rs b/examples/nrf/src/bin/usb/cdc_acm.rs
index 2a78324fe..c28681dc4 100644
--- a/examples/nrf/src/bin/usb/cdc_acm.rs
+++ b/examples/nrf/src/bin/usb/cdc_acm.rs
@@ -66,7 +66,6 @@ pub struct CdcAcmClass<'d, D: Driver<'d>> {
66 66
67struct Control<'a> { 67struct Control<'a> {
68 shared: &'a ControlShared, 68 shared: &'a ControlShared,
69 buf: [u8; 7],
70} 69}
71 70
72/// Shared data between Control and CdcAcmClass 71/// Shared data between Control and CdcAcmClass
@@ -97,7 +96,7 @@ impl<'a> Control<'a> {
97 } 96 }
98} 97}
99 98
100impl<'a> ControlHandler for Control<'a> { 99impl<'d> ControlHandler for Control<'d> {
101 fn reset(&mut self) { 100 fn reset(&mut self) {
102 let shared = self.shared(); 101 let shared = self.shared();
103 shared.line_coding.lock(|x| x.set(LineCoding::default())); 102 shared.line_coding.lock(|x| x.set(LineCoding::default()));
@@ -139,17 +138,18 @@ impl<'a> ControlHandler for Control<'a> {
139 } 138 }
140 } 139 }
141 140
142 fn control_in(&mut self, req: Request) -> InResponse<'_> { 141 fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
143 match req.request { 142 match req.request {
144 // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. 143 // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below.
145 REQ_GET_LINE_CODING if req.length == 7 => { 144 REQ_GET_LINE_CODING if req.length == 7 => {
146 info!("Sending line coding"); 145 info!("Sending line coding");
147 let coding = self.shared().line_coding.lock(|x| x.get()); 146 let coding = self.shared().line_coding.lock(|x| x.get());
148 self.buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes()); 147 assert!(buf.len() >= 7);
149 self.buf[4] = coding.stop_bits as u8; 148 buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes());
150 self.buf[5] = coding.parity_type as u8; 149 buf[4] = coding.stop_bits as u8;
151 self.buf[6] = coding.data_bits; 150 buf[5] = coding.parity_type as u8;
152 InResponse::Accepted(&self.buf) 151 buf[6] = coding.data_bits;
152 InResponse::Accepted(&buf[0..7])
153 } 153 }
154 _ => InResponse::Rejected, 154 _ => InResponse::Rejected,
155 } 155 }
@@ -166,11 +166,12 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
166 ) -> Self { 166 ) -> Self {
167 let control = state.control.write(Control { 167 let control = state.control.write(Control {
168 shared: &state.shared, 168 shared: &state.shared,
169 buf: [0; 7],
170 }); 169 });
171 170
172 let control_shared = &state.shared; 171 let control_shared = &state.shared;
173 172
173 assert!(builder.control_buf_len() >= 7);
174
174 let comm_if = builder.alloc_interface_with_handler(control); 175 let comm_if = builder.alloc_interface_with_handler(control);
175 let comm_ep = builder.alloc_interrupt_endpoint_in(8, 255); 176 let comm_ep = builder.alloc_interrupt_endpoint_in(8, 255);
176 let data_if = builder.alloc_interface(); 177 let data_if = builder.alloc_interface();
diff --git a/examples/nrf/src/bin/usb/main.rs b/examples/nrf/src/bin/usb/main.rs
index 398dd07b6..c4b9c0176 100644
--- a/examples/nrf/src/bin/usb/main.rs
+++ b/examples/nrf/src/bin/usb/main.rs
@@ -47,6 +47,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
47 let mut device_descriptor = [0; 256]; 47 let mut device_descriptor = [0; 256];
48 let mut config_descriptor = [0; 256]; 48 let mut config_descriptor = [0; 256];
49 let mut bos_descriptor = [0; 256]; 49 let mut bos_descriptor = [0; 256];
50 let mut control_buf = [0; 7];
50 51
51 let mut state = State::new(); 52 let mut state = State::new();
52 53
@@ -56,6 +57,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
56 &mut device_descriptor, 57 &mut device_descriptor,
57 &mut config_descriptor, 58 &mut config_descriptor,
58 &mut bos_descriptor, 59 &mut bos_descriptor,
60 &mut control_buf,
59 ); 61 );
60 62
61 // Create classes on the builder. 63 // Create classes on the builder.