usb_device/
control_pipe.rs
1use crate::bus::UsbBus;
2use crate::control::Request;
3use crate::endpoint::{EndpointIn, EndpointOut};
4use crate::{Result, UsbDirection, UsbError};
5use core::cmp::min;
6
7#[derive(Debug)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9#[allow(unused)]
10enum ControlState {
11 Idle,
12 DataIn,
13 DataInZlp,
14 DataInLast,
15 CompleteIn(Request),
16 StatusOut,
17 CompleteOut,
18 DataOut(Request),
19 StatusIn,
20 Error,
21}
22
23#[cfg(not(feature = "control-buffer-256"))]
26const CONTROL_BUF_LEN: usize = 128;
27#[cfg(feature = "control-buffer-256")]
28const CONTROL_BUF_LEN: usize = 256;
29
30pub struct ControlPipe<'a, B: UsbBus> {
32 ep_out: EndpointOut<'a, B>,
33 ep_in: EndpointIn<'a, B>,
34 state: ControlState,
35 buf: [u8; CONTROL_BUF_LEN],
36 static_in_buf: Option<&'static [u8]>,
37 i: usize,
38 len: usize,
39}
40
41impl<B: UsbBus> ControlPipe<'_, B> {
42 pub fn new<'a>(ep_out: EndpointOut<'a, B>, ep_in: EndpointIn<'a, B>) -> ControlPipe<'a, B> {
43 ControlPipe {
44 ep_out,
45 ep_in,
46 state: ControlState::Idle,
47 buf: [0; CONTROL_BUF_LEN],
48 static_in_buf: None,
49 i: 0,
50 len: 0,
51 }
52 }
53
54 pub fn waiting_for_response(&self) -> bool {
55 matches!(
56 self.state,
57 ControlState::CompleteOut | ControlState::CompleteIn(_)
58 )
59 }
60
61 pub fn data(&self) -> &[u8] {
62 &self.buf[0..self.len]
63 }
64
65 pub fn reset(&mut self) {
66 usb_trace!("Control pipe reset");
67 self.state = ControlState::Idle;
68 }
69
70 pub fn handle_setup(&mut self) -> Option<Request> {
71 let count = match self.ep_out.read(&mut self.buf[..]) {
72 Ok(count) => {
73 usb_trace!("Read {} bytes on EP0-OUT: {:?}", count, &self.buf[..count]);
74 count
75 }
76 Err(UsbError::WouldBlock) => return None,
77 Err(_) => {
78 return None;
79 }
80 };
81
82 let req = match Request::parse(&self.buf[0..count]) {
83 Ok(req) => req,
84 Err(_) => {
85 return None;
87 }
88 };
89
90 self.ep_out.unstall();
93
94 usb_debug!("EP0 request received: {:?}", req);
95
96 if req.direction == UsbDirection::Out {
102 if req.length > 0 {
105 if req.length as usize > self.buf.len() {
108 return None;
110 }
111
112 self.i = 0;
113 self.len = req.length as usize;
114 self.state = ControlState::DataOut(req);
115 } else {
116 self.len = 0;
119 self.state = ControlState::CompleteOut;
120 return Some(req);
121 }
122 } else {
123 self.state = ControlState::CompleteIn(req);
126 return Some(req);
127 }
128
129 None
130 }
131
132 pub fn handle_out(&mut self) -> Result<Option<Request>> {
133 match self.state {
134 ControlState::DataOut(req) => {
135 let i = self.i;
136 let count = match self.ep_out.read(&mut self.buf[i..]) {
137 Ok(count) => count,
138 Err(UsbError::WouldBlock) => return Ok(None),
139 Err(_err) => {
140 usb_debug!("Failed EP0 read: {:?}", _err);
143 self.set_error();
144 return Ok(None);
145 }
146 };
147
148 usb_trace!(
149 "Read {} bytes on EP0-OUT: {:?}",
150 count,
151 &self.buf[i..(i + count)]
152 );
153 self.i += count;
154
155 if self.i >= self.len {
156 usb_debug!("Request OUT complete: {:?}", req);
157 self.state = ControlState::CompleteOut;
158 return Ok(Some(req));
159 }
160 }
161 ControlState::DataIn
164 | ControlState::DataInLast
165 | ControlState::DataInZlp
166 | ControlState::StatusOut => {
167 usb_debug!(
168 "Control transfer completed. Current state: {:?}",
169 self.state
170 );
171 self.ep_out.read(&mut [])?;
172 self.state = ControlState::Idle;
173 }
174 _ => {
175 usb_debug!(
177 "Discarding EP0 data due to unexpected state. Current state: {:?}",
178 self.state
179 );
180 self.ep_out.read(&mut [])?;
181
182 self.set_error()
184 }
185 }
186
187 Ok(None)
188 }
189
190 pub fn handle_in_complete(&mut self) -> Result<bool> {
191 match self.state {
192 ControlState::DataIn => {
193 self.write_in_chunk()?;
194 }
195 ControlState::DataInZlp => {
196 self.ep_in.write(&[])?;
197 usb_trace!("wrote EP0: ZLP");
198 self.state = ControlState::DataInLast;
199 }
200 ControlState::DataInLast => {
201 self.ep_out.unstall();
202 self.state = ControlState::StatusOut;
203 }
204 ControlState::StatusIn => {
205 self.state = ControlState::Idle;
206 return Ok(true);
207 }
208 ControlState::Idle => {
209 }
213 _ => {
214 }
218 };
219
220 Ok(false)
221 }
222
223 fn write_in_chunk(&mut self) -> Result<()> {
224 let count = min(self.len - self.i, self.ep_in.max_packet_size() as usize);
225
226 let buffer = self.static_in_buf.unwrap_or(&self.buf);
227 let count = self.ep_in.write(&buffer[self.i..(self.i + count)])?;
228 usb_trace!("wrote EP0: {:?}", &buffer[self.i..(self.i + count)]);
229
230 self.i += count;
231
232 if self.i >= self.len {
233 self.static_in_buf = None;
234
235 self.state = if count == self.ep_in.max_packet_size() as usize {
236 ControlState::DataInZlp
237 } else {
238 ControlState::DataInLast
239 };
240 }
241
242 Ok(())
243 }
244
245 pub fn accept_out(&mut self) -> Result<()> {
246 match self.state {
247 ControlState::CompleteOut => {}
248 _ => {
249 usb_debug!("Cannot ACK, invalid state: {:?}", self.state);
250 return Err(UsbError::InvalidState);
251 }
252 };
253
254 self.ep_in.write(&[])?;
255 self.state = ControlState::StatusIn;
256 Ok(())
257 }
258
259 pub fn accept_in(&mut self, f: impl FnOnce(&mut [u8]) -> Result<usize>) -> Result<()> {
260 let req = match self.state {
261 ControlState::CompleteIn(req) => req,
262 _ => {
263 usb_debug!("EP0-IN cannot ACK, invalid state: {:?}", self.state);
264 return Err(UsbError::InvalidState);
265 }
266 };
267
268 let len = f(&mut self.buf[..])?;
269
270 if len > self.buf.len() {
271 self.set_error();
272 return Err(UsbError::BufferOverflow);
273 }
274
275 self.start_in_transfer(req, len)
276 }
277
278 pub fn accept_in_static(&mut self, data: &'static [u8]) -> Result<()> {
279 let req = match self.state {
280 ControlState::CompleteIn(req) => req,
281 _ => {
282 usb_debug!("EP0-IN cannot ACK, invalid state: {:?}", self.state);
283 return Err(UsbError::InvalidState);
284 }
285 };
286
287 self.static_in_buf = Some(data);
288
289 self.start_in_transfer(req, data.len())
290 }
291
292 fn start_in_transfer(&mut self, req: Request, data_len: usize) -> Result<()> {
293 self.len = min(data_len, req.length as usize);
294 self.i = 0;
295 self.state = ControlState::DataIn;
296 self.write_in_chunk()?;
297
298 Ok(())
299 }
300
301 pub fn reject(&mut self) -> Result<()> {
302 usb_debug!("EP0 transfer rejected");
303 if !self.waiting_for_response() {
304 return Err(UsbError::InvalidState);
305 }
306
307 self.set_error();
308 Ok(())
309 }
310
311 fn set_error(&mut self) {
312 usb_debug!("EP0 stalled - error");
313 self.state = ControlState::Error;
314 self.ep_out.stall();
315 self.ep_in.stall();
316 }
317}