extern crate evdev_sys as raw;
extern crate nix;
extern crate libc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
pub mod enums;
pub mod logging;
pub mod util;
#[macro_use]
mod macros;
use libc::{c_char, c_int, c_uint, c_void};
use nix::errno::Errno;
use std::any::Any;
use std::ffi::{CStr, CString};
use std::fs::File;
use std::os::unix::io::{AsRawFd, FromRawFd};
use enums::*;
use util::*;
pub enum GrabMode {
Grab = raw::LIBEVDEV_GRAB as isize,
Ungrab = raw::LIBEVDEV_UNGRAB as isize,
}
bitflags! {
pub flags ReadFlag: u32 {
const SYNC = 1,
const NORMAL = 2,
const FORCE_SYNC = 4,
const BLOCKING = 8,
}
}
#[derive(PartialEq)]
pub enum ReadStatus {
Success = raw::LIBEVDEV_READ_STATUS_SUCCESS as isize,
Sync = raw::LIBEVDEV_READ_STATUS_SYNC as isize,
}
pub enum LedState {
On = raw::LIBEVDEV_LED_ON as isize,
Off = raw::LIBEVDEV_LED_OFF as isize,
}
pub struct DeviceId {
pub bustype: BusType,
pub vendor: u16,
pub product: u16,
pub version: u16,
}
pub struct AbsInfo {
pub value: i32,
pub minimum: i32,
pub maximum: i32,
pub fuzz: i32,
pub flat: i32,
pub resolution: i32,
}
pub struct Device {
raw: *mut raw::libevdev,
}
pub struct TimeVal {
pub tv_sec: i64,
pub tv_usec: i64,
}
pub struct InputEvent {
pub time: TimeVal,
pub event_type: EventType,
pub event_code: EventCode,
pub value: i32,
}
fn ptr_to_str(ptr: *const c_char) -> Option<&'static str> {
let slice : Option<&CStr> = unsafe {
if ptr.is_null() {
return None
}
Some(CStr::from_ptr(ptr))
};
match slice {
None => None,
Some(s) => {
let buf : &[u8] = s.to_bytes();
Some(std::str::from_utf8(buf).unwrap())
}
}
}
impl Device {
pub fn new() -> Option<Device> {
let libevdev = unsafe {
raw::libevdev_new()
};
if libevdev.is_null() {
None
} else {
Some(Device {
raw: libevdev,
})
}
}
pub fn new_from_fd(fd: &File) -> Result<Device, Errno> {
let mut libevdev = 0 as *mut _;
let result = unsafe {
raw::libevdev_new_from_fd(fd.as_raw_fd(), &mut libevdev)
};
match result {
0 => Ok(Device { raw: libevdev }),
error => Err(Errno::from_i32(-error)),
}
}
string_getter!(name, libevdev_get_name,
phys, libevdev_get_phys,
uniq, libevdev_get_uniq);
string_setter!(set_name, libevdev_set_name,
set_phys, libevdev_set_phys,
set_uniq, libevdev_set_uniq);
pub fn fd(&self) -> Option<File> {
let result = unsafe {
raw::libevdev_get_fd(self.raw)
};
if result == 0 {
None
} else {
unsafe {
let f = File::from_raw_fd(result);
Some(f)
}
}
}
pub fn set_fd(&mut self, f: &File) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_set_fd(self.raw, f.as_raw_fd())
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn change_fd(&mut self, f: &File) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_change_fd(self.raw, f.as_raw_fd())
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn grab(&mut self, grab: GrabMode) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_grab(self.raw, grab as c_int)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error)),
}
}
pub fn abs_info(&self, code: &EventCode) -> Option<AbsInfo> {
let (_, ev_code) = event_code_to_int(code);
let a = unsafe {
raw::libevdev_get_abs_info(self.raw, ev_code)
};
if a.is_null() {
return None
}
unsafe {
let absinfo = AbsInfo {
value: (*a).value,
minimum: (*a).minimum,
maximum: (*a).maximum,
fuzz: (*a).fuzz,
flat: (*a).flat,
resolution: (*a).resolution,
};
Some(absinfo)
}
}
pub fn set_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) {
let (_, ev_code) = event_code_to_int(code);
let absinfo = raw::input_absinfo {
value: absinfo.value,
minimum: absinfo.minimum,
maximum: absinfo.maximum,
fuzz: absinfo.fuzz,
flat: absinfo.flat,
resolution: absinfo.resolution,
};
unsafe {
raw::libevdev_set_abs_info(self.raw, ev_code,
&absinfo as *const _);
}
}
pub fn has(&self, blob: &Any) -> bool {
if let Some(ev_type) = blob.downcast_ref::<EventType>() {
self.has_event_type(ev_type)
} else if let Some(ev_code) = blob.downcast_ref::<EventCode>() {
self.has_event_code(ev_code)
} else if let Some(prop) = blob.downcast_ref::<InputProp>() {
self.has_property(prop)
} else {
false
}
}
pub fn enable(&self, blob: &Any) -> Result<(),Errno> {
if let Some(ev_type) = blob.downcast_ref::<EventType>() {
self.enable_event_type(ev_type)
} else if let Some(ev_code) = blob.downcast_ref::<EventCode>() {
self.enable_event_code(ev_code, &0)
} else if let Some(prop) = blob.downcast_ref::<InputProp>() {
self.enable_property(prop)
} else {
Err(Errno::from_i32(-1))
}
}
fn has_property(&self, prop: &InputProp) -> bool {
unsafe {
raw::libevdev_has_property(self.raw, prop.clone() as c_uint) != 0
}
}
fn enable_property(&self, prop: &InputProp) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_enable_property(self.raw, prop.clone() as c_uint) as i32
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
fn has_event_type(&self, ev_type: &EventType) -> bool {
unsafe {
raw::libevdev_has_event_type(self.raw, ev_type.clone() as c_uint) != 0
}
}
fn has_event_code(&self, code: &EventCode) -> bool {
unsafe {
let (ev_type, ev_code) = event_code_to_int(code);
raw::libevdev_has_event_code(self.raw,
ev_type,
ev_code) != 0
}
}
pub fn event_value(&self, code: &EventCode) -> Option<i32> {
let mut value: i32 = 0;
let (ev_type, ev_code) = event_code_to_int(code);
let valid = unsafe {
raw::libevdev_fetch_event_value(self.raw,
ev_type,
ev_code ,
&mut value)
};
match valid {
0 => None,
_ => Some(value),
}
}
pub fn set_event_value(&self, code: &EventCode, val: i32)
-> Result<(), Errno> {
let (ev_type, ev_code) = event_code_to_int(code);
let result = unsafe {
raw::libevdev_set_event_value(self.raw,
ev_type,
ev_code,
val as c_int)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn has_event_pending(&self) -> bool {
unsafe {
raw::libevdev_has_event_pending(self.raw) > 0
}
}
product_getter!(product_id, libevdev_get_id_product,
vendor_id, libevdev_get_id_vendor,
bustype, libevdev_get_id_bustype,
version, libevdev_get_id_version);
product_setter!(set_product_id, libevdev_set_id_product,
set_vendor_id, libevdev_set_id_vendor,
set_bustype, libevdev_set_id_bustype,
set_version, libevdev_set_id_version);
pub fn driver_version(&self) -> i32 {
unsafe {
raw::libevdev_get_driver_version(self.raw) as i32
}
}
abs_getter!(abs_minimum, libevdev_get_abs_minimum,
abs_maximum, libevdev_get_abs_maximum,
abs_fuzz, libevdev_get_abs_fuzz,
abs_flat, libevdev_get_abs_flat,
abs_resolution, libevdev_get_abs_resolution);
abs_setter!(set_abs_minimum, libevdev_set_abs_minimum,
set_abs_maximum, libevdev_set_abs_maximum,
set_abs_fuzz, libevdev_set_abs_fuzz,
set_abs_flat, libevdev_set_abs_flat,
set_abs_resolution, libevdev_set_abs_resolution);
pub fn slot_value(&self, slot: u32, code: &EventCode) -> Option<i32> {
let (_, ev_code) = event_code_to_int(code);
let mut value: i32 = 0;
let valid = unsafe {
raw::libevdev_fetch_slot_value(self.raw,
slot as c_uint,
ev_code,
&mut value)
};
match valid {
0 => None,
_ => Some(value),
}
}
pub fn set_slot_value(&self, slot: u32, code: &EventCode, val: i32)
-> Result<(), Errno> {
let (_, ev_code) = event_code_to_int(code);
let result = unsafe {
raw::libevdev_set_slot_value(self.raw,
slot as c_uint,
ev_code,
val as c_int)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn num_slots(&self) -> Option<i32> {
let result = unsafe {
raw::libevdev_get_num_slots(self.raw)
};
match result {
-1 => None,
slots => Some(slots),
}
}
pub fn current_slot(&self) -> Option<i32> {
let result = unsafe {
raw::libevdev_get_current_slot(self.raw)
};
match result {
-1 => None,
slots => Some(slots),
}
}
fn enable_event_type(&self, ev_type: &EventType) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_enable_event_type(self.raw,
ev_type.clone() as c_uint)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
fn enable_event_code(&self, ev_code: &EventCode, data: &Any)
-> Result<(), Errno> {
let (ev_type, ev_code) = event_code_to_int(ev_code);
let result = unsafe {
raw::libevdev_enable_event_code(self.raw,
ev_type as c_uint,
ev_code as c_uint,
data as *const _ as *const c_void)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn disable(&self, blob: &Any) -> Result<(),Errno> {
if let Some(ev_type) = blob.downcast_ref::<EventType>() {
self.disable_event_type(ev_type)
} else if let Some(ev_code) = blob.downcast_ref::<EventCode>() {
self.disable_event_code(ev_code)
} else {
Err(Errno::from_i32(-1))
}
}
fn disable_event_type(&self, ev_type: &EventType) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_disable_event_type(self.raw,
ev_type.clone() as c_uint)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
fn disable_event_code(&self, code: &EventCode)
-> Result<(), Errno> {
let (ev_type, ev_code) = event_code_to_int(code);
let result = unsafe {
raw::libevdev_disable_event_code(self.raw,
ev_type,
ev_code)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn set_kernel_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) {
let (_, ev_code) = event_code_to_int(code);
let absinfo = raw::input_absinfo {
value: absinfo.value,
minimum: absinfo.minimum,
maximum: absinfo.maximum,
fuzz: absinfo.fuzz,
flat: absinfo.flat,
resolution: absinfo.resolution,
};
unsafe {
raw::libevdev_kernel_set_abs_info(self.raw, ev_code,
&absinfo as *const _);
}
}
pub fn kernel_set_led_value(&self, code: &EventCode, value: LedState)
-> Result<(), Errno> {
let (_, ev_code) = event_code_to_int(code);
let result = unsafe {
raw::libevdev_kernel_set_led_value(self.raw,
ev_code,
value as c_int)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn set_clock_id(&self, clockid: i32) -> Result<(), Errno> {
let result = unsafe {
raw::libevdev_set_clock_id(self.raw,
clockid as c_int)
};
match result {
0 => Ok(()),
error => Err(Errno::from_i32(-error))
}
}
pub fn next_event(&self, flags: ReadFlag)
-> Result<(ReadStatus, InputEvent), Errno> {
let mut ev = raw::input_event {
time: raw::timeval {
tv_sec: 0,
tv_usec: 0,
},
event_type: 0,
event_code: 0,
value: 0,
};
let result = unsafe {
raw::libevdev_next_event(self.raw, flags.bits as c_uint, &mut ev)
};
let event = InputEvent {
time: TimeVal {
tv_sec: ev.time.tv_sec,
tv_usec: ev.time.tv_usec,
},
event_type: int_to_event_type(ev.event_type as u32).unwrap(),
event_code: int_to_event_code(ev.event_type as u32, ev.event_code as u32).unwrap(),
value: ev.value,
};
match result {
raw::LIBEVDEV_READ_STATUS_SUCCESS => Ok((ReadStatus::Success, event)),
raw::LIBEVDEV_READ_STATUS_SYNC => Ok((ReadStatus::Sync, event)),
error => Err(Errno::from_i32(-error)),
}
}
}
impl InputEvent {
pub fn is_type(&self, ev_type: &EventType) -> bool {
let ev = raw::input_event {
time: raw::timeval {
tv_sec: self.time.tv_sec,
tv_usec: self.time.tv_usec,
},
event_type: self.event_type.clone() as u16,
event_code: event_code_to_int(&self.event_code).1 as u16,
value: self.value,
};
unsafe {
raw::libevdev_event_is_type(&ev, ev_type.clone() as c_uint) == 1
}
}
pub fn is_code(&self, code: &EventCode) -> bool {
let (ev_type, ev_code) = event_code_to_int(code);
let ev = raw::input_event {
time: raw::timeval {
tv_sec: self.time.tv_sec,
tv_usec: self.time.tv_usec,
},
event_type: self.event_type.clone() as u16,
event_code: event_code_to_int(&self.event_code).1 as u16,
value: self.value,
};
unsafe {
raw::libevdev_event_is_code(&ev, ev_type, ev_code) == 1
}
}
}
impl Drop for Device {
fn drop(&mut self) {
unsafe {
raw::libevdev_free(self.raw);
}
}
}