summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--devices/src/virtio/input/defaults.rs27
-rw-r--r--devices/src/virtio/input/mod.rs16
-rw-r--r--src/linux.rs22
-rw-r--r--src/main.rs42
4 files changed, 95 insertions, 12 deletions
diff --git a/devices/src/virtio/input/defaults.rs b/devices/src/virtio/input/defaults.rs
index f5343f7..a7a01d9 100644
--- a/devices/src/virtio/input/defaults.rs
+++ b/devices/src/virtio/input/defaults.rs
@@ -48,6 +48,33 @@ pub fn new_keyboard_config() -> VirtioInputConfig {
     )
 }
 
+/// Instantiates a VirtioInputConfig object with the default configuration for a touchscreen (no
+/// multitouch support).
+pub fn new_single_touch_config(width: u32, height: u32) -> VirtioInputConfig {
+    VirtioInputConfig::new(
+        virtio_input_device_ids::new(0, 0, 0, 0),
+        "Crosvm Virtio Touchscreen".as_bytes().to_vec(),
+        "virtio-touchscreen".as_bytes().to_vec(),
+        virtio_input_bitmap::from_bits(&[INPUT_PROP_DIRECT]),
+        default_touchscreen_events(),
+        default_touchscreen_absinfo(width, height),
+    )
+}
+
+fn default_touchscreen_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo> {
+    let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
+    absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
+    absinfo.insert(ABS_Y, virtio_input_absinfo::new(0, height, 0, 0));
+    absinfo
+}
+
+fn default_touchscreen_events() -> BTreeMap<u16, virtio_input_bitmap> {
+    let mut supported_events: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();
+    supported_events.insert(EV_KEY, virtio_input_bitmap::from_bits(&[BTN_TOUCH]));
+    supported_events.insert(EV_ABS, virtio_input_bitmap::from_bits(&[ABS_X, ABS_Y]));
+    supported_events
+}
+
 fn default_trackpad_absinfo(width: u32, height: u32) -> BTreeMap<u16, virtio_input_absinfo> {
     let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
     absinfo.insert(ABS_X, virtio_input_absinfo::new(0, width, 0, 0));
diff --git a/devices/src/virtio/input/mod.rs b/devices/src/virtio/input/mod.rs
index 22ef168..98dac60 100644
--- a/devices/src/virtio/input/mod.rs
+++ b/devices/src/virtio/input/mod.rs
@@ -687,6 +687,22 @@ where
     })
 }
 
+/// Creates a new virtio touch device which supports single touch only.
+pub fn new_single_touch<T>(
+    source: T,
+    width: u32,
+    height: u32,
+) -> Result<Input<SocketEventSource<T>>>
+where
+    T: Read + Write + AsRawFd,
+{
+    Ok(Input {
+        kill_evt: None,
+        config: defaults::new_single_touch_config(width, height),
+        source: Some(SocketEventSource::new(source)),
+    })
+}
+
 /// Creates a new virtio trackpad device which supports (single) touch, primary and secondary
 /// buttons as well as X and Y axis.
 pub fn new_trackpad<T>(source: T, width: u32, height: u32) -> Result<Input<SocketEventSource<T>>>
diff --git a/src/linux.rs b/src/linux.rs
index 6398270..acea1de 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -44,7 +44,7 @@ use sys_util::{
 use vhost;
 use vm_control::{VmRequest, VmResponse, VmRunMode};
 
-use crate::{Config, DiskOption, TrackpadOption};
+use crate::{Config, DiskOption, TouchDeviceOption};
 
 use arch::{self, LinuxArch, RunnableLinuxVm, VirtioDeviceStub, VmComponents};
 
@@ -358,7 +358,21 @@ fn create_tpm_device(cfg: &Config) -> DeviceResult {
     })
 }
 
-fn create_trackpad_device(cfg: &Config, trackpad_spec: &TrackpadOption) -> DeviceResult {
+fn create_single_touch_device(cfg: &Config, single_touch_spec: &TouchDeviceOption) -> DeviceResult {
+    let socket = create_input_socket(&single_touch_spec.path).map_err(|e| {
+        error!("failed configuring virtio single touch: {:?}", e);
+        e
+    })?;
+
+    let dev = virtio::new_single_touch(socket, single_touch_spec.width, single_touch_spec.height)
+        .map_err(Error::InputDeviceNew)?;
+    Ok(VirtioDeviceStub {
+        dev: Box::new(dev),
+        jail: simple_jail(&cfg, "input_device.policy")?,
+    })
+}
+
+fn create_trackpad_device(cfg: &Config, trackpad_spec: &TouchDeviceOption) -> DeviceResult {
     let socket = create_input_socket(&trackpad_spec.path).map_err(|e| {
         error!("failed configuring virtio trackpad: {}", e);
         e
@@ -651,6 +665,10 @@ fn create_virtio_devices(
         }
     }
 
+    if let Some(single_touch_spec) = &cfg.virtio_single_touch {
+        devs.push(create_single_touch_device(cfg, single_touch_spec)?);
+    }
+
     if let Some(trackpad_spec) = &cfg.virtio_trackpad {
         devs.push(create_trackpad_device(cfg, trackpad_spec)?);
     }
diff --git a/src/main.rs b/src/main.rs
index c2e294f..c4228be 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -79,21 +79,21 @@ struct GidMap {
     count: u32,
 }
 
-const DEFAULT_TRACKPAD_WIDTH: u32 = 800;
-const DEFAULT_TRACKPAD_HEIGHT: u32 = 1280;
+const DEFAULT_TOUCH_DEVICE_WIDTH: u32 = 800;
+const DEFAULT_TOUCH_DEVICE_HEIGHT: u32 = 1280;
 
-struct TrackpadOption {
+struct TouchDeviceOption {
     path: PathBuf,
     width: u32,
     height: u32,
 }
 
-impl TrackpadOption {
-    fn new(path: PathBuf) -> TrackpadOption {
-        TrackpadOption {
+impl TouchDeviceOption {
+    fn new(path: PathBuf) -> TouchDeviceOption {
+        TouchDeviceOption {
             path,
-            width: DEFAULT_TRACKPAD_WIDTH,
-            height: DEFAULT_TRACKPAD_HEIGHT,
+            width: DEFAULT_TOUCH_DEVICE_WIDTH,
+            height: DEFAULT_TOUCH_DEVICE_HEIGHT,
         }
     }
 }
@@ -126,7 +126,8 @@ pub struct Config {
     software_tpm: bool,
     cras_audio: bool,
     null_audio: bool,
-    virtio_trackpad: Option<TrackpadOption>,
+    virtio_single_touch: Option<TouchDeviceOption>,
+    virtio_trackpad: Option<TouchDeviceOption>,
     virtio_mouse: Option<PathBuf>,
     virtio_keyboard: Option<PathBuf>,
     virtio_input_evdevs: Vec<PathBuf>,
@@ -163,6 +164,7 @@ impl Default for Config {
             seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR),
             cras_audio: false,
             null_audio: false,
+            virtio_single_touch: None,
             virtio_trackpad: None,
             virtio_mouse: None,
             virtio_keyboard: None,
@@ -570,6 +572,25 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
         "software-tpm" => {
             cfg.software_tpm = true;
         }
+        "single-touch" => {
+            if cfg.virtio_single_touch.is_some() {
+                return Err(argument::Error::TooManyArguments(
+                    "`single-touch` already given".to_owned(),
+                ));
+            }
+            let mut it = value.unwrap().split(":");
+
+            let mut single_touch_spec =
+                TouchDeviceOption::new(PathBuf::from(it.next().unwrap().to_owned()));
+            if let Some(width) = it.next() {
+                single_touch_spec.width = width.trim().parse().unwrap();
+            }
+            if let Some(height) = it.next() {
+                single_touch_spec.height = height.trim().parse().unwrap();
+            }
+
+            cfg.virtio_single_touch = Some(single_touch_spec);
+        }
         "trackpad" => {
             if cfg.virtio_trackpad.is_some() {
                 return Err(argument::Error::TooManyArguments(
@@ -579,7 +600,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
             let mut it = value.unwrap().split(":");
 
             let mut trackpad_spec =
-                TrackpadOption::new(PathBuf::from(it.next().unwrap().to_owned()));
+                TouchDeviceOption::new(PathBuf::from(it.next().unwrap().to_owned()));
             if let Some(width) = it.next() {
                 trackpad_spec.width = width.trim().parse().unwrap();
             }
@@ -686,6 +707,7 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> {
           #[cfg(feature = "tpm")]
           Argument::flag("software-tpm", "enable a software emulated trusted platform module device"),
           Argument::value("evdev", "PATH", "Path to an event device node. The device will be grabbed (unusable from the host) and made available to the guest with the same configuration it shows on the host"),
+          Argument::value("single-touch", "PATH:WIDTH:HEIGHT", "Path to a socket from where to read single touch input events (such as those from a touchscreen) and write status updates to, optionally followed by width and height (defaults to 800x1280)."),
           Argument::value("trackpad", "PATH:WIDTH:HEIGHT", "Path to a socket from where to read trackpad input events and write status updates to, optionally followed by screen width and height (defaults to 800x1280)."),
           Argument::value("mouse", "PATH", "Path to a socket from where to read mouse input events and write status updates to."),
           Argument::value("keyboard", "PATH", "Path to a socket from where to read keyboard input events and write status updates to."),