Gut input crate

This commit is contained in:
htrefil 2020-10-25 18:35:50 +01:00
parent 033594e302
commit 5e2e7becb4
12 changed files with 31 additions and 272 deletions

View file

@ -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
View file

@ -0,0 +1 @@
#include <linux/input.h>

View file

@ -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;
}

View file

@ -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);

View file

@ -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)
}
}

View file

@ -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,
};

View file

@ -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};

View file

@ -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!()
}
}

View file

@ -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
View file

@ -0,0 +1,3 @@
#![allow(warnings)]
include!(concat!(env!("OUT_DIR"), "/glue.rs"));

View file

@ -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;

View file

@ -1,3 +0,0 @@
#![allow(warnings)]
include!(concat!(env!("OUT_DIR"), "/setup.rs"));