capsules_extra/
usb_hid_driver.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//! Provides userspace with access to USB HID devices with a simple syscall
6//! interface.
7
8use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
9use kernel::hil::usb_hid;
10use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
11use kernel::syscall::{CommandReturn, SyscallDriver};
12use kernel::utilities::cells::{OptionalCell, TakeCell};
13use kernel::{ErrorCode, ProcessId};
14
15/// Ids for read-write allow buffers
16mod rw_allow {
17    pub const RECV: usize = 0;
18    pub const SEND: usize = 1;
19    /// The number of allow buffers the kernel stores for this grant
20    pub const COUNT: u8 = 2;
21}
22
23#[derive(Default)]
24pub struct App {}
25
26pub struct UsbHidDriver<'a, U: usb_hid::UsbHid<'a, [u8; 64]>> {
27    usb: &'a U,
28
29    app: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<{ rw_allow::COUNT }>>,
30    processid: OptionalCell<ProcessId>,
31
32    send_buffer: TakeCell<'static, [u8; 64]>,
33    recv_buffer: TakeCell<'static, [u8; 64]>,
34}
35
36impl<'a, U: usb_hid::UsbHid<'a, [u8; 64]>> UsbHidDriver<'a, U> {
37    pub fn new(
38        usb: &'a U,
39        send_buffer: &'static mut [u8; 64],
40        recv_buffer: &'static mut [u8; 64],
41        grant: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<{ rw_allow::COUNT }>>,
42    ) -> UsbHidDriver<'a, U> {
43        UsbHidDriver {
44            usb,
45            app: grant,
46            processid: OptionalCell::empty(),
47            send_buffer: TakeCell::new(send_buffer),
48            recv_buffer: TakeCell::new(recv_buffer),
49        }
50    }
51}
52
53impl<'a, U: usb_hid::UsbHid<'a, [u8; 64]>> usb_hid::UsbHid<'a, [u8; 64]> for UsbHidDriver<'a, U> {
54    fn send_buffer(
55        &'a self,
56        send: &'static mut [u8; 64],
57    ) -> Result<usize, (ErrorCode, &'static mut [u8; 64])> {
58        self.usb.send_buffer(send)
59    }
60
61    fn send_cancel(&'a self) -> Result<&'static mut [u8; 64], ErrorCode> {
62        self.usb.send_cancel()
63    }
64
65    fn receive_buffer(
66        &'a self,
67        recv: &'static mut [u8; 64],
68    ) -> Result<(), (ErrorCode, &'static mut [u8; 64])> {
69        self.usb.receive_buffer(recv)
70    }
71
72    fn receive_cancel(&'a self) -> Result<&'static mut [u8; 64], ErrorCode> {
73        self.usb.receive_cancel()
74    }
75}
76
77impl<'a, U: usb_hid::UsbHid<'a, [u8; 64]>> usb_hid::Client<'a, [u8; 64]> for UsbHidDriver<'a, U> {
78    fn packet_received(
79        &'a self,
80        _result: Result<(), ErrorCode>,
81        buffer: &'static mut [u8; 64],
82        _endpoint: usize,
83    ) {
84        self.processid.map(|id| {
85            let _ = self.app.enter(id, |_app, kernel_data| {
86                let _ = kernel_data
87                    .get_readwrite_processbuffer(rw_allow::RECV)
88                    .and_then(|recv| {
89                        recv.mut_enter(|dest| {
90                            dest.copy_from_slice(buffer);
91                        })
92                    });
93
94                kernel_data.schedule_upcall(0, (0, 0, 0)).ok();
95            });
96        });
97
98        self.recv_buffer.replace(buffer);
99    }
100
101    fn packet_transmitted(
102        &'a self,
103        _result: Result<(), ErrorCode>,
104        buffer: &'static mut [u8; 64],
105        _endpoint: usize,
106    ) {
107        self.processid.map(|id| {
108            let _ = self.app.enter(id, |_app, kernel_data| {
109                kernel_data.schedule_upcall(0, (1, 0, 0)).ok();
110            });
111        });
112
113        // Save our send buffer so we can use it later
114        self.send_buffer.replace(buffer);
115    }
116}
117
118impl<'a, U: usb_hid::UsbHid<'a, [u8; 64]>> SyscallDriver for UsbHidDriver<'a, U> {
119    // Subscribe to UsbHidDriver events.
120    //
121    // ### `subscribe_num`
122    //
123    // - `0`: Subscribe to interrupts from HID events.
124    //        The callback signature is `fn(direction: u32)`
125    //        `fn(0)` indicates a packet was received
126    //        `fn(1)` indicates a packet was transmitted
127
128    fn command(
129        &self,
130        command_num: usize,
131        _data1: usize,
132        _data2: usize,
133        processid: ProcessId,
134    ) -> CommandReturn {
135        let can_access = self.processid.map_or_else(
136            || {
137                self.processid.set(processid);
138                true
139            },
140            |owning_app| {
141                // Check if we own the HID device
142                owning_app == processid
143            },
144        );
145
146        if !can_access {
147            return CommandReturn::failure(ErrorCode::BUSY);
148        }
149
150        match command_num {
151            0 => CommandReturn::success(),
152
153            // Send data
154            1 => self
155                .app
156                .enter(processid, |_, kernel_data| {
157                    self.processid.set(processid);
158                    kernel_data
159                        .get_readwrite_processbuffer(rw_allow::SEND)
160                        .and_then(|send| {
161                            send.enter(|data| {
162                                self.send_buffer.take().map_or(
163                                    CommandReturn::failure(ErrorCode::BUSY),
164                                    |buf| {
165                                        // Copy the data into the static buffer
166                                        data.copy_to_slice(buf);
167
168                                        let _ = self.usb.send_buffer(buf);
169                                        CommandReturn::success()
170                                    },
171                                )
172                            })
173                        })
174                        .unwrap_or(CommandReturn::failure(ErrorCode::RESERVE))
175                })
176                .unwrap_or_else(|err| err.into()),
177
178            // Allow receive
179            2 => self
180                .app
181                .enter(processid, |_app, _| {
182                    self.processid.set(processid);
183                    if let Some(buf) = self.recv_buffer.take() {
184                        match self.usb.receive_buffer(buf) {
185                            Ok(()) => CommandReturn::success(),
186                            Err((err, buffer)) => {
187                                self.recv_buffer.replace(buffer);
188                                CommandReturn::failure(err)
189                            }
190                        }
191                    } else {
192                        CommandReturn::failure(ErrorCode::BUSY)
193                    }
194                })
195                .unwrap_or_else(|err| err.into()),
196
197            // Cancel send
198            3 => self
199                .app
200                .enter(processid, |_app, _| {
201                    self.processid.set(processid);
202                    match self.usb.receive_cancel() {
203                        Ok(buf) => {
204                            self.recv_buffer.replace(buf);
205                            CommandReturn::success()
206                        }
207                        Err(err) => CommandReturn::failure(err),
208                    }
209                })
210                .unwrap_or_else(|err| err.into()),
211
212            // Cancel receive
213            4 => self
214                .app
215                .enter(processid, |_app, _| {
216                    self.processid.set(processid);
217                    match self.usb.receive_cancel() {
218                        Ok(buf) => {
219                            self.recv_buffer.replace(buf);
220                            CommandReturn::success()
221                        }
222                        Err(err) => CommandReturn::failure(err),
223                    }
224                })
225                .unwrap_or_else(|err| err.into()),
226
227            // Send or receive
228            // This command has two parts.
229            //    Part 1: Receive
230            //            This will allow receives, the same as the Allow
231            //            receive command above. If data is ready to receive
232            //            the `packet_received()` callback will be called.
233            //            When this happens the client callback will be
234            //            scheduled and no send event will occur.
235            //    Part 2: Send
236            //            If no receive occurs we will be left in a start where
237            //            future recieves will be allowed. This is the same
238            //            outcome as calling the Allow receive command.
239            //            As well as that we will then send the data in the
240            //            send buffer.
241            5 => self
242                .app
243                .enter(processid, |_app, kernel_data| {
244                    // First we try to setup a receive. If there is already
245                    // a receive we return `ErrorCode::ALREADY`. If the
246                    // receive fails we return an error.
247                    if let Some(buf) = self.recv_buffer.take() {
248                        if let Err((err, buffer)) = self.usb.receive_buffer(buf) {
249                            self.recv_buffer.replace(buffer);
250                            return CommandReturn::failure(err);
251                        }
252                    } else {
253                        return CommandReturn::failure(ErrorCode::ALREADY);
254                    }
255
256                    // If we were able to setup a read then next we do the
257                    // transmit.
258                    kernel_data
259                        .get_readwrite_processbuffer(rw_allow::SEND)
260                        .and_then(|send| {
261                            send.enter(|data| {
262                                self.send_buffer.take().map_or(
263                                    CommandReturn::failure(ErrorCode::BUSY),
264                                    |buf| {
265                                        // Copy the data into the static buffer
266                                        data.copy_to_slice(buf);
267
268                                        let _ = self.usb.send_buffer(buf);
269                                        CommandReturn::success()
270                                    },
271                                )
272                            })
273                        })
274                        .unwrap_or(CommandReturn::failure(ErrorCode::FAIL))
275                })
276                .unwrap_or_else(|err| err.into()),
277
278            // default
279            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
280        }
281    }
282
283    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
284        self.app.enter(processid, |_, _| {})
285    }
286}