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