evdev-rs-0.6.1/.cargo_vcs_info.json0000644000000001360000000000100125730ustar { "git": { "sha1": "ceef9f19122817c84b7ab3adab1eacecf34d5988" }, "path_in_vcs": "" }evdev-rs-0.6.1/.github/workflows/main.yml000064400000000000000000000053420072674642500164630ustar 00000000000000name: CI on: [push, pull_request] jobs: test: name: Test runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: build: [stable, beta, nightly, arm-gnueabi, arm-gnueabihf] include: - build: stable os: ubuntu-latest rust: stable target: x86_64-unknown-linux-gnu - build: beta os: ubuntu-latest rust: beta target: x86_64-unknown-linux-gnu - build: nightly os: ubuntu-latest rust: nightly target: x86_64-unknown-linux-gnu - build: arm-gnueabi os: ubuntu-latest rust: stable target: arm-unknown-linux-gnueabi packages: "gcc-arm-linux-gnueabi libc6-armel-cross libc6-dev-armel-cross" - build: arm-gnueabihf os: ubuntu-latest rust: stable target: arm-unknown-linux-gnueabihf packages: "gcc-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross" steps: - run: sudo apt install ${{ matrix.packages }} - uses: actions/checkout@v1 with: submodules: true - name: Install Rust run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} && rustup target add ${{ matrix.target }} shell: bash - run: cargo build --target ${{ matrix.target }} --verbose - run: cargo build --target ${{ matrix.target }} --verbose --no-default-features - run: cargo build --target ${{ matrix.target }} --verbose --all-features - run: sudo --preserve-env env "PATH=$PATH" cargo test --verbose if: contains(matrix.target, 'x86_64') - run: sudo --preserve-env env "PATH=$PATH" cargo test --all-features --verbose if: contains(matrix.target, 'x86_64') rustfmt: name: Rustfmt runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Install Rust run: rustup update stable && rustup default stable && rustup component add rustfmt - run: cargo fmt -- --check publish_docs: name: Publish Documentation runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 with: submodules: true - name: Install Rust run: rustup update stable && rustup default stable - name: Build documentation run: cargo doc --no-deps --all-features - name: Publish documentation run: | cd target/doc git init git add . git -c user.name='ci' -c user.email='ci' commit -m init git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' evdev-rs-0.6.1/.gitignore000064400000000000000000000000360072674642500134020ustar 00000000000000target Cargo.lock *.swp *.swo evdev-rs-0.6.1/.gitmodules000064400000000000000000000001640072674642500135710ustar 00000000000000[submodule "evdev-sys/libevdev"] path = evdev-sys/libevdev url = https://anongit.freedesktop.org/git/libevdev.git evdev-rs-0.6.1/Cargo.lock0000644000000057100000000000100105510ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "cc" version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "evdev-rs" version = "0.6.1" dependencies = [ "bitflags", "evdev-sys", "libc", "log", "serde", ] [[package]] name = "evdev-sys" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14ead42b547b15d47089c1243d907bcf0eb94e457046d3b315a26ac9c9e9ea6d" dependencies = [ "cc", "libc", "pkg-config", ] [[package]] name = "libc" version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ "cfg-if", ] [[package]] name = "pkg-config" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "proc-macro2" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] [[package]] name = "serde" version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "syn" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" evdev-rs-0.6.1/Cargo.toml0000644000000025360000000000100105770ustar # 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 = "evdev-rs" version = "0.6.1" authors = ["Nayan Deshmukh "] description = "Bindings to libevdev for interacting with evdev devices. It moves the\ncommon tasks when dealing with evdev devices into a library and provides\na library interface to the callers, thus avoiding erroneous ioctls, etc.\n" homepage = "https://github.com/ndesh26/evdev-rs" readme = "README.md" keywords = ["evdev"] license = "MIT/Apache-2.0" repository = "https://github.com/ndesh26/evdev-rs" [package.metadata.docs.rs] features = ["serde"] [dependencies.bitflags] version = "1.2.1" [dependencies.evdev-sys] version = "0.2.5" [dependencies.libc] version = "0.2.67" [dependencies.log] version = "0.4.8" [dependencies.serde] version = "1.0" features = ["derive"] optional = true default-features = false [features] default = [] libevdev-1-10 = ["evdev-sys/libevdev-1-10"] evdev-rs-0.6.1/Cargo.toml.orig000064400000000000000000000016520072674642500143060ustar 00000000000000[package] name = "evdev-rs" version = "0.6.1" authors = ["Nayan Deshmukh "] license = "MIT/Apache-2.0" keywords = ["evdev"] readme = "README.md" repository = "https://github.com/ndesh26/evdev-rs" homepage = "https://github.com/ndesh26/evdev-rs" edition = "2018" description = """ Bindings to libevdev for interacting with evdev devices. It moves the common tasks when dealing with evdev devices into a library and provides a library interface to the callers, thus avoiding erroneous ioctls, etc. """ [features] default = [] # Use features from libevdev version 1.10 and greater (libevdev_property_disable) libevdev-1-10 = ["evdev-sys/libevdev-1-10"] [dependencies] serde = { version = "1.0", default-features = false, features=["derive"], optional = true } evdev-sys = { path = "evdev-sys", version = "0.2.5" } libc = "0.2.67" bitflags = "1.2.1" log = "0.4.8" [package.metadata.docs.rs] features = ["serde"] evdev-rs-0.6.1/README.md000064400000000000000000000036220072674642500126750ustar 00000000000000# evdev-rs [![Build Status](https://travis-ci.org/ndesh26/evdev-rs.svg?branch=master)](https://travis-ci.org/ndesh26/evdev-rs) [![Latest Version](https://img.shields.io/crates/v/evdev-rs.svg)](https://crates.io/crates/evdev-rs) [![Documentation](https://docs.rs/evdev-rs/badge.svg)](https://docs.rs/evdev-rs) [Documentation](https://ndesh26.github.io/evdev-rs/evdev_rs/) A Rust wrapper for libevdev ```toml # Cargo.toml [dependencies] evdev-rs = "0.6.1" ``` to enable serialization support, enable the feature "serde" ```toml # Cargo.toml [dependencies] evdev-rs = { version = "0.6.1", features = ["serde"] } With a newer libevdev version (>= 1.10) enable the feature `libevdev-1-10` to allow disabling a property. It also extends the `Enable` trait to `InputProp`, enabling the use of `enable()`, `disable()` and `has()` for `InputProp` as well. ``` Why a libevdev wrapper? ----------------------- The evdev protocol is simple, but quirky, with a couple of behaviors that are non-obvious. libevdev transparently handles some of those quirks. The [evdev](https://github.com/emberian/evdev) crate is an implementation of libevdev in Rust which provides most of the same features. `evdev-rs` crate closely follows libevdev and hence enjoys all the complex handling that libevdev does. Some of the things that libevdev handles transparently, which may or may not be in `evdev` crate: * handling of fake multitouch devices * synching of slots and per-slot state * transparent generation of missing tracking ids after SYN_DROPPED * various boundary checks with defined error codes if you request invalid data (e.g. event codes that don't exist on the device) * fd swapping on the same context * disabling/enabling events on a per-context basis, so you can disable/enable ABS_FOO and then not care about quirks in the client-side code. Development ----------- `src/enums.rs` can be generated by running `./tools/make-enums.sh`. evdev-rs-0.6.1/TODO.md000064400000000000000000000010700072674642500125000ustar 00000000000000## These function need to implemented in evdev-rs * `int libevdev_kernel_set_led_values(struct libevdev *dev, ...);` ## We need to define this functions types and the corresponding functions * libevdev_log_func_t * `void libevdev_set_log_function(libevdev_log_func_t logfunc, void *data);` * libevdev_device_log_func_t * `void libevdev_set_device_log_function(struct libevdev *dev, libevdev_device_log_func_t logfunc, enum libevdev_log_priority priority, void *data);` ## Add Documentation evdev-rs-0.6.1/examples/evtest.rs000064400000000000000000000112270072674642500151140ustar 00000000000000use evdev_rs::enums::*; use evdev_rs::*; use std::fs::OpenOptions; use std::io; use std::io::ErrorKind; use std::io::Read; use std::os::unix::fs::OpenOptionsExt; fn usage() { println!("Usage: evtest /path/to/device"); } fn print_abs_bits(dev: &Device, axis: &EV_ABS) { let code = EventCode::EV_ABS(axis.clone()); if !dev.has(code) { return; } let abs = dev.abs_info(&code).unwrap(); println!("\tValue\t{}", abs.value); println!("\tMin\t{}", abs.minimum); println!("\tMax\t{}", abs.maximum); if abs.fuzz != 0 { println!("\tFuzz\t{}", abs.fuzz); } if abs.flat != 0 { println!("\tFlat\t{}", abs.flat); } if abs.resolution != 0 { println!("\tResolution\t{}", abs.resolution); } } fn print_code_bits(dev: &Device, ev_type: &EventType) { for code in EventCodeIterator::new(ev_type) { if !dev.has(code) { continue; } println!(" Event code: {}", code); match code { EventCode::EV_ABS(k) => print_abs_bits(dev, &k), _ => (), } } } fn print_bits(dev: &Device) { println!("Supported events:"); for ev_type in EventTypeIterator::new() { if dev.has(ev_type) { println!(" Event type: {} ", ev_type); } match ev_type { EventType::EV_KEY | EventType::EV_REL | EventType::EV_ABS | EventType::EV_LED => print_code_bits(dev, &ev_type), _ => (), } } } fn print_props(dev: &Device) { println!("Properties:"); for input_prop in InputPropIterator::new() { if dev.has_property(&input_prop) { println!(" Property type: {}", input_prop); } } } fn print_event(ev: &InputEvent) { match ev.event_code { EventCode::EV_SYN(_) => println!( "Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++", ev.time.tv_sec, ev.time.tv_usec, ev.event_type().unwrap() ), _ => println!( "Event: time {}.{}, type {} , code {} , value {}", ev.time.tv_sec, ev.time.tv_usec, ev.event_type() .map(|ev_type| format!("{}", ev_type)) .unwrap_or("None".to_owned()), ev.event_code, ev.value ), } } fn print_sync_dropped_event(ev: &InputEvent) { print!("SYNC DROPPED: "); print_event(ev); } fn main() { let mut args = std::env::args(); if args.len() != 2 { usage(); std::process::exit(1); } let path = &args.nth(1).unwrap(); let mut file = OpenOptions::new() .read(true) .write(true) .custom_flags(libc::O_NONBLOCK) .open(path) .unwrap(); let mut buffer = Vec::new(); let result = file.read_to_end(&mut buffer); if result.is_ok() || result.unwrap_err().kind() != ErrorKind::WouldBlock { println!("Failed to drain pending events from device file"); } let u_d = UninitDevice::new().unwrap(); let d = u_d.set_file(file).unwrap(); println!( "Input device ID: bus 0x{:x} vendor 0x{:x} product 0x{:x}", d.bustype(), d.vendor_id(), d.product_id() ); println!("Evdev version: {:x}", d.driver_version()); println!("Input device name: \"{}\"", d.name().unwrap_or("")); println!("Phys location: {}", d.phys().unwrap_or("")); println!("Uniq identifier: {}", d.uniq().unwrap_or("")); print_bits(&d); print_props(&d); let mut a: io::Result<(ReadStatus, InputEvent)>; loop { a = d.next_event(ReadFlag::NORMAL); if a.is_ok() { let mut result = a.ok().unwrap(); match result.0 { ReadStatus::Sync => { println!("::::::::::::::::::::: dropped ::::::::::::::::::::::"); while result.0 == ReadStatus::Sync { print_sync_dropped_event(&result.1); a = d.next_event(ReadFlag::SYNC); if a.is_ok() { result = a.ok().unwrap(); } else { break; } } println!("::::::::::::::::::::: re-synced ::::::::::::::::::::"); } ReadStatus::Success => print_event(&result.1), } } else { let err = a.err().unwrap(); match err.raw_os_error() { Some(libc::EAGAIN) => continue, _ => { println!("{}", err); break; } } } } } evdev-rs-0.6.1/examples/vmouse.rs000064400000000000000000000057010072674642500151200ustar 00000000000000use std::fs::File; use evdev_rs::enums::{BusType, EventCode, EventType, EV_KEY, EV_REL, EV_SYN}; use evdev_rs::{Device, DeviceWrapper, InputEvent, ReadFlag, UInputDevice, UninitDevice}; const MOUSE_STEP_X: i32 = 10; const MOUSE_STEP_Y: i32 = 10; fn main() -> Result<(), std::io::Error> { // Parse command line arguments let mut args = std::env::args(); if args.len() != 2 { let n = args.nth(0).unwrap(); println!("Usage: `{} DEVICE`, eg. `{} /dev/input/event13`", n, n); std::process::exit(1); } let device = &args.nth(1).unwrap(); // Connect to real keyboard let f = File::open(device)?; let d = Device::new_from_file(f)?; if let Some(n) = d.name() { println!( "Connected to device: '{}' ({:04x}:{:04x})", n, d.vendor_id(), d.product_id() ); } // Create virtual device let u = UninitDevice::new().unwrap(); // Setup device // per: https://01.org/linuxgraphics/gfx-docs/drm/input/uinput.html#mouse-movements u.set_name("Virtual Mouse"); u.set_bustype(BusType::BUS_USB as u16); u.set_vendor_id(0xabcd); u.set_product_id(0xefef); // Note mouse keys have to be enabled for this to be detected // as a usable device, see: https://stackoverflow.com/a/64559658/6074942 u.enable_event_type(&EventType::EV_KEY)?; u.enable_event_code(&EventCode::EV_KEY(EV_KEY::BTN_LEFT), None)?; u.enable_event_code(&EventCode::EV_KEY(EV_KEY::BTN_RIGHT), None)?; u.enable_event_type(&EventType::EV_REL)?; u.enable_event_code(&EventCode::EV_REL(EV_REL::REL_X), None)?; u.enable_event_code(&EventCode::EV_REL(EV_REL::REL_Y), None)?; u.enable_event_code(&EventCode::EV_SYN(EV_SYN::SYN_REPORT), None)?; // Attempt to create UInputDevice from UninitDevice let v = UInputDevice::create_from_device(&u)?; loop { // Fetch keyboard events let (_status, event) = d.next_event(ReadFlag::NORMAL | ReadFlag::BLOCKING)?; // Map these to mouse events println!("Event: {:?}", event); // Map direction keys to mouse events let e = match event.event_code { EventCode::EV_KEY(EV_KEY::KEY_RIGHT) => Some((EV_REL::REL_X, MOUSE_STEP_X)), EventCode::EV_KEY(EV_KEY::KEY_LEFT) => Some((EV_REL::REL_X, -MOUSE_STEP_X)), EventCode::EV_KEY(EV_KEY::KEY_UP) => Some((EV_REL::REL_Y, -MOUSE_STEP_Y)), EventCode::EV_KEY(EV_KEY::KEY_DOWN) => Some((EV_REL::REL_Y, MOUSE_STEP_Y)), _ => None, }; // Write mapped event if let Some((e, n)) = e { v.write_event(&InputEvent { time: event.time, event_code: EventCode::EV_REL(e), value: n, })?; v.write_event(&InputEvent { time: event.time, event_code: EventCode::EV_SYN(EV_SYN::SYN_REPORT), value: 0, })?; } } } evdev-rs-0.6.1/rustfmt.toml000064400000000000000000000000140072674642500140070ustar 00000000000000max_width=90evdev-rs-0.6.1/src/device.rs000064400000000000000000001011450072674642500140110ustar 00000000000000use crate::{AbsInfo, GrabMode, InputEvent, LedState, ReadFlag, ReadStatus, TimeVal}; use libc::{c_int, c_uint, c_void}; use std::ffi::CString; use std::fs::File; use std::fs::OpenOptions; use std::io::Read; use std::mem::ManuallyDrop; use std::os::unix::fs::OpenOptionsExt; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::path::Path; use std::{io, ptr}; use crate::enums::*; use crate::util::*; use evdev_sys as raw; /// Types that can be enabled on a DeviceWrapper (i.e. buttons, keys, relative motion) /// /// Generally this method will not be called directly, but will insted be called through [Device::enable()](crate::Device::enable) /// /// ```rust /// # use evdev_rs::{UninitDevice, DeviceWrapper, Enable, enums::{EventCode, EV_REL::REL_X}}; /// let dev = UninitDevice::new().expect("Device creation failed"); /// dev.enable(EventCode::EV_REL(REL_X)).expect("Enable failed"); /// ``` /// /// If you need to enable a EV_ABS or EV_REP event code, use /// [enable_event_code](crate::Device::enable_event_code), as this /// implementation doesn't pass EV_ABS data. pub trait Enable { fn enable(&self, device: &D) -> io::Result<()>; fn disable(&self, device: &D) -> io::Result<()>; fn has(&self, device: &D) -> bool; } #[cfg(feature = "libevdev-1-10")] impl Enable for InputProp { fn enable(&self, device: &D) -> io::Result<()> { device.enable_property(self) } fn disable(&self, device: &D) -> io::Result<()> { device.disable_property(self) } fn has(&self, device: &D) -> bool { device.has_property(self) } } impl Enable for EventType { fn enable(&self, device: &D) -> io::Result<()> { device.enable_event_type(self) } fn disable(&self, device: &D) -> io::Result<()> { device.disable_event_type(self) } fn has(&self, device: &D) -> bool { device.has_event_type(self) } } impl Enable for EventCode { fn enable(&self, device: &D) -> io::Result<()> { device.enable_event_code(self, None) } fn disable(&self, device: &D) -> io::Result<()> { device.disable_event_code(self) } fn has(&self, device: &D) -> bool { device.has_event_code(self) } } /// Extra data for use with enable_event_code #[derive(Clone, Copy, Debug)] pub enum EnableCodeData { AbsInfo(AbsInfo), RepInfo(i32), } /// Abstraction over structs which contain an inner `*mut libevdev` pub trait DeviceWrapper: Sized { fn raw(&self) -> *mut raw::libevdev; /// Forcibly enable an EventType/InputProp on this device, even if the underlying /// device does not support it. While this cannot make the device actually /// report such events, it will now return true for has(). /// /// This is a local modification only affecting only this representation of /// this device. fn enable(&self, e: E) -> io::Result<()> { e.enable(self) } /// Enables this property, a call to `set_file` will overwrite any previously set values /// /// Note: Please use the `enable` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn enable_property(&self, prop: &InputProp) -> io::Result<()> { let result = unsafe { raw::libevdev_enable_property(self.raw(), *prop as c_uint) as i32 }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Forcibly enable an event type on this device, even if the underlying /// device does not support it. While this cannot make the device actually /// report such events, it will now return true for libevdev_has_event_type(). /// /// This is a local modification only affecting only this representation of /// this device. /// /// Note: Please use the `enable` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn enable_event_type(&self, ev_type: &EventType) -> io::Result<()> { let result = unsafe { raw::libevdev_enable_event_type(self.raw(), *ev_type as c_uint) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Forcibly enable an event type on this device, even if the underlying /// device does not support it. While this cannot make the device actually /// report such events, it will now return true for libevdev_has_event_code(). /// /// The last argument depends on the type and code: /// If type is EV_ABS, data must be a pointer to a struct input_absinfo /// containing the data for this axis. /// If type is EV_REP, data must be a pointer to a int containing the data /// for this axis. /// For all other types, the argument must be `None`. /// /// Note: Please use the `enable` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn enable_event_code( &self, ev_code: &EventCode, data: Option, ) -> io::Result<()> { let data = match ev_code { EventCode::EV_ABS(_) => match data { Some(EnableCodeData::AbsInfo(info)) => { &info.as_raw() as *const _ as *const c_void } _ => return Err(io::Error::new( io::ErrorKind::InvalidInput, "EventCode::EV_ABS must be paired with EnableCodeData::AbsInfo", )), }, EventCode::EV_REP(_) => match data { Some(EnableCodeData::RepInfo(info)) => { &libc::c_int::from(info) as *const _ as *const c_void } _ => return Err(io::Error::new( io::ErrorKind::InvalidInput, "EventCode::EV_REP must be paired with EnableCodeData::RepInfo", )), }, _ => ptr::null(), }; let (ev_type, ev_code) = event_code_to_int(ev_code); let result = unsafe { raw::libevdev_enable_event_code(self.raw(), ev_type, ev_code, data) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Forcibly disable an EventType/EventCode on this device, even if the /// underlying device provides it. This effectively mutes the respective set of /// events. has() will return false for this EventType/EventCode /// /// In most cases, a caller likely only wants to disable a single code, not /// the whole type. /// /// Disabling EV_SYN will not work. In Peter's Words "Don't shoot yourself /// in the foot. It hurts". /// /// This is a local modification only affecting only this representation of /// this device. fn disable(&self, d: E) -> io::Result<()> { d.disable(self) } /// Forcibly disable an event type on this device, even if the underlying /// device provides it. This effectively mutes the respective set of /// events. libevdev will filter any events matching this type and none will /// reach the caller. libevdev_has_event_type() will return false for this /// type. /// /// In most cases, a caller likely only wants to disable a single code, not /// the whole type. Use `disable_event_code` for that. /// /// Disabling EV_SYN will not work. In Peter's Words "Don't shoot yourself /// in the foot. It hurts". /// /// This is a local modification only affecting only this representation of /// this device. /// /// Note: Please use the `disable` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn disable_event_type(&self, ev_type: &EventType) -> io::Result<()> { let result = unsafe { raw::libevdev_disable_event_type(self.raw(), *ev_type as c_uint) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Forcibly disable an event code on this device, even if the underlying /// device provides it. This effectively mutes the respective set of /// events. libevdev will filter any events matching this type and code and /// none will reach the caller. `has_event_code` will return false for /// this code. /// /// Disabling all event codes for a given type will not disable the event /// type. Use `disable_event_type` for that. /// /// This is a local modification only affecting only this representation of /// this device. /// /// Disabling codes of type EV_SYN will not work. Don't shoot yourself in the /// foot. It hurts. /// /// Note: Please use the `disable` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn disable_event_code(&self, code: &EventCode) -> io::Result<()> { let (ev_type, ev_code) = event_code_to_int(code); let result = unsafe { raw::libevdev_disable_event_code(self.raw(), ev_type, ev_code) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } #[cfg(feature = "libevdev-1-10")] fn disable_property(&self, prop: &InputProp) -> io::Result<()> { let result = unsafe { raw::libevdev_disable_property(self.raw(), (*prop) as c_uint) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Returns `true` if device support the InputProp/EventType/EventCode and false otherwise fn has(&self, e: E) -> bool { e.has(self) } /// Returns `true` if device support the property and false otherwise /// /// Note: Please use the `has` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn has_property(&self, prop: &InputProp) -> bool { unsafe { raw::libevdev_has_property(self.raw(), *prop as c_uint) != 0 } } /// Returns `true` is the device support this event type and `false` otherwise /// /// Note: Please use the `has` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn has_event_type(&self, ev_type: &EventType) -> bool { unsafe { raw::libevdev_has_event_type(self.raw(), *ev_type as c_uint) != 0 } } /// Return `true` is the device support this event type and code and `false` otherwise /// /// Note: Please use the `has` function instead. This function is only /// available for the sake of maintaining compatibility with libevdev. fn has_event_code(&self, code: &EventCode) -> bool { unsafe { let (ev_type, ev_code) = event_code_to_int(code); raw::libevdev_has_event_code(self.raw(), ev_type, ev_code) != 0 } } string_getter!( #[doc = "Get device's name, as set by the kernel, or overridden by a call to `set_name`"], name, libevdev_get_name, #[doc = "Get device's physical location, as set by the kernel, or overridden by a call to `set_phys`"], phys, libevdev_get_phys, #[doc = "Get device's unique identifier, as set by the kernel, or overridden by a call to `set_uniq`"], uniq, libevdev_get_uniq ); string_setter!( set_name, libevdev_set_name, set_phys, libevdev_set_phys, set_uniq, libevdev_set_uniq ); product_getter!( product_id, libevdev_get_id_product, vendor_id, libevdev_get_id_vendor, bustype, libevdev_get_id_bustype, version, libevdev_get_id_version ); product_setter!( set_product_id, libevdev_set_id_product, set_vendor_id, libevdev_set_id_vendor, set_bustype, libevdev_set_id_bustype, set_version, libevdev_set_id_version ); /// Get the axis info for the given axis, as advertised by the kernel. /// /// Returns the `AbsInfo` for the given the code or None if the device /// doesn't support this code fn abs_info(&self, code: &EventCode) -> Option { let (_, ev_code) = event_code_to_int(code); let a = unsafe { raw::libevdev_get_abs_info(self.raw(), ev_code).as_ref()? }; Some(AbsInfo { value: a.value, minimum: a.minimum, maximum: a.maximum, fuzz: a.fuzz, flat: a.flat, resolution: a.resolution, }) } /// Change the abs info for the given EV_ABS event code, if the code exists. /// /// This function has no effect if `has_event_code` returns false for /// this code. fn set_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) { let (_, ev_code) = event_code_to_int(code); unsafe { raw::libevdev_set_abs_info( self.raw(), ev_code, &absinfo.as_raw() as *const _, ); } } /// Returns the current value of the event type. /// /// If the device supports this event type and code, the return value is /// set to the current value of this axis. Otherwise, `None` is returned. fn event_value(&self, code: &EventCode) -> Option { let mut value: i32 = 0; let (ev_type, ev_code) = event_code_to_int(code); let valid = unsafe { raw::libevdev_fetch_event_value(self.raw(), ev_type, ev_code, &mut value) }; match valid { 0 => None, _ => Some(value), } } /// Set the value for a given event type and code. /// /// This only makes sense for some event types, e.g. setting the value for /// EV_REL is pointless. /// /// This is a local modification only affecting only this representation of /// this device. A future call to event_value() will return this /// value, unless the value was overwritten by an event. /// /// If the device supports ABS_MT_SLOT, the value set for any ABS_MT_* /// event code is the value of the currently active slot. You should use /// `set_slot_value` instead. /// /// If the device supports ABS_MT_SLOT and the type is EV_ABS and the code is /// ABS_MT_SLOT, the value must be a positive number less then the number of /// slots on the device. Otherwise, `set_event_value` returns Err. fn set_event_value(&self, code: &EventCode, val: i32) -> io::Result<()> { let (ev_type, ev_code) = event_code_to_int(code); let result = unsafe { raw::libevdev_set_event_value(self.raw(), ev_type, ev_code, val as c_int) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } abs_getter!( abs_minimum, libevdev_get_abs_minimum, abs_maximum, libevdev_get_abs_maximum, abs_fuzz, libevdev_get_abs_fuzz, abs_flat, libevdev_get_abs_flat, abs_resolution, libevdev_get_abs_resolution ); abs_setter!( set_abs_minimum, libevdev_set_abs_minimum, set_abs_maximum, libevdev_set_abs_maximum, set_abs_fuzz, libevdev_set_abs_fuzz, set_abs_flat, libevdev_set_abs_flat, set_abs_resolution, libevdev_set_abs_resolution ); /// Return the current value of the code for the given slot. /// /// If the device supports this event code, the return value is /// is set to the current value of this axis. Otherwise, or /// if the event code is not an ABS_MT_* event code, `None` is returned fn slot_value(&self, slot: u32, code: &EventCode) -> Option { let (_, ev_code) = event_code_to_int(code); let mut value: i32 = 0; let valid = unsafe { raw::libevdev_fetch_slot_value( self.raw(), slot as c_uint, ev_code, &mut value, ) }; match valid { 0 => None, _ => Some(value), } } /// Set the value for a given code for the given slot. /// /// This is a local modification only affecting only this representation of /// this device. A future call to `slot_value` will return this value, /// unless the value was overwritten by an event. /// /// This function does not set event values for axes outside the ABS_MT range, /// use `set_event_value` instead. fn set_slot_value(&self, slot: u32, code: &EventCode, val: i32) -> io::Result<()> { let (_, ev_code) = event_code_to_int(code); let result = unsafe { raw::libevdev_set_slot_value( self.raw(), slot as c_uint, ev_code, val as c_int, ) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Get the number of slots supported by this device. /// /// The number of slots supported, or `None` if the device does not provide /// any slots /// /// A device may provide ABS_MT_SLOT but a total number of 0 slots. Hence /// the return value of `None` for "device does not provide slots at all" fn num_slots(&self) -> Option { let result = unsafe { raw::libevdev_get_num_slots(self.raw()) }; match result { -1 => None, slots => Some(slots), } } /// Get the currently active slot. /// /// This may differ from the value an ioctl may return at this time as /// events may have been read off the file since changing the slot value /// but those events are still in the buffer waiting to be processed. /// The returned value is the value a caller would see if it were to /// process events manually one-by-one. fn current_slot(&self) -> Option { let result = unsafe { raw::libevdev_get_current_slot(self.raw()) }; match result { -1 => None, slots => Some(slots), } } } /// Opaque struct representing an evdev device with no backing file pub struct UninitDevice { raw: *mut raw::libevdev, } unsafe impl Send for UninitDevice {} impl DeviceWrapper for UninitDevice { fn raw(&self) -> *mut raw::libevdev { self.raw } } impl UninitDevice { /// Initialize a new libevdev device. /// /// Generally you should use Device::new_from_file instead of this method /// This function only initializes the struct to sane default values. /// To actually hook up the device to a kernel device, use `set_file`. pub fn new() -> Option { let libevdev = unsafe { raw::libevdev_new() }; if libevdev.is_null() { None } else { Some(UninitDevice { raw: libevdev }) } } /// Set the file for this struct and initialize internal data. /// /// If the device changed and you need to re-read a device, use `Device::new_from_file` method. /// If you need to change the file after /// closing and re-opening the same device, use `change_file`. pub fn set_file(self, file: File) -> io::Result { // Don't call UninitDevice's destructor so we can reuse the inner libevdev let leak = ManuallyDrop::new(self); let result = unsafe { raw::libevdev_set_fd(leak.raw, file.as_raw_fd()) }; match result { 0 => Ok(Device { file, raw: leak.raw, }), error => Err(io::Error::from_raw_os_error(-error)), } } #[deprecated( since = "0.5.0", note = "Prefer `set_file`. Some function names were changed so they more closely match their type signature. See issue 42 for discussion https://github.com/ndesh26/evdev-rs/issues/42" )] pub fn set_fd(self, file: File) -> io::Result { self.set_file(file) } } impl Drop for UninitDevice { fn drop(&mut self) { unsafe { raw::libevdev_free(self.raw); } } } impl std::fmt::Debug for UninitDevice { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("UninitDevice") .field("name", &self.name()) .field("phys", &self.phys()) .field("uniq", &self.uniq()) .finish() } } /// Opaque struct representing an evdev device /// /// Unlike libevdev, this `Device` mantains an associated file as an invariant pub struct Device { file: File, raw: *mut raw::libevdev, } unsafe impl Send for Device {} impl DeviceWrapper for Device { fn raw(&self) -> *mut raw::libevdev { self.raw } } impl Device { /// Initialize a new libevdev device from the given file. /// /// This is a shortcut for /// /// ```rust,no_run /// use evdev_rs::{Device, UninitDevice}; /// # use std::fs::File; /// /// let uninit_device = UninitDevice::new().unwrap(); /// # let file = File::open("/dev/input/event0").unwrap(); /// let device = uninit_device.set_file(file); /// ``` /// /// The caller is responsible for opening the file and setting /// the `O_NONBLOCK` flag and handling permissions. /// If the file is opened without O_NONBLOCK flag then next_event /// should be called with ReadFlag::BLOCKING. Due to the caching /// nature of next_event we might block while trying to buffer /// new events even though some events are already present. pub fn new_from_file(file: File) -> io::Result { let mut libevdev = std::ptr::null_mut(); let result = unsafe { raw::libevdev_new_from_fd(file.as_raw_fd(), &mut libevdev) }; match result { 0 => Ok(Device { file, raw: libevdev, }), error => Err(io::Error::from_raw_os_error(-error)), } } #[deprecated( since = "0.5.0", note = "Prefer `new_from_file`. Some function names were changed so they more closely match their type signature. See issue 42 for discussion https://github.com/ndesh26/evdev-rs/issues/42" )] pub fn new_from_fd(file: File) -> io::Result { Self::new_from_file(file) } /// Opens a device with the given path as the location of devnode /// /// The devnode file is opened with `O_NONBLOCK` and all the pending /// events are first read from the file before creating the device. pub fn new_from_path>(path: P) -> io::Result { let mut file = OpenOptions::new() .read(true) .write(true) .custom_flags(libc::O_NONBLOCK) .open(path)?; let mut buffer = [0u8; 20 * std::mem::size_of::()]; let last_result = loop { let result = file.read(&mut buffer); if !result.is_ok() { break result; } }; let _error_code = io::Error::from(io::ErrorKind::WouldBlock); match last_result { Err(_error_code) => Self::new_from_file(file), _ => Err(io::Error::new( io::ErrorKind::WouldBlock, "Unable to open file with O_NONBLOCK", )), } } /// Returns the file associated with the device pub fn file(&self) -> &File { &self.file } #[deprecated( since = "0.5.0", note = "Prefer `file`. This function can easily be misused. Calling this method, then dropping the returned file will lead to failures e.g. next_event will return an Err()" )] pub fn fd(&self) -> Option { let result = unsafe { raw::libevdev_get_fd(self.raw) }; match result { 0 => None, _ => unsafe { Some(File::from_raw_fd(result)) }, } } /// Change the file for this device, without re-reading the actual device. /// /// On success, returns the file that was previously associated with this /// device. /// /// If the file changes after initializing the device, for example after a /// VT-switch in the X.org X server, this function updates the internal /// file to the newly opened. No check is made that new file points to the /// same device. If the device has changed, evdev's behavior is undefined. /// /// evdev device does not sync itself after changing the file and keeps the /// current device state. Use next_event with the FORCE_SYNC flag to force /// a re-sync. /// /// # Example /// /// ```rust,no_run /// use evdev_rs::{Device, UninitDevice, ReadFlag, ReadStatus}; /// # use std::fs::File; /// # fn hidden() -> std::io::Result<()> { /// let mut dev = Device::new_from_file(File::open("/dev/input/input0")?)?; /// dev.change_file(File::open("/dev/input/input1")?)?; /// dev.next_event(ReadFlag::FORCE_SYNC); /// while dev.next_event(ReadFlag::SYNC).ok().unwrap().0 == ReadStatus::Sync /// {} // noop /// # Ok(()) /// # } /// ``` /// After changing the file, the device is assumed ungrabbed and a caller must /// call libevdev_grab() again. pub fn change_file(&mut self, file: File) -> io::Result { let result = unsafe { raw::libevdev_change_fd(self.raw, file.as_raw_fd()) }; match result { 0 => { let mut file = file; std::mem::swap(&mut file, &mut self.file); Ok(file) } error => Err(io::Error::from_raw_os_error(-error)), } } #[deprecated( since = "0.5.0", note = "Prefer new_from_file. Some function names were changed so they more closely match their type signature. See issue 42 for discussion https://github.com/ndesh26/evdev-rs/issues/42" )] pub fn change_fd(&mut self, file: File) -> io::Result<()> { self.change_file(file)?; Ok(()) } /// Grab or ungrab the device through a kernel EVIOCGRAB. /// /// This prevents other clients (including kernel-internal ones such as /// rfkill) from receiving events from this device. This is generally a /// bad idea. Don't do this. Grabbing an already grabbed device, or /// ungrabbing an ungrabbed device is a noop and always succeeds. /// /// A grab is an operation tied to a file descriptor, not a device. If a /// client changes the file descriptor with Device::change_file(), it must /// also re-issue a grab with libevdev_grab(). pub fn grab(&mut self, grab: GrabMode) -> io::Result<()> { let result = unsafe { raw::libevdev_grab(self.raw, grab as c_int) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Check if there are events waiting for us. /// /// This function does not consume an event and may not access the device /// file at all. If there are events queued internally this function will /// return true. If the internal queue is empty, this function will poll /// the file descriptor for data. /// /// This is a convenience function for simple processes, most complex programs /// are expected to use select(2) or poll(2) on the file descriptor. The kernel /// guarantees that if data is available, it is a multiple of sizeof(struct /// input_event), and thus calling `next_event` when select(2) or /// poll(2) return is safe. You do not need `has_event_pending` if /// you're using select(2) or poll(2). pub fn has_event_pending(&self) -> bool { unsafe { raw::libevdev_has_event_pending(self.raw) > 0 } } /// Return the driver version of a device already intialize with `set_file` pub fn driver_version(&self) -> i32 { unsafe { raw::libevdev_get_driver_version(self.raw) as i32 } } /// Set the device's EV_ABS axis to the value defined in the abs /// parameter. This will be written to the kernel. pub fn set_kernel_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) { let (_, ev_code) = event_code_to_int(code); unsafe { raw::libevdev_kernel_set_abs_info( self.raw, ev_code, &absinfo.as_raw() as *const _, ); } } /// Turn an LED on or off. /// /// enabling an LED requires write permissions on the device's file descriptor. pub fn kernel_set_led_value( &self, code: &EventCode, value: LedState, ) -> io::Result<()> { let (_, ev_code) = event_code_to_int(code); let result = unsafe { raw::libevdev_kernel_set_led_value(self.raw, ev_code, value as c_int) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Set the clock ID to be used for timestamps. Further events from this device /// will report an event time based on the given clock. /// /// This is a modification only affecting this representation of /// this device. pub fn set_clock_id(&self, clockid: i32) -> io::Result<()> { let result = unsafe { raw::libevdev_set_clock_id(self.raw, clockid) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } /// Get the next event from the device. This function operates in two different /// modes: normal mode or sync mode. /// /// In normal mode (when flags has `evdev::NORMAL` set), this function returns /// `ReadStatus::Success` and returns the event. If no events are available at /// this time, it returns `-EAGAIN` as `Err`. /// /// If the current event is an `EV_SYN::SYN_DROPPED` event, this function returns /// `ReadStatus::Sync` and is set to the `EV_SYN` event.The caller should now call /// this function with the `evdev::SYNC` flag set, to get the set of events that /// make up the device state delta. This function returns ReadStatus::Sync for /// each event part of that delta, until it returns `-EAGAIN` once all events /// have been synced. /// /// If a device needs to be synced by the caller but the caller does not call /// with the `evdev::SYNC` flag set, all events from the diff are dropped after /// evdev updates its internal state and event processing continues as normal. /// Note that the current slot and the state of touch points may have updated /// during the `SYN_DROPPED` event, it is strongly recommended that a caller /// ignoring all sync events calls `current_slot` and checks the /// `ABS_MT_TRACKING_ID` values for all slots. /// /// If a device has changed state without events being enqueued in evdev, /// e.g. after changing the file descriptor, use the `evdev::FORCE_SYNC` flag. /// This triggers an internal sync of the device and `next_event` returns /// `ReadStatus::Sync`. pub fn next_event(&self, flags: ReadFlag) -> io::Result<(ReadStatus, InputEvent)> { let mut ev = raw::input_event { time: raw::timeval { tv_sec: 0, tv_usec: 0, }, type_: 0, code: 0, value: 0, }; let result = unsafe { raw::libevdev_next_event(self.raw, flags.bits as c_uint, &mut ev) }; let event = InputEvent { time: TimeVal { tv_sec: ev.time.tv_sec, tv_usec: ev.time.tv_usec, }, event_code: int_to_event_code(ev.type_ as u32, ev.code as u32), value: ev.value, }; match result { raw::LIBEVDEV_READ_STATUS_SUCCESS => Ok((ReadStatus::Success, event)), raw::LIBEVDEV_READ_STATUS_SYNC => Ok((ReadStatus::Sync, event)), error => Err(io::Error::from_raw_os_error(-error)), } } } impl Drop for Device { fn drop(&mut self) { unsafe { raw::libevdev_free(self.raw); } } } impl std::fmt::Debug for Device { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("Device") .field("name", &self.name()) .field("phys", &self.phys()) .field("uniq", &self.uniq()) .finish() } } evdev-rs-0.6.1/src/enums.rs000064400000000000000000002764410072674642500137150ustar 00000000000000/* THIS FILE IS GENERATED, DO NOT EDIT */ #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EventType { EV_SYN = 0, EV_KEY = 1, EV_REL = 2, EV_ABS = 3, EV_MSC = 4, EV_SW = 5, EV_LED = 17, EV_SND = 18, EV_REP = 20, EV_FF = 21, EV_PWR = 22, EV_FF_STATUS = 23, EV_UNK, EV_MAX = 31, } pub const fn int_to_event_type(code: u32) -> Option { match code { 0 => Some(EventType::EV_SYN), 1 => Some(EventType::EV_KEY), 2 => Some(EventType::EV_REL), 3 => Some(EventType::EV_ABS), 4 => Some(EventType::EV_MSC), 5 => Some(EventType::EV_SW), 17 => Some(EventType::EV_LED), 18 => Some(EventType::EV_SND), 20 => Some(EventType::EV_REP), 21 => Some(EventType::EV_FF), 22 => Some(EventType::EV_PWR), 23 => Some(EventType::EV_FF_STATUS), c if c < 31 => Some(EventType::EV_UNK), 31 => Some(EventType::EV_MAX), _ => None, } } impl std::str::FromStr for EventType { type Err = (); fn from_str(s: &str) -> Result { match s { "EV_SYN" => Ok(EventType::EV_SYN), "EV_KEY" => Ok(EventType::EV_KEY), "EV_REL" => Ok(EventType::EV_REL), "EV_ABS" => Ok(EventType::EV_ABS), "EV_MSC" => Ok(EventType::EV_MSC), "EV_SW" => Ok(EventType::EV_SW), "EV_LED" => Ok(EventType::EV_LED), "EV_SND" => Ok(EventType::EV_SND), "EV_REP" => Ok(EventType::EV_REP), "EV_FF" => Ok(EventType::EV_FF), "EV_PWR" => Ok(EventType::EV_PWR), "EV_FF_STATUS" => Ok(EventType::EV_FF_STATUS), "EV_MAX" => Ok(EventType::EV_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum EventCode { EV_SYN(EV_SYN), EV_KEY(EV_KEY), EV_REL(EV_REL), EV_ABS(EV_ABS), EV_MSC(EV_MSC), EV_SW(EV_SW), EV_LED(EV_LED), EV_SND(EV_SND), EV_REP(EV_REP), EV_FF(EV_FF), EV_PWR, EV_FF_STATUS(EV_FF), EV_UNK { event_type: u32, event_code: u32 }, EV_MAX, } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_REL { REL_X = 0, REL_Y = 1, REL_Z = 2, REL_RX = 3, REL_RY = 4, REL_RZ = 5, REL_HWHEEL = 6, REL_DIAL = 7, REL_WHEEL = 8, REL_MISC = 9, REL_RESERVED = 10, REL_WHEEL_HI_RES = 11, REL_HWHEEL_HI_RES = 12, REL_MAX = 15, } pub const fn int_to_ev_rel(code: u32) -> Option { match code { 0 => Some(EV_REL::REL_X), 1 => Some(EV_REL::REL_Y), 2 => Some(EV_REL::REL_Z), 3 => Some(EV_REL::REL_RX), 4 => Some(EV_REL::REL_RY), 5 => Some(EV_REL::REL_RZ), 6 => Some(EV_REL::REL_HWHEEL), 7 => Some(EV_REL::REL_DIAL), 8 => Some(EV_REL::REL_WHEEL), 9 => Some(EV_REL::REL_MISC), 10 => Some(EV_REL::REL_RESERVED), 11 => Some(EV_REL::REL_WHEEL_HI_RES), 12 => Some(EV_REL::REL_HWHEEL_HI_RES), 15 => Some(EV_REL::REL_MAX), _ => None, } } impl std::str::FromStr for EV_REL { type Err = (); fn from_str(s: &str) -> Result { match s { "REL_X" => Ok(EV_REL::REL_X), "REL_Y" => Ok(EV_REL::REL_Y), "REL_Z" => Ok(EV_REL::REL_Z), "REL_RX" => Ok(EV_REL::REL_RX), "REL_RY" => Ok(EV_REL::REL_RY), "REL_RZ" => Ok(EV_REL::REL_RZ), "REL_HWHEEL" => Ok(EV_REL::REL_HWHEEL), "REL_DIAL" => Ok(EV_REL::REL_DIAL), "REL_WHEEL" => Ok(EV_REL::REL_WHEEL), "REL_MISC" => Ok(EV_REL::REL_MISC), "REL_RESERVED" => Ok(EV_REL::REL_RESERVED), "REL_WHEEL_HI_RES" => Ok(EV_REL::REL_WHEEL_HI_RES), "REL_HWHEEL_HI_RES" => Ok(EV_REL::REL_HWHEEL_HI_RES), "REL_MAX" => Ok(EV_REL::REL_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_ABS { ABS_X = 0, ABS_Y = 1, ABS_Z = 2, ABS_RX = 3, ABS_RY = 4, ABS_RZ = 5, ABS_THROTTLE = 6, ABS_RUDDER = 7, ABS_WHEEL = 8, ABS_GAS = 9, ABS_BRAKE = 10, ABS_HAT0X = 16, ABS_HAT0Y = 17, ABS_HAT1X = 18, ABS_HAT1Y = 19, ABS_HAT2X = 20, ABS_HAT2Y = 21, ABS_HAT3X = 22, ABS_HAT3Y = 23, ABS_PRESSURE = 24, ABS_DISTANCE = 25, ABS_TILT_X = 26, ABS_TILT_Y = 27, ABS_TOOL_WIDTH = 28, ABS_VOLUME = 32, ABS_MISC = 40, ABS_RESERVED = 46, ABS_MT_SLOT = 47, ABS_MT_TOUCH_MAJOR = 48, ABS_MT_TOUCH_MINOR = 49, ABS_MT_WIDTH_MAJOR = 50, ABS_MT_WIDTH_MINOR = 51, ABS_MT_ORIENTATION = 52, ABS_MT_POSITION_X = 53, ABS_MT_POSITION_Y = 54, ABS_MT_TOOL_TYPE = 55, ABS_MT_BLOB_ID = 56, ABS_MT_TRACKING_ID = 57, ABS_MT_PRESSURE = 58, ABS_MT_DISTANCE = 59, ABS_MT_TOOL_X = 60, ABS_MT_TOOL_Y = 61, ABS_MAX = 63, } pub const fn int_to_ev_abs(code: u32) -> Option { match code { 0 => Some(EV_ABS::ABS_X), 1 => Some(EV_ABS::ABS_Y), 2 => Some(EV_ABS::ABS_Z), 3 => Some(EV_ABS::ABS_RX), 4 => Some(EV_ABS::ABS_RY), 5 => Some(EV_ABS::ABS_RZ), 6 => Some(EV_ABS::ABS_THROTTLE), 7 => Some(EV_ABS::ABS_RUDDER), 8 => Some(EV_ABS::ABS_WHEEL), 9 => Some(EV_ABS::ABS_GAS), 10 => Some(EV_ABS::ABS_BRAKE), 16 => Some(EV_ABS::ABS_HAT0X), 17 => Some(EV_ABS::ABS_HAT0Y), 18 => Some(EV_ABS::ABS_HAT1X), 19 => Some(EV_ABS::ABS_HAT1Y), 20 => Some(EV_ABS::ABS_HAT2X), 21 => Some(EV_ABS::ABS_HAT2Y), 22 => Some(EV_ABS::ABS_HAT3X), 23 => Some(EV_ABS::ABS_HAT3Y), 24 => Some(EV_ABS::ABS_PRESSURE), 25 => Some(EV_ABS::ABS_DISTANCE), 26 => Some(EV_ABS::ABS_TILT_X), 27 => Some(EV_ABS::ABS_TILT_Y), 28 => Some(EV_ABS::ABS_TOOL_WIDTH), 32 => Some(EV_ABS::ABS_VOLUME), 40 => Some(EV_ABS::ABS_MISC), 46 => Some(EV_ABS::ABS_RESERVED), 47 => Some(EV_ABS::ABS_MT_SLOT), 48 => Some(EV_ABS::ABS_MT_TOUCH_MAJOR), 49 => Some(EV_ABS::ABS_MT_TOUCH_MINOR), 50 => Some(EV_ABS::ABS_MT_WIDTH_MAJOR), 51 => Some(EV_ABS::ABS_MT_WIDTH_MINOR), 52 => Some(EV_ABS::ABS_MT_ORIENTATION), 53 => Some(EV_ABS::ABS_MT_POSITION_X), 54 => Some(EV_ABS::ABS_MT_POSITION_Y), 55 => Some(EV_ABS::ABS_MT_TOOL_TYPE), 56 => Some(EV_ABS::ABS_MT_BLOB_ID), 57 => Some(EV_ABS::ABS_MT_TRACKING_ID), 58 => Some(EV_ABS::ABS_MT_PRESSURE), 59 => Some(EV_ABS::ABS_MT_DISTANCE), 60 => Some(EV_ABS::ABS_MT_TOOL_X), 61 => Some(EV_ABS::ABS_MT_TOOL_Y), 63 => Some(EV_ABS::ABS_MAX), _ => None, } } impl std::str::FromStr for EV_ABS { type Err = (); fn from_str(s: &str) -> Result { match s { "ABS_X" => Ok(EV_ABS::ABS_X), "ABS_Y" => Ok(EV_ABS::ABS_Y), "ABS_Z" => Ok(EV_ABS::ABS_Z), "ABS_RX" => Ok(EV_ABS::ABS_RX), "ABS_RY" => Ok(EV_ABS::ABS_RY), "ABS_RZ" => Ok(EV_ABS::ABS_RZ), "ABS_THROTTLE" => Ok(EV_ABS::ABS_THROTTLE), "ABS_RUDDER" => Ok(EV_ABS::ABS_RUDDER), "ABS_WHEEL" => Ok(EV_ABS::ABS_WHEEL), "ABS_GAS" => Ok(EV_ABS::ABS_GAS), "ABS_BRAKE" => Ok(EV_ABS::ABS_BRAKE), "ABS_HAT0X" => Ok(EV_ABS::ABS_HAT0X), "ABS_HAT0Y" => Ok(EV_ABS::ABS_HAT0Y), "ABS_HAT1X" => Ok(EV_ABS::ABS_HAT1X), "ABS_HAT1Y" => Ok(EV_ABS::ABS_HAT1Y), "ABS_HAT2X" => Ok(EV_ABS::ABS_HAT2X), "ABS_HAT2Y" => Ok(EV_ABS::ABS_HAT2Y), "ABS_HAT3X" => Ok(EV_ABS::ABS_HAT3X), "ABS_HAT3Y" => Ok(EV_ABS::ABS_HAT3Y), "ABS_PRESSURE" => Ok(EV_ABS::ABS_PRESSURE), "ABS_DISTANCE" => Ok(EV_ABS::ABS_DISTANCE), "ABS_TILT_X" => Ok(EV_ABS::ABS_TILT_X), "ABS_TILT_Y" => Ok(EV_ABS::ABS_TILT_Y), "ABS_TOOL_WIDTH" => Ok(EV_ABS::ABS_TOOL_WIDTH), "ABS_VOLUME" => Ok(EV_ABS::ABS_VOLUME), "ABS_MISC" => Ok(EV_ABS::ABS_MISC), "ABS_RESERVED" => Ok(EV_ABS::ABS_RESERVED), "ABS_MT_SLOT" => Ok(EV_ABS::ABS_MT_SLOT), "ABS_MT_TOUCH_MAJOR" => Ok(EV_ABS::ABS_MT_TOUCH_MAJOR), "ABS_MT_TOUCH_MINOR" => Ok(EV_ABS::ABS_MT_TOUCH_MINOR), "ABS_MT_WIDTH_MAJOR" => Ok(EV_ABS::ABS_MT_WIDTH_MAJOR), "ABS_MT_WIDTH_MINOR" => Ok(EV_ABS::ABS_MT_WIDTH_MINOR), "ABS_MT_ORIENTATION" => Ok(EV_ABS::ABS_MT_ORIENTATION), "ABS_MT_POSITION_X" => Ok(EV_ABS::ABS_MT_POSITION_X), "ABS_MT_POSITION_Y" => Ok(EV_ABS::ABS_MT_POSITION_Y), "ABS_MT_TOOL_TYPE" => Ok(EV_ABS::ABS_MT_TOOL_TYPE), "ABS_MT_BLOB_ID" => Ok(EV_ABS::ABS_MT_BLOB_ID), "ABS_MT_TRACKING_ID" => Ok(EV_ABS::ABS_MT_TRACKING_ID), "ABS_MT_PRESSURE" => Ok(EV_ABS::ABS_MT_PRESSURE), "ABS_MT_DISTANCE" => Ok(EV_ABS::ABS_MT_DISTANCE), "ABS_MT_TOOL_X" => Ok(EV_ABS::ABS_MT_TOOL_X), "ABS_MT_TOOL_Y" => Ok(EV_ABS::ABS_MT_TOOL_Y), "ABS_MAX" => Ok(EV_ABS::ABS_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_KEY { KEY_RESERVED = 0, KEY_ESC = 1, KEY_1 = 2, KEY_2 = 3, KEY_3 = 4, KEY_4 = 5, KEY_5 = 6, KEY_6 = 7, KEY_7 = 8, KEY_8 = 9, KEY_9 = 10, KEY_0 = 11, KEY_MINUS = 12, KEY_EQUAL = 13, KEY_BACKSPACE = 14, KEY_TAB = 15, KEY_Q = 16, KEY_W = 17, KEY_E = 18, KEY_R = 19, KEY_T = 20, KEY_Y = 21, KEY_U = 22, KEY_I = 23, KEY_O = 24, KEY_P = 25, KEY_LEFTBRACE = 26, KEY_RIGHTBRACE = 27, KEY_ENTER = 28, KEY_LEFTCTRL = 29, KEY_A = 30, KEY_S = 31, KEY_D = 32, KEY_F = 33, KEY_G = 34, KEY_H = 35, KEY_J = 36, KEY_K = 37, KEY_L = 38, KEY_SEMICOLON = 39, KEY_APOSTROPHE = 40, KEY_GRAVE = 41, KEY_LEFTSHIFT = 42, KEY_BACKSLASH = 43, KEY_Z = 44, KEY_X = 45, KEY_C = 46, KEY_V = 47, KEY_B = 48, KEY_N = 49, KEY_M = 50, KEY_COMMA = 51, KEY_DOT = 52, KEY_SLASH = 53, KEY_RIGHTSHIFT = 54, KEY_KPASTERISK = 55, KEY_LEFTALT = 56, KEY_SPACE = 57, KEY_CAPSLOCK = 58, KEY_F1 = 59, KEY_F2 = 60, KEY_F3 = 61, KEY_F4 = 62, KEY_F5 = 63, KEY_F6 = 64, KEY_F7 = 65, KEY_F8 = 66, KEY_F9 = 67, KEY_F10 = 68, KEY_NUMLOCK = 69, KEY_SCROLLLOCK = 70, KEY_KP7 = 71, KEY_KP8 = 72, KEY_KP9 = 73, KEY_KPMINUS = 74, KEY_KP4 = 75, KEY_KP5 = 76, KEY_KP6 = 77, KEY_KPPLUS = 78, KEY_KP1 = 79, KEY_KP2 = 80, KEY_KP3 = 81, KEY_KP0 = 82, KEY_KPDOT = 83, KEY_ZENKAKUHANKAKU = 85, KEY_102ND = 86, KEY_F11 = 87, KEY_F12 = 88, KEY_RO = 89, KEY_KATAKANA = 90, KEY_HIRAGANA = 91, KEY_HENKAN = 92, KEY_KATAKANAHIRAGANA = 93, KEY_MUHENKAN = 94, KEY_KPJPCOMMA = 95, KEY_KPENTER = 96, KEY_RIGHTCTRL = 97, KEY_KPSLASH = 98, KEY_SYSRQ = 99, KEY_RIGHTALT = 100, KEY_LINEFEED = 101, KEY_HOME = 102, KEY_UP = 103, KEY_PAGEUP = 104, KEY_LEFT = 105, KEY_RIGHT = 106, KEY_END = 107, KEY_DOWN = 108, KEY_PAGEDOWN = 109, KEY_INSERT = 110, KEY_DELETE = 111, KEY_MACRO = 112, KEY_MUTE = 113, KEY_VOLUMEDOWN = 114, KEY_VOLUMEUP = 115, KEY_POWER = 116, KEY_KPEQUAL = 117, KEY_KPPLUSMINUS = 118, KEY_PAUSE = 119, KEY_SCALE = 120, KEY_KPCOMMA = 121, KEY_HANGEUL = 122, KEY_HANJA = 123, KEY_YEN = 124, KEY_LEFTMETA = 125, KEY_RIGHTMETA = 126, KEY_COMPOSE = 127, KEY_STOP = 128, KEY_AGAIN = 129, KEY_PROPS = 130, KEY_UNDO = 131, KEY_FRONT = 132, KEY_COPY = 133, KEY_OPEN = 134, KEY_PASTE = 135, KEY_FIND = 136, KEY_CUT = 137, KEY_HELP = 138, KEY_MENU = 139, KEY_CALC = 140, KEY_SETUP = 141, KEY_SLEEP = 142, KEY_WAKEUP = 143, KEY_FILE = 144, KEY_SENDFILE = 145, KEY_DELETEFILE = 146, KEY_XFER = 147, KEY_PROG1 = 148, KEY_PROG2 = 149, KEY_WWW = 150, KEY_MSDOS = 151, KEY_COFFEE = 152, KEY_ROTATE_DISPLAY = 153, KEY_CYCLEWINDOWS = 154, KEY_MAIL = 155, KEY_BOOKMARKS = 156, KEY_COMPUTER = 157, KEY_BACK = 158, KEY_FORWARD = 159, KEY_CLOSECD = 160, KEY_EJECTCD = 161, KEY_EJECTCLOSECD = 162, KEY_NEXTSONG = 163, KEY_PLAYPAUSE = 164, KEY_PREVIOUSSONG = 165, KEY_STOPCD = 166, KEY_RECORD = 167, KEY_REWIND = 168, KEY_PHONE = 169, KEY_ISO = 170, KEY_CONFIG = 171, KEY_HOMEPAGE = 172, KEY_REFRESH = 173, KEY_EXIT = 174, KEY_MOVE = 175, KEY_EDIT = 176, KEY_SCROLLUP = 177, KEY_SCROLLDOWN = 178, KEY_KPLEFTPAREN = 179, KEY_KPRIGHTPAREN = 180, KEY_NEW = 181, KEY_REDO = 182, KEY_F13 = 183, KEY_F14 = 184, KEY_F15 = 185, KEY_F16 = 186, KEY_F17 = 187, KEY_F18 = 188, KEY_F19 = 189, KEY_F20 = 190, KEY_F21 = 191, KEY_F22 = 192, KEY_F23 = 193, KEY_F24 = 194, KEY_PLAYCD = 200, KEY_PAUSECD = 201, KEY_PROG3 = 202, KEY_PROG4 = 203, KEY_ALL_APPLICATIONS = 204, KEY_SUSPEND = 205, KEY_CLOSE = 206, KEY_PLAY = 207, KEY_FASTFORWARD = 208, KEY_BASSBOOST = 209, KEY_PRINT = 210, KEY_HP = 211, KEY_CAMERA = 212, KEY_SOUND = 213, KEY_QUESTION = 214, KEY_EMAIL = 215, KEY_CHAT = 216, KEY_SEARCH = 217, KEY_CONNECT = 218, KEY_FINANCE = 219, KEY_SPORT = 220, KEY_SHOP = 221, KEY_ALTERASE = 222, KEY_CANCEL = 223, KEY_BRIGHTNESSDOWN = 224, KEY_BRIGHTNESSUP = 225, KEY_MEDIA = 226, KEY_SWITCHVIDEOMODE = 227, KEY_KBDILLUMTOGGLE = 228, KEY_KBDILLUMDOWN = 229, KEY_KBDILLUMUP = 230, KEY_SEND = 231, KEY_REPLY = 232, KEY_FORWARDMAIL = 233, KEY_SAVE = 234, KEY_DOCUMENTS = 235, KEY_BATTERY = 236, KEY_BLUETOOTH = 237, KEY_WLAN = 238, KEY_UWB = 239, KEY_UNKNOWN = 240, KEY_VIDEO_NEXT = 241, KEY_VIDEO_PREV = 242, KEY_BRIGHTNESS_CYCLE = 243, KEY_BRIGHTNESS_AUTO = 244, KEY_DISPLAY_OFF = 245, KEY_WWAN = 246, KEY_RFKILL = 247, KEY_MICMUTE = 248, KEY_OK = 352, KEY_SELECT = 353, KEY_GOTO = 354, KEY_CLEAR = 355, KEY_POWER2 = 356, KEY_OPTION = 357, KEY_INFO = 358, KEY_TIME = 359, KEY_VENDOR = 360, KEY_ARCHIVE = 361, KEY_PROGRAM = 362, KEY_CHANNEL = 363, KEY_FAVORITES = 364, KEY_EPG = 365, KEY_PVR = 366, KEY_MHP = 367, KEY_LANGUAGE = 368, KEY_TITLE = 369, KEY_SUBTITLE = 370, KEY_ANGLE = 371, KEY_FULL_SCREEN = 372, KEY_MODE = 373, KEY_KEYBOARD = 374, KEY_ASPECT_RATIO = 375, KEY_PC = 376, KEY_TV = 377, KEY_TV2 = 378, KEY_VCR = 379, KEY_VCR2 = 380, KEY_SAT = 381, KEY_SAT2 = 382, KEY_CD = 383, KEY_TAPE = 384, KEY_RADIO = 385, KEY_TUNER = 386, KEY_PLAYER = 387, KEY_TEXT = 388, KEY_DVD = 389, KEY_AUX = 390, KEY_MP3 = 391, KEY_AUDIO = 392, KEY_VIDEO = 393, KEY_DIRECTORY = 394, KEY_LIST = 395, KEY_MEMO = 396, KEY_CALENDAR = 397, KEY_RED = 398, KEY_GREEN = 399, KEY_YELLOW = 400, KEY_BLUE = 401, KEY_CHANNELUP = 402, KEY_CHANNELDOWN = 403, KEY_FIRST = 404, KEY_LAST = 405, KEY_AB = 406, KEY_NEXT = 407, KEY_RESTART = 408, KEY_SLOW = 409, KEY_SHUFFLE = 410, KEY_BREAK = 411, KEY_PREVIOUS = 412, KEY_DIGITS = 413, KEY_TEEN = 414, KEY_TWEN = 415, KEY_VIDEOPHONE = 416, KEY_GAMES = 417, KEY_ZOOMIN = 418, KEY_ZOOMOUT = 419, KEY_ZOOMRESET = 420, KEY_WORDPROCESSOR = 421, KEY_EDITOR = 422, KEY_SPREADSHEET = 423, KEY_GRAPHICSEDITOR = 424, KEY_PRESENTATION = 425, KEY_DATABASE = 426, KEY_NEWS = 427, KEY_VOICEMAIL = 428, KEY_ADDRESSBOOK = 429, KEY_MESSENGER = 430, KEY_DISPLAYTOGGLE = 431, KEY_SPELLCHECK = 432, KEY_LOGOFF = 433, KEY_DOLLAR = 434, KEY_EURO = 435, KEY_FRAMEBACK = 436, KEY_FRAMEFORWARD = 437, KEY_CONTEXT_MENU = 438, KEY_MEDIA_REPEAT = 439, KEY_10CHANNELSUP = 440, KEY_10CHANNELSDOWN = 441, KEY_IMAGES = 442, KEY_NOTIFICATION_CENTER = 444, KEY_PICKUP_PHONE = 445, KEY_HANGUP_PHONE = 446, KEY_DEL_EOL = 448, KEY_DEL_EOS = 449, KEY_INS_LINE = 450, KEY_DEL_LINE = 451, KEY_FN = 464, KEY_FN_ESC = 465, KEY_FN_F1 = 466, KEY_FN_F2 = 467, KEY_FN_F3 = 468, KEY_FN_F4 = 469, KEY_FN_F5 = 470, KEY_FN_F6 = 471, KEY_FN_F7 = 472, KEY_FN_F8 = 473, KEY_FN_F9 = 474, KEY_FN_F10 = 475, KEY_FN_F11 = 476, KEY_FN_F12 = 477, KEY_FN_1 = 478, KEY_FN_2 = 479, KEY_FN_D = 480, KEY_FN_E = 481, KEY_FN_F = 482, KEY_FN_S = 483, KEY_FN_B = 484, KEY_FN_RIGHT_SHIFT = 485, KEY_BRL_DOT1 = 497, KEY_BRL_DOT2 = 498, KEY_BRL_DOT3 = 499, KEY_BRL_DOT4 = 500, KEY_BRL_DOT5 = 501, KEY_BRL_DOT6 = 502, KEY_BRL_DOT7 = 503, KEY_BRL_DOT8 = 504, KEY_BRL_DOT9 = 505, KEY_BRL_DOT10 = 506, KEY_NUMERIC_0 = 512, KEY_NUMERIC_1 = 513, KEY_NUMERIC_2 = 514, KEY_NUMERIC_3 = 515, KEY_NUMERIC_4 = 516, KEY_NUMERIC_5 = 517, KEY_NUMERIC_6 = 518, KEY_NUMERIC_7 = 519, KEY_NUMERIC_8 = 520, KEY_NUMERIC_9 = 521, KEY_NUMERIC_STAR = 522, KEY_NUMERIC_POUND = 523, KEY_NUMERIC_A = 524, KEY_NUMERIC_B = 525, KEY_NUMERIC_C = 526, KEY_NUMERIC_D = 527, KEY_CAMERA_FOCUS = 528, KEY_WPS_BUTTON = 529, KEY_TOUCHPAD_TOGGLE = 530, KEY_TOUCHPAD_ON = 531, KEY_TOUCHPAD_OFF = 532, KEY_CAMERA_ZOOMIN = 533, KEY_CAMERA_ZOOMOUT = 534, KEY_CAMERA_UP = 535, KEY_CAMERA_DOWN = 536, KEY_CAMERA_LEFT = 537, KEY_CAMERA_RIGHT = 538, KEY_ATTENDANT_ON = 539, KEY_ATTENDANT_OFF = 540, KEY_ATTENDANT_TOGGLE = 541, KEY_LIGHTS_TOGGLE = 542, KEY_ALS_TOGGLE = 560, KEY_ROTATE_LOCK_TOGGLE = 561, KEY_BUTTONCONFIG = 576, KEY_TASKMANAGER = 577, KEY_JOURNAL = 578, KEY_CONTROLPANEL = 579, KEY_APPSELECT = 580, KEY_SCREENSAVER = 581, KEY_VOICECOMMAND = 582, KEY_ASSISTANT = 583, KEY_KBD_LAYOUT_NEXT = 584, KEY_EMOJI_PICKER = 585, KEY_DICTATE = 586, KEY_BRIGHTNESS_MIN = 592, KEY_BRIGHTNESS_MAX = 593, KEY_KBDINPUTASSIST_PREV = 608, KEY_KBDINPUTASSIST_NEXT = 609, KEY_KBDINPUTASSIST_PREVGROUP = 610, KEY_KBDINPUTASSIST_NEXTGROUP = 611, KEY_KBDINPUTASSIST_ACCEPT = 612, KEY_KBDINPUTASSIST_CANCEL = 613, KEY_RIGHT_UP = 614, KEY_RIGHT_DOWN = 615, KEY_LEFT_UP = 616, KEY_LEFT_DOWN = 617, KEY_ROOT_MENU = 618, KEY_MEDIA_TOP_MENU = 619, KEY_NUMERIC_11 = 620, KEY_NUMERIC_12 = 621, KEY_AUDIO_DESC = 622, KEY_3D_MODE = 623, KEY_NEXT_FAVORITE = 624, KEY_STOP_RECORD = 625, KEY_PAUSE_RECORD = 626, KEY_VOD = 627, KEY_UNMUTE = 628, KEY_FASTREVERSE = 629, KEY_SLOWREVERSE = 630, KEY_DATA = 631, KEY_ONSCREEN_KEYBOARD = 632, KEY_PRIVACY_SCREEN_TOGGLE = 633, KEY_SELECTIVE_SCREENSHOT = 634, KEY_MACRO1 = 656, KEY_MACRO2 = 657, KEY_MACRO3 = 658, KEY_MACRO4 = 659, KEY_MACRO5 = 660, KEY_MACRO6 = 661, KEY_MACRO7 = 662, KEY_MACRO8 = 663, KEY_MACRO9 = 664, KEY_MACRO10 = 665, KEY_MACRO11 = 666, KEY_MACRO12 = 667, KEY_MACRO13 = 668, KEY_MACRO14 = 669, KEY_MACRO15 = 670, KEY_MACRO16 = 671, KEY_MACRO17 = 672, KEY_MACRO18 = 673, KEY_MACRO19 = 674, KEY_MACRO20 = 675, KEY_MACRO21 = 676, KEY_MACRO22 = 677, KEY_MACRO23 = 678, KEY_MACRO24 = 679, KEY_MACRO25 = 680, KEY_MACRO26 = 681, KEY_MACRO27 = 682, KEY_MACRO28 = 683, KEY_MACRO29 = 684, KEY_MACRO30 = 685, KEY_MACRO_RECORD_START = 688, KEY_MACRO_RECORD_STOP = 689, KEY_MACRO_PRESET_CYCLE = 690, KEY_MACRO_PRESET1 = 691, KEY_MACRO_PRESET2 = 692, KEY_MACRO_PRESET3 = 693, KEY_KBD_LCD_MENU1 = 696, KEY_KBD_LCD_MENU2 = 697, KEY_KBD_LCD_MENU3 = 698, KEY_KBD_LCD_MENU4 = 699, KEY_KBD_LCD_MENU5 = 700, KEY_MAX = 767, BTN_0 = 256, BTN_1 = 257, BTN_2 = 258, BTN_3 = 259, BTN_4 = 260, BTN_5 = 261, BTN_6 = 262, BTN_7 = 263, BTN_8 = 264, BTN_9 = 265, BTN_LEFT = 272, BTN_RIGHT = 273, BTN_MIDDLE = 274, BTN_SIDE = 275, BTN_EXTRA = 276, BTN_FORWARD = 277, BTN_BACK = 278, BTN_TASK = 279, BTN_TRIGGER = 288, BTN_THUMB = 289, BTN_THUMB2 = 290, BTN_TOP = 291, BTN_TOP2 = 292, BTN_PINKIE = 293, BTN_BASE = 294, BTN_BASE2 = 295, BTN_BASE3 = 296, BTN_BASE4 = 297, BTN_BASE5 = 298, BTN_BASE6 = 299, BTN_DEAD = 303, BTN_SOUTH = 304, BTN_EAST = 305, BTN_C = 306, BTN_NORTH = 307, BTN_WEST = 308, BTN_Z = 309, BTN_TL = 310, BTN_TR = 311, BTN_TL2 = 312, BTN_TR2 = 313, BTN_SELECT = 314, BTN_START = 315, BTN_MODE = 316, BTN_THUMBL = 317, BTN_THUMBR = 318, BTN_TOOL_PEN = 320, BTN_TOOL_RUBBER = 321, BTN_TOOL_BRUSH = 322, BTN_TOOL_PENCIL = 323, BTN_TOOL_AIRBRUSH = 324, BTN_TOOL_FINGER = 325, BTN_TOOL_MOUSE = 326, BTN_TOOL_LENS = 327, BTN_TOOL_QUINTTAP = 328, BTN_STYLUS3 = 329, BTN_TOUCH = 330, BTN_STYLUS = 331, BTN_STYLUS2 = 332, BTN_TOOL_DOUBLETAP = 333, BTN_TOOL_TRIPLETAP = 334, BTN_TOOL_QUADTAP = 335, BTN_GEAR_DOWN = 336, BTN_GEAR_UP = 337, BTN_DPAD_UP = 544, BTN_DPAD_DOWN = 545, BTN_DPAD_LEFT = 546, BTN_DPAD_RIGHT = 547, BTN_TRIGGER_HAPPY1 = 704, BTN_TRIGGER_HAPPY2 = 705, BTN_TRIGGER_HAPPY3 = 706, BTN_TRIGGER_HAPPY4 = 707, BTN_TRIGGER_HAPPY5 = 708, BTN_TRIGGER_HAPPY6 = 709, BTN_TRIGGER_HAPPY7 = 710, BTN_TRIGGER_HAPPY8 = 711, BTN_TRIGGER_HAPPY9 = 712, BTN_TRIGGER_HAPPY10 = 713, BTN_TRIGGER_HAPPY11 = 714, BTN_TRIGGER_HAPPY12 = 715, BTN_TRIGGER_HAPPY13 = 716, BTN_TRIGGER_HAPPY14 = 717, BTN_TRIGGER_HAPPY15 = 718, BTN_TRIGGER_HAPPY16 = 719, BTN_TRIGGER_HAPPY17 = 720, BTN_TRIGGER_HAPPY18 = 721, BTN_TRIGGER_HAPPY19 = 722, BTN_TRIGGER_HAPPY20 = 723, BTN_TRIGGER_HAPPY21 = 724, BTN_TRIGGER_HAPPY22 = 725, BTN_TRIGGER_HAPPY23 = 726, BTN_TRIGGER_HAPPY24 = 727, BTN_TRIGGER_HAPPY25 = 728, BTN_TRIGGER_HAPPY26 = 729, BTN_TRIGGER_HAPPY27 = 730, BTN_TRIGGER_HAPPY28 = 731, BTN_TRIGGER_HAPPY29 = 732, BTN_TRIGGER_HAPPY30 = 733, BTN_TRIGGER_HAPPY31 = 734, BTN_TRIGGER_HAPPY32 = 735, BTN_TRIGGER_HAPPY33 = 736, BTN_TRIGGER_HAPPY34 = 737, BTN_TRIGGER_HAPPY35 = 738, BTN_TRIGGER_HAPPY36 = 739, BTN_TRIGGER_HAPPY37 = 740, BTN_TRIGGER_HAPPY38 = 741, BTN_TRIGGER_HAPPY39 = 742, BTN_TRIGGER_HAPPY40 = 743, } pub const fn int_to_ev_key(code: u32) -> Option { match code { 0 => Some(EV_KEY::KEY_RESERVED), 1 => Some(EV_KEY::KEY_ESC), 2 => Some(EV_KEY::KEY_1), 3 => Some(EV_KEY::KEY_2), 4 => Some(EV_KEY::KEY_3), 5 => Some(EV_KEY::KEY_4), 6 => Some(EV_KEY::KEY_5), 7 => Some(EV_KEY::KEY_6), 8 => Some(EV_KEY::KEY_7), 9 => Some(EV_KEY::KEY_8), 10 => Some(EV_KEY::KEY_9), 11 => Some(EV_KEY::KEY_0), 12 => Some(EV_KEY::KEY_MINUS), 13 => Some(EV_KEY::KEY_EQUAL), 14 => Some(EV_KEY::KEY_BACKSPACE), 15 => Some(EV_KEY::KEY_TAB), 16 => Some(EV_KEY::KEY_Q), 17 => Some(EV_KEY::KEY_W), 18 => Some(EV_KEY::KEY_E), 19 => Some(EV_KEY::KEY_R), 20 => Some(EV_KEY::KEY_T), 21 => Some(EV_KEY::KEY_Y), 22 => Some(EV_KEY::KEY_U), 23 => Some(EV_KEY::KEY_I), 24 => Some(EV_KEY::KEY_O), 25 => Some(EV_KEY::KEY_P), 26 => Some(EV_KEY::KEY_LEFTBRACE), 27 => Some(EV_KEY::KEY_RIGHTBRACE), 28 => Some(EV_KEY::KEY_ENTER), 29 => Some(EV_KEY::KEY_LEFTCTRL), 30 => Some(EV_KEY::KEY_A), 31 => Some(EV_KEY::KEY_S), 32 => Some(EV_KEY::KEY_D), 33 => Some(EV_KEY::KEY_F), 34 => Some(EV_KEY::KEY_G), 35 => Some(EV_KEY::KEY_H), 36 => Some(EV_KEY::KEY_J), 37 => Some(EV_KEY::KEY_K), 38 => Some(EV_KEY::KEY_L), 39 => Some(EV_KEY::KEY_SEMICOLON), 40 => Some(EV_KEY::KEY_APOSTROPHE), 41 => Some(EV_KEY::KEY_GRAVE), 42 => Some(EV_KEY::KEY_LEFTSHIFT), 43 => Some(EV_KEY::KEY_BACKSLASH), 44 => Some(EV_KEY::KEY_Z), 45 => Some(EV_KEY::KEY_X), 46 => Some(EV_KEY::KEY_C), 47 => Some(EV_KEY::KEY_V), 48 => Some(EV_KEY::KEY_B), 49 => Some(EV_KEY::KEY_N), 50 => Some(EV_KEY::KEY_M), 51 => Some(EV_KEY::KEY_COMMA), 52 => Some(EV_KEY::KEY_DOT), 53 => Some(EV_KEY::KEY_SLASH), 54 => Some(EV_KEY::KEY_RIGHTSHIFT), 55 => Some(EV_KEY::KEY_KPASTERISK), 56 => Some(EV_KEY::KEY_LEFTALT), 57 => Some(EV_KEY::KEY_SPACE), 58 => Some(EV_KEY::KEY_CAPSLOCK), 59 => Some(EV_KEY::KEY_F1), 60 => Some(EV_KEY::KEY_F2), 61 => Some(EV_KEY::KEY_F3), 62 => Some(EV_KEY::KEY_F4), 63 => Some(EV_KEY::KEY_F5), 64 => Some(EV_KEY::KEY_F6), 65 => Some(EV_KEY::KEY_F7), 66 => Some(EV_KEY::KEY_F8), 67 => Some(EV_KEY::KEY_F9), 68 => Some(EV_KEY::KEY_F10), 69 => Some(EV_KEY::KEY_NUMLOCK), 70 => Some(EV_KEY::KEY_SCROLLLOCK), 71 => Some(EV_KEY::KEY_KP7), 72 => Some(EV_KEY::KEY_KP8), 73 => Some(EV_KEY::KEY_KP9), 74 => Some(EV_KEY::KEY_KPMINUS), 75 => Some(EV_KEY::KEY_KP4), 76 => Some(EV_KEY::KEY_KP5), 77 => Some(EV_KEY::KEY_KP6), 78 => Some(EV_KEY::KEY_KPPLUS), 79 => Some(EV_KEY::KEY_KP1), 80 => Some(EV_KEY::KEY_KP2), 81 => Some(EV_KEY::KEY_KP3), 82 => Some(EV_KEY::KEY_KP0), 83 => Some(EV_KEY::KEY_KPDOT), 85 => Some(EV_KEY::KEY_ZENKAKUHANKAKU), 86 => Some(EV_KEY::KEY_102ND), 87 => Some(EV_KEY::KEY_F11), 88 => Some(EV_KEY::KEY_F12), 89 => Some(EV_KEY::KEY_RO), 90 => Some(EV_KEY::KEY_KATAKANA), 91 => Some(EV_KEY::KEY_HIRAGANA), 92 => Some(EV_KEY::KEY_HENKAN), 93 => Some(EV_KEY::KEY_KATAKANAHIRAGANA), 94 => Some(EV_KEY::KEY_MUHENKAN), 95 => Some(EV_KEY::KEY_KPJPCOMMA), 96 => Some(EV_KEY::KEY_KPENTER), 97 => Some(EV_KEY::KEY_RIGHTCTRL), 98 => Some(EV_KEY::KEY_KPSLASH), 99 => Some(EV_KEY::KEY_SYSRQ), 100 => Some(EV_KEY::KEY_RIGHTALT), 101 => Some(EV_KEY::KEY_LINEFEED), 102 => Some(EV_KEY::KEY_HOME), 103 => Some(EV_KEY::KEY_UP), 104 => Some(EV_KEY::KEY_PAGEUP), 105 => Some(EV_KEY::KEY_LEFT), 106 => Some(EV_KEY::KEY_RIGHT), 107 => Some(EV_KEY::KEY_END), 108 => Some(EV_KEY::KEY_DOWN), 109 => Some(EV_KEY::KEY_PAGEDOWN), 110 => Some(EV_KEY::KEY_INSERT), 111 => Some(EV_KEY::KEY_DELETE), 112 => Some(EV_KEY::KEY_MACRO), 113 => Some(EV_KEY::KEY_MUTE), 114 => Some(EV_KEY::KEY_VOLUMEDOWN), 115 => Some(EV_KEY::KEY_VOLUMEUP), 116 => Some(EV_KEY::KEY_POWER), 117 => Some(EV_KEY::KEY_KPEQUAL), 118 => Some(EV_KEY::KEY_KPPLUSMINUS), 119 => Some(EV_KEY::KEY_PAUSE), 120 => Some(EV_KEY::KEY_SCALE), 121 => Some(EV_KEY::KEY_KPCOMMA), 122 => Some(EV_KEY::KEY_HANGEUL), 123 => Some(EV_KEY::KEY_HANJA), 124 => Some(EV_KEY::KEY_YEN), 125 => Some(EV_KEY::KEY_LEFTMETA), 126 => Some(EV_KEY::KEY_RIGHTMETA), 127 => Some(EV_KEY::KEY_COMPOSE), 128 => Some(EV_KEY::KEY_STOP), 129 => Some(EV_KEY::KEY_AGAIN), 130 => Some(EV_KEY::KEY_PROPS), 131 => Some(EV_KEY::KEY_UNDO), 132 => Some(EV_KEY::KEY_FRONT), 133 => Some(EV_KEY::KEY_COPY), 134 => Some(EV_KEY::KEY_OPEN), 135 => Some(EV_KEY::KEY_PASTE), 136 => Some(EV_KEY::KEY_FIND), 137 => Some(EV_KEY::KEY_CUT), 138 => Some(EV_KEY::KEY_HELP), 139 => Some(EV_KEY::KEY_MENU), 140 => Some(EV_KEY::KEY_CALC), 141 => Some(EV_KEY::KEY_SETUP), 142 => Some(EV_KEY::KEY_SLEEP), 143 => Some(EV_KEY::KEY_WAKEUP), 144 => Some(EV_KEY::KEY_FILE), 145 => Some(EV_KEY::KEY_SENDFILE), 146 => Some(EV_KEY::KEY_DELETEFILE), 147 => Some(EV_KEY::KEY_XFER), 148 => Some(EV_KEY::KEY_PROG1), 149 => Some(EV_KEY::KEY_PROG2), 150 => Some(EV_KEY::KEY_WWW), 151 => Some(EV_KEY::KEY_MSDOS), 152 => Some(EV_KEY::KEY_COFFEE), 153 => Some(EV_KEY::KEY_ROTATE_DISPLAY), 154 => Some(EV_KEY::KEY_CYCLEWINDOWS), 155 => Some(EV_KEY::KEY_MAIL), 156 => Some(EV_KEY::KEY_BOOKMARKS), 157 => Some(EV_KEY::KEY_COMPUTER), 158 => Some(EV_KEY::KEY_BACK), 159 => Some(EV_KEY::KEY_FORWARD), 160 => Some(EV_KEY::KEY_CLOSECD), 161 => Some(EV_KEY::KEY_EJECTCD), 162 => Some(EV_KEY::KEY_EJECTCLOSECD), 163 => Some(EV_KEY::KEY_NEXTSONG), 164 => Some(EV_KEY::KEY_PLAYPAUSE), 165 => Some(EV_KEY::KEY_PREVIOUSSONG), 166 => Some(EV_KEY::KEY_STOPCD), 167 => Some(EV_KEY::KEY_RECORD), 168 => Some(EV_KEY::KEY_REWIND), 169 => Some(EV_KEY::KEY_PHONE), 170 => Some(EV_KEY::KEY_ISO), 171 => Some(EV_KEY::KEY_CONFIG), 172 => Some(EV_KEY::KEY_HOMEPAGE), 173 => Some(EV_KEY::KEY_REFRESH), 174 => Some(EV_KEY::KEY_EXIT), 175 => Some(EV_KEY::KEY_MOVE), 176 => Some(EV_KEY::KEY_EDIT), 177 => Some(EV_KEY::KEY_SCROLLUP), 178 => Some(EV_KEY::KEY_SCROLLDOWN), 179 => Some(EV_KEY::KEY_KPLEFTPAREN), 180 => Some(EV_KEY::KEY_KPRIGHTPAREN), 181 => Some(EV_KEY::KEY_NEW), 182 => Some(EV_KEY::KEY_REDO), 183 => Some(EV_KEY::KEY_F13), 184 => Some(EV_KEY::KEY_F14), 185 => Some(EV_KEY::KEY_F15), 186 => Some(EV_KEY::KEY_F16), 187 => Some(EV_KEY::KEY_F17), 188 => Some(EV_KEY::KEY_F18), 189 => Some(EV_KEY::KEY_F19), 190 => Some(EV_KEY::KEY_F20), 191 => Some(EV_KEY::KEY_F21), 192 => Some(EV_KEY::KEY_F22), 193 => Some(EV_KEY::KEY_F23), 194 => Some(EV_KEY::KEY_F24), 200 => Some(EV_KEY::KEY_PLAYCD), 201 => Some(EV_KEY::KEY_PAUSECD), 202 => Some(EV_KEY::KEY_PROG3), 203 => Some(EV_KEY::KEY_PROG4), 204 => Some(EV_KEY::KEY_ALL_APPLICATIONS), 205 => Some(EV_KEY::KEY_SUSPEND), 206 => Some(EV_KEY::KEY_CLOSE), 207 => Some(EV_KEY::KEY_PLAY), 208 => Some(EV_KEY::KEY_FASTFORWARD), 209 => Some(EV_KEY::KEY_BASSBOOST), 210 => Some(EV_KEY::KEY_PRINT), 211 => Some(EV_KEY::KEY_HP), 212 => Some(EV_KEY::KEY_CAMERA), 213 => Some(EV_KEY::KEY_SOUND), 214 => Some(EV_KEY::KEY_QUESTION), 215 => Some(EV_KEY::KEY_EMAIL), 216 => Some(EV_KEY::KEY_CHAT), 217 => Some(EV_KEY::KEY_SEARCH), 218 => Some(EV_KEY::KEY_CONNECT), 219 => Some(EV_KEY::KEY_FINANCE), 220 => Some(EV_KEY::KEY_SPORT), 221 => Some(EV_KEY::KEY_SHOP), 222 => Some(EV_KEY::KEY_ALTERASE), 223 => Some(EV_KEY::KEY_CANCEL), 224 => Some(EV_KEY::KEY_BRIGHTNESSDOWN), 225 => Some(EV_KEY::KEY_BRIGHTNESSUP), 226 => Some(EV_KEY::KEY_MEDIA), 227 => Some(EV_KEY::KEY_SWITCHVIDEOMODE), 228 => Some(EV_KEY::KEY_KBDILLUMTOGGLE), 229 => Some(EV_KEY::KEY_KBDILLUMDOWN), 230 => Some(EV_KEY::KEY_KBDILLUMUP), 231 => Some(EV_KEY::KEY_SEND), 232 => Some(EV_KEY::KEY_REPLY), 233 => Some(EV_KEY::KEY_FORWARDMAIL), 234 => Some(EV_KEY::KEY_SAVE), 235 => Some(EV_KEY::KEY_DOCUMENTS), 236 => Some(EV_KEY::KEY_BATTERY), 237 => Some(EV_KEY::KEY_BLUETOOTH), 238 => Some(EV_KEY::KEY_WLAN), 239 => Some(EV_KEY::KEY_UWB), 240 => Some(EV_KEY::KEY_UNKNOWN), 241 => Some(EV_KEY::KEY_VIDEO_NEXT), 242 => Some(EV_KEY::KEY_VIDEO_PREV), 243 => Some(EV_KEY::KEY_BRIGHTNESS_CYCLE), 244 => Some(EV_KEY::KEY_BRIGHTNESS_AUTO), 245 => Some(EV_KEY::KEY_DISPLAY_OFF), 246 => Some(EV_KEY::KEY_WWAN), 247 => Some(EV_KEY::KEY_RFKILL), 248 => Some(EV_KEY::KEY_MICMUTE), 352 => Some(EV_KEY::KEY_OK), 353 => Some(EV_KEY::KEY_SELECT), 354 => Some(EV_KEY::KEY_GOTO), 355 => Some(EV_KEY::KEY_CLEAR), 356 => Some(EV_KEY::KEY_POWER2), 357 => Some(EV_KEY::KEY_OPTION), 358 => Some(EV_KEY::KEY_INFO), 359 => Some(EV_KEY::KEY_TIME), 360 => Some(EV_KEY::KEY_VENDOR), 361 => Some(EV_KEY::KEY_ARCHIVE), 362 => Some(EV_KEY::KEY_PROGRAM), 363 => Some(EV_KEY::KEY_CHANNEL), 364 => Some(EV_KEY::KEY_FAVORITES), 365 => Some(EV_KEY::KEY_EPG), 366 => Some(EV_KEY::KEY_PVR), 367 => Some(EV_KEY::KEY_MHP), 368 => Some(EV_KEY::KEY_LANGUAGE), 369 => Some(EV_KEY::KEY_TITLE), 370 => Some(EV_KEY::KEY_SUBTITLE), 371 => Some(EV_KEY::KEY_ANGLE), 372 => Some(EV_KEY::KEY_FULL_SCREEN), 373 => Some(EV_KEY::KEY_MODE), 374 => Some(EV_KEY::KEY_KEYBOARD), 375 => Some(EV_KEY::KEY_ASPECT_RATIO), 376 => Some(EV_KEY::KEY_PC), 377 => Some(EV_KEY::KEY_TV), 378 => Some(EV_KEY::KEY_TV2), 379 => Some(EV_KEY::KEY_VCR), 380 => Some(EV_KEY::KEY_VCR2), 381 => Some(EV_KEY::KEY_SAT), 382 => Some(EV_KEY::KEY_SAT2), 383 => Some(EV_KEY::KEY_CD), 384 => Some(EV_KEY::KEY_TAPE), 385 => Some(EV_KEY::KEY_RADIO), 386 => Some(EV_KEY::KEY_TUNER), 387 => Some(EV_KEY::KEY_PLAYER), 388 => Some(EV_KEY::KEY_TEXT), 389 => Some(EV_KEY::KEY_DVD), 390 => Some(EV_KEY::KEY_AUX), 391 => Some(EV_KEY::KEY_MP3), 392 => Some(EV_KEY::KEY_AUDIO), 393 => Some(EV_KEY::KEY_VIDEO), 394 => Some(EV_KEY::KEY_DIRECTORY), 395 => Some(EV_KEY::KEY_LIST), 396 => Some(EV_KEY::KEY_MEMO), 397 => Some(EV_KEY::KEY_CALENDAR), 398 => Some(EV_KEY::KEY_RED), 399 => Some(EV_KEY::KEY_GREEN), 400 => Some(EV_KEY::KEY_YELLOW), 401 => Some(EV_KEY::KEY_BLUE), 402 => Some(EV_KEY::KEY_CHANNELUP), 403 => Some(EV_KEY::KEY_CHANNELDOWN), 404 => Some(EV_KEY::KEY_FIRST), 405 => Some(EV_KEY::KEY_LAST), 406 => Some(EV_KEY::KEY_AB), 407 => Some(EV_KEY::KEY_NEXT), 408 => Some(EV_KEY::KEY_RESTART), 409 => Some(EV_KEY::KEY_SLOW), 410 => Some(EV_KEY::KEY_SHUFFLE), 411 => Some(EV_KEY::KEY_BREAK), 412 => Some(EV_KEY::KEY_PREVIOUS), 413 => Some(EV_KEY::KEY_DIGITS), 414 => Some(EV_KEY::KEY_TEEN), 415 => Some(EV_KEY::KEY_TWEN), 416 => Some(EV_KEY::KEY_VIDEOPHONE), 417 => Some(EV_KEY::KEY_GAMES), 418 => Some(EV_KEY::KEY_ZOOMIN), 419 => Some(EV_KEY::KEY_ZOOMOUT), 420 => Some(EV_KEY::KEY_ZOOMRESET), 421 => Some(EV_KEY::KEY_WORDPROCESSOR), 422 => Some(EV_KEY::KEY_EDITOR), 423 => Some(EV_KEY::KEY_SPREADSHEET), 424 => Some(EV_KEY::KEY_GRAPHICSEDITOR), 425 => Some(EV_KEY::KEY_PRESENTATION), 426 => Some(EV_KEY::KEY_DATABASE), 427 => Some(EV_KEY::KEY_NEWS), 428 => Some(EV_KEY::KEY_VOICEMAIL), 429 => Some(EV_KEY::KEY_ADDRESSBOOK), 430 => Some(EV_KEY::KEY_MESSENGER), 431 => Some(EV_KEY::KEY_DISPLAYTOGGLE), 432 => Some(EV_KEY::KEY_SPELLCHECK), 433 => Some(EV_KEY::KEY_LOGOFF), 434 => Some(EV_KEY::KEY_DOLLAR), 435 => Some(EV_KEY::KEY_EURO), 436 => Some(EV_KEY::KEY_FRAMEBACK), 437 => Some(EV_KEY::KEY_FRAMEFORWARD), 438 => Some(EV_KEY::KEY_CONTEXT_MENU), 439 => Some(EV_KEY::KEY_MEDIA_REPEAT), 440 => Some(EV_KEY::KEY_10CHANNELSUP), 441 => Some(EV_KEY::KEY_10CHANNELSDOWN), 442 => Some(EV_KEY::KEY_IMAGES), 444 => Some(EV_KEY::KEY_NOTIFICATION_CENTER), 445 => Some(EV_KEY::KEY_PICKUP_PHONE), 446 => Some(EV_KEY::KEY_HANGUP_PHONE), 448 => Some(EV_KEY::KEY_DEL_EOL), 449 => Some(EV_KEY::KEY_DEL_EOS), 450 => Some(EV_KEY::KEY_INS_LINE), 451 => Some(EV_KEY::KEY_DEL_LINE), 464 => Some(EV_KEY::KEY_FN), 465 => Some(EV_KEY::KEY_FN_ESC), 466 => Some(EV_KEY::KEY_FN_F1), 467 => Some(EV_KEY::KEY_FN_F2), 468 => Some(EV_KEY::KEY_FN_F3), 469 => Some(EV_KEY::KEY_FN_F4), 470 => Some(EV_KEY::KEY_FN_F5), 471 => Some(EV_KEY::KEY_FN_F6), 472 => Some(EV_KEY::KEY_FN_F7), 473 => Some(EV_KEY::KEY_FN_F8), 474 => Some(EV_KEY::KEY_FN_F9), 475 => Some(EV_KEY::KEY_FN_F10), 476 => Some(EV_KEY::KEY_FN_F11), 477 => Some(EV_KEY::KEY_FN_F12), 478 => Some(EV_KEY::KEY_FN_1), 479 => Some(EV_KEY::KEY_FN_2), 480 => Some(EV_KEY::KEY_FN_D), 481 => Some(EV_KEY::KEY_FN_E), 482 => Some(EV_KEY::KEY_FN_F), 483 => Some(EV_KEY::KEY_FN_S), 484 => Some(EV_KEY::KEY_FN_B), 485 => Some(EV_KEY::KEY_FN_RIGHT_SHIFT), 497 => Some(EV_KEY::KEY_BRL_DOT1), 498 => Some(EV_KEY::KEY_BRL_DOT2), 499 => Some(EV_KEY::KEY_BRL_DOT3), 500 => Some(EV_KEY::KEY_BRL_DOT4), 501 => Some(EV_KEY::KEY_BRL_DOT5), 502 => Some(EV_KEY::KEY_BRL_DOT6), 503 => Some(EV_KEY::KEY_BRL_DOT7), 504 => Some(EV_KEY::KEY_BRL_DOT8), 505 => Some(EV_KEY::KEY_BRL_DOT9), 506 => Some(EV_KEY::KEY_BRL_DOT10), 512 => Some(EV_KEY::KEY_NUMERIC_0), 513 => Some(EV_KEY::KEY_NUMERIC_1), 514 => Some(EV_KEY::KEY_NUMERIC_2), 515 => Some(EV_KEY::KEY_NUMERIC_3), 516 => Some(EV_KEY::KEY_NUMERIC_4), 517 => Some(EV_KEY::KEY_NUMERIC_5), 518 => Some(EV_KEY::KEY_NUMERIC_6), 519 => Some(EV_KEY::KEY_NUMERIC_7), 520 => Some(EV_KEY::KEY_NUMERIC_8), 521 => Some(EV_KEY::KEY_NUMERIC_9), 522 => Some(EV_KEY::KEY_NUMERIC_STAR), 523 => Some(EV_KEY::KEY_NUMERIC_POUND), 524 => Some(EV_KEY::KEY_NUMERIC_A), 525 => Some(EV_KEY::KEY_NUMERIC_B), 526 => Some(EV_KEY::KEY_NUMERIC_C), 527 => Some(EV_KEY::KEY_NUMERIC_D), 528 => Some(EV_KEY::KEY_CAMERA_FOCUS), 529 => Some(EV_KEY::KEY_WPS_BUTTON), 530 => Some(EV_KEY::KEY_TOUCHPAD_TOGGLE), 531 => Some(EV_KEY::KEY_TOUCHPAD_ON), 532 => Some(EV_KEY::KEY_TOUCHPAD_OFF), 533 => Some(EV_KEY::KEY_CAMERA_ZOOMIN), 534 => Some(EV_KEY::KEY_CAMERA_ZOOMOUT), 535 => Some(EV_KEY::KEY_CAMERA_UP), 536 => Some(EV_KEY::KEY_CAMERA_DOWN), 537 => Some(EV_KEY::KEY_CAMERA_LEFT), 538 => Some(EV_KEY::KEY_CAMERA_RIGHT), 539 => Some(EV_KEY::KEY_ATTENDANT_ON), 540 => Some(EV_KEY::KEY_ATTENDANT_OFF), 541 => Some(EV_KEY::KEY_ATTENDANT_TOGGLE), 542 => Some(EV_KEY::KEY_LIGHTS_TOGGLE), 560 => Some(EV_KEY::KEY_ALS_TOGGLE), 561 => Some(EV_KEY::KEY_ROTATE_LOCK_TOGGLE), 576 => Some(EV_KEY::KEY_BUTTONCONFIG), 577 => Some(EV_KEY::KEY_TASKMANAGER), 578 => Some(EV_KEY::KEY_JOURNAL), 579 => Some(EV_KEY::KEY_CONTROLPANEL), 580 => Some(EV_KEY::KEY_APPSELECT), 581 => Some(EV_KEY::KEY_SCREENSAVER), 582 => Some(EV_KEY::KEY_VOICECOMMAND), 583 => Some(EV_KEY::KEY_ASSISTANT), 584 => Some(EV_KEY::KEY_KBD_LAYOUT_NEXT), 585 => Some(EV_KEY::KEY_EMOJI_PICKER), 586 => Some(EV_KEY::KEY_DICTATE), 592 => Some(EV_KEY::KEY_BRIGHTNESS_MIN), 593 => Some(EV_KEY::KEY_BRIGHTNESS_MAX), 608 => Some(EV_KEY::KEY_KBDINPUTASSIST_PREV), 609 => Some(EV_KEY::KEY_KBDINPUTASSIST_NEXT), 610 => Some(EV_KEY::KEY_KBDINPUTASSIST_PREVGROUP), 611 => Some(EV_KEY::KEY_KBDINPUTASSIST_NEXTGROUP), 612 => Some(EV_KEY::KEY_KBDINPUTASSIST_ACCEPT), 613 => Some(EV_KEY::KEY_KBDINPUTASSIST_CANCEL), 614 => Some(EV_KEY::KEY_RIGHT_UP), 615 => Some(EV_KEY::KEY_RIGHT_DOWN), 616 => Some(EV_KEY::KEY_LEFT_UP), 617 => Some(EV_KEY::KEY_LEFT_DOWN), 618 => Some(EV_KEY::KEY_ROOT_MENU), 619 => Some(EV_KEY::KEY_MEDIA_TOP_MENU), 620 => Some(EV_KEY::KEY_NUMERIC_11), 621 => Some(EV_KEY::KEY_NUMERIC_12), 622 => Some(EV_KEY::KEY_AUDIO_DESC), 623 => Some(EV_KEY::KEY_3D_MODE), 624 => Some(EV_KEY::KEY_NEXT_FAVORITE), 625 => Some(EV_KEY::KEY_STOP_RECORD), 626 => Some(EV_KEY::KEY_PAUSE_RECORD), 627 => Some(EV_KEY::KEY_VOD), 628 => Some(EV_KEY::KEY_UNMUTE), 629 => Some(EV_KEY::KEY_FASTREVERSE), 630 => Some(EV_KEY::KEY_SLOWREVERSE), 631 => Some(EV_KEY::KEY_DATA), 632 => Some(EV_KEY::KEY_ONSCREEN_KEYBOARD), 633 => Some(EV_KEY::KEY_PRIVACY_SCREEN_TOGGLE), 634 => Some(EV_KEY::KEY_SELECTIVE_SCREENSHOT), 656 => Some(EV_KEY::KEY_MACRO1), 657 => Some(EV_KEY::KEY_MACRO2), 658 => Some(EV_KEY::KEY_MACRO3), 659 => Some(EV_KEY::KEY_MACRO4), 660 => Some(EV_KEY::KEY_MACRO5), 661 => Some(EV_KEY::KEY_MACRO6), 662 => Some(EV_KEY::KEY_MACRO7), 663 => Some(EV_KEY::KEY_MACRO8), 664 => Some(EV_KEY::KEY_MACRO9), 665 => Some(EV_KEY::KEY_MACRO10), 666 => Some(EV_KEY::KEY_MACRO11), 667 => Some(EV_KEY::KEY_MACRO12), 668 => Some(EV_KEY::KEY_MACRO13), 669 => Some(EV_KEY::KEY_MACRO14), 670 => Some(EV_KEY::KEY_MACRO15), 671 => Some(EV_KEY::KEY_MACRO16), 672 => Some(EV_KEY::KEY_MACRO17), 673 => Some(EV_KEY::KEY_MACRO18), 674 => Some(EV_KEY::KEY_MACRO19), 675 => Some(EV_KEY::KEY_MACRO20), 676 => Some(EV_KEY::KEY_MACRO21), 677 => Some(EV_KEY::KEY_MACRO22), 678 => Some(EV_KEY::KEY_MACRO23), 679 => Some(EV_KEY::KEY_MACRO24), 680 => Some(EV_KEY::KEY_MACRO25), 681 => Some(EV_KEY::KEY_MACRO26), 682 => Some(EV_KEY::KEY_MACRO27), 683 => Some(EV_KEY::KEY_MACRO28), 684 => Some(EV_KEY::KEY_MACRO29), 685 => Some(EV_KEY::KEY_MACRO30), 688 => Some(EV_KEY::KEY_MACRO_RECORD_START), 689 => Some(EV_KEY::KEY_MACRO_RECORD_STOP), 690 => Some(EV_KEY::KEY_MACRO_PRESET_CYCLE), 691 => Some(EV_KEY::KEY_MACRO_PRESET1), 692 => Some(EV_KEY::KEY_MACRO_PRESET2), 693 => Some(EV_KEY::KEY_MACRO_PRESET3), 696 => Some(EV_KEY::KEY_KBD_LCD_MENU1), 697 => Some(EV_KEY::KEY_KBD_LCD_MENU2), 698 => Some(EV_KEY::KEY_KBD_LCD_MENU3), 699 => Some(EV_KEY::KEY_KBD_LCD_MENU4), 700 => Some(EV_KEY::KEY_KBD_LCD_MENU5), 767 => Some(EV_KEY::KEY_MAX), 256 => Some(EV_KEY::BTN_0), 257 => Some(EV_KEY::BTN_1), 258 => Some(EV_KEY::BTN_2), 259 => Some(EV_KEY::BTN_3), 260 => Some(EV_KEY::BTN_4), 261 => Some(EV_KEY::BTN_5), 262 => Some(EV_KEY::BTN_6), 263 => Some(EV_KEY::BTN_7), 264 => Some(EV_KEY::BTN_8), 265 => Some(EV_KEY::BTN_9), 272 => Some(EV_KEY::BTN_LEFT), 273 => Some(EV_KEY::BTN_RIGHT), 274 => Some(EV_KEY::BTN_MIDDLE), 275 => Some(EV_KEY::BTN_SIDE), 276 => Some(EV_KEY::BTN_EXTRA), 277 => Some(EV_KEY::BTN_FORWARD), 278 => Some(EV_KEY::BTN_BACK), 279 => Some(EV_KEY::BTN_TASK), 288 => Some(EV_KEY::BTN_TRIGGER), 289 => Some(EV_KEY::BTN_THUMB), 290 => Some(EV_KEY::BTN_THUMB2), 291 => Some(EV_KEY::BTN_TOP), 292 => Some(EV_KEY::BTN_TOP2), 293 => Some(EV_KEY::BTN_PINKIE), 294 => Some(EV_KEY::BTN_BASE), 295 => Some(EV_KEY::BTN_BASE2), 296 => Some(EV_KEY::BTN_BASE3), 297 => Some(EV_KEY::BTN_BASE4), 298 => Some(EV_KEY::BTN_BASE5), 299 => Some(EV_KEY::BTN_BASE6), 303 => Some(EV_KEY::BTN_DEAD), 304 => Some(EV_KEY::BTN_SOUTH), 305 => Some(EV_KEY::BTN_EAST), 306 => Some(EV_KEY::BTN_C), 307 => Some(EV_KEY::BTN_NORTH), 308 => Some(EV_KEY::BTN_WEST), 309 => Some(EV_KEY::BTN_Z), 310 => Some(EV_KEY::BTN_TL), 311 => Some(EV_KEY::BTN_TR), 312 => Some(EV_KEY::BTN_TL2), 313 => Some(EV_KEY::BTN_TR2), 314 => Some(EV_KEY::BTN_SELECT), 315 => Some(EV_KEY::BTN_START), 316 => Some(EV_KEY::BTN_MODE), 317 => Some(EV_KEY::BTN_THUMBL), 318 => Some(EV_KEY::BTN_THUMBR), 320 => Some(EV_KEY::BTN_TOOL_PEN), 321 => Some(EV_KEY::BTN_TOOL_RUBBER), 322 => Some(EV_KEY::BTN_TOOL_BRUSH), 323 => Some(EV_KEY::BTN_TOOL_PENCIL), 324 => Some(EV_KEY::BTN_TOOL_AIRBRUSH), 325 => Some(EV_KEY::BTN_TOOL_FINGER), 326 => Some(EV_KEY::BTN_TOOL_MOUSE), 327 => Some(EV_KEY::BTN_TOOL_LENS), 328 => Some(EV_KEY::BTN_TOOL_QUINTTAP), 329 => Some(EV_KEY::BTN_STYLUS3), 330 => Some(EV_KEY::BTN_TOUCH), 331 => Some(EV_KEY::BTN_STYLUS), 332 => Some(EV_KEY::BTN_STYLUS2), 333 => Some(EV_KEY::BTN_TOOL_DOUBLETAP), 334 => Some(EV_KEY::BTN_TOOL_TRIPLETAP), 335 => Some(EV_KEY::BTN_TOOL_QUADTAP), 336 => Some(EV_KEY::BTN_GEAR_DOWN), 337 => Some(EV_KEY::BTN_GEAR_UP), 544 => Some(EV_KEY::BTN_DPAD_UP), 545 => Some(EV_KEY::BTN_DPAD_DOWN), 546 => Some(EV_KEY::BTN_DPAD_LEFT), 547 => Some(EV_KEY::BTN_DPAD_RIGHT), 704 => Some(EV_KEY::BTN_TRIGGER_HAPPY1), 705 => Some(EV_KEY::BTN_TRIGGER_HAPPY2), 706 => Some(EV_KEY::BTN_TRIGGER_HAPPY3), 707 => Some(EV_KEY::BTN_TRIGGER_HAPPY4), 708 => Some(EV_KEY::BTN_TRIGGER_HAPPY5), 709 => Some(EV_KEY::BTN_TRIGGER_HAPPY6), 710 => Some(EV_KEY::BTN_TRIGGER_HAPPY7), 711 => Some(EV_KEY::BTN_TRIGGER_HAPPY8), 712 => Some(EV_KEY::BTN_TRIGGER_HAPPY9), 713 => Some(EV_KEY::BTN_TRIGGER_HAPPY10), 714 => Some(EV_KEY::BTN_TRIGGER_HAPPY11), 715 => Some(EV_KEY::BTN_TRIGGER_HAPPY12), 716 => Some(EV_KEY::BTN_TRIGGER_HAPPY13), 717 => Some(EV_KEY::BTN_TRIGGER_HAPPY14), 718 => Some(EV_KEY::BTN_TRIGGER_HAPPY15), 719 => Some(EV_KEY::BTN_TRIGGER_HAPPY16), 720 => Some(EV_KEY::BTN_TRIGGER_HAPPY17), 721 => Some(EV_KEY::BTN_TRIGGER_HAPPY18), 722 => Some(EV_KEY::BTN_TRIGGER_HAPPY19), 723 => Some(EV_KEY::BTN_TRIGGER_HAPPY20), 724 => Some(EV_KEY::BTN_TRIGGER_HAPPY21), 725 => Some(EV_KEY::BTN_TRIGGER_HAPPY22), 726 => Some(EV_KEY::BTN_TRIGGER_HAPPY23), 727 => Some(EV_KEY::BTN_TRIGGER_HAPPY24), 728 => Some(EV_KEY::BTN_TRIGGER_HAPPY25), 729 => Some(EV_KEY::BTN_TRIGGER_HAPPY26), 730 => Some(EV_KEY::BTN_TRIGGER_HAPPY27), 731 => Some(EV_KEY::BTN_TRIGGER_HAPPY28), 732 => Some(EV_KEY::BTN_TRIGGER_HAPPY29), 733 => Some(EV_KEY::BTN_TRIGGER_HAPPY30), 734 => Some(EV_KEY::BTN_TRIGGER_HAPPY31), 735 => Some(EV_KEY::BTN_TRIGGER_HAPPY32), 736 => Some(EV_KEY::BTN_TRIGGER_HAPPY33), 737 => Some(EV_KEY::BTN_TRIGGER_HAPPY34), 738 => Some(EV_KEY::BTN_TRIGGER_HAPPY35), 739 => Some(EV_KEY::BTN_TRIGGER_HAPPY36), 740 => Some(EV_KEY::BTN_TRIGGER_HAPPY37), 741 => Some(EV_KEY::BTN_TRIGGER_HAPPY38), 742 => Some(EV_KEY::BTN_TRIGGER_HAPPY39), 743 => Some(EV_KEY::BTN_TRIGGER_HAPPY40), _ => None, } } impl std::str::FromStr for EV_KEY { type Err = (); fn from_str(s: &str) -> Result { match s { "KEY_RESERVED" => Ok(EV_KEY::KEY_RESERVED), "KEY_ESC" => Ok(EV_KEY::KEY_ESC), "KEY_1" => Ok(EV_KEY::KEY_1), "KEY_2" => Ok(EV_KEY::KEY_2), "KEY_3" => Ok(EV_KEY::KEY_3), "KEY_4" => Ok(EV_KEY::KEY_4), "KEY_5" => Ok(EV_KEY::KEY_5), "KEY_6" => Ok(EV_KEY::KEY_6), "KEY_7" => Ok(EV_KEY::KEY_7), "KEY_8" => Ok(EV_KEY::KEY_8), "KEY_9" => Ok(EV_KEY::KEY_9), "KEY_0" => Ok(EV_KEY::KEY_0), "KEY_MINUS" => Ok(EV_KEY::KEY_MINUS), "KEY_EQUAL" => Ok(EV_KEY::KEY_EQUAL), "KEY_BACKSPACE" => Ok(EV_KEY::KEY_BACKSPACE), "KEY_TAB" => Ok(EV_KEY::KEY_TAB), "KEY_Q" => Ok(EV_KEY::KEY_Q), "KEY_W" => Ok(EV_KEY::KEY_W), "KEY_E" => Ok(EV_KEY::KEY_E), "KEY_R" => Ok(EV_KEY::KEY_R), "KEY_T" => Ok(EV_KEY::KEY_T), "KEY_Y" => Ok(EV_KEY::KEY_Y), "KEY_U" => Ok(EV_KEY::KEY_U), "KEY_I" => Ok(EV_KEY::KEY_I), "KEY_O" => Ok(EV_KEY::KEY_O), "KEY_P" => Ok(EV_KEY::KEY_P), "KEY_LEFTBRACE" => Ok(EV_KEY::KEY_LEFTBRACE), "KEY_RIGHTBRACE" => Ok(EV_KEY::KEY_RIGHTBRACE), "KEY_ENTER" => Ok(EV_KEY::KEY_ENTER), "KEY_LEFTCTRL" => Ok(EV_KEY::KEY_LEFTCTRL), "KEY_A" => Ok(EV_KEY::KEY_A), "KEY_S" => Ok(EV_KEY::KEY_S), "KEY_D" => Ok(EV_KEY::KEY_D), "KEY_F" => Ok(EV_KEY::KEY_F), "KEY_G" => Ok(EV_KEY::KEY_G), "KEY_H" => Ok(EV_KEY::KEY_H), "KEY_J" => Ok(EV_KEY::KEY_J), "KEY_K" => Ok(EV_KEY::KEY_K), "KEY_L" => Ok(EV_KEY::KEY_L), "KEY_SEMICOLON" => Ok(EV_KEY::KEY_SEMICOLON), "KEY_APOSTROPHE" => Ok(EV_KEY::KEY_APOSTROPHE), "KEY_GRAVE" => Ok(EV_KEY::KEY_GRAVE), "KEY_LEFTSHIFT" => Ok(EV_KEY::KEY_LEFTSHIFT), "KEY_BACKSLASH" => Ok(EV_KEY::KEY_BACKSLASH), "KEY_Z" => Ok(EV_KEY::KEY_Z), "KEY_X" => Ok(EV_KEY::KEY_X), "KEY_C" => Ok(EV_KEY::KEY_C), "KEY_V" => Ok(EV_KEY::KEY_V), "KEY_B" => Ok(EV_KEY::KEY_B), "KEY_N" => Ok(EV_KEY::KEY_N), "KEY_M" => Ok(EV_KEY::KEY_M), "KEY_COMMA" => Ok(EV_KEY::KEY_COMMA), "KEY_DOT" => Ok(EV_KEY::KEY_DOT), "KEY_SLASH" => Ok(EV_KEY::KEY_SLASH), "KEY_RIGHTSHIFT" => Ok(EV_KEY::KEY_RIGHTSHIFT), "KEY_KPASTERISK" => Ok(EV_KEY::KEY_KPASTERISK), "KEY_LEFTALT" => Ok(EV_KEY::KEY_LEFTALT), "KEY_SPACE" => Ok(EV_KEY::KEY_SPACE), "KEY_CAPSLOCK" => Ok(EV_KEY::KEY_CAPSLOCK), "KEY_F1" => Ok(EV_KEY::KEY_F1), "KEY_F2" => Ok(EV_KEY::KEY_F2), "KEY_F3" => Ok(EV_KEY::KEY_F3), "KEY_F4" => Ok(EV_KEY::KEY_F4), "KEY_F5" => Ok(EV_KEY::KEY_F5), "KEY_F6" => Ok(EV_KEY::KEY_F6), "KEY_F7" => Ok(EV_KEY::KEY_F7), "KEY_F8" => Ok(EV_KEY::KEY_F8), "KEY_F9" => Ok(EV_KEY::KEY_F9), "KEY_F10" => Ok(EV_KEY::KEY_F10), "KEY_NUMLOCK" => Ok(EV_KEY::KEY_NUMLOCK), "KEY_SCROLLLOCK" => Ok(EV_KEY::KEY_SCROLLLOCK), "KEY_KP7" => Ok(EV_KEY::KEY_KP7), "KEY_KP8" => Ok(EV_KEY::KEY_KP8), "KEY_KP9" => Ok(EV_KEY::KEY_KP9), "KEY_KPMINUS" => Ok(EV_KEY::KEY_KPMINUS), "KEY_KP4" => Ok(EV_KEY::KEY_KP4), "KEY_KP5" => Ok(EV_KEY::KEY_KP5), "KEY_KP6" => Ok(EV_KEY::KEY_KP6), "KEY_KPPLUS" => Ok(EV_KEY::KEY_KPPLUS), "KEY_KP1" => Ok(EV_KEY::KEY_KP1), "KEY_KP2" => Ok(EV_KEY::KEY_KP2), "KEY_KP3" => Ok(EV_KEY::KEY_KP3), "KEY_KP0" => Ok(EV_KEY::KEY_KP0), "KEY_KPDOT" => Ok(EV_KEY::KEY_KPDOT), "KEY_ZENKAKUHANKAKU" => Ok(EV_KEY::KEY_ZENKAKUHANKAKU), "KEY_102ND" => Ok(EV_KEY::KEY_102ND), "KEY_F11" => Ok(EV_KEY::KEY_F11), "KEY_F12" => Ok(EV_KEY::KEY_F12), "KEY_RO" => Ok(EV_KEY::KEY_RO), "KEY_KATAKANA" => Ok(EV_KEY::KEY_KATAKANA), "KEY_HIRAGANA" => Ok(EV_KEY::KEY_HIRAGANA), "KEY_HENKAN" => Ok(EV_KEY::KEY_HENKAN), "KEY_KATAKANAHIRAGANA" => Ok(EV_KEY::KEY_KATAKANAHIRAGANA), "KEY_MUHENKAN" => Ok(EV_KEY::KEY_MUHENKAN), "KEY_KPJPCOMMA" => Ok(EV_KEY::KEY_KPJPCOMMA), "KEY_KPENTER" => Ok(EV_KEY::KEY_KPENTER), "KEY_RIGHTCTRL" => Ok(EV_KEY::KEY_RIGHTCTRL), "KEY_KPSLASH" => Ok(EV_KEY::KEY_KPSLASH), "KEY_SYSRQ" => Ok(EV_KEY::KEY_SYSRQ), "KEY_RIGHTALT" => Ok(EV_KEY::KEY_RIGHTALT), "KEY_LINEFEED" => Ok(EV_KEY::KEY_LINEFEED), "KEY_HOME" => Ok(EV_KEY::KEY_HOME), "KEY_UP" => Ok(EV_KEY::KEY_UP), "KEY_PAGEUP" => Ok(EV_KEY::KEY_PAGEUP), "KEY_LEFT" => Ok(EV_KEY::KEY_LEFT), "KEY_RIGHT" => Ok(EV_KEY::KEY_RIGHT), "KEY_END" => Ok(EV_KEY::KEY_END), "KEY_DOWN" => Ok(EV_KEY::KEY_DOWN), "KEY_PAGEDOWN" => Ok(EV_KEY::KEY_PAGEDOWN), "KEY_INSERT" => Ok(EV_KEY::KEY_INSERT), "KEY_DELETE" => Ok(EV_KEY::KEY_DELETE), "KEY_MACRO" => Ok(EV_KEY::KEY_MACRO), "KEY_MUTE" => Ok(EV_KEY::KEY_MUTE), "KEY_VOLUMEDOWN" => Ok(EV_KEY::KEY_VOLUMEDOWN), "KEY_VOLUMEUP" => Ok(EV_KEY::KEY_VOLUMEUP), "KEY_POWER" => Ok(EV_KEY::KEY_POWER), "KEY_KPEQUAL" => Ok(EV_KEY::KEY_KPEQUAL), "KEY_KPPLUSMINUS" => Ok(EV_KEY::KEY_KPPLUSMINUS), "KEY_PAUSE" => Ok(EV_KEY::KEY_PAUSE), "KEY_SCALE" => Ok(EV_KEY::KEY_SCALE), "KEY_KPCOMMA" => Ok(EV_KEY::KEY_KPCOMMA), "KEY_HANGEUL" => Ok(EV_KEY::KEY_HANGEUL), "KEY_HANJA" => Ok(EV_KEY::KEY_HANJA), "KEY_YEN" => Ok(EV_KEY::KEY_YEN), "KEY_LEFTMETA" => Ok(EV_KEY::KEY_LEFTMETA), "KEY_RIGHTMETA" => Ok(EV_KEY::KEY_RIGHTMETA), "KEY_COMPOSE" => Ok(EV_KEY::KEY_COMPOSE), "KEY_STOP" => Ok(EV_KEY::KEY_STOP), "KEY_AGAIN" => Ok(EV_KEY::KEY_AGAIN), "KEY_PROPS" => Ok(EV_KEY::KEY_PROPS), "KEY_UNDO" => Ok(EV_KEY::KEY_UNDO), "KEY_FRONT" => Ok(EV_KEY::KEY_FRONT), "KEY_COPY" => Ok(EV_KEY::KEY_COPY), "KEY_OPEN" => Ok(EV_KEY::KEY_OPEN), "KEY_PASTE" => Ok(EV_KEY::KEY_PASTE), "KEY_FIND" => Ok(EV_KEY::KEY_FIND), "KEY_CUT" => Ok(EV_KEY::KEY_CUT), "KEY_HELP" => Ok(EV_KEY::KEY_HELP), "KEY_MENU" => Ok(EV_KEY::KEY_MENU), "KEY_CALC" => Ok(EV_KEY::KEY_CALC), "KEY_SETUP" => Ok(EV_KEY::KEY_SETUP), "KEY_SLEEP" => Ok(EV_KEY::KEY_SLEEP), "KEY_WAKEUP" => Ok(EV_KEY::KEY_WAKEUP), "KEY_FILE" => Ok(EV_KEY::KEY_FILE), "KEY_SENDFILE" => Ok(EV_KEY::KEY_SENDFILE), "KEY_DELETEFILE" => Ok(EV_KEY::KEY_DELETEFILE), "KEY_XFER" => Ok(EV_KEY::KEY_XFER), "KEY_PROG1" => Ok(EV_KEY::KEY_PROG1), "KEY_PROG2" => Ok(EV_KEY::KEY_PROG2), "KEY_WWW" => Ok(EV_KEY::KEY_WWW), "KEY_MSDOS" => Ok(EV_KEY::KEY_MSDOS), "KEY_COFFEE" => Ok(EV_KEY::KEY_COFFEE), "KEY_ROTATE_DISPLAY" => Ok(EV_KEY::KEY_ROTATE_DISPLAY), "KEY_CYCLEWINDOWS" => Ok(EV_KEY::KEY_CYCLEWINDOWS), "KEY_MAIL" => Ok(EV_KEY::KEY_MAIL), "KEY_BOOKMARKS" => Ok(EV_KEY::KEY_BOOKMARKS), "KEY_COMPUTER" => Ok(EV_KEY::KEY_COMPUTER), "KEY_BACK" => Ok(EV_KEY::KEY_BACK), "KEY_FORWARD" => Ok(EV_KEY::KEY_FORWARD), "KEY_CLOSECD" => Ok(EV_KEY::KEY_CLOSECD), "KEY_EJECTCD" => Ok(EV_KEY::KEY_EJECTCD), "KEY_EJECTCLOSECD" => Ok(EV_KEY::KEY_EJECTCLOSECD), "KEY_NEXTSONG" => Ok(EV_KEY::KEY_NEXTSONG), "KEY_PLAYPAUSE" => Ok(EV_KEY::KEY_PLAYPAUSE), "KEY_PREVIOUSSONG" => Ok(EV_KEY::KEY_PREVIOUSSONG), "KEY_STOPCD" => Ok(EV_KEY::KEY_STOPCD), "KEY_RECORD" => Ok(EV_KEY::KEY_RECORD), "KEY_REWIND" => Ok(EV_KEY::KEY_REWIND), "KEY_PHONE" => Ok(EV_KEY::KEY_PHONE), "KEY_ISO" => Ok(EV_KEY::KEY_ISO), "KEY_CONFIG" => Ok(EV_KEY::KEY_CONFIG), "KEY_HOMEPAGE" => Ok(EV_KEY::KEY_HOMEPAGE), "KEY_REFRESH" => Ok(EV_KEY::KEY_REFRESH), "KEY_EXIT" => Ok(EV_KEY::KEY_EXIT), "KEY_MOVE" => Ok(EV_KEY::KEY_MOVE), "KEY_EDIT" => Ok(EV_KEY::KEY_EDIT), "KEY_SCROLLUP" => Ok(EV_KEY::KEY_SCROLLUP), "KEY_SCROLLDOWN" => Ok(EV_KEY::KEY_SCROLLDOWN), "KEY_KPLEFTPAREN" => Ok(EV_KEY::KEY_KPLEFTPAREN), "KEY_KPRIGHTPAREN" => Ok(EV_KEY::KEY_KPRIGHTPAREN), "KEY_NEW" => Ok(EV_KEY::KEY_NEW), "KEY_REDO" => Ok(EV_KEY::KEY_REDO), "KEY_F13" => Ok(EV_KEY::KEY_F13), "KEY_F14" => Ok(EV_KEY::KEY_F14), "KEY_F15" => Ok(EV_KEY::KEY_F15), "KEY_F16" => Ok(EV_KEY::KEY_F16), "KEY_F17" => Ok(EV_KEY::KEY_F17), "KEY_F18" => Ok(EV_KEY::KEY_F18), "KEY_F19" => Ok(EV_KEY::KEY_F19), "KEY_F20" => Ok(EV_KEY::KEY_F20), "KEY_F21" => Ok(EV_KEY::KEY_F21), "KEY_F22" => Ok(EV_KEY::KEY_F22), "KEY_F23" => Ok(EV_KEY::KEY_F23), "KEY_F24" => Ok(EV_KEY::KEY_F24), "KEY_PLAYCD" => Ok(EV_KEY::KEY_PLAYCD), "KEY_PAUSECD" => Ok(EV_KEY::KEY_PAUSECD), "KEY_PROG3" => Ok(EV_KEY::KEY_PROG3), "KEY_PROG4" => Ok(EV_KEY::KEY_PROG4), "KEY_ALL_APPLICATIONS" => Ok(EV_KEY::KEY_ALL_APPLICATIONS), "KEY_SUSPEND" => Ok(EV_KEY::KEY_SUSPEND), "KEY_CLOSE" => Ok(EV_KEY::KEY_CLOSE), "KEY_PLAY" => Ok(EV_KEY::KEY_PLAY), "KEY_FASTFORWARD" => Ok(EV_KEY::KEY_FASTFORWARD), "KEY_BASSBOOST" => Ok(EV_KEY::KEY_BASSBOOST), "KEY_PRINT" => Ok(EV_KEY::KEY_PRINT), "KEY_HP" => Ok(EV_KEY::KEY_HP), "KEY_CAMERA" => Ok(EV_KEY::KEY_CAMERA), "KEY_SOUND" => Ok(EV_KEY::KEY_SOUND), "KEY_QUESTION" => Ok(EV_KEY::KEY_QUESTION), "KEY_EMAIL" => Ok(EV_KEY::KEY_EMAIL), "KEY_CHAT" => Ok(EV_KEY::KEY_CHAT), "KEY_SEARCH" => Ok(EV_KEY::KEY_SEARCH), "KEY_CONNECT" => Ok(EV_KEY::KEY_CONNECT), "KEY_FINANCE" => Ok(EV_KEY::KEY_FINANCE), "KEY_SPORT" => Ok(EV_KEY::KEY_SPORT), "KEY_SHOP" => Ok(EV_KEY::KEY_SHOP), "KEY_ALTERASE" => Ok(EV_KEY::KEY_ALTERASE), "KEY_CANCEL" => Ok(EV_KEY::KEY_CANCEL), "KEY_BRIGHTNESSDOWN" => Ok(EV_KEY::KEY_BRIGHTNESSDOWN), "KEY_BRIGHTNESSUP" => Ok(EV_KEY::KEY_BRIGHTNESSUP), "KEY_MEDIA" => Ok(EV_KEY::KEY_MEDIA), "KEY_SWITCHVIDEOMODE" => Ok(EV_KEY::KEY_SWITCHVIDEOMODE), "KEY_KBDILLUMTOGGLE" => Ok(EV_KEY::KEY_KBDILLUMTOGGLE), "KEY_KBDILLUMDOWN" => Ok(EV_KEY::KEY_KBDILLUMDOWN), "KEY_KBDILLUMUP" => Ok(EV_KEY::KEY_KBDILLUMUP), "KEY_SEND" => Ok(EV_KEY::KEY_SEND), "KEY_REPLY" => Ok(EV_KEY::KEY_REPLY), "KEY_FORWARDMAIL" => Ok(EV_KEY::KEY_FORWARDMAIL), "KEY_SAVE" => Ok(EV_KEY::KEY_SAVE), "KEY_DOCUMENTS" => Ok(EV_KEY::KEY_DOCUMENTS), "KEY_BATTERY" => Ok(EV_KEY::KEY_BATTERY), "KEY_BLUETOOTH" => Ok(EV_KEY::KEY_BLUETOOTH), "KEY_WLAN" => Ok(EV_KEY::KEY_WLAN), "KEY_UWB" => Ok(EV_KEY::KEY_UWB), "KEY_UNKNOWN" => Ok(EV_KEY::KEY_UNKNOWN), "KEY_VIDEO_NEXT" => Ok(EV_KEY::KEY_VIDEO_NEXT), "KEY_VIDEO_PREV" => Ok(EV_KEY::KEY_VIDEO_PREV), "KEY_BRIGHTNESS_CYCLE" => Ok(EV_KEY::KEY_BRIGHTNESS_CYCLE), "KEY_BRIGHTNESS_AUTO" => Ok(EV_KEY::KEY_BRIGHTNESS_AUTO), "KEY_DISPLAY_OFF" => Ok(EV_KEY::KEY_DISPLAY_OFF), "KEY_WWAN" => Ok(EV_KEY::KEY_WWAN), "KEY_RFKILL" => Ok(EV_KEY::KEY_RFKILL), "KEY_MICMUTE" => Ok(EV_KEY::KEY_MICMUTE), "KEY_OK" => Ok(EV_KEY::KEY_OK), "KEY_SELECT" => Ok(EV_KEY::KEY_SELECT), "KEY_GOTO" => Ok(EV_KEY::KEY_GOTO), "KEY_CLEAR" => Ok(EV_KEY::KEY_CLEAR), "KEY_POWER2" => Ok(EV_KEY::KEY_POWER2), "KEY_OPTION" => Ok(EV_KEY::KEY_OPTION), "KEY_INFO" => Ok(EV_KEY::KEY_INFO), "KEY_TIME" => Ok(EV_KEY::KEY_TIME), "KEY_VENDOR" => Ok(EV_KEY::KEY_VENDOR), "KEY_ARCHIVE" => Ok(EV_KEY::KEY_ARCHIVE), "KEY_PROGRAM" => Ok(EV_KEY::KEY_PROGRAM), "KEY_CHANNEL" => Ok(EV_KEY::KEY_CHANNEL), "KEY_FAVORITES" => Ok(EV_KEY::KEY_FAVORITES), "KEY_EPG" => Ok(EV_KEY::KEY_EPG), "KEY_PVR" => Ok(EV_KEY::KEY_PVR), "KEY_MHP" => Ok(EV_KEY::KEY_MHP), "KEY_LANGUAGE" => Ok(EV_KEY::KEY_LANGUAGE), "KEY_TITLE" => Ok(EV_KEY::KEY_TITLE), "KEY_SUBTITLE" => Ok(EV_KEY::KEY_SUBTITLE), "KEY_ANGLE" => Ok(EV_KEY::KEY_ANGLE), "KEY_FULL_SCREEN" => Ok(EV_KEY::KEY_FULL_SCREEN), "KEY_MODE" => Ok(EV_KEY::KEY_MODE), "KEY_KEYBOARD" => Ok(EV_KEY::KEY_KEYBOARD), "KEY_ASPECT_RATIO" => Ok(EV_KEY::KEY_ASPECT_RATIO), "KEY_PC" => Ok(EV_KEY::KEY_PC), "KEY_TV" => Ok(EV_KEY::KEY_TV), "KEY_TV2" => Ok(EV_KEY::KEY_TV2), "KEY_VCR" => Ok(EV_KEY::KEY_VCR), "KEY_VCR2" => Ok(EV_KEY::KEY_VCR2), "KEY_SAT" => Ok(EV_KEY::KEY_SAT), "KEY_SAT2" => Ok(EV_KEY::KEY_SAT2), "KEY_CD" => Ok(EV_KEY::KEY_CD), "KEY_TAPE" => Ok(EV_KEY::KEY_TAPE), "KEY_RADIO" => Ok(EV_KEY::KEY_RADIO), "KEY_TUNER" => Ok(EV_KEY::KEY_TUNER), "KEY_PLAYER" => Ok(EV_KEY::KEY_PLAYER), "KEY_TEXT" => Ok(EV_KEY::KEY_TEXT), "KEY_DVD" => Ok(EV_KEY::KEY_DVD), "KEY_AUX" => Ok(EV_KEY::KEY_AUX), "KEY_MP3" => Ok(EV_KEY::KEY_MP3), "KEY_AUDIO" => Ok(EV_KEY::KEY_AUDIO), "KEY_VIDEO" => Ok(EV_KEY::KEY_VIDEO), "KEY_DIRECTORY" => Ok(EV_KEY::KEY_DIRECTORY), "KEY_LIST" => Ok(EV_KEY::KEY_LIST), "KEY_MEMO" => Ok(EV_KEY::KEY_MEMO), "KEY_CALENDAR" => Ok(EV_KEY::KEY_CALENDAR), "KEY_RED" => Ok(EV_KEY::KEY_RED), "KEY_GREEN" => Ok(EV_KEY::KEY_GREEN), "KEY_YELLOW" => Ok(EV_KEY::KEY_YELLOW), "KEY_BLUE" => Ok(EV_KEY::KEY_BLUE), "KEY_CHANNELUP" => Ok(EV_KEY::KEY_CHANNELUP), "KEY_CHANNELDOWN" => Ok(EV_KEY::KEY_CHANNELDOWN), "KEY_FIRST" => Ok(EV_KEY::KEY_FIRST), "KEY_LAST" => Ok(EV_KEY::KEY_LAST), "KEY_AB" => Ok(EV_KEY::KEY_AB), "KEY_NEXT" => Ok(EV_KEY::KEY_NEXT), "KEY_RESTART" => Ok(EV_KEY::KEY_RESTART), "KEY_SLOW" => Ok(EV_KEY::KEY_SLOW), "KEY_SHUFFLE" => Ok(EV_KEY::KEY_SHUFFLE), "KEY_BREAK" => Ok(EV_KEY::KEY_BREAK), "KEY_PREVIOUS" => Ok(EV_KEY::KEY_PREVIOUS), "KEY_DIGITS" => Ok(EV_KEY::KEY_DIGITS), "KEY_TEEN" => Ok(EV_KEY::KEY_TEEN), "KEY_TWEN" => Ok(EV_KEY::KEY_TWEN), "KEY_VIDEOPHONE" => Ok(EV_KEY::KEY_VIDEOPHONE), "KEY_GAMES" => Ok(EV_KEY::KEY_GAMES), "KEY_ZOOMIN" => Ok(EV_KEY::KEY_ZOOMIN), "KEY_ZOOMOUT" => Ok(EV_KEY::KEY_ZOOMOUT), "KEY_ZOOMRESET" => Ok(EV_KEY::KEY_ZOOMRESET), "KEY_WORDPROCESSOR" => Ok(EV_KEY::KEY_WORDPROCESSOR), "KEY_EDITOR" => Ok(EV_KEY::KEY_EDITOR), "KEY_SPREADSHEET" => Ok(EV_KEY::KEY_SPREADSHEET), "KEY_GRAPHICSEDITOR" => Ok(EV_KEY::KEY_GRAPHICSEDITOR), "KEY_PRESENTATION" => Ok(EV_KEY::KEY_PRESENTATION), "KEY_DATABASE" => Ok(EV_KEY::KEY_DATABASE), "KEY_NEWS" => Ok(EV_KEY::KEY_NEWS), "KEY_VOICEMAIL" => Ok(EV_KEY::KEY_VOICEMAIL), "KEY_ADDRESSBOOK" => Ok(EV_KEY::KEY_ADDRESSBOOK), "KEY_MESSENGER" => Ok(EV_KEY::KEY_MESSENGER), "KEY_DISPLAYTOGGLE" => Ok(EV_KEY::KEY_DISPLAYTOGGLE), "KEY_SPELLCHECK" => Ok(EV_KEY::KEY_SPELLCHECK), "KEY_LOGOFF" => Ok(EV_KEY::KEY_LOGOFF), "KEY_DOLLAR" => Ok(EV_KEY::KEY_DOLLAR), "KEY_EURO" => Ok(EV_KEY::KEY_EURO), "KEY_FRAMEBACK" => Ok(EV_KEY::KEY_FRAMEBACK), "KEY_FRAMEFORWARD" => Ok(EV_KEY::KEY_FRAMEFORWARD), "KEY_CONTEXT_MENU" => Ok(EV_KEY::KEY_CONTEXT_MENU), "KEY_MEDIA_REPEAT" => Ok(EV_KEY::KEY_MEDIA_REPEAT), "KEY_10CHANNELSUP" => Ok(EV_KEY::KEY_10CHANNELSUP), "KEY_10CHANNELSDOWN" => Ok(EV_KEY::KEY_10CHANNELSDOWN), "KEY_IMAGES" => Ok(EV_KEY::KEY_IMAGES), "KEY_NOTIFICATION_CENTER" => Ok(EV_KEY::KEY_NOTIFICATION_CENTER), "KEY_PICKUP_PHONE" => Ok(EV_KEY::KEY_PICKUP_PHONE), "KEY_HANGUP_PHONE" => Ok(EV_KEY::KEY_HANGUP_PHONE), "KEY_DEL_EOL" => Ok(EV_KEY::KEY_DEL_EOL), "KEY_DEL_EOS" => Ok(EV_KEY::KEY_DEL_EOS), "KEY_INS_LINE" => Ok(EV_KEY::KEY_INS_LINE), "KEY_DEL_LINE" => Ok(EV_KEY::KEY_DEL_LINE), "KEY_FN" => Ok(EV_KEY::KEY_FN), "KEY_FN_ESC" => Ok(EV_KEY::KEY_FN_ESC), "KEY_FN_F1" => Ok(EV_KEY::KEY_FN_F1), "KEY_FN_F2" => Ok(EV_KEY::KEY_FN_F2), "KEY_FN_F3" => Ok(EV_KEY::KEY_FN_F3), "KEY_FN_F4" => Ok(EV_KEY::KEY_FN_F4), "KEY_FN_F5" => Ok(EV_KEY::KEY_FN_F5), "KEY_FN_F6" => Ok(EV_KEY::KEY_FN_F6), "KEY_FN_F7" => Ok(EV_KEY::KEY_FN_F7), "KEY_FN_F8" => Ok(EV_KEY::KEY_FN_F8), "KEY_FN_F9" => Ok(EV_KEY::KEY_FN_F9), "KEY_FN_F10" => Ok(EV_KEY::KEY_FN_F10), "KEY_FN_F11" => Ok(EV_KEY::KEY_FN_F11), "KEY_FN_F12" => Ok(EV_KEY::KEY_FN_F12), "KEY_FN_1" => Ok(EV_KEY::KEY_FN_1), "KEY_FN_2" => Ok(EV_KEY::KEY_FN_2), "KEY_FN_D" => Ok(EV_KEY::KEY_FN_D), "KEY_FN_E" => Ok(EV_KEY::KEY_FN_E), "KEY_FN_F" => Ok(EV_KEY::KEY_FN_F), "KEY_FN_S" => Ok(EV_KEY::KEY_FN_S), "KEY_FN_B" => Ok(EV_KEY::KEY_FN_B), "KEY_FN_RIGHT_SHIFT" => Ok(EV_KEY::KEY_FN_RIGHT_SHIFT), "KEY_BRL_DOT1" => Ok(EV_KEY::KEY_BRL_DOT1), "KEY_BRL_DOT2" => Ok(EV_KEY::KEY_BRL_DOT2), "KEY_BRL_DOT3" => Ok(EV_KEY::KEY_BRL_DOT3), "KEY_BRL_DOT4" => Ok(EV_KEY::KEY_BRL_DOT4), "KEY_BRL_DOT5" => Ok(EV_KEY::KEY_BRL_DOT5), "KEY_BRL_DOT6" => Ok(EV_KEY::KEY_BRL_DOT6), "KEY_BRL_DOT7" => Ok(EV_KEY::KEY_BRL_DOT7), "KEY_BRL_DOT8" => Ok(EV_KEY::KEY_BRL_DOT8), "KEY_BRL_DOT9" => Ok(EV_KEY::KEY_BRL_DOT9), "KEY_BRL_DOT10" => Ok(EV_KEY::KEY_BRL_DOT10), "KEY_NUMERIC_0" => Ok(EV_KEY::KEY_NUMERIC_0), "KEY_NUMERIC_1" => Ok(EV_KEY::KEY_NUMERIC_1), "KEY_NUMERIC_2" => Ok(EV_KEY::KEY_NUMERIC_2), "KEY_NUMERIC_3" => Ok(EV_KEY::KEY_NUMERIC_3), "KEY_NUMERIC_4" => Ok(EV_KEY::KEY_NUMERIC_4), "KEY_NUMERIC_5" => Ok(EV_KEY::KEY_NUMERIC_5), "KEY_NUMERIC_6" => Ok(EV_KEY::KEY_NUMERIC_6), "KEY_NUMERIC_7" => Ok(EV_KEY::KEY_NUMERIC_7), "KEY_NUMERIC_8" => Ok(EV_KEY::KEY_NUMERIC_8), "KEY_NUMERIC_9" => Ok(EV_KEY::KEY_NUMERIC_9), "KEY_NUMERIC_STAR" => Ok(EV_KEY::KEY_NUMERIC_STAR), "KEY_NUMERIC_POUND" => Ok(EV_KEY::KEY_NUMERIC_POUND), "KEY_NUMERIC_A" => Ok(EV_KEY::KEY_NUMERIC_A), "KEY_NUMERIC_B" => Ok(EV_KEY::KEY_NUMERIC_B), "KEY_NUMERIC_C" => Ok(EV_KEY::KEY_NUMERIC_C), "KEY_NUMERIC_D" => Ok(EV_KEY::KEY_NUMERIC_D), "KEY_CAMERA_FOCUS" => Ok(EV_KEY::KEY_CAMERA_FOCUS), "KEY_WPS_BUTTON" => Ok(EV_KEY::KEY_WPS_BUTTON), "KEY_TOUCHPAD_TOGGLE" => Ok(EV_KEY::KEY_TOUCHPAD_TOGGLE), "KEY_TOUCHPAD_ON" => Ok(EV_KEY::KEY_TOUCHPAD_ON), "KEY_TOUCHPAD_OFF" => Ok(EV_KEY::KEY_TOUCHPAD_OFF), "KEY_CAMERA_ZOOMIN" => Ok(EV_KEY::KEY_CAMERA_ZOOMIN), "KEY_CAMERA_ZOOMOUT" => Ok(EV_KEY::KEY_CAMERA_ZOOMOUT), "KEY_CAMERA_UP" => Ok(EV_KEY::KEY_CAMERA_UP), "KEY_CAMERA_DOWN" => Ok(EV_KEY::KEY_CAMERA_DOWN), "KEY_CAMERA_LEFT" => Ok(EV_KEY::KEY_CAMERA_LEFT), "KEY_CAMERA_RIGHT" => Ok(EV_KEY::KEY_CAMERA_RIGHT), "KEY_ATTENDANT_ON" => Ok(EV_KEY::KEY_ATTENDANT_ON), "KEY_ATTENDANT_OFF" => Ok(EV_KEY::KEY_ATTENDANT_OFF), "KEY_ATTENDANT_TOGGLE" => Ok(EV_KEY::KEY_ATTENDANT_TOGGLE), "KEY_LIGHTS_TOGGLE" => Ok(EV_KEY::KEY_LIGHTS_TOGGLE), "KEY_ALS_TOGGLE" => Ok(EV_KEY::KEY_ALS_TOGGLE), "KEY_ROTATE_LOCK_TOGGLE" => Ok(EV_KEY::KEY_ROTATE_LOCK_TOGGLE), "KEY_BUTTONCONFIG" => Ok(EV_KEY::KEY_BUTTONCONFIG), "KEY_TASKMANAGER" => Ok(EV_KEY::KEY_TASKMANAGER), "KEY_JOURNAL" => Ok(EV_KEY::KEY_JOURNAL), "KEY_CONTROLPANEL" => Ok(EV_KEY::KEY_CONTROLPANEL), "KEY_APPSELECT" => Ok(EV_KEY::KEY_APPSELECT), "KEY_SCREENSAVER" => Ok(EV_KEY::KEY_SCREENSAVER), "KEY_VOICECOMMAND" => Ok(EV_KEY::KEY_VOICECOMMAND), "KEY_ASSISTANT" => Ok(EV_KEY::KEY_ASSISTANT), "KEY_KBD_LAYOUT_NEXT" => Ok(EV_KEY::KEY_KBD_LAYOUT_NEXT), "KEY_EMOJI_PICKER" => Ok(EV_KEY::KEY_EMOJI_PICKER), "KEY_DICTATE" => Ok(EV_KEY::KEY_DICTATE), "KEY_BRIGHTNESS_MIN" => Ok(EV_KEY::KEY_BRIGHTNESS_MIN), "KEY_BRIGHTNESS_MAX" => Ok(EV_KEY::KEY_BRIGHTNESS_MAX), "KEY_KBDINPUTASSIST_PREV" => Ok(EV_KEY::KEY_KBDINPUTASSIST_PREV), "KEY_KBDINPUTASSIST_NEXT" => Ok(EV_KEY::KEY_KBDINPUTASSIST_NEXT), "KEY_KBDINPUTASSIST_PREVGROUP" => Ok(EV_KEY::KEY_KBDINPUTASSIST_PREVGROUP), "KEY_KBDINPUTASSIST_NEXTGROUP" => Ok(EV_KEY::KEY_KBDINPUTASSIST_NEXTGROUP), "KEY_KBDINPUTASSIST_ACCEPT" => Ok(EV_KEY::KEY_KBDINPUTASSIST_ACCEPT), "KEY_KBDINPUTASSIST_CANCEL" => Ok(EV_KEY::KEY_KBDINPUTASSIST_CANCEL), "KEY_RIGHT_UP" => Ok(EV_KEY::KEY_RIGHT_UP), "KEY_RIGHT_DOWN" => Ok(EV_KEY::KEY_RIGHT_DOWN), "KEY_LEFT_UP" => Ok(EV_KEY::KEY_LEFT_UP), "KEY_LEFT_DOWN" => Ok(EV_KEY::KEY_LEFT_DOWN), "KEY_ROOT_MENU" => Ok(EV_KEY::KEY_ROOT_MENU), "KEY_MEDIA_TOP_MENU" => Ok(EV_KEY::KEY_MEDIA_TOP_MENU), "KEY_NUMERIC_11" => Ok(EV_KEY::KEY_NUMERIC_11), "KEY_NUMERIC_12" => Ok(EV_KEY::KEY_NUMERIC_12), "KEY_AUDIO_DESC" => Ok(EV_KEY::KEY_AUDIO_DESC), "KEY_3D_MODE" => Ok(EV_KEY::KEY_3D_MODE), "KEY_NEXT_FAVORITE" => Ok(EV_KEY::KEY_NEXT_FAVORITE), "KEY_STOP_RECORD" => Ok(EV_KEY::KEY_STOP_RECORD), "KEY_PAUSE_RECORD" => Ok(EV_KEY::KEY_PAUSE_RECORD), "KEY_VOD" => Ok(EV_KEY::KEY_VOD), "KEY_UNMUTE" => Ok(EV_KEY::KEY_UNMUTE), "KEY_FASTREVERSE" => Ok(EV_KEY::KEY_FASTREVERSE), "KEY_SLOWREVERSE" => Ok(EV_KEY::KEY_SLOWREVERSE), "KEY_DATA" => Ok(EV_KEY::KEY_DATA), "KEY_ONSCREEN_KEYBOARD" => Ok(EV_KEY::KEY_ONSCREEN_KEYBOARD), "KEY_PRIVACY_SCREEN_TOGGLE" => Ok(EV_KEY::KEY_PRIVACY_SCREEN_TOGGLE), "KEY_SELECTIVE_SCREENSHOT" => Ok(EV_KEY::KEY_SELECTIVE_SCREENSHOT), "KEY_MACRO1" => Ok(EV_KEY::KEY_MACRO1), "KEY_MACRO2" => Ok(EV_KEY::KEY_MACRO2), "KEY_MACRO3" => Ok(EV_KEY::KEY_MACRO3), "KEY_MACRO4" => Ok(EV_KEY::KEY_MACRO4), "KEY_MACRO5" => Ok(EV_KEY::KEY_MACRO5), "KEY_MACRO6" => Ok(EV_KEY::KEY_MACRO6), "KEY_MACRO7" => Ok(EV_KEY::KEY_MACRO7), "KEY_MACRO8" => Ok(EV_KEY::KEY_MACRO8), "KEY_MACRO9" => Ok(EV_KEY::KEY_MACRO9), "KEY_MACRO10" => Ok(EV_KEY::KEY_MACRO10), "KEY_MACRO11" => Ok(EV_KEY::KEY_MACRO11), "KEY_MACRO12" => Ok(EV_KEY::KEY_MACRO12), "KEY_MACRO13" => Ok(EV_KEY::KEY_MACRO13), "KEY_MACRO14" => Ok(EV_KEY::KEY_MACRO14), "KEY_MACRO15" => Ok(EV_KEY::KEY_MACRO15), "KEY_MACRO16" => Ok(EV_KEY::KEY_MACRO16), "KEY_MACRO17" => Ok(EV_KEY::KEY_MACRO17), "KEY_MACRO18" => Ok(EV_KEY::KEY_MACRO18), "KEY_MACRO19" => Ok(EV_KEY::KEY_MACRO19), "KEY_MACRO20" => Ok(EV_KEY::KEY_MACRO20), "KEY_MACRO21" => Ok(EV_KEY::KEY_MACRO21), "KEY_MACRO22" => Ok(EV_KEY::KEY_MACRO22), "KEY_MACRO23" => Ok(EV_KEY::KEY_MACRO23), "KEY_MACRO24" => Ok(EV_KEY::KEY_MACRO24), "KEY_MACRO25" => Ok(EV_KEY::KEY_MACRO25), "KEY_MACRO26" => Ok(EV_KEY::KEY_MACRO26), "KEY_MACRO27" => Ok(EV_KEY::KEY_MACRO27), "KEY_MACRO28" => Ok(EV_KEY::KEY_MACRO28), "KEY_MACRO29" => Ok(EV_KEY::KEY_MACRO29), "KEY_MACRO30" => Ok(EV_KEY::KEY_MACRO30), "KEY_MACRO_RECORD_START" => Ok(EV_KEY::KEY_MACRO_RECORD_START), "KEY_MACRO_RECORD_STOP" => Ok(EV_KEY::KEY_MACRO_RECORD_STOP), "KEY_MACRO_PRESET_CYCLE" => Ok(EV_KEY::KEY_MACRO_PRESET_CYCLE), "KEY_MACRO_PRESET1" => Ok(EV_KEY::KEY_MACRO_PRESET1), "KEY_MACRO_PRESET2" => Ok(EV_KEY::KEY_MACRO_PRESET2), "KEY_MACRO_PRESET3" => Ok(EV_KEY::KEY_MACRO_PRESET3), "KEY_KBD_LCD_MENU1" => Ok(EV_KEY::KEY_KBD_LCD_MENU1), "KEY_KBD_LCD_MENU2" => Ok(EV_KEY::KEY_KBD_LCD_MENU2), "KEY_KBD_LCD_MENU3" => Ok(EV_KEY::KEY_KBD_LCD_MENU3), "KEY_KBD_LCD_MENU4" => Ok(EV_KEY::KEY_KBD_LCD_MENU4), "KEY_KBD_LCD_MENU5" => Ok(EV_KEY::KEY_KBD_LCD_MENU5), "KEY_MAX" => Ok(EV_KEY::KEY_MAX), "BTN_0" => Ok(EV_KEY::BTN_0), "BTN_1" => Ok(EV_KEY::BTN_1), "BTN_2" => Ok(EV_KEY::BTN_2), "BTN_3" => Ok(EV_KEY::BTN_3), "BTN_4" => Ok(EV_KEY::BTN_4), "BTN_5" => Ok(EV_KEY::BTN_5), "BTN_6" => Ok(EV_KEY::BTN_6), "BTN_7" => Ok(EV_KEY::BTN_7), "BTN_8" => Ok(EV_KEY::BTN_8), "BTN_9" => Ok(EV_KEY::BTN_9), "BTN_LEFT" => Ok(EV_KEY::BTN_LEFT), "BTN_RIGHT" => Ok(EV_KEY::BTN_RIGHT), "BTN_MIDDLE" => Ok(EV_KEY::BTN_MIDDLE), "BTN_SIDE" => Ok(EV_KEY::BTN_SIDE), "BTN_EXTRA" => Ok(EV_KEY::BTN_EXTRA), "BTN_FORWARD" => Ok(EV_KEY::BTN_FORWARD), "BTN_BACK" => Ok(EV_KEY::BTN_BACK), "BTN_TASK" => Ok(EV_KEY::BTN_TASK), "BTN_TRIGGER" => Ok(EV_KEY::BTN_TRIGGER), "BTN_THUMB" => Ok(EV_KEY::BTN_THUMB), "BTN_THUMB2" => Ok(EV_KEY::BTN_THUMB2), "BTN_TOP" => Ok(EV_KEY::BTN_TOP), "BTN_TOP2" => Ok(EV_KEY::BTN_TOP2), "BTN_PINKIE" => Ok(EV_KEY::BTN_PINKIE), "BTN_BASE" => Ok(EV_KEY::BTN_BASE), "BTN_BASE2" => Ok(EV_KEY::BTN_BASE2), "BTN_BASE3" => Ok(EV_KEY::BTN_BASE3), "BTN_BASE4" => Ok(EV_KEY::BTN_BASE4), "BTN_BASE5" => Ok(EV_KEY::BTN_BASE5), "BTN_BASE6" => Ok(EV_KEY::BTN_BASE6), "BTN_DEAD" => Ok(EV_KEY::BTN_DEAD), "BTN_SOUTH" => Ok(EV_KEY::BTN_SOUTH), "BTN_EAST" => Ok(EV_KEY::BTN_EAST), "BTN_C" => Ok(EV_KEY::BTN_C), "BTN_NORTH" => Ok(EV_KEY::BTN_NORTH), "BTN_WEST" => Ok(EV_KEY::BTN_WEST), "BTN_Z" => Ok(EV_KEY::BTN_Z), "BTN_TL" => Ok(EV_KEY::BTN_TL), "BTN_TR" => Ok(EV_KEY::BTN_TR), "BTN_TL2" => Ok(EV_KEY::BTN_TL2), "BTN_TR2" => Ok(EV_KEY::BTN_TR2), "BTN_SELECT" => Ok(EV_KEY::BTN_SELECT), "BTN_START" => Ok(EV_KEY::BTN_START), "BTN_MODE" => Ok(EV_KEY::BTN_MODE), "BTN_THUMBL" => Ok(EV_KEY::BTN_THUMBL), "BTN_THUMBR" => Ok(EV_KEY::BTN_THUMBR), "BTN_TOOL_PEN" => Ok(EV_KEY::BTN_TOOL_PEN), "BTN_TOOL_RUBBER" => Ok(EV_KEY::BTN_TOOL_RUBBER), "BTN_TOOL_BRUSH" => Ok(EV_KEY::BTN_TOOL_BRUSH), "BTN_TOOL_PENCIL" => Ok(EV_KEY::BTN_TOOL_PENCIL), "BTN_TOOL_AIRBRUSH" => Ok(EV_KEY::BTN_TOOL_AIRBRUSH), "BTN_TOOL_FINGER" => Ok(EV_KEY::BTN_TOOL_FINGER), "BTN_TOOL_MOUSE" => Ok(EV_KEY::BTN_TOOL_MOUSE), "BTN_TOOL_LENS" => Ok(EV_KEY::BTN_TOOL_LENS), "BTN_TOOL_QUINTTAP" => Ok(EV_KEY::BTN_TOOL_QUINTTAP), "BTN_STYLUS3" => Ok(EV_KEY::BTN_STYLUS3), "BTN_TOUCH" => Ok(EV_KEY::BTN_TOUCH), "BTN_STYLUS" => Ok(EV_KEY::BTN_STYLUS), "BTN_STYLUS2" => Ok(EV_KEY::BTN_STYLUS2), "BTN_TOOL_DOUBLETAP" => Ok(EV_KEY::BTN_TOOL_DOUBLETAP), "BTN_TOOL_TRIPLETAP" => Ok(EV_KEY::BTN_TOOL_TRIPLETAP), "BTN_TOOL_QUADTAP" => Ok(EV_KEY::BTN_TOOL_QUADTAP), "BTN_GEAR_DOWN" => Ok(EV_KEY::BTN_GEAR_DOWN), "BTN_GEAR_UP" => Ok(EV_KEY::BTN_GEAR_UP), "BTN_DPAD_UP" => Ok(EV_KEY::BTN_DPAD_UP), "BTN_DPAD_DOWN" => Ok(EV_KEY::BTN_DPAD_DOWN), "BTN_DPAD_LEFT" => Ok(EV_KEY::BTN_DPAD_LEFT), "BTN_DPAD_RIGHT" => Ok(EV_KEY::BTN_DPAD_RIGHT), "BTN_TRIGGER_HAPPY1" => Ok(EV_KEY::BTN_TRIGGER_HAPPY1), "BTN_TRIGGER_HAPPY2" => Ok(EV_KEY::BTN_TRIGGER_HAPPY2), "BTN_TRIGGER_HAPPY3" => Ok(EV_KEY::BTN_TRIGGER_HAPPY3), "BTN_TRIGGER_HAPPY4" => Ok(EV_KEY::BTN_TRIGGER_HAPPY4), "BTN_TRIGGER_HAPPY5" => Ok(EV_KEY::BTN_TRIGGER_HAPPY5), "BTN_TRIGGER_HAPPY6" => Ok(EV_KEY::BTN_TRIGGER_HAPPY6), "BTN_TRIGGER_HAPPY7" => Ok(EV_KEY::BTN_TRIGGER_HAPPY7), "BTN_TRIGGER_HAPPY8" => Ok(EV_KEY::BTN_TRIGGER_HAPPY8), "BTN_TRIGGER_HAPPY9" => Ok(EV_KEY::BTN_TRIGGER_HAPPY9), "BTN_TRIGGER_HAPPY10" => Ok(EV_KEY::BTN_TRIGGER_HAPPY10), "BTN_TRIGGER_HAPPY11" => Ok(EV_KEY::BTN_TRIGGER_HAPPY11), "BTN_TRIGGER_HAPPY12" => Ok(EV_KEY::BTN_TRIGGER_HAPPY12), "BTN_TRIGGER_HAPPY13" => Ok(EV_KEY::BTN_TRIGGER_HAPPY13), "BTN_TRIGGER_HAPPY14" => Ok(EV_KEY::BTN_TRIGGER_HAPPY14), "BTN_TRIGGER_HAPPY15" => Ok(EV_KEY::BTN_TRIGGER_HAPPY15), "BTN_TRIGGER_HAPPY16" => Ok(EV_KEY::BTN_TRIGGER_HAPPY16), "BTN_TRIGGER_HAPPY17" => Ok(EV_KEY::BTN_TRIGGER_HAPPY17), "BTN_TRIGGER_HAPPY18" => Ok(EV_KEY::BTN_TRIGGER_HAPPY18), "BTN_TRIGGER_HAPPY19" => Ok(EV_KEY::BTN_TRIGGER_HAPPY19), "BTN_TRIGGER_HAPPY20" => Ok(EV_KEY::BTN_TRIGGER_HAPPY20), "BTN_TRIGGER_HAPPY21" => Ok(EV_KEY::BTN_TRIGGER_HAPPY21), "BTN_TRIGGER_HAPPY22" => Ok(EV_KEY::BTN_TRIGGER_HAPPY22), "BTN_TRIGGER_HAPPY23" => Ok(EV_KEY::BTN_TRIGGER_HAPPY23), "BTN_TRIGGER_HAPPY24" => Ok(EV_KEY::BTN_TRIGGER_HAPPY24), "BTN_TRIGGER_HAPPY25" => Ok(EV_KEY::BTN_TRIGGER_HAPPY25), "BTN_TRIGGER_HAPPY26" => Ok(EV_KEY::BTN_TRIGGER_HAPPY26), "BTN_TRIGGER_HAPPY27" => Ok(EV_KEY::BTN_TRIGGER_HAPPY27), "BTN_TRIGGER_HAPPY28" => Ok(EV_KEY::BTN_TRIGGER_HAPPY28), "BTN_TRIGGER_HAPPY29" => Ok(EV_KEY::BTN_TRIGGER_HAPPY29), "BTN_TRIGGER_HAPPY30" => Ok(EV_KEY::BTN_TRIGGER_HAPPY30), "BTN_TRIGGER_HAPPY31" => Ok(EV_KEY::BTN_TRIGGER_HAPPY31), "BTN_TRIGGER_HAPPY32" => Ok(EV_KEY::BTN_TRIGGER_HAPPY32), "BTN_TRIGGER_HAPPY33" => Ok(EV_KEY::BTN_TRIGGER_HAPPY33), "BTN_TRIGGER_HAPPY34" => Ok(EV_KEY::BTN_TRIGGER_HAPPY34), "BTN_TRIGGER_HAPPY35" => Ok(EV_KEY::BTN_TRIGGER_HAPPY35), "BTN_TRIGGER_HAPPY36" => Ok(EV_KEY::BTN_TRIGGER_HAPPY36), "BTN_TRIGGER_HAPPY37" => Ok(EV_KEY::BTN_TRIGGER_HAPPY37), "BTN_TRIGGER_HAPPY38" => Ok(EV_KEY::BTN_TRIGGER_HAPPY38), "BTN_TRIGGER_HAPPY39" => Ok(EV_KEY::BTN_TRIGGER_HAPPY39), "BTN_TRIGGER_HAPPY40" => Ok(EV_KEY::BTN_TRIGGER_HAPPY40), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_LED { LED_NUML = 0, LED_CAPSL = 1, LED_SCROLLL = 2, LED_COMPOSE = 3, LED_KANA = 4, LED_SLEEP = 5, LED_SUSPEND = 6, LED_MUTE = 7, LED_MISC = 8, LED_MAIL = 9, LED_CHARGING = 10, LED_MAX = 15, } pub const fn int_to_ev_led(code: u32) -> Option { match code { 0 => Some(EV_LED::LED_NUML), 1 => Some(EV_LED::LED_CAPSL), 2 => Some(EV_LED::LED_SCROLLL), 3 => Some(EV_LED::LED_COMPOSE), 4 => Some(EV_LED::LED_KANA), 5 => Some(EV_LED::LED_SLEEP), 6 => Some(EV_LED::LED_SUSPEND), 7 => Some(EV_LED::LED_MUTE), 8 => Some(EV_LED::LED_MISC), 9 => Some(EV_LED::LED_MAIL), 10 => Some(EV_LED::LED_CHARGING), 15 => Some(EV_LED::LED_MAX), _ => None, } } impl std::str::FromStr for EV_LED { type Err = (); fn from_str(s: &str) -> Result { match s { "LED_NUML" => Ok(EV_LED::LED_NUML), "LED_CAPSL" => Ok(EV_LED::LED_CAPSL), "LED_SCROLLL" => Ok(EV_LED::LED_SCROLLL), "LED_COMPOSE" => Ok(EV_LED::LED_COMPOSE), "LED_KANA" => Ok(EV_LED::LED_KANA), "LED_SLEEP" => Ok(EV_LED::LED_SLEEP), "LED_SUSPEND" => Ok(EV_LED::LED_SUSPEND), "LED_MUTE" => Ok(EV_LED::LED_MUTE), "LED_MISC" => Ok(EV_LED::LED_MISC), "LED_MAIL" => Ok(EV_LED::LED_MAIL), "LED_CHARGING" => Ok(EV_LED::LED_CHARGING), "LED_MAX" => Ok(EV_LED::LED_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_SND { SND_CLICK = 0, SND_BELL = 1, SND_TONE = 2, SND_MAX = 7, } pub const fn int_to_ev_snd(code: u32) -> Option { match code { 0 => Some(EV_SND::SND_CLICK), 1 => Some(EV_SND::SND_BELL), 2 => Some(EV_SND::SND_TONE), 7 => Some(EV_SND::SND_MAX), _ => None, } } impl std::str::FromStr for EV_SND { type Err = (); fn from_str(s: &str) -> Result { match s { "SND_CLICK" => Ok(EV_SND::SND_CLICK), "SND_BELL" => Ok(EV_SND::SND_BELL), "SND_TONE" => Ok(EV_SND::SND_TONE), "SND_MAX" => Ok(EV_SND::SND_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_MSC { MSC_SERIAL = 0, MSC_PULSELED = 1, MSC_GESTURE = 2, MSC_RAW = 3, MSC_SCAN = 4, MSC_TIMESTAMP = 5, MSC_MAX = 7, } pub const fn int_to_ev_msc(code: u32) -> Option { match code { 0 => Some(EV_MSC::MSC_SERIAL), 1 => Some(EV_MSC::MSC_PULSELED), 2 => Some(EV_MSC::MSC_GESTURE), 3 => Some(EV_MSC::MSC_RAW), 4 => Some(EV_MSC::MSC_SCAN), 5 => Some(EV_MSC::MSC_TIMESTAMP), 7 => Some(EV_MSC::MSC_MAX), _ => None, } } impl std::str::FromStr for EV_MSC { type Err = (); fn from_str(s: &str) -> Result { match s { "MSC_SERIAL" => Ok(EV_MSC::MSC_SERIAL), "MSC_PULSELED" => Ok(EV_MSC::MSC_PULSELED), "MSC_GESTURE" => Ok(EV_MSC::MSC_GESTURE), "MSC_RAW" => Ok(EV_MSC::MSC_RAW), "MSC_SCAN" => Ok(EV_MSC::MSC_SCAN), "MSC_TIMESTAMP" => Ok(EV_MSC::MSC_TIMESTAMP), "MSC_MAX" => Ok(EV_MSC::MSC_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_SW { SW_LID = 0, SW_TABLET_MODE = 1, SW_HEADPHONE_INSERT = 2, SW_RFKILL_ALL = 3, SW_MICROPHONE_INSERT = 4, SW_DOCK = 5, SW_LINEOUT_INSERT = 6, SW_JACK_PHYSICAL_INSERT = 7, SW_VIDEOOUT_INSERT = 8, SW_CAMERA_LENS_COVER = 9, SW_KEYPAD_SLIDE = 10, SW_FRONT_PROXIMITY = 11, SW_ROTATE_LOCK = 12, SW_LINEIN_INSERT = 13, SW_MUTE_DEVICE = 14, SW_PEN_INSERTED = 15, SW_MACHINE_COVER = 16, } impl EV_SW { pub const SW_MAX: EV_SW = EV_SW::SW_MACHINE_COVER; } pub const fn int_to_ev_sw(code: u32) -> Option { match code { 0 => Some(EV_SW::SW_LID), 1 => Some(EV_SW::SW_TABLET_MODE), 2 => Some(EV_SW::SW_HEADPHONE_INSERT), 3 => Some(EV_SW::SW_RFKILL_ALL), 4 => Some(EV_SW::SW_MICROPHONE_INSERT), 5 => Some(EV_SW::SW_DOCK), 6 => Some(EV_SW::SW_LINEOUT_INSERT), 7 => Some(EV_SW::SW_JACK_PHYSICAL_INSERT), 8 => Some(EV_SW::SW_VIDEOOUT_INSERT), 9 => Some(EV_SW::SW_CAMERA_LENS_COVER), 10 => Some(EV_SW::SW_KEYPAD_SLIDE), 11 => Some(EV_SW::SW_FRONT_PROXIMITY), 12 => Some(EV_SW::SW_ROTATE_LOCK), 13 => Some(EV_SW::SW_LINEIN_INSERT), 14 => Some(EV_SW::SW_MUTE_DEVICE), 15 => Some(EV_SW::SW_PEN_INSERTED), 16 => Some(EV_SW::SW_MACHINE_COVER), _ => None, } } impl std::str::FromStr for EV_SW { type Err = (); fn from_str(s: &str) -> Result { match s { "SW_LID" => Ok(EV_SW::SW_LID), "SW_TABLET_MODE" => Ok(EV_SW::SW_TABLET_MODE), "SW_HEADPHONE_INSERT" => Ok(EV_SW::SW_HEADPHONE_INSERT), "SW_RFKILL_ALL" => Ok(EV_SW::SW_RFKILL_ALL), "SW_MICROPHONE_INSERT" => Ok(EV_SW::SW_MICROPHONE_INSERT), "SW_DOCK" => Ok(EV_SW::SW_DOCK), "SW_LINEOUT_INSERT" => Ok(EV_SW::SW_LINEOUT_INSERT), "SW_JACK_PHYSICAL_INSERT" => Ok(EV_SW::SW_JACK_PHYSICAL_INSERT), "SW_VIDEOOUT_INSERT" => Ok(EV_SW::SW_VIDEOOUT_INSERT), "SW_CAMERA_LENS_COVER" => Ok(EV_SW::SW_CAMERA_LENS_COVER), "SW_KEYPAD_SLIDE" => Ok(EV_SW::SW_KEYPAD_SLIDE), "SW_FRONT_PROXIMITY" => Ok(EV_SW::SW_FRONT_PROXIMITY), "SW_ROTATE_LOCK" => Ok(EV_SW::SW_ROTATE_LOCK), "SW_LINEIN_INSERT" => Ok(EV_SW::SW_LINEIN_INSERT), "SW_MUTE_DEVICE" => Ok(EV_SW::SW_MUTE_DEVICE), "SW_PEN_INSERTED" => Ok(EV_SW::SW_PEN_INSERTED), "SW_MACHINE_COVER" => Ok(EV_SW::SW_MACHINE_COVER), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_SYN { SYN_REPORT = 0, SYN_CONFIG = 1, SYN_MT_REPORT = 2, SYN_DROPPED = 3, SYN_MAX = 15, } pub const fn int_to_ev_syn(code: u32) -> Option { match code { 0 => Some(EV_SYN::SYN_REPORT), 1 => Some(EV_SYN::SYN_CONFIG), 2 => Some(EV_SYN::SYN_MT_REPORT), 3 => Some(EV_SYN::SYN_DROPPED), 15 => Some(EV_SYN::SYN_MAX), _ => None, } } impl std::str::FromStr for EV_SYN { type Err = (); fn from_str(s: &str) -> Result { match s { "SYN_REPORT" => Ok(EV_SYN::SYN_REPORT), "SYN_CONFIG" => Ok(EV_SYN::SYN_CONFIG), "SYN_MT_REPORT" => Ok(EV_SYN::SYN_MT_REPORT), "SYN_DROPPED" => Ok(EV_SYN::SYN_DROPPED), "SYN_MAX" => Ok(EV_SYN::SYN_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_REP { REP_DELAY = 0, REP_PERIOD = 1, } impl EV_REP { pub const REP_MAX: EV_REP = EV_REP::REP_PERIOD; } pub const fn int_to_ev_rep(code: u32) -> Option { match code { 0 => Some(EV_REP::REP_DELAY), 1 => Some(EV_REP::REP_PERIOD), _ => None, } } impl std::str::FromStr for EV_REP { type Err = (); fn from_str(s: &str) -> Result { match s { "REP_DELAY" => Ok(EV_REP::REP_DELAY), "REP_PERIOD" => Ok(EV_REP::REP_PERIOD), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum InputProp { INPUT_PROP_POINTER = 0, INPUT_PROP_DIRECT = 1, INPUT_PROP_BUTTONPAD = 2, INPUT_PROP_SEMI_MT = 3, INPUT_PROP_TOPBUTTONPAD = 4, INPUT_PROP_POINTING_STICK = 5, INPUT_PROP_ACCELEROMETER = 6, INPUT_PROP_MAX = 31, } pub const fn int_to_input_prop(code: u32) -> Option { match code { 0 => Some(InputProp::INPUT_PROP_POINTER), 1 => Some(InputProp::INPUT_PROP_DIRECT), 2 => Some(InputProp::INPUT_PROP_BUTTONPAD), 3 => Some(InputProp::INPUT_PROP_SEMI_MT), 4 => Some(InputProp::INPUT_PROP_TOPBUTTONPAD), 5 => Some(InputProp::INPUT_PROP_POINTING_STICK), 6 => Some(InputProp::INPUT_PROP_ACCELEROMETER), 31 => Some(InputProp::INPUT_PROP_MAX), _ => None, } } impl std::str::FromStr for InputProp { type Err = (); fn from_str(s: &str) -> Result { match s { "INPUT_PROP_POINTER" => Ok(InputProp::INPUT_PROP_POINTER), "INPUT_PROP_DIRECT" => Ok(InputProp::INPUT_PROP_DIRECT), "INPUT_PROP_BUTTONPAD" => Ok(InputProp::INPUT_PROP_BUTTONPAD), "INPUT_PROP_SEMI_MT" => Ok(InputProp::INPUT_PROP_SEMI_MT), "INPUT_PROP_TOPBUTTONPAD" => Ok(InputProp::INPUT_PROP_TOPBUTTONPAD), "INPUT_PROP_POINTING_STICK" => Ok(InputProp::INPUT_PROP_POINTING_STICK), "INPUT_PROP_ACCELEROMETER" => Ok(InputProp::INPUT_PROP_ACCELEROMETER), "INPUT_PROP_MAX" => Ok(InputProp::INPUT_PROP_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum EV_FF { FF_STATUS_STOPPED = 0, FF_STATUS_PLAYING = 1, FF_RUMBLE = 80, FF_PERIODIC = 81, FF_CONSTANT = 82, FF_SPRING = 83, FF_FRICTION = 84, FF_DAMPER = 85, FF_INERTIA = 86, FF_RAMP = 87, FF_SQUARE = 88, FF_TRIANGLE = 89, FF_SINE = 90, FF_SAW_UP = 91, FF_SAW_DOWN = 92, FF_CUSTOM = 93, FF_GAIN = 96, FF_AUTOCENTER = 97, FF_MAX = 127, } impl EV_FF { pub const FF_STATUS_MAX: EV_FF = EV_FF::FF_STATUS_PLAYING; } pub const fn int_to_ev_ff(code: u32) -> Option { match code { 0 => Some(EV_FF::FF_STATUS_STOPPED), 1 => Some(EV_FF::FF_STATUS_PLAYING), 80 => Some(EV_FF::FF_RUMBLE), 81 => Some(EV_FF::FF_PERIODIC), 82 => Some(EV_FF::FF_CONSTANT), 83 => Some(EV_FF::FF_SPRING), 84 => Some(EV_FF::FF_FRICTION), 85 => Some(EV_FF::FF_DAMPER), 86 => Some(EV_FF::FF_INERTIA), 87 => Some(EV_FF::FF_RAMP), 88 => Some(EV_FF::FF_SQUARE), 89 => Some(EV_FF::FF_TRIANGLE), 90 => Some(EV_FF::FF_SINE), 91 => Some(EV_FF::FF_SAW_UP), 92 => Some(EV_FF::FF_SAW_DOWN), 93 => Some(EV_FF::FF_CUSTOM), 96 => Some(EV_FF::FF_GAIN), 97 => Some(EV_FF::FF_AUTOCENTER), 127 => Some(EV_FF::FF_MAX), _ => None, } } impl std::str::FromStr for EV_FF { type Err = (); fn from_str(s: &str) -> Result { match s { "FF_STATUS_STOPPED" => Ok(EV_FF::FF_STATUS_STOPPED), "FF_STATUS_PLAYING" => Ok(EV_FF::FF_STATUS_PLAYING), "FF_RUMBLE" => Ok(EV_FF::FF_RUMBLE), "FF_PERIODIC" => Ok(EV_FF::FF_PERIODIC), "FF_CONSTANT" => Ok(EV_FF::FF_CONSTANT), "FF_SPRING" => Ok(EV_FF::FF_SPRING), "FF_FRICTION" => Ok(EV_FF::FF_FRICTION), "FF_DAMPER" => Ok(EV_FF::FF_DAMPER), "FF_INERTIA" => Ok(EV_FF::FF_INERTIA), "FF_RAMP" => Ok(EV_FF::FF_RAMP), "FF_SQUARE" => Ok(EV_FF::FF_SQUARE), "FF_TRIANGLE" => Ok(EV_FF::FF_TRIANGLE), "FF_SINE" => Ok(EV_FF::FF_SINE), "FF_SAW_UP" => Ok(EV_FF::FF_SAW_UP), "FF_SAW_DOWN" => Ok(EV_FF::FF_SAW_DOWN), "FF_CUSTOM" => Ok(EV_FF::FF_CUSTOM), "FF_GAIN" => Ok(EV_FF::FF_GAIN), "FF_AUTOCENTER" => Ok(EV_FF::FF_AUTOCENTER), "FF_MAX" => Ok(EV_FF::FF_MAX), _ => Err(()), } } } #[allow(non_camel_case_types)] #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum BusType { BUS_PCI = 1, BUS_ISAPNP = 2, BUS_USB = 3, BUS_HIL = 4, BUS_BLUETOOTH = 5, BUS_VIRTUAL = 6, BUS_ISA = 16, BUS_I8042 = 17, BUS_XTKBD = 18, BUS_RS232 = 19, BUS_GAMEPORT = 20, BUS_PARPORT = 21, BUS_AMIGA = 22, BUS_ADB = 23, BUS_I2C = 24, BUS_HOST = 25, BUS_GSC = 26, BUS_ATARI = 27, BUS_SPI = 28, BUS_RMI = 29, BUS_CEC = 30, BUS_INTEL_ISHTP = 31, } pub const fn int_to_bus_type(code: u32) -> Option { match code { 1 => Some(BusType::BUS_PCI), 2 => Some(BusType::BUS_ISAPNP), 3 => Some(BusType::BUS_USB), 4 => Some(BusType::BUS_HIL), 5 => Some(BusType::BUS_BLUETOOTH), 6 => Some(BusType::BUS_VIRTUAL), 16 => Some(BusType::BUS_ISA), 17 => Some(BusType::BUS_I8042), 18 => Some(BusType::BUS_XTKBD), 19 => Some(BusType::BUS_RS232), 20 => Some(BusType::BUS_GAMEPORT), 21 => Some(BusType::BUS_PARPORT), 22 => Some(BusType::BUS_AMIGA), 23 => Some(BusType::BUS_ADB), 24 => Some(BusType::BUS_I2C), 25 => Some(BusType::BUS_HOST), 26 => Some(BusType::BUS_GSC), 27 => Some(BusType::BUS_ATARI), 28 => Some(BusType::BUS_SPI), 29 => Some(BusType::BUS_RMI), 30 => Some(BusType::BUS_CEC), 31 => Some(BusType::BUS_INTEL_ISHTP), _ => None, } } impl std::str::FromStr for BusType { type Err = (); fn from_str(s: &str) -> Result { match s { "BUS_PCI" => Ok(BusType::BUS_PCI), "BUS_ISAPNP" => Ok(BusType::BUS_ISAPNP), "BUS_USB" => Ok(BusType::BUS_USB), "BUS_HIL" => Ok(BusType::BUS_HIL), "BUS_BLUETOOTH" => Ok(BusType::BUS_BLUETOOTH), "BUS_VIRTUAL" => Ok(BusType::BUS_VIRTUAL), "BUS_ISA" => Ok(BusType::BUS_ISA), "BUS_I8042" => Ok(BusType::BUS_I8042), "BUS_XTKBD" => Ok(BusType::BUS_XTKBD), "BUS_RS232" => Ok(BusType::BUS_RS232), "BUS_GAMEPORT" => Ok(BusType::BUS_GAMEPORT), "BUS_PARPORT" => Ok(BusType::BUS_PARPORT), "BUS_AMIGA" => Ok(BusType::BUS_AMIGA), "BUS_ADB" => Ok(BusType::BUS_ADB), "BUS_I2C" => Ok(BusType::BUS_I2C), "BUS_HOST" => Ok(BusType::BUS_HOST), "BUS_GSC" => Ok(BusType::BUS_GSC), "BUS_ATARI" => Ok(BusType::BUS_ATARI), "BUS_SPI" => Ok(BusType::BUS_SPI), "BUS_RMI" => Ok(BusType::BUS_RMI), "BUS_CEC" => Ok(BusType::BUS_CEC), "BUS_INTEL_ISHTP" => Ok(BusType::BUS_INTEL_ISHTP), _ => Err(()), } } } evdev-rs-0.6.1/src/lib.rs000064400000000000000000000173370072674642500133310ustar 00000000000000//! Rust bindings to libevdev, a wrapper for evdev devices. //! //! This library intends to provide a safe interface to the libevdev library. It //! will look for the library on the local system, and link to the installed copy. //! //! # Examples //! //! ## Intializing a evdev device //! //! ```rust,no_run //! use evdev_rs::Device; //! use std::fs::File; //! //! let mut d = Device::new_from_path("/dev/input/event0").unwrap(); //! ``` //! //! ## Getting the next event //! //! ```rust,no_run //! use evdev_rs::Device; //! use std::fs::File; //! use evdev_rs::ReadFlag; //! //! let mut d = Device::new_from_path("/dev/input/event0").unwrap(); //! //! loop { //! let ev = d.next_event(ReadFlag::NORMAL).map(|val| val.1); //! match ev { //! Ok(ev) => println!("Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++", //! ev.time.tv_sec, //! ev.time.tv_usec, //! ev.event_type().map(|ev_type| format!("{}", ev_type)).unwrap_or("".to_owned())), //! Err(e) => (), //! } //! } //! ``` //! //! ## Serialization //! to use serialization, you muse enable the `serde` feature. //! ```toml //! # Cargo.toml //! [dependencies] //! evdev-rs = { version = "0.4.0", features = ["serde"] } //! ``` #[macro_use] mod macros; mod device; pub mod enums; pub mod logging; mod uinput; pub mod util; use bitflags::bitflags; use libc::{c_uint, suseconds_t, time_t}; use std::convert::{TryFrom, TryInto}; use std::time::{Duration, SystemTime, SystemTimeError, UNIX_EPOCH}; use enums::*; use util::*; pub use util::EventCodeIterator; pub use util::EventTypeIterator; pub use util::InputPropIterator; use evdev_sys as raw; #[doc(inline)] pub use device::Device; #[doc(inline)] pub use device::DeviceWrapper; #[doc(inline)] pub use device::Enable; #[doc(inline)] pub use device::EnableCodeData; #[doc(inline)] pub use device::UninitDevice; #[doc(inline)] pub use uinput::UInputDevice; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; pub enum GrabMode { /// Grab the device if not currently grabbed Grab = raw::LIBEVDEV_GRAB as isize, /// Ungrab the device if currently grabbed Ungrab = raw::LIBEVDEV_UNGRAB as isize, } bitflags! { pub struct ReadFlag: u32 { /// Process data in sync mode const SYNC = 1; /// Process data in normal mode const NORMAL = 2; /// Pretend the next event is a SYN_DROPPED and require the /// caller to sync const FORCE_SYNC = 4; /// The fd is not in O_NONBLOCK and a read may block const BLOCKING = 8; } } #[derive(PartialEq)] pub enum ReadStatus { /// `next_event` has finished without an error and an event is available /// for processing. Success = raw::LIBEVDEV_READ_STATUS_SUCCESS as isize, /// Depending on the `next_event` read flag: /// libevdev received a SYN_DROPPED from the device, and the caller should /// now resync the device, or, an event has been read in sync mode. Sync = raw::LIBEVDEV_READ_STATUS_SYNC as isize, } pub enum LedState { /// Turn the LED on On = raw::LIBEVDEV_LED_ON as isize, /// Turn the LED off Off = raw::LIBEVDEV_LED_OFF as isize, } #[derive(Debug)] pub struct DeviceId { pub bustype: BusType, pub vendor: u16, pub product: u16, pub version: u16, } #[derive(Clone, Copy, Debug)] /// used by EVIOCGABS/EVIOCSABS ioctls pub struct AbsInfo { /// 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 pub resolution: i32, } impl AbsInfo { pub const fn from_raw(absinfo: libc::input_absinfo) -> AbsInfo { AbsInfo { value: absinfo.value, minimum: absinfo.minimum, maximum: absinfo.maximum, fuzz: absinfo.fuzz, flat: absinfo.flat, resolution: absinfo.resolution, } } pub const fn as_raw(&self) -> libc::input_absinfo { libc::input_absinfo { value: self.value, minimum: self.minimum, maximum: self.maximum, fuzz: self.fuzz, flat: self.flat, resolution: self.resolution, } } } #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Copy, Clone, Eq, Hash, PartialOrd, Ord, Debug, PartialEq)] pub struct TimeVal { pub tv_sec: time_t, pub tv_usec: suseconds_t, } impl TryFrom for TimeVal { type Error = SystemTimeError; fn try_from(system_time: SystemTime) -> Result { let d = system_time.duration_since(UNIX_EPOCH)?; Ok(TimeVal { tv_sec: d.as_secs() as time_t, tv_usec: d.subsec_micros() as suseconds_t, }) } } impl TryInto for TimeVal { type Error = (); /// Fails if TimeVal.tv_usec is >= 10^6 or if the TimeVal is outside /// the range of SystemTime fn try_into(self) -> Result { let secs = self.tv_sec.try_into().map_err(|_| ())?; let nanos = (self.tv_usec * 1000).try_into().map_err(|_| ())?; let duration = Duration::new(secs, nanos); UNIX_EPOCH.checked_add(duration).ok_or(()) } } impl TimeVal { pub const fn new(tv_sec: time_t, tv_usec: suseconds_t) -> TimeVal { const MICROS_PER_SEC: suseconds_t = 1_000_000; TimeVal { tv_sec: tv_sec + tv_usec / MICROS_PER_SEC, tv_usec: tv_usec % MICROS_PER_SEC, } } pub const fn from_raw(timeval: &libc::timeval) -> TimeVal { TimeVal { tv_sec: timeval.tv_sec, tv_usec: timeval.tv_usec, } } pub const fn as_raw(&self) -> libc::timeval { libc::timeval { tv_sec: self.tv_sec, tv_usec: self.tv_usec, } } } /// The event structure itself #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct InputEvent { /// The time at which event occured pub time: TimeVal, pub event_code: EventCode, pub value: i32, } impl InputEvent { pub const fn new(timeval: &TimeVal, code: &EventCode, value: i32) -> InputEvent { InputEvent { time: *timeval, event_code: *code, value, } } pub fn event_type(&self) -> Option { int_to_event_type(event_code_to_int(&self.event_code).0) } pub fn from_raw(event: &libc::input_event) -> InputEvent { let ev_type = event.type_ as u32; let event_code = int_to_event_code(ev_type, event.code as u32); InputEvent { time: TimeVal::from_raw(&event.time), event_code, value: event.value, } } pub fn as_raw(&self) -> libc::input_event { let (ev_type, ev_code) = event_code_to_int(&self.event_code); libc::input_event { time: self.time.as_raw(), type_: ev_type as u16, code: ev_code as u16, value: self.value, } } pub fn is_type(&self, ev_type: &EventType) -> bool { unsafe { raw::libevdev_event_is_type(&self.as_raw(), *ev_type as c_uint) == 1 } } pub fn is_code(&self, code: &EventCode) -> bool { let (ev_type, ev_code) = event_code_to_int(code); unsafe { raw::libevdev_event_is_code(&self.as_raw(), ev_type, ev_code) == 1 } } } evdev-rs-0.6.1/src/logging.rs000064400000000000000000000021750072674642500142030ustar 00000000000000use evdev_sys as raw; pub enum LogPriority { /// critical errors and application bugs Error = raw::LIBEVDEV_LOG_ERROR as isize, /// informational messages Info = raw::LIBEVDEV_LOG_INFO as isize, /// debug information Debug = raw::LIBEVDEV_LOG_DEBUG as isize, } /// Define the minimum level to be printed to the log handler. /// Messages higher than this level are printed, others are discarded. This /// is a global setting and applies to any future logging messages. pub fn set_log_priority(priority: LogPriority) { unsafe { raw::libevdev_set_log_priority(priority as i32); } } /// Return the current log priority level. Messages higher than this level /// are printed, others are discarded. This is a global setting. pub fn get_log_priority() -> LogPriority { unsafe { let priority = raw::libevdev_get_log_priority(); match priority { raw::LIBEVDEV_LOG_ERROR => LogPriority::Error, raw::LIBEVDEV_LOG_INFO => LogPriority::Info, raw::LIBEVDEV_LOG_DEBUG => LogPriority::Debug, c => panic!("unknown log priority: {}", c), } } } evdev-rs-0.6.1/src/macros.rs000064400000000000000000000040210072674642500140310ustar 00000000000000macro_rules! string_getter { ( $( #[$doc:meta], $func_name:ident, $c_func: ident ),* ) => { $( #[$doc] fn $func_name (&self) -> Option<&str> { unsafe { ptr_to_str(raw::$c_func(self.raw())) } } )* }; } macro_rules! string_setter { ( $( $func_name:ident, $c_func: ident ),* ) => { $( fn $func_name (&self, field: &str) { let field = CString::new(field).unwrap(); unsafe { raw::$c_func(self.raw(), field.as_ptr()) } } )* }; } macro_rules! product_getter { ( $( $func_name:ident, $c_func: ident ),* ) => { $( fn $func_name (&self) -> u16 { unsafe { raw::$c_func(self.raw()) as u16 } } )* }; } macro_rules! product_setter { ( $( $func_name:ident, $c_func: ident ),* ) => { $( fn $func_name (&self, field: u16) { unsafe { raw::$c_func(self.raw(), field as c_int); } } )* }; } macro_rules! abs_getter { ( $( $func_name:ident, $c_func: ident ),* ) => { $( fn $func_name (&self, code: u32) -> std::io::Result { let result = unsafe { raw::$c_func(self.raw(), code as c_uint) as i32 }; match result { 0 => Err(std::io::Error::from_raw_os_error(0)), k => Ok(k) } } )* }; } macro_rules! abs_setter { ( $( $func_name:ident, $c_func: ident ),* ) => { $( fn $func_name (&self, code: u32, val: i32) { unsafe { raw::$c_func(self.raw(), code as c_uint, val as c_int); } } )* }; } evdev-rs-0.6.1/src/uinput.rs000064400000000000000000000075170072674642500141060ustar 00000000000000use crate::{device::DeviceWrapper, InputEvent}; use libc::c_int; use std::io; use std::os::unix::io::RawFd; use crate::util::*; use evdev_sys as raw; /// Opaque struct representing an evdev uinput device pub struct UInputDevice { raw: *mut raw::libevdev_uinput, } unsafe impl Send for UInputDevice {} impl UInputDevice { fn raw(&self) -> *mut raw::libevdev_uinput { self.raw } /// Create a uinput device based on the given libevdev device. /// /// The uinput device will be an exact copy of the libevdev device, minus /// the bits that uinput doesn't allow to be set. pub fn create_from_device(device: &T) -> io::Result { let mut libevdev_uinput = std::ptr::null_mut(); let result = unsafe { raw::libevdev_uinput_create_from_device( device.raw(), raw::LIBEVDEV_UINPUT_OPEN_MANAGED, &mut libevdev_uinput, ) }; match result { 0 => Ok(UInputDevice { raw: libevdev_uinput, }), error => Err(io::Error::from_raw_os_error(-error)), } } ///Return the device node representing this uinput device. /// /// This relies on `libevdev_uinput_get_syspath()` to provide a valid syspath. pub fn devnode(&self) -> Option<&str> { unsafe { ptr_to_str(raw::libevdev_uinput_get_devnode(self.raw())) } } ///Return the syspath representing this uinput device. /// /// If the UI_GET_SYSNAME ioctl not available, libevdev makes an educated /// guess. The UI_GET_SYSNAME ioctl is available since Linux 3.15. /// /// The syspath returned is the one of the input node itself /// (e.g. /sys/devices/virtual/input/input123), not the syspath of the /// device node returned with libevdev_uinput_get_devnode(). pub fn syspath(&self) -> Option<&str> { unsafe { ptr_to_str(raw::libevdev_uinput_get_syspath(self.raw())) } } /// Return the file descriptor used to create this uinput device. /// /// This is the fd pointing to /dev/uinput. This file descriptor may be used /// to write events that are emitted by the uinput device. Closing this file /// descriptor will destroy the uinput device. pub fn as_fd(&self) -> Option { match unsafe { raw::libevdev_uinput_get_fd(self.raw()) } { 0 => None, result => Some(result), } } #[deprecated( since = "0.5.0", note = "Prefer `as_fd`. Some function names were changed so they more closely match their type signature. See issue 42 for discussion https://github.com/ndesh26/evdev-rs/issues/42" )] pub fn fd(&self) -> Option { self.as_fd() } /// Post an event through the uinput device. /// /// It is the caller's responsibility that any event sequence is terminated /// with an EV_SYN/SYN_REPORT/0 event. Otherwise, listeners on the device /// node will not see the events until the next EV_SYN event is posted. pub fn write_event(&self, event: &InputEvent) -> io::Result<()> { let (ev_type, ev_code) = event_code_to_int(&event.event_code); let ev_value = event.value as c_int; let result = unsafe { raw::libevdev_uinput_write_event(self.raw(), ev_type, ev_code, ev_value) }; match result { 0 => Ok(()), error => Err(io::Error::from_raw_os_error(-error)), } } } impl Drop for UInputDevice { fn drop(&mut self) { unsafe { raw::libevdev_uinput_destroy(self.raw()); } } } impl std::fmt::Debug for UInputDevice { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("UInputDevice") .field("devnode", &self.devnode()) .finish() } } evdev-rs-0.6.1/src/util.rs000064400000000000000000000365520072674642500135400ustar 00000000000000use crate::enums::*; use libc::{c_char, c_uint}; use log::warn; use std::ffi::{CStr, CString}; use std::fmt; use evdev_sys as raw; pub(crate) unsafe fn ptr_to_str(ptr: *const c_char) -> Option<&'static str> { let slice = CStr::from_ptr(ptr.as_ref()?); let buf = slice.to_bytes(); std::str::from_utf8(buf).ok() } pub struct EventTypeIterator { current: EventType, } pub struct EventCodeIterator { current: EventCode, } pub struct InputPropIterator { current: InputProp, } impl EventTypeIterator { pub fn new() -> Self { EventTypeIterator { current: EventType::EV_SYN, } } } impl EventCodeIterator { pub fn new(event_type: &EventType) -> Self { let event_code = match *event_type { EventType::EV_SYN => EventCode::EV_SYN(EV_SYN::SYN_REPORT), EventType::EV_KEY => EventCode::EV_KEY(EV_KEY::KEY_RESERVED), EventType::EV_REL => EventCode::EV_REL(EV_REL::REL_X), EventType::EV_ABS => EventCode::EV_ABS(EV_ABS::ABS_X), EventType::EV_MSC => EventCode::EV_MSC(EV_MSC::MSC_SERIAL), EventType::EV_SW => EventCode::EV_SW(EV_SW::SW_LID), EventType::EV_LED => EventCode::EV_LED(EV_LED::LED_NUML), EventType::EV_SND => EventCode::EV_SND(EV_SND::SND_CLICK), EventType::EV_REP => EventCode::EV_REP(EV_REP::REP_DELAY), EventType::EV_FF => EventCode::EV_FF(EV_FF::FF_STATUS_STOPPED), EventType::EV_FF_STATUS => EventCode::EV_FF_STATUS(EV_FF::FF_STATUS_STOPPED), _ => EventCode::EV_MAX, }; EventCodeIterator { current: event_code, } } } impl InputPropIterator { pub fn new() -> Self { InputPropIterator { current: InputProp::INPUT_PROP_POINTER, } } } pub fn event_code_to_int(event_code: &EventCode) -> (c_uint, c_uint) { match *event_code { EventCode::EV_SYN(code) => (EventType::EV_SYN as c_uint, code as c_uint), EventCode::EV_KEY(code) => (EventType::EV_KEY as c_uint, code as c_uint), EventCode::EV_REL(code) => (EventType::EV_REL as c_uint, code as c_uint), EventCode::EV_ABS(code) => (EventType::EV_ABS as c_uint, code as c_uint), EventCode::EV_MSC(code) => (EventType::EV_MSC as c_uint, code as c_uint), EventCode::EV_SW(code) => (EventType::EV_SW as c_uint, code as c_uint), EventCode::EV_LED(code) => (EventType::EV_LED as c_uint, code as c_uint), EventCode::EV_SND(code) => (EventType::EV_SND as c_uint, code as c_uint), EventCode::EV_REP(code) => (EventType::EV_REP as c_uint, code as c_uint), EventCode::EV_FF(code) => (EventType::EV_FF as c_uint, code as c_uint), EventCode::EV_FF_STATUS(code) => { (EventType::EV_FF_STATUS as c_uint, code as c_uint) } EventCode::EV_UNK { event_type, event_code, } => (event_type as c_uint, event_code as c_uint), _ => { warn!("Event code not found"); (0, 0) } } } pub fn int_to_event_code(event_type: c_uint, event_code: c_uint) -> EventCode { let ev_type: EventType = int_to_event_type(event_type as u32).unwrap(); let code = event_code as u32; let ev_code = match ev_type { EventType::EV_SYN => int_to_ev_syn(code).map(EventCode::EV_SYN), EventType::EV_KEY => int_to_ev_key(code).map(EventCode::EV_KEY), EventType::EV_ABS => int_to_ev_abs(code).map(EventCode::EV_ABS), EventType::EV_REL => int_to_ev_rel(code).map(EventCode::EV_REL), EventType::EV_MSC => int_to_ev_msc(code).map(EventCode::EV_MSC), EventType::EV_SW => int_to_ev_sw(code).map(EventCode::EV_SW), EventType::EV_LED => int_to_ev_led(code).map(EventCode::EV_LED), EventType::EV_SND => int_to_ev_snd(code).map(EventCode::EV_SND), EventType::EV_REP => int_to_ev_rep(code).map(EventCode::EV_REP), EventType::EV_FF => int_to_ev_ff(code).map(EventCode::EV_FF), EventType::EV_PWR => Some(EventCode::EV_PWR), EventType::EV_FF_STATUS => int_to_ev_ff(code).map(EventCode::EV_FF_STATUS), EventType::EV_UNK => None, EventType::EV_MAX => Some(EventCode::EV_MAX), }; ev_code.unwrap_or(EventCode::EV_UNK { event_type, event_code, }) } impl fmt::Display for EventType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "{}", unsafe { ptr_to_str(raw::libevdev_event_type_get_name(*self as c_uint)) } .unwrap_or("") ) } } impl fmt::Display for EventCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (ev_type, ev_code) = event_code_to_int(self); write!( f, "{}", unsafe { ptr_to_str(raw::libevdev_event_code_get_name(ev_type, ev_code)) } .unwrap_or("") ) } } impl fmt::Display for InputProp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "{}", unsafe { ptr_to_str(raw::libevdev_property_get_name(*self as c_uint)) } .unwrap_or("") ) } } impl EventType { pub fn iter(&self) -> EventTypeIterator { EventTypeIterator { current: *self } } /// The given type constant for the passed name or Errno if not found. pub fn from_str(name: &str) -> Option { let name = CString::new(name).unwrap(); let result = unsafe { raw::libevdev_event_type_from_name(name.as_ptr()) }; match result { -1 => None, k => int_to_event_type(k as u32), } } /// The max value defined for the given event type, e.g. ABS_MAX for a type /// of EV_ABS, or Errno for an invalid type. pub fn get_max(ev_type: &EventType) -> Option { let result = unsafe { raw::libevdev_event_type_get_max(*ev_type as c_uint) }; match result { k if k < 0 => None, k => Some(k as u32), } } } impl EventCode { pub fn iter(&self) -> EventCodeIterator { EventCodeIterator { current: *self } } /// Look up an event code by its type and name. Event codes start with a fixed /// prefix followed by their name (eg., "ABS_X"). The prefix must be included in /// the name. It returns the constant assigned to the event code or Errno if not /// found. pub fn from_str(ev_type: &EventType, name: &str) -> Option { let name = CString::new(name).unwrap(); let result = unsafe { raw::libevdev_event_code_from_name(*ev_type as c_uint, name.as_ptr()) }; match result { -1 => None, k => Some(int_to_event_code(*ev_type as u32, k as u32)), } } } impl InputProp { pub fn iter(&self) -> InputPropIterator { InputPropIterator { current: *self } } /// Look up an input property by its name. Properties start with the fixed /// prefix "INPUT_PROP_" followed by their name (eg., "INPUT_PROP_POINTER"). /// The prefix must be included in the name. It returns the constant assigned /// to the property or Errno if not found. pub fn from_str(name: &str) -> Option { let name = CString::new(name).unwrap(); let result = unsafe { raw::libevdev_property_from_name(name.as_ptr()) }; match result { -1 => None, k => int_to_input_prop(k as u32), } } } // Iterator trait for the enum iterators impl Iterator for EventTypeIterator { type Item = EventType; fn next(&mut self) -> Option { match self.current { EventType::EV_MAX => None, _ => { let mut raw_code = (self.current as u32) + 1; loop { match int_to_event_type(raw_code) { // TODO: Find a way to iterate over Unknown types Some(EventType::EV_UNK) => raw_code += 1, Some(x) => { let code = self.current; self.current = x; return Some(code); } None => raw_code += 1, } } } } } } impl Iterator for EventCodeIterator { type Item = EventCode; fn next(&mut self) -> Option { match self.current { EventCode::EV_SYN(code) => match code { EV_SYN::SYN_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_syn(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_SYN(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_KEY(code) => match code { EV_KEY::KEY_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_key(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_KEY(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_REL(code) => match code { EV_REL::REL_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_rel(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_REL(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_ABS(code) => match code { EV_ABS::ABS_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_abs(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_ABS(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_MSC(code) => match code { EV_MSC::MSC_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_msc(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_MSC(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_SW(code) => match code { EV_SW::SW_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_sw(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_SW(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_LED(code) => match code { EV_LED::LED_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_led(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_LED(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_SND(code) => match code { EV_SND::SND_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_snd(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_SND(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_REP(code) => match code { EV_REP::REP_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_rep(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_REP(x); return Some(ev_code); } None => raw_code += 1, } } } }, EventCode::EV_FF(code) => match code { EV_FF::FF_MAX => None, _ => { let mut raw_code = (code as u32) + 1; loop { match int_to_ev_ff(raw_code) { Some(x) => { let ev_code = self.current; self.current = EventCode::EV_FF(x); return Some(ev_code); } None => raw_code += 1, } } } }, _ => None, } } } impl Iterator for InputPropIterator { type Item = InputProp; fn next(&mut self) -> Option { match self.current { InputProp::INPUT_PROP_MAX => None, _ => { let mut raw_enum = (self.current as u32) + 1; loop { match int_to_input_prop(raw_enum) { Some(x) => { let prop = self.current; self.current = x; return Some(prop); } None => raw_enum += 1, } } } } } } evdev-rs-0.6.1/tests/all.rs000064400000000000000000000106560072674642500137030ustar 00000000000000use evdev_rs::enums::*; use evdev_rs::*; use std::fs::File; use std::os::unix::io::AsRawFd; #[test] fn context_create() { assert!(UninitDevice::new().is_some()); } #[test] fn context_create_with_file() { let f = File::open("/dev/input/event0").unwrap(); let _d = Device::new_from_file(f).unwrap(); } #[test] fn context_create_with_path() { let _d = Device::new_from_path("/dev/input/event0").unwrap(); } #[test] fn context_set_file() { let d = UninitDevice::new().unwrap(); let f = File::open("/dev/input/event0").unwrap(); let _device = d.set_file(f).unwrap(); } #[test] fn context_change_file() { let d = UninitDevice::new().unwrap(); let f1 = File::open("/dev/input/event0").unwrap(); let f2 = File::open("/dev/input/event0").unwrap(); let f2_fd = f2.as_raw_fd(); let mut d = d.set_file(f1).unwrap(); d.change_file(f2).unwrap(); assert_eq!(d.file().as_raw_fd(), f2_fd); } #[test] fn context_grab() { let mut d = Device::new_from_path("/dev/input/event0").unwrap(); d.grab(GrabMode::Grab).unwrap(); d.grab(GrabMode::Ungrab).unwrap(); } #[test] fn device_get_name() { let d = UninitDevice::new().unwrap(); d.set_name("hello"); assert_eq!(d.name().unwrap(), "hello"); } #[test] fn device_get_uniq() { let d = UninitDevice::new().unwrap(); d.set_uniq("test"); assert_eq!(d.uniq().unwrap(), "test"); } #[test] fn device_get_phys() { let d = UninitDevice::new().unwrap(); d.set_phys("test"); assert_eq!(d.phys().unwrap(), "test"); } #[test] fn device_get_product_id() { let d = UninitDevice::new().unwrap(); d.set_product_id(5); assert_eq!(d.product_id(), 5); } #[test] fn device_get_vendor_id() { let d = UninitDevice::new().unwrap(); d.set_vendor_id(5); assert_eq!(d.vendor_id(), 5); } #[test] fn device_get_bustype() { let d = UninitDevice::new().unwrap(); d.set_bustype(5); assert_eq!(d.bustype(), 5); } #[test] fn device_get_version() { let d = UninitDevice::new().unwrap(); d.set_version(5); assert_eq!(d.version(), 5); } #[test] fn device_get_absinfo() { let d = Device::new_from_path("/dev/input/event0").unwrap(); for code in EventCode::EV_SYN(EV_SYN::SYN_REPORT).iter() { let absinfo: Option = d.abs_info(&code); match absinfo { None => .., Some(_a) => .., }; } } #[test] fn device_has_property() { let d = Device::new_from_path("/dev/input/event0").unwrap(); for prop in InputProp::INPUT_PROP_POINTER.iter() { if d.has_property(&prop) { panic!("Prop {} is set, shouldn't be", prop); } } } #[test] fn device_enable_disable() { #[cfg(feature = "libevdev-1-10")] let prop = InputProp::INPUT_PROP_POINTER; let ev_type = EventType::EV_KEY; let code = EventCode::EV_KEY(EV_KEY::KEY_LEFTSHIFT); let d = UninitDevice::new().unwrap(); #[cfg(feature = "libevdev-1-10")] assert!(!d.has(prop)); assert!(!d.has(ev_type)); assert!(!d.has(code)); #[cfg(feature = "libevdev-1-10")] d.enable(prop).unwrap(); d.enable(ev_type).unwrap(); d.enable(code).unwrap(); #[cfg(feature = "libevdev-1-10")] assert!(d.has(prop)); assert!(d.has(ev_type)); assert!(d.has(code)); #[cfg(feature = "libevdev-1-10")] d.disable(prop).unwrap(); d.disable(ev_type).unwrap(); d.disable(code).unwrap(); #[cfg(feature = "libevdev-1-10")] assert!(!d.has(prop)); assert!(!d.has(ev_type)); assert!(!d.has(code)); } #[test] fn device_has_syn() { let d = UninitDevice::new().unwrap(); let f = File::open("/dev/input/event0").unwrap(); let d = d.set_file(f).unwrap(); assert!(d.has(EventType::EV_SYN)); // EV_SYN assert!(d.has(EventCode::EV_SYN(EV_SYN::SYN_REPORT))); // SYN_REPORT } #[test] fn device_get_value() { let d = UninitDevice::new().unwrap(); let f = File::open("/dev/input/event0").unwrap(); let d = d.set_file(f).unwrap(); let v2 = d.event_value(&EventCode::EV_SYN(EV_SYN::SYN_REPORT)); // SYN_REPORT assert_eq!(v2, Some(0)); } #[test] fn check_event_name() { assert_eq!("EV_ABS", EventType::EV_ABS.to_string()); } #[test] fn test_timeval() { assert_eq!(TimeVal::new(1, 1_000_000), TimeVal::new(2, 0)); assert_eq!(TimeVal::new(-1, -1_000_000), TimeVal::new(-2, 0)); assert_eq!(TimeVal::new(1, -1_000_000), TimeVal::new(0, 0)); assert_eq!(TimeVal::new(-100, 1_000_000 * 100), TimeVal::new(0, 0)); } evdev-rs-0.6.1/tools/make-enums.sh000075500000000000000000000002760072674642500151610ustar 00000000000000#!/usr/bin/env bash set -eux HEADER_DIR=evdev-sys/libevdev/include/linux/linux ./tools/make-event-names.py $HEADER_DIR/input-event-codes.h $HEADER_DIR/input.h | head -n -1 > src/enums.rs evdev-rs-0.6.1/tools/make-event-names.py000075500000000000000000000152760072674642500163000ustar 00000000000000#!/usr/bin/env python3 # Parses linux/input.h scanning for #define KEY_FOO 134 # Prints Rust source header files that can be used for # mapping and lookup tables. # # The original version of this file is in libevdev # import re import sys class Bits(object): pass prefixes = [ "EV_", "REL_", "ABS_", "KEY_", "BTN_", "LED_", "SND_", "MSC_", "SW_", "FF_", "SYN_", "REP_", "INPUT_PROP_", "BUS_" ] prefix_additional = { "key": ["btn"] } blacklist = [ "EV_VERSION", "BTN_MISC", "BTN_MOUSE", "BTN_JOYSTICK", "BTN_GAMEPAD", "BTN_DIGI", "BTN_WHEEL", "BTN_TRIGGER_HAPPY", ] btn_additional = [ [0, "BTN_A"], [0, "BTN_B"], [0, "BTN_X"], [0, "BTN_Y"], ] event_names = [ "REL_", "ABS_", "KEY_", "BTN_", "LED_", "SND_", "MSC_", "SW_", "FF_", "SYN_", "REP_", ] def convert(name): s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() def get_enum_name(prefix): if prefix == "ev": return "EventType" elif prefix == "input_prop": return "InputProp" elif prefix == "bus": return "BusType" else: return "EV_" + prefix.upper() def print_enums(bits, prefix): if not hasattr(bits, prefix): return enum_name = get_enum_name(prefix) associated_names = [] print("#[allow(non_camel_case_types)]") print('#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]') print("#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]") print("pub enum %s {" % enum_name) for val, names in list(getattr(bits, prefix).items()): # Note(ndesh): We use EV_MAX as proxy to write the UNKnown event if names[0] == "EV_MAX": print(" EV_UNK,") print(" %s = %s," % (names[0], val)) if len(names) > 1: associated_names.extend([(names[0], names[1:])]) if prefix == "key": for val, names in list(getattr(bits, "btn").items()): print(" %s = %s," % (names[0], val)) if len(names) > 1: associated_names.extend([(names[0], names[1:])]) print("}") print("") if len(associated_names) > 0: print("impl %s {" % enum_name) for orig, names in associated_names: for name in names: print(" pub const %s: %s = %s::%s;" % (name, enum_name, enum_name, orig)) print("}") print("") def print_enums_convert_fn(bits, prefix): if prefix == "ev": fn_name = "EventType" elif prefix == "input_prop": fn_name = "InputProp" elif prefix == "bus": fn_name = "BusType" else: fn_name = "EV_" + prefix.upper() if not hasattr(bits, prefix): return print("pub const fn %s(code: u32) -> Option<%s> {" % ("int_to_" + convert(fn_name), fn_name)) print(" match code {") for val, names in list(getattr(bits, prefix).items()): # Note(ndesh): We use EV_MAX as proxy to write the UNKnown event if names[0] == "EV_MAX": print(" c if c < 31 => Some(EventType::EV_UNK),") print(" %s => Some(%s::%s)," % (val, fn_name, names[0])) if prefix == "key": for val, names in list(getattr(bits, "btn").items()): print(" %s => Some(%s::%s)," % (val, fn_name, names[0])) print(" _ => None,") print(" }") print("}") print("") def print_enums_fromstr(bits, prefix): if not hasattr(bits, prefix): return enum_name = get_enum_name(prefix) print('impl std::str::FromStr for %s {' % enum_name) print(' type Err = ();') print(' fn from_str(s: &str) -> Result {') print(' match s {') for p in (prefix, *prefix_additional.get(prefix, ())): for _val, names in list(getattr(bits, p).items()): name = names[0] print(' "%s" => Ok(%s::%s),' % (name, enum_name, name)) print(' _ => Err(()),') print(' }') print(' }') print('}') print('') def print_event_code(bits, prefix): if not hasattr(bits, prefix): return print("#[allow(non_camel_case_types)]") print('#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]') print("#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]") print("pub enum EventCode {") for val, [name] in list(getattr(bits, prefix).items()): if name[3:]+"_" in event_names: print(" %s(%s)," % (name, name)) elif name == "EV_FF_STATUS": print(" EV_FF_STATUS(EV_FF),") else: # Note(ndesh): We use EV_MAX as proxy to write the UNKnown event if name == "EV_MAX": print(" EV_UNK { event_type: u32, event_code: u32 },") print(" %s," % (name)) if prefix == "key": for val, names in list(getattr(bits, "btn").items()): for name in names: print(" %s = %s," % (name, val)) print("}") print("") def print_mapping_table(bits): for prefix in prefixes: if prefix == "BTN_": continue print_enums(bits, prefix[:-1].lower()) print_enums_convert_fn(bits, prefix[:-1].lower()) print_enums_fromstr(bits, prefix[:-1].lower()) if prefix == "EV_": print_event_code(bits, prefix[:-1].lower()) def parse_define(bits, line): m = re.match(r"^#define\s+(\w+)\s+(\w+)", line) if m is None: return name = m.group(1) if name in blacklist: return try: value = int(m.group(2), 0) except ValueError: return for prefix in prefixes: if not name.startswith(prefix): continue attrname = prefix[:-1].lower() if not hasattr(bits, attrname): setattr(bits, attrname, {}) b = getattr(bits, attrname) if value in b: b[value].append(name) else: b[value] = [name] def parse(fp): bits = Bits() lines = fp.readlines() for line in lines: if not line.startswith("#define"): continue parse_define(bits, line) return bits def usage(prog): print("Usage: {} ".format(prog)) if __name__ == "__main__": if len(sys.argv) <= 1: usage(sys.argv[0]) sys.exit(2) print("/* THIS FILE IS GENERATED, DO NOT EDIT */") print("") print('#[cfg(feature = "serde")]') print("use serde::{Deserialize, Serialize};") print("") for arg in sys.argv[1:]: with open(arg) as f: bits = parse(f) print_mapping_table(bits)