aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src/lib.rs
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2022-03-25 16:46:14 -0400
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commitbdc6e0481c42d20d5cca19dfc8ec56306e47296e (patch)
tree6beb805dd6ffea30877b654aa42e5c83f5a36c0b /embassy-usb/src/lib.rs
parent5c0db627feae071182dd9978ffb56b0524558d93 (diff)
Add support for USB classes handling control requests.
Diffstat (limited to 'embassy-usb/src/lib.rs')
-rw-r--r--embassy-usb/src/lib.rs169
1 files changed, 67 insertions, 102 deletions
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 95f78804d..4082868fb 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -1,16 +1,19 @@
1#![no_std] 1#![no_std]
2#![feature(generic_associated_types)] 2#![feature(generic_associated_types)]
3#![feature(type_alias_impl_trait)]
3 4
4// This mod MUST go first, so that the others see its macros. 5// This mod MUST go first, so that the others see its macros.
5pub(crate) mod fmt; 6pub(crate) mod fmt;
6 7
7mod builder; 8mod builder;
8mod control; 9pub mod class;
10pub mod control;
9pub mod descriptor; 11pub mod descriptor;
10pub mod driver; 12pub mod driver;
11pub mod types; 13pub mod types;
12mod util; 14mod util;
13 15
16use self::class::{RequestStatus, UsbClass};
14use self::control::*; 17use self::control::*;
15use self::descriptor::*; 18use self::descriptor::*;
16use self::driver::*; 19use self::driver::*;
@@ -48,10 +51,9 @@ pub const CONFIGURATION_VALUE: u8 = 1;
48/// The default value for bAlternateSetting for all interfaces. 51/// The default value for bAlternateSetting for all interfaces.
49pub const DEFAULT_ALTERNATE_SETTING: u8 = 0; 52pub const DEFAULT_ALTERNATE_SETTING: u8 = 0;
50 53
51pub struct UsbDevice<'d, D: Driver<'d>> { 54pub struct UsbDevice<'d, D: Driver<'d>, C: UsbClass<'d, D>> {
52 bus: D::Bus, 55 bus: D::Bus,
53 control_in: D::EndpointIn, 56 control: D::ControlPipe,
54 control_out: D::EndpointOut,
55 57
56 config: Config<'d>, 58 config: Config<'d>,
57 device_descriptor: &'d [u8], 59 device_descriptor: &'d [u8],
@@ -62,32 +64,21 @@ pub struct UsbDevice<'d, D: Driver<'d>> {
62 remote_wakeup_enabled: bool, 64 remote_wakeup_enabled: bool,
63 self_powered: bool, 65 self_powered: bool,
64 pending_address: u8, 66 pending_address: u8,
67
68 classes: C,
65} 69}
66 70
67impl<'d, D: Driver<'d>> UsbDevice<'d, D> { 71impl<'d, D: Driver<'d>, C: UsbClass<'d, D>> UsbDevice<'d, D, C> {
68 pub(crate) fn build( 72 pub(crate) fn build(
69 mut driver: D, 73 mut driver: D,
70 config: Config<'d>, 74 config: Config<'d>,
71 device_descriptor: &'d [u8], 75 device_descriptor: &'d [u8],
72 config_descriptor: &'d [u8], 76 config_descriptor: &'d [u8],
73 bos_descriptor: &'d [u8], 77 bos_descriptor: &'d [u8],
78 classes: C,
74 ) -> Self { 79 ) -> Self {
75 let control_out = driver 80 let control = driver
76 .alloc_endpoint_out( 81 .alloc_control_pipe(config.max_packet_size_0 as u16)
77 Some(0x00.into()),
78 EndpointType::Control,
79 config.max_packet_size_0 as u16,
80 0,
81 )
82 .expect("failed to alloc control endpoint");
83
84 let control_in = driver
85 .alloc_endpoint_in(
86 Some(0x80.into()),
87 EndpointType::Control,
88 config.max_packet_size_0 as u16,
89 0,
90 )
91 .expect("failed to alloc control endpoint"); 82 .expect("failed to alloc control endpoint");
92 83
93 // Enable the USB bus. 84 // Enable the USB bus.
@@ -97,8 +88,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
97 Self { 88 Self {
98 bus: driver, 89 bus: driver,
99 config, 90 config,
100 control_in, 91 control,
101 control_out,
102 device_descriptor, 92 device_descriptor,
103 config_descriptor, 93 config_descriptor,
104 bos_descriptor, 94 bos_descriptor,
@@ -106,14 +96,13 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
106 remote_wakeup_enabled: false, 96 remote_wakeup_enabled: false,
107 self_powered: false, 97 self_powered: false,
108 pending_address: 0, 98 pending_address: 0,
99 classes,
109 } 100 }
110 } 101 }
111 102
112 pub async fn run(&mut self) { 103 pub async fn run(&mut self) {
113 let mut buf = [0; 8];
114
115 loop { 104 loop {
116 let control_fut = self.control_out.read(&mut buf); 105 let control_fut = self.control.setup();
117 let bus_fut = self.bus.poll(); 106 let bus_fut = self.bus.poll();
118 match select(bus_fut, control_fut).await { 107 match select(bus_fut, control_fut).await {
119 Either::Left(evt) => match evt { 108 Either::Left(evt) => match evt {
@@ -124,11 +113,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
124 self.remote_wakeup_enabled = false; 113 self.remote_wakeup_enabled = false;
125 self.pending_address = 0; 114 self.pending_address = 0;
126 115
127 // TODO 116 self.classes.reset();
128 //self.control.reset();
129 //for cls in classes {
130 // cls.reset();
131 //}
132 } 117 }
133 Event::Resume => {} 118 Event::Resume => {}
134 Event::Suspend => { 119 Event::Suspend => {
@@ -136,16 +121,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
136 self.device_state = UsbDeviceState::Suspend; 121 self.device_state = UsbDeviceState::Suspend;
137 } 122 }
138 }, 123 },
139 Either::Right(n) => { 124 Either::Right(req) => {
140 let n = n.unwrap();
141 assert_eq!(n, 8);
142 let req = Request::parse(&buf).unwrap();
143 info!("control request: {:x}", req); 125 info!("control request: {:x}", req);
144 126
145 // Now that we have properly parsed the setup packet, ensure the end-point is no longer in
146 // a stalled state.
147 self.control_out.set_stalled(false);
148
149 match req.direction { 127 match req.direction {
150 UsbDirection::In => self.handle_control_in(req).await, 128 UsbDirection::In => self.handle_control_in(req).await,
151 UsbDirection::Out => self.handle_control_out(req).await, 129 UsbDirection::Out => self.handle_control_out(req).await,
@@ -155,36 +133,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
155 } 133 }
156 } 134 }
157 135
158 async fn write_chunked(&mut self, data: &[u8]) -> Result<(), driver::WriteError> {
159 for c in data.chunks(8) {
160 self.control_in.write(c).await?;
161 }
162 if data.len() % 8 == 0 {
163 self.control_in.write(&[]).await?;
164 }
165 Ok(())
166 }
167
168 async fn control_out_accept(&mut self, req: Request) {
169 info!("control out accept");
170 // status phase
171 // todo: cleanup
172 self.control_out.read(&mut []).await.unwrap();
173 }
174
175 async fn control_in_accept(&mut self, req: Request, data: &[u8]) {
176 info!("control accept {:x}", data);
177
178 let len = data.len().min(req.length as _);
179 if let Err(e) = self.write_chunked(&data[..len]).await {
180 info!("write_chunked failed: {:?}", e);
181 }
182
183 // status phase
184 // todo: cleanup
185 self.control_out.read(&mut []).await.unwrap();
186 }
187
188 async fn control_in_accept_writer( 136 async fn control_in_accept_writer(
189 &mut self, 137 &mut self,
190 req: Request, 138 req: Request,
@@ -193,17 +141,26 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
193 let mut buf = [0; 256]; 141 let mut buf = [0; 256];
194 let mut w = DescriptorWriter::new(&mut buf); 142 let mut w = DescriptorWriter::new(&mut buf);
195 f(&mut w); 143 f(&mut w);
196 let pos = w.position(); 144 let pos = w.position().min(usize::from(req.length));
197 self.control_in_accept(req, &buf[..pos]).await; 145 self.control.accept_in(&buf[..pos]).await;
198 }
199
200 fn control_reject(&mut self, req: Request) {
201 info!("control reject");
202 self.control_out.set_stalled(true);
203 } 146 }
204 147
205 async fn handle_control_out(&mut self, req: Request) { 148 async fn handle_control_out(&mut self, req: Request) {
206 // TODO actually read the data if there's an OUT data phase. 149 {
150 let mut buf = [0; 128];
151 let data = if req.length > 0 {
152 let size = self.control.data_out(&mut buf).await.unwrap();
153 &buf[0..size]
154 } else {
155 &[]
156 };
157
158 match self.classes.control_out(req, data).await {
159 RequestStatus::Accepted => return self.control.accept(),
160 RequestStatus::Rejected => return self.control.reject(),
161 RequestStatus::Unhandled => (),
162 }
163 }
207 164
208 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; 165 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
209 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; 166 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
@@ -217,12 +174,12 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
217 Request::FEATURE_DEVICE_REMOTE_WAKEUP, 174 Request::FEATURE_DEVICE_REMOTE_WAKEUP,
218 ) => { 175 ) => {
219 self.remote_wakeup_enabled = false; 176 self.remote_wakeup_enabled = false;
220 self.control_out_accept(req).await; 177 self.control.accept();
221 } 178 }
222 179
223 (Recipient::Endpoint, Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { 180 (Recipient::Endpoint, Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
224 //self.bus.set_stalled(((req.index as u8) & 0x8f).into(), false); 181 //self.bus.set_stalled(((req.index as u8) & 0x8f).into(), false);
225 self.control_out_accept(req).await; 182 self.control.accept();
226 } 183 }
227 184
228 ( 185 (
@@ -231,51 +188,61 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
231 Request::FEATURE_DEVICE_REMOTE_WAKEUP, 188 Request::FEATURE_DEVICE_REMOTE_WAKEUP,
232 ) => { 189 ) => {
233 self.remote_wakeup_enabled = true; 190 self.remote_wakeup_enabled = true;
234 self.control_out_accept(req).await; 191 self.control.accept();
235 } 192 }
236 193
237 (Recipient::Endpoint, Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { 194 (Recipient::Endpoint, Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
238 self.bus 195 self.bus
239 .set_stalled(((req.index as u8) & 0x8f).into(), true); 196 .set_stalled(((req.index as u8) & 0x8f).into(), true);
240 self.control_out_accept(req).await; 197 self.control.accept();
241 } 198 }
242 199
243 (Recipient::Device, Request::SET_ADDRESS, 1..=127) => { 200 (Recipient::Device, Request::SET_ADDRESS, 1..=127) => {
244 self.pending_address = req.value as u8; 201 self.pending_address = req.value as u8;
245 202
246 // on NRF the hardware auto-handles SET_ADDRESS. 203 // on NRF the hardware auto-handles SET_ADDRESS.
247 self.control_out_accept(req).await; 204 self.control.accept();
248 } 205 }
249 206
250 (Recipient::Device, Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { 207 (Recipient::Device, Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => {
251 self.device_state = UsbDeviceState::Configured; 208 self.device_state = UsbDeviceState::Configured;
252 self.control_out_accept(req).await; 209 self.control.accept();
253 } 210 }
254 211
255 (Recipient::Device, Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => { 212 (Recipient::Device, Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => {
256 match self.device_state { 213 match self.device_state {
257 UsbDeviceState::Default => { 214 UsbDeviceState::Default => {
258 self.control_out_accept(req).await; 215 self.control.accept();
259 } 216 }
260 _ => { 217 _ => {
261 self.device_state = UsbDeviceState::Addressed; 218 self.device_state = UsbDeviceState::Addressed;
262 self.control_out_accept(req).await; 219 self.control.accept();
263 } 220 }
264 } 221 }
265 } 222 }
266 223
267 (Recipient::Interface, Request::SET_INTERFACE, DEFAULT_ALTERNATE_SETTING_U16) => { 224 (Recipient::Interface, Request::SET_INTERFACE, DEFAULT_ALTERNATE_SETTING_U16) => {
268 // TODO: do something when alternate settings are implemented 225 // TODO: do something when alternate settings are implemented
269 self.control_out_accept(req).await; 226 self.control.accept();
270 } 227 }
271 228
272 _ => self.control_reject(req), 229 _ => self.control.reject(),
273 }, 230 },
274 _ => self.control_reject(req), 231 _ => self.control.reject(),
275 } 232 }
276 } 233 }
277 234
278 async fn handle_control_in(&mut self, req: Request) { 235 async fn handle_control_in(&mut self, req: Request) {
236 match self
237 .classes
238 .control_in(req, class::ControlIn::new(&mut self.control))
239 .await
240 .status()
241 {
242 RequestStatus::Accepted | RequestStatus::Rejected => return,
243 RequestStatus::Unhandled => (),
244 }
245
279 match req.request_type { 246 match req.request_type {
280 RequestType::Standard => match (req.recipient, req.request) { 247 RequestType::Standard => match (req.recipient, req.request) {
281 (Recipient::Device, Request::GET_STATUS) => { 248 (Recipient::Device, Request::GET_STATUS) => {
@@ -286,12 +253,12 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
286 if self.remote_wakeup_enabled { 253 if self.remote_wakeup_enabled {
287 status |= 0x0002; 254 status |= 0x0002;
288 } 255 }
289 self.control_in_accept(req, &status.to_le_bytes()).await; 256 self.control.accept_in(&status.to_le_bytes()).await;
290 } 257 }
291 258
292 (Recipient::Interface, Request::GET_STATUS) => { 259 (Recipient::Interface, Request::GET_STATUS) => {
293 let status: u16 = 0x0000; 260 let status: u16 = 0x0000;
294 self.control_in_accept(req, &status.to_le_bytes()).await; 261 self.control.accept_in(&status.to_le_bytes()).await;
295 } 262 }
296 263
297 (Recipient::Endpoint, Request::GET_STATUS) => { 264 (Recipient::Endpoint, Request::GET_STATUS) => {
@@ -300,7 +267,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
300 if self.bus.is_stalled(ep_addr) { 267 if self.bus.is_stalled(ep_addr) {
301 status |= 0x0001; 268 status |= 0x0001;
302 } 269 }
303 self.control_in_accept(req, &status.to_le_bytes()).await; 270 self.control.accept_in(&status.to_le_bytes()).await;
304 } 271 }
305 272
306 (Recipient::Device, Request::GET_DESCRIPTOR) => { 273 (Recipient::Device, Request::GET_DESCRIPTOR) => {
@@ -312,17 +279,17 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
312 UsbDeviceState::Configured => CONFIGURATION_VALUE, 279 UsbDeviceState::Configured => CONFIGURATION_VALUE,
313 _ => CONFIGURATION_NONE, 280 _ => CONFIGURATION_NONE,
314 }; 281 };
315 self.control_in_accept(req, &status.to_le_bytes()).await; 282 self.control.accept_in(&status.to_le_bytes()).await;
316 } 283 }
317 284
318 (Recipient::Interface, Request::GET_INTERFACE) => { 285 (Recipient::Interface, Request::GET_INTERFACE) => {
319 // TODO: change when alternate settings are implemented 286 // TODO: change when alternate settings are implemented
320 let status = DEFAULT_ALTERNATE_SETTING; 287 let status = DEFAULT_ALTERNATE_SETTING;
321 self.control_in_accept(req, &status.to_le_bytes()).await; 288 self.control.accept_in(&status.to_le_bytes()).await;
322 } 289 }
323 _ => self.control_reject(req), 290 _ => self.control.reject(),
324 }, 291 },
325 _ => self.control_reject(req), 292 _ => self.control.reject(),
326 } 293 }
327 } 294 }
328 295
@@ -331,11 +298,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
331 let config = self.config.clone(); 298 let config = self.config.clone();
332 299
333 match dtype { 300 match dtype {
334 descriptor_type::BOS => self.control_in_accept(req, self.bos_descriptor).await, 301 descriptor_type::BOS => self.control.accept_in(self.bos_descriptor).await,
335 descriptor_type::DEVICE => self.control_in_accept(req, self.device_descriptor).await, 302 descriptor_type::DEVICE => self.control.accept_in(self.device_descriptor).await,
336 descriptor_type::CONFIGURATION => { 303 descriptor_type::CONFIGURATION => self.control.accept_in(self.config_descriptor).await,
337 self.control_in_accept(req, self.config_descriptor).await
338 }
339 descriptor_type::STRING => { 304 descriptor_type::STRING => {
340 if index == 0 { 305 if index == 0 {
341 self.control_in_accept_writer(req, |w| { 306 self.control_in_accept_writer(req, |w| {
@@ -363,11 +328,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
363 self.control_in_accept_writer(req, |w| w.string(s).unwrap()) 328 self.control_in_accept_writer(req, |w| w.string(s).unwrap())
364 .await; 329 .await;
365 } else { 330 } else {
366 self.control_reject(req) 331 self.control.reject()
367 } 332 }
368 } 333 }
369 } 334 }
370 _ => self.control_reject(req), 335 _ => self.control.reject(),
371 } 336 }
372 } 337 }
373} 338}