mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
Add and enable virtio multi-touch touchscreen device
BUG=b:124121375 TEST=compile and run Change-Id: I795ec238cb4ba7551a98fdfd4258fcae38e8a7a8 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2439297 Tested-by: Tristan Muntsinger <muntsinger@google.com> Commit-Queue: Tristan Muntsinger <muntsinger@google.com> Reviewed-by: Zach Reizner <zachr@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org> Auto-Submit: Tristan Muntsinger <muntsinger@google.com>
This commit is contained in:
parent
18d5733e15
commit
486cffc41d
6 changed files with 146 additions and 6 deletions
|
@ -62,6 +62,19 @@ pub fn new_single_touch_config(width: u32, height: u32) -> VirtioInputConfig {
|
|||
)
|
||||
}
|
||||
|
||||
/// Instantiates a VirtioInputConfig object with the default configuration for a multitouch
|
||||
/// touchscreen.
|
||||
pub fn new_multi_touch_config(width: u32, height: u32) -> VirtioInputConfig {
|
||||
VirtioInputConfig::new(
|
||||
virtio_input_device_ids::new(0, 0, 0, 0),
|
||||
b"Crosvm Virtio Multitouch Touchscreen".to_vec(),
|
||||
b"virtio-touchscreen".to_vec(),
|
||||
virtio_input_bitmap::from_bits(&[INPUT_PROP_DIRECT]),
|
||||
default_multitouchscreen_events(),
|
||||
default_multitouchscreen_absinfo(width, height, 0, 0),
|
||||
)
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -76,6 +89,38 @@ fn default_touchscreen_events() -> BTreeMap<u16, virtio_input_bitmap> {
|
|||
supported_events
|
||||
}
|
||||
|
||||
fn default_multitouchscreen_absinfo(
|
||||
width: u32,
|
||||
height: u32,
|
||||
slot: u32,
|
||||
id: u32,
|
||||
) -> BTreeMap<u16, virtio_input_absinfo> {
|
||||
let mut absinfo: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();
|
||||
absinfo.insert(ABS_MT_SLOT, virtio_input_absinfo::new(0, slot, 0, 0));
|
||||
absinfo.insert(ABS_MT_TRACKING_ID, virtio_input_absinfo::new(0, id, 0, 0));
|
||||
absinfo.insert(ABS_MT_POSITION_X, virtio_input_absinfo::new(0, width, 0, 0));
|
||||
absinfo.insert(
|
||||
ABS_MT_POSITION_Y,
|
||||
virtio_input_absinfo::new(0, height, 0, 0),
|
||||
);
|
||||
absinfo
|
||||
}
|
||||
|
||||
fn default_multitouchscreen_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_MT_SLOT,
|
||||
ABS_MT_TRACKING_ID,
|
||||
ABS_MT_POSITION_X,
|
||||
ABS_MT_POSITION_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));
|
||||
|
|
|
@ -693,6 +693,25 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates a new virtio touch device which supports multi touch.
|
||||
pub fn new_multi_touch<T>(
|
||||
source: T,
|
||||
width: u32,
|
||||
height: u32,
|
||||
virtio_features: u64,
|
||||
) -> Result<Input<SocketEventSource<T>>>
|
||||
where
|
||||
T: Read + Write + AsRawDescriptor,
|
||||
{
|
||||
Ok(Input {
|
||||
kill_evt: None,
|
||||
worker_thread: None,
|
||||
config: defaults::new_multi_touch_config(width, height),
|
||||
source: Some(SocketEventSource::new(source)),
|
||||
virtio_features,
|
||||
})
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
|
|
|
@ -15,6 +15,10 @@ const SYN_REPORT: u16 = 0;
|
|||
const REL_X: u16 = 0x00;
|
||||
#[allow(dead_code)]
|
||||
const REL_Y: u16 = 0x01;
|
||||
const ABS_MT_TRACKING_ID: u16 = 0x39;
|
||||
const ABS_MT_SLOT: u16 = 0x2f;
|
||||
const ABS_MT_POSITION_X: u16 = 0x35;
|
||||
const ABS_MT_POSITION_Y: u16 = 0x36;
|
||||
const ABS_X: u16 = 0x00;
|
||||
const ABS_Y: u16 = 0x01;
|
||||
const BTN_TOUCH: u16 = 0x14a;
|
||||
|
@ -106,6 +110,26 @@ impl virtio_input_event {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn multitouch_tracking_id(id: u32) -> virtio_input_event {
|
||||
Self::absolute(ABS_MT_TRACKING_ID, id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn multitouch_slot(slot: u32) -> virtio_input_event {
|
||||
Self::absolute(ABS_MT_SLOT, slot)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn multitouch_absolute_x(x: u32) -> virtio_input_event {
|
||||
Self::absolute(ABS_MT_POSITION_X, x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn multitouch_absolute_y(y: u32) -> virtio_input_event {
|
||||
Self::absolute(ABS_MT_POSITION_Y, y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn absolute_x(x: u32) -> virtio_input_event {
|
||||
Self::absolute(ABS_X, x)
|
||||
|
|
|
@ -213,6 +213,7 @@ pub struct Config {
|
|||
pub serial_parameters: BTreeMap<(SerialHardware, u8), SerialParameters>,
|
||||
pub syslog_tag: Option<String>,
|
||||
pub virtio_single_touch: Option<TouchDeviceOption>,
|
||||
pub virtio_multi_touch: Option<TouchDeviceOption>,
|
||||
pub virtio_trackpad: Option<TouchDeviceOption>,
|
||||
pub virtio_mouse: Option<PathBuf>,
|
||||
pub virtio_keyboard: Option<PathBuf>,
|
||||
|
@ -272,6 +273,7 @@ impl Default for Config {
|
|||
serial_parameters: BTreeMap::new(),
|
||||
syslog_tag: None,
|
||||
virtio_single_touch: None,
|
||||
virtio_multi_touch: None,
|
||||
virtio_trackpad: None,
|
||||
virtio_mouse: None,
|
||||
virtio_keyboard: None,
|
||||
|
|
40
src/linux.rs
40
src/linux.rs
|
@ -598,6 +598,30 @@ fn create_single_touch_device(cfg: &Config, single_touch_spec: &TouchDeviceOptio
|
|||
})
|
||||
}
|
||||
|
||||
fn create_multi_touch_device(cfg: &Config, multi_touch_spec: &TouchDeviceOption) -> DeviceResult {
|
||||
let socket = multi_touch_spec
|
||||
.get_path()
|
||||
.into_unix_stream()
|
||||
.map_err(|e| {
|
||||
error!("failed configuring virtio multi touch: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let (width, height) = multi_touch_spec.get_size();
|
||||
let dev = virtio::new_multi_touch(
|
||||
socket,
|
||||
width,
|
||||
height,
|
||||
virtio::base_features(cfg.protected_vm),
|
||||
)
|
||||
.map_err(Error::InputDeviceNew)?;
|
||||
|
||||
Ok(VirtioDeviceStub {
|
||||
dev: Box::new(dev),
|
||||
jail: simple_jail(&cfg, "input_device")?,
|
||||
})
|
||||
}
|
||||
|
||||
fn create_trackpad_device(cfg: &Config, trackpad_spec: &TouchDeviceOption) -> DeviceResult {
|
||||
let socket = trackpad_spec.get_path().into_unix_stream().map_err(|e| {
|
||||
error!("failed configuring virtio trackpad: {}", e);
|
||||
|
@ -1298,6 +1322,10 @@ fn create_virtio_devices(
|
|||
devs.push(create_single_touch_device(cfg, single_touch_spec)?);
|
||||
}
|
||||
|
||||
if let Some(multi_touch_spec) = &cfg.virtio_multi_touch {
|
||||
devs.push(create_multi_touch_device(cfg, multi_touch_spec)?);
|
||||
}
|
||||
|
||||
if let Some(trackpad_spec) = &cfg.virtio_trackpad {
|
||||
devs.push(create_trackpad_device(cfg, trackpad_spec)?);
|
||||
}
|
||||
|
@ -1382,15 +1410,15 @@ fn create_virtio_devices(
|
|||
if cfg.display_window_mouse {
|
||||
let (event_device_socket, virtio_dev_socket) =
|
||||
UnixStream::pair().map_err(Error::CreateSocket)?;
|
||||
let (single_touch_width, single_touch_height) = cfg
|
||||
.virtio_single_touch
|
||||
let (multi_touch_width, multi_touch_height) = cfg
|
||||
.virtio_multi_touch
|
||||
.as_ref()
|
||||
.map(|single_touch_spec| single_touch_spec.get_size())
|
||||
.map(|multi_touch_spec| multi_touch_spec.get_size())
|
||||
.unwrap_or((gpu_parameters.display_width, gpu_parameters.display_height));
|
||||
let dev = virtio::new_single_touch(
|
||||
let dev = virtio::new_multi_touch(
|
||||
virtio_dev_socket,
|
||||
single_touch_width,
|
||||
single_touch_height,
|
||||
multi_touch_width,
|
||||
multi_touch_height,
|
||||
virtio::base_features(cfg.protected_vm),
|
||||
)
|
||||
.map_err(Error::InputDeviceNew)?;
|
||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -1357,6 +1357,24 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
|
|||
}
|
||||
cfg.virtio_single_touch = Some(single_touch_spec);
|
||||
}
|
||||
"multi-touch" => {
|
||||
if cfg.virtio_multi_touch.is_some() {
|
||||
return Err(argument::Error::TooManyArguments(
|
||||
"`multi-touch` already given".to_owned(),
|
||||
));
|
||||
}
|
||||
let mut it = value.unwrap().split(':');
|
||||
|
||||
let mut multi_touch_spec =
|
||||
TouchDeviceOption::new(PathBuf::from(it.next().unwrap().to_owned()));
|
||||
if let Some(width) = it.next() {
|
||||
multi_touch_spec.set_width(width.trim().parse().unwrap());
|
||||
}
|
||||
if let Some(height) = it.next() {
|
||||
multi_touch_spec.set_height(height.trim().parse().unwrap());
|
||||
}
|
||||
cfg.virtio_multi_touch = Some(multi_touch_spec);
|
||||
}
|
||||
"trackpad" => {
|
||||
if cfg.virtio_trackpad.is_some() {
|
||||
return Err(argument::Error::TooManyArguments(
|
||||
|
@ -1523,6 +1541,9 @@ fn validate_arguments(cfg: &mut Config) -> std::result::Result<(), argument::Err
|
|||
{
|
||||
if let Some(gpu_parameters) = cfg.gpu_parameters.as_ref() {
|
||||
let (width, height) = (gpu_parameters.display_width, gpu_parameters.display_height);
|
||||
if let Some(virtio_multi_touch) = cfg.virtio_multi_touch.as_mut() {
|
||||
virtio_multi_touch.set_default_size(width, height);
|
||||
}
|
||||
if let Some(virtio_single_touch) = cfg.virtio_single_touch.as_mut() {
|
||||
virtio_single_touch.set_default_size(width, height);
|
||||
}
|
||||
|
@ -1665,6 +1686,7 @@ writeback=BOOL - Indicates whether the VM can use writeback caching (default: fa
|
|||
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("multi-touch", "PATH:WIDTH:HEIGHT", "Path to a socket from where to read multi 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."),
|
||||
|
|
Loading…
Reference in a new issue