Initial port to nix
This commit is contained in:
parent
0c166f7726
commit
9ff9cf4718
3 changed files with 248 additions and 49 deletions
|
@ -8,12 +8,11 @@ repository = "https://github.com/cmr/evdev"
|
|||
documentation = "https://docs.rs/evdev"
|
||||
|
||||
[dependencies]
|
||||
ioctl = "0.3.3"
|
||||
bitflags = "0.8.2"
|
||||
errno = "0.2.3"
|
||||
libc = "0.2.22"
|
||||
fixedbitset = "0.1.6"
|
||||
num = "0.1.37"
|
||||
nix = "0.8.1"
|
||||
|
||||
[features]
|
||||
unstable = []
|
||||
|
|
77
src/lib.rs
77
src/lib.rs
|
@ -36,12 +36,14 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate ioctl;
|
||||
#[macro_use]
|
||||
extern crate nix;
|
||||
extern crate libc;
|
||||
extern crate errno;
|
||||
extern crate fixedbitset;
|
||||
extern crate num;
|
||||
|
||||
pub mod raw;
|
||||
|
||||
use std::os::unix::io::*;
|
||||
use std::os::unix::ffi::*;
|
||||
use std::path::Path;
|
||||
|
@ -50,41 +52,22 @@ use std::mem::size_of;
|
|||
use fixedbitset::FixedBitSet;
|
||||
use num::traits::WrappingSub;
|
||||
|
||||
use nix::Error;
|
||||
|
||||
pub use Key::*;
|
||||
pub use FFEffect::*;
|
||||
pub use Synchronization::*;
|
||||
|
||||
use raw::*;
|
||||
|
||||
#[link(name = "rt")]
|
||||
extern {
|
||||
fn clock_gettime(clkid: libc::c_int, res: *mut libc::timespec);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
NulError(std::ffi::NulError),
|
||||
LibcError(errno::Errno),
|
||||
IoctlError(&'static str, errno::Errno),
|
||||
}
|
||||
|
||||
impl From<std::ffi::NulError> for Error {
|
||||
fn from(e: std::ffi::NulError) -> Error {
|
||||
Error::NulError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<errno::Errno> for Error {
|
||||
fn from(e: errno::Errno) -> Error {
|
||||
Error::LibcError(e)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! do_ioctl {
|
||||
($name:ident($($arg:expr),+)) => {{
|
||||
let rc = unsafe { ::ioctl::$name($($arg,)+) };
|
||||
if rc < 0 {
|
||||
return Err(Error::IoctlError(stringify!($name), errno::errno()))
|
||||
}
|
||||
rc
|
||||
unsafe { ::raw::$name($($arg,)+) }?
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -399,7 +382,7 @@ pub struct DeviceState {
|
|||
pub timestamp: libc::timeval,
|
||||
/// Set = key pressed
|
||||
pub key_vals: FixedBitSet,
|
||||
pub abs_vals: Vec<ioctl::input_absinfo>,
|
||||
pub abs_vals: Vec<input_absinfo>,
|
||||
/// Set = switch enabled (closed)
|
||||
pub switch_vals: FixedBitSet,
|
||||
/// Set = LED lit
|
||||
|
@ -412,7 +395,7 @@ pub struct Device {
|
|||
name: CString,
|
||||
phys: Option<CString>,
|
||||
uniq: Option<CString>,
|
||||
id: ioctl::input_id,
|
||||
id: input_id,
|
||||
props: Props,
|
||||
driver_version: (u8, u8, u8),
|
||||
key_bits: FixedBitSet,
|
||||
|
@ -425,7 +408,7 @@ pub struct Device {
|
|||
ff_stat: FFStatus,
|
||||
rep: Repeat,
|
||||
snd: Sound,
|
||||
pending_events: Vec<ioctl::input_event>,
|
||||
pending_events: Vec<input_event>,
|
||||
clock: libc::c_int,
|
||||
// pending_events[last_seen..] is the events that have occurred since the last sync.
|
||||
last_seen: usize,
|
||||
|
@ -644,7 +627,7 @@ impl Device {
|
|||
&self.uniq
|
||||
}
|
||||
|
||||
pub fn input_id(&self) -> ioctl::input_id {
|
||||
pub fn input_id(&self) -> input_id {
|
||||
self.id
|
||||
}
|
||||
|
||||
|
@ -695,14 +678,14 @@ impl Device {
|
|||
pub fn open(path: &AsRef<Path>) -> Result<Device, Error> {
|
||||
let cstr = match CString::new(path.as_ref().as_os_str().as_bytes()) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return Err(Error::NulError(e))
|
||||
Err(e) => return Err(Error::InvalidPath),
|
||||
};
|
||||
// FIXME: only need for writing is for setting LED values. re-evaluate always using RDWR
|
||||
// later.
|
||||
let fd = Fd(unsafe { libc::open(cstr.as_ptr(), libc::O_NONBLOCK | libc::O_RDWR | libc::O_CLOEXEC, 0) });
|
||||
if *fd == -1 {
|
||||
std::mem::forget(fd);
|
||||
return Err(Error::LibcError(errno::errno()))
|
||||
return Err(Error::from_errno(::nix::Errno::last()));
|
||||
}
|
||||
|
||||
let mut dev = Device {
|
||||
|
@ -747,13 +730,13 @@ impl Device {
|
|||
unsafe { vec.set_len(dev_len as usize - 1) };
|
||||
dev.name = CString::new(vec.clone()).unwrap();
|
||||
|
||||
let phys_len = unsafe { ioctl::eviocgphys(*fd, vec.as_mut_ptr(), 255) };
|
||||
let phys_len = unsafe { eviocgphys(*fd, vec.as_mut_ptr(), 255) }?;
|
||||
if phys_len > 0 {
|
||||
unsafe { vec.set_len(phys_len as usize - 1) };
|
||||
dev.phys = Some(CString::new(vec.clone()).unwrap());
|
||||
}
|
||||
|
||||
let uniq_len = unsafe { ioctl::eviocguniq(*fd, vec.as_mut_ptr(), 255) };
|
||||
let uniq_len = unsafe { eviocguniq(*fd, vec.as_mut_ptr(), 255) }?;
|
||||
if uniq_len > 0 {
|
||||
unsafe { vec.set_len(uniq_len as usize - 1) };
|
||||
dev.uniq = Some(CString::new(vec.clone()).unwrap());
|
||||
|
@ -783,7 +766,7 @@ impl Device {
|
|||
do_ioctl!(eviocgbit(*fd, ABSOLUTE.number(), 0x3f, &mut bits64 as *mut u64 as *mut u8));
|
||||
println!("abs bits: {:b}", bits64);
|
||||
dev.abs = AbsoluteAxis::from_bits(bits64).expect("evdev: unexpected abs bits! report a bug");
|
||||
dev.state.abs_vals = vec![ioctl::input_absinfo::default(); 0x3f];
|
||||
dev.state.abs_vals = vec![input_absinfo::default(); 0x3f];
|
||||
}
|
||||
|
||||
if dev.ty.contains(SWITCH) {
|
||||
|
@ -882,7 +865,7 @@ impl Device {
|
|||
for key_idx in 0..self.key_bits.len() {
|
||||
if self.key_bits.contains(key_idx) {
|
||||
if old_state.key_vals[key_idx] != self.state.key_vals[key_idx] {
|
||||
self.pending_events.push(ioctl::input_event {
|
||||
self.pending_events.push(raw::input_event {
|
||||
time: time,
|
||||
_type: KEY.number(),
|
||||
code: key_idx as u16,
|
||||
|
@ -897,7 +880,7 @@ impl Device {
|
|||
let abs = 1 << idx;
|
||||
if self.abs.bits() & abs != 0 {
|
||||
if old_state.abs_vals[idx as usize] != self.state.abs_vals[idx as usize] {
|
||||
self.pending_events.push(ioctl::input_event {
|
||||
self.pending_events.push(raw::input_event {
|
||||
time: time,
|
||||
_type: ABSOLUTE.number(),
|
||||
code: idx as u16,
|
||||
|
@ -912,7 +895,7 @@ impl Device {
|
|||
let sw = 1 << idx;
|
||||
if sw < SW_MAX.bits() && self.switch.bits() & sw == 1 {
|
||||
if old_state.switch_vals[idx as usize] != self.state.switch_vals[idx as usize] {
|
||||
self.pending_events.push(ioctl::input_event {
|
||||
self.pending_events.push(raw::input_event {
|
||||
time: time,
|
||||
_type: SWITCH.number(),
|
||||
code: idx as u16,
|
||||
|
@ -927,7 +910,7 @@ impl Device {
|
|||
let led = 1 << idx;
|
||||
if led < LED_MAX.bits() && self.led.bits() & led == 1 {
|
||||
if old_state.led_vals[idx as usize] != self.state.led_vals[idx as usize] {
|
||||
self.pending_events.push(ioctl::input_event {
|
||||
self.pending_events.push(raw::input_event {
|
||||
time: time,
|
||||
_type: LED.number(),
|
||||
code: idx as u16,
|
||||
|
@ -938,7 +921,7 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
self.pending_events.push(ioctl::input_event {
|
||||
self.pending_events.push(raw::input_event {
|
||||
time: time,
|
||||
_type: SYNCHRONIZATION.number(),
|
||||
code: SYN_REPORT as u16,
|
||||
|
@ -956,18 +939,18 @@ impl Device {
|
|||
libc::read(self.fd,
|
||||
buf.as_mut_ptr()
|
||||
.offset(pre_len as isize) as *mut libc::c_void,
|
||||
(size_of::<ioctl::input_event>() * (buf.capacity() - pre_len)) as libc::size_t)
|
||||
(size_of::<raw::input_event>() * (buf.capacity() - pre_len)) as libc::size_t)
|
||||
};
|
||||
if sz == -1 {
|
||||
let errno = errno::errno();
|
||||
if errno != errno::Errno(libc::EAGAIN) {
|
||||
return Err(Error::LibcError(errno));
|
||||
let errno = ::nix::Errno::last();
|
||||
if errno != ::nix::Errno::EAGAIN {
|
||||
return Err(Error::from_errno(errno));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
buf.set_len(pre_len + (sz as usize / size_of::<ioctl::input_event>()));
|
||||
buf.set_len(pre_len + (sz as usize / size_of::<raw::input_event>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1010,10 +993,10 @@ impl<'a> Drop for RawEvents<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for RawEvents<'a> {
|
||||
type Item = ioctl::input_event;
|
||||
type Item = raw::input_event;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<ioctl::input_event> {
|
||||
fn next(&mut self) -> Option<raw::input_event> {
|
||||
self.0.pending_events.pop()
|
||||
}
|
||||
}
|
||||
|
|
217
src/raw.rs
Normal file
217
src/raw.rs
Normal file
|
@ -0,0 +1,217 @@
|
|||
ioctl!(read eviocgeffects with b'E', 0x84; ::libc::c_int);
|
||||
ioctl!(read eviocgid with b'E', 0x02; /*struct*/ input_id);
|
||||
ioctl!(read eviocgkeycode with b'E', 0x04; [::libc::c_uint; 2]);
|
||||
ioctl!(read eviocgrep with b'E', 0x03; [::libc::c_uint; 2]);
|
||||
ioctl!(read eviocgversion with b'E', 0x01; ::libc::c_int);
|
||||
ioctl!(write eviocrmff with b'E', 0x81; ::libc::c_int);
|
||||
// ioctl!(read eviocgkeycode_v2 with b'E', 0x04; /*struct*/ input_keymap_entry);
|
||||
// TODO #define EVIOCSFF _IOC ( _IOC_WRITE , 'E' , 0x80 , sizeof ( struct ff_effect ) )
|
||||
ioctl!(write eviocskeycode with b'E', 0x04; [::libc::c_uint; 2]);
|
||||
// ioctl!(write eviocskeycode_v2 with b'E', 0x04; /*struct*/ input_keymap_entry);
|
||||
ioctl!(write eviocsrep with b'E', 0x03; [::libc::c_uint; 2]);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct input_event {
|
||||
pub time: ::libc::timeval,
|
||||
pub _type: u16,
|
||||
pub code: u16,
|
||||
pub value: i32,
|
||||
}
|
||||
impl ::std::default::Default for input_event {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
impl ::std::fmt::Debug for input_event {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "input_event {{ time: {{ tv_sec: {}, tv_usec: {} }}, _type: {}, code: {}, value: {}",
|
||||
self.time.tv_sec, self.time.tv_usec, self._type, self.code, self.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct input_id {
|
||||
pub bustype: u16,
|
||||
pub vendor: u16,
|
||||
pub product: u16,
|
||||
pub version: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ff_effect {
|
||||
pub _type: u16,
|
||||
pub id: i16,
|
||||
pub direction: u16,
|
||||
pub trigger: ff_trigger,
|
||||
pub replay: ff_replay,
|
||||
pub u: Union_Unnamed16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Union_Unnamed16 {
|
||||
pub _bindgen_data_: [u64; 4usize],
|
||||
}
|
||||
impl Union_Unnamed16 {
|
||||
pub unsafe fn constant(&mut self) -> *mut ff_constant_effect {
|
||||
let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
|
||||
::std::mem::transmute(raw.offset(0))
|
||||
}
|
||||
pub unsafe fn ramp(&mut self) -> *mut ff_ramp_effect {
|
||||
let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
|
||||
::std::mem::transmute(raw.offset(0))
|
||||
}
|
||||
pub unsafe fn periodic(&mut self) -> *mut ff_periodic_effect {
|
||||
let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
|
||||
::std::mem::transmute(raw.offset(0))
|
||||
}
|
||||
pub unsafe fn condition(&mut self)
|
||||
-> *mut [ff_condition_effect; 2usize] {
|
||||
let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
|
||||
::std::mem::transmute(raw.offset(0))
|
||||
}
|
||||
pub unsafe fn rumble(&mut self) -> *mut ff_rumble_effect {
|
||||
let raw: *mut u8 = ::std::mem::transmute(&self._bindgen_data_);
|
||||
::std::mem::transmute(raw.offset(0))
|
||||
}
|
||||
}
|
||||
impl ::std::default::Default for Union_Unnamed16 {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
|
||||
pub struct input_absinfo {
|
||||
pub value: i32,
|
||||
pub minimum: i32,
|
||||
pub maximum: i32,
|
||||
pub fuzz: i32,
|
||||
pub flat: i32,
|
||||
pub resolution: i32,
|
||||
}
|
||||
impl ::std::default::Default for input_absinfo {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct input_keymap_entry {
|
||||
pub flags: u8,
|
||||
pub len: u8,
|
||||
pub index: u16,
|
||||
pub keycode: u32,
|
||||
pub scancode: [u8; 32usize],
|
||||
}
|
||||
impl ::std::default::Default for input_keymap_entry {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_replay {
|
||||
pub length: u16,
|
||||
pub delay: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_replay {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_trigger {
|
||||
pub button: u16,
|
||||
pub interval: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_trigger {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_envelope {
|
||||
pub attack_length: u16,
|
||||
pub attack_level: u16,
|
||||
pub fade_length: u16,
|
||||
pub fade_level: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_envelope {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_constant_effect {
|
||||
pub level: i16,
|
||||
pub envelope: ff_envelope,
|
||||
}
|
||||
impl ::std::default::Default for ff_constant_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_ramp_effect {
|
||||
pub start_level: i16,
|
||||
pub end_level: i16,
|
||||
pub envelope: ff_envelope,
|
||||
}
|
||||
impl ::std::default::Default for ff_ramp_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_condition_effect {
|
||||
pub right_saturation: u16,
|
||||
pub left_saturation: u16,
|
||||
pub right_coeff: i16,
|
||||
pub left_coeff: i16,
|
||||
pub deadband: u16,
|
||||
pub center: i16,
|
||||
}
|
||||
impl ::std::default::Default for ff_condition_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[allow(raw_pointer_derive)]
|
||||
pub struct ff_periodic_effect {
|
||||
pub waveform: u16,
|
||||
pub period: u16,
|
||||
pub magnitude: i16,
|
||||
pub offset: i16,
|
||||
pub phase: u16,
|
||||
pub envelope: ff_envelope,
|
||||
pub custom_len: u32,
|
||||
pub custom_data: *mut i16,
|
||||
}
|
||||
impl ::std::default::Default for ff_periodic_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ff_rumble_effect {
|
||||
pub strong_magnitude: u16,
|
||||
pub weak_magnitude: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_rumble_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
ioctl!(read buf eviocgname with b'E', 0x06; u8);
|
||||
ioctl!(read buf eviocgphys with b'E', 0x07; u8);
|
||||
ioctl!(read buf eviocguniq with b'E', 0x08; u8);
|
||||
ioctl!(read buf eviocgprop with b'E', 0x09; u8);
|
||||
ioctl!(read buf eviocgmtslots with b'E', 0x0a; u8);
|
||||
ioctl!(read buf eviocgkey with b'E', 0x18; u8);
|
||||
ioctl!(read buf eviocgled with b'E', 0x19; u8);
|
||||
ioctl!(read buf eviocgsnd with b'E', 0x1a; u8);
|
||||
ioctl!(read buf eviocgsw with b'E', 0x1b; u8);
|
||||
|
||||
ioctl!(write eviocsff with b'E', 0x80; ff_effect);
|
||||
ioctl!(write eviocgrab with b'E', 0x90; ::libc::c_int);
|
||||
ioctl!(write eviocrevoke with b'E', 0x91; ::libc::c_int);
|
||||
ioctl!(write eviocsclockid with b'E', 0xa0; ::libc::c_int);
|
||||
|
||||
pub unsafe fn eviocgbit(fd: ::libc::c_int, ev: u32, len: ::libc::c_int, buf: *mut u8) -> ::nix::Result<i32> {
|
||||
convert_ioctl_res!(::nix::sys::ioctl::ioctl(fd, ior!(b'E', 0x20 + ev, len) as ::libc::c_ulong, buf))
|
||||
}
|
||||
|
||||
pub unsafe fn eviocgabs(fd: ::libc::c_int, abs: u32, buf: *mut input_absinfo) -> ::nix::Result<i32> {
|
||||
convert_ioctl_res!(::nix::sys::ioctl::ioctl(fd, ior!(b'E', 0x40 + abs, ::std::mem::size_of::<input_absinfo>()) as ::libc::c_ulong, buf))
|
||||
}
|
||||
|
Loading…
Reference in a new issue