From e5e73329523b40de4c32e6799a265a176337c32c Mon Sep 17 00:00:00 2001 From: Greg V Date: Fri, 1 Dec 2017 22:44:06 +0300 Subject: [PATCH] Update nix to 0.9, support FreeBSD nix 0.9's ioctl macro works with buffers now. --- Cargo.toml | 2 +- README.md | 12 +++++++----- src/lib.rs | 57 +++++++++++++++++++++++++----------------------------- src/raw.rs | 38 ++++++++++++++++++------------------ 4 files changed, 53 insertions(+), 56 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a353603..c45b8ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = [] diff --git a/README.md b/README.md index 0fd6f0c..5883335 100644 --- a/README.md +++ b/README.md @@ -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 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. diff --git a/src/lib.rs b/src/lib.rs index 8705b19..a6e28fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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,8 +47,8 @@ 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; @@ -71,6 +71,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 { @@ -707,34 +722,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; @@ -744,7 +739,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) { @@ -794,7 +789,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 { @@ -806,10 +801,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(()) diff --git a/src/raw.rs b/src/raw.rs index d2b0f16..344b3c3 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -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)] @@ -192,26 +192,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 { - 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 { - convert_ioctl_res!(::nix::sys::ioctl::ioctl(fd, ior!(b'E', 0x40 + abs, ::std::mem::size_of::()) as ::libc::c_ulong, buf)) + convert_ioctl_res!(::nix::libc::ioctl(fd, ior!(b'E', 0x40 + abs, ::std::mem::size_of::()) as ::libc::c_ulong, buf)) }