commit 306b08dbbc1c4e0a49796dcc2877f7e37691cc73 Author: meh Date: Mon Apr 25 04:32:24 2016 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9fa5385 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "uinput" +version = "0.1.0" + +authors = ["meh. "] +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"] diff --git a/examples/keyboard.rs b/examples/keyboard.rs new file mode 100644 index 0000000..cd2082f --- /dev/null +++ b/examples/keyboard.rs @@ -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(); +} diff --git a/src/device/builder.rs b/src/device/builder.rs new file mode 100644 index 0000000..3e3b04e --- /dev/null +++ b/src/device/builder.rs @@ -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>(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, + }) + } + + #[cfg(feature = "udev")] + pub fn default() -> Res { + 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 { + Builder::open("/dev/uinput") + } + + pub fn name>(mut self, value: T) -> Res { + 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>(mut self, value: T) -> Res { + 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 { + 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)) + } +} diff --git a/src/device/device.rs b/src/device/device.rs new file mode 100644 index 0000000..5f2519b --- /dev/null +++ b/src/device/device.rs @@ -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(&mut self, event: T) -> Res<()> { + self.write(event.kind(), event.code(), 1) + } + + pub fn release(&mut self, event: T) -> Res<()> { + self.write(event.kind(), event.code(), 0) + } + + pub fn 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); + } + } +} diff --git a/src/device/mod.rs b/src/device/mod.rs new file mode 100644 index 0000000..c128458 --- /dev/null +++ b/src/device/mod.rs @@ -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; + diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..da17868 --- /dev/null +++ b/src/error.rs @@ -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 for Error { + fn from(value: ffi::NulError) -> Self { + Error::Nul(value) + } +} + +impl From for Error { + fn from(value: nix::Error) -> Self { + Error::Nix(value) + } +} + +#[cfg(feature = "udev")] +impl From for Error { + fn from(value: udev::Error) -> Self { + Error::Udev(value) + } +} diff --git a/src/event/absolute.rs b/src/event/absolute.rs new file mode 100644 index 0000000..46b3c23 --- /dev/null +++ b/src/event/absolute.rs @@ -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 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 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 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 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 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 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, + } + } +} diff --git a/src/event/controller.rs b/src/event/controller.rs new file mode 100644 index 0000000..f868177 --- /dev/null +++ b/src/event/controller.rs @@ -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 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 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 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 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 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 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 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 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 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, + } + } +} diff --git a/src/event/keyboard.rs b/src/event/keyboard.rs new file mode 100644 index 0000000..63c9dec --- /dev/null +++ b/src/event/keyboard.rs @@ -0,0 +1,1177 @@ +use libc::c_int; +use ffi::*; +use {Event}; +use super::{Kind, Code, Press, Release}; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Keyboard { + All, + Key(Key), + KeyPad(KeyPad), + Misc(Misc), + InputAssist(InputAssist), + Function(Function), + Braille(Braille), + Numeric(Numeric), + TouchPad(TouchPad), + Camera(Camera), + Attendant(Attendant), +} + +impl Into for Keyboard { + fn into(self) -> Event { + Event::Keyboard(self) + } +} + +impl Press for Keyboard { } +impl Release for Keyboard { } + +impl Kind for Keyboard { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Keyboard { + fn code(&self) -> c_int { + match self { + &Keyboard::All => unreachable!(), + + &Keyboard::Key(ref v) => v.code(), + &Keyboard::KeyPad(ref v) => v.code(), + &Keyboard::Misc(ref v) => v.code(), + &Keyboard::InputAssist(ref v) => v.code(), + &Keyboard::Function(ref v) => v.code(), + &Keyboard::Braille(ref v) => v.code(), + &Keyboard::Numeric(ref v) => v.code(), + &Keyboard::TouchPad(ref v) => v.code(), + &Keyboard::Camera(ref v) => v.code(), + &Keyboard::Attendant(ref v) => v.code(), + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(KeyVariants))] + pub enum Key { + Reserved, + Esc, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + _0, + Minus, + Equal, + Backspace, + Tab, + Q, + W, + E, + R, + T, + Y, + U, + I, + O, + P, + LeftBrace, + RightBrace, + Enter, + LeftControl, + A, + S, + D, + F, + G, + H, + J, + K, + L, + SemiColon, + Apostrophe, + Grave, + LeftShift, + BackSlash, + Z, + X, + C, + V, + B, + N, + M, + Comma, + Dot, + Slash, + RightShift, + LeftAlt, + Space, + CapsLock, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + NumLock, + ScrollLock, + F11, + F12, + RightControl, + SysRq, + RightAlt, + LineFeed, + Home, + Up, + PageUp, + Left, + Right, + End, + Down, + PageDown, + Insert, + Delete, + LeftMeta, + RightMeta, + ScrollUp, + ScrollDown, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + } +} + +impl Into for Key { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Key(self)) + } +} + +impl Press for Key { } +impl Release for Key { } + +impl Kind for Key { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Key { + fn code(&self) -> c_int { + match self { + &Key::Reserved => KEY_RESERVED, + &Key::Esc => KEY_ESC, + &Key::_1 => KEY_1, + &Key::_2 => KEY_2, + &Key::_3 => KEY_3, + &Key::_4 => KEY_4, + &Key::_5 => KEY_5, + &Key::_6 => KEY_6, + &Key::_7 => KEY_7, + &Key::_8 => KEY_8, + &Key::_9 => KEY_9, + &Key::_0 => KEY_10, + &Key::Minus => KEY_MINUS, + &Key::Equal => KEY_EQUAL, + &Key::Backspace => KEY_BACKSPACE, + &Key::Tab => KEY_TAB, + &Key::Q => KEY_Q, + &Key::W => KEY_W, + &Key::E => KEY_E, + &Key::R => KEY_R, + &Key::T => KEY_T, + &Key::Y => KEY_Y, + &Key::U => KEY_U, + &Key::I => KEY_I, + &Key::O => KEY_O, + &Key::P => KEY_P, + &Key::LeftBrace => KEY_LEFTBRACE, + &Key::RightBrace => KEY_RIGHTBRACE, + &Key::Enter => KEY_ENTER, + &Key::LeftControl => KEY_LEFTCTRL, + &Key::A => KEY_A, + &Key::S => KEY_S, + &Key::D => KEY_D, + &Key::F => KEY_F, + &Key::G => KEY_G, + &Key::H => KEY_H, + &Key::J => KEY_J, + &Key::K => KEY_K, + &Key::L => KEY_L, + &Key::SemiColon => KEY_SEMICOLON, + &Key::Apostrophe => KEY_APOSTROPHE, + &Key::Grave => KEY_GRAVE, + &Key::LeftShift => KEY_LEFTSHIFT, + &Key::BackSlash => KEY_BACKSLASH, + &Key::Z => KEY_Z, + &Key::X => KEY_X, + &Key::C => KEY_C, + &Key::V => KEY_V, + &Key::B => KEY_B, + &Key::N => KEY_N, + &Key::M => KEY_M, + &Key::Comma => KEY_COMMA, + &Key::Dot => KEY_DOT, + &Key::Slash => KEY_SLASH, + &Key::RightShift => KEY_RIGHTSHIFT, + &Key::LeftAlt => KEY_LEFTALT, + &Key::Space => KEY_SPACE, + &Key::CapsLock => KEY_CAPSLOCK, + &Key::F1 => KEY_F1, + &Key::F2 => KEY_F2, + &Key::F3 => KEY_F3, + &Key::F4 => KEY_F4, + &Key::F5 => KEY_F5, + &Key::F6 => KEY_F6, + &Key::F7 => KEY_F7, + &Key::F8 => KEY_F8, + &Key::F9 => KEY_F9, + &Key::F10 => KEY_F10, + &Key::NumLock => KEY_NUMLOCK, + &Key::ScrollLock => KEY_SCROLLLOCK, + &Key::F11 => KEY_F11, + &Key::F12 => KEY_F12, + &Key::RightControl => KEY_RIGHTCTRL, + &Key::SysRq => KEY_SYSRQ, + &Key::RightAlt => KEY_RIGHTALT, + &Key::LineFeed => KEY_LINEFEED, + &Key::Home => KEY_HOME, + &Key::Up => KEY_UP, + &Key::PageUp => KEY_PAGEUP, + &Key::Left => KEY_LEFT, + &Key::Right => KEY_RIGHT, + &Key::End => KEY_END, + &Key::Down => KEY_DOWN, + &Key::PageDown => KEY_PAGEDOWN, + &Key::Insert => KEY_INSERT, + &Key::Delete => KEY_DELETE, + &Key::LeftMeta => KEY_LEFTMETA, + &Key::RightMeta => KEY_RIGHTMETA, + &Key::ScrollUp => KEY_SCROLLUP, + &Key::ScrollDown => KEY_SCROLLDOWN, + &Key::F13 => KEY_F13, + &Key::F14 => KEY_F14, + &Key::F15 => KEY_F15, + &Key::F16 => KEY_F16, + &Key::F17 => KEY_F17, + &Key::F18 => KEY_F18, + &Key::F19 => KEY_F19, + &Key::F20 => KEY_F20, + &Key::F21 => KEY_F21, + &Key::F22 => KEY_F22, + &Key::F23 => KEY_F23, + &Key::F24 => KEY_F24, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(KeyPadVariants))] + pub enum KeyPad { + Asterisk, + _7, + _8, + _9, + Minus, + _4, + _5, + _6, + Plus, + _1, + _2, + _3, + _0, + Dot, + AltComma, + Enter, + Slash, + Equal, + PlusMinus, + Comma, + LeftParen, + RightParen, + } +} + +impl Into for KeyPad { + fn into(self) -> Event { + Event::Keyboard(Keyboard::KeyPad(self)) + } +} + +impl Press for KeyPad { } +impl Release for KeyPad { } + +impl Kind for KeyPad { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for KeyPad { + fn code(&self) -> c_int { + match self { + &KeyPad::Asterisk => KEY_KPASTERISK, + &KeyPad::_7 => KEY_KP7, + &KeyPad::_8 => KEY_KP8, + &KeyPad::_9 => KEY_KP9, + &KeyPad::Minus => KEY_KPMINUS, + &KeyPad::_4 => KEY_KP4, + &KeyPad::_5 => KEY_KP5, + &KeyPad::_6 => KEY_KP6, + &KeyPad::Plus => KEY_KPPLUS, + &KeyPad::_1 => KEY_KP1, + &KeyPad::_2 => KEY_KP2, + &KeyPad::_3 => KEY_KP3, + &KeyPad::_0 => KEY_KP0, + &KeyPad::Dot => KEY_KPDOT, + &KeyPad::AltComma => KEY_KPJPCOMMA, + &KeyPad::Enter => KEY_KPENTER, + &KeyPad::Slash => KEY_KPSLASH, + &KeyPad::Equal => KEY_KPEQUAL, + &KeyPad::PlusMinus => KEY_KPPLUSMINUS, + &KeyPad::Comma => KEY_KPCOMMA, + &KeyPad::LeftParen => KEY_KPLEFTPAREN, + &KeyPad::RightParen => KEY_KPRIGHTPAREN, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(MiscVariants))] + pub enum Misc { + ZenkakuHankaku, + ND102, + RO, + Katakana, + Hiragana, + Henkan, + KatakanaHiragana, + Muhenkan, + Macro, + Mute, + VolumeDown, + VolumeUp, + Power, + Pause, + Scale, + Hangeul, + Hanguel, + Hanja, + Yen, + Compose, + Stop, + Again, + Props, + Undo, + Front, + Copy, + Open, + Paste, + Find, + Cut, + Help, + Menu, + Calc, + Setup, + Sleep, + WakeUp, + File, + SendFile, + DeleteFile, + XFer, + Prog1, + Prog2, + WWW, + MSDOS, + Coffee, + ScreenLock, + RotateDisplay, + Direction, + CycleWindows, + Mail, + Bookmarks, + Computer, + Back, + Forward, + CloseCD, + EjectCD, + EjectCloseCD, + NextSong, + PlayPause, + PreviousSong, + StopCD, + Record, + Rewind, + Phone, + Iso, + Config, + HomePage, + Refresh, + Exit, + Move, + Edit, + New, + Redo, + PlayCD, + PauseCD, + Prog3, + Prog4, + DashBoard, + Suspend, + Close, + Play, + FastForward, + BassBoost, + Print, + HP, + Camera, + Sound, + Question, + Email, + Chat, + Search, + Connect, + Finance, + Sport, + Shop, + AltErase, + Cancel, + BrightnessDown, + BrightnessUp, + Media, + SwitchVideoMode, + IllumToggle, + IllumDown, + IllumUp, + Send, + Reply, + ForwardEmail, + Save, + Documents, + Battery, + Bluetooth, + WLAN, + UWB, + Unknown, + VideoNext, + VideoPrev, + BrightnessCycle, + BrightnessAuto, + BrightnessZero, + DisplayOff, + WWAN, + WIMAX, + RFKILL, + MicMute, + Ok, + Select, + Goto, + Clear, + Power2, + Option, + Info, + Time, + Vendor, + Archive, + Program, + Channel, + Favorites, + EPG, + PVR, + MHP, + Language, + Title, + Subtitle, + Angle, + Zoom, + Mode, + Keyboard, + Screen, + PC, + TV, + TV2, + VCR, + VCR2, + SAT, + SAT2, + CD, + Tape, + Radio, + Tuner, + Player, + Text, + DVD, + AUX, + MP3, + Audio, + Video, + Directory, + List, + Memo, + Calendar, + Red, + Green, + Yellow, + Blue, + ChannelUp, + ChannelDown, + First, + Last, + AB, + Next, + Restart, + Slow, + Shuffle, + Break, + Previous, + Digits, + TEEN, + TWEN, + VideoPhone, + Games, + ZoomIn, + ZoomOut, + ZoomReset, + WordProcessor, + Editor, + SpreadSheet, + GraphicsEditor, + Presentation, + Database, + News, + VoiceMail, + AddressBook, + Messenger, + DisplayToggle, + BrightnessToggle, + SpellCheck, + LogOff, + Dollar, + Euro, + FrameBack, + FrameForward, + ContextMenu, + MediaRepeat, + Up10Channels, + Down10Channels, + Images, + DeleteEOL, + DeleteEOS, + InsertLine, + DeleteLine, + WPS, + LightsToggle, + ALSToggle, + ButtonConfig, + TaskManager, + Journal, + ControlPanel, + AppSelect, + ScreenSaver, + VoiceCommand, + BrighnessMin, + BrightnessMax, + } +} + +impl Into for Misc { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Misc(self)) + } +} + +impl Press for Misc { } +impl Release for Misc { } + +impl Kind for Misc { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Misc { + fn code(&self) -> c_int { + match self { + &Misc::ZenkakuHankaku => KEY_ZENKAKUHANKAKU, + &Misc::ND102 => KEY_102ND, + &Misc::RO => KEY_RO, + &Misc::Katakana => KEY_KATAKANA, + &Misc::Hiragana => KEY_HIRAGANA, + &Misc::Henkan => KEY_HENKAN, + &Misc::KatakanaHiragana => KEY_KATAKANAHIRAGANA, + &Misc::Muhenkan => KEY_MUHENKAN, + &Misc::Macro => KEY_MACRO, + &Misc::Mute => KEY_MUTE, + &Misc::VolumeDown => KEY_VOLUMEDOWN, + &Misc::VolumeUp => KEY_VOLUMEUP, + &Misc::Power => KEY_POWER, + &Misc::Pause => KEY_PAUSE, + &Misc::Scale => KEY_SCALE, + &Misc::Hangeul => KEY_HANGEUL, + &Misc::Hanguel => KEY_HANGUEL, + &Misc::Hanja => KEY_HANJA, + &Misc::Yen => KEY_YEN, + &Misc::Compose => KEY_COMPOSE, + &Misc::Stop => KEY_STOP, + &Misc::Again => KEY_AGAIN, + &Misc::Props => KEY_PROPS, + &Misc::Undo => KEY_UNDO, + &Misc::Front => KEY_FRONT, + &Misc::Copy => KEY_COPY, + &Misc::Open => KEY_OPEN, + &Misc::Paste => KEY_PASTE, + &Misc::Find => KEY_FIND, + &Misc::Cut => KEY_CUT, + &Misc::Help => KEY_HELP, + &Misc::Menu => KEY_MENU, + &Misc::Calc => KEY_CALC, + &Misc::Setup => KEY_SETUP, + &Misc::Sleep => KEY_SLEEP, + &Misc::WakeUp => KEY_WAKEUP, + &Misc::File => KEY_FILE, + &Misc::SendFile => KEY_SENDFILE, + &Misc::DeleteFile => KEY_DELETEFILE, + &Misc::XFer => KEY_XFER, + &Misc::Prog1 => KEY_PROG1, + &Misc::Prog2 => KEY_PROG2, + &Misc::WWW => KEY_WWW, + &Misc::MSDOS => KEY_MSDOS, + &Misc::Coffee => KEY_COFFEE, + &Misc::ScreenLock => KEY_SCREENLOCK, + &Misc::RotateDisplay => KEY_ROTATE_DISPLAY, + &Misc::Direction => KEY_DIRECTION, + &Misc::CycleWindows => KEY_CYCLEWINDOWS, + &Misc::Mail => KEY_MAIL, + &Misc::Bookmarks => KEY_BOOKMARKS, + &Misc::Computer => KEY_COMPUTER, + &Misc::Back => KEY_BACK, + &Misc::Forward => KEY_FORWARD, + &Misc::CloseCD => KEY_CLOSECD, + &Misc::EjectCD => KEY_EJECTCD, + &Misc::EjectCloseCD => KEY_EJECTCLOSECD, + &Misc::NextSong => KEY_NEXTSONG, + &Misc::PlayPause => KEY_PLAYPAUSE, + &Misc::PreviousSong => KEY_PREVIOUSSONG, + &Misc::StopCD => KEY_STOPCD, + &Misc::Record => KEY_RECORD, + &Misc::Rewind => KEY_REWIND, + &Misc::Phone => KEY_PHONE, + &Misc::Iso => KEY_ISO, + &Misc::Config => KEY_CONFIG, + &Misc::HomePage => KEY_HOMEPAGE, + &Misc::Refresh => KEY_REFRESH, + &Misc::Exit => KEY_EXIT, + &Misc::Move => KEY_MOVE, + &Misc::Edit => KEY_EDIT, + &Misc::New => KEY_NEW, + &Misc::Redo => KEY_REDO, + &Misc::PlayCD => KEY_PLAYCD, + &Misc::PauseCD => KEY_PAUSECD, + &Misc::Prog3 => KEY_PROG3, + &Misc::Prog4 => KEY_PROG4, + &Misc::DashBoard => KEY_DASHBOARD, + &Misc::Suspend => KEY_SUSPEND, + &Misc::Close => KEY_CLOSE, + &Misc::Play => KEY_PLAY, + &Misc::FastForward => KEY_FASTFORWARD, + &Misc::BassBoost => KEY_BASSBOOST, + &Misc::Print => KEY_PRINT, + &Misc::HP => KEY_HP, + &Misc::Camera => KEY_CAMERA, + &Misc::Sound => KEY_SOUND, + &Misc::Question => KEY_QUESTION, + &Misc::Email => KEY_EMAIL, + &Misc::Chat => KEY_CHAT, + &Misc::Search => KEY_SEARCH, + &Misc::Connect => KEY_CONNECT, + &Misc::Finance => KEY_FINANCE, + &Misc::Sport => KEY_SPORT, + &Misc::Shop => KEY_SHOP, + &Misc::AltErase => KEY_ALTERASE, + &Misc::Cancel => KEY_CANCEL, + &Misc::BrightnessDown => KEY_BRIGHTNESSDOWN, + &Misc::BrightnessUp => KEY_BRIGHTNESSUP, + &Misc::Media => KEY_MEDIA, + &Misc::SwitchVideoMode => KEY_SWITCHVIDEOMODE, + &Misc::IllumToggle => KEY_KBDILLUMTOGGLE, + &Misc::IllumDown => KEY_KBDILLUMDOWN, + &Misc::IllumUp => KEY_KBDILLUMUP, + &Misc::Send => KEY_SEND, + &Misc::Reply => KEY_REPLY, + &Misc::ForwardEmail => KEY_FORWARDMAIL, + &Misc::Save => KEY_SAVE, + &Misc::Documents => KEY_DOCUMENTS, + &Misc::Battery => KEY_BATTERY, + &Misc::Bluetooth => KEY_BLUETOOTH, + &Misc::WLAN => KEY_WLAN, + &Misc::UWB => KEY_UWB, + &Misc::Unknown => KEY_UNKNOWN, + &Misc::VideoNext => KEY_VIDEO_NEXT, + &Misc::VideoPrev => KEY_VIDEO_PREV, + &Misc::BrightnessCycle => KEY_BRIGHTNESS_CYCLE, + &Misc::BrightnessAuto => KEY_BRIGHTNESS_AUTO, + &Misc::BrightnessZero => KEY_BRIGHTNESS_ZERO, + &Misc::DisplayOff => KEY_DISPLAY_OFF, + &Misc::WWAN => KEY_WWAN, + &Misc::WIMAX => KEY_WIMAX, + &Misc::RFKILL => KEY_RFKILL, + &Misc::MicMute => KEY_MICMUTE, + &Misc::Ok => KEY_OK, + &Misc::Select => KEY_SELECT, + &Misc::Goto => KEY_GOTO, + &Misc::Clear => KEY_CLEAR, + &Misc::Power2 => KEY_POWER2, + &Misc::Option => KEY_OPTION, + &Misc::Info => KEY_INFO, + &Misc::Time => KEY_TIME, + &Misc::Vendor => KEY_VENDOR, + &Misc::Archive => KEY_ARCHIVE, + &Misc::Program => KEY_PROGRAM, + &Misc::Channel => KEY_CHANNEL, + &Misc::Favorites => KEY_FAVORITES, + &Misc::EPG => KEY_EPG, + &Misc::PVR => KEY_PVR, + &Misc::MHP => KEY_MHP, + &Misc::Language => KEY_LANGUAGE, + &Misc::Title => KEY_TITLE, + &Misc::Subtitle => KEY_SUBTITLE, + &Misc::Angle => KEY_ANGLE, + &Misc::Zoom => KEY_ZOOM, + &Misc::Mode => KEY_MODE, + &Misc::Keyboard => KEY_KEYBOARD, + &Misc::Screen => KEY_SCREEN, + &Misc::PC => KEY_PC, + &Misc::TV => KEY_TV, + &Misc::TV2 => KEY_TV2, + &Misc::VCR => KEY_VCR, + &Misc::VCR2 => KEY_VCR2, + &Misc::SAT => KEY_SAT, + &Misc::SAT2 => KEY_SAT2, + &Misc::CD => KEY_CD, + &Misc::Tape => KEY_TAPE, + &Misc::Radio => KEY_RADIO, + &Misc::Tuner => KEY_TUNER, + &Misc::Player => KEY_PLAYER, + &Misc::Text => KEY_TEXT, + &Misc::DVD => KEY_DVD, + &Misc::AUX => KEY_AUX, + &Misc::MP3 => KEY_MP3, + &Misc::Audio => KEY_AUDIO, + &Misc::Video => KEY_VIDEO, + &Misc::Directory => KEY_DIRECTORY, + &Misc::List => KEY_LIST, + &Misc::Memo => KEY_MEMO, + &Misc::Calendar => KEY_CALENDAR, + &Misc::Red => KEY_RED, + &Misc::Green => KEY_GREEN, + &Misc::Yellow => KEY_YELLOW, + &Misc::Blue => KEY_BLUE, + &Misc::ChannelUp => KEY_CHANNELUP, + &Misc::ChannelDown => KEY_CHANNELDOWN, + &Misc::First => KEY_FIRST, + &Misc::Last => KEY_LAST, + &Misc::AB => KEY_AB, + &Misc::Next => KEY_NEXT, + &Misc::Restart => KEY_RESTART, + &Misc::Slow => KEY_SLOW, + &Misc::Shuffle => KEY_SHUFFLE, + &Misc::Break => KEY_BREAK, + &Misc::Previous => KEY_PREVIOUS, + &Misc::Digits => KEY_DIGITS, + &Misc::TEEN => KEY_TEEN, + &Misc::TWEN => KEY_TWEN, + &Misc::VideoPhone => KEY_VIDEOPHONE, + &Misc::Games => KEY_GAMES, + &Misc::ZoomIn => KEY_ZOOMIN, + &Misc::ZoomOut => KEY_ZOOMOUT, + &Misc::ZoomReset => KEY_ZOOMRESET, + &Misc::WordProcessor => KEY_WORDPROCESSOR, + &Misc::Editor => KEY_EDITOR, + &Misc::SpreadSheet => KEY_SPREADSHEET, + &Misc::GraphicsEditor => KEY_GRAPHICSEDITOR, + &Misc::Presentation => KEY_PRESENTATION, + &Misc::Database => KEY_DATABASE, + &Misc::News => KEY_NEWS, + &Misc::VoiceMail => KEY_VOICEMAIL, + &Misc::AddressBook => KEY_ADDRESSBOOK, + &Misc::Messenger => KEY_MESSENGER, + &Misc::DisplayToggle => KEY_DISPLAYTOGGLE, + &Misc::BrightnessToggle => KEY_BRIGHTNESS_TOGGLE, + &Misc::SpellCheck => KEY_SPELLCHECK, + &Misc::LogOff => KEY_LOGOFF, + &Misc::Dollar => KEY_DOLLAR, + &Misc::Euro => KEY_EURO, + &Misc::FrameBack => KEY_FRAMEBACK, + &Misc::FrameForward => KEY_FRAMEFORWARD, + &Misc::ContextMenu => KEY_CONTEXT_MENU, + &Misc::MediaRepeat => KEY_MEDIA_REPEAT, + &Misc::Up10Channels => KEY_10CHANNELSUP, + &Misc::Down10Channels => KEY_10CHANNELSDOWN, + &Misc::Images => KEY_IMAGES, + &Misc::DeleteEOL => KEY_DEL_EOL, + &Misc::DeleteEOS => KEY_DEL_EOS, + &Misc::InsertLine => KEY_INS_LINE, + &Misc::DeleteLine => KEY_DEL_LINE, + &Misc::WPS => KEY_WPS_BUTTON, + &Misc::LightsToggle => KEY_LIGHTS_TOGGLE, + &Misc::ALSToggle => KEY_ALS_TOGGLE, + &Misc::ButtonConfig => KEY_BUTTONCONFIG, + &Misc::TaskManager => KEY_TASKMANAGER, + &Misc::Journal => KEY_JOURNAL, + &Misc::ControlPanel => KEY_CONTROLPANEL, + &Misc::AppSelect => KEY_APPSELECT, + &Misc::ScreenSaver => KEY_SCREENSAVER, + &Misc::VoiceCommand => KEY_VOICECOMMAND, + &Misc::BrighnessMin => KEY_BRIGHTNESS_MIN, + &Misc::BrightnessMax => KEY_BRIGHTNESS_MAX, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(FunctionVariants))] + pub enum Function { + Press, + Esc, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + _1, + _2, + D, + E, + F, + S, + B, + } +} + +impl Into for Function { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Function(self)) + } +} + +impl Press for Function { } +impl Release for Function { } + +impl Kind for Function { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Function { + fn code(&self) -> c_int { + match self { + &Function::Press => KEY_FN, + &Function::Esc => KEY_FN_ESC, + &Function::F1 => KEY_FN_F1, + &Function::F2 => KEY_FN_F2, + &Function::F3 => KEY_FN_F3, + &Function::F4 => KEY_FN_F4, + &Function::F5 => KEY_FN_F5, + &Function::F6 => KEY_FN_F6, + &Function::F7 => KEY_FN_F7, + &Function::F8 => KEY_FN_F8, + &Function::F9 => KEY_FN_F9, + &Function::F10 => KEY_FN_F10, + &Function::F11 => KEY_FN_F11, + &Function::F12 => KEY_FN_F12, + &Function::_1 => KEY_FN_1, + &Function::_2 => KEY_FN_2, + &Function::D => KEY_FN_D, + &Function::E => KEY_FN_E, + &Function::F => KEY_FN_F, + &Function::S => KEY_FN_S, + &Function::B => KEY_FN_B, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(BrailleVariants))] + pub enum Braille { + Dot1, + Dot2, + Dot3, + Dot4, + Dot5, + Dot6, + Dot7, + Dot8, + Dot9, + Dot10, + } +} + +impl Into for Braille { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Braille(self)) + } +} + +impl Press for Braille { } +impl Release for Braille { } + +impl Kind for Braille { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Braille { + fn code(&self) -> c_int { + match self { + &Braille::Dot1 => KEY_BRL_DOT1, + &Braille::Dot2 => KEY_BRL_DOT2, + &Braille::Dot3 => KEY_BRL_DOT3, + &Braille::Dot4 => KEY_BRL_DOT4, + &Braille::Dot5 => KEY_BRL_DOT5, + &Braille::Dot6 => KEY_BRL_DOT6, + &Braille::Dot7 => KEY_BRL_DOT7, + &Braille::Dot8 => KEY_BRL_DOT8, + &Braille::Dot9 => KEY_BRL_DOT9, + &Braille::Dot10 => KEY_BRL_DOT10, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(NumericVariants))] + pub enum Numeric { + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + _8, + _9, + Star, + Pound, + A, + B, + C, + D, + } +} + +impl Into for Numeric { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Numeric(self)) + } +} + +impl Press for Numeric { } +impl Release for Numeric { } + +impl Kind for Numeric { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Numeric { + fn code(&self) -> c_int { + match self { + &Numeric::_0 => KEY_NUMERIC_0, + &Numeric::_1 => KEY_NUMERIC_1, + &Numeric::_2 => KEY_NUMERIC_2, + &Numeric::_3 => KEY_NUMERIC_3, + &Numeric::_4 => KEY_NUMERIC_4, + &Numeric::_5 => KEY_NUMERIC_5, + &Numeric::_6 => KEY_NUMERIC_6, + &Numeric::_7 => KEY_NUMERIC_7, + &Numeric::_8 => KEY_NUMERIC_8, + &Numeric::_9 => KEY_NUMERIC_9, + &Numeric::Star => KEY_NUMERIC_STAR, + &Numeric::Pound => KEY_NUMERIC_POUND, + &Numeric::A => KEY_NUMERIC_A, + &Numeric::B => KEY_NUMERIC_B, + &Numeric::C => KEY_NUMERIC_C, + &Numeric::D => KEY_NUMERIC_D, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(TouchPadVariants))] + pub enum TouchPad { + Toggle, + On, + Off, + } +} + +impl Into for TouchPad { + fn into(self) -> Event { + Event::Keyboard(Keyboard::TouchPad(self)) + } +} + +impl Press for TouchPad { } +impl Release for TouchPad { } + +impl Kind for TouchPad { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for TouchPad { + fn code(&self) -> c_int { + match self { + &TouchPad::Toggle => KEY_TOUCHPAD_TOGGLE, + &TouchPad::On => KEY_TOUCHPAD_ON, + &TouchPad::Off => KEY_TOUCHPAD_OFF, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(CameraVariants))] + pub enum Camera { + ZoomIn, + ZoomOut, + Up, + Down, + Left, + Right, + Focus, + } +} + +impl Into for Camera { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Camera(self)) + } +} + +impl Press for Camera { } +impl Release for Camera { } + +impl Kind for Camera { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Camera { + fn code(&self) -> c_int { + match self { + &Camera::ZoomIn => KEY_CAMERA_ZOOMIN, + &Camera::ZoomOut => KEY_CAMERA_ZOOMOUT, + &Camera::Up => KEY_CAMERA_UP, + &Camera::Down => KEY_CAMERA_DOWN, + &Camera::Left => KEY_CAMERA_LEFT, + &Camera::Right => KEY_CAMERA_RIGHT, + &Camera::Focus => KEY_CAMERA_FOCUS, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(AttendantVariants))] + pub enum Attendant { + On, + Off, + Toggle, + } +} + +impl Into for Attendant { + fn into(self) -> Event { + Event::Keyboard(Keyboard::Attendant(self)) + } +} + +impl Press for Attendant { } +impl Release for Attendant { } + +impl Kind for Attendant { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for Attendant { + fn code(&self) -> c_int { + match self { + &Attendant::On => KEY_ATTENDANT_ON, + &Attendant::Off => KEY_ATTENDANT_OFF, + &Attendant::Toggle => KEY_ATTENDANT_TOGGLE, + } + } +} + +custom_derive! { + #[derive(Clone, Copy, PartialEq, Eq, Debug, IterVariants(InputAssistVariants))] + pub enum InputAssist { + Prev, + Next, + PrevGroup, + NextGroup, + Accept, + Cancel, + } +} + +impl Into for InputAssist { + fn into(self) -> Event { + Event::Keyboard(Keyboard::InputAssist(self)) + } +} + +impl Press for InputAssist { } +impl Release for InputAssist { } + +impl Kind for InputAssist { + fn kind(&self) -> c_int { + EV_KEY + } +} + +impl Code for InputAssist { + fn code(&self) -> c_int { + match self { + &InputAssist::Prev => KEY_KBDINPUTASSIST_PREV, + &InputAssist::Next => KEY_KBDINPUTASSIST_NEXT, + &InputAssist::PrevGroup => KEY_KBDINPUTASSIST_PREVGROUP, + &InputAssist::NextGroup => KEY_KBDINPUTASSIST_NEXTGROUP, + &InputAssist::Accept => KEY_KBDINPUTASSIST_ACCEPT, + &InputAssist::Cancel => KEY_KBDINPUTASSIST_CANCEL, + } + } +} diff --git a/src/event/mod.rs b/src/event/mod.rs new file mode 100644 index 0000000..d7d604b --- /dev/null +++ b/src/event/mod.rs @@ -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; diff --git a/src/event/relative.rs b/src/event/relative.rs new file mode 100644 index 0000000..c668eb5 --- /dev/null +++ b/src/event/relative.rs @@ -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 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 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 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, + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..c9beeb0 --- /dev/null +++ b/src/lib.rs @@ -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 = ::std::result::Result; + +pub mod event; +pub use event::Event; + +pub mod device; +pub use device::Device; + +pub fn default() -> Result { + device::Builder::default() +} + +pub fn open>(path: P) -> Result { + device::Builder::open(path) +}