mirror of
https://github.com/htrefil/rkvm.git
synced 2025-01-29 20:34:14 +01:00
Gut input crate
This commit is contained in:
parent
033594e302
commit
5e2e7becb4
12 changed files with 31 additions and 272 deletions
|
@ -1,20 +1,16 @@
|
|||
use bindgen::{Builder, CargoCallbacks};
|
||||
use cc::Build;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=setup/setup.h");
|
||||
println!("cargo:rerun-if-changed=setup/setup.c");
|
||||
|
||||
Build::new().file("setup/setup.c").compile("setup");
|
||||
println!("cargo:rerun-if-changed=glue/glue.h");
|
||||
|
||||
let bindings = Builder::default()
|
||||
.header("setup/setup.h")
|
||||
.header("glue/glue.h")
|
||||
.parse_callbacks(Box::new(CargoCallbacks))
|
||||
.generate()
|
||||
.unwrap();
|
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings.write_to_file(out_path.join("setup.rs")).unwrap();
|
||||
bindings.write_to_file(out_path.join("glue.rs")).unwrap();
|
||||
}
|
||||
|
|
1
input/glue/glue.h
Normal file
1
input/glue/glue.h
Normal file
|
@ -0,0 +1 @@
|
|||
#include <linux/input.h>
|
|
@ -1,50 +0,0 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#define IOCTL(fd, ...) if (ioctl(fd, __VA_ARGS__) == -1) return 0;
|
||||
|
||||
int setup_write_fd(int fd) {
|
||||
IOCTL(fd, UI_SET_EVBIT, EV_KEY);
|
||||
IOCTL(fd, UI_SET_EVBIT, EV_SYN);
|
||||
IOCTL(fd, UI_SET_EVBIT, EV_REL);
|
||||
IOCTL(fd, UI_SET_EVBIT, EV_ABS);
|
||||
|
||||
for (int i = 0; i < KEY_MAX; i++)
|
||||
IOCTL(fd, UI_SET_KEYBIT, i);
|
||||
|
||||
for (int i = 0; i < ABS_MAX; i++)
|
||||
IOCTL(fd, UI_SET_ABSBIT, i);
|
||||
|
||||
IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT);
|
||||
IOCTL(fd, UI_SET_KEYBIT, BTN_RIGHT);
|
||||
|
||||
IOCTL(fd, UI_SET_RELBIT, REL_X);
|
||||
IOCTL(fd, UI_SET_RELBIT, REL_Y);
|
||||
IOCTL(fd, UI_SET_RELBIT, REL_WHEEL);
|
||||
|
||||
struct uinput_setup setup;
|
||||
memset(&setup, 0, sizeof(setup));
|
||||
setup.id.bustype = BUS_USB;
|
||||
setup.id.vendor = 1;
|
||||
setup.id.product = 1;
|
||||
setup.ff_effects_max = 0;
|
||||
strcpy(setup.name, "rkvm");
|
||||
|
||||
IOCTL(fd, UI_DEV_SETUP, &setup);
|
||||
IOCTL(fd, UI_DEV_CREATE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int destroy_write_fd(int fd) {
|
||||
IOCTL(fd, UI_DEV_DESTROY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setup_read_fd(int fd) {
|
||||
int grab = 1;
|
||||
IOCTL(fd, EVIOCGRAB, &grab);
|
||||
return 1;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#include <linux/uinput.h>
|
||||
|
||||
int setup_write_fd(int fd);
|
||||
|
||||
int destroy_write_fd(int fd);
|
||||
|
||||
int setup_read_fd(int fd);
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
use mio::event::Evented;
|
||||
use mio::unix::EventedFd;
|
||||
use mio::{Poll, PollOpt, Ready, Token};
|
||||
use std::convert::AsRef;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Error, Read, Write};
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::pin::Pin;
|
||||
use std::task::{self, Context};
|
||||
use tokio::io::{AsyncRead, AsyncWrite, PollEvented};
|
||||
|
||||
pub struct AsyncFile {
|
||||
file: PollEvented<Inner>,
|
||||
}
|
||||
|
||||
impl AsyncFile {
|
||||
pub async fn open(path: impl AsRef<Path>, mode: OpenMode) -> Result<Self, Error> {
|
||||
let path = path.as_ref().to_owned();
|
||||
|
||||
tokio::task::spawn_blocking(move || Self::open_sync(path, mode)).await?
|
||||
}
|
||||
|
||||
fn open_sync(path: PathBuf, mode: OpenMode) -> Result<Self, Error> {
|
||||
let mut options = OpenOptions::new();
|
||||
match mode {
|
||||
OpenMode::Read => options.read(true),
|
||||
OpenMode::Write => options.write(true),
|
||||
};
|
||||
|
||||
let file = options.custom_flags(libc::O_NONBLOCK).open(&path)?;
|
||||
Ok(Self {
|
||||
file: PollEvented::new(Inner { file })?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for AsyncFile {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.file.get_ref().file.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for AsyncFile {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
context: &mut Context,
|
||||
buffer: &mut [u8],
|
||||
) -> task::Poll<Result<usize, Error>> {
|
||||
Pin::new(&mut self.file).poll_read(context, buffer)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for AsyncFile {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
context: &mut Context,
|
||||
data: &[u8],
|
||||
) -> task::Poll<Result<usize, Error>> {
|
||||
Pin::new(&mut self.file).poll_write(context, data)
|
||||
}
|
||||
|
||||
fn poll_flush(
|
||||
mut self: Pin<&mut Self>,
|
||||
context: &mut Context,
|
||||
) -> task::Poll<Result<(), Error>> {
|
||||
Pin::new(&mut self.file).poll_flush(context)
|
||||
}
|
||||
|
||||
fn poll_shutdown(
|
||||
mut self: Pin<&mut Self>,
|
||||
context: &mut Context,
|
||||
) -> task::Poll<Result<(), Error>> {
|
||||
Pin::new(&mut self.file).poll_shutdown(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum OpenMode {
|
||||
Read,
|
||||
Write,
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl Read for Inner {
|
||||
fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
|
||||
self.file.read(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Inner {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
|
||||
self.file.write(data)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), Error> {
|
||||
self.file.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl Evented for Inner {
|
||||
fn register(
|
||||
&self,
|
||||
poll: &Poll,
|
||||
token: Token,
|
||||
interest: Ready,
|
||||
opts: PollOpt,
|
||||
) -> Result<(), Error> {
|
||||
EventedFd(&self.file.as_raw_fd()).register(poll, token, interest, opts)
|
||||
}
|
||||
|
||||
fn reregister(
|
||||
&self,
|
||||
poll: &Poll,
|
||||
token: Token,
|
||||
interest: Ready,
|
||||
opts: PollOpt,
|
||||
) -> Result<(), Error> {
|
||||
EventedFd(&self.file.as_raw_fd()).reregister(poll, token, interest, opts)
|
||||
}
|
||||
|
||||
fn deregister(&self, poll: &Poll) -> Result<(), Error> {
|
||||
EventedFd(&self.file.as_raw_fd()).deregister(poll)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::setup::{self, input_event, timeval};
|
||||
use crate::glue::{self, input_event, timeval};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
|
@ -12,24 +12,24 @@ pub enum Event {
|
|||
impl Event {
|
||||
pub(crate) fn to_raw(&self) -> input_event {
|
||||
let (type_, code, value) = match *self {
|
||||
Event::MouseScroll { delta } => (setup::EV_REL as _, setup::REL_WHEEL as _, delta),
|
||||
Event::MouseScroll { delta } => (glue::EV_REL as _, glue::REL_WHEEL as _, delta),
|
||||
Event::MouseMove {
|
||||
axis: Axis::X,
|
||||
delta,
|
||||
} => (setup::EV_REL as _, setup::REL_X as _, delta),
|
||||
} => (glue::EV_REL as _, glue::REL_X as _, delta),
|
||||
Event::MouseMove {
|
||||
axis: Axis::Y,
|
||||
delta,
|
||||
} => (setup::EV_REL as _, setup::REL_Y as _, delta),
|
||||
} => (glue::EV_REL as _, glue::REL_Y as _, delta),
|
||||
Event::Key {
|
||||
direction: Direction::Up,
|
||||
code,
|
||||
} => (setup::EV_KEY as _, code, 0),
|
||||
} => (glue::EV_KEY as _, code, 0),
|
||||
Event::Key {
|
||||
direction: Direction::Down,
|
||||
code,
|
||||
} => (setup::EV_KEY as _, code, 1),
|
||||
Event::Sync => (setup::EV_SYN as _, setup::SYN_REPORT as _, 0),
|
||||
} => (glue::EV_KEY as _, code, 1),
|
||||
Event::Sync => (glue::EV_SYN as _, glue::SYN_REPORT as _, 0),
|
||||
};
|
||||
|
||||
input_event {
|
||||
|
@ -45,24 +45,24 @@ impl Event {
|
|||
|
||||
pub(crate) fn from_raw(raw: input_event) -> Option<Self> {
|
||||
let event = match (raw.type_ as _, raw.code as _, raw.value) {
|
||||
(setup::EV_REL, setup::REL_WHEEL, value) => Event::MouseScroll { delta: value },
|
||||
(setup::EV_REL, setup::REL_X, value) => Event::MouseMove {
|
||||
(glue::EV_REL, glue::REL_WHEEL, value) => Event::MouseScroll { delta: value },
|
||||
(glue::EV_REL, glue::REL_X, value) => Event::MouseMove {
|
||||
axis: Axis::X,
|
||||
delta: value,
|
||||
},
|
||||
(setup::EV_REL, setup::REL_Y, value) => Event::MouseMove {
|
||||
(glue::EV_REL, glue::REL_Y, value) => Event::MouseMove {
|
||||
axis: Axis::Y,
|
||||
delta: value,
|
||||
},
|
||||
(setup::EV_KEY, code, 0) => Event::Key {
|
||||
(glue::EV_KEY, code, 0) => Event::Key {
|
||||
direction: Direction::Up,
|
||||
code: code as _,
|
||||
},
|
||||
(setup::EV_KEY, code, 1) => Event::Key {
|
||||
(glue::EV_KEY, code, 1) => Event::Key {
|
||||
direction: Direction::Down,
|
||||
code: code as _,
|
||||
},
|
||||
(setup::EV_SYN, setup::SYN_REPORT, _) => Event::Sync,
|
||||
(glue::EV_SYN, glue::SYN_REPORT, _) => Event::Sync,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::event::Event;
|
||||
use crate::event_reader::{EventReader, OpenError};
|
||||
use crate::event_writer::EventWriter;
|
||||
use crate::setup::input_event;
|
||||
use crate::glue::input_event;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use tokio::fs;
|
||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
|
|
|
@ -1,38 +1,16 @@
|
|||
use crate::async_file::{AsyncFile, OpenMode};
|
||||
use crate::setup::{self, input_event};
|
||||
use crate::glue::input_event;
|
||||
use std::io::Error;
|
||||
use std::mem;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::Path;
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
pub(crate) struct EventReader {
|
||||
file: AsyncFile,
|
||||
}
|
||||
pub(crate) struct EventReader {}
|
||||
|
||||
impl EventReader {
|
||||
pub async fn new(path: &Path) -> Result<Self, OpenError> {
|
||||
let file = AsyncFile::open(path, OpenMode::Read)
|
||||
.await
|
||||
.map_err(OpenError::Io)?;
|
||||
if unsafe { setup::setup_read_fd(file.as_raw_fd()) == 0 } {
|
||||
let err = Error::last_os_error();
|
||||
if err.raw_os_error() == Some(libc::ENOTTY) {
|
||||
return Err(OpenError::NotSupported);
|
||||
}
|
||||
|
||||
return Err(OpenError::Io(err));
|
||||
}
|
||||
|
||||
Ok(Self { file })
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn read(&mut self) -> Result<input_event, Error> {
|
||||
let mut buffer = [0; mem::size_of::<input_event>()];
|
||||
self.file
|
||||
.read_exact(&mut buffer)
|
||||
.await
|
||||
.map(|_| unsafe { mem::transmute(buffer) })
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,44 +1,19 @@
|
|||
use crate::async_file::{AsyncFile, OpenMode};
|
||||
use crate::event::Event;
|
||||
use crate::setup::{self, input_event, timeval};
|
||||
use crate::glue::input_event;
|
||||
use std::io::Error;
|
||||
use std::mem;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
pub struct EventWriter {
|
||||
file: AsyncFile,
|
||||
}
|
||||
pub struct EventWriter {}
|
||||
|
||||
impl EventWriter {
|
||||
pub async fn new() -> Result<Self, Error> {
|
||||
let file = AsyncFile::open("/dev/uinput", OpenMode::Write).await?;
|
||||
if unsafe { setup::setup_write_fd(file.as_raw_fd()) == 0 } {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(Self { file })
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn write(&mut self, event: Event) -> Result<(), Error> {
|
||||
self.write_raw(event.to_raw()).await
|
||||
}
|
||||
|
||||
pub(crate) async fn write_raw(&mut self, mut event: input_event) -> Result<(), Error> {
|
||||
event.time = timeval {
|
||||
tv_sec: 0,
|
||||
tv_usec: 0,
|
||||
};
|
||||
|
||||
let data: [u8; mem::size_of::<input_event>()] = unsafe { mem::transmute(event) };
|
||||
self.file.write_all(&data).await
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EventWriter {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
setup::destroy_write_fd(self.file.as_raw_fd());
|
||||
}
|
||||
pub(crate) async fn write_raw(&mut self, event: input_event) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
3
input/src/glue.rs
Normal file
3
input/src/glue.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
#![allow(warnings)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/glue.rs"));
|
|
@ -1,11 +1,8 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
mod async_file;
|
||||
mod event;
|
||||
mod event_manager;
|
||||
mod event_reader;
|
||||
mod event_writer;
|
||||
mod setup;
|
||||
mod glue;
|
||||
|
||||
pub use event::{Axis, Direction, Event};
|
||||
pub use event_manager::EventManager;
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#![allow(warnings)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/setup.rs"));
|
Loading…
Add table
Reference in a new issue