Edition 2018 (#25)
* Edition 2018 * cargo fmt * Bump rev to 0.11.0-alpha-2 * Change FF_MAX and KEY_MAX to associated constants
This commit is contained in:
parent
fe3d0e9ab0
commit
4e700d4671
4 changed files with 814 additions and 663 deletions
|
@ -1,11 +1,12 @@
|
|||
[package]
|
||||
name = "evdev"
|
||||
version = "0.11.0-alpha.1"
|
||||
version = "0.11.0-alpha.2"
|
||||
authors = ["Corey Richardson <corey@octayn.net>"]
|
||||
description = "evdev interface for Linux"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/cmr/evdev"
|
||||
documentation = "https://docs.rs/evdev"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.2"
|
||||
|
|
349
src/lib.rs
349
src/lib.rs
|
@ -34,38 +34,31 @@
|
|||
#![cfg(any(unix, target_os = "android"))]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
extern crate nix;
|
||||
extern crate libc;
|
||||
extern crate fixedbitset;
|
||||
extern crate num_traits;
|
||||
|
||||
pub mod raw;
|
||||
mod scancodes;
|
||||
|
||||
use std::os::unix::{io::RawFd, ffi::*};
|
||||
use std::path::Path;
|
||||
use std::ffi::{CString, CStr};
|
||||
use std::mem::{size_of, transmute};
|
||||
use bitflags::bitflags;
|
||||
use fixedbitset::FixedBitSet;
|
||||
|
||||
use nix::Error;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::mem::{size_of, transmute};
|
||||
use std::os::unix::{ffi::*, io::RawFd};
|
||||
use std::path::Path;
|
||||
|
||||
pub use Key::*;
|
||||
pub use FFEffect::*;
|
||||
pub use Synchronization::*;
|
||||
pub use crate::scancodes::*;
|
||||
pub use crate::FFEffect::*;
|
||||
pub use crate::Synchronization::*;
|
||||
|
||||
use raw::*;
|
||||
use crate::raw::*;
|
||||
|
||||
#[link(name = "rt")]
|
||||
extern {
|
||||
extern "C" {
|
||||
fn clock_gettime(clkid: libc::c_int, res: *mut libc::timespec);
|
||||
}
|
||||
|
||||
macro_rules! do_ioctl {
|
||||
($name:ident($($arg:expr),+)) => {{
|
||||
unsafe { ::raw::$name($($arg,)+) }?
|
||||
unsafe { crate::raw::$name($($arg,)+) }?
|
||||
}}
|
||||
}
|
||||
|
||||
|
@ -73,15 +66,15 @@ macro_rules! do_ioctl_buf {
|
|||
($buf:ident, $name:ident, $fd:expr) => {
|
||||
unsafe {
|
||||
let blen = $buf.len();
|
||||
match ::raw::$name($fd, &mut $buf[..]) {
|
||||
match crate::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
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -144,8 +137,6 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
include!("scancodes.rs"); // it's a huge glob of text that I'm tired of skipping over.
|
||||
|
||||
bitflags! {
|
||||
pub struct RelativeAxis: u32 {
|
||||
const REL_X = 1 << 0x00;
|
||||
|
@ -331,7 +322,10 @@ pub enum FFEffect {
|
|||
FF_CUSTOM = 0x5d,
|
||||
FF_GAIN = 0x60,
|
||||
FF_AUTOCENTER = 0x61,
|
||||
FF_MAX = 0x7f,
|
||||
}
|
||||
|
||||
impl FFEffect {
|
||||
pub const MAX: usize = 0x7f;
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
@ -365,7 +359,18 @@ macro_rules! impl_number {
|
|||
}
|
||||
}
|
||||
|
||||
impl_number!(Types, Props, RelativeAxis, AbsoluteAxis, Switch, Led, Misc, FFStatus, Repeat, Sound);
|
||||
impl_number!(
|
||||
Types,
|
||||
Props,
|
||||
RelativeAxis,
|
||||
AbsoluteAxis,
|
||||
Switch,
|
||||
Led,
|
||||
Misc,
|
||||
FFStatus,
|
||||
Repeat,
|
||||
Sound
|
||||
);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -422,7 +427,9 @@ pub struct Device {
|
|||
impl std::fmt::Debug for Device {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let mut ds = f.debug_struct("Device");
|
||||
ds.field("name", &self.name).field("fd", &self.fd).field("ty", &self.ty);
|
||||
ds.field("name", &self.name)
|
||||
.field("fd", &self.fd)
|
||||
.field("ty", &self.ty);
|
||||
if let Some(ref phys) = self.phys {
|
||||
ds.field("phys", phys);
|
||||
}
|
||||
|
@ -430,15 +437,13 @@ impl std::fmt::Debug for Device {
|
|||
ds.field("uniq", uniq);
|
||||
}
|
||||
ds.field("id", &self.id)
|
||||
.field("id", &self.id)
|
||||
.field("props", &self.props)
|
||||
.field("driver_version", &self.driver_version);
|
||||
if self.ty.contains(Types::SYNCHRONIZATION) {
|
||||
|
||||
}
|
||||
.field("id", &self.id)
|
||||
.field("props", &self.props)
|
||||
.field("driver_version", &self.driver_version);
|
||||
if self.ty.contains(Types::SYNCHRONIZATION) {}
|
||||
if self.ty.contains(Types::KEY) {
|
||||
ds.field("key_bits", &self.key_bits)
|
||||
.field("key_vals", &self.state.key_vals);
|
||||
.field("key_vals", &self.state.key_vals);
|
||||
}
|
||||
if self.ty.contains(Types::RELATIVE) {
|
||||
ds.field("rel", &self.rel);
|
||||
|
@ -450,20 +455,21 @@ impl std::fmt::Debug for Device {
|
|||
// ignore multitouch, we'll handle that later.
|
||||
if (self.abs.bits() & abs) == 1 {
|
||||
// eugh.
|
||||
ds.field(&format!("abs_{:x}", idx), &self.state.abs_vals[idx as usize]);
|
||||
ds.field(
|
||||
&format!("abs_{:x}", idx),
|
||||
&self.state.abs_vals[idx as usize],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.ty.contains(Types::MISC) {
|
||||
|
||||
}
|
||||
if self.ty.contains(Types::MISC) {}
|
||||
if self.ty.contains(Types::SWITCH) {
|
||||
ds.field("switch", &self.switch)
|
||||
.field("switch_vals", &self.state.switch_vals);
|
||||
.field("switch_vals", &self.state.switch_vals);
|
||||
}
|
||||
if self.ty.contains(Types::LED) {
|
||||
ds.field("led", &self.led)
|
||||
.field("led_vals", &self.state.led_vals);
|
||||
.field("led_vals", &self.state.led_vals);
|
||||
}
|
||||
if self.ty.contains(Types::SOUND) {
|
||||
ds.field("snd", &self.snd);
|
||||
|
@ -474,8 +480,7 @@ impl std::fmt::Debug for Device {
|
|||
if self.ty.contains(Types::FORCEFEEDBACK) {
|
||||
ds.field("ff", &self.ff);
|
||||
}
|
||||
if self.ty.contains(Types::POWER) {
|
||||
}
|
||||
if self.ty.contains(Types::POWER) {}
|
||||
if self.ty.contains(Types::FORCEFEEDBACKSTATUS) {
|
||||
ds.field("ff_stat", &self.ff_stat);
|
||||
}
|
||||
|
@ -510,94 +515,111 @@ fn bus_name(x: u16) -> &'static str {
|
|||
|
||||
impl std::fmt::Display for Device {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
try!(writeln!(f, "{:?}", self.name));
|
||||
try!(writeln!(f, " Driver version: {}.{}.{}", self.driver_version.0, self.driver_version.1, self.driver_version.2));
|
||||
writeln!(f, "{:?}", self.name)?;
|
||||
writeln!(
|
||||
f,
|
||||
" Driver version: {}.{}.{}",
|
||||
self.driver_version.0, self.driver_version.1, self.driver_version.2
|
||||
)?;
|
||||
if let Some(ref phys) = self.phys {
|
||||
try!(writeln!(f, " Physical address: {:?}", phys));
|
||||
writeln!(f, " Physical address: {:?}", phys)?;
|
||||
}
|
||||
if let Some(ref uniq) = self.uniq {
|
||||
try!(writeln!(f, " Unique name: {:?}", uniq));
|
||||
writeln!(f, " Unique name: {:?}", uniq)?;
|
||||
}
|
||||
|
||||
try!(writeln!(f, " Bus: {}", bus_name(self.id.bustype)));
|
||||
try!(writeln!(f, " Vendor: 0x{:x}", self.id.vendor));
|
||||
try!(writeln!(f, " Product: 0x{:x}", self.id.product));
|
||||
try!(writeln!(f, " Version: 0x{:x}", self.id.version));
|
||||
try!(writeln!(f, " Properties: {:?}", self.props));
|
||||
writeln!(f, " Bus: {}", bus_name(self.id.bustype))?;
|
||||
writeln!(f, " Vendor: 0x{:x}", self.id.vendor)?;
|
||||
writeln!(f, " Product: 0x{:x}", self.id.product)?;
|
||||
writeln!(f, " Version: 0x{:x}", self.id.version)?;
|
||||
writeln!(f, " Properties: {:?}", self.props)?;
|
||||
|
||||
if self.ty.contains(Types::SYNCHRONIZATION) {
|
||||
|
||||
}
|
||||
if self.ty.contains(Types::SYNCHRONIZATION) {}
|
||||
|
||||
if self.ty.contains(Types::KEY) {
|
||||
try!(writeln!(f, " Keys supported:"));
|
||||
writeln!(f, " Keys supported:")?;
|
||||
for key_idx in 0..self.key_bits.len() {
|
||||
if self.key_bits.contains(key_idx) {
|
||||
// Cross our fingers... (what did this mean?)
|
||||
try!(writeln!(f, " {:?} ({}index {})",
|
||||
unsafe { std::mem::transmute::<_, Key>(key_idx as libc::c_int) },
|
||||
if self.state.key_vals.contains(key_idx) { "pressed, " } else { "" },
|
||||
key_idx));
|
||||
writeln!(
|
||||
f,
|
||||
" {:?} ({}index {})",
|
||||
unsafe { std::mem::transmute::<_, Key>(key_idx as libc::c_int) },
|
||||
if self.state.key_vals.contains(key_idx) {
|
||||
"pressed, "
|
||||
} else {
|
||||
""
|
||||
},
|
||||
key_idx
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.ty.contains(Types::RELATIVE) {
|
||||
try!(writeln!(f, " Relative Axes: {:?}", self.rel));
|
||||
writeln!(f, " Relative Axes: {:?}", self.rel)?;
|
||||
}
|
||||
if self.ty.contains(Types::ABSOLUTE) {
|
||||
try!(writeln!(f, " Absolute Axes:"));
|
||||
writeln!(f, " Absolute Axes:")?;
|
||||
for idx in 0..0x3f {
|
||||
let abs = 1<< idx;
|
||||
let abs = 1 << idx;
|
||||
if self.abs.bits() & abs != 0 {
|
||||
// FIXME: abs val Debug is gross
|
||||
try!(writeln!(f, " {:?} ({:?}, index {})",
|
||||
AbsoluteAxis::from_bits(abs).unwrap(),
|
||||
self.state.abs_vals[idx as usize],
|
||||
idx));
|
||||
writeln!(
|
||||
f,
|
||||
" {:?} ({:?}, index {})",
|
||||
AbsoluteAxis::from_bits(abs).unwrap(),
|
||||
self.state.abs_vals[idx as usize],
|
||||
idx
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.ty.contains(Types::MISC) {
|
||||
try!(writeln!(f, " Miscellaneous capabilities: {:?}", self.misc));
|
||||
writeln!(f, " Miscellaneous capabilities: {:?}", self.misc)?;
|
||||
}
|
||||
if self.ty.contains(Types::SWITCH) {
|
||||
try!(writeln!(f, " Switches:"));
|
||||
writeln!(f, " Switches:")?;
|
||||
for idx in 0..0xf {
|
||||
let sw = 1 << idx;
|
||||
if sw < Switch::SW_MAX.bits() && self.switch.bits() & sw == 1 {
|
||||
try!(writeln!(f, " {:?} ({:?}, index {})",
|
||||
Switch::from_bits(sw).unwrap(),
|
||||
self.state.switch_vals[idx as usize],
|
||||
idx));
|
||||
writeln!(
|
||||
f,
|
||||
" {:?} ({:?}, index {})",
|
||||
Switch::from_bits(sw).unwrap(),
|
||||
self.state.switch_vals[idx as usize],
|
||||
idx
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.ty.contains(Types::LED) {
|
||||
try!(writeln!(f, " LEDs:"));
|
||||
writeln!(f, " LEDs:")?;
|
||||
for idx in 0..0xf {
|
||||
let led = 1 << idx;
|
||||
if led < Led::LED_MAX.bits() && self.led.bits() & led == 1 {
|
||||
try!(writeln!(f, " {:?} ({:?}, index {})",
|
||||
Led::from_bits(led).unwrap(),
|
||||
self.state.led_vals[idx as usize],
|
||||
idx));
|
||||
writeln!(
|
||||
f,
|
||||
" {:?} ({:?}, index {})",
|
||||
Led::from_bits(led).unwrap(),
|
||||
self.state.led_vals[idx as usize],
|
||||
idx
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.ty.contains(Types::SOUND) {
|
||||
try!(writeln!(f, " Sound: {:?}", self.snd));
|
||||
writeln!(f, " Sound: {:?}", self.snd)?;
|
||||
}
|
||||
if self.ty.contains(Types::REPEAT) {
|
||||
try!(writeln!(f, " Repeats: {:?}", self.rep));
|
||||
writeln!(f, " Repeats: {:?}", self.rep)?;
|
||||
}
|
||||
if self.ty.contains(Types::FORCEFEEDBACK) {
|
||||
try!(writeln!(f, " Force Feedback supported"));
|
||||
writeln!(f, " Force Feedback supported")?;
|
||||
}
|
||||
if self.ty.contains(Types::POWER) {
|
||||
try!(writeln!(f, " Power supported"));
|
||||
writeln!(f, " Power supported")?;
|
||||
}
|
||||
if self.ty.contains(Types::FORCEFEEDBACKSTATUS) {
|
||||
try!(writeln!(f, " Force Feedback status supported"));
|
||||
writeln!(f, " Force Feedback status supported")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -606,7 +628,9 @@ impl std::fmt::Display for Device {
|
|||
impl Drop for Device {
|
||||
fn drop(&mut self) {
|
||||
// Linux close(2) can fail, but there is nothing to do if it does.
|
||||
unsafe { libc::close(self.fd); }
|
||||
unsafe {
|
||||
libc::close(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -679,14 +703,20 @@ impl Device {
|
|||
&self.state
|
||||
}
|
||||
|
||||
pub fn open(path: &AsRef<Path>) -> Result<Device, Error> {
|
||||
pub fn open(path: &dyn AsRef<Path>) -> Result<Device, Error> {
|
||||
let cstr = match CString::new(path.as_ref().as_os_str().as_bytes()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return Err(Error::InvalidPath),
|
||||
};
|
||||
// FIXME: only need for writing is for setting LED values. re-evaluate always using RDWR
|
||||
// later.
|
||||
let fd = unsafe { libc::open(cstr.as_ptr(), libc::O_NONBLOCK | libc::O_RDWR | libc::O_CLOEXEC, 0) };
|
||||
let fd = unsafe {
|
||||
libc::open(
|
||||
cstr.as_ptr(),
|
||||
libc::O_NONBLOCK | libc::O_RDWR | libc::O_CLOEXEC,
|
||||
0,
|
||||
)
|
||||
};
|
||||
if fd == -1 {
|
||||
return Err(Error::from_errno(::nix::errno::Errno::last()));
|
||||
}
|
||||
|
@ -700,26 +730,29 @@ impl Device {
|
|||
id: unsafe { std::mem::zeroed() },
|
||||
props: Props::empty(),
|
||||
driver_version: (0, 0, 0),
|
||||
key_bits: FixedBitSet::with_capacity(KEY_MAX as usize),
|
||||
key_bits: FixedBitSet::with_capacity(Key::MAX),
|
||||
rel: RelativeAxis::empty(),
|
||||
abs: AbsoluteAxis::empty(),
|
||||
switch: Switch::empty(),
|
||||
led: Led::empty(),
|
||||
misc: Misc::empty(),
|
||||
ff: FixedBitSet::with_capacity(FF_MAX as usize + 1),
|
||||
ff: FixedBitSet::with_capacity(FFEffect::MAX + 1),
|
||||
ff_stat: FFStatus::empty(),
|
||||
rep: Repeat::empty(),
|
||||
snd: Sound::empty(),
|
||||
pending_events: Vec::with_capacity(64),
|
||||
last_seen: 0,
|
||||
state: DeviceState {
|
||||
timestamp: libc::timeval { tv_sec: 0, tv_usec: 0 },
|
||||
key_vals: FixedBitSet::with_capacity(KEY_MAX as usize),
|
||||
timestamp: libc::timeval {
|
||||
tv_sec: 0,
|
||||
tv_usec: 0,
|
||||
},
|
||||
key_vals: FixedBitSet::with_capacity(Key::MAX),
|
||||
abs_vals: vec![],
|
||||
switch_vals: FixedBitSet::with_capacity(0x10),
|
||||
led_vals: FixedBitSet::with_capacity(0x10),
|
||||
},
|
||||
clock: libc::CLOCK_REALTIME
|
||||
clock: libc::CLOCK_REALTIME,
|
||||
};
|
||||
|
||||
let mut bits: u32 = 0;
|
||||
|
@ -736,52 +769,94 @@ impl Device {
|
|||
do_ioctl!(eviocgid(fd, &mut dev.id));
|
||||
let mut driver_version: i32 = 0;
|
||||
do_ioctl!(eviocgversion(fd, &mut driver_version));
|
||||
dev.driver_version =
|
||||
(((driver_version >> 16) & 0xff) as u8,
|
||||
((driver_version >> 8) & 0xff) as u8,
|
||||
(driver_version & 0xff) as u8);
|
||||
dev.driver_version = (
|
||||
((driver_version >> 16) & 0xff) as u8,
|
||||
((driver_version >> 8) & 0xff) as u8,
|
||||
(driver_version & 0xff) as u8,
|
||||
);
|
||||
|
||||
do_ioctl!(eviocgprop(fd, std::slice::from_raw_parts_mut(&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(Types::KEY) {
|
||||
do_ioctl!(eviocgbit(fd, Types::KEY.number(), dev.key_bits.len() as libc::c_int, dev.key_bits.as_mut_slice().as_mut_ptr() as *mut u8));
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::KEY.number(),
|
||||
dev.key_bits.len() as libc::c_int,
|
||||
dev.key_bits.as_mut_slice().as_mut_ptr() as *mut u8
|
||||
));
|
||||
}
|
||||
|
||||
if dev.ty.contains(Types::RELATIVE) {
|
||||
do_ioctl!(eviocgbit(fd, Types::RELATIVE.number(), 0xf, &mut bits as *mut u32 as *mut u8));
|
||||
dev.rel = RelativeAxis::from_bits(bits).expect("evdev: unexpected rel bits! report a bug");
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::RELATIVE.number(),
|
||||
0xf,
|
||||
&mut bits as *mut u32 as *mut u8
|
||||
));
|
||||
dev.rel =
|
||||
RelativeAxis::from_bits(bits).expect("evdev: unexpected rel bits! report a bug");
|
||||
}
|
||||
|
||||
if dev.ty.contains(Types::ABSOLUTE) {
|
||||
do_ioctl!(eviocgbit(fd, Types::ABSOLUTE.number(), 0x3f, &mut bits64 as *mut u64 as *mut u8));
|
||||
dev.abs = AbsoluteAxis::from_bits(bits64).expect("evdev: unexpected abs bits! report a bug");
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::ABSOLUTE.number(),
|
||||
0x3f,
|
||||
&mut bits64 as *mut u64 as *mut u8
|
||||
));
|
||||
dev.abs =
|
||||
AbsoluteAxis::from_bits(bits64).expect("evdev: unexpected abs bits! report a bug");
|
||||
dev.state.abs_vals = vec![input_absinfo::default(); 0x3f];
|
||||
}
|
||||
|
||||
if dev.ty.contains(Types::SWITCH) {
|
||||
do_ioctl!(eviocgbit(fd, Types::SWITCH.number(), 0xf, &mut bits as *mut u32 as *mut u8));
|
||||
dev.switch = Switch::from_bits(bits).expect("evdev: unexpected switch bits! report a bug");
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::SWITCH.number(),
|
||||
0xf,
|
||||
&mut bits as *mut u32 as *mut u8
|
||||
));
|
||||
dev.switch =
|
||||
Switch::from_bits(bits).expect("evdev: unexpected switch bits! report a bug");
|
||||
}
|
||||
|
||||
if dev.ty.contains(Types::LED) {
|
||||
do_ioctl!(eviocgbit(fd, Types::LED.number(), 0xf, &mut bits as *mut u32 as *mut u8));
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::LED.number(),
|
||||
0xf,
|
||||
&mut bits as *mut u32 as *mut u8
|
||||
));
|
||||
dev.led = Led::from_bits(bits).expect("evdev: unexpected led bits! report a bug");
|
||||
}
|
||||
|
||||
if dev.ty.contains(Types::MISC) {
|
||||
do_ioctl!(eviocgbit(fd, Types::MISC.number(), 0x7, &mut bits as *mut u32 as *mut u8));
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::MISC.number(),
|
||||
0x7,
|
||||
&mut bits as *mut u32 as *mut u8
|
||||
));
|
||||
dev.misc = Misc::from_bits(bits).expect("evdev: unexpected misc bits! report a bug");
|
||||
}
|
||||
|
||||
//do_ioctl!(eviocgbit(fd, ffs(FORCEFEEDBACK.bits()), 0x7f, &mut bits as *mut u32 as *mut u8));
|
||||
|
||||
if dev.ty.contains(Types::SOUND) {
|
||||
do_ioctl!(eviocgbit(fd, Types::SOUND.number(), 0x7, &mut bits as *mut u32 as *mut u8));
|
||||
do_ioctl!(eviocgbit(
|
||||
fd,
|
||||
Types::SOUND.number(),
|
||||
0x7,
|
||||
&mut bits as *mut u32 as *mut u8
|
||||
));
|
||||
dev.snd = Sound::from_bits(bits).expect("evdev: unexpected sound bits! report a bug");
|
||||
}
|
||||
|
||||
try!(dev.sync_state());
|
||||
dev.sync_state()?;
|
||||
|
||||
Ok(dev)
|
||||
}
|
||||
|
@ -791,7 +866,10 @@ 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(Types::KEY) {
|
||||
do_ioctl!(eviocgkey(self.fd, transmute::<&mut [u32], &mut [u8]>(self.state.key_vals.as_mut_slice())));
|
||||
do_ioctl!(eviocgkey(
|
||||
self.fd,
|
||||
transmute::<&mut [u32], &mut [u8]>(self.state.key_vals.as_mut_slice())
|
||||
));
|
||||
}
|
||||
if self.ty.contains(Types::ABSOLUTE) {
|
||||
for idx in 0..0x3f {
|
||||
|
@ -801,15 +879,25 @@ impl Device {
|
|||
// handling later removed. not sure what the intention of "handling that later" was
|
||||
// the abs data seems to be fine (tested ABS_MT_POSITION_X/Y)
|
||||
if self.abs.bits() & abs != 0 {
|
||||
do_ioctl!(eviocgabs(self.fd, idx as u32, &mut self.state.abs_vals[idx as usize]));
|
||||
do_ioctl!(eviocgabs(
|
||||
self.fd,
|
||||
idx as u32,
|
||||
&mut self.state.abs_vals[idx as usize]
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.ty.contains(Types::SWITCH) {
|
||||
do_ioctl!(eviocgsw(self.fd, transmute::<&mut [u32], &mut [u8]>(self.state.switch_vals.as_mut_slice())));
|
||||
do_ioctl!(eviocgsw(
|
||||
self.fd,
|
||||
transmute::<&mut [u32], &mut [u8]>(self.state.switch_vals.as_mut_slice())
|
||||
));
|
||||
}
|
||||
if self.ty.contains(Types::LED) {
|
||||
do_ioctl!(eviocgled(self.fd, transmute::<&mut [u32], &mut [u8]>(self.state.led_vals.as_mut_slice())));
|
||||
do_ioctl!(eviocgled(
|
||||
self.fd,
|
||||
transmute::<&mut [u32], &mut [u8]>(self.state.led_vals.as_mut_slice())
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -823,7 +911,7 @@ impl Device {
|
|||
for (idx, event) in self.pending_events[self.last_seen..].iter().enumerate() {
|
||||
if event._type == SYN_DROPPED as u16 {
|
||||
drop_from = Some(idx);
|
||||
break
|
||||
break;
|
||||
}
|
||||
}
|
||||
// FIXME: see if we can *not* drop EV_REL events. EV_REL doesn't have any state, so
|
||||
|
@ -839,16 +927,18 @@ impl Device {
|
|||
}
|
||||
self.pending_events.truncate(prev_report);
|
||||
} else {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Alright, pending_events is in a sane state. Now, let's sync the local state. We will
|
||||
// create a phony packet that contains deltas from the previous device state to the current
|
||||
// device state.
|
||||
let old_state = self.state.clone();
|
||||
try!(self.sync_state());
|
||||
self.sync_state()?;
|
||||
let mut time = unsafe { std::mem::zeroed() };
|
||||
unsafe { clock_gettime(self.clock, &mut time); }
|
||||
unsafe {
|
||||
clock_gettime(self.clock, &mut time);
|
||||
}
|
||||
let time = libc::timeval {
|
||||
tv_sec: time.tv_sec,
|
||||
tv_usec: time.tv_nsec / 1000,
|
||||
|
@ -892,7 +982,11 @@ impl Device {
|
|||
time: time,
|
||||
_type: Types::SWITCH.number(),
|
||||
code: idx as u16,
|
||||
value: if self.state.switch_vals[idx as usize] { 1 } else { 0 },
|
||||
value: if self.state.switch_vals[idx as usize] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -907,7 +1001,11 @@ impl Device {
|
|||
time: time,
|
||||
_type: Types::LED.number(),
|
||||
code: idx as u16,
|
||||
value: if self.state.led_vals[idx as usize] { 1 } else { 0 },
|
||||
value: if self.state.led_vals[idx as usize] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -929,10 +1027,11 @@ impl Device {
|
|||
buf.reserve(20);
|
||||
let pre_len = buf.len();
|
||||
let sz = unsafe {
|
||||
libc::read(self.fd,
|
||||
buf.as_mut_ptr()
|
||||
.offset(pre_len as isize) as *mut libc::c_void,
|
||||
(size_of::<raw::input_event>() * (buf.capacity() - pre_len)) as libc::size_t)
|
||||
libc::read(
|
||||
self.fd,
|
||||
buf.as_mut_ptr().offset(pre_len as isize) as *mut libc::c_void,
|
||||
(size_of::<raw::input_event>() * (buf.capacity() - pre_len)) as libc::size_t,
|
||||
)
|
||||
};
|
||||
if sz == -1 {
|
||||
let errno = ::nix::errno::Errno::last();
|
||||
|
@ -952,7 +1051,7 @@ impl Device {
|
|||
|
||||
/// Exposes the raw evdev events without doing synchronization on SYN_DROPPED.
|
||||
pub fn events_no_sync(&mut self) -> Result<RawEvents, Error> {
|
||||
try!(self.fill_events());
|
||||
self.fill_events()?;
|
||||
Ok(RawEvents::new(self))
|
||||
}
|
||||
|
||||
|
@ -960,8 +1059,8 @@ impl Device {
|
|||
///
|
||||
/// Will insert "fake" events
|
||||
pub fn events(&mut self) -> Result<RawEvents, Error> {
|
||||
try!(self.fill_events());
|
||||
try!(self.compensate_dropped());
|
||||
self.fill_events()?;
|
||||
self.compensate_dropped()?;
|
||||
|
||||
Ok(RawEvents(self))
|
||||
}
|
||||
|
|
88
src/raw.rs
88
src/raw.rs
|
@ -1,3 +1,8 @@
|
|||
use nix::{
|
||||
convert_ioctl_res, ioctl_read, ioctl_read_buf, ioctl_write_int, ioctl_write_ptr,
|
||||
request_code_read,
|
||||
};
|
||||
|
||||
ioctl_read!(eviocgeffects, b'E', 0x84, ::libc::c_int);
|
||||
ioctl_read!(eviocgid, b'E', 0x02, /*struct*/ input_id);
|
||||
ioctl_read!(eviocgkeycode, b'E', 0x04, [::libc::c_uint; 2]);
|
||||
|
@ -19,12 +24,17 @@ pub struct input_event {
|
|||
pub value: i32,
|
||||
}
|
||||
impl ::std::default::Default for input_event {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
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)
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,8 +76,7 @@ impl Union_Unnamed16 {
|
|||
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] {
|
||||
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))
|
||||
}
|
||||
|
@ -77,7 +86,9 @@ impl Union_Unnamed16 {
|
|||
}
|
||||
}
|
||||
impl ::std::default::Default for Union_Unnamed16 {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -91,7 +102,9 @@ pub struct input_absinfo {
|
|||
pub resolution: i32,
|
||||
}
|
||||
impl ::std::default::Default for input_absinfo {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -103,7 +116,9 @@ pub struct input_keymap_entry {
|
|||
pub scancode: [u8; 32usize],
|
||||
}
|
||||
impl ::std::default::Default for input_keymap_entry {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -112,7 +127,9 @@ pub struct ff_replay {
|
|||
pub delay: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_replay {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -121,7 +138,9 @@ pub struct ff_trigger {
|
|||
pub interval: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_trigger {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -132,7 +151,9 @@ pub struct ff_envelope {
|
|||
pub fade_level: u16,
|
||||
}
|
||||
impl ::std::default::Default for ff_envelope {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -141,7 +162,9 @@ pub struct ff_constant_effect {
|
|||
pub envelope: ff_envelope,
|
||||
}
|
||||
impl ::std::default::Default for ff_constant_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -151,7 +174,9 @@ pub struct ff_ramp_effect {
|
|||
pub envelope: ff_envelope,
|
||||
}
|
||||
impl ::std::default::Default for ff_ramp_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -164,7 +189,9 @@ pub struct ff_condition_effect {
|
|||
pub center: i16,
|
||||
}
|
||||
impl ::std::default::Default for ff_condition_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -179,7 +206,9 @@ pub struct ff_periodic_effect {
|
|||
pub custom_data: *mut i16,
|
||||
}
|
||||
impl ::std::default::Default for ff_periodic_effect {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
fn default() -> Self {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -188,7 +217,9 @@ pub struct ff_rumble_effect {
|
|||
pub weak_magnitude: u16,
|
||||
}
|
||||
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, b'E', 0x06, u8);
|
||||
|
@ -206,10 +237,27 @@ ioctl_write_int!(eviocgrab, b'E', 0x90);
|
|||
ioctl_write_int!(eviocrevoke, b'E', 0x91);
|
||||
ioctl_write_int!(eviocsclockid, 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::libc::ioctl(fd, request_code_read!(b'E', 0x20 + ev, len), buf))
|
||||
pub unsafe fn eviocgbit(
|
||||
fd: ::libc::c_int,
|
||||
ev: u32,
|
||||
len: ::libc::c_int,
|
||||
buf: *mut u8,
|
||||
) -> ::nix::Result<i32> {
|
||||
convert_ioctl_res!(::nix::libc::ioctl(
|
||||
fd,
|
||||
request_code_read!(b'E', 0x20 + ev, len),
|
||||
buf
|
||||
))
|
||||
}
|
||||
|
||||
pub unsafe fn eviocgabs(fd: ::libc::c_int, abs: u32, buf: *mut input_absinfo) -> ::nix::Result<i32> {
|
||||
convert_ioctl_res!(::nix::libc::ioctl(fd, request_code_read!(b'E', 0x40 + abs, ::std::mem::size_of::<input_absinfo>()), buf))
|
||||
pub unsafe fn eviocgabs(
|
||||
fd: ::libc::c_int,
|
||||
abs: u32,
|
||||
buf: *mut input_absinfo,
|
||||
) -> ::nix::Result<i32> {
|
||||
convert_ioctl_res!(::nix::libc::ioctl(
|
||||
fd,
|
||||
request_code_read!(b'E', 0x40 + abs, ::std::mem::size_of::<input_absinfo>()),
|
||||
buf
|
||||
))
|
||||
}
|
||||
|
|
1037
src/scancodes.rs
1037
src/scancodes.rs
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue