mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-18 00:45:07 +00:00
cargo fmt
This commit is contained in:
parent
9070c4e836
commit
643c506a23
13 changed files with 443 additions and 48 deletions
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
use clap::{Parser, Subcommand};
|
||||
use vuinputd_tests::scenarios::{
|
||||
ScenarioArgs, basic_keyboard::BasicKeyboard, basic_mouse::BasicMouse, basic_ps4_gamepad::BasicPs4Gamepad, basic_xbox_gamepad::BasicXboxGamepad/*
|
||||
reuse_keyboard::ReuseKeyboard, reuse_xbox_gamepad::ReuseXboxGamepad,
|
||||
ScenarioArgs, stress_keyboard::StressKeyboard, stress_xbox_gamepad::StressXboxGamepad, */
|
||||
basic_keyboard::BasicKeyboard, basic_mouse::BasicMouse, basic_ps4_gamepad::BasicPs4Gamepad,
|
||||
basic_xbox_gamepad::BasicXboxGamepad, /*
|
||||
reuse_keyboard::ReuseKeyboard, reuse_xbox_gamepad::ReuseXboxGamepad,
|
||||
ScenarioArgs, stress_keyboard::StressKeyboard, stress_xbox_gamepad::StressXboxGamepad, */
|
||||
ScenarioArgs,
|
||||
};
|
||||
|
||||
#[derive(Parser)]
|
||||
|
|
@ -38,7 +40,6 @@ enum Commands {
|
|||
|
||||
/// Basic Xbox gamepad test
|
||||
BasicXboxGamepad,
|
||||
|
||||
/*
|
||||
/// Reuse keyboard test (create, destroy, recreate)
|
||||
ReuseKeyboard,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use super::Device;
|
||||
use std::{ffi::CStr, fs::File};
|
||||
use std::io;
|
||||
use std::{ffi::CStr, fs::File};
|
||||
use uinput_ioctls::*;
|
||||
|
||||
/// Key codes. Those are used by udev to recognize a device as a keyboard.
|
||||
|
|
@ -125,7 +125,6 @@ pub const KEY_PAGEDOWN: u16 = 109;
|
|||
pub const KEY_INSERT: u16 = 110;
|
||||
pub const KEY_DELETE: u16 = 111;
|
||||
|
||||
|
||||
/// Configure a full 101-key standard keyboard
|
||||
unsafe fn set_standard_keyboard_keys(fd: i32) -> Result<(), std::io::Error> {
|
||||
// We need to set more bits so that systemd recognizes a keyboard as a keyboard.
|
||||
|
|
@ -269,11 +268,10 @@ impl Device for KeyboardDevice {
|
|||
}
|
||||
|
||||
fn get_event_device(sysname: &str) -> Result<File, io::Error> {
|
||||
super::utils::fetch_device_node(sysname)
|
||||
.and_then(|devnode| File::open(&devnode))
|
||||
super::utils::fetch_device_node(sysname).and_then(|devnode| File::open(&devnode))
|
||||
}
|
||||
|
||||
fn setup(device:Option<&str>,name: &str) -> Result<i32, io::Error> {
|
||||
fn setup(device: Option<&str>, name: &str) -> Result<i32, io::Error> {
|
||||
let fd = super::utils::open_uinput(device)?;
|
||||
unsafe { set_standard_keyboard_keys(fd) }?;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use std::io;
|
|||
pub mod keyboard;
|
||||
pub mod mouse;
|
||||
pub mod ps4_gamepad;
|
||||
pub mod xbox_gamepad;
|
||||
pub mod utils;
|
||||
pub mod xbox_gamepad;
|
||||
|
||||
pub use keyboard::KeyboardDevice;
|
||||
pub use mouse::MouseDevice;
|
||||
|
|
@ -26,13 +26,13 @@ pub const EV_ABS: u16 = 0x03;
|
|||
pub trait Device {
|
||||
fn name() -> &'static str;
|
||||
fn get_event_device(sysname: &str) -> Result<File, io::Error>;
|
||||
|
||||
|
||||
/// Phase 1: open uinput, configure keys, call ui_dev_setup
|
||||
fn setup(device:Option<&str>,name: &str) -> Result<i32, io::Error>;
|
||||
|
||||
fn setup(device: Option<&str>, name: &str) -> Result<i32, io::Error>;
|
||||
|
||||
/// Phase 2: call ui_dev_create, get sysname and devnode
|
||||
fn create(fd: i32) -> Result<String, io::Error>;
|
||||
|
||||
|
||||
/// Phase 3: call ui_dev_destroy and close fd
|
||||
fn destroy(fd: i32);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use super::{ Device};
|
||||
use std::{ffi::CStr, fs::File};
|
||||
use std::io;
|
||||
use super::Device;
|
||||
use libc::c_int;
|
||||
use std::io;
|
||||
use std::{ffi::CStr, fs::File};
|
||||
use uinput_ioctls::*;
|
||||
|
||||
// Mouse codes
|
||||
|
|
@ -32,7 +32,6 @@ unsafe fn setup_mouse(fd: c_int) -> io::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub struct MouseDevice;
|
||||
|
||||
impl Device for MouseDevice {
|
||||
|
|
@ -41,8 +40,7 @@ impl Device for MouseDevice {
|
|||
}
|
||||
|
||||
fn get_event_device(sysname: &str) -> Result<File, io::Error> {
|
||||
super::utils::fetch_device_node(sysname)
|
||||
.and_then(|devnode| File::open(&devnode))
|
||||
super::utils::fetch_device_node(sysname).and_then(|devnode| File::open(&devnode))
|
||||
}
|
||||
|
||||
fn setup(device: Option<&str>, name: &str) -> Result<i32, io::Error> {
|
||||
|
|
|
|||
176
vuinputd-tests/src/devices/ps4_gamepad.rs
Normal file
176
vuinputd-tests/src/devices/ps4_gamepad.rs
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use super::Device;
|
||||
use libc::c_int;
|
||||
use std::io;
|
||||
use std::{ffi::CStr, fs::File};
|
||||
use uinput_ioctls::*;
|
||||
|
||||
// PS4 Gamepad codes
|
||||
const BTN_SOUTH: u16 = 304; // Cross
|
||||
const BTN_EAST: u16 = 305; // Circle
|
||||
const BTN_NORTH: u16 = 306; // Square
|
||||
const BTN_WEST: u16 = 307; // Triangle
|
||||
const BTN_TOP: u16 = 310; // L1
|
||||
const BTN_TOP2: u16 = 311; // R1
|
||||
const BTN_BASE: u16 = 312; // Share
|
||||
const BTN_BASE2: u16 = 313; // Options
|
||||
const BTN_BASE3: u16 = 314; // L3
|
||||
const BTN_BASE23: u16 = 315; // R3
|
||||
const BTN_TL: u16 = 316; // L2
|
||||
const BTN_TR: u16 = 317; // R2
|
||||
const BTN_SELECT: u16 = 318;
|
||||
const BTN_START: u16 = 319;
|
||||
const BTN_THUMBL: u16 = 320;
|
||||
const BTN_THUMBR: u16 = 321;
|
||||
const BTN_TOUCH: u16 = 322;
|
||||
const BTN_TR2: u16 = 323;
|
||||
const BTN_DPAD_UP: u16 = 325;
|
||||
const BTN_DPAD_DOWN: u16 = 326;
|
||||
const BTN_DPAD_LEFT: u16 = 327;
|
||||
const BTN_DPAD_RIGHT: u16 = 328;
|
||||
|
||||
const ABS_X: u16 = 0;
|
||||
const ABS_Y: u16 = 1;
|
||||
const ABS_Z: u16 = 2;
|
||||
const ABS_RX: u16 = 3;
|
||||
const ABS_RY: u16 = 4;
|
||||
const ABS_RZ: u16 = 5;
|
||||
const ABS_THROTTLE: u16 = 6;
|
||||
const ABS_RUDDER: u16 = 7;
|
||||
const ABS_PRESSURE: u16 = 24;
|
||||
const ABS_DISTANCE: u16 = 32;
|
||||
const ABS_MT_POSITION_X: u16 = 47;
|
||||
const ABS_MT_POSITION_Y: u16 = 48;
|
||||
const ABS_MT_TRACKING_ID: u16 = 57;
|
||||
const ABS_MT_PRESSURE: u16 = 47;
|
||||
const ABS_MT_TOOL_TYPE: u16 = 55;
|
||||
const ABS_MT_WIDTH: u16 = 56;
|
||||
|
||||
// Xbox Gamepad codes
|
||||
const BTN_A: u16 = 304; // A
|
||||
const BTN_B: u16 = 305; // B
|
||||
const BTN_X: u16 = 306; // X
|
||||
const BTN_Y: u16 = 307; // Y
|
||||
const BTN_TL2: u16 = 319; // LT
|
||||
|
||||
pub struct Ps4GamepadDevice;
|
||||
|
||||
/// Setup PS4 gamepad device
|
||||
unsafe fn setup_ps4_gamepad(fd: c_int) -> io::Result<()> {
|
||||
// EV_SYN
|
||||
ui_set_evbit(fd, super::EV_SYN.try_into().unwrap())?;
|
||||
// EV_KEY
|
||||
ui_set_evbit(fd, super::EV_KEY.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_SOUTH.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_EAST.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_NORTH.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_WEST.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TOP.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TOP2.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_BASE.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_BASE2.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_BASE3.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_BASE23.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TL.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TR.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_SELECT.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_START.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_THUMBL.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_THUMBR.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TOUCH.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TR2.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_UP.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_DOWN.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_LEFT.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_RIGHT.try_into().unwrap())?;
|
||||
// EV_ABS
|
||||
ui_set_evbit(fd, super::EV_ABS.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_X.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_Y.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_RX.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_RY.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_PRESSURE.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_DISTANCE.try_into().unwrap())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Device for Ps4GamepadDevice {
|
||||
fn name() -> &'static str {
|
||||
"PS4 Gamepad"
|
||||
}
|
||||
|
||||
fn get_event_device(sysname: &str) -> Result<File, io::Error> {
|
||||
super::utils::fetch_device_node(sysname).and_then(|devnode| File::open(&devnode))
|
||||
}
|
||||
|
||||
fn setup(device: Option<&str>, name: &str) -> Result<i32, io::Error> {
|
||||
let fd = super::utils::open_uinput(device)?;
|
||||
unsafe { setup_ps4_gamepad(fd) }?;
|
||||
|
||||
unsafe {
|
||||
let mut usetup: libc::uinput_setup = std::mem::zeroed();
|
||||
usetup.id.bustype = BUS_USB;
|
||||
usetup.id.vendor = 0xbeef;
|
||||
usetup.id.product = 0xdead;
|
||||
|
||||
let name_cstr = CString::new(name).unwrap();
|
||||
let name_ptr = usetup.name.as_mut_ptr() as *mut c_char;
|
||||
std::ptr::copy_nonoverlapping(
|
||||
name_cstr.as_ptr(),
|
||||
name_ptr,
|
||||
name_cstr.to_bytes_with_nul().len(),
|
||||
);
|
||||
|
||||
let usetup_ptr = &mut usetup as *mut libc::uinput_setup;
|
||||
ui_dev_setup(fd, usetup_ptr).map_err(|e| {
|
||||
eprintln!("ui_dev_setup failed: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(fd)
|
||||
}
|
||||
|
||||
fn create(fd: i32) -> Result<String, io::Error> {
|
||||
unsafe {
|
||||
ui_dev_create(fd).map_err(|e| {
|
||||
eprintln!("ui_dev_create failed: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let mut resultbuf: [c_char; 64] = [0; 64];
|
||||
ui_get_sysname(fd, resultbuf.as_mut_slice()).map_err(|e| {
|
||||
eprintln!("ui_get_sysname failed: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let sysname = format!(
|
||||
"{}{}",
|
||||
SYS_INPUT_DIR,
|
||||
CStr::from_ptr(resultbuf.as_ptr()).to_string_lossy()
|
||||
);
|
||||
|
||||
Ok(sysname)
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy(fd: i32) {
|
||||
unsafe {
|
||||
ui_dev_destroy(fd).unwrap_or_else(|e| {
|
||||
eprintln!("ui_dev_destroy failed: {:?}", e);
|
||||
std::process::exit(1);
|
||||
});
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use libc::{c_char, close};
|
||||
use std::ffi::CString;
|
||||
|
||||
const SYS_INPUT_DIR: &str = "/sys/devices/virtual/input/";
|
||||
const BUS_USB: u16 = 0x03;
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use crate::test_log::{LoggedInputEvent, TestLog};
|
||||
use libc::{c_int, close, open, write, O_NONBLOCK, O_WRONLY};
|
||||
use libc::{input_event, timespec, uinput_setup, CLOCK_MONOTONIC};
|
||||
use std::ffi::{CStr, CString};
|
||||
|
|
@ -12,7 +13,6 @@ use std::os::fd::AsRawFd;
|
|||
use std::os::raw::{c_char, c_void};
|
||||
use std::ptr;
|
||||
pub use uinput_ioctls::*;
|
||||
use crate::test_log::{LoggedInputEvent, TestLog};
|
||||
|
||||
// Constants (same numeric values as in linux headers)
|
||||
const EV_SYN: u16 = 0x00;
|
||||
|
|
@ -20,7 +20,6 @@ const EV_KEY: u16 = 0x01;
|
|||
const SYN_REPORT: u16 = 0;
|
||||
const BUS_USB: u16 = 0x03;
|
||||
|
||||
|
||||
pub fn emit(fd: c_int, ev_type: u16, code: u16, val: i32) -> io::Result<()> {
|
||||
// libc's input_event struct layout:
|
||||
// struct input_event {
|
||||
|
|
@ -126,8 +125,7 @@ pub fn monotonic_time() -> (i64, i64) {
|
|||
(ts.tv_sec, ts.tv_nsec)
|
||||
}
|
||||
|
||||
|
||||
pub fn open_uinput(device:Option<&str>) -> io::Result<i32> {
|
||||
pub fn open_uinput(device: Option<&str>) -> io::Result<i32> {
|
||||
let device = match device {
|
||||
Some(dev_path) => dev_path,
|
||||
_ => "/dev/uinput",
|
||||
|
|
@ -140,4 +138,4 @@ pub fn open_uinput(device:Option<&str>) -> io::Result<i32> {
|
|||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(fd)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
170
vuinputd-tests/src/devices/xbox_gamepad.rs
Normal file
170
vuinputd-tests/src/devices/xbox_gamepad.rs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Author: Johannes Leupolz <dev@leupolz.eu>
|
||||
|
||||
use super::Device;
|
||||
use libc::c_int;
|
||||
use std::io;
|
||||
use std::{ffi::CStr, fs::File};
|
||||
use uinput_ioctls::*;
|
||||
|
||||
// PS4 Gamepad codes
|
||||
const BTN_SOUTH: u16 = 304; // Cross
|
||||
const BTN_EAST: u16 = 305; // Circle
|
||||
const BTN_NORTH: u16 = 306; // Square
|
||||
const BTN_WEST: u16 = 307; // Triangle
|
||||
const BTN_TOP: u16 = 310; // L1
|
||||
const BTN_TOP2: u16 = 311; // R1
|
||||
const BTN_BASE: u16 = 312; // Share
|
||||
const BTN_BASE2: u16 = 313; // Options
|
||||
const BTN_BASE3: u16 = 314; // L3
|
||||
const BTN_BASE23: u16 = 315; // R3
|
||||
const BTN_TL: u16 = 316; // L2
|
||||
const BTN_TR: u16 = 317; // R2
|
||||
const BTN_SELECT: u16 = 318;
|
||||
const BTN_START: u16 = 319;
|
||||
const BTN_THUMBL: u16 = 320;
|
||||
const BTN_THUMBR: u16 = 321;
|
||||
const BTN_TOUCH: u16 = 322;
|
||||
const BTN_TR2: u16 = 323;
|
||||
const BTN_DPAD_UP: u16 = 325;
|
||||
const BTN_DPAD_DOWN: u16 = 326;
|
||||
const BTN_DPAD_LEFT: u16 = 327;
|
||||
const BTN_DPAD_RIGHT: u16 = 328;
|
||||
|
||||
const ABS_X: u16 = 0;
|
||||
const ABS_Y: u16 = 1;
|
||||
const ABS_Z: u16 = 2;
|
||||
const ABS_RX: u16 = 3;
|
||||
const ABS_RY: u16 = 4;
|
||||
const ABS_RZ: u16 = 5;
|
||||
const ABS_THROTTLE: u16 = 6;
|
||||
const ABS_RUDDER: u16 = 7;
|
||||
const ABS_PRESSURE: u16 = 24;
|
||||
const ABS_DISTANCE: u16 = 32;
|
||||
const ABS_MT_POSITION_X: u16 = 47;
|
||||
const ABS_MT_POSITION_Y: u16 = 48;
|
||||
const ABS_MT_TRACKING_ID: u16 = 57;
|
||||
const ABS_MT_PRESSURE: u16 = 47;
|
||||
const ABS_MT_TOOL_TYPE: u16 = 55;
|
||||
const ABS_MT_WIDTH: u16 = 56;
|
||||
|
||||
// Xbox Gamepad codes
|
||||
const BTN_A: u16 = 304; // A
|
||||
const BTN_B: u16 = 305; // B
|
||||
const BTN_X: u16 = 306; // X
|
||||
const BTN_Y: u16 = 307; // Y
|
||||
const BTN_TL2: u16 = 319; // LT
|
||||
|
||||
/// Setup Xbox gamepad device
|
||||
unsafe fn setup_xbox_gamepad(fd: c_int) -> io::Result<()> {
|
||||
// EV_SYN
|
||||
ui_set_evbit(fd, super::EV_SYN.try_into().unwrap())?;
|
||||
// EV_KEY
|
||||
ui_set_evbit(fd, super::EV_KEY.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_A.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_B.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_X.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_Y.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TL.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TR.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_SELECT.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_START.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_THUMBL.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_THUMBR.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TL2.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_TR2.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_UP.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_DOWN.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_LEFT.try_into().unwrap())?;
|
||||
ui_set_keybit(fd, BTN_DPAD_RIGHT.try_into().unwrap())?;
|
||||
// EV_ABS
|
||||
ui_set_evbit(fd, super::EV_ABS.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_X.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_Y.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_RX.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_RY.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_PRESSURE.try_into().unwrap())?;
|
||||
ui_set_absbit(fd, ABS_DISTANCE.try_into().unwrap())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct XboxGamepadDevice;
|
||||
|
||||
impl Device for XboxGamepadDevice {
|
||||
fn name() -> &'static str {
|
||||
"Xbox Gamepad"
|
||||
}
|
||||
|
||||
fn get_event_device(sysname: &str) -> Result<File, io::Error> {
|
||||
super::utils::fetch_device_node(sysname).and_then(|devnode| File::open(&devnode))
|
||||
}
|
||||
|
||||
fn setup(device: Option<&str>, name: &str) -> Result<i32, io::Error> {
|
||||
let fd = super::utils::open_uinput(device)?;
|
||||
unsafe { setup_xbox_gamepad(fd) }?;
|
||||
|
||||
unsafe {
|
||||
let mut usetup: libc::uinput_setup = std::mem::zeroed();
|
||||
usetup.id.bustype = BUS_USB;
|
||||
usetup.id.vendor = 0xbeef;
|
||||
usetup.id.product = 0xdead;
|
||||
|
||||
let name_cstr = CString::new(name).unwrap();
|
||||
let name_ptr = usetup.name.as_mut_ptr() as *mut c_char;
|
||||
std::ptr::copy_nonoverlapping(
|
||||
name_cstr.as_ptr(),
|
||||
name_ptr,
|
||||
name_cstr.to_bytes_with_nul().len(),
|
||||
);
|
||||
|
||||
let usetup_ptr = &mut usetup as *mut libc::uinput_setup;
|
||||
ui_dev_setup(fd, usetup_ptr).map_err(|e| {
|
||||
eprintln!("ui_dev_setup failed: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(fd)
|
||||
}
|
||||
|
||||
fn create(fd: i32) -> Result<String, io::Error> {
|
||||
unsafe {
|
||||
ui_dev_create(fd).map_err(|e| {
|
||||
eprintln!("ui_dev_create failed: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let mut resultbuf: [c_char; 64] = [0; 64];
|
||||
ui_get_sysname(fd, resultbuf.as_mut_slice()).map_err(|e| {
|
||||
eprintln!("ui_get_sysname failed: {:?}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let sysname = format!(
|
||||
"{}{}",
|
||||
SYS_INPUT_DIR,
|
||||
CStr::from_ptr(resultbuf.as_ptr()).to_string_lossy()
|
||||
);
|
||||
|
||||
Ok(sysname)
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy(fd: i32) {
|
||||
unsafe {
|
||||
ui_dev_destroy(fd).unwrap_or_else(|e| {
|
||||
eprintln!("ui_dev_destroy failed: {:?}", e);
|
||||
std::process::exit(1);
|
||||
});
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use libc::{c_char, close};
|
||||
use std::ffi::CString;
|
||||
|
||||
const SYS_INPUT_DIR: &str = "/sys/devices/virtual/input/";
|
||||
const BUS_USB: u16 = 0x03;
|
||||
|
|
@ -6,9 +6,9 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::devices::keyboard::KeyboardDevice;
|
||||
use crate::devices::{utils, Device};
|
||||
use crate::scenarios::ScenarioArgs;
|
||||
use crate::devices::{Device, utils};
|
||||
use crate::test_log::{TestLog};
|
||||
use crate::test_log::TestLog;
|
||||
|
||||
const KEY_SPACE: u16 = 57;
|
||||
|
||||
|
|
@ -16,8 +16,11 @@ pub struct BasicKeyboard;
|
|||
|
||||
impl BasicKeyboard {
|
||||
pub fn run(args: &ScenarioArgs) -> Result<(), std::io::Error> {
|
||||
let device = args.dev_path.clone().unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
let fd = KeyboardDevice::setup(Some(&device),"Example Keyboard")?;
|
||||
let device = args
|
||||
.dev_path
|
||||
.clone()
|
||||
.unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
let fd = KeyboardDevice::setup(Some(&device), "Example Keyboard")?;
|
||||
let sysname = KeyboardDevice::create(fd)?;
|
||||
eprintln!("sysname: {}", sysname);
|
||||
|
||||
|
|
@ -30,11 +33,13 @@ impl BasicKeyboard {
|
|||
let ev1 = utils::emit_read_and_log(fd, &event_device, 0x01, KEY_SPACE, 1)?;
|
||||
let ev2 = utils::emit_read_and_log(fd, &event_device, 0x01, KEY_SPACE, 0)?;
|
||||
|
||||
let eventlog = TestLog { events: vec![ev1, ev2] };
|
||||
let eventlog = TestLog {
|
||||
events: vec![ev1, ev2],
|
||||
};
|
||||
let serialized = serde_json::to_string(&eventlog).unwrap();
|
||||
println!("Event log: {}", serialized);
|
||||
|
||||
KeyboardDevice::destroy(fd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::devices::mouse::MouseDevice;
|
||||
use crate::devices::{utils, Device};
|
||||
use crate::scenarios::ScenarioArgs;
|
||||
use crate::devices::{Device, utils};
|
||||
use crate::test_log::{LoggedInputEvent, TestLog};
|
||||
|
||||
const BTN_LEFT: u16 = 272;
|
||||
|
|
@ -15,8 +15,11 @@ pub struct BasicMouse;
|
|||
|
||||
impl BasicMouse {
|
||||
pub fn run(args: &ScenarioArgs) -> Result<(), std::io::Error> {
|
||||
let device = args.dev_path.clone().unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
|
||||
let device = args
|
||||
.dev_path
|
||||
.clone()
|
||||
.unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
|
||||
let fd = MouseDevice::setup(Some(&device), "Example Mouse")?;
|
||||
let sysname = MouseDevice::create(fd)?;
|
||||
eprintln!("sysname: {}", sysname);
|
||||
|
|
@ -30,7 +33,9 @@ impl BasicMouse {
|
|||
let ev1 = utils::emit_read_and_log(fd, &event_device, 0x01, BTN_LEFT, 1)?;
|
||||
let ev2 = utils::emit_read_and_log(fd, &event_device, 0x01, BTN_LEFT, 0)?;
|
||||
|
||||
let eventlog = TestLog { events: vec![ev1, ev2] };
|
||||
let eventlog = TestLog {
|
||||
events: vec![ev1, ev2],
|
||||
};
|
||||
let serialized = serde_json::to_string(&eventlog).unwrap();
|
||||
println!("Event log: {}", serialized);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::devices::ps4_gamepad::Ps4GamepadDevice;
|
||||
use crate::devices::{utils, Device};
|
||||
use crate::scenarios::ScenarioArgs;
|
||||
use crate::devices::{Device, utils};
|
||||
use crate::test_log::{LoggedInputEvent, TestLog};
|
||||
|
||||
const BTN_SOUTH: u16 = 304;
|
||||
|
|
@ -15,8 +15,11 @@ pub struct BasicPs4Gamepad;
|
|||
|
||||
impl BasicPs4Gamepad {
|
||||
pub fn run(args: &ScenarioArgs) -> Result<(), std::io::Error> {
|
||||
let device = args.dev_path.clone().unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
|
||||
let device = args
|
||||
.dev_path
|
||||
.clone()
|
||||
.unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
|
||||
let fd = Ps4GamepadDevice::setup(Some(&device), "PS4 Gamepad")?;
|
||||
let sysname = Ps4GamepadDevice::create(fd)?;
|
||||
eprintln!("sysname: {}", sysname);
|
||||
|
|
@ -30,11 +33,13 @@ impl BasicPs4Gamepad {
|
|||
let ev1 = utils::emit_read_and_log(fd, &event_device, 0x01, BTN_SOUTH, 1)?;
|
||||
let ev2 = utils::emit_read_and_log(fd, &event_device, 0x01, BTN_SOUTH, 0)?;
|
||||
|
||||
let eventlog = TestLog { events: vec![ev1, ev2] };
|
||||
let eventlog = TestLog {
|
||||
events: vec![ev1, ev2],
|
||||
};
|
||||
let serialized = serde_json::to_string(&eventlog).unwrap();
|
||||
println!("Event log: {}", serialized);
|
||||
|
||||
Ps4GamepadDevice::destroy(fd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::devices::xbox_gamepad::XboxGamepadDevice;
|
||||
use crate::devices::{utils, Device};
|
||||
use crate::scenarios::ScenarioArgs;
|
||||
use crate::devices::{Device, utils};
|
||||
use crate::test_log::{LoggedInputEvent, TestLog};
|
||||
|
||||
const BTN_A: u16 = 304;
|
||||
|
|
@ -16,8 +16,11 @@ pub struct BasicXboxGamepad;
|
|||
|
||||
impl BasicXboxGamepad {
|
||||
pub fn run(args: &ScenarioArgs) -> Result<(), std::io::Error> {
|
||||
let device = args.dev_path.clone().unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
|
||||
let device = args
|
||||
.dev_path
|
||||
.clone()
|
||||
.unwrap_or_else(|| "/dev/uinput".to_string());
|
||||
|
||||
let fd = XboxGamepadDevice::setup(Some(&device), "Xbox Gamepad")?;
|
||||
let sysname = XboxGamepadDevice::create(fd)?;
|
||||
eprintln!("sysname: {}", sysname);
|
||||
|
|
@ -31,7 +34,9 @@ impl BasicXboxGamepad {
|
|||
let ev1 = utils::emit_read_and_log(fd, &event_device, 0x01, BTN_A, 1)?;
|
||||
let ev2 = utils::emit_read_and_log(fd, &event_device, 0x01, BTN_A, 0)?;
|
||||
|
||||
let eventlog = TestLog { events: vec![ev1, ev2] };
|
||||
let eventlog = TestLog {
|
||||
events: vec![ev1, ev2],
|
||||
};
|
||||
let serialized = serde_json::to_string(&eventlog).unwrap();
|
||||
println!("Event log: {}", serialized);
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ fn test_keyboard_in_container_with_uinput() {
|
|||
))]
|
||||
#[test]
|
||||
fn test_keyboard_in_container_with_vuinput_placement_in_container() {
|
||||
let _guard: run_vuinputd::VuinputdGuard=run_vuinputd::ensure_vuinputd_running(&[]);
|
||||
let _guard: run_vuinputd::VuinputdGuard = run_vuinputd::ensure_vuinputd_running(&[]);
|
||||
|
||||
let test_keyboard = env!("CARGO_BIN_EXE_test-keyboard");
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ fn test_keyboard_in_container_with_vuinput_placement_in_container() {
|
|||
))]
|
||||
#[test]
|
||||
fn test_keyboard_in_container_with_vuinput_placement_on_host() {
|
||||
let _guard=run_vuinputd::ensure_vuinputd_running(&["--placement","on-host"]);
|
||||
let _guard = run_vuinputd::ensure_vuinputd_running(&["--placement", "on-host"]);
|
||||
|
||||
let test_keyboard = env!("CARGO_BIN_EXE_test-keyboard");
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ fn test_podman_ipc() {
|
|||
))]
|
||||
#[test]
|
||||
fn test_keyboard_in_container_with_vuinput() {
|
||||
let _guard=run_vuinputd::ensure_vuinputd_running(&[]);
|
||||
let _guard = run_vuinputd::ensure_vuinputd_running(&[]);
|
||||
|
||||
let (builder, _ipc) = podman::PodmanBuilder::new()
|
||||
.run_cmd()
|
||||
|
|
@ -91,3 +91,37 @@ fn test_keyboard_in_container_with_vuinput() {
|
|||
|
||||
assert!(out.status.success());
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "requires-rootless",
|
||||
feature = "requires-uinput",
|
||||
feature = "requires-podman"
|
||||
))]
|
||||
#[test]
|
||||
fn test_keyboard_in_container_with_vuinput_rootless_with_userns() {
|
||||
let _guard = run_vuinputd::ensure_vuinputd_running(&[]);
|
||||
|
||||
let (builder, _ipc) = podman::PodmanBuilder::new()
|
||||
.run_cmd()
|
||||
.rm()
|
||||
.userns("auto")
|
||||
.with_ipc()
|
||||
.expect("failed to create IPC");
|
||||
let builder = builder
|
||||
//.detach()
|
||||
//.name(&format!("vuinputd-podman-tests"))
|
||||
.device("/dev/vuinput-test:/dev/uinput")
|
||||
.allow_input_devices()
|
||||
.image("localhost/vuinputd-tests:latest")
|
||||
.command(&["/test-keyboard"]);
|
||||
|
||||
let out = builder
|
||||
.run()
|
||||
.unwrap_or_else(|e| panic!("failed to run podman!: {e}"));
|
||||
|
||||
println!("Output");
|
||||
println!("stdout: {}", str::from_utf8(&out.stdout).unwrap());
|
||||
println!("stderr: {}", str::from_utf8(&out.stderr).unwrap());
|
||||
|
||||
assert!(out.status.success());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue