1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
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 constants;
7 mod defaults;
8 mod evdev;
9 mod event_source;
10
11 use self::constants::*;
12
13 use base::{error, warn, AsRawDescriptor, Event, PollToken, RawDescriptor, WaitContext};
14 use data_model::{DataInit, Le16, Le32};
15 use vm_memory::GuestMemory;
16
17 use self::event_source::{EvdevEventSource, EventSource, SocketEventSource};
18 use super::{
19 copy_config, DescriptorChain, DescriptorError, Interrupt, Queue, Reader, SignalableInterrupt,
20 VirtioDevice, Writer, TYPE_INPUT,
21 };
22 use linux_input_sys::{virtio_input_event, InputEventDecoder};
23 use std::collections::BTreeMap;
24 use std::fmt::{self, Display};
25 use std::io::Read;
26 use std::io::Write;
27 use std::thread;
28
29 const EVENT_QUEUE_SIZE: u16 = 64;
30 const STATUS_QUEUE_SIZE: u16 = 64;
31 const QUEUE_SIZES: &[u16] = &[EVENT_QUEUE_SIZE, STATUS_QUEUE_SIZE];
32
33 #[derive(Debug)]
34 pub enum InputError {
35 /// Failed to write events to the source
36 EventsWriteError(std::io::Error),
37 /// Failed to read events from the source
38 EventsReadError(std::io::Error),
39 // Failed to get name of event device
40 EvdevIdError(base::Error),
41 // Failed to get name of event device
42 EvdevNameError(base::Error),
43 // Failed to get serial name of event device
44 EvdevSerialError(base::Error),
45 // Failed to get properties of event device
46 EvdevPropertiesError(base::Error),
47 // Failed to get event types supported by device
48 EvdevEventTypesError(base::Error),
49 // Failed to get axis information of event device
50 EvdevAbsInfoError(base::Error),
51 // Failed to grab event device
52 EvdevGrabError(base::Error),
53 // Detected error on guest side
54 GuestError(String),
55 // Virtio descriptor error
56 Descriptor(DescriptorError),
57 // Error while reading from virtqueue
58 ReadQueue(std::io::Error),
59 // Error while writing to virtqueue
60 WriteQueue(std::io::Error),
61 }
62
63 pub type Result<T> = std::result::Result<T, InputError>;
64
65 impl Display for InputError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 use self::InputError::*;
68
69 match self {
70 EventsWriteError(e) => write!(f, "failed to write events to the source: {}", e),
71 EventsReadError(e) => write!(f, "failed to read events from the source: {}", e),
72 EvdevIdError(e) => write!(f, "failed to get id of event device: {}", e),
73 EvdevNameError(e) => write!(f, "failed to get name of event device: {}", e),
74 EvdevSerialError(e) => write!(f, "failed to get serial name of event device: {}", e),
75 EvdevPropertiesError(e) => write!(f, "failed to get properties of event device: {}", e),
76 EvdevEventTypesError(e) => {
77 write!(f, "failed to get event types supported by device: {}", e)
78 }
79 EvdevAbsInfoError(e) => {
80 write!(f, "failed to get axis information of event device: {}", e)
81 }
82 EvdevGrabError(e) => write!(f, "failed to grab event device: {}", e),
83 GuestError(s) => write!(f, "detected error on guest side: {}", s),
84 Descriptor(e) => write!(f, "virtio descriptor error: {}", e),
85 ReadQueue(e) => write!(f, "failed to read from virtqueue: {}", e),
86 WriteQueue(e) => write!(f, "failed to write to virtqueue: {}", e),
87 }
88 }
89 }
90
91 #[derive(Copy, Clone, Default, Debug)]
92 #[repr(C)]
93 pub struct virtio_input_device_ids {
94 bustype: Le16,
95 vendor: Le16,
96 product: Le16,
97 version: Le16,
98 }
99
100 // Safe because it only has data and has no implicit padding.
101 unsafe impl DataInit for virtio_input_device_ids {}
102
103 impl virtio_input_device_ids {
new(bustype: u16, product: u16, vendor: u16, version: u16) -> virtio_input_device_ids104 fn new(bustype: u16, product: u16, vendor: u16, version: u16) -> virtio_input_device_ids {
105 virtio_input_device_ids {
106 bustype: Le16::from(bustype),
107 vendor: Le16::from(vendor),
108 product: Le16::from(product),
109 version: Le16::from(version),
110 }
111 }
112 }
113
114 #[derive(Copy, Clone, Default, Debug)]
115 #[repr(C)]
116 pub struct virtio_input_absinfo {
117 min: Le32,
118 max: Le32,
119 fuzz: Le32,
120 flat: Le32,
121 }
122
123 // Safe because it only has data and has no implicit padding.
124 unsafe impl DataInit for virtio_input_absinfo {}
125
126 impl virtio_input_absinfo {
new(min: u32, max: u32, fuzz: u32, flat: u32) -> virtio_input_absinfo127 fn new(min: u32, max: u32, fuzz: u32, flat: u32) -> virtio_input_absinfo {
128 virtio_input_absinfo {
129 min: Le32::from(min),
130 max: Le32::from(max),
131 fuzz: Le32::from(fuzz),
132 flat: Le32::from(flat),
133 }
134 }
135 }
136
137 #[derive(Copy, Clone)]
138 #[repr(C)]
139 struct virtio_input_config {
140 select: u8,
141 subsel: u8,
142 size: u8,
143 reserved: [u8; 5],
144 payload: [u8; 128],
145 }
146
147 // Safe because it only has data and has no implicit padding.
148 unsafe impl DataInit for virtio_input_config {}
149
150 impl virtio_input_config {
new() -> virtio_input_config151 fn new() -> virtio_input_config {
152 virtio_input_config {
153 select: 0,
154 subsel: 0,
155 size: 0,
156 reserved: [0u8; 5],
157 payload: [0u8; 128],
158 }
159 }
160
set_payload_slice(&mut self, slice: &[u8])161 fn set_payload_slice(&mut self, slice: &[u8]) {
162 let bytes_written = match (&mut self.payload[..]).write(slice) {
163 Ok(x) => x,
164 Err(_) => {
165 // This won't happen because write is guaranteed to succeed with slices
166 unreachable!();
167 }
168 };
169 self.size = bytes_written as u8;
170 if bytes_written < slice.len() {
171 // This shouldn't happen since everywhere this function is called the size is guaranteed
172 // to be at most 128 bytes (the size of the payload)
173 warn!("Slice is too long to fit in payload");
174 }
175 }
176
set_payload_bitmap(&mut self, bitmap: &virtio_input_bitmap)177 fn set_payload_bitmap(&mut self, bitmap: &virtio_input_bitmap) {
178 self.size = bitmap.min_size();
179 self.payload.copy_from_slice(&bitmap.bitmap);
180 }
181
set_absinfo(&mut self, absinfo: &virtio_input_absinfo)182 fn set_absinfo(&mut self, absinfo: &virtio_input_absinfo) {
183 self.set_payload_slice(absinfo.as_slice());
184 }
185
set_device_ids(&mut self, device_ids: &virtio_input_device_ids)186 fn set_device_ids(&mut self, device_ids: &virtio_input_device_ids) {
187 self.set_payload_slice(device_ids.as_slice());
188 }
189 }
190
191 #[derive(Copy, Clone)]
192 #[repr(C)]
193 pub struct virtio_input_bitmap {
194 bitmap: [u8; 128],
195 }
196
197 impl virtio_input_bitmap {
new(bitmap: [u8; 128]) -> virtio_input_bitmap198 fn new(bitmap: [u8; 128]) -> virtio_input_bitmap {
199 virtio_input_bitmap { bitmap }
200 }
201
len(&self) -> usize202 fn len(&self) -> usize {
203 self.bitmap.len()
204 }
205
206 // Creates a bitmap from an array of bit indices
from_bits(set_indices: &[u16]) -> virtio_input_bitmap207 fn from_bits(set_indices: &[u16]) -> virtio_input_bitmap {
208 let mut ret = virtio_input_bitmap { bitmap: [0u8; 128] };
209 for idx in set_indices {
210 let byte_pos = (idx / 8) as usize;
211 let bit_byte = 1u8 << (idx % 8);
212 if byte_pos < ret.len() {
213 ret.bitmap[byte_pos] |= bit_byte;
214 } else {
215 // This would only happen if new event codes (or types, or ABS_*, etc) are defined to be
216 // larger than or equal to 1024, in which case a new version of the virtio input
217 // protocol needs to be defined.
218 // There is nothing we can do about this error except log it.
219 error!("Attempted to set an out of bounds bit: {}", idx);
220 }
221 }
222 ret
223 }
224
225 // Returns the length of the minimum array that can hold all set bits in the map
min_size(&self) -> u8226 fn min_size(&self) -> u8 {
227 self.bitmap
228 .iter()
229 .rposition(|v| *v != 0)
230 .map_or(0, |i| i + 1) as u8
231 }
232 }
233
234 pub struct VirtioInputConfig {
235 select: u8,
236 subsel: u8,
237 device_ids: virtio_input_device_ids,
238 name: Vec<u8>,
239 serial_name: Vec<u8>,
240 properties: virtio_input_bitmap,
241 supported_events: BTreeMap<u16, virtio_input_bitmap>,
242 axis_info: BTreeMap<u16, virtio_input_absinfo>,
243 }
244
245 impl VirtioInputConfig {
new( device_ids: virtio_input_device_ids, name: Vec<u8>, serial_name: Vec<u8>, properties: virtio_input_bitmap, supported_events: BTreeMap<u16, virtio_input_bitmap>, axis_info: BTreeMap<u16, virtio_input_absinfo>, ) -> VirtioInputConfig246 fn new(
247 device_ids: virtio_input_device_ids,
248 name: Vec<u8>,
249 serial_name: Vec<u8>,
250 properties: virtio_input_bitmap,
251 supported_events: BTreeMap<u16, virtio_input_bitmap>,
252 axis_info: BTreeMap<u16, virtio_input_absinfo>,
253 ) -> VirtioInputConfig {
254 VirtioInputConfig {
255 select: 0,
256 subsel: 0,
257 device_ids,
258 name,
259 serial_name,
260 properties,
261 supported_events,
262 axis_info,
263 }
264 }
265
from_evdev<T: AsRawDescriptor>(source: &T) -> Result<VirtioInputConfig>266 fn from_evdev<T: AsRawDescriptor>(source: &T) -> Result<VirtioInputConfig> {
267 Ok(VirtioInputConfig::new(
268 evdev::device_ids(source)?,
269 evdev::name(source)?,
270 evdev::serial_name(source)?,
271 evdev::properties(source)?,
272 evdev::supported_events(source)?,
273 evdev::abs_info(source),
274 ))
275 }
276
build_config_memory(&self) -> virtio_input_config277 fn build_config_memory(&self) -> virtio_input_config {
278 let mut cfg = virtio_input_config::new();
279 cfg.select = self.select;
280 cfg.subsel = self.subsel;
281 match self.select {
282 VIRTIO_INPUT_CFG_ID_NAME => {
283 cfg.set_payload_slice(&self.name);
284 }
285 VIRTIO_INPUT_CFG_ID_SERIAL => {
286 cfg.set_payload_slice(&self.serial_name);
287 }
288 VIRTIO_INPUT_CFG_PROP_BITS => {
289 cfg.set_payload_bitmap(&self.properties);
290 }
291 VIRTIO_INPUT_CFG_EV_BITS => {
292 let ev_type = self.subsel as u16;
293 // zero is a special case: return all supported event types (just like EVIOCGBIT)
294 if ev_type == 0 {
295 let events_bm = virtio_input_bitmap::from_bits(
296 &self.supported_events.keys().cloned().collect::<Vec<u16>>(),
297 );
298 cfg.set_payload_bitmap(&events_bm);
299 } else if let Some(supported_codes) = self.supported_events.get(&ev_type) {
300 cfg.set_payload_bitmap(&supported_codes);
301 }
302 }
303 VIRTIO_INPUT_CFG_ABS_INFO => {
304 let abs_axis = self.subsel as u16;
305 if let Some(absinfo) = self.axis_info.get(&abs_axis) {
306 cfg.set_absinfo(absinfo);
307 } // else all zeroes in the payload
308 }
309 VIRTIO_INPUT_CFG_ID_DEVIDS => {
310 cfg.set_device_ids(&self.device_ids);
311 }
312 VIRTIO_INPUT_CFG_UNSET => {
313 // Per the virtio spec at https://docs.oasis-open.org/virtio/virtio/v1.1/cs01/virtio-v1.1-cs01.html#x1-3390008,
314 // there is no action required of us when this is set. It's unclear whether we
315 // should be zeroing the virtio_input_config, but empirically we know that the
316 // existing behavior of doing nothing works with the Linux virtio-input frontend.
317 }
318 _ => {
319 warn!("Unsuported virtio input config selection: {}", self.select);
320 }
321 }
322 cfg
323 }
324
read(&self, offset: usize, data: &mut [u8])325 fn read(&self, offset: usize, data: &mut [u8]) {
326 copy_config(
327 data,
328 0,
329 self.build_config_memory().as_slice(),
330 offset as u64,
331 );
332 }
333
write(&mut self, offset: usize, data: &[u8])334 fn write(&mut self, offset: usize, data: &[u8]) {
335 let mut config = self.build_config_memory();
336 copy_config(config.as_mut_slice(), offset as u64, data, 0);
337 self.select = config.select;
338 self.subsel = config.subsel;
339 }
340 }
341
342 struct Worker<T: EventSource> {
343 interrupt: Interrupt,
344 event_source: T,
345 event_queue: Queue,
346 status_queue: Queue,
347 guest_memory: GuestMemory,
348 }
349
350 impl<T: EventSource> Worker<T> {
351 // Fills a virtqueue with events from the source. Returns the number of bytes written.
fill_event_virtqueue( event_source: &mut T, avail_desc: DescriptorChain, mem: &GuestMemory, ) -> Result<usize>352 fn fill_event_virtqueue(
353 event_source: &mut T,
354 avail_desc: DescriptorChain,
355 mem: &GuestMemory,
356 ) -> Result<usize> {
357 let mut writer = Writer::new(mem.clone(), avail_desc).map_err(InputError::Descriptor)?;
358
359 while writer.available_bytes() >= virtio_input_event::SIZE {
360 if let Some(evt) = event_source.pop_available_event() {
361 writer.write_obj(evt).map_err(InputError::WriteQueue)?;
362 } else {
363 break;
364 }
365 }
366
367 Ok(writer.bytes_written())
368 }
369
370 // Send events from the source to the guest
send_events(&mut self) -> bool371 fn send_events(&mut self) -> bool {
372 let mut needs_interrupt = false;
373
374 // Only consume from the queue iterator if we know we have events to send
375 while self.event_source.available_events_count() > 0 {
376 match self.event_queue.pop(&self.guest_memory) {
377 None => {
378 break;
379 }
380 Some(avail_desc) => {
381 let avail_desc_index = avail_desc.index;
382
383 let bytes_written = match Worker::fill_event_virtqueue(
384 &mut self.event_source,
385 avail_desc,
386 &self.guest_memory,
387 ) {
388 Ok(count) => count,
389 Err(e) => {
390 error!("Input: failed to send events to guest: {}", e);
391 break;
392 }
393 };
394
395 self.event_queue.add_used(
396 &self.guest_memory,
397 avail_desc_index,
398 bytes_written as u32,
399 );
400 needs_interrupt = true;
401 }
402 }
403 }
404
405 needs_interrupt
406 }
407
408 // Sends events from the guest to the source. Returns the number of bytes read.
read_event_virtqueue( avail_desc: DescriptorChain, event_source: &mut T, mem: &GuestMemory, ) -> Result<usize>409 fn read_event_virtqueue(
410 avail_desc: DescriptorChain,
411 event_source: &mut T,
412 mem: &GuestMemory,
413 ) -> Result<usize> {
414 let mut reader = Reader::new(mem.clone(), avail_desc).map_err(InputError::Descriptor)?;
415 while reader.available_bytes() >= virtio_input_event::SIZE {
416 let evt: virtio_input_event = reader.read_obj().map_err(InputError::ReadQueue)?;
417 event_source.send_event(&evt)?;
418 }
419
420 Ok(reader.bytes_read())
421 }
422
process_status_queue(&mut self) -> Result<bool>423 fn process_status_queue(&mut self) -> Result<bool> {
424 let mut needs_interrupt = false;
425 while let Some(avail_desc) = self.status_queue.pop(&self.guest_memory) {
426 let avail_desc_index = avail_desc.index;
427
428 let bytes_read = match Worker::read_event_virtqueue(
429 avail_desc,
430 &mut self.event_source,
431 &self.guest_memory,
432 ) {
433 Ok(count) => count,
434 Err(e) => {
435 error!("Input: failed to read events from virtqueue: {}", e);
436 return Err(e);
437 }
438 };
439
440 self.status_queue
441 .add_used(&self.guest_memory, avail_desc_index, bytes_read as u32);
442 needs_interrupt = true;
443 }
444
445 Ok(needs_interrupt)
446 }
447
run(&mut self, event_queue_evt: Event, status_queue_evt: Event, kill_evt: Event)448 fn run(&mut self, event_queue_evt: Event, status_queue_evt: Event, kill_evt: Event) {
449 if let Err(e) = self.event_source.init() {
450 error!("failed initializing event source: {}", e);
451 return;
452 }
453
454 #[derive(PollToken)]
455 enum Token {
456 EventQAvailable,
457 StatusQAvailable,
458 InputEventsAvailable,
459 InterruptResample,
460 Kill,
461 }
462 let wait_ctx: WaitContext<Token> = match WaitContext::build_with(&[
463 (&event_queue_evt, Token::EventQAvailable),
464 (&status_queue_evt, Token::StatusQAvailable),
465 (&self.event_source, Token::InputEventsAvailable),
466 (&kill_evt, Token::Kill),
467 ]) {
468 Ok(wait_ctx) => wait_ctx,
469 Err(e) => {
470 error!("failed creating WaitContext: {}", e);
471 return;
472 }
473 };
474 if let Some(resample_evt) = self.interrupt.get_resample_evt() {
475 if wait_ctx
476 .add(resample_evt, Token::InterruptResample)
477 .is_err()
478 {
479 error!("failed adding resample event to WaitContext.");
480 return;
481 }
482 }
483
484 'wait: loop {
485 let wait_events = match wait_ctx.wait() {
486 Ok(wait_events) => wait_events,
487 Err(e) => {
488 error!("failed polling for events: {}", e);
489 break;
490 }
491 };
492
493 let mut needs_interrupt = false;
494 for wait_event in wait_events.iter().filter(|e| e.is_readable) {
495 match wait_event.token {
496 Token::EventQAvailable => {
497 if let Err(e) = event_queue_evt.read() {
498 error!("failed reading event queue Event: {}", e);
499 break 'wait;
500 }
501 needs_interrupt |= self.send_events();
502 }
503 Token::StatusQAvailable => {
504 if let Err(e) = status_queue_evt.read() {
505 error!("failed reading status queue Event: {}", e);
506 break 'wait;
507 }
508 match self.process_status_queue() {
509 Ok(b) => needs_interrupt |= b,
510 Err(e) => error!("failed processing status events: {}", e),
511 }
512 }
513 Token::InputEventsAvailable => match self.event_source.receive_events() {
514 Err(e) => error!("error receiving events: {}", e),
515 Ok(_cnt) => needs_interrupt |= self.send_events(),
516 },
517 Token::InterruptResample => {
518 self.interrupt.interrupt_resample();
519 }
520 Token::Kill => {
521 let _ = kill_evt.read();
522 break 'wait;
523 }
524 }
525 }
526 if needs_interrupt {
527 self.interrupt.signal_used_queue(self.event_queue.vector);
528 }
529 }
530
531 if let Err(e) = self.event_source.finalize() {
532 error!("failed finalizing event source: {}", e);
533 return;
534 }
535 }
536 }
537
538 /// Virtio input device
539
540 pub struct Input<T: EventSource> {
541 kill_evt: Option<Event>,
542 worker_thread: Option<thread::JoinHandle<Worker<T>>>,
543 config: VirtioInputConfig,
544 source: Option<T>,
545 virtio_features: u64,
546 }
547
548 impl<T: EventSource> Drop for Input<T> {
drop(&mut self)549 fn drop(&mut self) {
550 if let Some(kill_evt) = self.kill_evt.take() {
551 // Ignore the result because there is nothing we can do about it.
552 let _ = kill_evt.write(1);
553 }
554
555 if let Some(worker_thread) = self.worker_thread.take() {
556 let _ = worker_thread.join();
557 }
558 }
559 }
560
561 impl<T> VirtioDevice for Input<T>
562 where
563 T: 'static + EventSource + Send,
564 {
keep_rds(&self) -> Vec<RawDescriptor>565 fn keep_rds(&self) -> Vec<RawDescriptor> {
566 if let Some(source) = &self.source {
567 return vec![source.as_raw_descriptor()];
568 }
569 Vec::new()
570 }
571
device_type(&self) -> u32572 fn device_type(&self) -> u32 {
573 TYPE_INPUT
574 }
575
queue_max_sizes(&self) -> &[u16]576 fn queue_max_sizes(&self) -> &[u16] {
577 QUEUE_SIZES
578 }
579
read_config(&self, offset: u64, data: &mut [u8])580 fn read_config(&self, offset: u64, data: &mut [u8]) {
581 self.config.read(offset as usize, data);
582 }
583
write_config(&mut self, offset: u64, data: &[u8])584 fn write_config(&mut self, offset: u64, data: &[u8]) {
585 self.config.write(offset as usize, data);
586 }
587
features(&self) -> u64588 fn features(&self) -> u64 {
589 self.virtio_features
590 }
591
activate( &mut self, mem: GuestMemory, interrupt: Interrupt, mut queues: Vec<Queue>, mut queue_evts: Vec<Event>, )592 fn activate(
593 &mut self,
594 mem: GuestMemory,
595 interrupt: Interrupt,
596 mut queues: Vec<Queue>,
597 mut queue_evts: Vec<Event>,
598 ) {
599 if queues.len() != 2 || queue_evts.len() != 2 {
600 return;
601 }
602
603 let (self_kill_evt, kill_evt) = match Event::new().and_then(|e| Ok((e.try_clone()?, e))) {
604 Ok(v) => v,
605 Err(e) => {
606 error!("failed to create kill Event pair: {}", e);
607 return;
608 }
609 };
610 self.kill_evt = Some(self_kill_evt);
611
612 // Status is queue 1, event is queue 0
613 let status_queue = queues.remove(1);
614 let status_queue_evt = queue_evts.remove(1);
615
616 let event_queue = queues.remove(0);
617 let event_queue_evt = queue_evts.remove(0);
618
619 if let Some(source) = self.source.take() {
620 let worker_result = thread::Builder::new()
621 .name(String::from("virtio_input"))
622 .spawn(move || {
623 let mut worker = Worker {
624 interrupt,
625 event_source: source,
626 event_queue,
627 status_queue,
628 guest_memory: mem,
629 };
630 worker.run(event_queue_evt, status_queue_evt, kill_evt);
631 worker
632 });
633
634 match worker_result {
635 Err(e) => {
636 error!("failed to spawn virtio_input worker: {}", e);
637 }
638 Ok(join_handle) => {
639 self.worker_thread = Some(join_handle);
640 }
641 }
642 } else {
643 error!("tried to activate device without a source for events");
644 }
645 }
646
reset(&mut self) -> bool647 fn reset(&mut self) -> bool {
648 if let Some(kill_evt) = self.kill_evt.take() {
649 if kill_evt.write(1).is_err() {
650 error!("{}: failed to notify the kill event", self.debug_label());
651 return false;
652 }
653 }
654
655 if let Some(worker_thread) = self.worker_thread.take() {
656 match worker_thread.join() {
657 Err(_) => {
658 error!("{}: failed to get back resources", self.debug_label());
659 return false;
660 }
661 Ok(worker) => {
662 self.source = Some(worker.event_source);
663 return true;
664 }
665 }
666 }
667 false
668 }
669 }
670
671 /// 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,672 pub fn new_evdev<T>(source: T, virtio_features: u64) -> Result<Input<EvdevEventSource<T>>>
673 where
674 T: Read + Write + AsRawDescriptor,
675 {
676 Ok(Input {
677 kill_evt: None,
678 worker_thread: None,
679 config: VirtioInputConfig::from_evdev(&source)?,
680 source: Some(EvdevEventSource::new(source)),
681 virtio_features,
682 })
683 }
684
685 /// Creates a new virtio touch device which supports single touch only.
new_single_touch<T>( source: T, width: u32, height: u32, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor,686 pub fn new_single_touch<T>(
687 source: T,
688 width: u32,
689 height: u32,
690 virtio_features: u64,
691 ) -> Result<Input<SocketEventSource<T>>>
692 where
693 T: Read + Write + AsRawDescriptor,
694 {
695 Ok(Input {
696 kill_evt: None,
697 worker_thread: None,
698 config: defaults::new_single_touch_config(width, height),
699 source: Some(SocketEventSource::new(source)),
700 virtio_features,
701 })
702 }
703
704 /// Creates a new virtio touch device which supports multi touch.
new_multi_touch<T>( source: T, width: u32, height: u32, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor,705 pub fn new_multi_touch<T>(
706 source: T,
707 width: u32,
708 height: u32,
709 virtio_features: u64,
710 ) -> Result<Input<SocketEventSource<T>>>
711 where
712 T: Read + Write + AsRawDescriptor,
713 {
714 Ok(Input {
715 kill_evt: None,
716 worker_thread: None,
717 config: defaults::new_multi_touch_config(width, height),
718 source: Some(SocketEventSource::new(source)),
719 virtio_features,
720 })
721 }
722
723 /// Creates a new virtio trackpad device which supports (single) touch, primary and secondary
724 /// buttons as well as X and Y axis.
new_trackpad<T>( source: T, width: u32, height: u32, virtio_features: u64, ) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor,725 pub fn new_trackpad<T>(
726 source: T,
727 width: u32,
728 height: u32,
729 virtio_features: u64,
730 ) -> Result<Input<SocketEventSource<T>>>
731 where
732 T: Read + Write + AsRawDescriptor,
733 {
734 Ok(Input {
735 kill_evt: None,
736 worker_thread: None,
737 config: defaults::new_trackpad_config(width, height),
738 source: Some(SocketEventSource::new(source)),
739 virtio_features,
740 })
741 }
742
743 /// Creates a new virtio mouse which supports primary, secondary, wheel and REL events.
new_mouse<T>(source: T, virtio_features: u64) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor,744 pub fn new_mouse<T>(source: T, virtio_features: u64) -> Result<Input<SocketEventSource<T>>>
745 where
746 T: Read + Write + AsRawDescriptor,
747 {
748 Ok(Input {
749 kill_evt: None,
750 worker_thread: None,
751 config: defaults::new_mouse_config(),
752 source: Some(SocketEventSource::new(source)),
753 virtio_features,
754 })
755 }
756
757 /// Creates a new virtio keyboard, which supports the same events as an en-us physical keyboard.
new_keyboard<T>(source: T, virtio_features: u64) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor,758 pub fn new_keyboard<T>(source: T, virtio_features: u64) -> Result<Input<SocketEventSource<T>>>
759 where
760 T: Read + Write + AsRawDescriptor,
761 {
762 Ok(Input {
763 kill_evt: None,
764 worker_thread: None,
765 config: defaults::new_keyboard_config(),
766 source: Some(SocketEventSource::new(source)),
767 virtio_features,
768 })
769 }
770
771 /// Creates a new virtio device for switches.
new_switches<T>(source: T, virtio_features: u64) -> Result<Input<SocketEventSource<T>>> where T: Read + Write + AsRawDescriptor,772 pub fn new_switches<T>(source: T, virtio_features: u64) -> Result<Input<SocketEventSource<T>>>
773 where
774 T: Read + Write + AsRawDescriptor,
775 {
776 Ok(Input {
777 kill_evt: None,
778 worker_thread: None,
779 config: defaults::new_switches_config(),
780 source: Some(SocketEventSource::new(source)),
781 virtio_features,
782 })
783 }
784