1 //! Driver for VirtIO input devices.
2 
3 use super::common::Feature;
4 use crate::hal::Hal;
5 use crate::queue::VirtQueue;
6 use crate::transport::Transport;
7 use crate::volatile::{volread, volwrite, ReadOnly, VolatileReadable, WriteOnly};
8 use crate::Error;
9 use alloc::{boxed::Box, string::String};
10 use core::cmp::min;
11 use core::mem::size_of;
12 use core::ptr::{addr_of, NonNull};
13 use zerocopy::{AsBytes, FromBytes, FromZeroes};
14 
15 /// Virtual human interface devices such as keyboards, mice and tablets.
16 ///
17 /// An instance of the virtio device represents one such input device.
18 /// Device behavior mirrors that of the evdev layer in Linux,
19 /// making pass-through implementations on top of evdev easy.
20 pub struct VirtIOInput<H: Hal, T: Transport> {
21     transport: T,
22     event_queue: VirtQueue<H, QUEUE_SIZE>,
23     status_queue: VirtQueue<H, QUEUE_SIZE>,
24     event_buf: Box<[InputEvent; 32]>,
25     config: NonNull<Config>,
26 }
27 
28 impl<H: Hal, T: Transport> VirtIOInput<H, T> {
29     /// Create a new VirtIO-Input driver.
new(mut transport: T) -> Result<Self, Error>30     pub fn new(mut transport: T) -> Result<Self, Error> {
31         let mut event_buf = Box::new([InputEvent::default(); QUEUE_SIZE]);
32 
33         let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
34 
35         let config = transport.config_space::<Config>()?;
36 
37         let mut event_queue = VirtQueue::new(
38             &mut transport,
39             QUEUE_EVENT,
40             negotiated_features.contains(Feature::RING_INDIRECT_DESC),
41             negotiated_features.contains(Feature::RING_EVENT_IDX),
42         )?;
43         let status_queue = VirtQueue::new(
44             &mut transport,
45             QUEUE_STATUS,
46             negotiated_features.contains(Feature::RING_INDIRECT_DESC),
47             negotiated_features.contains(Feature::RING_EVENT_IDX),
48         )?;
49         for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
50             // Safe because the buffer lasts as long as the queue.
51             let token = unsafe { event_queue.add(&[], &mut [event.as_bytes_mut()])? };
52             assert_eq!(token, i as u16);
53         }
54         if event_queue.should_notify() {
55             transport.notify(QUEUE_EVENT);
56         }
57 
58         transport.finish_init();
59 
60         Ok(VirtIOInput {
61             transport,
62             event_queue,
63             status_queue,
64             event_buf,
65             config,
66         })
67     }
68 
69     /// Acknowledge interrupt and process events.
ack_interrupt(&mut self) -> bool70     pub fn ack_interrupt(&mut self) -> bool {
71         self.transport.ack_interrupt()
72     }
73 
74     /// Pop the pending event.
pop_pending_event(&mut self) -> Option<InputEvent>75     pub fn pop_pending_event(&mut self) -> Option<InputEvent> {
76         if let Some(token) = self.event_queue.peek_used() {
77             let event = &mut self.event_buf[token as usize];
78             // Safe because we are passing the same buffer as we passed to `VirtQueue::add` and it
79             // is still valid.
80             unsafe {
81                 self.event_queue
82                     .pop_used(token, &[], &mut [event.as_bytes_mut()])
83                     .ok()?;
84             }
85             let event_saved = *event;
86             // requeue
87             // Safe because buffer lasts as long as the queue.
88             if let Ok(new_token) = unsafe { self.event_queue.add(&[], &mut [event.as_bytes_mut()]) }
89             {
90                 // This only works because nothing happen between `pop_used` and `add` that affects
91                 // the list of free descriptors in the queue, so `add` reuses the descriptor which
92                 // was just freed by `pop_used`.
93                 assert_eq!(new_token, token);
94                 if self.event_queue.should_notify() {
95                     self.transport.notify(QUEUE_EVENT);
96                 }
97                 return Some(event_saved);
98             }
99         }
100         None
101     }
102 
103     /// Query a specific piece of information by `select` and `subsel`, and write
104     /// result to `out`, return the result size.
query_config_select( &mut self, select: InputConfigSelect, subsel: u8, out: &mut [u8], ) -> u8105     pub fn query_config_select(
106         &mut self,
107         select: InputConfigSelect,
108         subsel: u8,
109         out: &mut [u8],
110     ) -> u8 {
111         let size;
112         // Safe because config points to a valid MMIO region for the config space.
113         unsafe {
114             volwrite!(self.config, select, select as u8);
115             volwrite!(self.config, subsel, subsel);
116             size = volread!(self.config, size);
117             let size_to_copy = min(usize::from(size), out.len());
118             for (i, out_item) in out.iter_mut().take(size_to_copy).enumerate() {
119                 *out_item = addr_of!((*self.config.as_ptr()).data[i]).vread();
120             }
121         }
122         size
123     }
124 
125     /// Queries a specific piece of information by `select` and `subsel`, allocates a sufficiently
126     /// large byte buffer for it, and returns it.
query_config_select_alloc( &mut self, select: InputConfigSelect, subsel: u8, ) -> Result<Box<[u8]>, Error>127     fn query_config_select_alloc(
128         &mut self,
129         select: InputConfigSelect,
130         subsel: u8,
131     ) -> Result<Box<[u8]>, Error> {
132         // Safe because config points to a valid MMIO region for the config space.
133         unsafe {
134             volwrite!(self.config, select, select as u8);
135             volwrite!(self.config, subsel, subsel);
136             let size = usize::from(volread!(self.config, size));
137             if size > CONFIG_DATA_MAX_LENGTH {
138                 return Err(Error::IoError);
139             }
140             let mut buf = u8::new_box_slice_zeroed(size);
141             for i in 0..size {
142                 buf[i] = addr_of!((*self.config.as_ptr()).data[i]).vread();
143             }
144             Ok(buf)
145         }
146     }
147 
148     /// Queries a specific piece of information by `select` and `subsel` into a newly-allocated
149     /// buffer, and tries to convert it to a string.
150     ///
151     /// Returns an error if it is not valid UTF-8.
query_config_string( &mut self, select: InputConfigSelect, subsel: u8, ) -> Result<String, Error>152     fn query_config_string(
153         &mut self,
154         select: InputConfigSelect,
155         subsel: u8,
156     ) -> Result<String, Error> {
157         Ok(String::from_utf8(
158             self.query_config_select_alloc(select, subsel)?.into(),
159         )?)
160     }
161 
162     /// Queries and returns the name of the device, or an error if it is not valid UTF-8.
name(&mut self) -> Result<String, Error>163     pub fn name(&mut self) -> Result<String, Error> {
164         self.query_config_string(InputConfigSelect::IdName, 0)
165     }
166 
167     /// Queries and returns the serial number of the device, or an error if it is not valid UTF-8.
serial_number(&mut self) -> Result<String, Error>168     pub fn serial_number(&mut self) -> Result<String, Error> {
169         self.query_config_string(InputConfigSelect::IdSerial, 0)
170     }
171 
172     /// Queries and returns the ID information of the device.
ids(&mut self) -> Result<DevIDs, Error>173     pub fn ids(&mut self) -> Result<DevIDs, Error> {
174         let mut ids = DevIDs::default();
175         let size = self.query_config_select(InputConfigSelect::IdDevids, 0, ids.as_bytes_mut());
176         if usize::from(size) == size_of::<DevIDs>() {
177             Ok(ids)
178         } else {
179             Err(Error::IoError)
180         }
181     }
182 
183     /// Queries and returns the input properties of the device.
prop_bits(&mut self) -> Result<Box<[u8]>, Error>184     pub fn prop_bits(&mut self) -> Result<Box<[u8]>, Error> {
185         self.query_config_select_alloc(InputConfigSelect::PropBits, 0)
186     }
187 
188     /// Queries and returns a bitmap of supported event codes for the given event type.
189     ///
190     /// If the event type is not supported an empty slice will be returned.
ev_bits(&mut self, event_type: u8) -> Result<Box<[u8]>, Error>191     pub fn ev_bits(&mut self, event_type: u8) -> Result<Box<[u8]>, Error> {
192         self.query_config_select_alloc(InputConfigSelect::EvBits, event_type)
193     }
194 
195     /// Queries and returns information about the given axis of the device.
abs_info(&mut self, axis: u8) -> Result<AbsInfo, Error>196     pub fn abs_info(&mut self, axis: u8) -> Result<AbsInfo, Error> {
197         let mut info = AbsInfo::default();
198         let size = self.query_config_select(InputConfigSelect::AbsInfo, axis, info.as_bytes_mut());
199         if usize::from(size) == size_of::<AbsInfo>() {
200             Ok(info)
201         } else {
202             Err(Error::IoError)
203         }
204     }
205 }
206 
207 // SAFETY: The config space can be accessed from any thread.
208 unsafe impl<H: Hal, T: Transport + Send> Send for VirtIOInput<H, T> where
209     VirtQueue<H, QUEUE_SIZE>: Send
210 {
211 }
212 
213 // SAFETY: An '&VirtIOInput` can't do anything, all methods take `&mut self`.
214 unsafe impl<H: Hal, T: Transport + Sync> Sync for VirtIOInput<H, T> where
215     VirtQueue<H, QUEUE_SIZE>: Sync
216 {
217 }
218 
219 impl<H: Hal, T: Transport> Drop for VirtIOInput<H, T> {
drop(&mut self)220     fn drop(&mut self) {
221         // Clear any pointers pointing to DMA regions, so the device doesn't try to access them
222         // after they have been freed.
223         self.transport.queue_unset(QUEUE_EVENT);
224         self.transport.queue_unset(QUEUE_STATUS);
225     }
226 }
227 
228 const CONFIG_DATA_MAX_LENGTH: usize = 128;
229 
230 /// Select value used for [`VirtIOInput::query_config_select()`].
231 #[repr(u8)]
232 #[derive(Debug, Clone, Copy)]
233 pub enum InputConfigSelect {
234     /// Returns the name of the device, in u.string. subsel is zero.
235     IdName = 0x01,
236     /// Returns the serial number of the device, in u.string. subsel is zero.
237     IdSerial = 0x02,
238     /// Returns ID information of the device, in u.ids. subsel is zero.
239     IdDevids = 0x03,
240     /// Returns input properties of the device, in u.bitmap. subsel is zero.
241     /// Individual bits in the bitmap correspond to INPUT_PROP_* constants used
242     /// by the underlying evdev implementation.
243     PropBits = 0x10,
244     /// subsel specifies the event type using EV_* constants in the underlying
245     /// evdev implementation. If size is non-zero the event type is supported
246     /// and a bitmap of supported event codes is returned in u.bitmap. Individual
247     /// bits in the bitmap correspond to implementation-defined input event codes,
248     /// for example keys or pointing device axes.
249     EvBits = 0x11,
250     /// subsel specifies the absolute axis using ABS_* constants in the underlying
251     /// evdev implementation. Information about the axis will be returned in u.abs.
252     AbsInfo = 0x12,
253 }
254 
255 #[repr(C)]
256 struct Config {
257     select: WriteOnly<u8>,
258     subsel: WriteOnly<u8>,
259     size: ReadOnly<u8>,
260     _reserved: [ReadOnly<u8>; 5],
261     data: [ReadOnly<u8>; CONFIG_DATA_MAX_LENGTH],
262 }
263 
264 /// Information about an axis of an input device, typically a joystick.
265 #[repr(C)]
266 #[derive(AsBytes, Clone, Debug, Default, Eq, PartialEq, FromBytes, FromZeroes)]
267 pub struct AbsInfo {
268     /// The minimum value for the axis.
269     pub min: u32,
270     /// The maximum value for the axis.
271     pub max: u32,
272     /// The fuzz value used to filter noise from the event stream.
273     pub fuzz: u32,
274     /// The size of the dead zone; values less than this will be reported as 0.
275     pub flat: u32,
276     /// The resolution for values reported for the axis.
277     pub res: u32,
278 }
279 
280 /// The identifiers of a VirtIO input device.
281 #[repr(C)]
282 #[derive(AsBytes, Clone, Debug, Default, Eq, PartialEq, FromBytes, FromZeroes)]
283 pub struct DevIDs {
284     /// The bustype identifier.
285     pub bustype: u16,
286     /// The vendor identifier.
287     pub vendor: u16,
288     /// The product identifier.
289     pub product: u16,
290     /// The version identifier.
291     pub version: u16,
292 }
293 
294 /// Both queues use the same `virtio_input_event` struct. `type`, `code` and `value`
295 /// are filled according to the Linux input layer (evdev) interface.
296 #[repr(C)]
297 #[derive(AsBytes, Clone, Copy, Debug, Default, FromBytes, FromZeroes)]
298 pub struct InputEvent {
299     /// Event type.
300     pub event_type: u16,
301     /// Event code.
302     pub code: u16,
303     /// Event value.
304     pub value: u32,
305 }
306 
307 const QUEUE_EVENT: u16 = 0;
308 const QUEUE_STATUS: u16 = 1;
309 const SUPPORTED_FEATURES: Feature = Feature::RING_EVENT_IDX.union(Feature::RING_INDIRECT_DESC);
310 
311 // a parameter that can change
312 const QUEUE_SIZE: usize = 32;
313 
314 #[cfg(test)]
315 mod tests {
316     use super::*;
317     use crate::{
318         hal::fake::FakeHal,
319         transport::{
320             fake::{FakeTransport, QueueStatus, State},
321             DeviceType,
322         },
323     };
324     use alloc::{sync::Arc, vec};
325     use core::convert::TryInto;
326     use std::sync::Mutex;
327 
328     #[test]
config()329     fn config() {
330         const DEFAULT_DATA: ReadOnly<u8> = ReadOnly::new(0);
331         let mut config_space = Config {
332             select: WriteOnly::default(),
333             subsel: WriteOnly::default(),
334             size: ReadOnly::new(0),
335             _reserved: Default::default(),
336             data: [DEFAULT_DATA; 128],
337         };
338         let state = Arc::new(Mutex::new(State {
339             queues: vec![QueueStatus::default(), QueueStatus::default()],
340             ..Default::default()
341         }));
342         let transport = FakeTransport {
343             device_type: DeviceType::Block,
344             max_queue_size: QUEUE_SIZE.try_into().unwrap(),
345             device_features: 0,
346             config_space: NonNull::from(&mut config_space),
347             state: state.clone(),
348         };
349         let mut input = VirtIOInput::<FakeHal, FakeTransport<Config>>::new(transport).unwrap();
350 
351         set_data(&mut config_space, "Test input device".as_bytes());
352         assert_eq!(input.name().unwrap(), "Test input device");
353         assert_eq!(config_space.select.0, InputConfigSelect::IdName as u8);
354         assert_eq!(config_space.subsel.0, 0);
355 
356         set_data(&mut config_space, "Serial number".as_bytes());
357         assert_eq!(input.serial_number().unwrap(), "Serial number");
358         assert_eq!(config_space.select.0, InputConfigSelect::IdSerial as u8);
359         assert_eq!(config_space.subsel.0, 0);
360 
361         let ids = DevIDs {
362             bustype: 0x4242,
363             product: 0x0067,
364             vendor: 0x1234,
365             version: 0x4321,
366         };
367         set_data(&mut config_space, ids.as_bytes());
368         assert_eq!(input.ids().unwrap(), ids);
369         assert_eq!(config_space.select.0, InputConfigSelect::IdDevids as u8);
370         assert_eq!(config_space.subsel.0, 0);
371 
372         set_data(&mut config_space, &[0x12, 0x34, 0x56]);
373         assert_eq!(input.prop_bits().unwrap().as_ref(), &[0x12, 0x34, 0x56]);
374         assert_eq!(config_space.select.0, InputConfigSelect::PropBits as u8);
375         assert_eq!(config_space.subsel.0, 0);
376 
377         set_data(&mut config_space, &[0x42, 0x66]);
378         assert_eq!(input.ev_bits(3).unwrap().as_ref(), &[0x42, 0x66]);
379         assert_eq!(config_space.select.0, InputConfigSelect::EvBits as u8);
380         assert_eq!(config_space.subsel.0, 3);
381 
382         let abs_info = AbsInfo {
383             min: 12,
384             max: 1234,
385             fuzz: 4,
386             flat: 10,
387             res: 2,
388         };
389         set_data(&mut config_space, abs_info.as_bytes());
390         assert_eq!(input.abs_info(5).unwrap(), abs_info);
391         assert_eq!(config_space.select.0, InputConfigSelect::AbsInfo as u8);
392         assert_eq!(config_space.subsel.0, 5);
393     }
394 
set_data(config_space: &mut Config, value: &[u8])395     fn set_data(config_space: &mut Config, value: &[u8]) {
396         config_space.size.0 = value.len().try_into().unwrap();
397         for (i, &byte) in value.into_iter().enumerate() {
398             config_space.data[i].0 = byte;
399         }
400     }
401 }
402