From 0d4db8fe13fa738d65dc652c2658546b80178e31 Mon Sep 17 00:00:00 2001 From: meh Date: Mon, 25 Apr 2016 17:57:45 +0200 Subject: [PATCH] *: add docs --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ src/device/builder.rs | 39 ++++++++++++++++++++++++++++----------- src/device/device.rs | 7 +++++++ src/error.rs | 6 ++++++ src/event/mod.rs | 17 +++++++++++++++++ src/lib.rs | 2 ++ 6 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..70f3184 --- /dev/null +++ b/README.md @@ -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(); +} +``` diff --git a/src/device/builder.rs b/src/device/builder.rs index c83ffa0..8c885f1 100644 --- a/src/device/builder.rs +++ b/src/device/builder.rs @@ -11,22 +11,25 @@ use event::{self, Kind, Code}; #[cfg(feature = "udev")] use udev; +/// Device builder. pub struct Builder { - fd: c_int, - def: uinput_user_dev, - code: c_int, + fd: c_int, + def: uinput_user_dev, + abs: Option, } impl Builder { + /// Create a builder from the specified path. pub fn open>(path: P) -> Res { Ok(Builder { - fd: try!(fcntl::open(path.as_ref(), fcntl::O_WRONLY | fcntl::O_NONBLOCK, stat::Mode::empty())), - def: unsafe { mem::zeroed() }, - code: 0, + fd: try!(fcntl::open(path.as_ref(), fcntl::O_WRONLY | fcntl::O_NONBLOCK, stat::Mode::empty())), + def: unsafe { mem::zeroed() }, + abs: None, }) } #[cfg(feature = "udev")] + /// Create a builder from the default path taken from udev. pub fn default() -> Res { let context = try!(udev::Context::new()); let mut enumerator = try!(udev::Enumerator::new(&context)); @@ -41,10 +44,12 @@ impl Builder { } #[cfg(not(feature = "udev"))] + /// Create a builder from `/dev/uinput`. pub fn default() -> Res { Builder::open("/dev/uinput") } + /// Set the name. pub fn name>(mut self, value: T) -> Res { let string = try!(CString::new(value.as_ref())); let bytes = string.as_bytes_with_nul(); @@ -59,27 +64,34 @@ impl Builder { Ok(self) } + /// Set the bus type. pub fn bus(mut self, value: u16) -> Self { self.def.id.bustype = value; self } + /// Set the vendor ID. pub fn vendor(mut self, value: u16) -> Self { self.def.id.vendor = value; self } + /// Set the product ID. pub fn product(mut self, value: u16) -> Self { self.def.id.product = value; self } + /// Set the version. pub fn version(mut self, value: u16) -> Self { self.def.id.version = value; self } + /// Enable the given event. pub fn event>(mut self, value: T) -> Res { + self.abs = None; + match value.into() { Event::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()))); } - self.code = value.code(); + self.abs = Some(value.code()); Ok(self) } } } + /// Set the maximum value for the previously enabled absolute event. 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 } + /// Set the minimum value for the previously enabled absolute event. 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 } + /// Set the fuzz value for the previously enabled absolute event. 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 } + /// Set the flat value for the previously enabled absolute event. 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 } + /// Create the defined device. pub fn create(self) -> Res { unsafe { let ptr = &self.def as *const _ as *const u8; diff --git a/src/device/device.rs b/src/device/device.rs index 0ae33bd..f7862fe 100644 --- a/src/device/device.rs +++ b/src/device/device.rs @@ -5,11 +5,13 @@ use nix::unistd; use ffi::*; use {Result as Res, Error, Event, event}; +/// The virtual device. pub struct Device { fd: c_int, } impl Device { + /// Wrap a file descriptor in a `Device`. pub fn new(fd: c_int) -> Self { Device { fd: fd @@ -36,18 +38,22 @@ impl Device { Ok(()) } + /// Synchronize the device. pub fn synchronize(&mut self) -> Res<()> { self.write(EV_SYN, SYN_REPORT, 0) } + /// Send a press event. pub fn press(&mut self, event: &T) -> Res<()> { self.write(event.kind(), event.code(), 1) } + /// Send a release event. pub fn release(&mut self, event: &T) -> Res<()> { self.write(event.kind(), event.code(), 0) } + /// Send a press and release event. pub fn click(&mut self, event: &T) -> Res<()> { try!(self.press(event)); try!(self.release(event)); @@ -55,6 +61,7 @@ impl Device { Ok(()) } + /// Send a relative or absolute positioning event. pub fn position(&mut self, event: &T, value: i32) -> Res<()> { self.write(event.kind(), event.code(), value) } diff --git a/src/error.rs b/src/error.rs index da17868..09d5eae 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,14 +4,20 @@ use nix; #[cfg(feature = "udev")] use udev; +/// UInput error. #[derive(Debug)] pub enum Error { + /// System errors. Nix(nix::Error), + + /// Errors with internal nulls in names. Nul(ffi::NulError), #[cfg(feature = "udev")] + /// Errors coming from udev. Udev(udev::Error), + /// The uinput file could not be found. NotFound, } diff --git a/src/event/mod.rs b/src/event/mod.rs index d7d604b..3731942 100644 --- a/src/event/mod.rs +++ b/src/event/mod.rs @@ -1,24 +1,41 @@ use libc::c_int; +/// Trait for event type. pub trait Kind { + /// Get the event type. fn kind(&self) -> c_int; } +/// Trait for event code. pub trait Code { + /// Get the event code. fn code(&self) -> c_int; } +/// Trait for events that support pressing (namely keys). pub trait Press: Kind + Code { } + +/// Trait for events that support releasing (namely keys). pub trait Release: Kind + Code { } + +/// Trait for events that support absolute or relative positioning. pub trait Position: Kind + Code { } +/// All supported events. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Event { All, + /// Keyboard event. Keyboard(Keyboard), + + /// Controller event. Controller(Controller), + + /// Relative movement event. Relative(Relative), + + /// Absolute movement event. Absolute(Absolute), } diff --git a/src/lib.rs b/src/lib.rs index c9beeb0..5200fe9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,10 +29,12 @@ pub use event::Event; pub mod device; pub use device::Device; +/// Open the default uinput device. pub fn default() -> Result { device::Builder::default() } +/// Open the specified uinput device. pub fn open>(path: P) -> Result { device::Builder::open(path) }