capsules_extra/usb/
usbc_client_ctrl.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! A generic USB client layer managing control requests
6//!
7//! This layer responds to control requests and handles the state machine for
8//! implementing them.
9//!
10//! Right now, the stack looks like this:
11//!
12//! ```text
13//!                  Client
14//!                  |   ^
15//!             |-----   |
16//!             v        |
17//!      ClientCtrl      |
18//!          |           |
19//!          v           |
20//!          UsbController
21//! ```
22
23use super::descriptors::Buffer64;
24use super::descriptors::Descriptor;
25use super::descriptors::DescriptorBuffer;
26use super::descriptors::DescriptorType;
27use super::descriptors::DeviceBuffer;
28use super::descriptors::HIDDescriptor;
29use super::descriptors::LanguagesDescriptor;
30use super::descriptors::Recipient;
31use super::descriptors::ReportDescriptor;
32use super::descriptors::SetupData;
33use super::descriptors::StandardRequest;
34use super::descriptors::StringDescriptor;
35use super::descriptors::TransferDirection;
36
37use core::cell::Cell;
38use core::cmp::min;
39
40use kernel::hil;
41use kernel::hil::usb::TransferType;
42
43const DESCRIPTOR_BUFLEN: usize = 128;
44
45const N_ENDPOINTS: usize = 3;
46
47/// Handler for USB control endpoint requests.
48pub struct ClientCtrl<'a, 'b, U: 'a> {
49    /// The USB hardware controller.
50    controller: &'a U,
51
52    /// State of each endpoint.
53    state: [Cell<State>; N_ENDPOINTS],
54
55    /// A 64-byte buffer for the control endpoint to be passed to the USB
56    /// driver.
57    pub ctrl_buffer: Buffer64,
58
59    /// Storage for composing responses to device descriptor requests.
60    descriptor_storage: [Cell<u8>; DESCRIPTOR_BUFLEN],
61
62    /// Buffer containing the byte-packed representation of the device
63    /// descriptor. This is expected to be created and passed from the user of
64    /// `ClientCtrl`.
65    device_descriptor_buffer: DeviceBuffer,
66
67    /// Buffer containing the byte-serialized representation of the configuration
68    /// descriptor and all other descriptors for this device.
69    other_descriptor_buffer: DescriptorBuffer,
70
71    /// An optional HID descriptor for the configuration. This can be requested
72    /// separately. It must also be included in `other_descriptor_buffer` if it exists.
73    hid_descriptor: Option<&'b HIDDescriptor<'b>>,
74
75    /// An optional report descriptor for the configuration. This can be
76    /// requested separately. It must also be included in
77    /// `other_descriptor_buffer` if it exists.
78    report_descriptor: Option<&'b ReportDescriptor<'b>>,
79
80    /// Supported language (only one for now).
81    language: &'b [u16; 1],
82
83    /// USB strings to provide human readable descriptions of certain descriptor attributes.
84    strings: &'b [&'b str],
85}
86
87/// States for the individual endpoints.
88#[derive(Copy, Clone, Default)]
89enum State {
90    #[default]
91    Init,
92
93    /// We are doing a Control In transfer of some data in
94    /// self.descriptor_storage, with the given extent remaining to send.
95    CtrlIn(usize, usize),
96
97    /// We will accept data from the host.
98    CtrlOut,
99
100    SetAddress,
101}
102
103impl<'a, 'b, U: hil::usb::UsbController<'a>> ClientCtrl<'a, 'b, U> {
104    pub fn new(
105        controller: &'a U,
106        device_descriptor_buffer: DeviceBuffer,
107        other_descriptor_buffer: DescriptorBuffer,
108        hid_descriptor: Option<&'b HIDDescriptor<'b>>,
109        report_descriptor: Option<&'b ReportDescriptor<'b>>,
110        language: &'b [u16; 1],
111        strings: &'b [&'b str],
112    ) -> Self {
113        ClientCtrl {
114            controller,
115            state: Default::default(),
116            // For the moment, the Default trait is not implemented for arrays
117            // of length > 32, and the Cell type is not Copy, so we have to
118            // initialize each element manually.
119            #[rustfmt::skip]
120            descriptor_storage: [
121                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
122                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
123                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
124                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
125                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
126                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
127                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
128                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
129                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
130                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
131                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
132                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
133                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
134                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
135                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
136                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
137                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
138                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
139                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
140                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
141                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
142                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
143                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
144                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
145                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
146                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
147                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
148                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
149                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
150                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
151                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
152                Cell::default(), Cell::default(), Cell::default(), Cell::default(),
153            ],
154            ctrl_buffer: Buffer64::default(),
155            device_descriptor_buffer,
156            other_descriptor_buffer,
157            hid_descriptor,
158            report_descriptor,
159            language,
160            strings,
161        }
162    }
163
164    #[inline]
165    pub fn controller(&self) -> &'a U {
166        self.controller
167    }
168
169    #[inline]
170    fn descriptor_buf(&'a self) -> &'a [Cell<u8>] {
171        &self.descriptor_storage
172    }
173
174    pub fn enable(&'a self) {
175        // Set up the default control endpoint
176        self.controller
177            .endpoint_set_ctrl_buffer(&self.ctrl_buffer.buf);
178        self.controller
179            .enable_as_device(hil::usb::DeviceSpeed::Full); // must be Full for Bulk transfers
180        self.controller
181            .endpoint_out_enable(TransferType::Control, 0);
182    }
183
184    pub fn attach(&'a self) {
185        self.controller.attach();
186    }
187
188    /// Handle a Control Setup transaction
189    pub fn ctrl_setup(&'a self, endpoint: usize) -> hil::usb::CtrlSetupResult {
190        if endpoint != 0 {
191            // For now we only support the default Control endpoint
192            return hil::usb::CtrlSetupResult::ErrInvalidDeviceIndex;
193        }
194        SetupData::get(&self.ctrl_buffer.buf).map_or(
195            hil::usb::CtrlSetupResult::ErrNoParse,
196            |setup_data| {
197                let transfer_direction = setup_data.request_type.transfer_direction();
198                let recipient = setup_data.request_type.recipient();
199                setup_data.get_standard_request().map_or_else(
200                    || {
201                        // XX: CtrlSetupResult::ErrNonstandardRequest
202
203                        // For now, promiscuously accept vendor data and even supply
204                        // a few debugging bytes when host does a read
205
206                        match transfer_direction {
207                            TransferDirection::HostToDevice => {
208                                self.state[endpoint].set(State::CtrlOut);
209                                hil::usb::CtrlSetupResult::Ok
210                            }
211                            TransferDirection::DeviceToHost => {
212                                // Arrange to send some crap back
213                                let buf = self.descriptor_buf();
214                                buf[0].set(0xa);
215                                buf[1].set(0xb);
216                                buf[2].set(0xc);
217                                self.state[endpoint].set(State::CtrlIn(0, 3));
218                                hil::usb::CtrlSetupResult::Ok
219                            }
220                        }
221                    },
222                    |request| match recipient {
223                        Recipient::Device => self.handle_standard_device_request(endpoint, request),
224                        Recipient::Interface => {
225                            self.handle_standard_interface_request(endpoint, request)
226                        }
227                        _ => hil::usb::CtrlSetupResult::ErrGeneric,
228                    },
229                )
230            },
231        )
232    }
233
234    fn handle_standard_device_request(
235        &'a self,
236        endpoint: usize,
237        request: StandardRequest,
238    ) -> hil::usb::CtrlSetupResult {
239        match request {
240            StandardRequest::GetDescriptor {
241                descriptor_type,
242                descriptor_index,
243                lang_id,
244                requested_length,
245            } => {
246                match descriptor_type {
247                    DescriptorType::Device => match descriptor_index {
248                        0 => {
249                            let buf = self.descriptor_buf();
250                            let len = self.device_descriptor_buffer.write_to(buf);
251
252                            let end = min(len, requested_length as usize);
253
254                            self.state[endpoint].set(State::CtrlIn(0, end));
255                            hil::usb::CtrlSetupResult::Ok
256                        }
257                        _ => hil::usb::CtrlSetupResult::ErrInvalidDeviceIndex,
258                    },
259                    DescriptorType::Configuration => match descriptor_index {
260                        0 => {
261                            let buf = self.descriptor_buf();
262                            let len = self.other_descriptor_buffer.write_to(buf);
263
264                            let end = min(len, requested_length as usize);
265                            self.state[endpoint].set(State::CtrlIn(0, end));
266                            hil::usb::CtrlSetupResult::Ok
267                        }
268                        _ => hil::usb::CtrlSetupResult::ErrInvalidConfigurationIndex,
269                    },
270                    DescriptorType::String => {
271                        if let Some(len) = match descriptor_index {
272                            0 => {
273                                let buf = self.descriptor_buf();
274                                let d = LanguagesDescriptor {
275                                    langs: self.language,
276                                };
277                                let len = d.write_to(buf);
278                                Some(len)
279                            }
280                            i if i > 0
281                                && (i as usize) <= self.strings.len()
282                                && lang_id == self.language[0] =>
283                            {
284                                let buf = self.descriptor_buf();
285                                let d = StringDescriptor {
286                                    string: self.strings[i as usize - 1],
287                                };
288                                let len = d.write_to(buf);
289                                Some(len)
290                            }
291                            _ => None,
292                        } {
293                            let end = min(len, requested_length as usize);
294                            self.state[endpoint].set(State::CtrlIn(0, end));
295                            hil::usb::CtrlSetupResult::Ok
296                        } else {
297                            hil::usb::CtrlSetupResult::ErrInvalidStringIndex
298                        }
299                    }
300                    DescriptorType::DeviceQualifier => {
301                        // We are full-speed only, so we must
302                        // respond with a request error
303                        hil::usb::CtrlSetupResult::ErrNoDeviceQualifier
304                    }
305                    _ => hil::usb::CtrlSetupResult::ErrUnrecognizedDescriptorType,
306                } // match descriptor_type
307            }
308            StandardRequest::SetAddress { device_address } => {
309                // Load the address we've been assigned ...
310                self.controller.set_address(device_address);
311
312                // ... and when this request gets to the Status stage we will actually enable the
313                // address.
314                self.state[endpoint].set(State::SetAddress);
315                hil::usb::CtrlSetupResult::OkSetAddress
316            }
317            StandardRequest::SetConfiguration { .. } => {
318                // We have been assigned a particular configuration: fine!
319                hil::usb::CtrlSetupResult::Ok
320            }
321            _ => hil::usb::CtrlSetupResult::ErrUnrecognizedRequestType,
322        }
323    }
324
325    fn handle_standard_interface_request(
326        &'a self,
327        endpoint: usize,
328        request: StandardRequest,
329    ) -> hil::usb::CtrlSetupResult {
330        match request {
331            StandardRequest::GetDescriptor {
332                descriptor_type,
333                // TODO: use the descriptor index
334                descriptor_index: _,
335                // TODO: use the language ID?
336                lang_id: _,
337                requested_length,
338            } => match descriptor_type {
339                DescriptorType::HID => {
340                    if let Some(desc) = self.hid_descriptor {
341                        let buf = self.descriptor_buf();
342                        let len = desc.write_to(buf);
343                        let end = min(len, requested_length as usize);
344                        self.state[endpoint].set(State::CtrlIn(0, end));
345                        hil::usb::CtrlSetupResult::Ok
346                    } else {
347                        hil::usb::CtrlSetupResult::ErrGeneric
348                    }
349                }
350                DescriptorType::Report => {
351                    if let Some(desc) = self.report_descriptor {
352                        let buf = self.descriptor_buf();
353                        let len = desc.write_to(buf);
354                        let end = min(len, requested_length as usize);
355                        self.state[endpoint].set(State::CtrlIn(0, end));
356                        hil::usb::CtrlSetupResult::Ok
357                    } else {
358                        hil::usb::CtrlSetupResult::ErrGeneric
359                    }
360                }
361                _ => hil::usb::CtrlSetupResult::ErrGeneric,
362            },
363            _ => hil::usb::CtrlSetupResult::ErrGeneric,
364        }
365    }
366
367    /// Handle a Control In transaction
368    pub fn ctrl_in(&'a self, endpoint: usize) -> hil::usb::CtrlInResult {
369        match self.state[endpoint].get() {
370            State::CtrlIn(start, end) => {
371                let len = end.saturating_sub(start);
372                if len > 0 {
373                    let packet_bytes = min(self.ctrl_buffer.buf.len(), len);
374                    let packet = &self.descriptor_storage[start..start + packet_bytes];
375                    let buf = &self.ctrl_buffer.buf;
376
377                    // Copy a packet into the endpoint buffer
378                    for (i, b) in packet.iter().enumerate() {
379                        buf[i].set(b.get());
380                    }
381
382                    let start = start + packet_bytes;
383                    let len = end.saturating_sub(start);
384                    let transfer_complete = len == 0;
385
386                    self.state[endpoint].set(State::CtrlIn(start, end));
387
388                    hil::usb::CtrlInResult::Packet(packet_bytes, transfer_complete)
389                } else {
390                    hil::usb::CtrlInResult::Packet(0, true)
391                }
392            }
393            _ => hil::usb::CtrlInResult::Error,
394        }
395    }
396
397    /// Handle a Control Out transaction
398    pub fn ctrl_out(&'a self, endpoint: usize, _packet_bytes: u32) -> hil::usb::CtrlOutResult {
399        match self.state[endpoint].get() {
400            State::CtrlOut => {
401                // Gamely accept the data
402                hil::usb::CtrlOutResult::Ok
403            }
404            _ => {
405                // Bad state
406                hil::usb::CtrlOutResult::Halted
407            }
408        }
409    }
410
411    pub fn ctrl_status(&'a self, _endpoint: usize) {
412        // Entered Status stage
413    }
414
415    /// Handle the completion of a Control transfer
416    pub fn ctrl_status_complete(&'a self, endpoint: usize) {
417        // Control Read: IN request acknowledged
418        // Control Write: status sent
419
420        match self.state[endpoint].get() {
421            State::SetAddress => {
422                self.controller.enable_address();
423            }
424            _ => {}
425        }
426        self.state[endpoint].set(State::Init);
427    }
428}