input-linux-0.6.0/.cargo_vcs_info.json0000644000000001360000000000100133330ustar { "git": { "sha1": "d6fff21d61d13fc36bf5c04c0bd21bf15f74b11f" }, "path_in_vcs": "" }input-linux-0.6.0/COPYING000064400000000000000000000020321046102023000131530ustar 00000000000000Copyright (c) 2017 arcnmx Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. input-linux-0.6.0/Cargo.lock0000644000000177250000000000100113220ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "futures-core" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-sink" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "input-linux" version = "0.6.0" dependencies = [ "bytes", "input-linux-sys", "nix", "serde", "tokio-util 0.6.10", "tokio-util 0.7.7", ] [[package]] name = "input-linux-sys" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a687a25a4973027df9153753a5589f97fe1e958f694a34eea5606ae65299ab8" dependencies = [ "libc", "nix", ] [[package]] name = "libc" version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "memoffset" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] [[package]] name = "nix" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ "bitflags", "cfg-if", "libc", "memoffset", "pin-utils", "static_assertions", ] [[package]] name = "once_cell" version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "pin-project-lite" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] [[package]] name = "serde" version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tokio" version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" dependencies = [ "autocfg", "pin-project-lite", "windows-sys", ] [[package]] name = "tokio-util" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ "bytes", "futures-core", "futures-sink", "log", "pin-project-lite", "tokio", ] [[package]] name = "tokio-util" version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", "tracing", ] [[package]] name = "tracing" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] [[package]] name = "unicode-ident" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "windows-sys" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" input-linux-0.6.0/Cargo.toml0000644000000032200000000000100113260ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "input-linux" version = "0.6.0" authors = ["arcnmx"] include = [ "src/**/*.rs", "/README*", "/COPYING*", ] description = "evdev and uinput" documentation = "http://docs.rs/input-linux/*/input_linux" readme = "README.md" keywords = [ "evdev", "uinput", "linux", "input", ] license = "MIT" repository = "https://github.com/arcnmx/input-linux-rs" [package.metadata.docs.rs] features = [ "dox", "tokio-util-0_6", "tokio-util-0_7", "serde", ] [dependencies.bytes] version = "1" optional = true [dependencies.input-linux-sys] version = "0.8" [dependencies.nix] version = "0.26" [dependencies.serde] version = "1" features = ["derive"] optional = true [dependencies.tokio-util-0_6] version = "0.6" features = ["codec"] optional = true default-features = false package = "tokio-util" [dependencies.tokio-util-0_7] version = "0.7" features = ["codec"] optional = true default-features = false package = "tokio-util" [features] codec = ["bytes"] dox = [] serde = ["dep:serde"] tokio-util-0_6 = [ "dep:tokio-util-0_6", "codec", "bytes", ] tokio-util-0_7 = [ "dep:tokio-util-0_7", "codec", "bytes", ] unstable = [] input-linux-0.6.0/Cargo.toml.orig000064400000000000000000000020661046102023000150160ustar 00000000000000[package] name = "input-linux" version = "0.6.0" authors = ["arcnmx"] edition = "2018" description = "evdev and uinput" keywords = ["evdev", "uinput", "linux", "input"] documentation = "http://docs.rs/input-linux/*/input_linux" repository = "https://github.com/arcnmx/input-linux-rs" readme = "README.md" license = "MIT" include = [ "src/**/*.rs", "/README*", "/COPYING*", ] [package.metadata.docs.rs] features = ["dox", "tokio-util-0_6", "tokio-util-0_7", "serde"] [dependencies] input-linux-sys = "0.8" nix = "0.26" tokio-util-0_7 = { package = "tokio-util", version = "0.7", default-features = false, features = ["codec"], optional = true } tokio-util-0_6 = { package = "tokio-util", version = "0.6", default-features = false, features = ["codec"], optional = true } bytes = { version = "1", optional = true } serde = { version = "1", features = ["derive"], optional = true } [features] tokio-util-0_6 = ["dep:tokio-util-0_6", "codec", "bytes"] tokio-util-0_7 = ["dep:tokio-util-0_7", "codec", "bytes"] codec = ["bytes"] serde = ["dep:serde"] unstable = [] dox = [] input-linux-0.6.0/README.md000064400000000000000000000012301046102023000133760ustar 00000000000000# input-linux [![release-badge][]][cargo] [![docs-badge][]][docs] [![license-badge][]][license] `input-linux` is a Rust client for evdev and uinput on Linux. ## [Documentation][docs] See the [documentation][docs] for up to date information. [release-badge]: https://img.shields.io/crates/v/input-linux.svg?style=flat-square [cargo]: https://crates.io/crates/input-linux [docs-badge]: https://img.shields.io/badge/API-docs-blue.svg?style=flat-square [docs]: https://docs.rs/input-linux/*/input_linux/ [license-badge]: https://img.shields.io/badge/license-MIT-ff69b4.svg?style=flat-square [license]: https://github.com/arcnmx/input-linux-rs/blob/master/COPYING input-linux-0.6.0/src/bitmask.rs000064400000000000000000000124661046102023000147230ustar 00000000000000//! Bitmasks are a set of bits that can be indexed and queried by the values of //! various enum types. use std::fmt; use std::ops::{Deref, DerefMut}; use crate::EventKind; use crate::enum_iterator::{IterableEnum, EnumIterator}; /// A generic trait that can be used to index by a given type into a set of bits. pub trait BitmaskTrait { /// The underlying array storage data type. type Array: Sized; /// The type that the bitmask can be indexed by. type Index: Copy + IterableEnum; /// Empty default data. const ZERO: Self::Array; /// The default empty state of the bitmask. fn array_default() -> Self::Array; /// A representation of the bitmask as a slice of bytes. fn array_slice(array: &Self::Array) -> &[u8]; /// A mutable representation of the bitmask as a slice of bytes. fn array_slice_mut(array: &mut Self::Array) -> &mut [u8]; /// Computes a normalized index value. fn index(index: Self::Index) -> usize; /// Validates whether a given index is valid and in range for the bitmask. /// /// Dynamically allocated bitmasks may not be large enough to contain all indices. fn index_valid(_array: &Self::Array, _index: Self::Index) -> bool { true } } impl BitmaskTrait for Vec { type Array = Self; type Index = u16; const ZERO: Self = Vec::new(); fn array_default() -> Self::Array { vec![0u8; 0x10] } fn array_slice(array: &Self::Array) -> &[u8] { array } fn array_slice_mut(array: &mut Self::Array) -> &mut [u8] { array } fn index(index: Self::Index) -> usize { index as _ } fn index_valid(array: &Self::Array, index: Self::Index) -> bool { array.len() > index as usize } } /// A dynamically allocated bitmask. pub type BitmaskVec = Bitmask>; impl Bitmask> { /// Reallocate the bitmask to fit all valid code values for the given event /// type. pub fn resize(&mut self, kind: EventKind) { self.data_mut().resize((kind.count_bits().unwrap_or(0x80) + 7) / 8, 0); } } #[derive(Copy, Clone)] /// A set of bits that can be indexed by specific enum values. pub struct Bitmask { mask: T::Array, } impl Default for Bitmask { fn default() -> Self { Bitmask { mask: T::array_default(), } } } impl Bitmask { /// A new empty bitmask. pub const EMPTY: Self = Self { mask: T::ZERO, }; /// Extracts the underlying bitmask data. pub fn into_inner(self) -> T::Array { self.mask } /// Iterates over all set bits. pub fn iter(&self) -> BitmaskIterator { self.into_iter() } /// Borrows the underlying bitmask data. pub fn data(&self) -> &T::Array { &self.mask } /// Mutably borrows the underlying bitmask data. pub fn data_mut(&mut self) -> &mut T::Array { &mut self.mask } fn slice(&self) -> &[u8] { T::array_slice(&self.mask) } fn slice_mut(&mut self) -> &mut [u8] { T::array_slice_mut(&mut self.mask) } fn index(index: T::Index) -> (usize, usize) { let index = T::index(index); (index / 8, index % 8) } fn index_valid(&self, index: T::Index) -> bool { T::index_valid(&self.mask, index) } /// Unset all bits in the bitmask. pub fn clear(&mut self) { for b in self.slice_mut() { *b = 0; } } /// Gets the status of an index in the bitmask. pub fn get(&self, index: T::Index) -> bool { let (offset, shift) = Self::index(index); (self.slice()[offset] & (1u8 << shift)) != 0 } /// Sets the status of an index in the bitmask. pub fn insert(&mut self, index: T::Index) { let (offset, shift) = Self::index(index); let v = &mut self.slice_mut()[offset]; *v |= 1u8 << shift; } /// Clears the status of an index in the bitmask. pub fn remove(&mut self, index: T::Index) { let (offset, shift) = Self::index(index); let v = &mut self.slice_mut()[offset]; *v &= !(1u8 << shift); } /// Inverts the status of an index in the bitmask. pub fn toggle(&mut self, index: T::Index) { let (offset, shift) = Self::index(index); self.slice_mut()[offset] ^= 1u8 << shift; } /// Merges the provided indices into the bitmask. pub fn or>(&mut self, indices: I) { for index in indices { self.insert(index); } } } impl<'a, T: BitmaskTrait> IntoIterator for &'a Bitmask { type Item = T::Index; type IntoIter = BitmaskIterator<'a, T>; fn into_iter(self) -> Self::IntoIter { BitmaskIterator { mask: self, iter: T::Index::iter(), } } } /// An iterator over the set bits of a bitmask. pub struct BitmaskIterator<'a, T: BitmaskTrait + 'a> { mask: &'a Bitmask, iter: EnumIterator, } impl<'a, T: BitmaskTrait> Iterator for BitmaskIterator<'a, T> { type Item = T::Index; fn next(&mut self) -> Option { let mask = &self.mask; self.iter.by_ref().take_while(|i| mask.index_valid(*i)).find(|i| mask.get(*i)) } } impl fmt::Debug for Bitmask where T::Index: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list().entries(self.into_iter()).finish() } } impl Deref for Bitmask { type Target = [u8]; fn deref(&self) -> &Self::Target { self.slice() } } impl DerefMut for Bitmask { fn deref_mut(&mut self) -> &mut Self::Target { self.slice_mut() } } impl AsRef<[u8]> for Bitmask { fn as_ref(&self) -> &[u8] { self.slice() } } impl AsMut<[u8]> for Bitmask { fn as_mut(&mut self) -> &mut [u8] { self.slice_mut() } } input-linux-0.6.0/src/codec.rs000064400000000000000000000030631046102023000143370ustar 00000000000000#![allow(missing_docs)] use std::{io, mem, ptr}; use crate::sys::input_event; #[cfg(feature = "bytes")] use bytes::{BytesMut, BufMut}; use crate::InputEvent; pub struct EventCodec { _dummy: (), } impl EventCodec { pub const fn new() -> Self { EventCodec { _dummy: (), } } #[cfg(feature = "bytes")] #[cfg_attr(feature = "dox", doc(cfg(feature = "bytes")))] pub fn decode_bytes(&mut self, src: &mut BytesMut) -> Result, io::Error> { if src.len() >= mem::size_of::() { let src = src.split_to(mem::size_of::()); let event = unsafe { let mut event = mem::MaybeUninit::::uninit(); ptr::copy_nonoverlapping(src.as_ptr(), event.as_mut_ptr() as *mut u8, mem::size_of::()); InputEvent::from_raw(&*event.as_ptr()).map(|e| *e).map_err(From::from) }; event.map(Some) } else { Ok(None) } } #[cfg(feature = "bytes")] #[cfg_attr(feature = "dox", doc(cfg(feature = "bytes")))] pub fn encode_bytes(&mut self, item: InputEvent, dst: &mut BytesMut) -> Result<(), io::Error> { dst.reserve(mem::size_of::()); dst.put_slice(item.as_bytes()); Ok(()) } } #[cfg(feature = "tokio-util-0_6")] #[cfg_attr(feature = "dox", doc(cfg(feature = "tokio-util-0_6")))] mod tokio_util_impl_0_6 { use tokio_util_0_6::codec::{Encoder, Decoder}; include!("tokio_impl.rs"); } #[cfg(feature = "tokio-util-0_7")] #[cfg_attr(feature = "dox", doc(cfg(feature = "tokio-util-0_7")))] mod tokio_util_impl_0_7 { use tokio_util_0_7::codec::{Encoder, Decoder}; include!("tokio_impl.rs"); } input-linux-0.6.0/src/enum_iterator.rs000064400000000000000000000022711046102023000161370ustar 00000000000000//! Iteration over enum values. use std::marker::PhantomData; /// Allows [`EnumIterator`] to iterate over an enum type. pub trait IterableEnum: Sized { /// Given an index into the iterator, return the value and the next index. /// /// Iterators shall start by calling this with `0`. fn iter_next(v: usize) -> Option<(usize, Self)>; /// Instantiates an [`EnumIterator`] for an iterable type. fn iter() -> EnumIterator; } impl IterableEnum for u16 { fn iter_next(v: usize) -> Option<(usize, Self)> { if v < 0xffff { Some((v + 1, v as u16)) } else { None } } fn iter() -> EnumIterator { EnumIterator::new(0) } } /// Iterates over all values of an enum. #[derive(Copy, Clone, Debug)] pub struct EnumIterator { count: usize, _marker: PhantomData T>, } impl EnumIterator { pub(crate) fn new(start: usize) -> Self { EnumIterator { count: start, _marker: PhantomData, } } } impl Iterator for EnumIterator { type Item = T; fn next(&mut self) -> Option { match T::iter_next(self.count) { Some((new_count, res)) => { self.count = new_count; Some(res) }, None => None, } } } input-linux-0.6.0/src/evdev.rs000064400000000000000000000170361046102023000144000ustar 00000000000000//! An interface to the Linux kernel's event devices (`/dev/input/*`). use std::{io, fs}; use std::mem::{MaybeUninit, size_of}; use std::slice::from_raw_parts_mut; use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd, FromRawFd}; use nix; use crate::sys; use crate::{ AbsoluteAxis, AbsoluteInfo, AutorepeatKind, EventKind, InputId, InputProperty, Key, LedKind, MiscKind, RelativeAxis, SoundKind, SwitchKind }; use crate::macros::convert_error; use crate::bitmask::Bitmask; pub use sys::EV_VERSION; /// A handle to an input device allowing the use of ioctls pub struct EvdevHandle(F); impl EvdevHandle { /// Create a new handle using an existing open file object. pub const fn new(fd: F) -> Self { EvdevHandle(fd) } /// Extracts the contained handle. pub fn into_inner(self) -> F { self.0 } /// A reference to the contained handle. pub const fn as_inner(&self) -> &F { &self.0 } /// A mutable reference to the contained handle. pub fn as_inner_mut(&mut self) -> &mut F { &mut self.0 } } impl AsRawFd for EvdevHandle { fn as_raw_fd(&self) -> RawFd { self.fd() } } impl IntoRawFd for EvdevHandle { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } impl FromRawFd for EvdevHandle { unsafe fn from_raw_fd(fd: RawFd) -> Self { EvdevHandle(FromRawFd::from_raw_fd(fd)) } } impl EvdevHandle { /// Create a new handle from a raw file descriptor. pub unsafe fn from_fd(fd: RawFd) -> Self { FromRawFd::from_raw_fd(fd) } } impl EvdevHandle { #[inline] fn fd(&self) -> RawFd { self.0.as_raw_fd() } /// Read events from the input device pub fn read(&self, events: &mut [sys::input_event]) -> io::Result { let events = unsafe { from_raw_parts_mut(events.as_mut_ptr() as *mut u8, size_of::() * events.len()) }; nix::unistd::read(self.fd(), events) .map(|len| len / size_of::()).map_err(convert_error) } /// Write events to the input device pub fn write(&self, events: &[sys::input_event]) -> io::Result { let events = unsafe { from_raw_parts_mut(events.as_ptr() as *mut u8, size_of::() * events.len()) }; nix::unistd::write(self.fd(), events) .map(|len| len / size_of::()).map_err(convert_error) } ioctl_impl! { { /// `EVIOCGVERSION` @get driver_version = ev_get_version -> i32 } { /// `EVIOCGID` @get device_id = ev_get_id -> InputId } { /// `EVIOGREP` @get repeat_settings = ev_get_rep -> sys::repeat_settings } { /// `EVIOSREP` @set set_repeat_settings(&sys::repeat_settings) = ev_set_rep } { /// `EVIOCGKEYCODE` @get keycode_legacy = ev_get_keycode -> [u32; 2] } { /// `EVIOCGKEYCODE_V2` @get keycode = ev_get_keycode_v2 -> sys::input_keymap_entry } { /// `EVIOCSKEYCODE` @set set_keycode_legacy(&[u32; 2]) = ev_set_keycode } { /// `EVIOCSKEYCODE_V2` @set set_keycode(&sys::input_keymap_entry) = ev_set_keycode_v2 } { /// `EVIOCGNAME` @get_str device_name, device_name_buf = ev_get_name } { /// `EVIOCGPHYS` @get_str physical_location, physical_location_buf = ev_get_phys } { /// `EVIOCGUNIQ` @get_str unique_id, unique_id_buf = ev_get_uniq } { /// `EVIOCGPROP` @get_buf device_properties_raw(u8) = ev_get_prop } { /// `EVIOCGKEY` @get_buf key_state(u8) = ev_get_key } { /// `EVIOCGLED` @get_buf led_state(u8) = ev_get_led } { /// `EVIOCGSND` @get_buf sounds_state(u8) = ev_get_snd } { /// `EVIOCGSW` @get_buf switch_state(u8) = ev_get_sw } { /// `EVIOCSFF` @set send_force_feedback(&mut sys::ff_effect) = ev_send_ff } { /// `EVIOCRMFF` @set erase_force_feedback(i16) = ev_erase_ff } { /// `EVIOCGEFFECTS` @get effects_count = ev_get_effects -> i32 } } /// `EVIOCGPROP` pub fn device_properties(&self) -> io::Result> { let mut bitmask = Bitmask::default(); self.device_properties_raw(&mut bitmask).map(|_| bitmask) } /// `EVIOCGMTSLOTS` /// /// Warning: the current implementation can leak uninitialized heap memory into `values` pub fn multi_touch_slots(&self, code: AbsoluteAxis, values: &mut [i32]) -> io::Result<()> { let input_len = values.len() + 1; let mut buf = Vec::::with_capacity(input_len); // a perfect example of how not to use ev_get_mtslots unsafe { buf.set_len(input_len); buf[0] = code as _; // the first field isn't counted in the len of the fat pointer let ptr = from_raw_parts_mut(buf.as_mut_ptr(), values.len()) as *mut _; sys::ev_get_mtslots(self.fd(), ptr as *mut sys::input_mt_request_layout<[i32]>) .map_err(convert_error)?; } values.copy_from_slice(&buf[1..]); Ok(()) } impl_bitmasks! { EventKind, EventKind::Synchronize, event_mask_events, set_event_mask_events, event_bits } impl_bitmasks! { Key, EventKind::Key, key_mask, set_key_mask, key_bits } impl_bitmasks! { RelativeAxis, EventKind::Relative, relative_mask, set_relative_mask, relative_bits } impl_bitmasks! { AbsoluteAxis, EventKind::Absolute, absolute_mask, set_absolute_mask, absolute_bits } impl_bitmasks! { MiscKind, EventKind::Misc, misc_mask, set_misc_mask, misc_bits } impl_bitmasks! { SwitchKind, EventKind::Switch, switch_mask, set_switch_mask, switch_bits } impl_bitmasks! { LedKind, EventKind::Led, led_mask, set_led_mask, led_bits } impl_bitmasks! { SoundKind, EventKind::Sound, sound_mask, set_sound_mask, sound_bits } impl_bitmasks! { AutorepeatKind, EventKind::Autorepeat, autorepeat_mask, set_autorepeat_mask, autorepeat_bits } /// `EVIOCGMASK` pub fn event_mask_raw(&self, kind: EventKind, buffer: &mut [u8]) -> io::Result<()> { unsafe { let mut mask = sys::input_mask { type_: kind as _, codes_size: buffer.len() as _, codes_ptr: buffer.as_mut_ptr() as usize as _, }; sys::ev_get_mask(self.fd(), &mut mask) .map(drop) .map_err(convert_error) } } /// `EVIOCSMASK` pub fn set_event_mask_raw(&self, kind: EventKind, buffer: &[u8]) -> io::Result<()> { unsafe { let mask = sys::input_mask { type_: kind as _, codes_size: buffer.len() as _, codes_ptr: buffer.as_ptr() as usize as _, }; sys::ev_set_mask(self.fd(), &mask) .map(drop) .map_err(convert_error) } } /// `EVIOCGBIT` pub fn event_bits_raw(&self, kind: EventKind, buffer: &mut [u8]) -> io::Result { unsafe { sys::ev_get_bit(self.fd(), kind as _, buffer) .map(|i| i as _) .map_err(convert_error) } } /// `EVIOCGABS` pub fn absolute_info(&self, abs: AbsoluteAxis) -> io::Result { unsafe { let mut info = MaybeUninit::uninit(); sys::ev_get_abs(self.fd(), abs as _, &mut *info.as_mut_ptr()) .map(|_| info.assume_init().into()) .map_err(convert_error) } } /// `EVIOCSABS` pub fn set_absolute_info(&self, abs: AbsoluteAxis, info: &AbsoluteInfo) -> io::Result<()> { unsafe { let info: &sys::input_absinfo = info.into(); sys::ev_set_abs(self.fd(), abs as _, info) .map(drop) .map_err(convert_error) } } /// `EVIOCGRAB` pub fn grab(&self, grab: bool) -> io::Result<()> { unsafe { sys::ev_grab(self.fd(), if grab { 1 } else { 0 }) .map(drop) .map_err(convert_error) } } /// `EVIOCREVOKE` pub fn revoke(&self) -> io::Result<()> { unsafe { sys::ev_revoke(self.fd(), 0) .map(drop) .map_err(convert_error) } } /// `EVIOCSCLOCKID` pub fn set_clock_id(&self, value: i32) -> io::Result<()> { unsafe { sys::ev_set_clockid(self.fd(), &value) .map(drop) .map_err(convert_error) } } } input-linux-0.6.0/src/events.rs000064400000000000000000000371401046102023000145710ustar 00000000000000use std::convert::TryFrom; use crate::sys::input_event; use crate::{ EventTime, RangeError, KeyState, EventKind, SynchronizeKind, Key, RelativeAxis, AbsoluteAxis, SwitchKind, MiscKind, LedKind, AutorepeatKind, SoundKind, UInputKind, }; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Synchronization events are used by evdev to group events or convey other /// out-of-band information. pub struct SynchronizeEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The type of synchronization event. pub kind: SynchronizeKind, /// An associated value with the event. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// An event that indicates the state of a key has changed. pub struct KeyEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The key that triggered the event. pub key: Key, /// The value of the event. pub value: KeyState, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Events that occur when the state of a relative axis is changed. pub struct RelativeEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The axis associated with the event. pub axis: RelativeAxis, /// The relative distance of the axis event. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Events that occur when the state of an absolute axis is changed. pub struct AbsoluteEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The axis associated with the event. pub axis: AbsoluteAxis, /// The absolute value of the axis. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Special switch events. pub struct SwitchEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The switch that triggered the event. pub switch: SwitchKind, /// The state of the switch. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Miscellaneous events. pub struct MiscEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The kind of miscellaneous event. pub kind: MiscKind, /// The state/value of the event. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// An event that indicates whether the specified LED should turn on/off. pub struct LedEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The led associated with the event. pub led: LedKind, /// The state of the led. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// An event that configures the autorepeat behaviour of the input device. pub struct AutorepeatEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The kind of autorepeat event. pub kind: AutorepeatKind, /// The value of the event. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// An event that indicates the device should play a specified sound. pub struct SoundEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The sound to play. pub sound: SoundKind, /// The value or state associated with the sound. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// A special event type used to send force-feedback events to uinput. pub struct UInputEvent { /// The timestamp associated with the event. pub time: EventTime, event: EventKind, /// The code of the event. pub code: UInputKind, /// The unique request ID. pub value: i32, } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// A generic event. pub struct InputEvent { /// The timestamp associated with the event. pub time: EventTime, /// The type of event that occurred. pub kind: EventKind, /// The code of the event. /// /// The meaning of this code depends on the `kind` of event. Using the typed /// events via [`Event`] and [`EventRef`] is recommended. pub code: u16, /// The value of the event. /// /// The interpretation of this value depends on the `kind` of event. pub value: i32, } impl InputEvent { /// Reinterpret this event as an array of bytes pub fn as_bytes(&self) -> &[u8; core::mem::size_of::()] { unsafe { core::mem::transmute(self) } } } impl SynchronizeEvent { /// Synchronization event pub const fn report(time: EventTime) -> Self { Self::new(time, SynchronizeKind::Report, 0) } } macro_rules! event_impl { (@impl_event InputEvent $($tt:tt)*) => { }; (@impl_event $name:ident $code:ident $kind:path, $codekind:ident, $valuekind:ident) => { impl GenericEvent for $name { fn event_kind(&self) -> EventKind { $kind } fn time(&self) -> &EventTime { &self.time } fn code(&self) -> u16 { self.$code as _ } fn value(&self) -> i32 { self.value.into() } fn from_ref(event: &InputEvent) -> Result<&Self, RangeError> { $codekind::from_code(event.code) .and_then(move |_| if event.kind == $kind { Ok(unsafe { Self::from_event(event) }) } else { Err(Default::default()) }) } fn from_mut(event: &mut InputEvent) -> Result<&mut Self, RangeError> { $codekind::from_code(event.code) .and_then(move |_| if event.kind == $kind { Ok(unsafe { Self::from_event_mut(event) }) } else { Err(Default::default()) }) } } impl<'a> TryFrom<&'a InputEvent> for &'a $name { type Error = RangeError; fn try_from(event: &'a InputEvent) -> Result { $name::from_ref(event) } } impl TryFrom for $name { type Error = RangeError; fn try_from(event: InputEvent) -> Result { $name::from_ref(&event).map(|&e| e) } } impl<'a> TryFrom<&'a mut InputEvent> for &'a mut $name { type Error = RangeError; fn try_from(event: &'a mut InputEvent) -> Result { $name::from_mut(event) } } impl<'a> From<&'a $name> for &'a InputEvent { fn from(event: &'a $name) -> Self { event.as_event() } } impl<'a> From<&'a $name> for InputEvent { fn from(event: &'a $name) -> Self { event.as_event().clone() } } impl From<$name> for InputEvent { fn from(event: $name) -> Self { From::from(&event) } } impl AsRef for $name { fn as_ref(&self) -> &InputEvent { self.as_event() } } impl<'a> $name { /// Creates a new event from the given code and value. pub const fn new(time: EventTime, $code: $codekind, value: $valuekind) -> Self { $name { time, event: $kind, $code: $code, value, } } /// Reinterpret a generic event without checking for validity. pub unsafe fn from_event>(event: &E) -> &Self { let raw = event.as_ref() as *const _ as *const _; &*raw } /// Reinterpret a mutable generic event without checking for validity. pub unsafe fn from_event_mut(event: &mut InputEvent) -> &mut Self { let raw = event as *mut _ as *mut _; &mut *raw } /// A generic input event reference. pub fn as_event(&self) -> &InputEvent { let raw = self as *const _ as *const _; unsafe { &*raw } } /// A mutable generic input event reference. pub unsafe fn as_event_mut(&mut self) -> &mut InputEvent { let raw = self as *mut _ as *mut _; &mut *raw } } }; (@impl $name:ident $code:ident $kind:path, $codekind:ident, $valuekind:ident) => { event_impl! { @impl_event $name $code $kind, $codekind, $valuekind } impl AsRef for $name { fn as_ref(&self) -> &input_event { let raw = self as *const _ as *const _; unsafe { &*raw } } } }; ($(struct $name:ident : $kind:path { $code:ident: $codekind:ident, value: $valuekind:ident })*) => { $( event_impl! { @impl $name $code $kind, $codekind, $valuekind } )* }; } /// A generic linux input event. pub trait GenericEvent: AsRef + AsRef { /// The event kind. fn event_kind(&self) -> EventKind; /// The timestamp associated with the event. fn time(&self) -> &EventTime; /// The type code value of the event. fn code(&self) -> u16; /// The value associated with the event. fn value(&self) -> i32; /// Interprets a generic event reference into a concrete event type. fn from_ref(event: &InputEvent) -> Result<&Self, RangeError>; /// Interprets a mutable generic event reference into a concrete event type. fn from_mut(event: &mut InputEvent) -> Result<&mut Self, RangeError>; } event_impl! { struct SynchronizeEvent : EventKind::Synchronize { kind: SynchronizeKind, value: i32 } struct KeyEvent : EventKind::Key { key: Key, value: KeyState } struct RelativeEvent : EventKind::Relative { axis: RelativeAxis, value: i32 } struct AbsoluteEvent : EventKind::Absolute { axis: AbsoluteAxis, value: i32 } struct SwitchEvent : EventKind::Switch { switch: SwitchKind, value: i32 } struct MiscEvent : EventKind::Misc { kind: MiscKind, value: i32 } struct LedEvent : EventKind::Led { led: LedKind, value: i32 } struct AutorepeatEvent : EventKind::Autorepeat { kind: AutorepeatKind, value: i32 } struct SoundEvent : EventKind::Sound { sound: SoundKind, value: i32 } struct UInputEvent : EventKind::UInput { code: UInputKind, value: i32 } struct InputEvent : Unknown { code: u16, value: i32 } } impl GenericEvent for InputEvent { fn event_kind(&self) -> EventKind { self.kind } fn time(&self) -> &EventTime { &self.time } fn code(&self) -> u16 { self.code } fn value(&self) -> i32 { self.value } fn from_ref(event: &InputEvent) -> Result<&Self, RangeError> { Ok(event) } fn from_mut(event: &mut InputEvent) -> Result<&mut Self, RangeError> { Ok(event) } } impl AsRef for InputEvent { fn as_ref(&self) -> &InputEvent { self } } impl InputEvent { /// Reinterprets a raw [`input_event`]. pub fn from_raw(event: &input_event) -> Result<&Self, RangeError> { EventKind::from_type(event.type_).map(|_| { let raw = event as *const _ as *const _; unsafe { &*raw } }) } /// Reinterprets a raw [`input_event`] into a mutable reference. pub fn from_raw_mut(event: &mut input_event) -> Result<&mut Self, RangeError> { EventKind::from_type(event.type_).map(|_| { let raw = event as *mut _ as *mut _; unsafe { &mut *raw } }) } /// Reinterprets the event as a raw [`input_event`]. pub fn as_raw(&self) -> &input_event { let raw = self as *const _ as *const _; unsafe { &*raw } } /// Reinterprets the event as a mutable raw [`input_event`]. pub unsafe fn as_raw_mut(&mut self) -> &mut input_event { let raw = self as *mut _ as *mut _; &mut *raw } } macro_rules! input_event_enum { ($($variant:ident($ty:ident),)*) => { /// An owned and typed input event. #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub enum Event { $( #[allow(missing_docs)] $variant($ty), )* /// Unknown event type. Unknown(InputEvent), } /// A reference to an input event. #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] pub enum EventRef<'a> { $( #[allow(missing_docs)] $variant(&'a $ty), )* /// Unknown event type. Unknown(&'a InputEvent), } /// A mutable reference to an input event. #[derive(PartialEq, Eq, Hash, Debug)] pub enum EventMut<'a> { $( #[allow(missing_docs)] $variant(&'a mut $ty), )* /// Unknown event type. Unknown(&'a mut InputEvent), } impl Event { /// Converts a generic [`InputEvent`] to a typed event. pub fn new(event: InputEvent) -> Result { match event.kind { $( EventKind::$variant => $ty::from_ref(&event).map(Clone::clone).map(Event::$variant), )* _ => Ok(Event::Unknown(event)), } } } impl<'a> EventRef<'a> { /// Wraps the generic [`InputEvent`] into an event. pub fn new(event: &'a InputEvent) -> Result { match event.kind { $( EventKind::$variant => $ty::from_ref(event).map(EventRef::$variant), )* _ => Ok(EventRef::Unknown(event)), } } } impl<'a> EventMut<'a> { /// Wraps the generic [`InputEvent`] into a mutable event. pub fn new(event: &'a mut InputEvent) -> Result { match event.kind { $( EventKind::$variant => $ty::from_mut(event).map(EventMut::$variant), )* _ => Ok(EventMut::Unknown(event)), } } } $( impl From<$ty> for Event { fn from(event: $ty) -> Self { Event::$variant(event) } } )* $( impl<'a> From<&'a $ty> for EventRef<'a> { fn from(event: &'a $ty) -> Self { EventRef::$variant(event) } } )* $( impl<'a> From<&'a mut $ty> for EventMut<'a> { fn from(event: &'a mut $ty) -> Self { EventMut::$variant(event) } } )* impl From for InputEvent { fn from(event: Event) -> Self { match event { $( Event::$variant(ref event) => <&InputEvent as From<_>>::from(event).clone(), )* Event::Unknown(event) => event, } } } impl<'a> From<&'a Event> for EventRef<'a> { fn from(event: &'a Event) -> Self { match *event { $( Event::$variant(ref event) => EventRef::$variant(event), )* Event::Unknown(ref event) => EventRef::Unknown(event), } } } impl<'a> From<&'a mut Event> for EventMut<'a> { fn from(event: &'a mut Event) -> Self { match *event { $( Event::$variant(ref mut event) => EventMut::$variant(event), )* Event::Unknown(ref mut event) => EventMut::Unknown(event), } } } impl<'a> From> for &'a InputEvent { fn from(event: EventRef<'a>) -> Self { match event { $( EventRef::$variant(event) => event.as_ref(), )* EventRef::Unknown(event) => event, } } } impl<'a> From<&'a EventMut<'a>> for &'a InputEvent { fn from(event: &'a EventMut<'a>) -> Self { match *event { $( EventMut::$variant(ref event) => event.as_ref(), )* EventMut::Unknown(ref event) => event, } } } impl AsRef for Event { fn as_ref(&self) -> &InputEvent { match *self { $( Event::$variant(ref event) => event.as_ref(), )* Event::Unknown(ref event) => event.as_ref(), } } } impl<'a> AsRef for EventRef<'a> { fn as_ref(&self) -> &InputEvent { From::from(*self) } } impl<'a> AsRef for EventMut<'a> { fn as_ref(&self) -> &InputEvent { From::from(self) } } }; } input_event_enum! { Synchronize(SynchronizeEvent), Key(KeyEvent), Relative(RelativeEvent), Absolute(AbsoluteEvent), Switch(SwitchEvent), Misc(MiscEvent), Led(LedEvent), Autorepeat(AutorepeatEvent), Sound(SoundEvent), UInput(UInputEvent), } input-linux-0.6.0/src/keys.rs000064400000000000000000000724131046102023000142420ustar 00000000000000use crate::sys; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// Keys and Buttons /// /// Most of the keys/buttons are modeled after USB HUT 1.12 (see ). /// /// ## Comment Abbreviations /// AC - Application Control /// AL - Application Launch Button /// SC - System Control #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum Key { Reserved = sys::KEY_RESERVED as _, Esc = sys::KEY_ESC as _, Num1 = sys::KEY_1 as _, Num2 = sys::KEY_2 as _, Num3 = sys::KEY_3 as _, Num4 = sys::KEY_4 as _, Num5 = sys::KEY_5 as _, Num6 = sys::KEY_6 as _, Num7 = sys::KEY_7 as _, Num8 = sys::KEY_8 as _, Num9 = sys::KEY_9 as _, Num0 = sys::KEY_0 as _, Minus = sys::KEY_MINUS as _, Equal = sys::KEY_EQUAL as _, Backspace = sys::KEY_BACKSPACE as _, Tab = sys::KEY_TAB as _, Q = sys::KEY_Q as _, W = sys::KEY_W as _, E = sys::KEY_E as _, R = sys::KEY_R as _, T = sys::KEY_T as _, Y = sys::KEY_Y as _, U = sys::KEY_U as _, I = sys::KEY_I as _, O = sys::KEY_O as _, P = sys::KEY_P as _, LeftBrace = sys::KEY_LEFTBRACE as _, RightBrace = sys::KEY_RIGHTBRACE as _, Enter = sys::KEY_ENTER as _, LeftCtrl = sys::KEY_LEFTCTRL as _, A = sys::KEY_A as _, S = sys::KEY_S as _, D = sys::KEY_D as _, F = sys::KEY_F as _, G = sys::KEY_G as _, H = sys::KEY_H as _, J = sys::KEY_J as _, K = sys::KEY_K as _, L = sys::KEY_L as _, Semicolon = sys::KEY_SEMICOLON as _, Apostrophe = sys::KEY_APOSTROPHE as _, Grave = sys::KEY_GRAVE as _, LeftShift = sys::KEY_LEFTSHIFT as _, Backslash = sys::KEY_BACKSLASH as _, Z = sys::KEY_Z as _, X = sys::KEY_X as _, C = sys::KEY_C as _, V = sys::KEY_V as _, B = sys::KEY_B as _, N = sys::KEY_N as _, M = sys::KEY_M as _, Comma = sys::KEY_COMMA as _, Dot = sys::KEY_DOT as _, Slash = sys::KEY_SLASH as _, RightShift = sys::KEY_RIGHTSHIFT as _, KpAsterisk = sys::KEY_KPASTERISK as _, LeftAlt = sys::KEY_LEFTALT as _, Space = sys::KEY_SPACE as _, CapsLock = sys::KEY_CAPSLOCK as _, F1 = sys::KEY_F1 as _, F2 = sys::KEY_F2 as _, F3 = sys::KEY_F3 as _, F4 = sys::KEY_F4 as _, F5 = sys::KEY_F5 as _, F6 = sys::KEY_F6 as _, F7 = sys::KEY_F7 as _, F8 = sys::KEY_F8 as _, F9 = sys::KEY_F9 as _, F10 = sys::KEY_F10 as _, NumLock = sys::KEY_NUMLOCK as _, ScrollLock = sys::KEY_SCROLLLOCK as _, Kp7 = sys::KEY_KP7 as _, Kp8 = sys::KEY_KP8 as _, Kp9 = sys::KEY_KP9 as _, KpMinus = sys::KEY_KPMINUS as _, Kp4 = sys::KEY_KP4 as _, Kp5 = sys::KEY_KP5 as _, Kp6 = sys::KEY_KP6 as _, KpPlus = sys::KEY_KPPLUS as _, Kp1 = sys::KEY_KP1 as _, Kp2 = sys::KEY_KP2 as _, Kp3 = sys::KEY_KP3 as _, Kp0 = sys::KEY_KP0 as _, KpDot = sys::KEY_KPDOT as _, Unknown54, ZenkakuHankaku = sys::KEY_ZENKAKUHANKAKU as _, NonUsBackslashAndPipe = sys::KEY_102ND as _, F11 = sys::KEY_F11 as _, F12 = sys::KEY_F12 as _, Ro = sys::KEY_RO as _, Katakana = sys::KEY_KATAKANA as _, Hiragana = sys::KEY_HIRAGANA as _, Henkan = sys::KEY_HENKAN as _, KatakanaHiragana = sys::KEY_KATAKANAHIRAGANA as _, Muhenkan = sys::KEY_MUHENKAN as _, KpJpComma = sys::KEY_KPJPCOMMA as _, KpEnter = sys::KEY_KPENTER as _, RightCtrl = sys::KEY_RIGHTCTRL as _, KpSlash = sys::KEY_KPSLASH as _, Sysrq = sys::KEY_SYSRQ as _, RightAlt = sys::KEY_RIGHTALT as _, LineFeed = sys::KEY_LINEFEED as _, Home = sys::KEY_HOME as _, Up = sys::KEY_UP as _, PageUp = sys::KEY_PAGEUP as _, Left = sys::KEY_LEFT as _, Right = sys::KEY_RIGHT as _, End = sys::KEY_END as _, Down = sys::KEY_DOWN as _, PageDown = sys::KEY_PAGEDOWN as _, Insert = sys::KEY_INSERT as _, Delete = sys::KEY_DELETE as _, Macro = sys::KEY_MACRO as _, Mute = sys::KEY_MUTE as _, VolumeDown = sys::KEY_VOLUMEDOWN as _, VolumeUp = sys::KEY_VOLUMEUP as _, /// SC System Power Down Power = sys::KEY_POWER as _, KpEqual = sys::KEY_KPEQUAL as _, KpPlusMinus = sys::KEY_KPPLUSMINUS as _, Pause = sys::KEY_PAUSE as _, /// AL Compiz Scale (Expose) Scale = sys::KEY_SCALE as _, KpComma = sys::KEY_KPCOMMA as _, /// KeyHangeul / KeyHanguel Hangul = sys::KEY_HANGEUL as _, // KeyHangeul = KeyHangul // KeyHanguel = KeyHangul Hanja = sys::KEY_HANJA as _, Yen = sys::KEY_YEN as _, LeftMeta = sys::KEY_LEFTMETA as _, RightMeta = sys::KEY_RIGHTMETA as _, Compose = sys::KEY_COMPOSE as _, /// AC Stop Stop = sys::KEY_STOP as _, Again = sys::KEY_AGAIN as _, /// AC Properties Props = sys::KEY_PROPS as _, /// AC Undo Undo = sys::KEY_UNDO as _, Front = sys::KEY_FRONT as _, /// AC Copy Copy = sys::KEY_COPY as _, /// AC Open Open = sys::KEY_OPEN as _, /// AC Paste Paste = sys::KEY_PASTE as _, /// AC Search Find = sys::KEY_FIND as _, /// AC Cut Cut = sys::KEY_CUT as _, /// AL Integrated Help Center Help = sys::KEY_HELP as _, /// Menu (show menu) Menu = sys::KEY_MENU as _, /// AL Calculator Calc = sys::KEY_CALC as _, Setup = sys::KEY_SETUP as _, /// SC System Sleep Sleep = sys::KEY_SLEEP as _, /// System Wake Up Wakeup = sys::KEY_WAKEUP as _, /// AL Local Machine Browser File = sys::KEY_FILE as _, SendFile = sys::KEY_SENDFILE as _, DeleteFile = sys::KEY_DELETEFILE as _, Xfer = sys::KEY_XFER as _, Prog1 = sys::KEY_PROG1 as _, Prog2 = sys::KEY_PROG2 as _, /// AL Internet Browser WWW = sys::KEY_WWW as _, MSDOS = sys::KEY_MSDOS as _, /// AL Terminal Lock/Screensaver /// KeyScreenLock Coffee = sys::KEY_COFFEE as _, // KeyScreenLock = KeyCoffee, /// Display orientation for e.g. tablets (aka KeyDirectionKey) RotateDisplay = sys::KEY_ROTATE_DISPLAY as _, // KeyDirectionKey = KeyRotateDisplay CycleWindows = sys::KEY_CYCLEWINDOWS as _, Mail = sys::KEY_MAIL as _, /// AC Bookmarks Bookmarks = sys::KEY_BOOKMARKS as _, Computer = sys::KEY_COMPUTER as _, /// AC Back Back = sys::KEY_BACK as _, /// AC Forward Forward = sys::KEY_FORWARD as _, CloseCD = sys::KEY_CLOSECD as _, EjectCD = sys::KEY_EJECTCD as _, EjectCloseCD = sys::KEY_EJECTCLOSECD as _, NextSong = sys::KEY_NEXTSONG as _, PlayPause = sys::KEY_PLAYPAUSE as _, PreviousSong = sys::KEY_PREVIOUSSONG as _, StopCD = sys::KEY_STOPCD as _, Record = sys::KEY_RECORD as _, Rewind = sys::KEY_REWIND as _, /// Media Select Telephone Phone = sys::KEY_PHONE as _, Iso = sys::KEY_ISO as _, /// AL Consumer Control Configuration Config = sys::KEY_CONFIG as _, /// AC Home Homepage = sys::KEY_HOMEPAGE as _, /// AC Refresh Refresh = sys::KEY_REFRESH as _, /// AC Exit Exit = sys::KEY_EXIT as _, Move = sys::KEY_MOVE as _, Edit = sys::KEY_EDIT as _, ScrollUp = sys::KEY_SCROLLUP as _, ScrollDown = sys::KEY_SCROLLDOWN as _, KpLeftParen = sys::KEY_KPLEFTPAREN as _, KpRightParen = sys::KEY_KPRIGHTPAREN as _, /// AC New New = sys::KEY_NEW as _, /// AC Redo/Repeat Redo = sys::KEY_REDO as _, F13 = sys::KEY_F13 as _, F14 = sys::KEY_F14 as _, F15 = sys::KEY_F15 as _, F16 = sys::KEY_F16 as _, F17 = sys::KEY_F17 as _, F18 = sys::KEY_F18 as _, F19 = sys::KEY_F19 as _, F20 = sys::KEY_F20 as _, F21 = sys::KEY_F21 as _, F22 = sys::KEY_F22 as _, F23 = sys::KEY_F23 as _, F24 = sys::KEY_F24 as _, UnknownC3, UnknownC4, UnknownC5, UnknownC6, UnknownC7, PlayCD = sys::KEY_PLAYCD as _, PauseCD = sys::KEY_PAUSECD as _, Prog3 = sys::KEY_PROG3 as _, Prog4 = sys::KEY_PROG4 as _, /// AC Desktop Show All Applications AllApplications = sys::KEY_ALL_APPLICATIONS as _, Suspend = sys::KEY_SUSPEND as _, /// AC Close Close = sys::KEY_CLOSE as _, Play = sys::KEY_PLAY as _, FastForward = sys::KEY_FASTFORWARD as _, BassBoost = sys::KEY_BASSBOOST as _, /// AC Print Print = sys::KEY_PRINT as _, Hp = sys::KEY_HP as _, Camera = sys::KEY_CAMERA as _, Sound = sys::KEY_SOUND as _, Question = sys::KEY_QUESTION as _, Email = sys::KEY_EMAIL as _, Chat = sys::KEY_CHAT as _, Search = sys::KEY_SEARCH as _, Connect = sys::KEY_CONNECT as _, /// AL Checkbook/Finance Finance = sys::KEY_FINANCE as _, Sport = sys::KEY_SPORT as _, Shop = sys::KEY_SHOP as _, Alterase = sys::KEY_ALTERASE as _, /// AC Cancel Cancel = sys::KEY_CANCEL as _, BrightnessDown = sys::KEY_BRIGHTNESSDOWN as _, BrightnessUp = sys::KEY_BRIGHTNESSUP as _, Media = sys::KEY_MEDIA as _, /// Cycle between available video outputs (Monitor/LCD/TV-out/etc) SwitchVideoMode = sys::KEY_SWITCHVIDEOMODE as _, IllumToggle = sys::KEY_KBDILLUMTOGGLE as _, IllumDown = sys::KEY_KBDILLUMDOWN as _, IllumUp = sys::KEY_KBDILLUMUP as _, /// AC Send Send = sys::KEY_SEND as _, /// AC Reply Reply = sys::KEY_REPLY as _, /// AC Forward Msg ForwardMail = sys::KEY_FORWARDMAIL as _, /// AC Save Save = sys::KEY_SAVE as _, Documents = sys::KEY_DOCUMENTS as _, Battery = sys::KEY_BATTERY as _, Bluetooth = sys::KEY_BLUETOOTH as _, WLAN = sys::KEY_WLAN as _, UWB = sys::KEY_UWB as _, Unknown = sys::KEY_UNKNOWN as _, /// drive next video source VideoNext = sys::KEY_VIDEO_NEXT as _, /// drive previous video source VideoPrev = sys::KEY_VIDEO_PREV as _, /// brightness up, after max is min BrightnessCycle = sys::KEY_BRIGHTNESS_CYCLE as _, /// Set Auto Brightness: manual brightness control is off, rely on ambient /// (aka KeyBrightnessZero) BrightnessAuto = sys::KEY_BRIGHTNESS_AUTO as _, // KeyBrightnessZero = KeyBrightnessAuto /// display device to off state DisplayOff = sys::KEY_DISPLAY_OFF as _, /// Wireless WAN (LTE, UMTS, GSM, etc.) /// (aka KeyWiMAX) WWAN = sys::KEY_WWAN as _, // KeyWiMAX = KeyWWAN /// Key that controls all radios Rfkill = sys::KEY_RFKILL as _, /// Mute / unmute the microphone MicMute = sys::KEY_MICMUTE as _, UnknownF9, UnknownFA, UnknownFB, UnknownFC, UnknownFD, UnknownFE, /// Code 255 is reserved for special needs of AT keyboard driver ReservedFF = 0xff, //ButtonMisc = sys::BTN_MISC as _, Button0 = sys::BTN_0 as _, Button1 = sys::BTN_1 as _, Button2 = sys::BTN_2 as _, Button3 = sys::BTN_3 as _, Button4 = sys::BTN_4 as _, Button5 = sys::BTN_5 as _, Button6 = sys::BTN_6 as _, Button7 = sys::BTN_7 as _, Button8 = sys::BTN_8 as _, Button9 = sys::BTN_9 as _, Unknown10A, Unknown10B, Unknown10C, Unknown10D, Unknown10E, Unknown10F, //ButtonMouse = sys::BTN_MOUSE as _, ButtonLeft = sys::BTN_LEFT as _, ButtonRight = sys::BTN_RIGHT as _, ButtonMiddle = sys::BTN_MIDDLE as _, ButtonSide = sys::BTN_SIDE as _, ButtonExtra = sys::BTN_EXTRA as _, ButtonForward = sys::BTN_FORWARD as _, ButtonBack = sys::BTN_BACK as _, ButtonTask = sys::BTN_TASK as _, Unknown118, Unknown119, Unknown11A, Unknown11B, Unknown11C, Unknown11D, Unknown11E, Unknown11F, //ButtonJoystick = sys::BTN_JOYSTICK as _, ButtonTrigger = sys::BTN_TRIGGER as _, ButtonThumb = sys::BTN_THUMB as _, ButtonThumb2 = sys::BTN_THUMB2 as _, ButtonTop = sys::BTN_TOP as _, ButtonTop2 = sys::BTN_TOP2 as _, ButtonPinkie = sys::BTN_PINKIE as _, ButtonBase = sys::BTN_BASE as _, ButtonBase2 = sys::BTN_BASE2 as _, ButtonBase3 = sys::BTN_BASE3 as _, ButtonBase4 = sys::BTN_BASE4 as _, ButtonBase5 = sys::BTN_BASE5 as _, ButtonBase6 = sys::BTN_BASE6 as _, Unknown12C, Unknown12D, Unknown12E, ButtonDead = sys::BTN_DEAD as _, //ButtonGamepad = sys::BTN_GAMEPAD as _, /// aka ButtonA ButtonSouth = sys::BTN_SOUTH as _, // ButtonA = ButtonSouth /// aka ButtonB ButtonEast = sys::BTN_EAST as _, // ButtonB = ButtonEast ButtonC = sys::BTN_C as _, /// aka ButtonX ButtonNorth = sys::BTN_NORTH as _, // ButtonX = ButtonNorth /// aka ButtonY ButtonWest = sys::BTN_WEST as _, // ButtonY = ButtonWest ButtonZ = sys::BTN_Z as _, ButtonTL = sys::BTN_TL as _, ButtonTR = sys::BTN_TR as _, ButtonTL2 = sys::BTN_TL2 as _, ButtonTR2 = sys::BTN_TR2 as _, ButtonSelect = sys::BTN_SELECT as _, ButtonStart = sys::BTN_START as _, ButtonMode = sys::BTN_MODE as _, ButtonThumbl = sys::BTN_THUMBL as _, ButtonThumbr = sys::BTN_THUMBR as _, Unknown13F, //ButtonDigi = sys::BTN_DIGI as _, ButtonToolPen = sys::BTN_TOOL_PEN as _, ButtonToolRubber = sys::BTN_TOOL_RUBBER as _, ButtonToolBrush = sys::BTN_TOOL_BRUSH as _, ButtonToolPencil = sys::BTN_TOOL_PENCIL as _, ButtonToolAirbrush = sys::BTN_TOOL_AIRBRUSH as _, ButtonToolFinger = sys::BTN_TOOL_FINGER as _, ButtonToolMouse = sys::BTN_TOOL_MOUSE as _, ButtonToolLens = sys::BTN_TOOL_LENS as _, /// Five fingers on trackpad ButtonToolQuintTap = sys::BTN_TOOL_QUINTTAP as _, ButtonStylus3 = sys::BTN_STYLUS3 as _, ButtonTouch = sys::BTN_TOUCH as _, ButtonStylus = sys::BTN_STYLUS as _, ButtonStylus2 = sys::BTN_STYLUS2 as _, ButtonToolDoubleTap = sys::BTN_TOOL_DOUBLETAP as _, ButtonToolTripleTap = sys::BTN_TOOL_TRIPLETAP as _, /// Four fingers on trackpad ButtonToolQuadtap = sys::BTN_TOOL_QUADTAP as _, ButtonWheel = sys::BTN_WHEEL as _, //ButtonGearDown = sys::BTN_GEAR_DOWN as _, ButtonGearUp = sys::BTN_GEAR_UP as _, Unknown152, Unknown153, Unknown154, Unknown155, Unknown156, Unknown157, Unknown158, Unknown159, Unknown15A, Unknown15B, Unknown15C, Unknown15D, Unknown15E, Unknown15F, Ok = sys::KEY_OK as _, Select = sys::KEY_SELECT as _, Goto = sys::KEY_GOTO as _, Clear = sys::KEY_CLEAR as _, Power2 = sys::KEY_POWER2 as _, Option = sys::KEY_OPTION as _, /// AL OEM Features/Tips/Tutorial Info = sys::KEY_INFO as _, Time = sys::KEY_TIME as _, Vendor = sys::KEY_VENDOR as _, Archive = sys::KEY_ARCHIVE as _, /// Media Select Program Guide Program = sys::KEY_PROGRAM as _, Channel = sys::KEY_CHANNEL as _, Favorites = sys::KEY_FAVORITES as _, EPG = sys::KEY_EPG as _, /// Media Select Home PVR = sys::KEY_PVR as _, MHP = sys::KEY_MHP as _, Language = sys::KEY_LANGUAGE as _, Title = sys::KEY_TITLE as _, Subtitle = sys::KEY_SUBTITLE as _, Angle = sys::KEY_ANGLE as _, FullScreen = sys::KEY_FULL_SCREEN as _, Mode = sys::KEY_MODE as _, Keyboard = sys::KEY_KEYBOARD as _, AspectRatio = sys::KEY_ASPECT_RATIO as _, /// Media Select Computer PC = sys::KEY_PC as _, /// Media Select TV TV = sys::KEY_TV as _, /// Media Select Cable TV2 = sys::KEY_TV2 as _, /// Media Select VCR VCR = sys::KEY_VCR as _, /// VCR Plus VCR2 = sys::KEY_VCR2 as _, /// Media Select Satellite Sat = sys::KEY_SAT as _, Sat2 = sys::KEY_SAT2 as _, /// Media Select CD CD = sys::KEY_CD as _, /// Media Select Tape Tape = sys::KEY_TAPE as _, Radio = sys::KEY_RADIO as _, /// Media Select Tuner Tuner = sys::KEY_TUNER as _, Player = sys::KEY_PLAYER as _, Text = sys::KEY_TEXT as _, /// Media Select DVD Dvd = sys::KEY_DVD as _, Aux = sys::KEY_AUX as _, Mp3 = sys::KEY_MP3 as _, /// AL Audio Browser Audio = sys::KEY_AUDIO as _, /// AL Movie Browser Video = sys::KEY_VIDEO as _, Directory = sys::KEY_DIRECTORY as _, List = sys::KEY_LIST as _, /// Media Select Messages Memo = sys::KEY_MEMO as _, Calendar = sys::KEY_CALENDAR as _, Red = sys::KEY_RED as _, Green = sys::KEY_GREEN as _, Yellow = sys::KEY_YELLOW as _, Blue = sys::KEY_BLUE as _, /// Channel Increment ChannelUp = sys::KEY_CHANNELUP as _, /// Channel Decrement ChannelDown = sys::KEY_CHANNELDOWN as _, First = sys::KEY_FIRST as _, /// Recall Last Last = sys::KEY_LAST as _, Ab = sys::KEY_AB as _, Next = sys::KEY_NEXT as _, Restart = sys::KEY_RESTART as _, Slow = sys::KEY_SLOW as _, Shuffle = sys::KEY_SHUFFLE as _, Break = sys::KEY_BREAK as _, Previous = sys::KEY_PREVIOUS as _, Digits = sys::KEY_DIGITS as _, Teen = sys::KEY_TEEN as _, Twen = sys::KEY_TWEN as _, /// Media Select Video Phone Videophone = sys::KEY_VIDEOPHONE as _, /// Media Select Games Games = sys::KEY_GAMES as _, /// AC Zoom In ZoomIn = sys::KEY_ZOOMIN as _, /// AC Zoom Out ZoomOut = sys::KEY_ZOOMOUT as _, /// AC Zoom ZoomReset = sys::KEY_ZOOMRESET as _, /// AL Word Processor WordProcessor = sys::KEY_WORDPROCESSOR as _, /// AL Text Editor Editor = sys::KEY_EDITOR as _, /// AL Spreadsheet Spreadsheet = sys::KEY_SPREADSHEET as _, /// AL Graphics Editor GraphicsEditor = sys::KEY_GRAPHICSEDITOR as _, /// AL Presentation App Presentation = sys::KEY_PRESENTATION as _, /// AL Database App Database = sys::KEY_DATABASE as _, /// AL Newsreader News = sys::KEY_NEWS as _, /// AL Voicemail Voicemail = sys::KEY_VOICEMAIL as _, /// AL Contacts/Address Book AddressBook = sys::KEY_ADDRESSBOOK as _, /// AL Instant Messaging Messenger = sys::KEY_MESSENGER as _, /// Turn display (LCD) on and off (aka KeyBrightnessToggle) DisplayToggle = sys::KEY_DISPLAYTOGGLE as _, // KeyBrightnessToggle = KeyDisplayToggle /// AL Spell Check SpellCheck = sys::KEY_SPELLCHECK as _, /// AL Logoff Logoff = sys::KEY_LOGOFF as _, Dollar = sys::KEY_DOLLAR as _, Euro = sys::KEY_EURO as _, /// Consumer - transport controls FrameBack = sys::KEY_FRAMEBACK as _, FrameForward = sys::KEY_FRAMEFORWARD as _, /// GenDesc - system context menu ContextMenu = sys::KEY_CONTEXT_MENU as _, /// Consumer - transport control MediaRepeat = sys::KEY_MEDIA_REPEAT as _, /// 10 channels up (10+) TenChannelsUp = sys::KEY_10CHANNELSUP as _, /// 10 channels down (10-) TenChannelsDown = sys::KEY_10CHANNELSDOWN as _, /// AL Image Browser Images = sys::KEY_IMAGES as _, Unknown1BB, Unknown1BC, Unknown1BD, Unknown1BE, Unknown1BF, DelEol = sys::KEY_DEL_EOL as _, DelEos = sys::KEY_DEL_EOS as _, InsLine = sys::KEY_INS_LINE as _, DelLine = sys::KEY_DEL_LINE as _, Unknown1C4, Unknown1C5, Unknown1C6, Unknown1C7, Unknown1C8, Unknown1C9, Unknown1CA, Unknown1CB, Unknown1CC, Unknown1CD, Unknown1CE, Unknown1CF, Fn = sys::KEY_FN as _, FnEsc = sys::KEY_FN_ESC as _, FnF1 = sys::KEY_FN_F1 as _, FnF2 = sys::KEY_FN_F2 as _, FnF3 = sys::KEY_FN_F3 as _, FnF4 = sys::KEY_FN_F4 as _, FnF5 = sys::KEY_FN_F5 as _, FnF6 = sys::KEY_FN_F6 as _, FnF7 = sys::KEY_FN_F7 as _, FnF8 = sys::KEY_FN_F8 as _, FnF9 = sys::KEY_FN_F9 as _, FnF10 = sys::KEY_FN_F10 as _, FnF11 = sys::KEY_FN_F11 as _, FnF12 = sys::KEY_FN_F12 as _, Fn1 = sys::KEY_FN_1 as _, Fn2 = sys::KEY_FN_2 as _, FnD = sys::KEY_FN_D as _, FnE = sys::KEY_FN_E as _, FnF = sys::KEY_FN_F as _, FnS = sys::KEY_FN_S as _, FnB = sys::KEY_FN_B as _, Unknown1E5, Unknown1E6, Unknown1E7, Unknown1E8, Unknown1E9, Unknown1EA, Unknown1EB, Unknown1EC, Unknown1ED, Unknown1EE, Unknown1EF, Unknown1F0, BrlDot1 = sys::KEY_BRL_DOT1 as _, BrlDot2 = sys::KEY_BRL_DOT2 as _, BrlDot3 = sys::KEY_BRL_DOT3 as _, BrlDot4 = sys::KEY_BRL_DOT4 as _, BrlDot5 = sys::KEY_BRL_DOT5 as _, BrlDot6 = sys::KEY_BRL_DOT6 as _, BrlDot7 = sys::KEY_BRL_DOT7 as _, BrlDot8 = sys::KEY_BRL_DOT8 as _, BrlDot9 = sys::KEY_BRL_DOT9 as _, BrlDot10 = sys::KEY_BRL_DOT10 as _, Unknown1FB, Unknown1FC, Unknown1FD, Unknown1FE, Unknown1FF, /// used by phones, remote controls, Numeric0 = sys::KEY_NUMERIC_0 as _, /// and other keypads Numeric1 = sys::KEY_NUMERIC_1 as _, Numeric2 = sys::KEY_NUMERIC_2 as _, Numeric3 = sys::KEY_NUMERIC_3 as _, Numeric4 = sys::KEY_NUMERIC_4 as _, Numeric5 = sys::KEY_NUMERIC_5 as _, Numeric6 = sys::KEY_NUMERIC_6 as _, Numeric7 = sys::KEY_NUMERIC_7 as _, Numeric8 = sys::KEY_NUMERIC_8 as _, Numeric9 = sys::KEY_NUMERIC_9 as _, NumericStar = sys::KEY_NUMERIC_STAR as _, NumericPound = sys::KEY_NUMERIC_POUND as _, /// Phone key A - HUT Telephony 0xb9 NumericA = sys::KEY_NUMERIC_A as _, NumericB = sys::KEY_NUMERIC_B as _, NumericC = sys::KEY_NUMERIC_C as _, NumericD = sys::KEY_NUMERIC_D as _, CameraFocus = sys::KEY_CAMERA_FOCUS as _, /// WiFi Protected Setup key WpsButton = sys::KEY_WPS_BUTTON as _, /// Request switch touchpad on or off TouchpadToggle = sys::KEY_TOUCHPAD_TOGGLE as _, TouchpadOn = sys::KEY_TOUCHPAD_ON as _, TouchpadOff = sys::KEY_TOUCHPAD_OFF as _, CameraZoomin = sys::KEY_CAMERA_ZOOMIN as _, CameraZoomout = sys::KEY_CAMERA_ZOOMOUT as _, CameraUp = sys::KEY_CAMERA_UP as _, CameraDown = sys::KEY_CAMERA_DOWN as _, CameraLeft = sys::KEY_CAMERA_LEFT as _, CameraRight = sys::KEY_CAMERA_RIGHT as _, AttendantOn = sys::KEY_ATTENDANT_ON as _, AttendantOff = sys::KEY_ATTENDANT_OFF as _, /// Attendant call on or off AttendantToggle = sys::KEY_ATTENDANT_TOGGLE as _, /// Reading light on or off LightsToggle = sys::KEY_LIGHTS_TOGGLE as _, Unknown21F, ButtonDpadUp = sys::BTN_DPAD_UP as _, ButtonDpadDown = sys::BTN_DPAD_DOWN as _, ButtonDpadLeft = sys::BTN_DPAD_LEFT as _, ButtonDpadRight = sys::BTN_DPAD_RIGHT as _, Unknown224, Unknown225, Unknown226, Unknown227, Unknown228, Unknown229, Unknown22A, Unknown22B, Unknown22C, Unknown22D, Unknown22E, Unknown22F, /// Ambient light sensor AlsToggle = sys::KEY_ALS_TOGGLE as _, RotateLockToggle = sys::KEY_ROTATE_LOCK_TOGGLE as _, Unknown232, Unknown233, Unknown234, Unknown235, Unknown236, Unknown237, Unknown238, Unknown239, Unknown23A, Unknown23B, Unknown23C, Unknown23D, Unknown23E, Unknown23F, /// AL Button Configuration ButtonConfig = sys::KEY_BUTTONCONFIG as _, /// AL Task/Project Manager TaskManager = sys::KEY_TASKMANAGER as _, /// AL Log/Journal/Timecard Journal = sys::KEY_JOURNAL as _, /// AL Control Panel ControlPanel = sys::KEY_CONTROLPANEL as _, /// AL Select Task/Application AppSelect = sys::KEY_APPSELECT as _, /// AL Screen Saver Screensaver = sys::KEY_SCREENSAVER as _, /// Listening Voice Command Voicecommand = sys::KEY_VOICECOMMAND as _, /// AL Context-aware desktop assistant Assistant = sys::KEY_ASSISTANT as _, /// AC Next Keyboard Layout Select KbdLayoutNext = sys::KEY_KBD_LAYOUT_NEXT as _, /// Show/hide emoji picker (HUTRR101) EmojiPicker = sys::KEY_EMOJI_PICKER as _, /// Start or Stop Voice Dictation Session (HUTRR99) Dictate = sys::KEY_DICTATE as _, /// Enables programmatic access to camera devices. (HUTRR72) CameraAccessEnable = sys::KEY_CAMERA_ACCESS_ENABLE as _, /// Disables programmatic access to camera devices. (HUTRR72) CameraAccessDisable = sys::KEY_CAMERA_ACCESS_DISABLE as _, /// Toggles the current state of the camera access control. (HUTRR72) CameraAccessToggle = sys::KEY_CAMERA_ACCESS_TOGGLE as _, Unknown24E, Unknown24F, /// Set Brightness to Minimum BrightnessMin = sys::KEY_BRIGHTNESS_MIN as _, /// Set Brightness to Maximum BrightnessMax = sys::KEY_BRIGHTNESS_MAX as _, Unknown252, Unknown253, Unknown254, Unknown255, Unknown256, Unknown257, Unknown258, Unknown259, Unknown25A, Unknown25B, Unknown25C, Unknown25D, Unknown25E, Unknown25F, InputAssistPrev = sys::KEY_KBDINPUTASSIST_PREV as _, InputAssistNext = sys::KEY_KBDINPUTASSIST_NEXT as _, InputAssistPrevGroup = sys::KEY_KBDINPUTASSIST_PREVGROUP as _, InputAssistNextGroup = sys::KEY_KBDINPUTASSIST_NEXTGROUP as _, InputAssistAccept = sys::KEY_KBDINPUTASSIST_ACCEPT as _, InputAssistCancel = sys::KEY_KBDINPUTASSIST_CANCEL as _, /// Diagonal movement keys RightUp = sys::KEY_RIGHT_UP as _, RightDown = sys::KEY_RIGHT_DOWN as _, LeftUp = sys::KEY_LEFT_UP as _, LeftDown = sys::KEY_LEFT_DOWN as _, /// Show Device's Root Menu RootMenu = sys::KEY_ROOT_MENU as _, /// Show Top Menu of the Media (e.g. DVD) MediaTopMenu = sys::KEY_MEDIA_TOP_MENU as _, Numeric11 = sys::KEY_NUMERIC_11 as _, Numeric12 = sys::KEY_NUMERIC_12 as _, /// Toggle Audio Description: refers to an audio service that helps blind and /// visually impaired consumers understand the action in a program. Note: in /// some countries this is referred to as "Video Description". AudioDesc = sys::KEY_AUDIO_DESC as _, Audio3dMode = sys::KEY_3D_MODE as _, NextFavorite = sys::KEY_NEXT_FAVORITE as _, StopRecord = sys::KEY_STOP_RECORD as _, PauseRecord = sys::KEY_PAUSE_RECORD as _, /// Video on Demand Vod = sys::KEY_VOD as _, Unmute = sys::KEY_UNMUTE as _, FastReverse = sys::KEY_FASTREVERSE as _, SlowReverse = sys::KEY_SLOWREVERSE as _, /// Control a data application associated with the currently viewed channel, /// e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.) Data = sys::KEY_DATA as _, OnscreenKeyboard = sys::KEY_ONSCREEN_KEYBOARD as _, PrivacyScreenToggle = sys::KEY_PRIVACY_SCREEN_TOGGLE as _, SelectiveScreenshot = sys::KEY_SELECTIVE_SCREENSHOT as _, /// Move the focus to the next user controllable element within a UI container NextElement = sys::KEY_NEXT_ELEMENT as _, /// Move the focus to the previous user controllable element within a UI container PreviousElement = sys::KEY_PREVIOUS_ELEMENT as _, /// Toggle Autopilot engagement AutopilotEngageToggle = sys::KEY_AUTOPILOT_ENGAGE_TOGGLE as _, /// Marine navigation shortcut key MarkWaypoint = sys::KEY_MARK_WAYPOINT as _, /// Marine navigation shortcut key SOS = sys::KEY_SOS as _, /// Marine navigation shortcut key NavChart = sys::KEY_NAV_CHART as _, /// Marine navigation shortcut key FishingChart = sys::KEY_FISHING_CHART as _, /// Marine navigation shortcut key SingleRangeRadar = sys::KEY_SINGLE_RANGE_RADAR as _, /// Marine navigation shortcut key DualRangeRadar = sys::KEY_DUAL_RANGE_RADAR as _, /// Marine navigation shortcut key RadarOverlay = sys::KEY_RADAR_OVERLAY as _, /// Marine navigation shortcut key TraditionalSonar = sys::KEY_TRADITIONAL_SONAR as _, /// Marine navigation shortcut key ClearVuSonar = sys::KEY_CLEARVU_SONAR as _, /// Marine navigation shortcut key SideVuSonar = sys::KEY_SIDEVU_SONAR as _, /// Marine navigation shortcut key NavInfo = sys::KEY_NAV_INFO as _, /// Marine navigation shortcut key BrightnessMenu = sys::KEY_BRIGHTNESS_MENU as _, Unknown28A, Unknown28B, Unknown28C, Unknown28D, Unknown28E, Unknown28F, Macro1 = sys::KEY_MACRO1 as _, Macro2 = sys::KEY_MACRO2 as _, Macro3 = sys::KEY_MACRO3 as _, Macro4 = sys::KEY_MACRO4 as _, Macro5 = sys::KEY_MACRO5 as _, Macro6 = sys::KEY_MACRO6 as _, Macro7 = sys::KEY_MACRO7 as _, Macro8 = sys::KEY_MACRO8 as _, Macro9 = sys::KEY_MACRO9 as _, Macro10 = sys::KEY_MACRO10 as _, Macro11 = sys::KEY_MACRO11 as _, Macro12 = sys::KEY_MACRO12 as _, Macro13 = sys::KEY_MACRO13 as _, Macro14 = sys::KEY_MACRO14 as _, Macro15 = sys::KEY_MACRO15 as _, Macro16 = sys::KEY_MACRO16 as _, Macro17 = sys::KEY_MACRO17 as _, Macro18 = sys::KEY_MACRO18 as _, Macro19 = sys::KEY_MACRO19 as _, Macro20 = sys::KEY_MACRO20 as _, Macro21 = sys::KEY_MACRO21 as _, Macro22 = sys::KEY_MACRO22 as _, Macro23 = sys::KEY_MACRO23 as _, Macro24 = sys::KEY_MACRO24 as _, Macro25 = sys::KEY_MACRO25 as _, Macro26 = sys::KEY_MACRO26 as _, Macro27 = sys::KEY_MACRO27 as _, Macro28 = sys::KEY_MACRO28 as _, Macro29 = sys::KEY_MACRO29 as _, Macro30 = sys::KEY_MACRO30 as _, Unknown2AE, Unknown2AF, MacroRecordStart = sys::KEY_MACRO_RECORD_START as _, MacroRecordStop = sys::KEY_MACRO_RECORD_STOP as _, MacroPresetCycle = sys::KEY_MACRO_PRESET_CYCLE as _, MacroPreset1 = sys::KEY_MACRO_PRESET1 as _, MacroPreset2 = sys::KEY_MACRO_PRESET2 as _, MacroPreset3 = sys::KEY_MACRO_PRESET3 as _, Unknown2B6, Unknown2B7, KbdLcdMenu1 = sys::KEY_KBD_LCD_MENU1 as _, KbdLcdMenu2 = sys::KEY_KBD_LCD_MENU2 as _, KbdLcdMenu3 = sys::KEY_KBD_LCD_MENU3 as _, KbdLcdMenu4 = sys::KEY_KBD_LCD_MENU4 as _, KbdLcdMenu5 = sys::KEY_KBD_LCD_MENU5 as _, Unknown2BD, Unknown2BE, Unknown2BF, ButtonTriggerHappy1 = sys::BTN_TRIGGER_HAPPY1 as _, ButtonTriggerHappy2 = sys::BTN_TRIGGER_HAPPY2 as _, ButtonTriggerHappy3 = sys::BTN_TRIGGER_HAPPY3 as _, ButtonTriggerHappy4 = sys::BTN_TRIGGER_HAPPY4 as _, ButtonTriggerHappy5 = sys::BTN_TRIGGER_HAPPY5 as _, ButtonTriggerHappy6 = sys::BTN_TRIGGER_HAPPY6 as _, ButtonTriggerHappy7 = sys::BTN_TRIGGER_HAPPY7 as _, ButtonTriggerHappy8 = sys::BTN_TRIGGER_HAPPY8 as _, ButtonTriggerHappy9 = sys::BTN_TRIGGER_HAPPY9 as _, ButtonTriggerHappy10 = sys::BTN_TRIGGER_HAPPY10 as _, ButtonTriggerHappy11 = sys::BTN_TRIGGER_HAPPY11 as _, ButtonTriggerHappy12 = sys::BTN_TRIGGER_HAPPY12 as _, ButtonTriggerHappy13 = sys::BTN_TRIGGER_HAPPY13 as _, ButtonTriggerHappy14 = sys::BTN_TRIGGER_HAPPY14 as _, ButtonTriggerHappy15 = sys::BTN_TRIGGER_HAPPY15 as _, ButtonTriggerHappy16 = sys::BTN_TRIGGER_HAPPY16 as _, ButtonTriggerHappy17 = sys::BTN_TRIGGER_HAPPY17 as _, ButtonTriggerHappy18 = sys::BTN_TRIGGER_HAPPY18 as _, ButtonTriggerHappy19 = sys::BTN_TRIGGER_HAPPY19 as _, ButtonTriggerHappy20 = sys::BTN_TRIGGER_HAPPY20 as _, ButtonTriggerHappy21 = sys::BTN_TRIGGER_HAPPY21 as _, ButtonTriggerHappy22 = sys::BTN_TRIGGER_HAPPY22 as _, ButtonTriggerHappy23 = sys::BTN_TRIGGER_HAPPY23 as _, ButtonTriggerHappy24 = sys::BTN_TRIGGER_HAPPY24 as _, ButtonTriggerHappy25 = sys::BTN_TRIGGER_HAPPY25 as _, ButtonTriggerHappy26 = sys::BTN_TRIGGER_HAPPY26 as _, ButtonTriggerHappy27 = sys::BTN_TRIGGER_HAPPY27 as _, ButtonTriggerHappy28 = sys::BTN_TRIGGER_HAPPY28 as _, ButtonTriggerHappy29 = sys::BTN_TRIGGER_HAPPY29 as _, ButtonTriggerHappy30 = sys::BTN_TRIGGER_HAPPY30 as _, ButtonTriggerHappy31 = sys::BTN_TRIGGER_HAPPY31 as _, ButtonTriggerHappy32 = sys::BTN_TRIGGER_HAPPY32 as _, ButtonTriggerHappy33 = sys::BTN_TRIGGER_HAPPY33 as _, ButtonTriggerHappy34 = sys::BTN_TRIGGER_HAPPY34 as _, ButtonTriggerHappy35 = sys::BTN_TRIGGER_HAPPY35 as _, ButtonTriggerHappy36 = sys::BTN_TRIGGER_HAPPY36 as _, ButtonTriggerHappy37 = sys::BTN_TRIGGER_HAPPY37 as _, ButtonTriggerHappy38 = sys::BTN_TRIGGER_HAPPY38 as _, ButtonTriggerHappy39 = sys::BTN_TRIGGER_HAPPY39 as _, ButtonTriggerHappy40 = sys::BTN_TRIGGER_HAPPY40 as _, Unknown2E8, Unknown2E9, Unknown2EA, Unknown2EB, Unknown2EC, Unknown2ED, Unknown2EE, Unknown2EF, Unknown2F0, Unknown2F1, Unknown2F2, Unknown2F3, Unknown2F4, Unknown2F5, Unknown2F6, Unknown2F7, Unknown2F8, Unknown2F9, Unknown2FA, Unknown2FB, Unknown2FC, Unknown2FD, Unknown2FE, Unknown2FF, } impl_iterable! { Key(0, sys::KEY_CNT) } impl Key { /// Determines whether the given value represents a button. /// /// Buttons are often found on a mouse or gamepad. pub const fn is_button(&self) -> bool { let key = *self as u16; ((key >= Key::Button0 as _) & (key < Key::Ok as _)) | (key >= Key::ButtonTriggerHappy1 as _) } /// Determines whether the given value represents a keyboard key. pub const fn is_key(&self) -> bool { !self.is_button() } } input-linux-0.6.0/src/kinds.rs000064400000000000000000000324501046102023000143740ustar 00000000000000use std::convert::TryFrom; use std::mem::transmute; use std::{io, fmt, error}; use crate::{Key, sys}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// Indicates that a value or event type code was out of range. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct RangeError; impl From for io::Error { fn from(e: RangeError) -> Self { io::Error::new(io::ErrorKind::InvalidData, e.to_string()) } } impl error::Error for RangeError {} impl fmt::Display for RangeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "event code out of range") } } /// Device properties and quirks. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum InputProperty { Pointer = sys::INPUT_PROP_POINTER as _, Direct = sys::INPUT_PROP_DIRECT as _, ButtonPad = sys::INPUT_PROP_BUTTONPAD as _, SemiMultiTouch = sys::INPUT_PROP_SEMI_MT as _, TopButtonPad = sys::INPUT_PROP_TOPBUTTONPAD as _, PointingStick = sys::INPUT_PROP_POINTING_STICK as _, Accelerometer = sys::INPUT_PROP_ACCELEROMETER as _, Unknown07, Unknown08, Unknown09, Unknown0A, Unknown0B, Unknown0C, Unknown0D, Unknown0E, Unknown0F, Unknown10, Unknown11, Unknown12, Unknown13, Unknown14, Unknown15, Unknown16, Unknown17, Unknown18, Unknown19, Unknown1A, Unknown1B, Unknown1C, Unknown1D, Unknown1E, Unknown1F, } /// Event types #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum EventKind { Synchronize = sys::EV_SYN as _, Key = sys::EV_KEY as _, Relative = sys::EV_REL as _, Absolute = sys::EV_ABS as _, Misc = sys::EV_MSC as _, Switch = sys::EV_SW as _, Unknown6, Unknown7, Unknown8, Unknown9, UnknownA, UnknownB, UnknownC, UnknownD, UnknownE, UnknownF, Unknown10, Led = sys::EV_LED as _, Sound = sys::EV_SND as _, Unknown13, Autorepeat = sys::EV_REP as _, ForceFeedback = sys::EV_FF as _, Power = sys::EV_PWR as _, ForceFeedbackStatus = sys::EV_FF_STATUS as _, Unknown18, Unknown19, Unknown1A, Unknown1B, Unknown1C, Unknown1D, Unknown1E, Unknown1F, UInput = sys::EV_UINPUT as _, } /// UInput feedback events. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum UInputKind { Unknown0 = 0, ForceFeedbackUpload = sys::UI_FF_UPLOAD as _, ForceFeedbackErase = sys::UI_FF_ERASE as _, } /// Synchronization events. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum SynchronizeKind { Report = sys::SYN_REPORT as _, Config = sys::SYN_CONFIG as _, MultitouchReport = sys::SYN_MT_REPORT as _, Dropped = sys::SYN_DROPPED as _, Unknown4, Unknown5, Unknown6, Unknown7, Unknown8, Unknown9, UnknownA, UnknownB, UnknownC, UnknownD, UnknownE, UnknownF, } /// Key event value states. #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[allow(missing_docs)] #[repr(transparent)] pub struct KeyState { pub value: i32, } #[allow(missing_docs)] impl KeyState { pub const RELEASED: Self = KeyState { value: 0 }; pub const PRESSED: Self = KeyState { value: 1 }; pub const AUTOREPEAT: Self = KeyState { value: 2 }; pub const fn is_pressed(&self) -> bool { self.value == 1 } pub const fn pressed(pressed: bool) -> Self { Self { value: pressed as i32, } } } /// Relative axes. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum RelativeAxis { X = sys::REL_X as _, Y = sys::REL_Y as _, Z = sys::REL_Z as _, RX = sys::REL_RX as _, RY = sys::REL_RY as _, RZ = sys::REL_RZ as _, HorizontalWheel = sys::REL_HWHEEL as _, Dial = sys::REL_DIAL as _, Wheel = sys::REL_WHEEL as _, Misc = sys::REL_MISC as _, Reserved = sys::REL_RESERVED as _, WheelHiRes = sys::REL_WHEEL_HI_RES as _, HorizontalWheelHiRes = sys::REL_HWHEEL_HI_RES as _, UnknownD, UnknownE, UnknownF, } /// Absolute axes. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum AbsoluteAxis { X = sys::ABS_X as _, Y = sys::ABS_Y as _, Z = sys::ABS_Z as _, RX = sys::ABS_RX as _, RY = sys::ABS_RY as _, RZ = sys::ABS_RZ as _, Throttle = sys::ABS_THROTTLE as _, Rudder = sys::ABS_RUDDER as _, Wheel = sys::ABS_WHEEL as _, Gas = sys::ABS_GAS as _, Brake = sys::ABS_BRAKE as _, UnknownB, UnknownC, UnknownD, UnknownE, UnknownF, Hat0X = sys::ABS_HAT0X as _, Hat0Y = sys::ABS_HAT0Y as _, Hat1X = sys::ABS_HAT1X as _, Hat1Y = sys::ABS_HAT1Y as _, Hat2X = sys::ABS_HAT2X as _, Hat2Y = sys::ABS_HAT2Y as _, Hat3X = sys::ABS_HAT3X as _, Hat3Y = sys::ABS_HAT3Y as _, Pressure = sys::ABS_PRESSURE as _, Distance = sys::ABS_DISTANCE as _, TiltX = sys::ABS_TILT_X as _, TiltY = sys::ABS_TILT_Y as _, ToolWidth = sys::ABS_TOOL_WIDTH as _, Unknown1D, Unknown1E, Unknown1F, Volume = sys::ABS_VOLUME as _, Profile = sys::ABS_PROFILE as _, Unknown22, Unknown23, Unknown24, Unknown25, Unknown26, Unknown27, Misc = sys::ABS_MISC as _, Unknown29, Unknown2A, Unknown2B, Unknown2C, Unknown2D, Reserved = sys::ABS_RESERVED as _, /// MT slot being modified MultitouchSlot = sys::ABS_MT_SLOT as _, /// Major axis of touching ellipse MultitouchTouchMajor = sys::ABS_MT_TOUCH_MAJOR as _, /// Minor axis (omit if circular) MultitouchTouchMinor = sys::ABS_MT_TOUCH_MINOR as _, /// Major axis of approaching ellipse MultitouchWidthMajor = sys::ABS_MT_WIDTH_MAJOR as _, /// Minor axis (omit if circular) MultitouchWidthMinor = sys::ABS_MT_WIDTH_MINOR as _, /// Ellipse orientation MultitouchOrientation = sys::ABS_MT_ORIENTATION as _, /// Center X touch position MultitouchPositionX = sys::ABS_MT_POSITION_X as _, /// Center Y touch position MultitouchPositionY = sys::ABS_MT_POSITION_Y as _, /// Type of touching device MultitouchToolType = sys::ABS_MT_TOOL_TYPE as _, /// Group a set of packets as a blob MultitouchBlobId = sys::ABS_MT_BLOB_ID as _, /// Unique ID of initiated contact MultitouchTrackingId = sys::ABS_MT_TRACKING_ID as _, /// Pressure on contact area MultitouchPressure = sys::ABS_MT_PRESSURE as _, /// Contact hover distance MultitouchDistance = sys::ABS_MT_DISTANCE as _, /// Center X tool position MultitouchToolX = sys::ABS_MT_TOOL_X as _, /// Center Y tool position MultitouchToolY = sys::ABS_MT_TOOL_Y as _, Unknown3E, Unknown3F, } /// Switch events. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum SwitchKind { /// set = lid shut Lid = sys::SW_LID as _, /// set = tablet mode TabletMode = sys::SW_TABLET_MODE as _, /// set = inserted HeadphoneInsert = sys::SW_HEADPHONE_INSERT as _, /// set = radio enabled RfKillAll = sys::SW_RFKILL_ALL as _, // Radio = sys::SW_RADIO as _ = RfKillAll, /// set = inserted MicrophoneInsert = sys::SW_MICROPHONE_INSERT as _, /// set = plugged into dock Dock = sys::SW_DOCK as _, /// set = inserted LineoutInsert = sys::SW_LINEOUT_INSERT as _, /// set = mechanical switch set JackPhysicalInsert = sys::SW_JACK_PHYSICAL_INSERT as _, /// set = inserted VideoOutInsert = sys::SW_VIDEOOUT_INSERT as _, /// set = lens covered CameraLensCover = sys::SW_CAMERA_LENS_COVER as _, /// set = keypad slide out KeypadSlide = sys::SW_KEYPAD_SLIDE as _, /// set = front proximity sensor active FrontProximity = sys::SW_FRONT_PROXIMITY as _, /// set = rotate locked/disabled RotateLock = sys::SW_ROTATE_LOCK as _, /// set = inserted LineInInsert = sys::SW_LINEIN_INSERT as _, /// set = device disabled MuteDevice = sys::SW_MUTE_DEVICE as _, /// set = pen inserted PenInserted = sys::SW_PEN_INSERTED as _, MachineCover = sys::SW_MACHINE_COVER as _, } /// Miscellaneous events. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum MiscKind { /// Serial number, only exported for tablets ("Transducer Serial Number") Serial = sys::MSC_SERIAL as _, /// Only used by the PowerMate driver, right now. PulseLed = sys::MSC_PULSELED as _, /// Completely unused Gesture = sys::MSC_GESTURE as _, /// "Raw" event, rarely used. Raw = sys::MSC_RAW as _, /// Key scancode Scancode = sys::MSC_SCAN as _, /// Completely unused Timestamp = sys::MSC_TIMESTAMP as _, Unknown6, Unknown7, } /// LEDs. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum LedKind { NumLock = sys::LED_NUML as _, CapsLock = sys::LED_CAPSL as _, ScrollLock = sys::LED_SCROLLL as _, Compose = sys::LED_COMPOSE as _, Kana = sys::LED_KANA as _, Sleep = sys::LED_SLEEP as _, Suspend = sys::LED_SUSPEND as _, Mute = sys::LED_MUTE as _, Misc = sys::LED_MISC as _, Mail = sys::LED_MAIL as _, Charging = sys::LED_CHARGING as _, UnknownB, UnknownC, UnknownD, UnknownE, UnknownF, } /// Autorepeat values. #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum AutorepeatKind { Delay = sys::REP_DELAY as _, Period = sys::REP_PERIOD as _, } /// Sounds #[repr(u16)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[allow(missing_docs)] pub enum SoundKind { Click = sys::SND_CLICK as _, Bell = sys::SND_BELL as _, Tone = sys::SND_TONE as _, Unknown3, Unknown4, Unknown5, Unknown6, Unknown7, } impl_iterable! { InputProperty(0, sys::INPUT_PROP_CNT) } impl EventKind { /// Instantiate from a type code. pub fn from_type(code: u16) -> Result { const EV_UINPUT: u16 = sys::EV_UINPUT as _; match code { 0..=0x1f | EV_UINPUT => Ok(unsafe { transmute(code) }), _ => Err(Default::default()), } } /// Returns the maximum known number of codes for the current event pub fn count(&self) -> Result { match *self { EventKind::Synchronize => Ok(SynchronizeKind::COUNT), EventKind::Key => Ok(Key::COUNT), EventKind::Relative => Ok(RelativeAxis::COUNT), EventKind::Absolute => Ok(AbsoluteAxis::COUNT), EventKind::Misc => Ok(MiscKind::COUNT), EventKind::Switch => Ok(SwitchKind::COUNT), EventKind::Led => Ok(LedKind::COUNT), EventKind::Sound => Ok(SoundKind::COUNT), EventKind::Autorepeat => Ok(AutorepeatKind::COUNT), EventKind::UInput => Ok(UInputKind::COUNT), _ => Err(()), } } /// Like [`count`](Self::count) but with an exception for /// [`Synchronize`](Self::Synchronize) representing `EventKind`, matching /// the behaviour of `EVIOCGBIT` and `EVIOCGMASK`. If you're using a /// bitmask you probably want this. pub fn count_bits(&self) -> Result { match *self { EventKind::Synchronize => Ok(EventKind::COUNT), _ => self.count(), } } } impl TryFrom for EventKind { type Error = RangeError; fn try_from(code: u16) -> Result { Self::from_type(code) } } impl_iterable! { @nofromcode EventKind(0, sys::EV_CNT) } impl_iterable! { UInputKind(0, sys::UI_FF_ERASE + 1) } impl_iterable! { SynchronizeKind(0, sys::SYN_CNT) } impl From for KeyState { fn from(key: i32) -> Self { unsafe { transmute(key) } } } impl From for i32 { fn from(k: KeyState) -> Self { k.value } } #[cfg(feature = "serde")] mod key_state_serde { use serde::{Deserialize, Deserializer, Serialize, Serializer}; use super::KeyState as KeyStateSuper; #[derive(Serialize, Deserialize)] #[serde(untagged)] enum KeyState { Released, Pressed, Autorepeat, Unknown(i32), } impl From for KeyStateSuper { #[inline(always)] fn from(k: KeyState) -> Self { match k { KeyState::Released => KeyStateSuper::RELEASED, KeyState::Pressed => KeyStateSuper::PRESSED, KeyState::Autorepeat => KeyStateSuper::AUTOREPEAT, KeyState::Unknown(v) => v.into(), } } } impl From for KeyState { #[inline(always)] fn from(k: KeyStateSuper) -> Self { match k { KeyStateSuper::RELEASED => KeyState::Released, KeyStateSuper::PRESSED => KeyState::Pressed, KeyStateSuper::AUTOREPEAT => KeyState::Autorepeat, KeyStateSuper { value } => KeyState::Unknown(value), } } } impl<'de> Deserialize<'de> for KeyStateSuper { fn deserialize>(deserializer: D) -> Result { KeyState::deserialize(deserializer).map(From::from) } } impl Serialize for KeyStateSuper { fn serialize(&self, serializer: S) -> Result { KeyState::from(*self).serialize(serializer) } } } impl_iterable! { RelativeAxis(0, sys::REL_CNT) } impl_iterable! { AbsoluteAxis(0, sys::ABS_CNT) } impl_iterable! { SwitchKind(0, sys::SW_CNT) } impl_iterable! { MiscKind(0, sys::MSC_CNT) } impl_iterable! { LedKind(0, sys::LED_CNT) } impl_iterable! { AutorepeatKind(0, sys::REP_CNT) } impl_iterable! { SoundKind(0, sys::SND_CNT) } input-linux-0.6.0/src/lib.rs000064400000000000000000000101451046102023000140270ustar 00000000000000#![deny(missing_docs)] #![doc(html_root_url = "https://docs.rs/input-linux/0.6.0/")] #![cfg_attr(feature = "dox", feature(doc_cfg))] //! Userspace bindings to the Linux evdev and uinput subsystems. //! //! Start by looking at the [`EvdevHandle`] and [`UInputHandle`] types. pub use input_linux_sys as sys; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize, }; #[macro_use] mod macros; mod kinds; pub use crate::kinds::*; mod time; pub use crate::time::EventTime; mod events; pub use crate::events::*; mod keys; pub use crate::keys::Key; pub mod evdev; pub use crate::evdev::EvdevHandle; pub mod uinput; pub use crate::uinput::UInputHandle; pub mod enum_iterator; pub mod bitmask; pub use crate::bitmask::Bitmask; #[cfg(feature = "codec")] #[cfg_attr(feature = "dox", doc(cfg(feature = "codec")))] mod codec; #[cfg(feature = "codec")] pub use crate::codec::EventCodec; #[repr(C)] #[derive(Copy, Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Identifies an input device. pub struct InputId { /// Identifies the bus where the input device is found, see `sys::BUS_*` pub bustype: u16, /// The vendor ID of the input device. pub vendor: u16, /// The product ID of the input device. pub product: u16, /// The version of the input device. pub version: u16, } impl<'a> From<&'a sys::input_id> for &'a InputId { fn from(id: &'a sys::input_id) -> Self { let raw = id as *const _ as *const _; unsafe { &*raw } } } impl<'a> From<&'a InputId> for &'a sys::input_id { fn from(id: &'a InputId) -> Self { let raw = id as *const _ as *const _; unsafe { &*raw } } } impl From for InputId { fn from(id: sys::input_id) -> Self { *<&InputId>::from(&id) } } impl From for sys::input_id { fn from(id: InputId) -> Self { *<&sys::input_id>::from(&id) } } #[repr(C)] #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// A descriptor used to create a virtual uinput absolute axis. pub struct AbsoluteInfoSetup { /// The axis to attach the `AbsoluteInfo` constraints to. pub axis: AbsoluteAxis, /// Describes the capabilities of the absolute axis. pub info: AbsoluteInfo, } impl<'a> From<&'a AbsoluteInfoSetup> for &'a sys::uinput_abs_setup { fn from(info: &'a AbsoluteInfoSetup) -> Self { let raw = info as *const _ as *const _; unsafe { &*raw } } } impl From for sys::uinput_abs_setup { fn from(info: AbsoluteInfoSetup) -> Self { use std::mem; unsafe { mem::transmute(info) } } } #[repr(C)] #[derive(Copy, Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] /// Describes the capabilities and constraints of an input device's absolute axis. pub struct AbsoluteInfo { /// latest reported value for the axis pub value: i32, /// specifies minimum value for the axis pub minimum: i32, /// specifies maximum value for the axis pub maximum: i32, /// specifies fuzz value that is used to filter noise from the event stream pub fuzz: i32, /// values that are within this value will be discarded by joydev interface and reported as 0 instead pub flat: i32, /// specifies resolution for the values reported for the axis /// /// Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in units per /// millimeter (units/mm), resolution for rotational axes (ABS_RX, ABS_RY, /// ABS_RZ) is reported in units per radian. pub resolution: i32, } impl<'a> From<&'a sys::input_absinfo> for &'a AbsoluteInfo { fn from(info: &'a sys::input_absinfo) -> Self { let raw = info as *const _ as *const _; unsafe { &*raw } } } impl<'a> From<&'a AbsoluteInfo> for &'a sys::input_absinfo { fn from(info: &'a AbsoluteInfo) -> Self { let raw = info as *const _ as *const _; unsafe { &*raw } } } impl From for AbsoluteInfo { fn from(info: sys::input_absinfo) -> Self { *<&AbsoluteInfo>::from(&info) } } impl From for sys::input_absinfo { fn from(info: AbsoluteInfo) -> Self { *<&sys::input_absinfo>::from(&info) } } input-linux-0.6.0/src/macros.rs000064400000000000000000000113771046102023000145550ustar 00000000000000use std::io; use crate::sys; pub(crate) const STRING_BUFFER_LENGTH: usize = 0x200; pub(crate) fn convert_error(e: sys::Error) -> io::Error { e.into() } macro_rules! impl_iterable { (@impliter $name: ident($start:expr, $count:expr)) => { impl crate::bitmask::BitmaskTrait for $name { type Array = [u8; (Self::COUNT + 7) / 8]; type Index = $name; const ZERO: Self::Array = [0u8; (Self::COUNT + 7) / 8]; fn array_default() -> Self::Array { unsafe {std::mem::zeroed() } } fn array_slice(array: &Self::Array) -> &[u8] { array } fn array_slice_mut(array: &mut Self::Array) -> &mut [u8] { array } fn index(index: Self::Index) -> usize { index as usize } } impl crate::enum_iterator::IterableEnum for $name { fn iter_next(v: usize) -> Option<(usize, Self)> { if v < Self::COUNT { unsafe { Some((v + 1, std::mem::transmute(v as u16))) } } else { None } } fn iter() -> crate::enum_iterator::EnumIterator { crate::enum_iterator::EnumIterator::new($start) } } impl $name { /// The maximum valid value. pub const COUNT: usize = $count as usize; /// An iterator over all values of the enum. pub fn iter() -> crate::enum_iterator::EnumIterator { crate::enum_iterator::IterableEnum::iter() } /// A bitmask that can contain all values of the enum. pub fn bitmask() -> crate::bitmask::Bitmask { Default::default() } } impl From<$name> for u16 { fn from(v: $name) -> Self { v as _ } } }; (@implcode $name: ident($start:expr, $count:expr)) => { impl $name { /// Instantiates the enum from a raw code value. pub fn from_code(code: u16) -> Result { use std::mem; if code < Self::COUNT as u16 { Ok(unsafe { mem::transmute(code) }) } else { Err(crate::kinds::RangeError) } } } impl std::convert::TryFrom for $name { type Error = crate::kinds::RangeError; fn try_from(code: u16) -> Result { Self::from_code(code) } } }; ($name: ident($start:expr, $count:expr)) => { impl_iterable! { @impliter $name($start, $count) } impl_iterable! { @implcode $name($start, $count) } }; (@nofromcode $name: ident($start:expr, $count:expr)) => { impl_iterable! { @impliter $name($start, $count) } }; } macro_rules! ioctl_impl { ($(#[$attr:meta])* @get $f:ident = $ev:ident -> $ret:ty) => { $(#[$attr])* pub fn $f(&self) -> io::Result<$ret> { unsafe { let mut v = std::mem::MaybeUninit::uninit(); sys::$ev(self.fd(), &mut *v.as_mut_ptr()) .map(|_| v.assume_init().into()) .map_err(crate::macros::convert_error) } } }; ($(#[$attr:meta])* @call $f:ident = $ev:ident) => { $(#[$attr])* pub fn $f(&self) -> io::Result<()> { unsafe { sys::$ev(self.fd()) .map(drop) .map_err(crate::macros::convert_error) } } }; ($(#[$attr:meta])* @get_buf $f:ident($ty:ty) = $ev:ident) => { $(#[$attr])* pub fn $f(&self, buffer: &mut [$ty]) -> io::Result { unsafe { sys::$ev(self.fd(), &mut *(buffer as *mut [$ty] as *mut [_])) .map(|len| len as _) .map_err(crate::macros::convert_error) } } }; ($(#[$attr:meta])* @get_str $f:ident, $fbuf:ident = $ev:ident) => { ioctl_impl! { $(#[$attr])* @get_buf $fbuf(u8) = $ev } $(#[$attr])* pub fn $f(&self) -> io::Result> { let mut buf = vec![0; crate::macros::STRING_BUFFER_LENGTH]; self.$fbuf(&mut buf[..]).map(move |len| { buf.truncate(len as _); buf }) } }; ($(#[$attr:meta])* @set_str $f:ident = $ev:ident) => { $(#[$attr])* pub fn $f(&self, value: &::std::ffi::CStr) -> io::Result<()> { unsafe { sys::$ev(self.fd(), value.as_ptr()) .map(drop) .map_err(crate::macros::convert_error) } } }; ($(#[$attr:meta])* @set $f:ident($in:ty) = $ev:ident) => { $(#[$attr])* pub fn $f(&self, value: $in) -> io::Result<()> { unsafe { sys::$ev(self.fd(), value as _) .map(drop) .map_err(crate::macros::convert_error) } } }; ($({ $($tt:tt)* })*) => { $( ioctl_impl! {$($tt)*} )* }; } macro_rules! impl_bitmasks { { $kind:path, $event: expr, $name_mask:ident, $name_mask_set:ident, $name_bits:ident } => { /// `EVIOCGMASK` pub fn $name_mask(&self) -> io::Result> { let mut bitmask = crate::bitmask::Bitmask::default(); self.event_mask_raw($event, &mut bitmask).map(|_| bitmask) } /// `EVIOCSMASK` pub fn $name_mask_set(&self, bitmask: &crate::bitmask::Bitmask<$kind>) -> io::Result<()> { self.set_event_mask_raw($event, bitmask) } /// `EVIOCGBIT` pub fn $name_bits(&self) -> io::Result> { let mut bitmask = crate::bitmask::Bitmask::default(); self.event_bits_raw($event, &mut bitmask).map(|_| bitmask) } }; } input-linux-0.6.0/src/time.rs000064400000000000000000000064271046102023000142270ustar 00000000000000use std::{fmt, cmp}; use std::hash::{Hash, Hasher}; use std::ops::{Deref, DerefMut}; use crate::sys::timeval; use nix::libc::{time_t, suseconds_t}; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize}; /// An event timestamp. #[repr(C)] #[derive(Copy, Clone)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct EventTime( #[cfg_attr(feature = "serde", serde(with = "TimevalDef"))] timeval ); #[cfg(feature = "serde")] #[derive(Serialize, Deserialize)] #[serde(remote = "timeval")] #[allow(dead_code)] struct TimevalDef { tv_sec: i64, tv_usec: i64, } impl EventTime { /// Create a new timestamp. pub const fn new(secs: i64, usecs: i64) -> Self { EventTime(timeval { tv_sec: secs as time_t, tv_usec: usecs as suseconds_t, }) } /// Create a timestamp given a libc [`timeval`]. pub const fn from_timeval(time: timeval) -> Self { EventTime(time) } /// The timestamp represented as seconds since an epoch. pub const fn seconds(&self) -> i64 { (self.0).tv_sec as i64 } /// Set the seconds component of the timestamp. pub fn set_seconds(&mut self, value: i64) { (self.0).tv_sec = value as time_t } /// The microseconds component of the seconds. /// /// This is meant to be modulo one second, though any value is technically /// valid. pub const fn microseconds(&self) -> i64 { (self.0).tv_usec as i64 } /// Set the microseconds component of the timestamp. pub fn set_microseconds(&mut self, value: i64) { (self.0).tv_usec = value as suseconds_t } /// The inner `libc` [`timeval`]. pub const fn into_inner(self) -> timeval { self.0 } } impl Default for EventTime { fn default() -> Self { Self::new(0, 0) } } impl fmt::Debug for EventTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("EventTime") .field("seconds", &(self.0).tv_sec) .field("microseconds", &(self.0).tv_usec) .finish() } } impl From for EventTime { fn from(time: timeval) -> Self { EventTime::from_timeval(time) } } impl From for timeval { fn from(time: EventTime) -> Self { time.into_inner() } } impl Deref for EventTime { type Target = timeval; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for EventTime { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl AsRef for EventTime { fn as_ref(&self) -> &timeval { &self.0 } } impl<'a> From<&'a timeval> for &'a EventTime { fn from(time: &'a timeval) -> Self { unsafe { let raw = time as *const _ as *const _; &*raw } } } impl<'a> From<&'a mut timeval> for &'a mut EventTime { fn from(time: &'a mut timeval) -> Self { unsafe { let raw = time as *mut _ as *mut _; &mut *raw } } } impl PartialOrd for EventTime { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl PartialEq for EventTime { fn eq(&self, other: &Self) -> bool { (self.0).tv_sec == (other.0).tv_sec && (self.0).tv_usec == (other.0).tv_usec } } impl Hash for EventTime { fn hash(&self, state: &mut H) { (self.0).tv_sec.hash(state); (self.0).tv_usec.hash(state); } } impl Ord for EventTime { fn cmp(&self, other: &Self) -> cmp::Ordering { (self.0).tv_sec.cmp(&(other.0).tv_sec) .then((self.0).tv_usec.cmp(&(other.0).tv_usec)) } } impl Eq for EventTime {} input-linux-0.6.0/src/tokio_impl.rs000064400000000000000000000007171046102023000154330ustar 00000000000000use crate::{EventCodec, InputEvent}; use bytes::BytesMut; use std::io::Error; impl Decoder for EventCodec { type Item = InputEvent; type Error = Error; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { self.decode_bytes(src) } } impl Encoder for EventCodec { type Error = Error; fn encode(&mut self, item: InputEvent, dst: &mut BytesMut) -> Result<(), Self::Error> { self.encode_bytes(item, dst) } } input-linux-0.6.0/src/uinput.rs000064400000000000000000000162221046102023000146070ustar 00000000000000//! An interface to the Linux uinput kernel module that can be used to create //! virtual input devices. use std::{io, fs, ptr}; use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd, FromRawFd}; use std::os::unix::ffi::OsStrExt; use std::os::raw::c_char; use std::mem::{MaybeUninit, size_of}; use std::path::{Path, PathBuf}; use std::slice::{from_raw_parts, from_raw_parts_mut}; use std::ffi::{OsStr, OsString, CStr}; use crate::sys; use nix; use crate::{Key, InputId, AbsoluteInfoSetup, kinds}; use crate::macros::{convert_error}; pub use crate::sys::{UINPUT_MAX_NAME_SIZE, UINPUT_VERSION}; /// A handle to a uinput allowing the use of ioctls pub struct UInputHandle(F); fn copy_name(dest: &mut [c_char; UINPUT_MAX_NAME_SIZE as usize], name: &[u8]) -> io::Result<()> { if name.len() >= UINPUT_MAX_NAME_SIZE as usize { Err(io::Error::new(io::ErrorKind::InvalidInput, "name too long")) } else { unsafe { ptr::copy_nonoverlapping(name.as_ptr() as *const _, dest.as_mut_ptr() as *mut _, name.len()); } dest[name.len()] = 0; Ok(()) } } impl UInputHandle { /// Create a new handle using an existing open file object. pub const fn new(fd: F) -> Self { UInputHandle(fd) } /// Extracts the contained handle. pub fn into_inner(self) -> F { self.0 } /// A reference to the contained handle. pub const fn as_inner(&self) -> &F { &self.0 } /// A mutable reference to the contained handle. pub fn as_inner_mut(&mut self) -> &mut F { &mut self.0 } } impl IntoRawFd for UInputHandle { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } impl FromRawFd for UInputHandle { unsafe fn from_raw_fd(fd: RawFd) -> Self { UInputHandle(FromRawFd::from_raw_fd(fd)) } } impl UInputHandle { /// Create a new handle from a raw file descriptor. pub unsafe fn from_fd(fd: RawFd) -> Self { FromRawFd::from_raw_fd(fd) } } impl UInputHandle { #[inline] fn fd(&self) -> RawFd { self.0.as_raw_fd() } /// Create a new uinput device using the legacy `UI_DEV_CREATE` interface pub fn create_legacy(&self, id: &InputId, name: &[u8], ff_effects_max: u32, abs: &[AbsoluteInfoSetup]) -> io::Result<()> { let mut setup: sys::uinput_user_dev = unsafe { MaybeUninit::zeroed().assume_init() }; setup.id = (*id).into(); setup.ff_effects_max = ff_effects_max; copy_name(&mut setup.name, name)?; for abs in abs { let code = abs.axis as usize; if code >= sys::ABS_CNT as _ { return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid abs axis code")) } let abs = &abs.info; setup.absmax[code] = abs.maximum; setup.absmin[code] = abs.minimum; setup.absfuzz[code] = abs.fuzz; setup.absflat[code] = abs.flat; } let setup = unsafe { from_raw_parts(&setup as *const _ as *const u8, size_of::()) }; nix::unistd::write(self.fd(), setup).map_err(convert_error)?; self.dev_create() } /// Create a new uinput device, and fall back on the legacy interface if necessary pub fn create(&self, id: &InputId, name: &[u8], ff_effects_max: u32, abs: &[AbsoluteInfoSetup]) -> io::Result<()> { let mut setup: sys::uinput_setup = unsafe { MaybeUninit::zeroed().assume_init() }; setup.id = (*id).into(); setup.ff_effects_max = ff_effects_max; copy_name(&mut setup.name, name)?; match self.dev_setup(&setup) { Err(ref e) if e.raw_os_error() == Some(sys::Errno::EINVAL as _) => return self.create_legacy(id, name, ff_effects_max, abs), v => v, }?; for abs in abs { self.abs_setup(abs.into())?; } self.dev_create() } /// Write input events to the device pub fn write(&self, events: &[sys::input_event]) -> io::Result { let events = unsafe { from_raw_parts(events.as_ptr() as *const u8, size_of::() * events.len()) }; nix::unistd::write(self.fd(), events) .map(|c| c / size_of::()).map_err(convert_error) } /// Read events from uinput (see `EV_UINPUT`) pub fn read(&self, events: &mut [sys::input_event]) -> io::Result { let events = unsafe { from_raw_parts_mut(events.as_mut_ptr() as *mut u8, size_of::() * events.len()) }; nix::unistd::read(self.fd(), events) .map(|len| len / size_of::()).map_err(convert_error) } /// Returns the sysfs directory for the input device. /// /// Note that this path may not exist if sysfs is not mounted in the standard `/sys` location. pub fn sys_path(&self) -> io::Result { let sys = self.sys_name()?; let sys = CStr::from_bytes_with_nul(&sys).map(|c| c.to_bytes()).unwrap_or(&sys); Ok(Path::new("/sys/devices/virtual/input/").join(OsStr::from_bytes(sys))) } /// The device name of the input device. pub fn evdev_name(&self) -> io::Result { let sys = self.sys_path()?; fs::read_dir(&sys)?.filter_map(|e| match e { Err(err) => Some(Err(err)), Ok(e) => match e.file_type() { Err(err) => Some(Err(err)), Ok(ty) if ty.is_dir() => { let name = e.file_name(); if name.as_bytes().starts_with(b"event") { Some(Ok(e.file_name())) } else { None } }, Ok(..) => None, }, }).next().unwrap_or_else(|| Err(io::Error::new(io::ErrorKind::NotFound, "event input device not found"))) } /// The device node path of the input device. /// /// Note that this path may not exist if `/dev/input/*` isn't mounted properly. pub fn evdev_path(&self) -> io::Result { self.evdev_name().map(|ev| Path::new("/dev/input/").join(ev)) } ioctl_impl! { { /// `UI_DEV_CREATE` @call dev_create = ui_dev_create } { /// `UI_DEV_DESTROY` @call dev_destroy = ui_dev_destroy } { /// `UI_DEV_SETUP` @set dev_setup(&sys::uinput_setup) = ui_dev_setup } { /// `UI_ABS_SETUP` @set abs_setup(&sys::uinput_abs_setup) = ui_abs_setup } { /// `UI_SET_EVBIT` @set set_evbit(kinds::EventKind) = ui_set_evbit } { /// `UI_SET_KEYBIT` @set set_keybit(Key) = ui_set_keybit } { /// `UI_SET_RELBIT` @set set_relbit(kinds::RelativeAxis) = ui_set_relbit } { /// `UI_SET_ABSBIT` @set set_absbit(kinds::AbsoluteAxis) = ui_set_absbit } { /// `UI_SET_MSCBIT` @set set_mscbit(kinds::MiscKind) = ui_set_mscbit } { /// `UI_SET_LEDBIT` @set set_ledbit(kinds::LedKind) = ui_set_ledbit } { /// `UI_SET_SNDBIT` @set set_sndbit(kinds::SoundKind) = ui_set_sndbit } { /// `UI_SET_FFBIT` @set set_ffbit(i32) = ui_set_ffbit } { /// `UI_SET_PHYS` @set_str set_phys = ui_set_phys } { /// `UI_SET_SWBIT` @set set_swbit(kinds::SwitchKind) = ui_set_swbit } { /// `UI_SET_PROPBIT` @set set_propbit(kinds::InputProperty) = ui_set_propbit } { /// `UI_BEGIN_FF_UPLOAD` @set ff_upload_begin(&mut sys::uinput_ff_upload) = ui_begin_ff_upload } { /// `UI_END_FF_UPLOAD` @set ff_upload_end(&sys::uinput_ff_upload) = ui_end_ff_upload } { /// `UI_BEGIN_FF_ERASE` @set ff_erase_begin(&mut sys::uinput_ff_erase) = ui_begin_ff_erase } { /// `UI_END_FF_ERASE` @set ff_erase_end(&sys::uinput_ff_erase) = ui_end_ff_erase } { /// `UI_GET_SYSNAME` @get_str sys_name, sys_name_buf = ui_get_sysname } { /// `UI_GET_VERSION` @get version = ui_get_version -> u32 } } }