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