*: add docs
This commit is contained in:
parent
7d3f868cac
commit
0d4db8fe13
39
README.md
Normal file
39
README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
uinput
|
||||||
|
======
|
||||||
|
`/dev/uinput` high level wrapper.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
The following example writes `hello world`.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
extern crate uinput;
|
||||||
|
use uinput::event::keyboard;
|
||||||
|
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut device = uinput::default().unwrap()
|
||||||
|
.name("test").unwrap()
|
||||||
|
.event(uinput::event::Keyboard::All).unwrap()
|
||||||
|
.create().unwrap();
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
|
||||||
|
device.click(&keyboard::Key::H).unwrap();
|
||||||
|
device.click(&keyboard::Key::E).unwrap();
|
||||||
|
device.click(&keyboard::Key::L).unwrap();
|
||||||
|
device.click(&keyboard::Key::L).unwrap();
|
||||||
|
device.click(&keyboard::Key::O).unwrap();
|
||||||
|
device.click(&keyboard::Key::Space).unwrap();
|
||||||
|
device.click(&keyboard::Key::W).unwrap();
|
||||||
|
device.click(&keyboard::Key::O).unwrap();
|
||||||
|
device.click(&keyboard::Key::R).unwrap();
|
||||||
|
device.click(&keyboard::Key::L).unwrap();
|
||||||
|
device.click(&keyboard::Key::D).unwrap();
|
||||||
|
device.click(&keyboard::Key::Enter).unwrap();
|
||||||
|
|
||||||
|
device.synchronize().unwrap();
|
||||||
|
}
|
||||||
|
```
|
@ -11,22 +11,25 @@ use event::{self, Kind, Code};
|
|||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
use udev;
|
use udev;
|
||||||
|
|
||||||
|
/// Device builder.
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
fd: c_int,
|
fd: c_int,
|
||||||
def: uinput_user_dev,
|
def: uinput_user_dev,
|
||||||
code: c_int,
|
abs: Option<c_int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
|
/// Create a builder from the specified path.
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> Res<Self> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Res<Self> {
|
||||||
Ok(Builder {
|
Ok(Builder {
|
||||||
fd: try!(fcntl::open(path.as_ref(), fcntl::O_WRONLY | fcntl::O_NONBLOCK, stat::Mode::empty())),
|
fd: try!(fcntl::open(path.as_ref(), fcntl::O_WRONLY | fcntl::O_NONBLOCK, stat::Mode::empty())),
|
||||||
def: unsafe { mem::zeroed() },
|
def: unsafe { mem::zeroed() },
|
||||||
code: 0,
|
abs: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
|
/// Create a builder from the default path taken from udev.
|
||||||
pub fn default() -> Res<Self> {
|
pub fn default() -> Res<Self> {
|
||||||
let context = try!(udev::Context::new());
|
let context = try!(udev::Context::new());
|
||||||
let mut enumerator = try!(udev::Enumerator::new(&context));
|
let mut enumerator = try!(udev::Enumerator::new(&context));
|
||||||
@ -41,10 +44,12 @@ impl Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "udev"))]
|
#[cfg(not(feature = "udev"))]
|
||||||
|
/// Create a builder from `/dev/uinput`.
|
||||||
pub fn default() -> Res<Self> {
|
pub fn default() -> Res<Self> {
|
||||||
Builder::open("/dev/uinput")
|
Builder::open("/dev/uinput")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the name.
|
||||||
pub fn name<T: AsRef<str>>(mut self, value: T) -> Res<Self> {
|
pub fn name<T: AsRef<str>>(mut self, value: T) -> Res<Self> {
|
||||||
let string = try!(CString::new(value.as_ref()));
|
let string = try!(CString::new(value.as_ref()));
|
||||||
let bytes = string.as_bytes_with_nul();
|
let bytes = string.as_bytes_with_nul();
|
||||||
@ -59,27 +64,34 @@ impl Builder {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the bus type.
|
||||||
pub fn bus(mut self, value: u16) -> Self {
|
pub fn bus(mut self, value: u16) -> Self {
|
||||||
self.def.id.bustype = value;
|
self.def.id.bustype = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the vendor ID.
|
||||||
pub fn vendor(mut self, value: u16) -> Self {
|
pub fn vendor(mut self, value: u16) -> Self {
|
||||||
self.def.id.vendor = value;
|
self.def.id.vendor = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the product ID.
|
||||||
pub fn product(mut self, value: u16) -> Self {
|
pub fn product(mut self, value: u16) -> Self {
|
||||||
self.def.id.product = value;
|
self.def.id.product = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the version.
|
||||||
pub fn version(mut self, value: u16) -> Self {
|
pub fn version(mut self, value: u16) -> Self {
|
||||||
self.def.id.version = value;
|
self.def.id.version = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable the given event.
|
||||||
pub fn event<T: Into<Event>>(mut self, value: T) -> Res<Self> {
|
pub fn event<T: Into<Event>>(mut self, value: T) -> Res<Self> {
|
||||||
|
self.abs = None;
|
||||||
|
|
||||||
match value.into() {
|
match value.into() {
|
||||||
Event::All => {
|
Event::All => {
|
||||||
try!(self.event(Event::Keyboard(event::Keyboard::All)))
|
try!(self.event(Event::Keyboard(event::Keyboard::All)))
|
||||||
@ -211,33 +223,38 @@ impl Builder {
|
|||||||
try!(Errno::result(ui_set_absbit(self.fd, value.code())));
|
try!(Errno::result(ui_set_absbit(self.fd, value.code())));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.code = value.code();
|
self.abs = Some(value.code());
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the maximum value for the previously enabled absolute event.
|
||||||
pub fn max(mut self, value: i32) -> Self {
|
pub fn max(mut self, value: i32) -> Self {
|
||||||
self.def.absmax[self.code as usize] = value;
|
self.def.absmax[self.abs.unwrap() as usize] = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the minimum value for the previously enabled absolute event.
|
||||||
pub fn min(mut self, value: i32) -> Self {
|
pub fn min(mut self, value: i32) -> Self {
|
||||||
self.def.absmin[self.code as usize] = value;
|
self.def.absmin[self.abs.unwrap() as usize] = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the fuzz value for the previously enabled absolute event.
|
||||||
pub fn fuzz(mut self, value: i32) -> Self {
|
pub fn fuzz(mut self, value: i32) -> Self {
|
||||||
self.def.absfuzz[self.code as usize] = value;
|
self.def.absfuzz[self.abs.unwrap() as usize] = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the flat value for the previously enabled absolute event.
|
||||||
pub fn flat(mut self, value: i32) -> Self {
|
pub fn flat(mut self, value: i32) -> Self {
|
||||||
self.def.absflat[self.code as usize] = value;
|
self.def.absflat[self.abs.unwrap() as usize] = value;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create the defined device.
|
||||||
pub fn create(self) -> Res<Device> {
|
pub fn create(self) -> Res<Device> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = &self.def as *const _ as *const u8;
|
let ptr = &self.def as *const _ as *const u8;
|
||||||
|
@ -5,11 +5,13 @@ use nix::unistd;
|
|||||||
use ffi::*;
|
use ffi::*;
|
||||||
use {Result as Res, Error, Event, event};
|
use {Result as Res, Error, Event, event};
|
||||||
|
|
||||||
|
/// The virtual device.
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
fd: c_int,
|
fd: c_int,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
|
/// Wrap a file descriptor in a `Device`.
|
||||||
pub fn new(fd: c_int) -> Self {
|
pub fn new(fd: c_int) -> Self {
|
||||||
Device {
|
Device {
|
||||||
fd: fd
|
fd: fd
|
||||||
@ -36,18 +38,22 @@ impl Device {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Synchronize the device.
|
||||||
pub fn synchronize(&mut self) -> Res<()> {
|
pub fn synchronize(&mut self) -> Res<()> {
|
||||||
self.write(EV_SYN, SYN_REPORT, 0)
|
self.write(EV_SYN, SYN_REPORT, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a press event.
|
||||||
pub fn press<T: event::Press>(&mut self, event: &T) -> Res<()> {
|
pub fn press<T: event::Press>(&mut self, event: &T) -> Res<()> {
|
||||||
self.write(event.kind(), event.code(), 1)
|
self.write(event.kind(), event.code(), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a release event.
|
||||||
pub fn release<T: event::Release>(&mut self, event: &T) -> Res<()> {
|
pub fn release<T: event::Release>(&mut self, event: &T) -> Res<()> {
|
||||||
self.write(event.kind(), event.code(), 0)
|
self.write(event.kind(), event.code(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a press and release event.
|
||||||
pub fn click<T: event::Press + event::Release>(&mut self, event: &T) -> Res<()> {
|
pub fn click<T: event::Press + event::Release>(&mut self, event: &T) -> Res<()> {
|
||||||
try!(self.press(event));
|
try!(self.press(event));
|
||||||
try!(self.release(event));
|
try!(self.release(event));
|
||||||
@ -55,6 +61,7 @@ impl Device {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a relative or absolute positioning event.
|
||||||
pub fn position<T: event::Position>(&mut self, event: &T, value: i32) -> Res<()> {
|
pub fn position<T: event::Position>(&mut self, event: &T, value: i32) -> Res<()> {
|
||||||
self.write(event.kind(), event.code(), value)
|
self.write(event.kind(), event.code(), value)
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,20 @@ use nix;
|
|||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
use udev;
|
use udev;
|
||||||
|
|
||||||
|
/// UInput error.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// System errors.
|
||||||
Nix(nix::Error),
|
Nix(nix::Error),
|
||||||
|
|
||||||
|
/// Errors with internal nulls in names.
|
||||||
Nul(ffi::NulError),
|
Nul(ffi::NulError),
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
|
/// Errors coming from udev.
|
||||||
Udev(udev::Error),
|
Udev(udev::Error),
|
||||||
|
|
||||||
|
/// The uinput file could not be found.
|
||||||
NotFound,
|
NotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,24 +1,41 @@
|
|||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
|
|
||||||
|
/// Trait for event type.
|
||||||
pub trait Kind {
|
pub trait Kind {
|
||||||
|
/// Get the event type.
|
||||||
fn kind(&self) -> c_int;
|
fn kind(&self) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for event code.
|
||||||
pub trait Code {
|
pub trait Code {
|
||||||
|
/// Get the event code.
|
||||||
fn code(&self) -> c_int;
|
fn code(&self) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for events that support pressing (namely keys).
|
||||||
pub trait Press: Kind + Code { }
|
pub trait Press: Kind + Code { }
|
||||||
|
|
||||||
|
/// Trait for events that support releasing (namely keys).
|
||||||
pub trait Release: Kind + Code { }
|
pub trait Release: Kind + Code { }
|
||||||
|
|
||||||
|
/// Trait for events that support absolute or relative positioning.
|
||||||
pub trait Position: Kind + Code { }
|
pub trait Position: Kind + Code { }
|
||||||
|
|
||||||
|
/// All supported events.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
All,
|
All,
|
||||||
|
|
||||||
|
/// Keyboard event.
|
||||||
Keyboard(Keyboard),
|
Keyboard(Keyboard),
|
||||||
|
|
||||||
|
/// Controller event.
|
||||||
Controller(Controller),
|
Controller(Controller),
|
||||||
|
|
||||||
|
/// Relative movement event.
|
||||||
Relative(Relative),
|
Relative(Relative),
|
||||||
|
|
||||||
|
/// Absolute movement event.
|
||||||
Absolute(Absolute),
|
Absolute(Absolute),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,10 +29,12 @@ pub use event::Event;
|
|||||||
pub mod device;
|
pub mod device;
|
||||||
pub use device::Device;
|
pub use device::Device;
|
||||||
|
|
||||||
|
/// Open the default uinput device.
|
||||||
pub fn default() -> Result<device::Builder> {
|
pub fn default() -> Result<device::Builder> {
|
||||||
device::Builder::default()
|
device::Builder::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Open the specified uinput device.
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<device::Builder> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Result<device::Builder> {
|
||||||
device::Builder::open(path)
|
device::Builder::open(path)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user