Merge pull request #8 from myfreeweb/master

Adds some bugs!
This commit is contained in:
ember arlynx 2020-05-03 22:34:15 -07:00 committed by GitHub
commit 62bb393491
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 60 deletions

View file

@ -12,7 +12,7 @@ bitflags = "0.8.2"
libc = "0.2.22"
fixedbitset = "0.1.6"
num = "0.1.37"
nix = "0.8.1"
nix = "0.9.0"
[features]
unstable = []

View file

@ -11,16 +11,18 @@ Nice(r) access to `evdev` devices.
What is `evdev`?
===================
`evdev` is the Linux kernel's generic input interface. This crate exposes
access to these sorts of input devices. There is some trickery involved, so
please read the crate documentation.
`evdev` is the Linux kernel's generic input interface, also implemented by other
kernels such as FreeBSD.
This crate exposes access to these sorts of input devices. There is some trickery
involved, so please read the crate documentation.
What does this library support?
===============================
This library exposes raw evdev events, but uses the Rust `Iterator` trait to
do so, and will handle `SYN_DROPPED` events properly for the client. I try to
match [libevdev](http://www.freedesktop.org/software/libevdev/doc/latest/)
match [libevdev](https://www.freedesktop.org/software/libevdev/doc/latest/)
closely, where possible.
Writing to devices is not yet supported (eg, turning LEDs on).
@ -33,5 +35,5 @@ Example
=======
See <examples/evtest.rs> for an example of using this library (which roughly
corresponds to the userspace [evtest](http://cgit.freedesktop.org/evtest/)
corresponds to the userspace [evtest](https://cgit.freedesktop.org/evtest/)
tool.

View file

@ -31,7 +31,7 @@
//! It is recommended that you dedicate a thread to processing input events, or use epoll with the
//! fd returned by `Device::fd` to process events when they are ready.
#![cfg(any(target_os = "linux", target_os = "android"))]
#![cfg(any(unix, target_os = "android"))]
#![allow(non_camel_case_types)]
#[macro_use]
@ -47,10 +47,9 @@ pub mod raw;
use std::os::unix::io::*;
use std::os::unix::ffi::*;
use std::path::Path;
use std::ffi::CString;
use std::mem::size_of;
use std::ffi::{CString, CStr};
use std::mem::{size_of, transmute};
use fixedbitset::FixedBitSet;
use num::traits::WrappingSub;
use nix::Error;
@ -71,6 +70,21 @@ macro_rules! do_ioctl {
}}
}
macro_rules! do_ioctl_buf {
($buf:ident, $name:ident, $fd:expr) => {
unsafe {
let blen = $buf.len();
match ::raw::$name($fd, &mut $buf[..]) {
Ok(len) if len >= 0 => {
$buf[blen - 1] = 0;
Some(CStr::from_ptr(&mut $buf[0] as *mut u8 as *mut _).to_owned())
},
_ => None
}
}
}
}
bitflags! {
/// Event types supported by the device.
pub flags Types: u32 {
@ -669,7 +683,7 @@ 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::InvalidPath),
Err(_) => return Err(Error::InvalidPath),
};
// FIXME: only need for writing is for setting LED values. re-evaluate always using RDWR
// later.
@ -711,34 +725,14 @@ impl Device {
let mut bits: u32 = 0;
let mut bits64: u64 = 0;
let mut vec = Vec::with_capacity(256);
let mut buf = [0u8; 256];
do_ioctl!(eviocgbit(fd, 0, 4, &mut bits as *mut u32 as *mut u8));
dev.ty = Types::from_bits(bits).expect("evdev: unexpected type bits! report a bug");
let dev_len = do_ioctl!(eviocgname(fd, vec.as_mut_ptr(), 255));
unsafe { vec.set_len(dev_len as usize - 1) };
dev.name = CString::new(vec.clone()).unwrap();
match unsafe { eviocgphys(fd, vec.as_mut_ptr(), 255) } {
Ok(phys_len) => {
if phys_len > 0 {
unsafe { vec.set_len(phys_len as usize - 1) };
dev.phys = Some(CString::new(vec.clone()).unwrap());
}
},
Err(_) => { /* not essential */ }
}
match unsafe { eviocguniq(fd, vec.as_mut_ptr(), 255) } {
Ok(uniq_len) => {
if uniq_len > 0 {
unsafe { vec.set_len(uniq_len as usize - 1) };
dev.uniq = Some(CString::new(vec.clone()).unwrap());
}
},
Err(_) => { /* not essential */ }
}
dev.name = do_ioctl_buf!(buf, eviocgname, fd).unwrap_or(CString::default());
dev.phys = do_ioctl_buf!(buf, eviocgphys, fd);
dev.uniq = do_ioctl_buf!(buf, eviocguniq, fd);
do_ioctl!(eviocgid(fd, &mut dev.id));
let mut driver_version: i32 = 0;
@ -748,7 +742,7 @@ impl Device {
((driver_version >> 8) & 0xff) as u8,
(driver_version & 0xff) as u8);
do_ioctl!(eviocgprop(fd, &mut bits as *mut u32 as *mut u8, 0x1f)); // FIXME: handle old kernel
do_ioctl!(eviocgprop(fd, std::slice::from_raw_parts_mut(&mut bits as *mut u32 as *mut u8, 0x1f))); // FIXME: handle old kernel
dev.props = Props::from_bits(bits).expect("evdev: unexpected prop bits! report a bug");
if dev.ty.contains(KEY) {
@ -798,7 +792,7 @@ impl Device {
/// If there is an error at any point, the state will not be synchronized completely.
pub fn sync_state(&mut self) -> Result<(), Error> {
if self.ty.contains(KEY) {
do_ioctl!(eviocgkey(self.fd, self.state.key_vals.as_mut_slice().as_mut_ptr() as *mut u32 as *mut u8, self.state.key_vals.len()));
do_ioctl!(eviocgkey(self.fd, transmute::<&mut [u32], &mut [u8]>(self.state.key_vals.as_mut_slice())));
}
if self.ty.contains(ABSOLUTE) {
for idx in 0..0x28 {
@ -810,10 +804,10 @@ impl Device {
}
}
if self.ty.contains(SWITCH) {
do_ioctl!(eviocgsw(self.fd, self.state.switch_vals.as_mut_slice().as_mut_ptr() as *mut u32 as *mut u8, self.state.switch_vals.len()));
do_ioctl!(eviocgsw(self.fd, transmute::<&mut [u32], &mut [u8]>(self.state.switch_vals.as_mut_slice())));
}
if self.ty.contains(LED) {
do_ioctl!(eviocgled(self.fd, self.state.led_vals.as_mut_slice().as_mut_ptr() as *mut u32 as *mut u8, self.state.led_vals.len()));
do_ioctl!(eviocgled(self.fd, transmute::<&mut [u32], &mut [u8]>(self.state.led_vals.as_mut_slice())));
}
Ok(())
@ -928,7 +922,7 @@ impl Device {
}
fn fill_events(&mut self) -> Result<(), Error> {
let mut buf = &mut self.pending_events;
let buf = &mut self.pending_events;
loop {
buf.reserve(20);
let pre_len = buf.len();

View file

@ -3,12 +3,12 @@ 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!(write_int eviocrmff with b'E', 0x81);
// 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]);
ioctl!(write_ptr eviocskeycode with b'E', 0x04; [::libc::c_uint; 2]);
// ioctl!(write_int eviocskeycode_v2 with b'E', 0x04; /*struct*/ input_keymap_entry);
ioctl!(write_ptr eviocsrep with b'E', 0x03; [::libc::c_uint; 2]);
#[repr(C)]
#[derive(Copy, Clone)]
@ -168,7 +168,6 @@ impl ::std::default::Default for ff_condition_effect {
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[allow(raw_pointer_derive)]
pub struct ff_periodic_effect {
pub waveform: u16,
pub period: u16,
@ -192,26 +191,26 @@ 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!(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);
ioctl!(write_ptr eviocsff with b'E', 0x80; ff_effect);
ioctl!(write_int eviocgrab with b'E', 0x90);
ioctl!(write_int eviocrevoke with b'E', 0x91);
ioctl!(write_int eviocsclockid with b'E', 0xa0);
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))
convert_ioctl_res!(::nix::libc::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))
convert_ioctl_res!(::nix::libc::ioctl(fd, ior!(b'E', 0x40 + abs, ::std::mem::size_of::<input_absinfo>()) as ::libc::c_ulong, buf))
}