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" libc = "0.2.22"
fixedbitset = "0.1.6" fixedbitset = "0.1.6"
num = "0.1.37" num = "0.1.37"
nix = "0.8.1" nix = "0.9.0"
[features] [features]
unstable = [] unstable = []

View file

@ -11,16 +11,18 @@ Nice(r) access to `evdev` devices.
What is `evdev`? What is `evdev`?
=================== ===================
`evdev` is the Linux kernel's generic input interface. This crate exposes `evdev` is the Linux kernel's generic input interface, also implemented by other
access to these sorts of input devices. There is some trickery involved, so kernels such as FreeBSD.
please read the crate documentation.
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? What does this library support?
=============================== ===============================
This library exposes raw evdev events, but uses the Rust `Iterator` trait to 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 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. closely, where possible.
Writing to devices is not yet supported (eg, turning LEDs on). 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 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. tool.

View file

@ -31,7 +31,7 @@
//! It is recommended that you dedicate a thread to processing input events, or use epoll with the //! 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. //! 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)] #![allow(non_camel_case_types)]
#[macro_use] #[macro_use]
@ -47,10 +47,9 @@ pub mod raw;
use std::os::unix::io::*; use std::os::unix::io::*;
use std::os::unix::ffi::*; use std::os::unix::ffi::*;
use std::path::Path; use std::path::Path;
use std::ffi::CString; use std::ffi::{CString, CStr};
use std::mem::size_of; use std::mem::{size_of, transmute};
use fixedbitset::FixedBitSet; use fixedbitset::FixedBitSet;
use num::traits::WrappingSub;
use nix::Error; 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! { bitflags! {
/// Event types supported by the device. /// Event types supported by the device.
pub flags Types: u32 { pub flags Types: u32 {
@ -669,7 +683,7 @@ impl Device {
pub fn open(path: &AsRef<Path>) -> Result<Device, Error> { pub fn open(path: &AsRef<Path>) -> Result<Device, Error> {
let cstr = match CString::new(path.as_ref().as_os_str().as_bytes()) { let cstr = match CString::new(path.as_ref().as_os_str().as_bytes()) {
Ok(s) => s, 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 // FIXME: only need for writing is for setting LED values. re-evaluate always using RDWR
// later. // later.
@ -711,34 +725,14 @@ impl Device {
let mut bits: u32 = 0; let mut bits: u32 = 0;
let mut bits64: u64 = 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)); 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"); 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)); dev.name = do_ioctl_buf!(buf, eviocgname, fd).unwrap_or(CString::default());
unsafe { vec.set_len(dev_len as usize - 1) }; dev.phys = do_ioctl_buf!(buf, eviocgphys, fd);
dev.name = CString::new(vec.clone()).unwrap(); dev.uniq = do_ioctl_buf!(buf, eviocguniq, fd);
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 */ }
}
do_ioctl!(eviocgid(fd, &mut dev.id)); do_ioctl!(eviocgid(fd, &mut dev.id));
let mut driver_version: i32 = 0; let mut driver_version: i32 = 0;
@ -748,7 +742,7 @@ impl Device {
((driver_version >> 8) & 0xff) as u8, ((driver_version >> 8) & 0xff) as u8,
(driver_version & 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"); dev.props = Props::from_bits(bits).expect("evdev: unexpected prop bits! report a bug");
if dev.ty.contains(KEY) { 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. /// If there is an error at any point, the state will not be synchronized completely.
pub fn sync_state(&mut self) -> Result<(), Error> { pub fn sync_state(&mut self) -> Result<(), Error> {
if self.ty.contains(KEY) { 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) { if self.ty.contains(ABSOLUTE) {
for idx in 0..0x28 { for idx in 0..0x28 {
@ -810,10 +804,10 @@ impl Device {
} }
} }
if self.ty.contains(SWITCH) { 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) { 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(()) Ok(())
@ -928,7 +922,7 @@ impl Device {
} }
fn fill_events(&mut self) -> Result<(), Error> { fn fill_events(&mut self) -> Result<(), Error> {
let mut buf = &mut self.pending_events; let buf = &mut self.pending_events;
loop { loop {
buf.reserve(20); buf.reserve(20);
let pre_len = buf.len(); 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 eviocgkeycode with b'E', 0x04; [::libc::c_uint; 2]);
ioctl!(read eviocgrep with b'E', 0x03; [::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!(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); // ioctl!(read eviocgkeycode_v2 with b'E', 0x04; /*struct*/ input_keymap_entry);
// TODO #define EVIOCSFF _IOC ( _IOC_WRITE , 'E' , 0x80 , sizeof ( struct ff_effect ) ) // 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_ptr eviocskeycode with b'E', 0x04; [::libc::c_uint; 2]);
// ioctl!(write eviocskeycode_v2 with b'E', 0x04; /*struct*/ input_keymap_entry); // ioctl!(write_int eviocskeycode_v2 with b'E', 0x04; /*struct*/ input_keymap_entry);
ioctl!(write eviocsrep with b'E', 0x03; [::libc::c_uint; 2]); ioctl!(write_ptr eviocsrep with b'E', 0x03; [::libc::c_uint; 2]);
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -168,7 +168,6 @@ impl ::std::default::Default for ff_condition_effect {
} }
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[allow(raw_pointer_derive)]
pub struct ff_periodic_effect { pub struct ff_periodic_effect {
pub waveform: u16, pub waveform: u16,
pub period: u16, pub period: u16,
@ -192,26 +191,26 @@ impl ::std::default::Default for ff_rumble_effect {
fn default() -> Self { unsafe { ::std::mem::zeroed() } } fn default() -> Self { unsafe { ::std::mem::zeroed() } }
} }
ioctl!(read buf eviocgname with b'E', 0x06; u8); ioctl!(read_buf eviocgname with b'E', 0x06; u8);
ioctl!(read buf eviocgphys with b'E', 0x07; u8); ioctl!(read_buf eviocgphys with b'E', 0x07; u8);
ioctl!(read buf eviocguniq with b'E', 0x08; u8); ioctl!(read_buf eviocguniq with b'E', 0x08; u8);
ioctl!(read buf eviocgprop with b'E', 0x09; u8); ioctl!(read_buf eviocgprop with b'E', 0x09; u8);
ioctl!(read buf eviocgmtslots with b'E', 0x0a; u8); ioctl!(read_buf eviocgmtslots with b'E', 0x0a; u8);
ioctl!(read buf eviocgkey with b'E', 0x18; u8); ioctl!(read_buf eviocgkey with b'E', 0x18; u8);
ioctl!(read buf eviocgled with b'E', 0x19; u8); ioctl!(read_buf eviocgled with b'E', 0x19; u8);
ioctl!(read buf eviocgsnd with b'E', 0x1a; u8); ioctl!(read_buf eviocgsnd with b'E', 0x1a; u8);
ioctl!(read buf eviocgsw with b'E', 0x1b; u8); ioctl!(read_buf eviocgsw with b'E', 0x1b; u8);
ioctl!(write eviocsff with b'E', 0x80; ff_effect); ioctl!(write_ptr eviocsff with b'E', 0x80; ff_effect);
ioctl!(write eviocgrab with b'E', 0x90; ::libc::c_int); ioctl!(write_int eviocgrab with b'E', 0x90);
ioctl!(write eviocrevoke with b'E', 0x91; ::libc::c_int); ioctl!(write_int eviocrevoke with b'E', 0x91);
ioctl!(write eviocsclockid with b'E', 0xa0; ::libc::c_int); 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> { 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> { 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))
} }