xref: /aosp_15_r20/external/crosvm/devices/src/virtio/input/mod.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #[allow(dead_code)]
6 mod defaults;
7 mod evdev;
8 mod event_source;
9 
10 use std::collections::BTreeMap;
11 use std::fs;
12 use std::io::Read;
13 use std::io::Write;
14 use std::path::PathBuf;
15 
16 use anyhow::anyhow;
17 use anyhow::bail;
18 use anyhow::Context;
19 use base::custom_serde::deserialize_seq_to_arr;
20 use base::custom_serde::serialize_arr;
21 use base::error;
22 use base::info;
23 use base::warn;
24 use base::AsRawDescriptor;
25 use base::Event;
26 use base::EventToken;
27 use base::RawDescriptor;
28 use base::WaitContext;
29 use base::WorkerThread;
30 use data_model::Le16;
31 use data_model::Le32;
32 use linux_input_sys::constants::*;
33 use linux_input_sys::virtio_input_event;
34 use linux_input_sys::InputEventDecoder;
35 use remain::sorted;
36 use serde::Deserialize;
37 use serde::Serialize;
38 use thiserror::Error;
39 use vm_memory::GuestMemory;
40 use zerocopy::AsBytes;
41 use zerocopy::FromBytes;
42 use zerocopy::FromZeroes;
43 
44 use self::event_source::EvdevEventSource;
45 use self::event_source::EventSource;
46 use self::event_source::SocketEventSource;
47 use super::copy_config;
48 use super::DescriptorChain;
49 use super::DeviceType;
50 use super::Interrupt;
51 use super::Queue;
52 use super::VirtioDevice;
53 
54 const EVENT_QUEUE_SIZE: u16 = 64;
55 const STATUS_QUEUE_SIZE: u16 = 64;
56 const QUEUE_SIZES: &[u16] = &[EVENT_QUEUE_SIZE, STATUS_QUEUE_SIZE];
57 
58 #[sorted]
59 #[derive(Error, Debug)]
60 pub enum InputError {
61     // Failed to get axis information of event device
62     #[error("failed to get axis information of event device: {0}")]
63     EvdevAbsInfoError(base::Error),
64     // Failed to get event types supported by device
65     #[error("failed to get event types supported by device: {0}")]
66     EvdevEventTypesError(base::Error),
67     // Failed to grab event device
68     #[error("failed to grab event device: {0}")]
69     EvdevGrabError(base::Error),
70     // Failed to get name of event device
71     #[error("failed to get id of event device: {0}")]
72     EvdevIdError(base::Error),
73     // Failed to get name of event device
74     #[error("failed to get name of event device: {0}")]
75     EvdevNameError(base::Error),
76     // Failed to get properties of event device
77     #[error("failed to get properties of event device: {0}")]
78     EvdevPropertiesError(base::Error),
79     // Failed to get serial name of event device
80     #[error("failed to get serial name of event device: {0}")]
81     EvdevSerialError(base::Error),
82     /// Failed to read events from the source
83     #[error("failed to read events from the source: {0}")]
84     EventsReadError(std::io::Error),
85     /// Failed to write events to the source
86     #[error("failed to write events to the source: {0}")]
87     EventsWriteError(std::io::Error),
88     // Detected error on guest side
89     #[error("detected error on guest side: {0}")]
90     GuestError(String),
91     // Invalid UTF-8 string
92     #[error("invalid UTF-8 string: {0}")]
93     InvalidString(std::string::FromUtf8Error),
94     // Failed to parse event config file
95     #[error("failed to parse event config file: {0}")]
96     ParseEventConfigError(String),
97     // Error while reading from virtqueue
98     #[error("failed to read from virtqueue: {0}")]
99     ReadQueue(std::io::Error),
100     // Error while writing to virtqueue
101     #[error("failed to write to virtqueue: {0}")]
102     WriteQueue(std::io::Error),
103 }
104 
105 pub type Result<T> = std::result::Result<T, InputError>;
106 
107 #[derive(Copy, Clone, Default, Debug, AsBytes, FromZeroes, FromBytes, Serialize, Deserialize)]
108 #[repr(C)]
109 pub struct virtio_input_device_ids {
110     bustype: Le16,
111     vendor: Le16,
112     product: Le16,
113     version: Le16,
114 }
115 
116 impl virtio_input_device_ids {
new(bustype: u16, product: u16, vendor: u16, version: u16) -> virtio_input_device_ids117     fn new(bustype: u16, product: u16, vendor: u16, version: u16) -> virtio_input_device_ids {
118         virtio_input_device_ids {
119             bustype: Le16::from(bustype),
120             vendor: Le16::from(vendor),
121             product: Le16::from(product),
122             version: Le16::from(version),
123         }
124     }
125 }
126 
127 #[derive(Copy, Clone, Default, Debug, AsBytes, FromZeroes, FromBytes, Serialize, Deserialize)]
128 #[repr(C)]
129 pub struct virtio_input_absinfo {
130     min: Le32,
131     max: Le32,
132     fuzz: Le32,
133     flat: Le32,
134 }
135 
136 impl virtio_input_absinfo {
new(min: u32, max: u32, fuzz: u32, flat: u32) -> virtio_input_absinfo137     fn new(min: u32, max: u32, fuzz: u32, flat: u32) -> virtio_input_absinfo {
138         virtio_input_absinfo {
139             min: Le32::from(min),
140             max: Le32::from(max),
141             fuzz: Le32::from(fuzz),
142             flat: Le32::from(flat),
143         }
144     }
145 }
146 
147 #[derive(Copy, Clone, AsBytes, FromZeroes, FromBytes)]
148 #[repr(C)]
149 struct virtio_input_config {
150     select: u8,
151     subsel: u8,
152     size: u8,
153     reserved: [u8; 5],
154     payload: [u8; 128],
155 }
156 
157 impl virtio_input_config {
new() -> virtio_input_config158     fn new() -> virtio_input_config {
159         virtio_input_config {
160             select: 0,
161             subsel: 0,
162             size: 0,
163             reserved: [0u8; 5],
164             payload: [0u8; 128],
165         }
166     }
167 
set_payload_slice(&mut self, slice: &[u8])168     fn set_payload_slice(&mut self, slice: &[u8]) {
169         let bytes_written = match (&mut self.payload[..]).write(slice) {
170             Ok(x) => x,
171             Err(_) => {
172                 // This won't happen because write is guaranteed to succeed with slices
173                 unreachable!();
174             }
175         };
176         self.size = bytes_written as u8;
177         if bytes_written < slice.len() {
178             // This shouldn't happen since everywhere this function is called the size is guaranteed
179             // to be at most 128 bytes (the size of the payload)
180             warn!("Slice is too long to fit in payload");
181         }
182     }
183 
set_payload_str(&mut self, s: &str)184     fn set_payload_str(&mut self, s: &str) {
185         self.set_payload_slice(s.as_bytes());
186     }
187 
set_payload_bitmap(&mut self, bitmap: &virtio_input_bitmap)188     fn set_payload_bitmap(&mut self, bitmap: &virtio_input_bitmap) {
189         self.size = bitmap.min_size();
190         self.payload.copy_from_slice(&bitmap.bitmap);
191     }
192 
set_absinfo(&mut self, absinfo: &virtio_input_absinfo)193     fn set_absinfo(&mut self, absinfo: &virtio_input_absinfo) {
194         self.set_payload_slice(absinfo.as_bytes());
195     }
196 
set_device_ids(&mut self, device_ids: &virtio_input_device_ids)197     fn set_device_ids(&mut self, device_ids: &virtio_input_device_ids) {
198         self.set_payload_slice(device_ids.as_bytes());
199     }
200 }
201 
202 #[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
203 #[repr(C)]
204 pub struct virtio_input_bitmap {
205     #[serde(
206         serialize_with = "serialize_arr",
207         deserialize_with = "deserialize_seq_to_arr"
208     )]
209     bitmap: [u8; 128],
210 }
211 
212 impl virtio_input_bitmap {
new(bitmap: [u8; 128]) -> virtio_input_bitmap213     fn new(bitmap: [u8; 128]) -> virtio_input_bitmap {
214         virtio_input_bitmap { bitmap }
215     }
216 
len(&self) -> usize217     fn len(&self) -> usize {
218         self.bitmap.len()
219     }
220 
221     // Creates a bitmap from an array of bit indices
from_bits(set_indices: &[u16]) -> virtio_input_bitmap222     fn from_bits(set_indices: &[u16]) -> virtio_input_bitmap {
223         let mut ret = virtio_input_bitmap { bitmap: [0u8; 128] };
224         for idx in set_indices {
225             let byte_pos = (idx / 8) as usize;
226             let bit_byte = 1u8 << (idx % 8);
227             if byte_pos < ret.len() {
228                 ret.bitmap[byte_pos] |= bit_byte;
229             } else {
230                 // This would only happen if new event codes (or types, or ABS_*, etc) are defined
231                 // to be larger than or equal to 1024, in which case a new version
232                 // of the virtio input protocol needs to be defined.
233                 // There is nothing we can do about this error except log it.
234                 error!("Attempted to set an out of bounds bit: {}", idx);
235             }
236         }
237         ret
238     }
239 
240     // Returns the length of the minimum array that can hold all set bits in the map
min_size(&self) -> u8241     fn min_size(&self) -> u8 {
242         self.bitmap
243             .iter()
244             .rposition(|v| *v != 0)
245             .map_or(0, |i| i + 1) as u8
246     }
247 }
248 
249 #[derive(Debug, Serialize, Deserialize, Clone)]
250 pub struct VirtioInputConfig {
251     select: u8,
252     subsel: u8,
253     device_ids: virtio_input_device_ids,
254     name: String,
255     serial_name: String,
256     properties: virtio_input_bitmap,
257     supported_events: BTreeMap<u16, virtio_input_bitmap>,
258     axis_info: BTreeMap<u16, virtio_input_absinfo>,
259 }
260 
261 impl VirtioInputConfig {
new( device_ids: virtio_input_device_ids, name: String, serial_name: String, properties: virtio_input_bitmap, supported_events: BTreeMap<u16, virtio_input_bitmap>, axis_info: BTreeMap<u16, virtio_input_absinfo>, ) -> VirtioInputConfig262     fn new(
263         device_ids: virtio_input_device_ids,
264         name: String,
265         serial_name: String,
266         properties: virtio_input_bitmap,
267         supported_events: BTreeMap<u16, virtio_input_bitmap>,
268         axis_info: BTreeMap<u16, virtio_input_absinfo>,
269     ) -> VirtioInputConfig {
270         VirtioInputConfig {
271             select: 0,
272             subsel: 0,
273             device_ids,
274             name,
275             serial_name,
276             properties,
277             supported_events,
278             axis_info,
279         }
280     }
281 
from_evdev<T: AsRawDescriptor>(source: &T) -> Result<VirtioInputConfig>282     fn from_evdev<T: AsRawDescriptor>(source: &T) -> Result<VirtioInputConfig> {
283         Ok(VirtioInputConfig::new(
284             evdev::device_ids(source)?,
285             evdev::name(source)?,
286             evdev::serial_name(source)?,
287             evdev::properties(source)?,
288             evdev::supported_events(source)?,
289             evdev::abs_info(source),
290         ))
291     }
292 
build_config_memory(&self) -> virtio_input_config293     fn build_config_memory(&self) -> virtio_input_config {
294         let mut cfg = virtio_input_config::new();
295         cfg.select = self.select;
296         cfg.subsel = self.subsel;
297         match self.select {
298             VIRTIO_INPUT_CFG_ID_NAME => {
299                 cfg.set_payload_str(&self.name);
300             }
301             VIRTIO_INPUT_CFG_ID_SERIAL => {
302                 cfg.set_payload_str(&self.serial_name);
303             }
304             VIRTIO_INPUT_CFG_PROP_BITS => {
305                 cfg.set_payload_bitmap(&self.properties);
306             }
307             VIRTIO_INPUT_CFG_EV_BITS => {
308                 let ev_type = self.subsel as u16;
309                 // zero is a special case: return all supported event types (just like EVIOCGBIT)
310                 if ev_type == 0 {
311                     let events_bm = virtio_input_bitmap::from_bits(
312                         &self.supported_events.keys().cloned().collect::<Vec<u16>>(),
313                     );
314                     cfg.set_payload_bitmap(&events_bm);
315                 } else if let Some(supported_codes) = self.supported_events.get(&ev_type) {
316                     cfg.set_payload_bitmap(supported_codes);
317                 }
318             }
319             VIRTIO_INPUT_CFG_ABS_INFO => {
320                 let abs_axis = self.subsel as u16;
321                 if let Some(absinfo) = self.axis_info.get(&abs_axis) {
322                     cfg.set_absinfo(absinfo);
323                 } // else all zeroes in the payload
324             }
325             VIRTIO_INPUT_CFG_ID_DEVIDS => {
326                 cfg.set_device_ids(&self.device_ids);
327             }
328             VIRTIO_INPUT_CFG_UNSET => {
329                 // Per the virtio spec at https://docs.oasis-open.org/virtio/virtio/v1.1/cs01/virtio-v1.1-cs01.html#x1-3390008,
330                 // there is no action required of us when this is set. It's unclear whether we
331                 // should be zeroing the virtio_input_config, but empirically we know that the
332                 // existing behavior of doing nothing works with the Linux virtio-input frontend.
333             }
334             _ => {
335                 warn!("Unsuported virtio input config selection: {}", self.select);
336             }
337         }
338         cfg
339     }
340 
read(&self, offset: usize, data: &mut [u8])341     fn read(&self, offset: usize, data: &mut [u8]) {
342         copy_config(
343             data,
344             0,
345             self.build_config_memory().as_bytes(),
346             offset as u64,
347         );
348     }
349 
write(&mut self, offset: usize, data: &[u8])350     fn write(&mut self, offset: usize, data: &[u8]) {
351         let mut config = self.build_config_memory();
352         copy_config(config.as_bytes_mut(), offset as u64, data, 0);
353         self.select = config.select;
354         self.subsel = config.subsel;
355     }
356 }
357 
358 struct Worker<T: EventSource> {
359     interrupt: Interrupt,
360     event_source: T,
361     event_queue: Queue,
362     status_queue: Queue,
363     name: String,
364 }
365 
366 impl<T: EventSource> Worker<T> {
367     // Fills a virtqueue with events from the source.  Returns the number of bytes written.
fill_event_virtqueue( event_source: &mut T, avail_desc: &mut DescriptorChain, ) -> Result<usize>368     fn fill_event_virtqueue(
369         event_source: &mut T,
370         avail_desc: &mut DescriptorChain,
371     ) -> Result<usize> {
372         let writer = &mut avail_desc.writer;
373 
374         while writer.available_bytes() >= virtio_input_event::SIZE {
375             if let Some(evt) = event_source.pop_available_event() {
376                 writer.write_obj(evt).map_err(InputError::WriteQueue)?;
377             } else {
378                 break;
379             }
380         }
381 
382         Ok(writer.bytes_written())
383     }
384 
385     // Send events from the source to the guest
send_events(&mut self) -> bool386     fn send_events(&mut self) -> bool {
387         let mut needs_interrupt = false;
388 
389         // Only consume from the queue iterator if we know we have events to send
390         while self.event_source.available_events_count() > 0 {
391             match self.event_queue.pop() {
392                 None => {
393                     break;
394                 }
395                 Some(mut avail_desc) => {
396                     let bytes_written =
397                         match Worker::fill_event_virtqueue(&mut self.event_source, &mut avail_desc)
398                         {
399                             Ok(count) => count,
400                             Err(e) => {
401                                 error!("Input: failed to send events to guest: {}", e);
402                                 break;
403                             }
404                         };
405 
406                     self.event_queue.add_used(avail_desc, bytes_written as u32);
407                     needs_interrupt = true;
408                 }
409             }
410         }
411 
412         needs_interrupt
413     }
414 
415     // Sends events from the guest to the source.  Returns the number of bytes read.
read_event_virtqueue( avail_desc: &mut DescriptorChain, event_source: &mut T, ) -> Result<usize>416     fn read_event_virtqueue(
417         avail_desc: &mut DescriptorChain,
418         event_source: &mut T,
419     ) -> Result<usize> {
420         let reader = &mut avail_desc.reader;
421         while reader.available_bytes() >= virtio_input_event::SIZE {
422             let evt: virtio_input_event = reader.read_obj().map_err(InputError::ReadQueue)?;
423             event_source.send_event(&evt)?;
424         }
425 
426         Ok(reader.bytes_read())
427     }
428 
process_status_queue(&mut self) -> Result<bool>429     fn process_status_queue(&mut self) -> Result<bool> {
430         let mut needs_interrupt = false;
431         while let Some(mut avail_desc) = self.status_queue.pop() {
432             let bytes_read =
433                 match Worker::read_event_virtqueue(&mut avail_desc, &mut self.event_source) {
434                     Ok(count) => count,
435                     Err(e) => {
436                         error!("Input: failed to read events from virtqueue: {}", e);
437                         return Err(e);
438                     }
439                 };
440 
441             self.status_queue.add_used(avail_desc, bytes_read as u32);
442             needs_interrupt = true;
443         }
444 
445         Ok(needs_interrupt)
446     }
447 
448     // Allow error! and early return anywhere in function
449     #[allow(clippy::needless_return)]
run(&mut self, kill_evt: Event)450     fn run(&mut self, kill_evt: Event) {
451         if let Err(e) = self.event_source.init() {
452             error!("failed initializing event source: {}", e);
453             return;
454         }
455 
456         #[derive(EventToken)]
457         enum Token {
458             EventQAvailable,
459             StatusQAvailable,
460             InputEventsAvailable,
461             InterruptResample,
462             Kill,
463         }
464         let wait_ctx: WaitContext<Token> = match WaitContext::build_with(&[
465             (self.event_queue.event(), Token::EventQAvailable),
466             (self.status_queue.event(), Token::StatusQAvailable),
467             (&self.event_source, Token::InputEventsAvailable),
468             (&kill_evt, Token::Kill),
469         ]) {
470             Ok(wait_ctx) => wait_ctx,
471             Err(e) => {
472                 error!("failed creating WaitContext: {}", e);
473                 return;
474             }
475         };
476         if let Some(resample_evt) = self.interrupt.get_resample_evt() {
477             if wait_ctx
478                 .add(resample_evt, Token::InterruptResample)
479                 .is_err()
480             {
481                 error!("failed adding resample event to WaitContext.");
482                 return;
483             }
484         }
485 
486         'wait: loop {
487             let wait_events = match wait_ctx.wait() {
488                 Ok(wait_events) => wait_events,
489                 Err(e) => {
490                     error!("failed polling for events: {}", e);
491                     break;
492                 }
493             };
494 
495             let mut eventq_needs_interrupt = false;
496             let mut statusq_needs_interrupt = false;
497             for wait_event in wait_events.iter().filter(|e| e.is_readable) {
498                 match wait_event.token {
499                     Token::EventQAvailable => {
500                         if let Err(e) = self.event_queue.event().wait() {
501                             error!("failed reading event queue Event: {}", e);
502                             break 'wait;
503                         }
504                         eventq_needs_interrupt |= self.send_events();
505                     }
506                     Token::StatusQAvailable => {
507                         if let Err(e) = self.status_queue.event().wait() {
508                             error!("failed reading status queue Event: {}", e);
509                             break 'wait;
510                         }
511                         match self.process_status_queue() {
512                             Ok(b) => statusq_needs_interrupt |= b,
513                             Err(e) => error!("failed processing status events: {}", e),
514                         }
515                     }
516                     Token::InputEventsAvailable => match self.event_source.receive_events() {
517                         Err(e) => error!("error receiving events: {}", e),
518                         Ok(_cnt) => eventq_needs_interrupt |= self.send_events(),
519                     },
520                     Token::InterruptResample => {
521                         self.interrupt.interrupt_resample();
522                     }
523                     Token::Kill => {
524                         let _ = kill_evt.wait();
525                         break 'wait;
526                     }
527                 }
528             }
529 
530             for event in wait_events.iter().filter(|e| e.is_hungup) {
531                 if let Token::InputEventsAvailable = event.token {
532                     warn!("input event source for '{}' disconnected", self.name);
533                     let _ = wait_ctx.delete(&self.event_source);
534                 }
535             }
536 
537             if eventq_needs_interrupt {
538                 self.event_queue.trigger_interrupt();
539             }
540             if statusq_needs_interrupt {
541                 self.status_queue.trigger_interrupt();
542             }
543         }
544 
545         if let Err(e) = self.event_source.finalize() {
546             error!("failed finalizing event source: {}", e);
547             return;
548         }
549     }
550 }
551 
552 /// Virtio input device
553 
554 pub struct Input<T: EventSource + Send + 'static> {
555     worker_thread: Option<WorkerThread<Worker<T>>>,
556     config: VirtioInputConfig,
557     source: Option<T>,
558     virtio_features: u64,
559 }
560 
561 /// Snapshot of [Input]'s state.
562 #[derive(Serialize, Deserialize)]
563 struct InputSnapshot {
564     config: VirtioInputConfig,
565     virtio_features: u64,
566 }
567 
568 impl<T> VirtioDevice for Input<T>
569 where
570     T: 'static + EventSource + Send,
571 {
keep_rds(&self) -> Vec<RawDescriptor>572     fn keep_rds(&self) -> Vec<RawDescriptor> {
573         if let Some(source) = &self.source {
574             return vec![source.as_raw_descriptor()];
575         }
576         Vec::new()
577     }
578 
device_type(&self) -> DeviceType579     fn device_type(&self) -> DeviceType {
580         DeviceType::Input
581     }
582 
queue_max_sizes(&self) -> &[u16]583     fn queue_max_sizes(&self) -> &[u16] {
584         QUEUE_SIZES
585     }
586 
read_config(&self, offset: u64, data: &mut [u8])587     fn read_config(&self, offset: u64, data: &mut [u8]) {
588         self.config.read(offset as usize, data);
589     }
590 
write_config(&mut self, offset: u64, data: &[u8])591     fn write_config(&mut self, offset: u64, data: &[u8]) {
592         self.config.write(offset as usize, data);
593     }
594 
features(&self) -> u64595     fn features(&self) -> u64 {
596         self.virtio_features
597     }
598 
activate( &mut self, _mem: GuestMemory, interrupt: Interrupt, mut queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>599     fn activate(
600         &mut self,
601         _mem: GuestMemory,
602         interrupt: Interrupt,
603         mut queues: BTreeMap<usize, Queue>,
604     ) -> anyhow::Result<()> {
605         if queues.len() != 2 {
606             return Err(anyhow!("expected 2 queues, got {}", queues.len()));
607         }
608         let event_queue = queues.remove(&0).unwrap();
609         let status_queue = queues.remove(&1).unwrap();
610 
611         let name = self.config.name.clone();
612         let source = self
613             .source
614             .take()
615             .context("tried to activate device without a source for events")?;
616         self.worker_thread = Some(WorkerThread::start("v_input", move |kill_evt| {
617             let mut worker = Worker {
618                 interrupt,
619                 event_source: source,
620                 event_queue,
621                 status_queue,
622                 name,
623             };
624             worker.run(kill_evt);
625             worker
626         }));
627 
628         Ok(())
629     }
630 
reset(&mut self) -> anyhow::Result<()>631     fn reset(&mut self) -> anyhow::Result<()> {
632         if let Some(worker_thread) = self.worker_thread.take() {
633             let worker = worker_thread.stop();
634             self.source = Some(worker.event_source);
635         }
636         Ok(())
637     }
638 
virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>>639     fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> {
640         if let Some(worker_thread) = self.worker_thread.take() {
641             let worker = worker_thread.stop();
642             self.source = Some(worker.event_source);
643             let queues = BTreeMap::from([(0, worker.event_queue), (1, worker.status_queue)]);
644             Ok(Some(queues))
645         } else {
646             Ok(None)
647         }
648     }
649 
virtio_wake( &mut self, queues_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>, ) -> anyhow::Result<()>650     fn virtio_wake(
651         &mut self,
652         queues_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>,
653     ) -> anyhow::Result<()> {
654         if let Some((mem, interrupt, queues)) = queues_state {
655             self.activate(mem, interrupt, queues)?;
656         }
657         Ok(())
658     }
659 
virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value>660     fn virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
661         serde_json::to_value(InputSnapshot {
662             virtio_features: self.virtio_features,
663             config: self.config.clone(),
664         })
665         .context("failed to serialize InputSnapshot")
666     }
667 
virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>668     fn virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
669         let snap: InputSnapshot = serde_json::from_value(data).context("error deserializing")?;
670         if snap.virtio_features != self.virtio_features {
671             bail!(
672                 "expected virtio_features to match, but they did not. Live: {:?}, snapshot {:?}",
673                 self.virtio_features,
674                 snap.virtio_features,
675             );
676         }
677         self.config = snap.config;
678         Ok(())
679     }
680 }
681 
682 /// Creates a new virtio input device from an event device node
new_evdev<T>(source: T, virtio_features: u64) -> Result<Input<EvdevEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,683 pub fn new_evdev<T>(source: T, virtio_features: u64) -> Result<Input<EvdevEventSource<T>>>
684 where
685     T: Read + Write + AsRawDescriptor + Send + 'static,
686 {
687     Ok(Input {
688         worker_thread: None,
689         config: VirtioInputConfig::from_evdev(&source)?,
690         source: Some(EvdevEventSource::new(source)),
691         virtio_features,
692     })
693 }
694 
695 /// Creates a new virtio touch device which supports single touch only.
new_single_touch<T>( idx: u32, source: T, width: u32, height: u32, name: Option<&str>, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,696 pub fn new_single_touch<T>(
697     idx: u32,
698     source: T,
699     width: u32,
700     height: u32,
701     name: Option<&str>,
702     virtio_features: u64,
703 ) -> Result<Input<SocketEventSource<T>>>
704 where
705     T: Read + Write + AsRawDescriptor + Send + 'static,
706 {
707     Ok(Input {
708         worker_thread: None,
709         config: defaults::new_single_touch_config(idx, width, height, name),
710         source: Some(SocketEventSource::new(source)),
711         virtio_features,
712     })
713 }
714 
715 /// Creates a new virtio touch device which supports multi touch.
new_multi_touch<T>( idx: u32, source: T, width: u32, height: u32, name: Option<&str>, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,716 pub fn new_multi_touch<T>(
717     idx: u32,
718     source: T,
719     width: u32,
720     height: u32,
721     name: Option<&str>,
722     virtio_features: u64,
723 ) -> Result<Input<SocketEventSource<T>>>
724 where
725     T: Read + Write + AsRawDescriptor + Send + 'static,
726 {
727     Ok(Input {
728         worker_thread: None,
729         config: defaults::new_multi_touch_config(idx, width, height, name),
730         source: Some(SocketEventSource::new(source)),
731         virtio_features,
732     })
733 }
734 
735 /// Creates a new virtio trackpad device which supports (single) touch, primary and secondary
736 /// buttons as well as X and Y axis.
new_trackpad<T>( idx: u32, source: T, width: u32, height: u32, name: Option<&str>, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,737 pub fn new_trackpad<T>(
738     idx: u32,
739     source: T,
740     width: u32,
741     height: u32,
742     name: Option<&str>,
743     virtio_features: u64,
744 ) -> Result<Input<SocketEventSource<T>>>
745 where
746     T: Read + Write + AsRawDescriptor + Send + 'static,
747 {
748     Ok(Input {
749         worker_thread: None,
750         config: defaults::new_trackpad_config(idx, width, height, name),
751         source: Some(SocketEventSource::new(source)),
752         virtio_features,
753     })
754 }
755 
756 /// Creates a new virtio trackpad device which supports multi touch, primary and secondary
757 /// buttons as well as X and Y axis.
new_multitouch_trackpad<T>( idx: u32, source: T, width: u32, height: u32, name: Option<&str>, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,758 pub fn new_multitouch_trackpad<T>(
759     idx: u32,
760     source: T,
761     width: u32,
762     height: u32,
763     name: Option<&str>,
764     virtio_features: u64,
765 ) -> Result<Input<SocketEventSource<T>>>
766 where
767     T: Read + Write + AsRawDescriptor + Send + 'static,
768 {
769     Ok(Input {
770         worker_thread: None,
771         config: defaults::new_multitouch_trackpad_config(idx, width, height, name),
772         source: Some(SocketEventSource::new(source)),
773         virtio_features,
774     })
775 }
776 
777 /// Creates a new virtio mouse which supports primary, secondary, wheel and REL events.
new_mouse<T>( idx: u32, source: T, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,778 pub fn new_mouse<T>(
779     idx: u32,
780     source: T,
781     virtio_features: u64,
782 ) -> Result<Input<SocketEventSource<T>>>
783 where
784     T: Read + Write + AsRawDescriptor + Send + 'static,
785 {
786     Ok(Input {
787         worker_thread: None,
788         config: defaults::new_mouse_config(idx),
789         source: Some(SocketEventSource::new(source)),
790         virtio_features,
791     })
792 }
793 
794 /// Creates a new virtio keyboard, which supports the same events as an en-us physical keyboard.
new_keyboard<T>( idx: u32, source: T, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,795 pub fn new_keyboard<T>(
796     idx: u32,
797     source: T,
798     virtio_features: u64,
799 ) -> Result<Input<SocketEventSource<T>>>
800 where
801     T: Read + Write + AsRawDescriptor + Send + 'static,
802 {
803     Ok(Input {
804         worker_thread: None,
805         config: defaults::new_keyboard_config(idx),
806         source: Some(SocketEventSource::new(source)),
807         virtio_features,
808     })
809 }
810 
811 /// Creates a new virtio device for switches.
new_switches<T>( idx: u32, source: T, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,812 pub fn new_switches<T>(
813     idx: u32,
814     source: T,
815     virtio_features: u64,
816 ) -> Result<Input<SocketEventSource<T>>>
817 where
818     T: Read + Write + AsRawDescriptor + Send + 'static,
819 {
820     Ok(Input {
821         worker_thread: None,
822         config: defaults::new_switches_config(idx),
823         source: Some(SocketEventSource::new(source)),
824         virtio_features,
825     })
826 }
827 
828 /// Creates a new virtio device for rotary.
new_rotary<T>( idx: u32, source: T, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,829 pub fn new_rotary<T>(
830     idx: u32,
831     source: T,
832     virtio_features: u64,
833 ) -> Result<Input<SocketEventSource<T>>>
834 where
835     T: Read + Write + AsRawDescriptor + Send + 'static,
836 {
837     Ok(Input {
838         worker_thread: None,
839         config: defaults::new_rotary_config(idx),
840         source: Some(SocketEventSource::new(source)),
841         virtio_features,
842     })
843 }
844 
845 /// Creates a new custom virtio input device
new_custom<T>( idx: u32, source: T, input_config_path: PathBuf, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor + Send + 'static,846 pub fn new_custom<T>(
847     idx: u32,
848     source: T,
849     input_config_path: PathBuf,
850     virtio_features: u64,
851 ) -> Result<Input<SocketEventSource<T>>>
852 where
853     T: Read + Write + AsRawDescriptor + Send + 'static,
854 {
855     let config = parse_input_config_file(&input_config_path, idx)?;
856 
857     Ok(Input {
858         worker_thread: None,
859         config: defaults::new_custom_config(
860             idx,
861             &config.name,
862             &config.serial_name,
863             config.supported_events,
864         ),
865         source: Some(SocketEventSource::new(source)),
866         virtio_features,
867     })
868 }
869 
870 #[derive(Debug, Deserialize)]
871 struct InputConfigFile {
872     name: Option<String>,
873     serial_name: Option<String>,
874     events: Vec<InputConfigFileEvent>,
875 }
876 
877 #[derive(Debug, Deserialize)]
878 struct InputConfigFileEvent {
879     event_type: String,
880     event_type_code: u16,
881     supported_events: BTreeMap<String, u16>,
882 }
883 
884 struct CustomInputConfig {
885     name: String,
886     serial_name: String,
887     supported_events: BTreeMap<u16, virtio_input_bitmap>,
888 }
889 
890 // Read and parse input event config file to input device bitmaps. If parsing is successful, this
891 // function returns a CustomInputConfig. The field in CustomInputConfig are corresponding to the
892 // same field in struct VirtioInputConfig.
parse_input_config_file(config_path: &PathBuf, device_idx: u32) -> Result<CustomInputConfig>893 fn parse_input_config_file(config_path: &PathBuf, device_idx: u32) -> Result<CustomInputConfig> {
894     let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
895 
896     // Read the json file to String
897     let contents = fs::read_to_string(config_path).map_err(|e| {
898         InputError::ParseEventConfigError(format!(
899             "Failed to read input event config from {}: {}",
900             config_path.display(),
901             e
902         ))
903     })?;
904 
905     // Parse the string into a JSON object
906     let config_file: InputConfigFile = serde_json::from_str(contents.as_str()).map_err(|e| {
907         InputError::ParseEventConfigError(format!("Failed to parse json string: {}", e))
908     })?;
909     // Parse the supported events
910     for event in config_file.events {
911         let mut bit_map_idx: Vec<u16> = Vec::new();
912         for (event_name, event_code) in event.supported_events {
913             if event_code >= 1024 {
914                 return Err(InputError::ParseEventConfigError(format!(
915                     "The {} config file's {} event has event_code exceeds bounds(>=1024)",
916                     config_path.display(),
917                     event_name
918                 )));
919             }
920             bit_map_idx.push(event_code);
921         }
922         let bitmap = virtio_input_bitmap::from_bits(&bit_map_idx);
923         if supported_events
924             .insert(event.event_type_code, bitmap)
925             .is_some()
926         {
927             return Err(InputError::ParseEventConfigError(format!(
928                 "The {} event has been repeatedly defined by {}",
929                 event.event_type,
930                 config_path.display()
931             )));
932         }
933         info!(
934             "{} event is defined by {} for input device id {}",
935             event.event_type,
936             config_path.display(),
937             device_idx
938         );
939     }
940 
941     let name = config_file
942         .name
943         .unwrap_or_else(|| "Crosvm Virtio Custom".to_string());
944     let serial_name = config_file
945         .serial_name
946         .unwrap_or_else(|| "virtio-custom".to_string());
947 
948     Ok(CustomInputConfig {
949         name,
950         serial_name,
951         supported_events,
952     })
953 }
954 
955 #[cfg(test)]
956 mod tests {
957     use tempfile::TempDir;
958 
959     use super::*;
960     #[test]
parse_keyboard_like_input_config_file_success()961     fn parse_keyboard_like_input_config_file_success() {
962         pub const EV_KEY: u16 = 0x01;
963         pub const EV_LED: u16 = 0x11;
964         pub const EV_REP: u16 = 0x14;
965         // Create a sample JSON file for testing
966         let temp_file = TempDir::new().unwrap();
967         let path = temp_file.path().join("test.json");
968         let test_json = r#"
969         {
970           "name": "Virtio Custom Test",
971           "serial_name": "virtio-custom-test",
972           "events": [
973             {
974               "event_type": "EV_KEY",
975               "event_type_code": 1,
976               "supported_events": {
977                 "KEY_ESC": 1,
978                 "KEY_1": 2,
979                 "KEY_2": 3,
980                 "KEY_A": 30,
981                 "KEY_B": 48,
982                 "KEY_SPACE": 57
983               }
984             },
985             {
986               "event_type": "EV_REP",
987               "event_type_code": 20,
988               "supported_events": {
989                 "REP_DELAY": 0,
990                 "REP_PERIOD": 1
991             }
992             },
993             {
994               "event_type": "EV_LED",
995               "event_type_code": 17,
996               "supported_events": {
997                 "LED_NUML": 0,
998                 "LED_CAPSL": 1,
999                 "LED_SCROLLL": 2
1000               }
1001             }
1002           ]
1003         }"#;
1004         fs::write(&path, test_json).expect("Unable to write test file");
1005 
1006         // Call the function and assert the result
1007         let result = parse_input_config_file(&path, 0);
1008         assert!(result.is_ok());
1009 
1010         let supported_event = result.unwrap().supported_events;
1011         // EV_KEY type
1012         let ev_key_events = supported_event.get(&EV_KEY);
1013         assert!(ev_key_events.is_some());
1014         let ev_key_bitmap = ev_key_events.unwrap();
1015         let expected_ev_key_bitmap = &virtio_input_bitmap::from_bits(&[1, 2, 3, 30, 48, 57]);
1016         assert_eq!(ev_key_bitmap, expected_ev_key_bitmap);
1017         // EV_REP type
1018         let ev_rep_events = supported_event.get(&EV_REP);
1019         assert!(ev_rep_events.is_some());
1020         let ev_rep_bitmap = ev_rep_events.unwrap();
1021         let expected_ev_rep_bitmap = &virtio_input_bitmap::from_bits(&[0, 1]);
1022         assert_eq!(ev_rep_bitmap, expected_ev_rep_bitmap);
1023         // EV_LED type
1024         let ev_led_events = supported_event.get(&EV_LED);
1025         assert!(ev_led_events.is_some());
1026         let ev_led_bitmap = ev_led_events.unwrap();
1027         let expected_ev_led_bitmap = &virtio_input_bitmap::from_bits(&[0, 1, 2]);
1028         assert_eq!(ev_led_bitmap, expected_ev_led_bitmap);
1029     }
1030 }
1031