aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src
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
parent5c0db627feae071182dd9978ffb56b0524558d93 (diff)
Add support for USB classes handling control requests.
Diffstat (limited to 'embassy-usb/src')
-rw-r--r--embassy-usb/src/builder.rs14
-rw-r--r--embassy-usb/src/class.rs190
-rw-r--r--embassy-usb/src/control.rs17
-rw-r--r--embassy-usb/src/driver.rs42
-rw-r--r--embassy-usb/src/lib.rs169
5 files changed, 313 insertions, 119 deletions
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index e92cc8ef2..f0f94b932 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -1,3 +1,4 @@
1use super::class::UsbClass;
1use super::descriptor::{BosWriter, DescriptorWriter}; 2use super::descriptor::{BosWriter, DescriptorWriter};
2use super::driver::{Driver, EndpointAllocError}; 3use super::driver::{Driver, EndpointAllocError};
3use super::types::*; 4use super::types::*;
@@ -174,7 +175,10 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
174 } 175 }
175 176
176 /// Creates the [`UsbDevice`] instance with the configuration in this builder. 177 /// Creates the [`UsbDevice`] instance with the configuration in this builder.
177 pub fn build(mut self) -> UsbDevice<'d, D> { 178 ///
179 /// If a device has mutliple [`UsbClass`]es, they can be provided as a tuple list:
180 /// `(class1, (class2, (class3, ()))`.
181 pub fn build<C: UsbClass<'d, D>>(mut self, classes: C) -> UsbDevice<'d, D, C> {
178 self.config_descriptor.end_configuration(); 182 self.config_descriptor.end_configuration();
179 self.bos_descriptor.end_bos(); 183 self.bos_descriptor.end_bos();
180 184
@@ -184,6 +188,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
184 self.device_descriptor.into_buf(), 188 self.device_descriptor.into_buf(),
185 self.config_descriptor.into_buf(), 189 self.config_descriptor.into_buf(),
186 self.bos_descriptor.writer.into_buf(), 190 self.bos_descriptor.writer.into_buf(),
191 classes,
187 ) 192 )
188 } 193 }
189 194
@@ -268,9 +273,10 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> {
268 /// Panics if endpoint allocation fails, because running out of endpoints or memory is not 273 /// Panics if endpoint allocation fails, because running out of endpoints or memory is not
269 /// feasibly recoverable. 274 /// feasibly recoverable.
270 #[inline] 275 #[inline]
271 pub fn alloc_control_endpoint_out(&mut self, max_packet_size: u16) -> D::EndpointOut { 276 pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe {
272 self.alloc_endpoint_out(None, EndpointType::Control, max_packet_size, 0) 277 self.bus
273 .expect("alloc_ep failed") 278 .alloc_control_pipe(max_packet_size)
279 .expect("alloc_control_pipe failed")
274 } 280 }
275 281
276 /// Allocates a bulk in endpoint. 282 /// Allocates a bulk in endpoint.
diff --git a/embassy-usb/src/class.rs b/embassy-usb/src/class.rs
new file mode 100644
index 000000000..97bf7aba1
--- /dev/null
+++ b/embassy-usb/src/class.rs
@@ -0,0 +1,190 @@
1use core::future::Future;
2
3use crate::control::Request;
4use crate::driver::{ControlPipe, Driver};
5
6#[derive(Copy, Clone, Eq, PartialEq, Debug)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8pub enum RequestStatus {
9 Unhandled,
10 Accepted,
11 Rejected,
12}
13
14impl Default for RequestStatus {
15 fn default() -> Self {
16 RequestStatus::Unhandled
17 }
18}
19
20/// A trait for implementing USB classes.
21///
22/// All methods are optional callbacks that will be called by
23/// [`UsbDevice::run()`](crate::UsbDevice::run)
24pub trait UsbClass<'d, D: Driver<'d>> {
25 type ControlOutFuture<'a>: Future<Output = RequestStatus> + 'a
26 where
27 Self: 'a,
28 'd: 'a,
29 D: 'a;
30
31 type ControlInFuture<'a>: Future<Output = ControlInRequestStatus> + 'a
32 where
33 Self: 'a,
34 'd: 'a,
35 D: 'a;
36
37 /// Called after a USB reset after the bus reset sequence is complete.
38 fn reset(&mut self) {}
39
40 /// Called when a control request is received with direction HostToDevice.
41 ///
42 /// All requests are passed to classes in turn, which can choose to accept, ignore or report an
43 /// error. Classes can even choose to override standard requests, but doing that is rarely
44 /// necessary.
45 ///
46 /// When implementing your own class, you should ignore any requests that are not meant for your
47 /// class so that any other classes in the composite device can process them.
48 ///
49 /// # Arguments
50 ///
51 /// * `req` - The request from the SETUP packet.
52 /// * `data` - The data from the request.
53 fn control_out<'a>(&'a mut self, req: Request, data: &'a [u8]) -> Self::ControlOutFuture<'a>
54 where
55 'd: 'a,
56 D: 'a;
57
58 /// Called when a control request is received with direction DeviceToHost.
59 ///
60 /// All requests are passed to classes in turn, which can choose to accept, ignore or report an
61 /// error. Classes can even choose to override standard requests, but doing that is rarely
62 /// necessary.
63 ///
64 /// See [`ControlIn`] for how to respond to the transfer.
65 ///
66 /// When implementing your own class, you should ignore any requests that are not meant for your
67 /// class so that any other classes in the composite device can process them.
68 ///
69 /// # Arguments
70 ///
71 /// * `req` - The request from the SETUP packet.
72 /// * `control` - The control pipe.
73 fn control_in<'a>(
74 &'a mut self,
75 req: Request,
76 control: ControlIn<'a, 'd, D>,
77 ) -> Self::ControlInFuture<'a>
78 where
79 'd: 'a;
80}
81
82impl<'d, D: Driver<'d>> UsbClass<'d, D> for () {
83 type ControlOutFuture<'a> = impl Future<Output = RequestStatus> + 'a where Self: 'a, 'd: 'a, D: 'a;
84 type ControlInFuture<'a> = impl Future<Output = ControlInRequestStatus> + 'a where Self: 'a, 'd: 'a, D: 'a;
85
86 fn control_out<'a>(&'a mut self, _req: Request, _data: &'a [u8]) -> Self::ControlOutFuture<'a>
87 where
88 'd: 'a,
89 D: 'a,
90 {
91 async move { RequestStatus::default() }
92 }
93
94 fn control_in<'a>(
95 &'a mut self,
96 _req: Request,
97 control: ControlIn<'a, 'd, D>,
98 ) -> Self::ControlInFuture<'a>
99 where
100 'd: 'a,
101 D: 'a,
102 {
103 async move { control.ignore() }
104 }
105}
106
107impl<'d, D: Driver<'d>, Head, Tail> UsbClass<'d, D> for (Head, Tail)
108where
109 Head: UsbClass<'d, D>,
110 Tail: UsbClass<'d, D>,
111{
112 type ControlOutFuture<'a> = impl Future<Output = RequestStatus> + 'a where Self: 'a, 'd: 'a, D: 'a;
113 type ControlInFuture<'a> = impl Future<Output = ControlInRequestStatus> + 'a where Self: 'a, 'd: 'a, D: 'a;
114
115 fn control_out<'a>(&'a mut self, req: Request, data: &'a [u8]) -> Self::ControlOutFuture<'a>
116 where
117 'd: 'a,
118 D: 'a,
119 {
120 async move {
121 match self.0.control_out(req, data).await {
122 RequestStatus::Unhandled => self.1.control_out(req, data).await,
123 status => status,
124 }
125 }
126 }
127
128 fn control_in<'a>(
129 &'a mut self,
130 req: Request,
131 control: ControlIn<'a, 'd, D>,
132 ) -> Self::ControlInFuture<'a>
133 where
134 'd: 'a,
135 {
136 async move {
137 match self
138 .0
139 .control_in(req, ControlIn::new(control.control))
140 .await
141 {
142 ControlInRequestStatus(RequestStatus::Unhandled) => {
143 self.1.control_in(req, control).await
144 }
145 status => status,
146 }
147 }
148 }
149}
150
151/// Handle for a control IN transfer. When implementing a class, use the methods of this object to
152/// response to the transfer with either data or an error (STALL condition). To ignore the request
153/// and pass it on to the next class, call [`Self::ignore()`].
154pub struct ControlIn<'a, 'd: 'a, D: Driver<'d>> {
155 control: &'a mut D::ControlPipe,
156}
157
158#[derive(Eq, PartialEq, Debug)]
159#[cfg_attr(feature = "defmt", derive(defmt::Format))]
160pub struct ControlInRequestStatus(pub(crate) RequestStatus);
161
162impl ControlInRequestStatus {
163 pub fn status(self) -> RequestStatus {
164 self.0
165 }
166}
167
168impl<'a, 'd: 'a, D: Driver<'d>> ControlIn<'a, 'd, D> {
169 pub(crate) fn new(control: &'a mut D::ControlPipe) -> Self {
170 ControlIn { control }
171 }
172
173 /// Ignores the request and leaves it unhandled.
174 pub fn ignore(self) -> ControlInRequestStatus {
175 ControlInRequestStatus(RequestStatus::Unhandled)
176 }
177
178 /// Accepts the transfer with the supplied buffer.
179 pub async fn accept(self, data: &[u8]) -> ControlInRequestStatus {
180 self.control.accept_in(data).await;
181
182 ControlInRequestStatus(RequestStatus::Accepted)
183 }
184
185 /// Rejects the transfer by stalling the pipe.
186 pub fn reject(self) -> ControlInRequestStatus {
187 self.control.reject();
188 ControlInRequestStatus(RequestStatus::Rejected)
189 }
190}
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index f1148ac76..77bc10aa4 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -2,12 +2,6 @@ use core::mem;
2 2
3use super::types::*; 3use super::types::*;
4 4
5#[derive(Debug, PartialEq, Eq, Clone, Copy)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub enum ParseError {
8 InvalidLength,
9}
10
11/// Control request type. 5/// Control request type.
12#[repr(u8)] 6#[repr(u8)]
13#[derive(Copy, Clone, Eq, PartialEq, Debug)] 7#[derive(Copy, Clone, Eq, PartialEq, Debug)]
@@ -104,15 +98,12 @@ impl Request {
104 /// Standard USB feature Device Remote Wakeup for Set/Clear Feature 98 /// Standard USB feature Device Remote Wakeup for Set/Clear Feature
105 pub const FEATURE_DEVICE_REMOTE_WAKEUP: u16 = 1; 99 pub const FEATURE_DEVICE_REMOTE_WAKEUP: u16 = 1;
106 100
107 pub(crate) fn parse(buf: &[u8]) -> Result<Request, ParseError> { 101 /// Parses a USB control request from a byte array.
108 if buf.len() != 8 { 102 pub fn parse(buf: &[u8; 8]) -> Request {
109 return Err(ParseError::InvalidLength);
110 }
111
112 let rt = buf[0]; 103 let rt = buf[0];
113 let recipient = rt & 0b11111; 104 let recipient = rt & 0b11111;
114 105
115 Ok(Request { 106 Request {
116 direction: rt.into(), 107 direction: rt.into(),
117 request_type: unsafe { mem::transmute((rt >> 5) & 0b11) }, 108 request_type: unsafe { mem::transmute((rt >> 5) & 0b11) },
118 recipient: if recipient <= 3 { 109 recipient: if recipient <= 3 {
@@ -124,7 +115,7 @@ impl Request {
124 value: (buf[2] as u16) | ((buf[3] as u16) << 8), 115 value: (buf[2] as u16) | ((buf[3] as u16) << 8),
125 index: (buf[4] as u16) | ((buf[5] as u16) << 8), 116 index: (buf[4] as u16) | ((buf[5] as u16) << 8),
126 length: (buf[6] as u16) | ((buf[7] as u16) << 8), 117 length: (buf[6] as u16) | ((buf[7] as u16) << 8),
127 }) 118 }
128 } 119 }
129 120
130 /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request. 121 /// Gets the descriptor type and index from the value field of a GET_DESCRIPTOR request.
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs
index a7b16efa5..1c6ba1f52 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb/src/driver.rs
@@ -1,5 +1,7 @@
1use core::future::Future; 1use core::future::Future;
2 2
3use crate::control::Request;
4
3use super::types::*; 5use super::types::*;
4 6
5/// Driver for a specific USB peripheral. Implement this to add support for a new hardware 7/// Driver for a specific USB peripheral. Implement this to add support for a new hardware
@@ -7,6 +9,7 @@ use super::types::*;
7pub trait Driver<'a> { 9pub trait Driver<'a> {
8 type EndpointOut: EndpointOut + 'a; 10 type EndpointOut: EndpointOut + 'a;
9 type EndpointIn: EndpointIn + 'a; 11 type EndpointIn: EndpointIn + 'a;
12 type ControlPipe: ControlPipe + 'a;
10 type Bus: Bus + 'a; 13 type Bus: Bus + 'a;
11 14
12 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device 15 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device
@@ -36,6 +39,11 @@ pub trait Driver<'a> {
36 interval: u8, 39 interval: u8,
37 ) -> Result<Self::EndpointIn, EndpointAllocError>; 40 ) -> Result<Self::EndpointIn, EndpointAllocError>;
38 41
42 fn alloc_control_pipe(
43 &mut self,
44 max_packet_size: u16,
45 ) -> Result<Self::ControlPipe, EndpointAllocError>;
46
39 /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so 47 /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so
40 /// there is no need to perform a USB reset in this method. 48 /// there is no need to perform a USB reset in this method.
41 fn enable(self) -> Self::Bus; 49 fn enable(self) -> Self::Bus;
@@ -122,6 +130,40 @@ pub trait EndpointOut: Endpoint {
122 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a>; 130 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a>;
123} 131}
124 132
133pub trait ControlPipe {
134 type SetupFuture<'a>: Future<Output = Request> + 'a
135 where
136 Self: 'a;
137 type DataOutFuture<'a>: Future<Output = Result<usize, ReadError>> + 'a
138 where
139 Self: 'a;
140 type AcceptInFuture<'a>: Future<Output = ()> + 'a
141 where
142 Self: 'a;
143
144 /// Reads a single setup packet from the endpoint.
145 fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a>;
146
147 /// Reads the data packet of a control write sequence.
148 ///
149 /// Must be called after `setup()` for requests with `direction` of `Out`
150 /// and `length` greater than zero.
151 ///
152 /// `buf.len()` must be greater than or equal to the request's `length`.
153 fn data_out<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::DataOutFuture<'a>;
154
155 /// Accepts a control request.
156 fn accept(&mut self);
157
158 /// Accepts a control read request with `data`.
159 ///
160 /// `data.len()` must be less than or equal to the request's `length`.
161 fn accept_in<'a>(&'a mut self, data: &'a [u8]) -> Self::AcceptInFuture<'a>;
162
163 /// Rejects a control request.
164 fn reject(&mut self);
165}
166
125pub trait EndpointIn: Endpoint { 167pub trait EndpointIn: Endpoint {
126 type WriteFuture<'a>: Future<Output = Result<(), WriteError>> + 'a 168 type WriteFuture<'a>: Future<Output = Result<(), WriteError>> + 'a
127 where 169 where
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}