Update nix to 0.9, support FreeBSD

nix 0.9's ioctl macro works with buffers now.
This commit is contained in:
Greg V 2017-12-01 22:44:06 +03:00
parent 04761b788f
commit e5e7332952
4 changed files with 53 additions and 56 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,8 +47,8 @@ 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 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! { bitflags! {
/// Event types supported by the device. /// Event types supported by the device.
pub flags Types: u32 { pub flags Types: u32 {
@ -707,34 +722,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;
@ -744,7 +739,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) {
@ -794,7 +789,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 {
@ -806,10 +801,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(())

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)]
@ -192,26 +192,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))
} }