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// Maximum length of control transfer data stage in bytes. 128 bytes by default. You can define the
24// feature "control-buffer-256" to make it 256 bytes if you have larger control transfers.
25#[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
30/// Buffers and parses USB control transfers.
31pub 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                // Failed to parse SETUP packet. We are supposed to silently ignore this.
86                return None;
87            }
88        };
89
90        // Now that we have properly parsed the setup packet, ensure the end-point is no longer in
91        // a stalled state.
92        self.ep_out.unstall();
93
94        usb_debug!("EP0 request received: {:?}", req);
95
96        /*sprintln!("SETUP {:?} {:?} {:?} req:{} val:{} idx:{} len:{} {:?}",
97        req.direction, req.request_type, req.recipient,
98        req.request, req.value, req.index, req.length,
99        self.state);*/
100
101        if req.direction == UsbDirection::Out {
102            // OUT transfer
103
104            if req.length > 0 {
105                // Has data stage
106
107                if req.length as usize > self.buf.len() {
108                    // Data stage won't fit in buffer
109                    return None;
110                }
111
112                self.i = 0;
113                self.len = req.length as usize;
114                self.state = ControlState::DataOut(req);
115            } else {
116                // No data stage
117
118                self.len = 0;
119                self.state = ControlState::CompleteOut;
120                return Some(req);
121            }
122        } else {
123            // IN transfer
124
125            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                        // Failed to read or buffer overflow (overflow is only possible if the host
141                        // sends more data than it indicated in the SETUP request)
142                        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            // The host may terminate a DATA stage early by sending a zero-length status packet
162            // acknowledging the data we sent it.
163            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                // Discard the packet
176                usb_debug!(
177                    "Discarding EP0 data due to unexpected state. Current state: {:?}",
178                    self.state
179                );
180                self.ep_out.read(&mut [])?;
181
182                // Unexpected OUT packet
183                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                // If we received a message on EP0 while sending the last portion of an IN
210                // transfer, we may have already transitioned to IDLE without getting the last
211                // IN-complete status. Just ignore this indication.
212            }
213            _ => {
214                // If we get IN-COMPLETE indications in unexpected states, it's generally because
215                // of control flow in previous phases updating after our packet was successfully
216                // sent. Ignore these indications if they don't drive any further behavior.
217            }
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}