diff options
| author | alexmoon <[email protected]> | 2022-03-29 15:09:24 -0400 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-04-06 05:38:11 +0200 |
| commit | 13370c28db244edd24029d6066ac9e448bd419c9 (patch) | |
| tree | 4728f35654af719466c52446ae3bd9fb58524793 | |
| parent | c53bb7394a20e180e2ac7e81cc468025018bd1da (diff) | |
Add a control_buf to UsbDevice
| -rw-r--r-- | embassy-usb/src/builder.rs | 14 | ||||
| -rw-r--r-- | embassy-usb/src/control.rs | 2 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 10 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb/cdc_acm.rs | 19 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb/main.rs | 2 |
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> { | |||
| 120 | pub struct UsbDeviceBuilder<'d, D: Driver<'d>> { | 120 | pub 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 | ||
| 134 | impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | 135 | impl<'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 | ||
| 67 | struct Control<'a> { | 67 | struct 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 | ||
| 100 | impl<'a> ControlHandler for Control<'a> { | 99 | impl<'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. |
