use std::collections::BTreeMap;
use std::fs::File;
use anyhow::{bail, Result};
use libc::c_int;
use log::error;
use vmm_sys_util::{ioctl::ioctl_with_mut_ref, ioctl_ioc_nr, ioctl_ior_nr, ioctl_iow_nr};
use crate::byte_code::ByteCode;
pub const EV_KEY: u8 = 0x01;
pub const EV_ABS: u8 = 0x03;
pub const EV_MSC: u8 = 0x04;
pub const EV_REP: u8 = 0x14;
pub const EV_MAX: u8 = 0x1F;
pub const ABS_X: u8 = 0x00;
pub const ABS_Y: u8 = 0x01;
pub const ABS_MT_SLOT: u8 = 0x2F;
pub const ABS_MT_TOUCH_MAJOR: u8 = 0x30;
pub const ABS_MT_TOUCH_MINOR: u8 = 0x31;
pub const ABS_MT_POSITION_X: u8 = 0x35;
pub const ABS_MT_POSITION_Y: u8 = 0x36;
pub const ABS_MT_TRACKING_ID: u8 = 0x39;
pub const ABS_MT_PRESSURE: u8 = 0x3A;
pub const ABS_MAX: u8 = 0x3F;
pub const BTN_LEFT: u16 = 0x110;
pub const BTN_TOUCH: u16 = 0x14A;
pub const BTN_TOOL_FINGER: u16 = 0x145;
pub const BTN_TOOL_DOUBLETAP: u16 = 0x14D;
pub const BTN_TOOL_TRIPLETAP: u16 = 0x14E;
pub const MSC_TIMESTAMP: u16 = 0x05;
pub const EV_SYN: u16 = 0x00;
pub const SYN_REPORT: u16 = 0x00;
pub const SYN_MT_REPORT: u16 = 0x2;
pub const INPUT_PROP_POINTER: u16 = 0x00;
pub const INPUT_PROP_DIRECT: u16 = 0x01;
pub const INPUT_PROP_BUTTONPAD: u16 = 0x02;
pub const BUS_VIRTUAL: u16 = 0x06;
pub const VIRTIO_INPUT_CFG_PAYLOAD_SIZE: usize = 128;
#[derive(Copy, Clone)]
pub struct EvdevBuf {
pub buf: [u8; VIRTIO_INPUT_CFG_PAYLOAD_SIZE],
pub len: usize,
}
impl EvdevBuf {
pub fn new() -> Self {
Self {
buf: [0_u8; VIRTIO_INPUT_CFG_PAYLOAD_SIZE],
len: 0,
}
}
pub fn get_bit(&self, bit: usize) -> bool {
if bit.div_ceil(8) > self.len {
return false;
}
let idx = bit / 8;
let offset = bit % 8;
self.buf[idx] & (1u8 << offset) != 0
}
pub fn set_bit(&mut self, bit: usize) -> &mut Self {
let ceiling_len = bit.div_ceil(8);
if ceiling_len > VIRTIO_INPUT_CFG_PAYLOAD_SIZE {
return self;
}
if ceiling_len > self.len {
self.len = ceiling_len;
}
let idx = bit / 8;
let offset = bit % 8;
self.buf[idx] |= 1u8 << offset;
self
}
pub fn to_vec(self) -> Vec<u8> {
self.buf[0..self.len].to_vec()
}
}
impl Default for EvdevBuf {
fn default() -> Self {
Self::new()
}
}
impl ByteCode for EvdevBuf {}
#[derive(Copy, Clone, Default)]
#[repr(C)]
pub struct EvdevId {
pub bustype: u16,
pub vendor: u16,
pub product: u16,
pub version: u16,
}
impl EvdevId {
pub fn from_buf(buf: EvdevBuf) -> Self {
*Self::from_bytes(buf.to_vec().as_slice()).unwrap()
}
}
impl ByteCode for EvdevId {}
#[derive(Copy, Clone, Default)]
#[repr(C)]
pub struct InputAbsInfo {
pub value: u32,
pub minimum: u32,
pub maximum: u32,
pub fuzz: u32,
pub flat: u32,
pub resolution: u32,
}
impl InputAbsInfo {
pub fn new(min: u32, max: u32, res: u32) -> Self {
Self {
minimum: min,
maximum: max,
resolution: res,
..Default::default()
}
}
}
const EVDEV: u32 = 69;
ioctl_ior_nr!(EVIOCGVERSION, EVDEV, 0x01, c_int);
ioctl_ior_nr!(EVIOCGID, EVDEV, 0x02, EvdevId);
ioctl_ior_nr!(EVIOCGNAME, EVDEV, 0x06, EvdevBuf);
ioctl_ior_nr!(EVIOCGUNIQ, EVDEV, 0x08, EvdevBuf);
ioctl_ior_nr!(EVIOCGPROP, EVDEV, 0x09, EvdevBuf);
ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, EvdevBuf, evt);
ioctl_ior_nr!(EVIOCGABS, EVDEV, 0x40 + abs, InputAbsInfo, abs);
ioctl_iow_nr!(EVIOCGRAB, EVDEV, 0x90, c_int);
pub unsafe fn evdev_ioctl(fd: &File, req: u64, len: usize) -> EvdevBuf {
let mut evbuf = EvdevBuf::new();
let ret = unsafe { ioctl_with_mut_ref(fd, req, &mut evbuf.buf) };
if ret < 0 {
error!(
"Ioctl {} failed, error is {}.",
req,
std::io::Error::last_os_error()
);
evbuf.len = 0;
return evbuf;
}
evbuf.len = len;
if evbuf.len == 0 {
if ret != 0 {
evbuf.len = ret as usize;
} else {
evbuf.len = VIRTIO_INPUT_CFG_PAYLOAD_SIZE;
}
}
evbuf
}
pub unsafe fn evdev_evt_supported(fd: &File) -> Result<BTreeMap<u8, EvdevBuf>> {
let mut evts: BTreeMap<u8, EvdevBuf> = BTreeMap::new();
let evt_type = unsafe { evdev_ioctl(fd, EVIOCGBIT(0), 0) };
if evt_type.len == 0 {
bail!(format!(
"Failed to get bit 0, error {}",
std::io::Error::last_os_error()
))
}
for ev in 1..EV_MAX {
if ev == EV_REP || !evt_type.get_bit(ev as usize) {
continue;
}
let ret = unsafe { evdev_ioctl(fd, EVIOCGBIT(ev as u32), 0) };
evts.insert(ev, ret);
}
Ok(evts)
}
#[derive(Default)]
pub struct EvdevBufHelper {
evbufdb: BTreeMap<u8, EvdevBuf>,
}
impl EvdevBufHelper {
pub fn new() -> Self {
Self {
evbufdb: BTreeMap::new(),
}
}
pub fn push(&mut self, key: u8, evbuf: EvdevBuf) -> &mut Self {
self.evbufdb.insert(key, evbuf);
self
}
pub fn to_raw(&self) -> BTreeMap<u8, EvdevBuf> {
self.evbufdb.clone()
}
}
pub fn evdev_abs(fd: &File) -> Result<BTreeMap<u8, InputAbsInfo>> {
let mut absinfo_db: BTreeMap<u8, InputAbsInfo> = BTreeMap::new();
for abs in 0..ABS_MAX {
let mut absinfo = InputAbsInfo::default();
let len = unsafe { ioctl_with_mut_ref(fd, EVIOCGABS(abs as u32), &mut absinfo) };
if len == 0 {
absinfo_db.insert(abs, absinfo);
}
}
Ok(absinfo_db)
}
#[derive(Default)]
pub struct AbsinfoHelper {
absdb: BTreeMap<u8, InputAbsInfo>,
}
impl AbsinfoHelper {
pub fn new() -> Self {
Self {
absdb: BTreeMap::new(),
}
}
pub fn push(&mut self, abs: u8, absinfo: InputAbsInfo) -> &mut Self {
self.absdb.insert(abs, absinfo);
self
}
pub fn to_raw(&self) -> BTreeMap<u8, InputAbsInfo> {
self.absdb.clone()
}
}
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct InputEvent {
pub timestamp: [u64; 2],
pub ev_type: u16,
pub code: u16,
pub value: i32,
}
impl ByteCode for InputEvent {}
impl InputEvent {
pub fn new(ev_type: u16, code: u16, value: i32) -> Self {
Self {
timestamp: [0; 2],
ev_type,
code,
value,
}
}
pub fn new_u8(ev_type: u8, code: u8, value: i32) -> Self {
Self {
timestamp: [0; 2],
ev_type: ev_type as u16,
code: code as u16,
value,
}
}
}