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