Use typed ioctl calls + other misc changes (#29)
* Use typed ioctl calls * Make enumerate() return an iterator instead of a vec * Fix(?) events() behavior * read() into a buf of mem::MaybeUninit * Add Device.wait_ready() * impl AsRawFd for Device * Add remaining ioctls
This commit is contained in:
parent
73fd0ae421
commit
2e2d6f1468
3 changed files with 120 additions and 110 deletions
|
@ -1,16 +1,13 @@
|
||||||
// Similar to the evtest tool.
|
// Similar to the evtest tool.
|
||||||
|
|
||||||
extern crate evdev;
|
|
||||||
|
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut args = std::env::args_os();
|
let mut args = std::env::args_os();
|
||||||
let mut d;
|
let mut d = if args.len() > 1 {
|
||||||
if args.len() > 1 {
|
evdev::Device::open(&args.nth(1).unwrap()).unwrap()
|
||||||
d = evdev::Device::open(&args.nth(1).unwrap()).unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
let mut devices = evdev::enumerate();
|
let mut devices = evdev::enumerate().collect::<Vec<_>>();
|
||||||
for (i, d) in devices.iter().enumerate() {
|
for (i, d) in devices.iter().enumerate() {
|
||||||
println!("{}: {:?}", i, d.name());
|
println!("{}: {:?}", i, d.name());
|
||||||
}
|
}
|
||||||
|
@ -18,13 +15,14 @@ fn main() {
|
||||||
let _ = std::io::stdout().flush();
|
let _ = std::io::stdout().flush();
|
||||||
let mut chosen = String::new();
|
let mut chosen = String::new();
|
||||||
std::io::stdin().read_line(&mut chosen).unwrap();
|
std::io::stdin().read_line(&mut chosen).unwrap();
|
||||||
d = devices.swap_remove(chosen.trim().parse::<usize>().unwrap());
|
devices.swap_remove(chosen.trim().parse::<usize>().unwrap())
|
||||||
}
|
};
|
||||||
println!("{}", d);
|
println!("{}", d);
|
||||||
println!("Events:");
|
println!("Events:");
|
||||||
loop {
|
loop {
|
||||||
for ev in d.events_no_sync().unwrap() {
|
for ev in d.events_no_sync().unwrap() {
|
||||||
println!("{:?}", ev);
|
println!("{:?}", ev);
|
||||||
}
|
}
|
||||||
|
d.wait_ready().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
170
src/lib.rs
170
src/lib.rs
|
@ -41,7 +41,7 @@ mod scancodes;
|
||||||
use fixedbitset::FixedBitSet;
|
use fixedbitset::FixedBitSet;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::mem::size_of;
|
use std::mem;
|
||||||
use std::os::unix::{
|
use std::os::unix::{
|
||||||
fs::OpenOptionsExt,
|
fs::OpenOptionsExt,
|
||||||
io::{AsRawFd, RawFd},
|
io::{AsRawFd, RawFd},
|
||||||
|
@ -187,6 +187,12 @@ pub struct Device {
|
||||||
state: DeviceState,
|
state: DeviceState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for Device {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.file.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const fn bus_name(x: u16) -> &'static str {
|
const fn bus_name(x: u16) -> &'static str {
|
||||||
match x {
|
match x {
|
||||||
0x1 => "PCI",
|
0x1 => "PCI",
|
||||||
|
@ -320,10 +326,6 @@ impl std::fmt::Display for Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
pub fn fd(&self) -> RawFd {
|
|
||||||
self.file.as_raw_fd()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn events_supported(&self) -> Types {
|
pub fn events_supported(&self) -> Types {
|
||||||
self.ty
|
self.ty
|
||||||
}
|
}
|
||||||
|
@ -388,7 +390,12 @@ impl Device {
|
||||||
&self.state
|
&self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open(path: &dyn AsRef<Path>) -> Result<Device, Error> {
|
#[inline(always)]
|
||||||
|
pub fn open(path: impl AsRef<Path>) -> Result<Device, Error> {
|
||||||
|
Self::_open(path.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _open(path: &Path) -> Result<Device, Error> {
|
||||||
let mut options = OpenOptions::new();
|
let mut options = OpenOptions::new();
|
||||||
|
|
||||||
// Try to load read/write, then fall back to read-only.
|
// Try to load read/write, then fall back to read-only.
|
||||||
|
@ -399,14 +406,9 @@ impl Device {
|
||||||
.open(path)
|
.open(path)
|
||||||
.or_else(|_| options.write(false).open(path))?;
|
.or_else(|_| options.write(false).open(path))?;
|
||||||
|
|
||||||
let mut bits: u32 = 0;
|
let mut ty = 0;
|
||||||
let mut bits64: u64 = 0;
|
unsafe { eviocgbit_type(file.as_raw_fd(), &mut ty)? };
|
||||||
|
let ty = Types::from_bits(ty).expect("evdev: unexpected type bits! report a bug");
|
||||||
unsafe {
|
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
|
||||||
eviocgbit(file.as_raw_fd(), 0, bits_as_u8_slice)?;
|
|
||||||
}
|
|
||||||
let ty = Types::from_bits(bits).expect("evdev: unexpected type bits! report a bug");
|
|
||||||
|
|
||||||
let name = ioctl_get_cstring(eviocgname, file.as_raw_fd());
|
let name = ioctl_get_cstring(eviocgname, file.as_raw_fd());
|
||||||
let phys = ioctl_get_cstring(eviocgphys, file.as_raw_fd());
|
let phys = ioctl_get_cstring(eviocgphys, file.as_raw_fd());
|
||||||
|
@ -427,11 +429,11 @@ impl Device {
|
||||||
(driver_version & 0xff) as u8,
|
(driver_version & 0xff) as u8,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut props = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
eviocgprop(file.as_raw_fd(), &mut props)?;
|
||||||
eviocgprop(file.as_raw_fd(), bits_as_u8_slice)?;
|
|
||||||
} // FIXME: handle old kernel
|
} // FIXME: handle old kernel
|
||||||
let props = Props::from_bits(bits).expect("evdev: unexpected prop bits! report a bug");
|
let props = Props::from_bits(props).expect("evdev: unexpected prop bits! report a bug");
|
||||||
|
|
||||||
let mut state = DeviceState::default();
|
let mut state = DeviceState::default();
|
||||||
|
|
||||||
|
@ -442,11 +444,7 @@ impl Device {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (_, supported_keys_as_u8_slice, _) = key_slice.align_to_mut();
|
let (_, supported_keys_as_u8_slice, _) = key_slice.align_to_mut();
|
||||||
debug_assert!(supported_keys_as_u8_slice.len() == Key::MAX / 8);
|
debug_assert!(supported_keys_as_u8_slice.len() == Key::MAX / 8);
|
||||||
eviocgbit(
|
eviocgbit_key(file.as_raw_fd(), supported_keys_as_u8_slice)?;
|
||||||
file.as_raw_fd(),
|
|
||||||
Types::KEY.number(),
|
|
||||||
supported_keys_as_u8_slice,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
let key_vals = FixedBitSet::with_capacity(Key::MAX);
|
let key_vals = FixedBitSet::with_capacity(Key::MAX);
|
||||||
debug_assert!(key_vals.len() % 8 == 0);
|
debug_assert!(key_vals.len() % 8 == 0);
|
||||||
|
@ -458,62 +456,48 @@ impl Device {
|
||||||
};
|
};
|
||||||
|
|
||||||
let supported_relative = if ty.contains(Types::RELATIVE) {
|
let supported_relative = if ty.contains(Types::RELATIVE) {
|
||||||
unsafe {
|
let mut rel = 0;
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
unsafe { eviocgbit_relative(file.as_raw_fd(), &mut rel)? };
|
||||||
eviocgbit(file.as_raw_fd(), Types::RELATIVE.number(), bits_as_u8_slice)?;
|
Some(RelativeAxis::from_bits(rel).expect("evdev: unexpected rel bits! report a bug"))
|
||||||
}
|
|
||||||
Some(RelativeAxis::from_bits(bits).expect("evdev: unexpected rel bits! report a bug"))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let supported_absolute = if ty.contains(Types::ABSOLUTE) {
|
let supported_absolute = if ty.contains(Types::ABSOLUTE) {
|
||||||
unsafe {
|
let mut abs = 0;
|
||||||
let (_, bits64_as_u8_slice, _) = std::slice::from_mut(&mut bits64).align_to_mut();
|
unsafe { eviocgbit_absolute(file.as_raw_fd(), &mut abs)? };
|
||||||
eviocgbit(
|
|
||||||
file.as_raw_fd(),
|
|
||||||
Types::ABSOLUTE.number(),
|
|
||||||
bits64_as_u8_slice,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
state.abs_vals = Some(vec![input_absinfo_default(); 0x3f]);
|
state.abs_vals = Some(vec![input_absinfo_default(); 0x3f]);
|
||||||
Some(AbsoluteAxis::from_bits(bits64).expect("evdev: unexpected abs bits! report a bug"))
|
Some(AbsoluteAxis::from_bits(abs).expect("evdev: unexpected abs bits! report a bug"))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let supported_switch = if ty.contains(Types::SWITCH) {
|
let supported_switch = if ty.contains(Types::SWITCH) {
|
||||||
unsafe {
|
let mut switch = 0;
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
unsafe { eviocgbit_switch(file.as_raw_fd(), &mut switch)? };
|
||||||
eviocgbit(file.as_raw_fd(), Types::SWITCH.number(), bits_as_u8_slice)?;
|
|
||||||
}
|
|
||||||
state.switch_vals = Some(FixedBitSet::with_capacity(0x10));
|
state.switch_vals = Some(FixedBitSet::with_capacity(0x10));
|
||||||
|
|
||||||
Some(Switch::from_bits(bits).expect("evdev: unexpected switch bits! report a bug"))
|
Some(Switch::from_bits(switch).expect("evdev: unexpected switch bits! report a bug"))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let supported_led = if ty.contains(Types::LED) {
|
let supported_led = if ty.contains(Types::LED) {
|
||||||
unsafe {
|
let mut led = 0;
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
unsafe { eviocgbit_led(file.as_raw_fd(), &mut led)? };
|
||||||
eviocgbit(file.as_raw_fd(), Types::LED.number(), bits_as_u8_slice)?;
|
|
||||||
}
|
|
||||||
let led_vals = FixedBitSet::with_capacity(0x10);
|
let led_vals = FixedBitSet::with_capacity(0x10);
|
||||||
debug_assert!(led_vals.len() % 8 == 0);
|
debug_assert!(led_vals.len() % 8 == 0);
|
||||||
state.led_vals = Some(led_vals);
|
state.led_vals = Some(led_vals);
|
||||||
|
|
||||||
Some(Led::from_bits(bits).expect("evdev: unexpected led bits! report a bug"))
|
Some(Led::from_bits(led).expect("evdev: unexpected led bits! report a bug"))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let supported_misc = if ty.contains(Types::MISC) {
|
let supported_misc = if ty.contains(Types::MISC) {
|
||||||
unsafe {
|
let mut misc = 0;
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
unsafe { eviocgbit_misc(file.as_raw_fd(), &mut misc)? };
|
||||||
eviocgbit(file.as_raw_fd(), Types::MISC.number(), bits_as_u8_slice)?;
|
Some(Misc::from_bits(misc).expect("evdev: unexpected misc bits! report a bug"))
|
||||||
}
|
|
||||||
Some(Misc::from_bits(bits).expect("evdev: unexpected misc bits! report a bug"))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -521,11 +505,9 @@ impl Device {
|
||||||
//unsafe { eviocgbit(file.as_raw_fd(), ffs(FORCEFEEDBACK.bits()), 0x7f, bits_as_u8_slice)?; }
|
//unsafe { eviocgbit(file.as_raw_fd(), ffs(FORCEFEEDBACK.bits()), 0x7f, bits_as_u8_slice)?; }
|
||||||
|
|
||||||
let supported_snd = if ty.contains(Types::SOUND) {
|
let supported_snd = if ty.contains(Types::SOUND) {
|
||||||
unsafe {
|
let mut snd = 0;
|
||||||
let (_, bits_as_u8_slice, _) = std::slice::from_mut(&mut bits).align_to_mut();
|
unsafe { eviocgbit_sound(file.as_raw_fd(), &mut snd)? };
|
||||||
eviocgbit(file.as_raw_fd(), Types::SOUND.number(), bits_as_u8_slice)?;
|
Some(Sound::from_bits(snd).expect("evdev: unexpected sound bits! report a bug"))
|
||||||
}
|
|
||||||
Some(Sound::from_bits(bits).expect("evdev: unexpected sound bits! report a bug"))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -560,11 +542,12 @@ 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> {
|
||||||
|
let fd = self.as_raw_fd();
|
||||||
if let Some(key_vals) = &mut self.state.key_vals {
|
if let Some(key_vals) = &mut self.state.key_vals {
|
||||||
unsafe {
|
unsafe {
|
||||||
let key_slice = key_vals.as_mut_slice();
|
let key_slice = key_vals.as_mut_slice();
|
||||||
let (_, key_vals_as_u8_slice, _) = key_slice.align_to_mut();
|
let (_, key_vals_as_u8_slice, _) = key_slice.align_to_mut();
|
||||||
eviocgkey(self.file.as_raw_fd(), key_vals_as_u8_slice)?;
|
eviocgkey(fd, key_vals_as_u8_slice)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,7 +562,7 @@ impl Device {
|
||||||
// the abs data seems to be fine (tested ABS_MT_POSITION_X/Y)
|
// the abs data seems to be fine (tested ABS_MT_POSITION_X/Y)
|
||||||
if supported_abs.contains(abs) {
|
if supported_abs.contains(abs) {
|
||||||
unsafe {
|
unsafe {
|
||||||
eviocgabs(self.file.as_raw_fd(), idx as u32, &mut abs_vals[idx])?;
|
eviocgabs(fd, idx as u32, &mut abs_vals[idx])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -589,7 +572,7 @@ impl Device {
|
||||||
unsafe {
|
unsafe {
|
||||||
let switch_slice = switch_vals.as_mut_slice();
|
let switch_slice = switch_vals.as_mut_slice();
|
||||||
let (_, switch_vals_as_u8_slice, _) = switch_slice.align_to_mut();
|
let (_, switch_vals_as_u8_slice, _) = switch_slice.align_to_mut();
|
||||||
eviocgsw(self.file.as_raw_fd(), switch_vals_as_u8_slice)?;
|
eviocgsw(fd, switch_vals_as_u8_slice)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +580,7 @@ impl Device {
|
||||||
unsafe {
|
unsafe {
|
||||||
let led_slice = led_vals.as_mut_slice();
|
let led_slice = led_vals.as_mut_slice();
|
||||||
let (_, led_vals_as_u8_slice, _) = led_slice.align_to_mut();
|
let (_, led_vals_as_u8_slice, _) = led_slice.align_to_mut();
|
||||||
eviocgled(self.file.as_raw_fd(), led_vals_as_u8_slice)?;
|
eviocgled(fd, led_vals_as_u8_slice)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,18 +700,23 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_events(&mut self) -> Result<(), Error> {
|
fn fill_events(&mut self) -> Result<(), Error> {
|
||||||
|
let fd = self.as_raw_fd();
|
||||||
let buf = &mut self.pending_events;
|
let buf = &mut self.pending_events;
|
||||||
loop {
|
loop {
|
||||||
buf.reserve(20);
|
buf.reserve(20);
|
||||||
// TODO: use spare_capacity_mut or split_at_spare_mut when they stabilize
|
// TODO: use Vec::spare_capacity_mut or Vec::split_at_spare_mut when they stabilize
|
||||||
let pre_len = buf.len();
|
let spare_capacity = vec_spare_capacity_mut(buf);
|
||||||
let capacity = buf.capacity();
|
let (_, uninit_buf, _) =
|
||||||
let (_, unsafe_buf_slice, _) =
|
unsafe { spare_capacity.align_to_mut::<mem::MaybeUninit<u8>>() };
|
||||||
unsafe { buf.get_unchecked_mut(pre_len..capacity).align_to_mut() };
|
|
||||||
|
|
||||||
match nix::unistd::read(self.file.as_raw_fd(), unsafe_buf_slice) {
|
// use libc::read instead of nix::unistd::read b/c we need to pass an uninitialized buf
|
||||||
|
let res = unsafe { libc::read(fd, uninit_buf.as_mut_ptr() as _, uninit_buf.len()) };
|
||||||
|
match nix::errno::Errno::result(res) {
|
||||||
Ok(bytes_read) => unsafe {
|
Ok(bytes_read) => unsafe {
|
||||||
buf.set_len(pre_len + (bytes_read / size_of::<raw::input_event>()));
|
let pre_len = buf.len();
|
||||||
|
buf.set_len(
|
||||||
|
pre_len + (bytes_read as usize / mem::size_of::<raw::input_event>()),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e == nix::Error::Sys(::nix::errno::Errno::EAGAIN) {
|
if e == nix::Error::Sys(::nix::errno::Errno::EAGAIN) {
|
||||||
|
@ -755,7 +743,14 @@ impl Device {
|
||||||
self.fill_events()?;
|
self.fill_events()?;
|
||||||
self.compensate_dropped()?;
|
self.compensate_dropped()?;
|
||||||
|
|
||||||
Ok(RawEvents(self))
|
Ok(RawEvents::new(self))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_ready(&self) -> nix::Result<()> {
|
||||||
|
use nix::poll;
|
||||||
|
let mut pfd = poll::PollFd::new(self.as_raw_fd(), poll::PollFlags::POLLIN);
|
||||||
|
poll::poll(std::slice::from_mut(&mut pfd), -1)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,19 +784,28 @@ impl<'a> Iterator for RawEvents<'a> {
|
||||||
/// Crawls `/dev/input` for evdev devices.
|
/// Crawls `/dev/input` for evdev devices.
|
||||||
///
|
///
|
||||||
/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
|
/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
|
||||||
/// an empty vector or omits the devices that could not be opened.
|
/// an empty iterator or omits the devices that could not be opened.
|
||||||
pub fn enumerate() -> Vec<Device> {
|
pub fn enumerate() -> EnumerateDevices {
|
||||||
let mut res = Vec::new();
|
EnumerateDevices {
|
||||||
if let Ok(dir) = std::fs::read_dir("/dev/input") {
|
readdir: std::fs::read_dir("/dev/input").ok(),
|
||||||
for entry in dir {
|
}
|
||||||
if let Ok(entry) = entry {
|
}
|
||||||
if let Ok(dev) = Device::open(&entry.path()) {
|
|
||||||
res.push(dev)
|
pub struct EnumerateDevices {
|
||||||
|
readdir: Option<std::fs::ReadDir>,
|
||||||
|
}
|
||||||
|
impl Iterator for EnumerateDevices {
|
||||||
|
type Item = Device;
|
||||||
|
fn next(&mut self) -> Option<Device> {
|
||||||
|
let readdir = self.readdir.as_mut()?;
|
||||||
|
loop {
|
||||||
|
if let Ok(entry) = readdir.next()? {
|
||||||
|
if let Ok(dev) = Device::open(entry.path()) {
|
||||||
|
return Some(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A safe Rust version of clock_gettime against CLOCK_REALTIME
|
/// A safe Rust version of clock_gettime against CLOCK_REALTIME
|
||||||
|
@ -814,6 +818,18 @@ fn into_timeval(time: &SystemTime) -> Result<libc::timeval, std::time::SystemTim
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A copy of the unstable Vec::spare_capacity_mut
|
||||||
|
#[inline]
|
||||||
|
fn vec_spare_capacity_mut<T>(v: &mut Vec<T>) -> &mut [mem::MaybeUninit<T>] {
|
||||||
|
let (len, cap) = (v.len(), v.capacity());
|
||||||
|
unsafe {
|
||||||
|
std::slice::from_raw_parts_mut(
|
||||||
|
v.as_mut_ptr().add(len) as *mut mem::MaybeUninit<T>,
|
||||||
|
cap - len,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
|
46
src/raw.rs
46
src/raw.rs
|
@ -35,7 +35,7 @@ ioctl_write_ptr!(eviocsrep, b'E', 0x03, [::libc::c_uint; 2]);
|
||||||
ioctl_read_buf!(eviocgname, b'E', 0x06, u8);
|
ioctl_read_buf!(eviocgname, b'E', 0x06, u8);
|
||||||
ioctl_read_buf!(eviocgphys, b'E', 0x07, u8);
|
ioctl_read_buf!(eviocgphys, b'E', 0x07, u8);
|
||||||
ioctl_read_buf!(eviocguniq, b'E', 0x08, u8);
|
ioctl_read_buf!(eviocguniq, b'E', 0x08, u8);
|
||||||
ioctl_read_buf!(eviocgprop, b'E', 0x09, u8);
|
ioctl_read!(eviocgprop, b'E', 0x09, u32);
|
||||||
ioctl_read_buf!(eviocgmtslots, b'E', 0x0a, u8);
|
ioctl_read_buf!(eviocgmtslots, b'E', 0x0a, u8);
|
||||||
ioctl_read_buf!(eviocgkey, b'E', 0x18, u8);
|
ioctl_read_buf!(eviocgkey, b'E', 0x18, u8);
|
||||||
ioctl_read_buf!(eviocgled, b'E', 0x19, u8);
|
ioctl_read_buf!(eviocgled, b'E', 0x19, u8);
|
||||||
|
@ -47,32 +47,28 @@ ioctl_write_int!(eviocgrab, b'E', 0x90);
|
||||||
ioctl_write_int!(eviocrevoke, b'E', 0x91);
|
ioctl_write_int!(eviocrevoke, b'E', 0x91);
|
||||||
ioctl_write_int!(eviocsclockid, b'E', 0xa0);
|
ioctl_write_int!(eviocsclockid, b'E', 0xa0);
|
||||||
|
|
||||||
/// ioctl: "get event bits"
|
macro_rules! eviocgbit_ioctl {
|
||||||
///
|
($mac:ident!($name:ident, $ev:ident, $ty:ty)) => {
|
||||||
/// `ev` should be one of the "Event types" as defined in the Linux kernel headers.
|
eviocgbit_ioctl!($mac!($name, $crate::Types::$ev.number::<u32>(), $ty));
|
||||||
/// In modern (5.11) kernels these are in `include/uapi/linux/input-event-codes.h`, and in older
|
};
|
||||||
/// kernels these defines can be found in `include/uapi/linux/input.h`
|
($mac:ident!($name:ident, $ev:expr, $ty:ty)) => {
|
||||||
///
|
$mac!($name, b'E', 0x20 + $ev, $ty);
|
||||||
/// # Panics
|
};
|
||||||
///
|
|
||||||
/// Calling this with a value greater than the kernel-defined `EV_MAX` (typically 0x1f) will panic.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// `ev` must be a valid event number otherwise the behavior is undefined.
|
|
||||||
pub unsafe fn eviocgbit(
|
|
||||||
fd: ::libc::c_int,
|
|
||||||
ev: u32,
|
|
||||||
buf: &mut [u8],
|
|
||||||
) -> ::nix::Result<c_int> {
|
|
||||||
assert!(ev <= 0x1f);
|
|
||||||
convert_ioctl_res!(::nix::libc::ioctl(
|
|
||||||
fd,
|
|
||||||
request_code_read!(b'E', 0x20 + ev, buf.len()),
|
|
||||||
buf.as_mut_ptr()
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_type, 0, u32));
|
||||||
|
eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_key, KEY, u8));
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_relative, RELATIVE, u32));
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_absolute, ABSOLUTE, u64));
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_misc, MISC, u32));
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_switch, SWITCH, u32));
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_led, LED, u32));
|
||||||
|
eviocgbit_ioctl!(ioctl_read!(eviocgbit_sound, SOUND, u32));
|
||||||
|
eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_repeat, REPEAT, u8));
|
||||||
|
eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_ff, FORCEFEEDBACK, u8));
|
||||||
|
eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_power, POWER, u8));
|
||||||
|
eviocgbit_ioctl!(ioctl_read_buf!(eviocgbit_ffstatus, FORCEFEEDBACKSTATUS, u8));
|
||||||
|
|
||||||
/// ioctl: "get abs value/limits"
|
/// ioctl: "get abs value/limits"
|
||||||
///
|
///
|
||||||
/// `abs` should be one of the "Absolute axes" values defined in the Linux kernel headers.
|
/// `abs` should be one of the "Absolute axes" values defined in the Linux kernel headers.
|
||||||
|
|
Loading…
Reference in a new issue