Initial commit

This commit is contained in:
meh 2016-04-25 04:32:24 +02:00
commit 306b08dbbc
13 changed files with 2585 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
target
Cargo.lock

26
Cargo.toml Normal file
View File

@ -0,0 +1,26 @@
[package]
name = "uinput"
version = "0.1.0"
authors = ["meh. <meh@schizofreni.co>"]
license = "WTFPL"
description = "Linux uinput wrapper."
repository = "https://github.com/meh/rust-uinput"
keywords = ["linux", "input"]
[dependencies]
libc = "0.2"
nix = "0.5"
uinput-sys = "0.1"
custom_derive = "0.1"
enum_derive = "0.1"
[dependencies.libudev]
optional = true
version = "0.2"
[features]
default = ["udev"]
udev = ["libudev"]

18
examples/keyboard.rs Normal file
View File

@ -0,0 +1,18 @@
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::Key::K).unwrap()
.create().unwrap();
thread::sleep(Duration::from_secs(1));
device.press(keyboard::Key::K).unwrap();
device.release(keyboard::Key::K).unwrap();
device.synchronize().unwrap();
}

302
src/device/builder.rs Normal file
View File

@ -0,0 +1,302 @@
use std::path::Path;
use std::{mem, slice};
use std::ffi::CString;
use libc::c_int;
use nix::{self, fcntl, unistd, Errno};
use nix::sys::stat;
use ffi::*;
use {Result as Res, Error, Device, Event};
use event::{self, Kind, Code};
#[cfg(feature = "udev")]
use udev;
pub struct Builder {
fd: c_int,
def: uinput_user_dev,
code: c_int,
}
impl Builder {
pub fn open<P: AsRef<Path>>(path: P) -> Res<Self> {
Ok(Builder {
fd: try!(fcntl::open(path.as_ref(), fcntl::O_WRONLY | fcntl::O_NONBLOCK, stat::Mode::empty())),
def: unsafe { mem::zeroed() },
code: 0,
})
}
#[cfg(feature = "udev")]
pub fn default() -> Res<Self> {
let context = try!(udev::Context::new());
let mut enumerator = try!(udev::Enumerator::new(&context));
try!(enumerator.match_subsystem("misc"));
try!(enumerator.match_sysname("uinput"));
let device = try!(try!(enumerator.scan_devices())
.next().ok_or(Error::NotFound));
Builder::open(try!(device.devnode().ok_or(Error::NotFound)))
}
#[cfg(not(feature = "udev"))]
pub fn default() -> Res<Self> {
Builder::open("/dev/uinput")
}
pub fn name<T: AsRef<str>>(mut self, value: T) -> Res<Self> {
let string = try!(CString::new(value.as_ref()));
let bytes = string.as_bytes_with_nul();
if bytes.len() > UINPUT_MAX_NAME_SIZE as usize {
try!(Err(nix::Error::from_errno(nix::Errno::EINVAL)));
}
(&mut self.def.name)[..bytes.len()]
.clone_from_slice(unsafe { mem::transmute(bytes) });
Ok(self)
}
pub fn bus(mut self, value: u16) -> Self {
self.def.id.bustype = value;
self
}
pub fn vendor(mut self, value: u16) -> Self {
self.def.id.vendor = value;
self
}
pub fn product(mut self, value: u16) -> Self {
self.def.id.product = value;
self
}
pub fn version(mut self, value: u16) -> Self {
self.def.id.version = value;
self
}
pub fn event<T: Into<Event>>(mut self, value: T) -> Res<Self> {
match value.into() {
Event::All => {
try!(try!(try!(self.event(Event::Keyboard(event::Keyboard::All)))
.event(Event::Controller(event::Controller::All)))
.event(Event::Relative(event::Relative::All)))
.event(Event::Absolute(event::Absolute::All))
}
Event::Keyboard(value) => {
match value {
event::Keyboard::All => {
let mut builder = self;
for item in event::keyboard::Key::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::KeyPad::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::Misc::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::InputAssist::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::Function::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::Braille::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::Numeric::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::TouchPad::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::Camera::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::keyboard::Attendant::iter_variants() {
builder = try!(builder.event(item));
}
Ok(builder)
}
value => {
unsafe {
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
try!(Errno::result(ui_set_keybit(self.fd, value.code())));
}
Ok(self)
}
}
}
Event::Controller(value) => {
match value {
event::Controller::All => {
let mut builder = self;
for item in event::controller::Misc::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::Mouse::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::JoyStick::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::GamePad::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::Digi::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::Wheel::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::DPad::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::controller::TriggerHappy::iter_variants() {
builder = try!(builder.event(item));
}
Ok(builder)
}
value => {
unsafe {
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
try!(Errno::result(ui_set_keybit(self.fd, value.code())));
}
Ok(self)
}
}
}
Event::Relative(value) => {
match value {
event::Relative::All => {
let mut builder = self;
for item in event::relative::Position::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::relative::Wheel::iter_variants() {
builder = try!(builder.event(item));
}
Ok(builder)
}
value => {
unsafe {
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
try!(Errno::result(ui_set_relbit(self.fd, value.code())));
}
Ok(self)
}
}
}
Event::Absolute(value) => {
match value {
event::Absolute::All => {
let mut builder = self;
for item in event::absolute::Position::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::absolute::Wheel::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::absolute::Hat::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::absolute::Digi::iter_variants() {
builder = try!(builder.event(item));
}
for item in event::absolute::Multi::iter_variants() {
builder = try!(builder.event(item));
}
Ok(builder)
}
value => {
unsafe {
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
try!(Errno::result(ui_set_absbit(self.fd, value.code())));
}
self.code = value.code();
Ok(self)
}
}
}
}
}
pub fn max(mut self, value: i32) -> Self {
self.def.absmax[self.code as usize] = value;
self
}
pub fn min(mut self, value: i32) -> Self {
self.def.absmin[self.code as usize] = value;
self
}
pub fn fuzz(mut self, value: i32) -> Self {
self.def.absfuzz[self.code as usize] = value;
self
}
pub fn flat(mut self, value: i32) -> Self {
self.def.absflat[self.code as usize] = value;
self
}
pub fn create(self) -> Res<Device> {
unsafe {
let ptr = &self.def as *const _ as *const u8;
let size = mem::size_of_val(&self.def);
try!(unistd::write(self.fd, slice::from_raw_parts(ptr, size)));
try!(Errno::result(ui_dev_create(self.fd)));
}
Ok(Device::new(self.fd))
}
}

62
src/device/device.rs Normal file
View File

@ -0,0 +1,62 @@
use std::{mem, ptr, slice};
use libc::c_int;
use libc::{timeval, gettimeofday};
use nix::unistd;
use ffi::*;
use {Result as Res, Error, Event, event};
pub struct Device {
fd: c_int,
}
impl Device {
pub fn new(fd: c_int) -> Self {
Device {
fd: fd
}
}
fn write(&mut self, kind: c_int, code: c_int, value: c_int) -> Res<()> {
unsafe {
let mut event = input_event {
time: timeval { tv_sec: 0, tv_usec: 0 },
kind: kind as u16,
code: code as u16,
value: value as i32,
};
gettimeofday(&mut event.time, ptr::null_mut());
let ptr = &event as *const _ as *const u8;
let size = mem::size_of_val(&event);
try!(unistd::write(self.fd, slice::from_raw_parts(ptr, size)));
}
Ok(())
}
pub fn synchronize(&mut self) -> Res<()> {
self.write(EV_SYN, SYN_REPORT, 0)
}
pub fn press<T: event::Press>(&mut self, event: T) -> Res<()> {
self.write(event.kind(), event.code(), 1)
}
pub fn release<T: event::Release>(&mut self, event: T) -> Res<()> {
self.write(event.kind(), event.code(), 0)
}
pub fn position<T: event::Position>(&mut self, event: T, value: i32) -> Res<()> {
self.write(event.kind(), event.code(), value)
}
}
impl Drop for Device {
fn drop(&mut self) {
unsafe {
ui_dev_destroy(self.fd);
}
}
}

14
src/device/mod.rs Normal file
View File

@ -0,0 +1,14 @@
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
pub struct Id {
pub bus: u16,
pub vendor: u16,
pub product: u16,
pub version: u16,
}
mod builder;
pub use self::builder::Builder;
mod device;
pub use self::device::Device;

35
src/error.rs Normal file
View File

@ -0,0 +1,35 @@
use std::ffi;
use nix;
#[cfg(feature = "udev")]
use udev;
#[derive(Debug)]
pub enum Error {
Nix(nix::Error),
Nul(ffi::NulError),
#[cfg(feature = "udev")]
Udev(udev::Error),
NotFound,
}
impl From<ffi::NulError> for Error {
fn from(value: ffi::NulError) -> Self {
Error::Nul(value)
}
}
impl From<nix::Error> for Error {
fn from(value: nix::Error) -> Self {
Error::Nix(value)
}
}
#[cfg(feature = "udev")]
impl From<udev::Error> for Error {
fn from(value: udev::Error) -> Self {
Error::Udev(value)
}
}

258
src/event/absolute.rs Normal file
View File

@ -0,0 +1,258 @@
use libc::c_int;
use ffi::*;
use {Event};
use super::{Kind, Code};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Absolute {
All,
Position(Position),
Wheel(Wheel),
Hat(Hat),
Digi(Digi),
Multi(Multi),
}
impl Into<Event> for Absolute {
fn into(self) -> Event {
Event::Absolute(self)
}
}
impl super::Position for Absolute { }
impl Kind for Absolute {
fn kind(&self) -> c_int {
EV_ABS
}
}
impl Code for Absolute {
fn code(&self) -> c_int {
match self {
&Absolute::All => unreachable!(),
&Absolute::Position(ref v) => v.code(),
&Absolute::Wheel(ref v) => v.code(),
&Absolute::Hat(ref v) => v.code(),
&Absolute::Digi(ref v) => v.code(),
&Absolute::Multi(ref v) => v.code(),
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(PositionVariants))]
pub enum Position {
X,
Y,
Z,
RX,
RY,
RZ,
}
}
impl Into<Event> for Position {
fn into(self) -> Event {
Event::Absolute(Absolute::Position(self))
}
}
impl super::Position for Position { }
impl Kind for Position {
fn kind(&self) -> c_int {
EV_ABS
}
}
impl Code for Position {
fn code(&self) -> c_int {
match self {
&Position::X => ABS_X,
&Position::Y => ABS_Y,
&Position::Z => ABS_Z,
&Position::RX => ABS_RX,
&Position::RY => ABS_RY,
&Position::RZ => ABS_RZ,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(WheelVariants))]
pub enum Wheel {
Throttle,
Rudder,
Position,
Gas,
Brake,
}
}
impl Into<Event> for Wheel {
fn into(self) -> Event {
Event::Absolute(Absolute::Wheel(self))
}
}
impl super::Position for Wheel { }
impl Kind for Wheel {
fn kind(&self) -> c_int {
EV_ABS
}
}
impl Code for Wheel {
fn code(&self) -> c_int {
match self {
&Wheel::Throttle => ABS_THROTTLE,
&Wheel::Rudder => ABS_RUDDER,
&Wheel::Position => ABS_WHEEL,
&Wheel::Gas => ABS_GAS,
&Wheel::Brake => ABS_BRAKE,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(HatVariants))]
pub enum Hat {
X0,
Y0,
X1,
Y1,
X2,
Y2,
X3,
Y3,
}
}
impl Into<Event> for Hat {
fn into(self) -> Event {
Event::Absolute(Absolute::Hat(self))
}
}
impl super::Position for Hat { }
impl Kind for Hat {
fn kind(&self) -> c_int {
EV_ABS
}
}
impl Code for Hat {
fn code(&self) -> c_int {
match self {
&Hat::X0 => ABS_HAT0X,
&Hat::Y0 => ABS_HAT0Y,
&Hat::X1 => ABS_HAT1X,
&Hat::Y1 => ABS_HAT1Y,
&Hat::X2 => ABS_HAT2X,
&Hat::Y2 => ABS_HAT2Y,
&Hat::X3 => ABS_HAT3X,
&Hat::Y3 => ABS_HAT3Y,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(DigiVariants))]
pub enum Digi {
Pressure,
Distance,
TiltX,
TiltY,
ToolWidth,
Volume,
}
}
impl Into<Event> for Digi {
fn into(self) -> Event {
Event::Absolute(Absolute::Digi(self))
}
}
impl super::Position for Digi { }
impl Kind for Digi {
fn kind(&self) -> c_int {
EV_ABS
}
}
impl Code for Digi {
fn code(&self) -> c_int {
match self {
&Digi::Pressure => ABS_PRESSURE,
&Digi::Distance => ABS_DISTANCE,
&Digi::TiltX => ABS_TILT_X,
&Digi::TiltY => ABS_TILT_Y,
&Digi::ToolWidth => ABS_TOOL_WIDTH,
&Digi::Volume => ABS_VOLUME,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(MultiVariants))]
pub enum Multi {
Slot,
TouchMajor,
TouchMinor,
WidthMajor,
WidthMinor,
Orientation,
PositionX,
PositionY,
ToolType,
BlobId,
TrackingId,
Pressure,
Distance,
ToolX,
ToolY,
}
}
impl Into<Event> for Multi {
fn into(self) -> Event {
Event::Absolute(Absolute::Multi(self))
}
}
impl super::Position for Multi { }
impl Kind for Multi {
fn kind(&self) -> c_int {
EV_ABS
}
}
impl Code for Multi {
fn code(&self) -> c_int {
match self {
&Multi::Slot => ABS_MT_SLOT,
&Multi::TouchMajor => ABS_MT_TOUCH_MAJOR,
&Multi::TouchMinor => ABS_MT_TOUCH_MINOR,
&Multi::WidthMajor => ABS_MT_WIDTH_MAJOR,
&Multi::WidthMinor => ABS_MT_WIDTH_MINOR,
&Multi::Orientation => ABS_MT_ORIENTATION,
&Multi::PositionX => ABS_MT_POSITION_X,
&Multi::PositionY => ABS_MT_POSITION_Y,
&Multi::ToolType => ABS_MT_TOOL_TYPE,
&Multi::BlobId => ABS_MT_BLOB_ID,
&Multi::TrackingId => ABS_MT_TRACKING_ID,
&Multi::Pressure => ABS_MT_PRESSURE,
&Multi::Distance => ABS_MT_DISTANCE,
&Multi::ToolX => ABS_MT_TOOL_X,
&Multi::ToolY => ABS_MT_TOOL_Y,
}
}
}

483
src/event/controller.rs Normal file
View File

@ -0,0 +1,483 @@
use libc::c_int;
use ffi::*;
use {Event};
use super::{Kind, Code, Press, Release};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Controller {
All,
Misc(Misc),
Mouse(Mouse),
JoyStick(JoyStick),
GamePad(GamePad),
Digi(Digi),
Wheel(Wheel),
DPad(DPad),
TriggerHappy(TriggerHappy),
}
impl Into<Event> for Controller {
fn into(self) -> Event {
Event::Controller(self)
}
}
impl Press for Controller { }
impl Release for Controller { }
impl Kind for Controller {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for Controller {
fn code(&self) -> c_int {
match self {
&Controller::All => unreachable!(),
&Controller::Misc(ref v) => v.code(),
&Controller::Mouse(ref v) => v.code(),
&Controller::JoyStick(ref v) => v.code(),
&Controller::GamePad(ref v) => v.code(),
&Controller::Digi(ref v) => v.code(),
&Controller::Wheel(ref v) => v.code(),
&Controller::DPad(ref v) => v.code(),
&Controller::TriggerHappy(ref v) => v.code(),
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(MiscVariants))]
pub enum Misc {
_0,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
}
}
impl Into<Event> for Misc {
fn into(self) -> Event {
Event::Controller(Controller::Misc(self))
}
}
impl Kind for Misc {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for Misc {
fn code(&self) -> c_int {
match self {
&Misc::_0 => BTN_0,
&Misc::_1 => BTN_1,
&Misc::_2 => BTN_2,
&Misc::_3 => BTN_3,
&Misc::_4 => BTN_4,
&Misc::_5 => BTN_5,
&Misc::_6 => BTN_6,
&Misc::_7 => BTN_7,
&Misc::_8 => BTN_8,
&Misc::_9 => BTN_9,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(MouseVariants))]
pub enum Mouse {
Left,
Right,
Middle,
Side,
Extra,
Forward,
Back,
Task,
}
}
impl Into<Event> for Mouse {
fn into(self) -> Event {
Event::Controller(Controller::Mouse(self))
}
}
impl Code for Mouse {
fn code(&self) -> c_int {
match self {
&Mouse::Left => BTN_LEFT,
&Mouse::Right => BTN_RIGHT,
&Mouse::Middle => BTN_MIDDLE,
&Mouse::Side => BTN_SIDE,
&Mouse::Extra => BTN_EXTRA,
&Mouse::Forward => BTN_FORWARD,
&Mouse::Back => BTN_BACK,
&Mouse::Task => BTN_TASK,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(JoyStickVariants))]
pub enum JoyStick {
Trigger,
Thumb,
Thumb2,
Top,
Top2,
Pinkie,
Base,
Base2,
Base3,
Base4,
Base5,
Base6,
Dead,
}
}
impl Into<Event> for JoyStick {
fn into(self) -> Event {
Event::Controller(Controller::JoyStick(self))
}
}
impl Press for JoyStick { }
impl Release for JoyStick { }
impl Kind for JoyStick {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for JoyStick {
fn code(&self) -> c_int {
match self {
&JoyStick::Trigger => BTN_TRIGGER,
&JoyStick::Thumb => BTN_THUMB,
&JoyStick::Thumb2 => BTN_THUMB2,
&JoyStick::Top => BTN_TOP,
&JoyStick::Top2 => BTN_TOP2,
&JoyStick::Pinkie => BTN_PINKIE,
&JoyStick::Base => BTN_BASE,
&JoyStick::Base2 => BTN_BASE2,
&JoyStick::Base3 => BTN_BASE3,
&JoyStick::Base4 => BTN_BASE4,
&JoyStick::Base5 => BTN_BASE5,
&JoyStick::Base6 => BTN_BASE6,
&JoyStick::Dead => BTN_DEAD,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(GamePadVariants))]
pub enum GamePad {
South,
A,
East,
B,
C,
North,
X,
West,
Y,
Z,
TL,
TR,
TL2,
TR2,
Select,
Start,
Mode,
ThumbL,
ThumbR,
}
}
impl Into<Event> for GamePad {
fn into(self) -> Event {
Event::Controller(Controller::GamePad(self))
}
}
impl Press for GamePad { }
impl Release for GamePad { }
impl Kind for GamePad {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for GamePad {
fn code(&self) -> c_int {
match self {
&GamePad::South => BTN_SOUTH,
&GamePad::A => BTN_A,
&GamePad::East => BTN_EAST,
&GamePad::B => BTN_B,
&GamePad::C => BTN_C,
&GamePad::North => BTN_NORTH,
&GamePad::X => BTN_X,
&GamePad::West => BTN_WEST,
&GamePad::Y => BTN_Y,
&GamePad::Z => BTN_Z,
&GamePad::TL => BTN_TL,
&GamePad::TR => BTN_TR,
&GamePad::TL2 => BTN_TL2,
&GamePad::TR2 => BTN_TR2,
&GamePad::Select => BTN_SELECT,
&GamePad::Start => BTN_START,
&GamePad::Mode => BTN_MODE,
&GamePad::ThumbL => BTN_THUMBL,
&GamePad::ThumbR => BTN_THUMBR,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(DigiVariants))]
pub enum Digi {
Pen,
Rubber,
Brush,
Pencil,
AirBrush,
Finger,
Mouse,
Lens,
QuintTap,
Touch,
Stylus,
Stylus2,
DoubleTap,
TripleTap,
QuadTap,
}
}
impl Into<Event> for Digi {
fn into(self) -> Event {
Event::Controller(Controller::Digi(self))
}
}
impl Press for Digi { }
impl Release for Digi { }
impl Kind for Digi {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for Digi {
fn code(&self) -> c_int {
match self {
&Digi::Pen => BTN_TOOL_PEN,
&Digi::Rubber => BTN_TOOL_RUBBER,
&Digi::Brush => BTN_TOOL_BRUSH,
&Digi::Pencil => BTN_TOOL_PENCIL,
&Digi::AirBrush => BTN_TOOL_AIRBRUSH,
&Digi::Finger => BTN_TOOL_FINGER,
&Digi::Mouse => BTN_TOOL_MOUSE,
&Digi::Lens => BTN_TOOL_LENS,
&Digi::QuintTap => BTN_TOOL_QUINTTAP,
&Digi::Touch => BTN_TOUCH,
&Digi::Stylus => BTN_STYLUS,
&Digi::Stylus2 => BTN_STYLUS2,
&Digi::DoubleTap => BTN_TOOL_DOUBLETAP,
&Digi::TripleTap => BTN_TOOL_TRIPLETAP,
&Digi::QuadTap => BTN_TOOL_QUADTAP,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(WheelVariants))]
pub enum Wheel {
GearDown,
GearUp,
}
}
impl Into<Event> for Wheel {
fn into(self) -> Event {
Event::Controller(Controller::Wheel(self))
}
}
impl Press for Wheel { }
impl Release for Wheel { }
impl Kind for Wheel {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for Wheel {
fn code(&self) -> c_int {
match self {
&Wheel::GearDown => BTN_GEAR_DOWN,
&Wheel::GearUp => BTN_GEAR_UP,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(DPadVariants))]
pub enum DPad {
Up,
Down,
Left,
Right,
}
}
impl Into<Event> for DPad {
fn into(self) -> Event {
Event::Controller(Controller::DPad(self))
}
}
impl Press for DPad { }
impl Release for DPad { }
impl Kind for DPad {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for DPad {
fn code(&self) -> c_int {
match self {
&DPad::Up => BTN_DPAD_UP,
&DPad::Down => BTN_DPAD_DOWN,
&DPad::Left => BTN_DPAD_LEFT,
&DPad::Right => BTN_DPAD_RIGHT,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(TriggerHappyVariants))]
pub enum TriggerHappy {
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
_10,
_11,
_12,
_13,
_14,
_15,
_16,
_17,
_18,
_19,
_20,
_21,
_22,
_23,
_24,
_25,
_26,
_27,
_28,
_29,
_30,
_31,
_32,
_33,
_34,
_35,
_36,
_37,
_38,
_39,
_40,
}
}
impl Into<Event> for TriggerHappy {
fn into(self) -> Event {
Event::Controller(Controller::TriggerHappy(self))
}
}
impl Press for TriggerHappy { }
impl Release for TriggerHappy { }
impl Kind for TriggerHappy {
fn kind(&self) -> c_int {
EV_KEY
}
}
impl Code for TriggerHappy {
fn code(&self) -> c_int {
match self {
&TriggerHappy::_1 => BTN_TRIGGER_HAPPY1,
&TriggerHappy::_2 => BTN_TRIGGER_HAPPY2,
&TriggerHappy::_3 => BTN_TRIGGER_HAPPY3,
&TriggerHappy::_4 => BTN_TRIGGER_HAPPY4,
&TriggerHappy::_5 => BTN_TRIGGER_HAPPY5,
&TriggerHappy::_6 => BTN_TRIGGER_HAPPY6,
&TriggerHappy::_7 => BTN_TRIGGER_HAPPY7,
&TriggerHappy::_8 => BTN_TRIGGER_HAPPY8,
&TriggerHappy::_9 => BTN_TRIGGER_HAPPY9,
&TriggerHappy::_10 => BTN_TRIGGER_HAPPY10,
&TriggerHappy::_11 => BTN_TRIGGER_HAPPY11,
&TriggerHappy::_12 => BTN_TRIGGER_HAPPY12,
&TriggerHappy::_13 => BTN_TRIGGER_HAPPY13,
&TriggerHappy::_14 => BTN_TRIGGER_HAPPY14,
&TriggerHappy::_15 => BTN_TRIGGER_HAPPY15,
&TriggerHappy::_16 => BTN_TRIGGER_HAPPY16,
&TriggerHappy::_17 => BTN_TRIGGER_HAPPY17,
&TriggerHappy::_18 => BTN_TRIGGER_HAPPY18,
&TriggerHappy::_19 => BTN_TRIGGER_HAPPY19,
&TriggerHappy::_20 => BTN_TRIGGER_HAPPY20,
&TriggerHappy::_21 => BTN_TRIGGER_HAPPY21,
&TriggerHappy::_22 => BTN_TRIGGER_HAPPY22,
&TriggerHappy::_23 => BTN_TRIGGER_HAPPY23,
&TriggerHappy::_24 => BTN_TRIGGER_HAPPY24,
&TriggerHappy::_25 => BTN_TRIGGER_HAPPY25,
&TriggerHappy::_26 => BTN_TRIGGER_HAPPY26,
&TriggerHappy::_27 => BTN_TRIGGER_HAPPY27,
&TriggerHappy::_28 => BTN_TRIGGER_HAPPY28,
&TriggerHappy::_29 => BTN_TRIGGER_HAPPY29,
&TriggerHappy::_30 => BTN_TRIGGER_HAPPY30,
&TriggerHappy::_31 => BTN_TRIGGER_HAPPY31,
&TriggerHappy::_32 => BTN_TRIGGER_HAPPY32,
&TriggerHappy::_33 => BTN_TRIGGER_HAPPY33,
&TriggerHappy::_34 => BTN_TRIGGER_HAPPY34,
&TriggerHappy::_35 => BTN_TRIGGER_HAPPY35,
&TriggerHappy::_36 => BTN_TRIGGER_HAPPY36,
&TriggerHappy::_37 => BTN_TRIGGER_HAPPY37,
&TriggerHappy::_38 => BTN_TRIGGER_HAPPY38,
&TriggerHappy::_39 => BTN_TRIGGER_HAPPY39,
&TriggerHappy::_40 => BTN_TRIGGER_HAPPY40,
}
}
}

1177
src/event/keyboard.rs Normal file

File diff suppressed because it is too large Load Diff

61
src/event/mod.rs Normal file
View File

@ -0,0 +1,61 @@
use libc::c_int;
pub trait Kind {
fn kind(&self) -> c_int;
}
pub trait Code {
fn code(&self) -> c_int;
}
pub trait Press: Kind + Code { }
pub trait Release: Kind + Code { }
pub trait Position: Kind + Code { }
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Event {
All,
Keyboard(Keyboard),
Controller(Controller),
Relative(Relative),
Absolute(Absolute),
}
impl Kind for Event {
fn kind(&self) -> c_int {
match self {
&Event::All => unreachable!(),
&Event::Keyboard(ref v) => v.kind(),
&Event::Controller(ref v) => v.kind(),
&Event::Relative(ref v) => v.kind(),
&Event::Absolute(ref v) => v.kind(),
}
}
}
impl Code for Event {
fn code(&self) -> c_int {
match self {
&Event::All => unreachable!(),
&Event::Keyboard(ref v) => v.code(),
&Event::Controller(ref v) => v.code(),
&Event::Relative(ref v) => v.code(),
&Event::Absolute(ref v) => v.code(),
}
}
}
pub mod keyboard;
pub use self::keyboard::Keyboard;
pub mod controller;
pub use self::controller::Controller;
pub mod relative;
pub use self::relative::Relative;
pub mod absolute;
pub use self::absolute::Absolute;

109
src/event/relative.rs Normal file
View File

@ -0,0 +1,109 @@
use libc::c_int;
use ffi::*;
use {Event};
use super::{Kind, Code};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Relative {
All,
Position(Position),
Wheel(Wheel),
}
impl Into<Event> for Relative {
fn into(self) -> Event {
Event::Relative(self)
}
}
impl super::Position for Relative { }
impl Kind for Relative {
fn kind(&self) -> c_int {
EV_REL
}
}
impl Code for Relative {
fn code(&self) -> c_int {
match self {
&Relative::All => unreachable!(),
&Relative::Position(ref v) => v.code(),
&Relative::Wheel(ref v) => v.code(),
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(PositionVariants))]
pub enum Position {
X,
Y,
Z,
RX,
RY,
RZ,
}
}
impl Into<Event> for Position {
fn into(self) -> Event {
Event::Relative(Relative::Position(self))
}
}
impl super::Position for Position { }
impl Kind for Position {
fn kind(&self) -> c_int {
EV_REL
}
}
impl Code for Position {
fn code(&self) -> c_int {
match self {
&Position::X => REL_X,
&Position::Y => REL_Y,
&Position::Z => REL_Z,
&Position::RX => REL_RX,
&Position::RY => REL_RY,
&Position::RZ => REL_RZ,
}
}
}
custom_derive! {
#[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(WheelVariants))]
pub enum Wheel {
Horizontal,
Dial,
Vertical,
}
}
impl Into<Event> for Wheel {
fn into(self) -> Event {
Event::Relative(Relative::Wheel(self))
}
}
impl super::Position for Wheel { }
impl Kind for Wheel {
fn kind(&self) -> c_int {
EV_REL
}
}
impl Code for Wheel {
fn code(&self) -> c_int {
match self {
&Wheel::Horizontal => REL_HWHEEL,
&Wheel::Dial => REL_DIAL,
&Wheel::Vertical => REL_WHEEL,
}
}
}

38
src/lib.rs Normal file
View File

@ -0,0 +1,38 @@
#![recursion_limit = "1000"]
extern crate libc;
extern crate uinput_sys as ffi;
#[macro_use]
extern crate nix;
#[macro_use]
extern crate custom_derive;
#[macro_use]
extern crate enum_derive;
#[cfg(feature = "udev")]
extern crate libudev as udev;
use std::path::Path;
mod error;
pub use error::Error;
pub type Result<T> = ::std::result::Result<T, Error>;
pub mod event;
pub use event::Event;
pub mod device;
pub use device::Device;
pub fn default() -> Result<device::Builder> {
device::Builder::default()
}
pub fn open<P: AsRef<Path>>(path: P) -> Result<device::Builder> {
device::Builder::open(path)
}