├── .github └── workflows │ └── main.yml ├── .gitignore ├── .gitmodules ├── Cargo.toml ├── README.md ├── TODO.md ├── evdev-sys ├── Cargo.toml ├── build.rs └── src │ └── lib.rs ├── examples ├── evtest.rs └── vmouse.rs ├── rustfmt.toml ├── src ├── device.rs ├── enums.rs ├── lib.rs ├── logging.rs ├── macros.rs ├── uinput.rs └── util.rs ├── tests └── all.rs └── tools ├── make-enums.sh └── make-event-names.py /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | name: Test 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | build: [stable, beta, nightly, arm-gnueabi, arm-gnueabihf] 12 | include: 13 | - build: stable 14 | os: ubuntu-latest 15 | rust: stable 16 | target: x86_64-unknown-linux-gnu 17 | - build: beta 18 | os: ubuntu-latest 19 | rust: beta 20 | target: x86_64-unknown-linux-gnu 21 | - build: nightly 22 | os: ubuntu-latest 23 | rust: nightly 24 | target: x86_64-unknown-linux-gnu 25 | - build: arm-gnueabi 26 | os: ubuntu-latest 27 | rust: stable 28 | target: arm-unknown-linux-gnueabi 29 | packages: "gcc-arm-linux-gnueabi libc6-armel-cross libc6-dev-armel-cross" 30 | - build: arm-gnueabihf 31 | os: ubuntu-latest 32 | rust: stable 33 | target: arm-unknown-linux-gnueabihf 34 | packages: "gcc-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross" 35 | steps: 36 | - run: sudo apt install ${{ matrix.packages }} 37 | - uses: actions/checkout@v1 38 | with: 39 | submodules: true 40 | - name: Install Rust 41 | run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }} && rustup target add ${{ matrix.target }} 42 | shell: bash 43 | - run: cargo build --target ${{ matrix.target }} --verbose 44 | - run: cargo build --target ${{ matrix.target }} --verbose --no-default-features 45 | - run: cargo build --target ${{ matrix.target }} --verbose --all-features 46 | - run: sudo --preserve-env env "PATH=$PATH" cargo test --verbose 47 | if: contains(matrix.target, 'x86_64') 48 | - run: sudo --preserve-env env "PATH=$PATH" cargo test --all-features --verbose 49 | if: contains(matrix.target, 'x86_64') 50 | 51 | rustfmt: 52 | name: Rustfmt 53 | runs-on: ubuntu-latest 54 | steps: 55 | - uses: actions/checkout@v1 56 | - name: Install Rust 57 | run: rustup update stable && rustup default stable && rustup component add rustfmt 58 | - run: cargo fmt -- --check 59 | 60 | publish_docs: 61 | name: Publish Documentation 62 | runs-on: ubuntu-latest 63 | steps: 64 | - uses: actions/checkout@v1 65 | with: 66 | submodules: true 67 | - name: Install Rust 68 | run: rustup update stable && rustup default stable 69 | - name: Build documentation 70 | run: cargo doc --no-deps --all-features 71 | - name: Publish documentation 72 | run: | 73 | cd target/doc 74 | git init 75 | git add . 76 | git -c user.name='ci' -c user.email='ci' commit -m init 77 | git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages 78 | if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.swp 4 | *.swo 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "evdev-sys/libevdev"] 2 | path = evdev-sys/libevdev 3 | url = https://gitlab.freedesktop.org/libevdev/libevdev.git 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "evdev-rs" 3 | version = "0.6.1" 4 | authors = ["Nayan Deshmukh "] 5 | license = "MIT/Apache-2.0" 6 | keywords = ["evdev"] 7 | readme = "README.md" 8 | repository = "https://github.com/ndesh26/evdev-rs" 9 | homepage = "https://github.com/ndesh26/evdev-rs" 10 | edition = "2018" 11 | description = """ 12 | Bindings to libevdev for interacting with evdev devices. It moves the 13 | common tasks when dealing with evdev devices into a library and provides 14 | a library interface to the callers, thus avoiding erroneous ioctls, etc. 15 | """ 16 | 17 | [features] 18 | default = [] 19 | # Use features from libevdev version 1.10 and greater (libevdev_property_disable) 20 | libevdev-1-10 = ["evdev-sys/libevdev-1-10"] 21 | 22 | [dependencies] 23 | serde = { version = "1.0", default-features = false, features=["derive"], optional = true } 24 | evdev-sys = { path = "evdev-sys", version = "0.2.5" } 25 | libc = "0.2.67" 26 | bitflags = "2.4.1" 27 | log = "0.4.8" 28 | 29 | [package.metadata.docs.rs] 30 | features = ["serde"] 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # evdev-rs 2 | 3 | [![Build Status](https://travis-ci.org/ndesh26/evdev-rs.svg?branch=master)](https://travis-ci.org/ndesh26/evdev-rs) 4 | [![Latest Version](https://img.shields.io/crates/v/evdev-rs.svg)](https://crates.io/crates/evdev-rs) 5 | [![Documentation](https://docs.rs/evdev-rs/badge.svg)](https://docs.rs/evdev-rs) 6 | 7 | A Rust wrapper for libevdev 8 | 9 | ```toml 10 | # Cargo.toml 11 | [dependencies] 12 | evdev-rs = "0.6.1" 13 | ``` 14 | 15 | to enable serialization support, enable the feature "serde" 16 | ```toml 17 | # Cargo.toml 18 | [dependencies] 19 | evdev-rs = { version = "0.6.1", features = ["serde"] } 20 | ``` 21 | 22 | With a newer libevdev version (>= 1.10) enable the feature `libevdev-1-10` to 23 | allow disabling a property. It also extends the `Enable` trait to `InputProp`, 24 | enabling the use of `enable()`, `disable()` and `has()` for `InputProp` as well. 25 | 26 | Why a libevdev wrapper? 27 | ----------------------- 28 | The evdev protocol is simple, but quirky, with a couple of behaviors that 29 | are non-obvious. libevdev transparently handles some of those quirks. 30 | 31 | The [evdev](https://github.com/emberian/evdev) crate is an implementation 32 | of libevdev in Rust which provides most of the same features. 33 | 34 | `evdev-rs` crate closely follows libevdev and hence enjoys all the complex handling 35 | that libevdev does. Some of the things that libevdev handles transparently, which may or 36 | may not be in `evdev` crate: 37 | 38 | * handling of fake multitouch devices 39 | * synching of slots and per-slot state 40 | * transparent generation of missing tracking ids after SYN_DROPPED 41 | * various boundary checks with defined error codes if you request invalid data 42 | (e.g. event codes that don't exist on the device) 43 | * fd swapping on the same context 44 | * disabling/enabling events on a per-context basis, so you can disable/enable ABS_FOO 45 | and then not care about quirks in the client-side code. 46 | 47 | Development 48 | ----------- 49 | 50 | `src/enums.rs` can be generated by running `./tools/make-enums.sh`. 51 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ## These function need to implemented in evdev-rs 2 | 3 | * `int libevdev_kernel_set_led_values(struct libevdev *dev, ...);` 4 | 5 | ## We need to define this functions types and the corresponding functions 6 | 7 | * libevdev_log_func_t 8 | * `void libevdev_set_log_function(libevdev_log_func_t logfunc, void *data);` 9 | * libevdev_device_log_func_t 10 | * `void libevdev_set_device_log_function(struct libevdev *dev, 11 | libevdev_device_log_func_t logfunc, 12 | enum libevdev_log_priority priority, 13 | void *data);` 14 | 15 | ## Add Documentation 16 | -------------------------------------------------------------------------------- /evdev-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "evdev-sys" 3 | version = "0.2.5" 4 | authors = ["Nayan Deshmukh Option<(u32, u32, u32)> { 10 | let mut major_minor_patch = ver_str 11 | .split(".") 12 | .map(|str| str.parse::().unwrap()); 13 | let major = major_minor_patch.next()?; 14 | let minor = major_minor_patch.next()?; 15 | let patch = major_minor_patch.next()?; 16 | Some((major, minor, patch)) 17 | } 18 | 19 | fn main() -> Result<(), Box> { 20 | if env::var_os("TARGET") == env::var_os("HOST") { 21 | let mut config = pkg_config::Config::new(); 22 | config.print_system_libs(false); 23 | 24 | match config.probe("libevdev") { 25 | Ok(lib) => { 26 | // panic if feature 1.10 is enabled and the installed library 27 | // is older than 1.10 28 | #[cfg(feature = "libevdev-1-10")] 29 | { 30 | let (major, minor, patch) = parse_version(&lib.version) 31 | .expect("Could not parse version information"); 32 | assert_eq!(major, 1, "evdev-rs works only with libevdev 1"); 33 | assert!(minor >= 10, 34 | "Feature libevdev-1-10 was enabled, when compiling \ 35 | for a system with libevdev version {}.{}.{}", 36 | major, 37 | minor, 38 | patch, 39 | ); 40 | } 41 | for path in &lib.include_paths { 42 | println!("cargo:include={}", path.display()); 43 | } 44 | return Ok(()); 45 | } 46 | Err(e) => eprintln!( 47 | "Couldn't find libevdev from pkgconfig ({:?}), \ 48 | compiling it from source...", 49 | e 50 | ), 51 | }; 52 | } 53 | 54 | if !Path::new("libevdev/.git").exists() { 55 | let mut download = Command::new("git"); 56 | download.args(&["submodule", "update", "--init", "--depth", "1"]); 57 | run_ignore_error(&mut download)?; 58 | } 59 | 60 | let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); 61 | let src = env::current_dir()?; 62 | let mut cp = Command::new("cp"); 63 | cp.arg("-r") 64 | .arg(&src.join("libevdev/")) 65 | .arg(&dst) 66 | .current_dir(&src); 67 | run(&mut cp)?; 68 | 69 | println!("cargo:rustc-link-search={}/lib", dst.display()); 70 | println!("cargo:root={}", dst.display()); 71 | println!("cargo:include={}/include", dst.display()); 72 | println!("cargo:rerun-if-changed=libevdev"); 73 | 74 | println!("cargo:rustc-link-lib=static=evdev"); 75 | let cfg = cc::Build::new(); 76 | let compiler = cfg.get_compiler(); 77 | 78 | if !&dst.join("build").exists() { 79 | fs::create_dir(&dst.join("build"))?; 80 | } 81 | 82 | let mut autogen = Command::new("sh"); 83 | let mut cflags = OsString::new(); 84 | for arg in compiler.args() { 85 | cflags.push(arg); 86 | cflags.push(" "); 87 | } 88 | autogen 89 | .env("CC", compiler.path()) 90 | .env("CFLAGS", cflags) 91 | .current_dir(&dst.join("build")) 92 | .arg( 93 | dst.join("libevdev/autogen.sh") 94 | .to_str() 95 | .unwrap() 96 | .replace("C:\\", "/c/") 97 | .replace("\\", "/"), 98 | ); 99 | if let Ok(h) = env::var("HOST") { 100 | autogen.arg(format!("--host={}", h)); 101 | } 102 | if let Ok(t) = env::var("TARGET") { 103 | autogen.arg(format!("--target={}", t)); 104 | } 105 | autogen.arg(format!("--prefix={}", sanitize_sh(&dst))); 106 | run(&mut autogen)?; 107 | 108 | let mut make = Command::new("make"); 109 | make.arg(&format!("-j{}", env::var("NUM_JOBS").unwrap())) 110 | .current_dir(&dst.join("build")); 111 | run(&mut make)?; 112 | 113 | let mut install = Command::new("make"); 114 | install.arg("install").current_dir(&dst.join("build")); 115 | run(&mut install)?; 116 | Ok(()) 117 | } 118 | 119 | fn run(cmd: &mut Command) -> std::io::Result<()> { 120 | println!("running: {:?}", cmd); 121 | assert!(cmd.status()?.success()); 122 | Ok(()) 123 | } 124 | 125 | fn run_ignore_error(cmd: &mut Command) -> std::io::Result<()> { 126 | println!("running: {:?}", cmd); 127 | let _ = cmd.status(); 128 | Ok(()) 129 | } 130 | 131 | fn sanitize_sh(path: &Path) -> String { 132 | let path = path.to_str().unwrap().replace("\\", "/"); 133 | return change_drive(&path).unwrap_or(path); 134 | 135 | fn change_drive(s: &str) -> Option { 136 | let mut ch = s.chars(); 137 | let drive = ch.next().unwrap_or('C'); 138 | if ch.next() != Some(':') { 139 | return None; 140 | } 141 | if ch.next() != Some('/') { 142 | return None; 143 | } 144 | Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..])) 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /evdev-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(bad_style)] 2 | #![allow(dead_code)] 3 | #![allow(improper_ctypes)] 4 | 5 | use libc::{c_char, c_int, c_uint, c_void, size_t}; 6 | pub use libc::{input_absinfo, input_event, timeval}; 7 | 8 | pub type __enum_ty = libc::c_int; 9 | pub type libevdev_read_flag = __enum_ty; 10 | pub type libevdev_log_priority = __enum_ty; 11 | pub type libevdev_grab_mode = __enum_ty; 12 | pub type libevdev_read_status = __enum_ty; 13 | pub type libevdev_led_value = __enum_ty; 14 | pub type libevdev_uinput_open_mode = __enum_ty; 15 | 16 | pub const LIBEVDEV_READ_FLAG_SYNC: libevdev_read_flag = 1; 17 | pub const LIBEVDEV_READ_FLAG_NORMAL: libevdev_read_flag = 2; 18 | pub const LIBEVDEV_READ_FLAG_FORCE_SYNC: libevdev_read_flag = 4; 19 | pub const LIBEVDEV_READ_FLAG_BLOCKING: libevdev_read_flag = 8; 20 | 21 | pub const LIBEVDEV_LOG_ERROR: libevdev_log_priority = 10; 22 | pub const LIBEVDEV_LOG_INFO: libevdev_log_priority = 20; 23 | pub const LIBEVDEV_LOG_DEBUG: libevdev_log_priority = 30; 24 | 25 | pub const LIBEVDEV_GRAB: libevdev_grab_mode = 3; 26 | pub const LIBEVDEV_UNGRAB: libevdev_grab_mode = 4; 27 | 28 | pub const LIBEVDEV_READ_STATUS_SUCCESS: libevdev_read_status = 0; 29 | pub const LIBEVDEV_READ_STATUS_SYNC: libevdev_read_status = 1; 30 | 31 | pub const LIBEVDEV_LED_ON: libevdev_led_value = 3; 32 | pub const LIBEVDEV_LED_OFF: libevdev_led_value = 4; 33 | 34 | pub const LIBEVDEV_UINPUT_OPEN_MANAGED: libevdev_uinput_open_mode = -2; 35 | 36 | pub enum libevdev {} 37 | pub enum libevdev_uinput {} 38 | 39 | #[repr(C)] 40 | pub struct va_list { 41 | // TODO 42 | } 43 | 44 | type libevdev_log_func_t = extern "C" fn( 45 | *const libevdev, 46 | *mut c_void, 47 | *const c_char, 48 | c_int, 49 | *const c_char, 50 | *const c_char, 51 | va_list, 52 | ); 53 | 54 | type libevdev_device_log_func_t = extern "C" fn( 55 | *const libevdev, 56 | c_int, 57 | *mut c_void, 58 | *const c_char, 59 | c_int, 60 | *const c_char, 61 | *const c_char, 62 | va_list, 63 | ); 64 | 65 | extern "C" { 66 | pub fn libevdev_new() -> *mut libevdev; 67 | pub fn libevdev_new_from_fd(fd: c_int, ctx: *mut *mut libevdev) -> c_int; 68 | pub fn libevdev_free(ctx: *mut libevdev); 69 | pub fn libevdev_set_log_function(logfunc: libevdev_log_func_t, data: *mut c_void); 70 | pub fn libevdev_set_log_priority(priority: libevdev_log_priority); 71 | pub fn libevdev_get_log_priority() -> libevdev_log_priority; 72 | pub fn libevdev_set_device_log_function( 73 | ctx: *mut libevdev, 74 | logfunc: libevdev_device_log_func_t, 75 | priority: libevdev_log_priority, 76 | data: *mut c_void, 77 | ); 78 | pub fn libevdev_grab(ctx: *mut libevdev, grab: libevdev_grab_mode) -> c_int; 79 | pub fn libevdev_set_fd(ctx: *mut libevdev, fd: c_int) -> c_int; 80 | pub fn libevdev_change_fd(ctx: *mut libevdev, fd: c_int) -> c_int; 81 | pub fn libevdev_get_fd(ctx: *mut libevdev) -> c_int; 82 | pub fn libevdev_next_event( 83 | ctx: *mut libevdev, 84 | flags: c_uint, 85 | ev: *mut input_event, 86 | ) -> c_int; 87 | pub fn libevdev_has_event_pending(ctx: *mut libevdev) -> c_int; 88 | pub fn libevdev_get_name(ctx: *const libevdev) -> *const c_char; 89 | pub fn libevdev_set_name(ctx: *mut libevdev, name: *const c_char); 90 | pub fn libevdev_get_phys(ctx: *const libevdev) -> *const c_char; 91 | pub fn libevdev_set_phys(ctx: *mut libevdev, phys: *const c_char); 92 | pub fn libevdev_get_uniq(ctx: *const libevdev) -> *const c_char; 93 | pub fn libevdev_set_uniq(ctx: *mut libevdev, uniq: *const c_char); 94 | pub fn libevdev_get_id_product(ctx: *const libevdev) -> c_int; 95 | pub fn libevdev_set_id_product(ctx: *mut libevdev, product_id: c_int); 96 | pub fn libevdev_get_id_vendor(ctx: *const libevdev) -> c_int; 97 | pub fn libevdev_set_id_vendor(ctx: *mut libevdev, vendor_id: c_int); 98 | pub fn libevdev_get_id_bustype(ctx: *const libevdev) -> c_int; 99 | pub fn libevdev_set_id_bustype(ctx: *mut libevdev, bustype: c_int); 100 | pub fn libevdev_get_id_version(ctx: *const libevdev) -> c_int; 101 | pub fn libevdev_set_id_version(ctx: *mut libevdev, version: c_int); 102 | pub fn libevdev_get_driver_version(ctx: *const libevdev) -> c_int; 103 | pub fn libevdev_has_property(ctx: *const libevdev, prop: c_uint) -> c_int; 104 | pub fn libevdev_enable_property(ctx: *mut libevdev, prop: c_uint) -> c_int; 105 | #[cfg(feature = "libevdev-1-10")] 106 | pub fn libevdev_disable_property (ctx: *mut libevdev, prop: c_uint) -> c_int; 107 | pub fn libevdev_has_event_type(ctx: *const libevdev, type_: c_uint) -> c_int; 108 | pub fn libevdev_has_event_code( 109 | ctx: *const libevdev, 110 | type_: c_uint, 111 | code: c_uint, 112 | ) -> c_int; 113 | pub fn libevdev_get_abs_minimum(ctx: *const libevdev, code: c_uint) -> c_int; 114 | pub fn libevdev_get_abs_maximum(ctx: *const libevdev, code: c_uint) -> c_int; 115 | pub fn libevdev_get_abs_fuzz(ctx: *const libevdev, code: c_uint) -> c_int; 116 | pub fn libevdev_get_abs_flat(ctx: *const libevdev, code: c_uint) -> c_int; 117 | pub fn libevdev_get_abs_resolution(ctx: *const libevdev, code: c_uint) -> c_int; 118 | pub fn libevdev_get_abs_info( 119 | ctx: *const libevdev, 120 | code: c_uint, 121 | ) -> *const input_absinfo; 122 | pub fn libevdev_get_event_value( 123 | ctx: *const libevdev, 124 | type_: c_uint, 125 | code: c_uint, 126 | ) -> c_int; 127 | pub fn libevdev_set_event_value( 128 | ctx: *mut libevdev, 129 | type_: c_uint, 130 | code: c_uint, 131 | value: c_int, 132 | ) -> c_int; 133 | pub fn libevdev_fetch_event_value( 134 | ctx: *const libevdev, 135 | type_: c_uint, 136 | code: c_uint, 137 | value: *mut c_int, 138 | ) -> c_int; 139 | pub fn libevdev_get_slot_value( 140 | ctx: *const libevdev, 141 | slot: c_uint, 142 | code: c_uint, 143 | ) -> c_int; 144 | pub fn libevdev_set_slot_value( 145 | ctx: *mut libevdev, 146 | slot: c_uint, 147 | code: c_uint, 148 | value: c_int, 149 | ) -> c_int; 150 | pub fn libevdev_fetch_slot_value( 151 | ctx: *const libevdev, 152 | slot: c_uint, 153 | code: c_uint, 154 | value: *mut c_int, 155 | ) -> c_int; 156 | pub fn libevdev_get_num_slots(ctx: *const libevdev) -> c_int; 157 | pub fn libevdev_get_current_slot(ctx: *const libevdev) -> c_int; 158 | pub fn libevdev_set_abs_minimum(ctx: *mut libevdev, code: c_uint, min: c_int); 159 | pub fn libevdev_set_abs_maximum(ctx: *mut libevdev, code: c_uint, max: c_int); 160 | pub fn libevdev_set_abs_fuzz(ctx: *mut libevdev, code: c_uint, fuzz: c_int); 161 | pub fn libevdev_set_abs_flat(ctx: *mut libevdev, code: c_uint, flat: c_int); 162 | pub fn libevdev_set_abs_resolution( 163 | ctx: *mut libevdev, 164 | code: c_uint, 165 | resolution: c_int, 166 | ); 167 | pub fn libevdev_set_abs_info( 168 | ctx: *mut libevdev, 169 | code: c_uint, 170 | abs: *const input_absinfo, 171 | ); 172 | pub fn libevdev_enable_event_type(ctx: *mut libevdev, type_: c_uint) -> c_int; 173 | pub fn libevdev_disable_event_type(ctx: *mut libevdev, type_: c_uint) -> c_int; 174 | pub fn libevdev_enable_event_code( 175 | ctx: *mut libevdev, 176 | type_: c_uint, 177 | code: c_uint, 178 | data: *const c_void, 179 | ) -> c_int; 180 | pub fn libevdev_disable_event_code( 181 | ctx: *mut libevdev, 182 | type_: c_uint, 183 | code: c_uint, 184 | ) -> c_int; 185 | pub fn libevdev_kernel_set_abs_info( 186 | ctx: *mut libevdev, 187 | code: c_uint, 188 | abs: *const input_absinfo, 189 | ) -> c_int; 190 | pub fn libevdev_kernel_set_led_value( 191 | ctx: *mut libevdev, 192 | code: c_uint, 193 | value: libevdev_led_value, 194 | ) -> c_int; 195 | pub fn libevdev_kernel_set_led_values(ctx: *mut libevdev, ...) -> c_int; 196 | pub fn libevdev_set_clock_id(ctx: *mut libevdev, clockid: c_int) -> c_int; 197 | pub fn libevdev_event_is_type(ev: *const input_event, type_: c_uint) -> c_int; 198 | pub fn libevdev_event_is_code( 199 | ev: *const input_event, 200 | type_: c_uint, 201 | code: c_uint, 202 | ) -> c_int; 203 | pub fn libevdev_event_type_get_name(type_: c_uint) -> *const c_char; 204 | pub fn libevdev_event_code_get_name(type_: c_uint, code: c_uint) -> *const c_char; 205 | pub fn libevdev_property_get_name(prop: c_uint) -> *const c_char; 206 | pub fn libevdev_event_type_get_max(type_: c_uint) -> c_int; 207 | pub fn libevdev_event_type_from_name(name: *const c_char) -> c_int; 208 | pub fn libevdev_event_type_from_name_n(name: *const c_char, len: size_t) -> c_int; 209 | pub fn libevdev_event_code_from_name(type_: c_uint, name: *const c_char) -> c_int; 210 | pub fn libevdev_event_code_from_name_n( 211 | type_: c_uint, 212 | name: *const c_char, 213 | len: size_t, 214 | ) -> c_int; 215 | pub fn libevdev_property_from_name(name: *const c_char) -> c_int; 216 | pub fn libevdev_property_from_name_n(name: *const c_char, len: size_t) -> c_int; 217 | pub fn libevdev_get_repeat( 218 | ctx: *const libevdev, 219 | delay: *mut c_int, 220 | period: *mut c_int, 221 | ) -> c_int; 222 | pub fn libevdev_uinput_create_from_device( 223 | ctx: *const libevdev, 224 | uinput_fd: c_int, 225 | uinput_dev: *mut *mut libevdev_uinput, 226 | ) -> c_int; 227 | pub fn libevdev_uinput_destroy(uinput_dev: *mut libevdev_uinput); 228 | pub fn libevdev_uinput_get_devnode(uinput_dev: *mut libevdev_uinput) 229 | -> *const c_char; 230 | pub fn libevdev_uinput_get_fd(uinput_dev: *const libevdev_uinput) -> c_int; 231 | pub fn libevdev_uinput_get_syspath(uinput_dev: *mut libevdev_uinput) 232 | -> *const c_char; 233 | pub fn libevdev_uinput_write_event( 234 | uinput_dev: *const libevdev_uinput, 235 | type_: c_uint, 236 | code: c_uint, 237 | value: c_int, 238 | ) -> c_int; 239 | } 240 | -------------------------------------------------------------------------------- /examples/evtest.rs: -------------------------------------------------------------------------------- 1 | use evdev_rs::enums::*; 2 | use evdev_rs::*; 3 | use std::fs::OpenOptions; 4 | use std::io; 5 | use std::io::ErrorKind; 6 | use std::io::Read; 7 | use std::os::unix::fs::OpenOptionsExt; 8 | 9 | fn usage() { 10 | println!("Usage: evtest /path/to/device"); 11 | } 12 | 13 | fn print_abs_bits(dev: &Device, axis: &EV_ABS) { 14 | let code = EventCode::EV_ABS(axis.clone()); 15 | 16 | if !dev.has(code) { 17 | return; 18 | } 19 | 20 | let abs = dev.abs_info(&code).unwrap(); 21 | 22 | println!("\tValue\t{}", abs.value); 23 | println!("\tMin\t{}", abs.minimum); 24 | println!("\tMax\t{}", abs.maximum); 25 | if abs.fuzz != 0 { 26 | println!("\tFuzz\t{}", abs.fuzz); 27 | } 28 | if abs.flat != 0 { 29 | println!("\tFlat\t{}", abs.flat); 30 | } 31 | if abs.resolution != 0 { 32 | println!("\tResolution\t{}", abs.resolution); 33 | } 34 | } 35 | 36 | fn print_code_bits(dev: &Device, ev_type: &EventType) { 37 | for code in EventCodeIterator::new(ev_type) { 38 | if !dev.has(code) { 39 | continue; 40 | } 41 | 42 | println!(" Event code: {}", code); 43 | match code { 44 | EventCode::EV_ABS(k) => print_abs_bits(dev, &k), 45 | _ => (), 46 | } 47 | } 48 | } 49 | 50 | fn print_bits(dev: &Device) { 51 | println!("Supported events:"); 52 | 53 | for ev_type in EventTypeIterator::new() { 54 | if dev.has(ev_type) { 55 | println!(" Event type: {} ", ev_type); 56 | } 57 | 58 | match ev_type { 59 | EventType::EV_KEY 60 | | EventType::EV_REL 61 | | EventType::EV_ABS 62 | | EventType::EV_LED => print_code_bits(dev, &ev_type), 63 | _ => (), 64 | } 65 | } 66 | } 67 | 68 | fn print_props(dev: &Device) { 69 | println!("Properties:"); 70 | 71 | for input_prop in InputPropIterator::new() { 72 | if dev.has_property(&input_prop) { 73 | println!(" Property type: {}", input_prop); 74 | } 75 | } 76 | } 77 | 78 | fn print_event(ev: &InputEvent) { 79 | match ev.event_code { 80 | EventCode::EV_SYN(_) => println!( 81 | "Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++", 82 | ev.time.tv_sec, 83 | ev.time.tv_usec, 84 | ev.event_type().unwrap() 85 | ), 86 | _ => println!( 87 | "Event: time {}.{}, type {} , code {} , value {}", 88 | ev.time.tv_sec, 89 | ev.time.tv_usec, 90 | ev.event_type() 91 | .map(|ev_type| format!("{}", ev_type)) 92 | .unwrap_or("None".to_owned()), 93 | ev.event_code, 94 | ev.value 95 | ), 96 | } 97 | } 98 | 99 | fn print_sync_dropped_event(ev: &InputEvent) { 100 | print!("SYNC DROPPED: "); 101 | print_event(ev); 102 | } 103 | 104 | fn main() { 105 | let mut args = std::env::args(); 106 | 107 | if args.len() != 2 { 108 | usage(); 109 | std::process::exit(1); 110 | } 111 | 112 | let path = &args.nth(1).unwrap(); 113 | let mut file = OpenOptions::new() 114 | .read(true) 115 | .write(true) 116 | .custom_flags(libc::O_NONBLOCK) 117 | .open(path) 118 | .unwrap(); 119 | let mut buffer = Vec::new(); 120 | let result = file.read_to_end(&mut buffer); 121 | if result.is_ok() || result.unwrap_err().kind() != ErrorKind::WouldBlock { 122 | println!("Failed to drain pending events from device file"); 123 | } 124 | 125 | let u_d = UninitDevice::new().unwrap(); 126 | let d = u_d.set_file(file).unwrap(); 127 | 128 | println!( 129 | "Input device ID: bus 0x{:x} vendor 0x{:x} product 0x{:x}", 130 | d.bustype(), 131 | d.vendor_id(), 132 | d.product_id() 133 | ); 134 | println!("Evdev version: {:x}", d.driver_version()); 135 | println!("Input device name: \"{}\"", d.name().unwrap_or("")); 136 | println!("Phys location: {}", d.phys().unwrap_or("")); 137 | println!("Uniq identifier: {}", d.uniq().unwrap_or("")); 138 | 139 | print_bits(&d); 140 | print_props(&d); 141 | 142 | let mut a: io::Result<(ReadStatus, InputEvent)>; 143 | loop { 144 | a = d.next_event(ReadFlag::NORMAL); 145 | if a.is_ok() { 146 | let mut result = a.ok().unwrap(); 147 | match result.0 { 148 | ReadStatus::Sync => { 149 | println!("::::::::::::::::::::: dropped ::::::::::::::::::::::"); 150 | while result.0 == ReadStatus::Sync { 151 | print_sync_dropped_event(&result.1); 152 | a = d.next_event(ReadFlag::SYNC); 153 | if a.is_ok() { 154 | result = a.ok().unwrap(); 155 | } else { 156 | break; 157 | } 158 | } 159 | println!("::::::::::::::::::::: re-synced ::::::::::::::::::::"); 160 | } 161 | ReadStatus::Success => print_event(&result.1), 162 | } 163 | } else { 164 | let err = a.err().unwrap(); 165 | match err.raw_os_error() { 166 | Some(libc::EAGAIN) => continue, 167 | _ => { 168 | println!("{}", err); 169 | break; 170 | } 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /examples/vmouse.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | 3 | use evdev_rs::enums::{BusType, EventCode, EventType, EV_KEY, EV_REL, EV_SYN}; 4 | use evdev_rs::{Device, DeviceWrapper, InputEvent, ReadFlag, UInputDevice, UninitDevice}; 5 | 6 | const MOUSE_STEP_X: i32 = 10; 7 | const MOUSE_STEP_Y: i32 = 10; 8 | 9 | fn main() -> Result<(), std::io::Error> { 10 | // Parse command line arguments 11 | let mut args = std::env::args(); 12 | 13 | if args.len() != 2 { 14 | let n = args.nth(0).unwrap(); 15 | println!("Usage: `{} DEVICE`, eg. `{} /dev/input/event13`", n, n); 16 | std::process::exit(1); 17 | } 18 | 19 | let device = &args.nth(1).unwrap(); 20 | 21 | // Connect to real keyboard 22 | let f = File::open(device)?; 23 | let d = Device::new_from_file(f)?; 24 | 25 | if let Some(n) = d.name() { 26 | println!( 27 | "Connected to device: '{}' ({:04x}:{:04x})", 28 | n, 29 | d.vendor_id(), 30 | d.product_id() 31 | ); 32 | } 33 | 34 | // Create virtual device 35 | let u = UninitDevice::new().unwrap(); 36 | 37 | // Setup device 38 | // per: https://01.org/linuxgraphics/gfx-docs/drm/input/uinput.html#mouse-movements 39 | 40 | u.set_name("Virtual Mouse"); 41 | u.set_bustype(BusType::BUS_USB as u16); 42 | u.set_vendor_id(0xabcd); 43 | u.set_product_id(0xefef); 44 | 45 | // Note mouse keys have to be enabled for this to be detected 46 | // as a usable device, see: https://stackoverflow.com/a/64559658/6074942 47 | u.enable(EventCode::EV_KEY(EV_KEY::BTN_LEFT))?; 48 | u.enable(EventCode::EV_KEY(EV_KEY::BTN_RIGHT))?; 49 | 50 | u.enable(EventCode::EV_REL(EV_REL::REL_X))?; 51 | u.enable(EventCode::EV_REL(EV_REL::REL_Y))?; 52 | 53 | u.enable(EventCode::EV_SYN(EV_SYN::SYN_REPORT))?; 54 | 55 | // Attempt to create UInputDevice from UninitDevice 56 | let v = UInputDevice::create_from_device(&u)?; 57 | 58 | loop { 59 | // Fetch keyboard events 60 | let (_status, event) = d.next_event(ReadFlag::NORMAL | ReadFlag::BLOCKING)?; 61 | 62 | // Map these to mouse events 63 | println!("Event: {:?}", event); 64 | 65 | // Map direction keys to mouse events 66 | let e = match event.event_code { 67 | EventCode::EV_KEY(EV_KEY::KEY_RIGHT) => Some((EV_REL::REL_X, MOUSE_STEP_X)), 68 | EventCode::EV_KEY(EV_KEY::KEY_LEFT) => Some((EV_REL::REL_X, -MOUSE_STEP_X)), 69 | EventCode::EV_KEY(EV_KEY::KEY_UP) => Some((EV_REL::REL_Y, -MOUSE_STEP_Y)), 70 | EventCode::EV_KEY(EV_KEY::KEY_DOWN) => Some((EV_REL::REL_Y, MOUSE_STEP_Y)), 71 | _ => None, 72 | }; 73 | 74 | // Write mapped event 75 | if let Some((e, n)) = e { 76 | v.write_event(&InputEvent { 77 | time: event.time, 78 | event_code: EventCode::EV_REL(e), 79 | value: n, 80 | })?; 81 | 82 | v.write_event(&InputEvent { 83 | time: event.time, 84 | event_code: EventCode::EV_SYN(EV_SYN::SYN_REPORT), 85 | value: 0, 86 | })?; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width=90 -------------------------------------------------------------------------------- /src/device.rs: -------------------------------------------------------------------------------- 1 | use crate::{AbsInfo, GrabMode, InputEvent, LedState, ReadFlag, ReadStatus, TimeVal}; 2 | use libc::{c_int, c_uint, c_void}; 3 | use std::ffi::CString; 4 | use std::fs::File; 5 | use std::fs::OpenOptions; 6 | use std::io::Read; 7 | use std::mem::ManuallyDrop; 8 | use std::os::unix::fs::OpenOptionsExt; 9 | use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; 10 | use std::path::Path; 11 | use std::{io, ptr}; 12 | 13 | use crate::enums::*; 14 | use crate::util::*; 15 | 16 | use evdev_sys as raw; 17 | 18 | /// Types that can be enabled on a DeviceWrapper (i.e. buttons, keys, relative motion) 19 | /// 20 | /// Generally this method will not be called directly, but will insted be called through [Device::enable()](crate::Device::enable) 21 | /// 22 | /// ```rust 23 | /// # use evdev_rs::{UninitDevice, DeviceWrapper, Enable, enums::{EventCode, EV_REL::REL_X}}; 24 | /// let dev = UninitDevice::new().expect("Device creation failed"); 25 | /// dev.enable(EventCode::EV_REL(REL_X)).expect("Enable failed"); 26 | /// ``` 27 | /// 28 | /// If you need to enable a EV_ABS or EV_REP event code, use 29 | /// [enable_event_code](crate::Device::enable_event_code), as this 30 | /// implementation doesn't pass EV_ABS data. 31 | pub trait Enable { 32 | fn enable(&self, device: &D) -> io::Result<()>; 33 | fn disable(&self, device: &D) -> io::Result<()>; 34 | fn has(&self, device: &D) -> bool; 35 | } 36 | 37 | #[cfg(feature = "libevdev-1-10")] 38 | impl Enable for InputProp { 39 | fn enable(&self, device: &D) -> io::Result<()> { 40 | device.enable_property(self) 41 | } 42 | fn disable(&self, device: &D) -> io::Result<()> { 43 | device.disable_property(self) 44 | } 45 | fn has(&self, device: &D) -> bool { 46 | device.has_property(self) 47 | } 48 | } 49 | 50 | impl Enable for EventType { 51 | fn enable(&self, device: &D) -> io::Result<()> { 52 | device.enable_event_type(self) 53 | } 54 | fn disable(&self, device: &D) -> io::Result<()> { 55 | device.disable_event_type(self) 56 | } 57 | fn has(&self, device: &D) -> bool { 58 | device.has_event_type(self) 59 | } 60 | } 61 | 62 | impl Enable for EventCode { 63 | fn enable(&self, device: &D) -> io::Result<()> { 64 | device.enable_event_code(self, None) 65 | } 66 | fn disable(&self, device: &D) -> io::Result<()> { 67 | device.disable_event_code(self) 68 | } 69 | fn has(&self, device: &D) -> bool { 70 | device.has_event_code(self) 71 | } 72 | } 73 | 74 | /// Extra data for use with enable_event_code 75 | #[derive(Clone, Copy, Debug)] 76 | pub enum EnableCodeData { 77 | AbsInfo(AbsInfo), 78 | RepInfo(i32), 79 | } 80 | 81 | /// Abstraction over structs which contain an inner `*mut libevdev` 82 | pub trait DeviceWrapper: Sized { 83 | fn raw(&self) -> *mut raw::libevdev; 84 | 85 | /// Forcibly enable an EventType/InputProp on this device, even if the underlying 86 | /// device does not support it. While this cannot make the device actually 87 | /// report such events, it will now return true for has(). 88 | /// 89 | /// This is a local modification only affecting only this representation of 90 | /// this device. 91 | fn enable(&self, e: E) -> io::Result<()> { 92 | e.enable(self) 93 | } 94 | 95 | /// Enables this property, a call to `set_file` will overwrite any previously set values 96 | /// 97 | /// Note: Please use the `enable` function instead. This function is only 98 | /// available for the sake of maintaining compatibility with libevdev. 99 | fn enable_property(&self, prop: &InputProp) -> io::Result<()> { 100 | let result = 101 | unsafe { raw::libevdev_enable_property(self.raw(), *prop as c_uint) as i32 }; 102 | 103 | match result { 104 | 0 => Ok(()), 105 | error => Err(io::Error::from_raw_os_error(-error)), 106 | } 107 | } 108 | 109 | /// Forcibly enable an event type on this device, even if the underlying 110 | /// device does not support it. While this cannot make the device actually 111 | /// report such events, it will now return true for libevdev_has_event_type(). 112 | /// 113 | /// This is a local modification only affecting only this representation of 114 | /// this device. 115 | /// 116 | /// Note: Please use the `enable` function instead. This function is only 117 | /// available for the sake of maintaining compatibility with libevdev. 118 | fn enable_event_type(&self, ev_type: &EventType) -> io::Result<()> { 119 | let result = 120 | unsafe { raw::libevdev_enable_event_type(self.raw(), *ev_type as c_uint) }; 121 | 122 | match result { 123 | 0 => Ok(()), 124 | error => Err(io::Error::from_raw_os_error(-error)), 125 | } 126 | } 127 | 128 | /// Forcibly enable an event type on this device, even if the underlying 129 | /// device does not support it. While this cannot make the device actually 130 | /// report such events, it will now return true for libevdev_has_event_code(). 131 | /// 132 | /// The last argument depends on the type and code: 133 | /// If type is EV_ABS, data must be a pointer to a struct input_absinfo 134 | /// containing the data for this axis. 135 | /// If type is EV_REP, data must be a pointer to a int containing the data 136 | /// for this axis. 137 | /// For all other types, the argument must be `None`. 138 | /// 139 | /// Note: Please use the `enable` function instead. This function is only 140 | /// available for the sake of maintaining compatibility with libevdev. 141 | fn enable_event_code( 142 | &self, 143 | ev_code: &EventCode, 144 | data: Option, 145 | ) -> io::Result<()> { 146 | let data = 147 | match ev_code { 148 | EventCode::EV_ABS(_) => match data { 149 | Some(EnableCodeData::AbsInfo(info)) => { 150 | &info.as_raw() as *const _ as *const c_void 151 | } 152 | _ => return Err(io::Error::new( 153 | io::ErrorKind::InvalidInput, 154 | "EventCode::EV_ABS must be paired with EnableCodeData::AbsInfo", 155 | )), 156 | }, 157 | EventCode::EV_REP(_) => match data { 158 | Some(EnableCodeData::RepInfo(info)) => { 159 | &libc::c_int::from(info) as *const _ as *const c_void 160 | } 161 | _ => return Err(io::Error::new( 162 | io::ErrorKind::InvalidInput, 163 | "EventCode::EV_REP must be paired with EnableCodeData::RepInfo", 164 | )), 165 | }, 166 | _ => ptr::null(), 167 | }; 168 | 169 | let (ev_type, ev_code) = event_code_to_int(ev_code); 170 | 171 | let result = unsafe { 172 | raw::libevdev_enable_event_code(self.raw(), ev_type, ev_code, data) 173 | }; 174 | 175 | match result { 176 | 0 => Ok(()), 177 | error => Err(io::Error::from_raw_os_error(-error)), 178 | } 179 | } 180 | 181 | /// Forcibly disable an EventType/EventCode on this device, even if the 182 | /// underlying device provides it. This effectively mutes the respective set of 183 | /// events. has() will return false for this EventType/EventCode 184 | /// 185 | /// In most cases, a caller likely only wants to disable a single code, not 186 | /// the whole type. 187 | /// 188 | /// Disabling EV_SYN will not work. In Peter's Words "Don't shoot yourself 189 | /// in the foot. It hurts". 190 | /// 191 | /// This is a local modification only affecting only this representation of 192 | /// this device. 193 | fn disable(&self, d: E) -> io::Result<()> { 194 | d.disable(self) 195 | } 196 | 197 | /// Forcibly disable an event type on this device, even if the underlying 198 | /// device provides it. This effectively mutes the respective set of 199 | /// events. libevdev will filter any events matching this type and none will 200 | /// reach the caller. libevdev_has_event_type() will return false for this 201 | /// type. 202 | /// 203 | /// In most cases, a caller likely only wants to disable a single code, not 204 | /// the whole type. Use `disable_event_code` for that. 205 | /// 206 | /// Disabling EV_SYN will not work. In Peter's Words "Don't shoot yourself 207 | /// in the foot. It hurts". 208 | /// 209 | /// This is a local modification only affecting only this representation of 210 | /// this device. 211 | /// 212 | /// Note: Please use the `disable` function instead. This function is only 213 | /// available for the sake of maintaining compatibility with libevdev. 214 | fn disable_event_type(&self, ev_type: &EventType) -> io::Result<()> { 215 | let result = 216 | unsafe { raw::libevdev_disable_event_type(self.raw(), *ev_type as c_uint) }; 217 | 218 | match result { 219 | 0 => Ok(()), 220 | error => Err(io::Error::from_raw_os_error(-error)), 221 | } 222 | } 223 | /// Forcibly disable an event code on this device, even if the underlying 224 | /// device provides it. This effectively mutes the respective set of 225 | /// events. libevdev will filter any events matching this type and code and 226 | /// none will reach the caller. `has_event_code` will return false for 227 | /// this code. 228 | /// 229 | /// Disabling all event codes for a given type will not disable the event 230 | /// type. Use `disable_event_type` for that. 231 | /// 232 | /// This is a local modification only affecting only this representation of 233 | /// this device. 234 | /// 235 | /// Disabling codes of type EV_SYN will not work. Don't shoot yourself in the 236 | /// foot. It hurts. 237 | /// 238 | /// Note: Please use the `disable` function instead. This function is only 239 | /// available for the sake of maintaining compatibility with libevdev. 240 | fn disable_event_code(&self, code: &EventCode) -> io::Result<()> { 241 | let (ev_type, ev_code) = event_code_to_int(code); 242 | let result = 243 | unsafe { raw::libevdev_disable_event_code(self.raw(), ev_type, ev_code) }; 244 | 245 | match result { 246 | 0 => Ok(()), 247 | error => Err(io::Error::from_raw_os_error(-error)), 248 | } 249 | } 250 | 251 | #[cfg(feature = "libevdev-1-10")] 252 | fn disable_property(&self, prop: &InputProp) -> io::Result<()> { 253 | let result = 254 | unsafe { raw::libevdev_disable_property(self.raw(), (*prop) as c_uint) }; 255 | match result { 256 | 0 => Ok(()), 257 | error => Err(io::Error::from_raw_os_error(-error)), 258 | } 259 | } 260 | 261 | /// Returns `true` if device support the InputProp/EventType/EventCode and false otherwise 262 | fn has(&self, e: E) -> bool { 263 | e.has(self) 264 | } 265 | 266 | /// Returns `true` if device support the property and false otherwise 267 | /// 268 | /// Note: Please use the `has` function instead. This function is only 269 | /// available for the sake of maintaining compatibility with libevdev. 270 | fn has_property(&self, prop: &InputProp) -> bool { 271 | unsafe { raw::libevdev_has_property(self.raw(), *prop as c_uint) != 0 } 272 | } 273 | 274 | /// Returns `true` is the device support this event type and `false` otherwise 275 | /// 276 | /// Note: Please use the `has` function instead. This function is only 277 | /// available for the sake of maintaining compatibility with libevdev. 278 | fn has_event_type(&self, ev_type: &EventType) -> bool { 279 | unsafe { raw::libevdev_has_event_type(self.raw(), *ev_type as c_uint) != 0 } 280 | } 281 | 282 | /// Return `true` is the device support this event type and code and `false` otherwise 283 | /// 284 | /// Note: Please use the `has` function instead. This function is only 285 | /// available for the sake of maintaining compatibility with libevdev. 286 | fn has_event_code(&self, code: &EventCode) -> bool { 287 | unsafe { 288 | let (ev_type, ev_code) = event_code_to_int(code); 289 | raw::libevdev_has_event_code(self.raw(), ev_type, ev_code) != 0 290 | } 291 | } 292 | 293 | string_getter!( 294 | #[doc = "Get device's name, as set by the kernel, or overridden by a call to `set_name`"], 295 | name, libevdev_get_name, 296 | #[doc = "Get device's physical location, as set by the kernel, or overridden by a call to `set_phys`"], 297 | phys, libevdev_get_phys, 298 | #[doc = "Get device's unique identifier, as set by the kernel, or overridden by a call to `set_uniq`"], 299 | uniq, libevdev_get_uniq 300 | ); 301 | 302 | string_setter!( 303 | set_name, 304 | libevdev_set_name, 305 | set_phys, 306 | libevdev_set_phys, 307 | set_uniq, 308 | libevdev_set_uniq 309 | ); 310 | 311 | product_getter!( 312 | product_id, 313 | libevdev_get_id_product, 314 | vendor_id, 315 | libevdev_get_id_vendor, 316 | bustype, 317 | libevdev_get_id_bustype, 318 | version, 319 | libevdev_get_id_version 320 | ); 321 | 322 | product_setter!( 323 | set_product_id, 324 | libevdev_set_id_product, 325 | set_vendor_id, 326 | libevdev_set_id_vendor, 327 | set_bustype, 328 | libevdev_set_id_bustype, 329 | set_version, 330 | libevdev_set_id_version 331 | ); 332 | 333 | /// Get the axis info for the given axis, as advertised by the kernel. 334 | /// 335 | /// Returns the `AbsInfo` for the given the code or None if the device 336 | /// doesn't support this code 337 | fn abs_info(&self, code: &EventCode) -> Option { 338 | let (_, ev_code) = event_code_to_int(code); 339 | let a = unsafe { raw::libevdev_get_abs_info(self.raw(), ev_code).as_ref()? }; 340 | 341 | Some(AbsInfo { 342 | value: a.value, 343 | minimum: a.minimum, 344 | maximum: a.maximum, 345 | fuzz: a.fuzz, 346 | flat: a.flat, 347 | resolution: a.resolution, 348 | }) 349 | } 350 | 351 | /// Change the abs info for the given EV_ABS event code, if the code exists. 352 | /// 353 | /// This function has no effect if `has_event_code` returns false for 354 | /// this code. 355 | fn set_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) { 356 | let (_, ev_code) = event_code_to_int(code); 357 | 358 | unsafe { 359 | raw::libevdev_set_abs_info( 360 | self.raw(), 361 | ev_code, 362 | &absinfo.as_raw() as *const _, 363 | ); 364 | } 365 | } 366 | 367 | /// Returns the current value of the event type. 368 | /// 369 | /// If the device supports this event type and code, the return value is 370 | /// set to the current value of this axis. Otherwise, `None` is returned. 371 | fn event_value(&self, code: &EventCode) -> Option { 372 | let mut value: i32 = 0; 373 | let (ev_type, ev_code) = event_code_to_int(code); 374 | let valid = unsafe { 375 | raw::libevdev_fetch_event_value(self.raw(), ev_type, ev_code, &mut value) 376 | }; 377 | 378 | match valid { 379 | 0 => None, 380 | _ => Some(value), 381 | } 382 | } 383 | 384 | /// Set the value for a given event type and code. 385 | /// 386 | /// This only makes sense for some event types, e.g. setting the value for 387 | /// EV_REL is pointless. 388 | /// 389 | /// This is a local modification only affecting only this representation of 390 | /// this device. A future call to event_value() will return this 391 | /// value, unless the value was overwritten by an event. 392 | /// 393 | /// If the device supports ABS_MT_SLOT, the value set for any ABS_MT_* 394 | /// event code is the value of the currently active slot. You should use 395 | /// `set_slot_value` instead. 396 | /// 397 | /// If the device supports ABS_MT_SLOT and the type is EV_ABS and the code is 398 | /// ABS_MT_SLOT, the value must be a positive number less then the number of 399 | /// slots on the device. Otherwise, `set_event_value` returns Err. 400 | fn set_event_value(&self, code: &EventCode, val: i32) -> io::Result<()> { 401 | let (ev_type, ev_code) = event_code_to_int(code); 402 | let result = unsafe { 403 | raw::libevdev_set_event_value(self.raw(), ev_type, ev_code, val as c_int) 404 | }; 405 | 406 | match result { 407 | 0 => Ok(()), 408 | error => Err(io::Error::from_raw_os_error(-error)), 409 | } 410 | } 411 | 412 | abs_getter!( 413 | abs_minimum, 414 | libevdev_get_abs_minimum, 415 | abs_maximum, 416 | libevdev_get_abs_maximum, 417 | abs_fuzz, 418 | libevdev_get_abs_fuzz, 419 | abs_flat, 420 | libevdev_get_abs_flat, 421 | abs_resolution, 422 | libevdev_get_abs_resolution 423 | ); 424 | 425 | abs_setter!( 426 | set_abs_minimum, 427 | libevdev_set_abs_minimum, 428 | set_abs_maximum, 429 | libevdev_set_abs_maximum, 430 | set_abs_fuzz, 431 | libevdev_set_abs_fuzz, 432 | set_abs_flat, 433 | libevdev_set_abs_flat, 434 | set_abs_resolution, 435 | libevdev_set_abs_resolution 436 | ); 437 | 438 | /// Return the current value of the code for the given slot. 439 | /// 440 | /// If the device supports this event code, the return value is 441 | /// is set to the current value of this axis. Otherwise, or 442 | /// if the event code is not an ABS_MT_* event code, `None` is returned 443 | fn slot_value(&self, slot: u32, code: &EventCode) -> Option { 444 | let (_, ev_code) = event_code_to_int(code); 445 | let mut value: i32 = 0; 446 | let valid = unsafe { 447 | raw::libevdev_fetch_slot_value( 448 | self.raw(), 449 | slot as c_uint, 450 | ev_code, 451 | &mut value, 452 | ) 453 | }; 454 | 455 | match valid { 456 | 0 => None, 457 | _ => Some(value), 458 | } 459 | } 460 | 461 | /// Set the value for a given code for the given slot. 462 | /// 463 | /// This is a local modification only affecting only this representation of 464 | /// this device. A future call to `slot_value` will return this value, 465 | /// unless the value was overwritten by an event. 466 | /// 467 | /// This function does not set event values for axes outside the ABS_MT range, 468 | /// use `set_event_value` instead. 469 | fn set_slot_value(&self, slot: u32, code: &EventCode, val: i32) -> io::Result<()> { 470 | let (_, ev_code) = event_code_to_int(code); 471 | let result = unsafe { 472 | raw::libevdev_set_slot_value( 473 | self.raw(), 474 | slot as c_uint, 475 | ev_code, 476 | val as c_int, 477 | ) 478 | }; 479 | 480 | match result { 481 | 0 => Ok(()), 482 | error => Err(io::Error::from_raw_os_error(-error)), 483 | } 484 | } 485 | 486 | /// Get the number of slots supported by this device. 487 | /// 488 | /// The number of slots supported, or `None` if the device does not provide 489 | /// any slots 490 | /// 491 | /// A device may provide ABS_MT_SLOT but a total number of 0 slots. Hence 492 | /// the return value of `None` for "device does not provide slots at all" 493 | fn num_slots(&self) -> Option { 494 | let result = unsafe { raw::libevdev_get_num_slots(self.raw()) }; 495 | 496 | match result { 497 | -1 => None, 498 | slots => Some(slots), 499 | } 500 | } 501 | 502 | /// Get the currently active slot. 503 | /// 504 | /// This may differ from the value an ioctl may return at this time as 505 | /// events may have been read off the file since changing the slot value 506 | /// but those events are still in the buffer waiting to be processed. 507 | /// The returned value is the value a caller would see if it were to 508 | /// process events manually one-by-one. 509 | fn current_slot(&self) -> Option { 510 | let result = unsafe { raw::libevdev_get_current_slot(self.raw()) }; 511 | 512 | match result { 513 | -1 => None, 514 | slots => Some(slots), 515 | } 516 | } 517 | } 518 | 519 | /// Opaque struct representing an evdev device with no backing file 520 | pub struct UninitDevice { 521 | raw: *mut raw::libevdev, 522 | } 523 | 524 | unsafe impl Send for UninitDevice {} 525 | 526 | impl DeviceWrapper for UninitDevice { 527 | fn raw(&self) -> *mut raw::libevdev { 528 | self.raw 529 | } 530 | } 531 | 532 | impl UninitDevice { 533 | /// Initialize a new libevdev device. 534 | /// 535 | /// Generally you should use Device::new_from_file instead of this method 536 | /// This function only initializes the struct to sane default values. 537 | /// To actually hook up the device to a kernel device, use `set_file`. 538 | pub fn new() -> Option { 539 | let libevdev = unsafe { raw::libevdev_new() }; 540 | 541 | if libevdev.is_null() { 542 | None 543 | } else { 544 | Some(UninitDevice { raw: libevdev }) 545 | } 546 | } 547 | 548 | /// Set the file for this struct and initialize internal data. 549 | /// 550 | /// If the device changed and you need to re-read a device, use `Device::new_from_file` method. 551 | /// If you need to change the file after 552 | /// closing and re-opening the same device, use `change_file`. 553 | pub fn set_file(self, file: File) -> io::Result { 554 | // Don't call UninitDevice's destructor so we can reuse the inner libevdev 555 | let leak = ManuallyDrop::new(self); 556 | let result = unsafe { raw::libevdev_set_fd(leak.raw, file.as_raw_fd()) }; 557 | match result { 558 | 0 => Ok(Device { 559 | file, 560 | raw: leak.raw, 561 | }), 562 | error => Err(io::Error::from_raw_os_error(-error)), 563 | } 564 | } 565 | 566 | #[deprecated( 567 | since = "0.5.0", 568 | note = "Prefer `set_file`. Some function names were changed so they 569 | more closely match their type signature. See issue 42 for discussion 570 | https://github.com/ndesh26/evdev-rs/issues/42" 571 | )] 572 | pub fn set_fd(self, file: File) -> io::Result { 573 | self.set_file(file) 574 | } 575 | } 576 | 577 | impl Drop for UninitDevice { 578 | fn drop(&mut self) { 579 | unsafe { 580 | raw::libevdev_free(self.raw); 581 | } 582 | } 583 | } 584 | 585 | impl std::fmt::Debug for UninitDevice { 586 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 587 | f.debug_struct("UninitDevice") 588 | .field("name", &self.name()) 589 | .field("phys", &self.phys()) 590 | .field("uniq", &self.uniq()) 591 | .finish() 592 | } 593 | } 594 | 595 | /// Opaque struct representing an evdev device 596 | /// 597 | /// Unlike libevdev, this `Device` mantains an associated file as an invariant 598 | pub struct Device { 599 | file: File, 600 | raw: *mut raw::libevdev, 601 | } 602 | 603 | unsafe impl Send for Device {} 604 | 605 | impl DeviceWrapper for Device { 606 | fn raw(&self) -> *mut raw::libevdev { 607 | self.raw 608 | } 609 | } 610 | 611 | impl Device { 612 | /// Initialize a new libevdev device from the given file. 613 | /// 614 | /// This is a shortcut for 615 | /// 616 | /// ```rust,no_run 617 | /// use evdev_rs::{Device, UninitDevice}; 618 | /// # use std::fs::File; 619 | /// 620 | /// let uninit_device = UninitDevice::new().unwrap(); 621 | /// # let file = File::open("/dev/input/event0").unwrap(); 622 | /// let device = uninit_device.set_file(file); 623 | /// ``` 624 | /// 625 | /// The caller is responsible for opening the file and setting 626 | /// the `O_NONBLOCK` flag and handling permissions. 627 | /// If the file is opened without O_NONBLOCK flag then next_event 628 | /// should be called with ReadFlag::BLOCKING. Due to the caching 629 | /// nature of next_event we might block while trying to buffer 630 | /// new events even though some events are already present. 631 | pub fn new_from_file(file: File) -> io::Result { 632 | let mut libevdev = std::ptr::null_mut(); 633 | let result = 634 | unsafe { raw::libevdev_new_from_fd(file.as_raw_fd(), &mut libevdev) }; 635 | 636 | match result { 637 | 0 => Ok(Device { 638 | file, 639 | raw: libevdev, 640 | }), 641 | error => Err(io::Error::from_raw_os_error(-error)), 642 | } 643 | } 644 | 645 | #[deprecated( 646 | since = "0.5.0", 647 | note = "Prefer `new_from_file`. Some function names were changed so they 648 | more closely match their type signature. See issue 42 for discussion 649 | https://github.com/ndesh26/evdev-rs/issues/42" 650 | )] 651 | pub fn new_from_fd(file: File) -> io::Result { 652 | Self::new_from_file(file) 653 | } 654 | 655 | /// Opens a device with the given path as the location of devnode 656 | /// 657 | /// The devnode file is opened with `O_NONBLOCK` and all the pending 658 | /// events are first read from the file before creating the device. 659 | pub fn new_from_path>(path: P) -> io::Result { 660 | let mut file = OpenOptions::new() 661 | .read(true) 662 | .write(true) 663 | .custom_flags(libc::O_NONBLOCK) 664 | .open(path)?; 665 | let mut buffer = [0u8; 20 * std::mem::size_of::()]; 666 | let last_result = loop { 667 | let result = file.read(&mut buffer); 668 | if !result.is_ok() { 669 | break result; 670 | } 671 | }; 672 | let _error_code = io::Error::from(io::ErrorKind::WouldBlock); 673 | match last_result { 674 | Err(_error_code) => Self::new_from_file(file), 675 | _ => Err(io::Error::new( 676 | io::ErrorKind::WouldBlock, 677 | "Unable to open file with O_NONBLOCK", 678 | )), 679 | } 680 | } 681 | 682 | /// Returns the file associated with the device 683 | pub fn file(&self) -> &File { 684 | &self.file 685 | } 686 | 687 | #[deprecated( 688 | since = "0.5.0", 689 | note = "Prefer `file`. This function can easily be misused. Calling 690 | this method, then dropping the returned file will lead to failures 691 | e.g. next_event will return an Err()" 692 | )] 693 | pub fn fd(&self) -> Option { 694 | let result = unsafe { raw::libevdev_get_fd(self.raw) }; 695 | match result { 696 | 0 => None, 697 | _ => unsafe { Some(File::from_raw_fd(result)) }, 698 | } 699 | } 700 | 701 | /// Change the file for this device, without re-reading the actual device. 702 | /// 703 | /// On success, returns the file that was previously associated with this 704 | /// device. 705 | /// 706 | /// If the file changes after initializing the device, for example after a 707 | /// VT-switch in the X.org X server, this function updates the internal 708 | /// file to the newly opened. No check is made that new file points to the 709 | /// same device. If the device has changed, evdev's behavior is undefined. 710 | /// 711 | /// evdev device does not sync itself after changing the file and keeps the 712 | /// current device state. Use next_event with the FORCE_SYNC flag to force 713 | /// a re-sync. 714 | /// 715 | /// # Example 716 | /// 717 | /// ```rust,no_run 718 | /// use evdev_rs::{Device, UninitDevice, ReadFlag, ReadStatus}; 719 | /// # use std::fs::File; 720 | /// # fn hidden() -> std::io::Result<()> { 721 | /// let mut dev = Device::new_from_file(File::open("/dev/input/input0")?)?; 722 | /// dev.change_file(File::open("/dev/input/input1")?)?; 723 | /// dev.next_event(ReadFlag::FORCE_SYNC); 724 | /// while dev.next_event(ReadFlag::SYNC).ok().unwrap().0 == ReadStatus::Sync 725 | /// {} // noop 726 | /// # Ok(()) 727 | /// # } 728 | /// ``` 729 | /// After changing the file, the device is assumed ungrabbed and a caller must 730 | /// call libevdev_grab() again. 731 | pub fn change_file(&mut self, file: File) -> io::Result { 732 | let result = unsafe { raw::libevdev_change_fd(self.raw, file.as_raw_fd()) }; 733 | 734 | match result { 735 | 0 => { 736 | let mut file = file; 737 | std::mem::swap(&mut file, &mut self.file); 738 | Ok(file) 739 | } 740 | error => Err(io::Error::from_raw_os_error(-error)), 741 | } 742 | } 743 | 744 | #[deprecated( 745 | since = "0.5.0", 746 | note = "Prefer new_from_file. Some function names were changed so they 747 | more closely match their type signature. See issue 42 for discussion 748 | https://github.com/ndesh26/evdev-rs/issues/42" 749 | )] 750 | pub fn change_fd(&mut self, file: File) -> io::Result<()> { 751 | self.change_file(file)?; 752 | Ok(()) 753 | } 754 | 755 | /// Grab or ungrab the device through a kernel EVIOCGRAB. 756 | /// 757 | /// This prevents other clients (including kernel-internal ones such as 758 | /// rfkill) from receiving events from this device. This is generally a 759 | /// bad idea. Don't do this. Grabbing an already grabbed device, or 760 | /// ungrabbing an ungrabbed device is a noop and always succeeds. 761 | /// 762 | /// A grab is an operation tied to a file descriptor, not a device. If a 763 | /// client changes the file descriptor with Device::change_file(), it must 764 | /// also re-issue a grab with libevdev_grab(). 765 | pub fn grab(&mut self, grab: GrabMode) -> io::Result<()> { 766 | let result = unsafe { raw::libevdev_grab(self.raw, grab as c_int) }; 767 | 768 | match result { 769 | 0 => Ok(()), 770 | error => Err(io::Error::from_raw_os_error(-error)), 771 | } 772 | } 773 | 774 | /// Check if there are events waiting for us. 775 | /// 776 | /// This function does not consume an event and may not access the device 777 | /// file at all. If there are events queued internally this function will 778 | /// return true. If the internal queue is empty, this function will poll 779 | /// the file descriptor for data. 780 | /// 781 | /// This is a convenience function for simple processes, most complex programs 782 | /// are expected to use select(2) or poll(2) on the file descriptor. The kernel 783 | /// guarantees that if data is available, it is a multiple of sizeof(struct 784 | /// input_event), and thus calling `next_event` when select(2) or 785 | /// poll(2) return is safe. You do not need `has_event_pending` if 786 | /// you're using select(2) or poll(2). 787 | pub fn has_event_pending(&self) -> bool { 788 | unsafe { raw::libevdev_has_event_pending(self.raw) > 0 } 789 | } 790 | 791 | /// Return the driver version of a device already intialize with `set_file` 792 | pub fn driver_version(&self) -> i32 { 793 | unsafe { raw::libevdev_get_driver_version(self.raw) as i32 } 794 | } 795 | 796 | /// Set the device's EV_ABS axis to the value defined in the abs 797 | /// parameter. This will be written to the kernel. 798 | pub fn set_kernel_abs_info(&self, code: &EventCode, absinfo: &AbsInfo) { 799 | let (_, ev_code) = event_code_to_int(code); 800 | 801 | unsafe { 802 | raw::libevdev_kernel_set_abs_info( 803 | self.raw, 804 | ev_code, 805 | &absinfo.as_raw() as *const _, 806 | ); 807 | } 808 | } 809 | 810 | /// Turn an LED on or off. 811 | /// 812 | /// enabling an LED requires write permissions on the device's file descriptor. 813 | pub fn kernel_set_led_value( 814 | &self, 815 | code: &EventCode, 816 | value: LedState, 817 | ) -> io::Result<()> { 818 | let (_, ev_code) = event_code_to_int(code); 819 | let result = unsafe { 820 | raw::libevdev_kernel_set_led_value(self.raw, ev_code, value as c_int) 821 | }; 822 | 823 | match result { 824 | 0 => Ok(()), 825 | error => Err(io::Error::from_raw_os_error(-error)), 826 | } 827 | } 828 | 829 | /// Set the clock ID to be used for timestamps. Further events from this device 830 | /// will report an event time based on the given clock. 831 | /// 832 | /// This is a modification only affecting this representation of 833 | /// this device. 834 | pub fn set_clock_id(&self, clockid: i32) -> io::Result<()> { 835 | let result = unsafe { raw::libevdev_set_clock_id(self.raw, clockid) }; 836 | 837 | match result { 838 | 0 => Ok(()), 839 | error => Err(io::Error::from_raw_os_error(-error)), 840 | } 841 | } 842 | 843 | /// Get the next event from the device. This function operates in two different 844 | /// modes: normal mode or sync mode. 845 | /// 846 | /// In normal mode (when flags has `evdev::NORMAL` set), this function returns 847 | /// `ReadStatus::Success` and returns the event. If no events are available at 848 | /// this time, it returns `-EAGAIN` as `Err`. 849 | /// 850 | /// If the current event is an `EV_SYN::SYN_DROPPED` event, this function returns 851 | /// `ReadStatus::Sync` and is set to the `EV_SYN` event.The caller should now call 852 | /// this function with the `evdev::SYNC` flag set, to get the set of events that 853 | /// make up the device state delta. This function returns ReadStatus::Sync for 854 | /// each event part of that delta, until it returns `-EAGAIN` once all events 855 | /// have been synced. 856 | /// 857 | /// If a device needs to be synced by the caller but the caller does not call 858 | /// with the `evdev::SYNC` flag set, all events from the diff are dropped after 859 | /// evdev updates its internal state and event processing continues as normal. 860 | /// Note that the current slot and the state of touch points may have updated 861 | /// during the `SYN_DROPPED` event, it is strongly recommended that a caller 862 | /// ignoring all sync events calls `current_slot` and checks the 863 | /// `ABS_MT_TRACKING_ID` values for all slots. 864 | /// 865 | /// If a device has changed state without events being enqueued in evdev, 866 | /// e.g. after changing the file descriptor, use the `evdev::FORCE_SYNC` flag. 867 | /// This triggers an internal sync of the device and `next_event` returns 868 | /// `ReadStatus::Sync`. 869 | pub fn next_event(&self, flags: ReadFlag) -> io::Result<(ReadStatus, InputEvent)> { 870 | let mut ev = raw::input_event { 871 | time: raw::timeval { 872 | tv_sec: 0, 873 | tv_usec: 0, 874 | }, 875 | type_: 0, 876 | code: 0, 877 | value: 0, 878 | }; 879 | 880 | let result = unsafe { 881 | raw::libevdev_next_event(self.raw, flags.bits() as c_uint, &mut ev) 882 | }; 883 | 884 | let event = InputEvent { 885 | time: TimeVal { 886 | tv_sec: ev.time.tv_sec, 887 | tv_usec: ev.time.tv_usec, 888 | }, 889 | event_code: int_to_event_code(ev.type_ as u32, ev.code as u32), 890 | value: ev.value, 891 | }; 892 | 893 | match result { 894 | raw::LIBEVDEV_READ_STATUS_SUCCESS => Ok((ReadStatus::Success, event)), 895 | raw::LIBEVDEV_READ_STATUS_SYNC => Ok((ReadStatus::Sync, event)), 896 | error => Err(io::Error::from_raw_os_error(-error)), 897 | } 898 | } 899 | } 900 | 901 | impl Drop for Device { 902 | fn drop(&mut self) { 903 | unsafe { 904 | raw::libevdev_free(self.raw); 905 | } 906 | } 907 | } 908 | 909 | impl std::fmt::Debug for Device { 910 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 911 | f.debug_struct("Device") 912 | .field("name", &self.name()) 913 | .field("phys", &self.phys()) 914 | .field("uniq", &self.uniq()) 915 | .finish() 916 | } 917 | } 918 | 919 | impl AsRawFd for Device { 920 | fn as_raw_fd(&self) -> RawFd { 921 | self.file.as_raw_fd() 922 | } 923 | } 924 | -------------------------------------------------------------------------------- /src/enums.rs: -------------------------------------------------------------------------------- 1 | /* THIS FILE IS GENERATED, DO NOT EDIT */ 2 | 3 | #[cfg(feature = "serde")] 4 | use serde::{Deserialize, Serialize}; 5 | 6 | #[allow(non_camel_case_types)] 7 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 8 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 9 | pub enum EventType { 10 | EV_SYN = 0, 11 | EV_KEY = 1, 12 | EV_REL = 2, 13 | EV_ABS = 3, 14 | EV_MSC = 4, 15 | EV_SW = 5, 16 | EV_LED = 17, 17 | EV_SND = 18, 18 | EV_REP = 20, 19 | EV_FF = 21, 20 | EV_PWR = 22, 21 | EV_FF_STATUS = 23, 22 | EV_UNK, 23 | EV_MAX = 31, 24 | } 25 | 26 | pub const fn int_to_event_type(code: u32) -> Option { 27 | match code { 28 | 0 => Some(EventType::EV_SYN), 29 | 1 => Some(EventType::EV_KEY), 30 | 2 => Some(EventType::EV_REL), 31 | 3 => Some(EventType::EV_ABS), 32 | 4 => Some(EventType::EV_MSC), 33 | 5 => Some(EventType::EV_SW), 34 | 17 => Some(EventType::EV_LED), 35 | 18 => Some(EventType::EV_SND), 36 | 20 => Some(EventType::EV_REP), 37 | 21 => Some(EventType::EV_FF), 38 | 22 => Some(EventType::EV_PWR), 39 | 23 => Some(EventType::EV_FF_STATUS), 40 | c if c < 31 => Some(EventType::EV_UNK), 41 | 31 => Some(EventType::EV_MAX), 42 | _ => None, 43 | } 44 | } 45 | 46 | impl std::str::FromStr for EventType { 47 | type Err = (); 48 | fn from_str(s: &str) -> Result { 49 | match s { 50 | "EV_SYN" => Ok(EventType::EV_SYN), 51 | "EV_KEY" => Ok(EventType::EV_KEY), 52 | "EV_REL" => Ok(EventType::EV_REL), 53 | "EV_ABS" => Ok(EventType::EV_ABS), 54 | "EV_MSC" => Ok(EventType::EV_MSC), 55 | "EV_SW" => Ok(EventType::EV_SW), 56 | "EV_LED" => Ok(EventType::EV_LED), 57 | "EV_SND" => Ok(EventType::EV_SND), 58 | "EV_REP" => Ok(EventType::EV_REP), 59 | "EV_FF" => Ok(EventType::EV_FF), 60 | "EV_PWR" => Ok(EventType::EV_PWR), 61 | "EV_FF_STATUS" => Ok(EventType::EV_FF_STATUS), 62 | "EV_MAX" => Ok(EventType::EV_MAX), 63 | _ => Err(()), 64 | } 65 | } 66 | } 67 | 68 | #[allow(non_camel_case_types)] 69 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 70 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 71 | pub enum EventCode { 72 | EV_SYN(EV_SYN), 73 | EV_KEY(EV_KEY), 74 | EV_REL(EV_REL), 75 | EV_ABS(EV_ABS), 76 | EV_MSC(EV_MSC), 77 | EV_SW(EV_SW), 78 | EV_LED(EV_LED), 79 | EV_SND(EV_SND), 80 | EV_REP(EV_REP), 81 | EV_FF(EV_FF), 82 | EV_PWR, 83 | EV_FF_STATUS(EV_FF), 84 | EV_UNK { event_type: u32, event_code: u32 }, 85 | EV_MAX, 86 | } 87 | 88 | #[allow(non_camel_case_types)] 89 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 90 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 91 | pub enum EV_REL { 92 | REL_X = 0, 93 | REL_Y = 1, 94 | REL_Z = 2, 95 | REL_RX = 3, 96 | REL_RY = 4, 97 | REL_RZ = 5, 98 | REL_HWHEEL = 6, 99 | REL_DIAL = 7, 100 | REL_WHEEL = 8, 101 | REL_MISC = 9, 102 | REL_RESERVED = 10, 103 | REL_WHEEL_HI_RES = 11, 104 | REL_HWHEEL_HI_RES = 12, 105 | REL_MAX = 15, 106 | } 107 | 108 | pub const fn int_to_ev_rel(code: u32) -> Option { 109 | match code { 110 | 0 => Some(EV_REL::REL_X), 111 | 1 => Some(EV_REL::REL_Y), 112 | 2 => Some(EV_REL::REL_Z), 113 | 3 => Some(EV_REL::REL_RX), 114 | 4 => Some(EV_REL::REL_RY), 115 | 5 => Some(EV_REL::REL_RZ), 116 | 6 => Some(EV_REL::REL_HWHEEL), 117 | 7 => Some(EV_REL::REL_DIAL), 118 | 8 => Some(EV_REL::REL_WHEEL), 119 | 9 => Some(EV_REL::REL_MISC), 120 | 10 => Some(EV_REL::REL_RESERVED), 121 | 11 => Some(EV_REL::REL_WHEEL_HI_RES), 122 | 12 => Some(EV_REL::REL_HWHEEL_HI_RES), 123 | 15 => Some(EV_REL::REL_MAX), 124 | _ => None, 125 | } 126 | } 127 | 128 | impl std::str::FromStr for EV_REL { 129 | type Err = (); 130 | fn from_str(s: &str) -> Result { 131 | match s { 132 | "REL_X" => Ok(EV_REL::REL_X), 133 | "REL_Y" => Ok(EV_REL::REL_Y), 134 | "REL_Z" => Ok(EV_REL::REL_Z), 135 | "REL_RX" => Ok(EV_REL::REL_RX), 136 | "REL_RY" => Ok(EV_REL::REL_RY), 137 | "REL_RZ" => Ok(EV_REL::REL_RZ), 138 | "REL_HWHEEL" => Ok(EV_REL::REL_HWHEEL), 139 | "REL_DIAL" => Ok(EV_REL::REL_DIAL), 140 | "REL_WHEEL" => Ok(EV_REL::REL_WHEEL), 141 | "REL_MISC" => Ok(EV_REL::REL_MISC), 142 | "REL_RESERVED" => Ok(EV_REL::REL_RESERVED), 143 | "REL_WHEEL_HI_RES" => Ok(EV_REL::REL_WHEEL_HI_RES), 144 | "REL_HWHEEL_HI_RES" => Ok(EV_REL::REL_HWHEEL_HI_RES), 145 | "REL_MAX" => Ok(EV_REL::REL_MAX), 146 | _ => Err(()), 147 | } 148 | } 149 | } 150 | 151 | impl std::fmt::Display for EV_REL { 152 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 153 | write!(f, "{:?}", self) 154 | } 155 | } 156 | 157 | #[allow(non_camel_case_types)] 158 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 159 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 160 | pub enum EV_ABS { 161 | ABS_X = 0, 162 | ABS_Y = 1, 163 | ABS_Z = 2, 164 | ABS_RX = 3, 165 | ABS_RY = 4, 166 | ABS_RZ = 5, 167 | ABS_THROTTLE = 6, 168 | ABS_RUDDER = 7, 169 | ABS_WHEEL = 8, 170 | ABS_GAS = 9, 171 | ABS_BRAKE = 10, 172 | ABS_HAT0X = 16, 173 | ABS_HAT0Y = 17, 174 | ABS_HAT1X = 18, 175 | ABS_HAT1Y = 19, 176 | ABS_HAT2X = 20, 177 | ABS_HAT2Y = 21, 178 | ABS_HAT3X = 22, 179 | ABS_HAT3Y = 23, 180 | ABS_PRESSURE = 24, 181 | ABS_DISTANCE = 25, 182 | ABS_TILT_X = 26, 183 | ABS_TILT_Y = 27, 184 | ABS_TOOL_WIDTH = 28, 185 | ABS_VOLUME = 32, 186 | ABS_PROFILE = 33, 187 | ABS_MISC = 40, 188 | ABS_RESERVED = 46, 189 | ABS_MT_SLOT = 47, 190 | ABS_MT_TOUCH_MAJOR = 48, 191 | ABS_MT_TOUCH_MINOR = 49, 192 | ABS_MT_WIDTH_MAJOR = 50, 193 | ABS_MT_WIDTH_MINOR = 51, 194 | ABS_MT_ORIENTATION = 52, 195 | ABS_MT_POSITION_X = 53, 196 | ABS_MT_POSITION_Y = 54, 197 | ABS_MT_TOOL_TYPE = 55, 198 | ABS_MT_BLOB_ID = 56, 199 | ABS_MT_TRACKING_ID = 57, 200 | ABS_MT_PRESSURE = 58, 201 | ABS_MT_DISTANCE = 59, 202 | ABS_MT_TOOL_X = 60, 203 | ABS_MT_TOOL_Y = 61, 204 | ABS_MAX = 63, 205 | } 206 | 207 | pub const fn int_to_ev_abs(code: u32) -> Option { 208 | match code { 209 | 0 => Some(EV_ABS::ABS_X), 210 | 1 => Some(EV_ABS::ABS_Y), 211 | 2 => Some(EV_ABS::ABS_Z), 212 | 3 => Some(EV_ABS::ABS_RX), 213 | 4 => Some(EV_ABS::ABS_RY), 214 | 5 => Some(EV_ABS::ABS_RZ), 215 | 6 => Some(EV_ABS::ABS_THROTTLE), 216 | 7 => Some(EV_ABS::ABS_RUDDER), 217 | 8 => Some(EV_ABS::ABS_WHEEL), 218 | 9 => Some(EV_ABS::ABS_GAS), 219 | 10 => Some(EV_ABS::ABS_BRAKE), 220 | 16 => Some(EV_ABS::ABS_HAT0X), 221 | 17 => Some(EV_ABS::ABS_HAT0Y), 222 | 18 => Some(EV_ABS::ABS_HAT1X), 223 | 19 => Some(EV_ABS::ABS_HAT1Y), 224 | 20 => Some(EV_ABS::ABS_HAT2X), 225 | 21 => Some(EV_ABS::ABS_HAT2Y), 226 | 22 => Some(EV_ABS::ABS_HAT3X), 227 | 23 => Some(EV_ABS::ABS_HAT3Y), 228 | 24 => Some(EV_ABS::ABS_PRESSURE), 229 | 25 => Some(EV_ABS::ABS_DISTANCE), 230 | 26 => Some(EV_ABS::ABS_TILT_X), 231 | 27 => Some(EV_ABS::ABS_TILT_Y), 232 | 28 => Some(EV_ABS::ABS_TOOL_WIDTH), 233 | 32 => Some(EV_ABS::ABS_VOLUME), 234 | 33 => Some(EV_ABS::ABS_PROFILE), 235 | 40 => Some(EV_ABS::ABS_MISC), 236 | 46 => Some(EV_ABS::ABS_RESERVED), 237 | 47 => Some(EV_ABS::ABS_MT_SLOT), 238 | 48 => Some(EV_ABS::ABS_MT_TOUCH_MAJOR), 239 | 49 => Some(EV_ABS::ABS_MT_TOUCH_MINOR), 240 | 50 => Some(EV_ABS::ABS_MT_WIDTH_MAJOR), 241 | 51 => Some(EV_ABS::ABS_MT_WIDTH_MINOR), 242 | 52 => Some(EV_ABS::ABS_MT_ORIENTATION), 243 | 53 => Some(EV_ABS::ABS_MT_POSITION_X), 244 | 54 => Some(EV_ABS::ABS_MT_POSITION_Y), 245 | 55 => Some(EV_ABS::ABS_MT_TOOL_TYPE), 246 | 56 => Some(EV_ABS::ABS_MT_BLOB_ID), 247 | 57 => Some(EV_ABS::ABS_MT_TRACKING_ID), 248 | 58 => Some(EV_ABS::ABS_MT_PRESSURE), 249 | 59 => Some(EV_ABS::ABS_MT_DISTANCE), 250 | 60 => Some(EV_ABS::ABS_MT_TOOL_X), 251 | 61 => Some(EV_ABS::ABS_MT_TOOL_Y), 252 | 63 => Some(EV_ABS::ABS_MAX), 253 | _ => None, 254 | } 255 | } 256 | 257 | impl std::str::FromStr for EV_ABS { 258 | type Err = (); 259 | fn from_str(s: &str) -> Result { 260 | match s { 261 | "ABS_X" => Ok(EV_ABS::ABS_X), 262 | "ABS_Y" => Ok(EV_ABS::ABS_Y), 263 | "ABS_Z" => Ok(EV_ABS::ABS_Z), 264 | "ABS_RX" => Ok(EV_ABS::ABS_RX), 265 | "ABS_RY" => Ok(EV_ABS::ABS_RY), 266 | "ABS_RZ" => Ok(EV_ABS::ABS_RZ), 267 | "ABS_THROTTLE" => Ok(EV_ABS::ABS_THROTTLE), 268 | "ABS_RUDDER" => Ok(EV_ABS::ABS_RUDDER), 269 | "ABS_WHEEL" => Ok(EV_ABS::ABS_WHEEL), 270 | "ABS_GAS" => Ok(EV_ABS::ABS_GAS), 271 | "ABS_BRAKE" => Ok(EV_ABS::ABS_BRAKE), 272 | "ABS_HAT0X" => Ok(EV_ABS::ABS_HAT0X), 273 | "ABS_HAT0Y" => Ok(EV_ABS::ABS_HAT0Y), 274 | "ABS_HAT1X" => Ok(EV_ABS::ABS_HAT1X), 275 | "ABS_HAT1Y" => Ok(EV_ABS::ABS_HAT1Y), 276 | "ABS_HAT2X" => Ok(EV_ABS::ABS_HAT2X), 277 | "ABS_HAT2Y" => Ok(EV_ABS::ABS_HAT2Y), 278 | "ABS_HAT3X" => Ok(EV_ABS::ABS_HAT3X), 279 | "ABS_HAT3Y" => Ok(EV_ABS::ABS_HAT3Y), 280 | "ABS_PRESSURE" => Ok(EV_ABS::ABS_PRESSURE), 281 | "ABS_DISTANCE" => Ok(EV_ABS::ABS_DISTANCE), 282 | "ABS_TILT_X" => Ok(EV_ABS::ABS_TILT_X), 283 | "ABS_TILT_Y" => Ok(EV_ABS::ABS_TILT_Y), 284 | "ABS_TOOL_WIDTH" => Ok(EV_ABS::ABS_TOOL_WIDTH), 285 | "ABS_VOLUME" => Ok(EV_ABS::ABS_VOLUME), 286 | "ABS_PROFILE" => Ok(EV_ABS::ABS_PROFILE), 287 | "ABS_MISC" => Ok(EV_ABS::ABS_MISC), 288 | "ABS_RESERVED" => Ok(EV_ABS::ABS_RESERVED), 289 | "ABS_MT_SLOT" => Ok(EV_ABS::ABS_MT_SLOT), 290 | "ABS_MT_TOUCH_MAJOR" => Ok(EV_ABS::ABS_MT_TOUCH_MAJOR), 291 | "ABS_MT_TOUCH_MINOR" => Ok(EV_ABS::ABS_MT_TOUCH_MINOR), 292 | "ABS_MT_WIDTH_MAJOR" => Ok(EV_ABS::ABS_MT_WIDTH_MAJOR), 293 | "ABS_MT_WIDTH_MINOR" => Ok(EV_ABS::ABS_MT_WIDTH_MINOR), 294 | "ABS_MT_ORIENTATION" => Ok(EV_ABS::ABS_MT_ORIENTATION), 295 | "ABS_MT_POSITION_X" => Ok(EV_ABS::ABS_MT_POSITION_X), 296 | "ABS_MT_POSITION_Y" => Ok(EV_ABS::ABS_MT_POSITION_Y), 297 | "ABS_MT_TOOL_TYPE" => Ok(EV_ABS::ABS_MT_TOOL_TYPE), 298 | "ABS_MT_BLOB_ID" => Ok(EV_ABS::ABS_MT_BLOB_ID), 299 | "ABS_MT_TRACKING_ID" => Ok(EV_ABS::ABS_MT_TRACKING_ID), 300 | "ABS_MT_PRESSURE" => Ok(EV_ABS::ABS_MT_PRESSURE), 301 | "ABS_MT_DISTANCE" => Ok(EV_ABS::ABS_MT_DISTANCE), 302 | "ABS_MT_TOOL_X" => Ok(EV_ABS::ABS_MT_TOOL_X), 303 | "ABS_MT_TOOL_Y" => Ok(EV_ABS::ABS_MT_TOOL_Y), 304 | "ABS_MAX" => Ok(EV_ABS::ABS_MAX), 305 | _ => Err(()), 306 | } 307 | } 308 | } 309 | 310 | impl std::fmt::Display for EV_ABS { 311 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 312 | write!(f, "{:?}", self) 313 | } 314 | } 315 | 316 | #[allow(non_camel_case_types)] 317 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 318 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 319 | pub enum EV_KEY { 320 | KEY_RESERVED = 0, 321 | KEY_ESC = 1, 322 | KEY_1 = 2, 323 | KEY_2 = 3, 324 | KEY_3 = 4, 325 | KEY_4 = 5, 326 | KEY_5 = 6, 327 | KEY_6 = 7, 328 | KEY_7 = 8, 329 | KEY_8 = 9, 330 | KEY_9 = 10, 331 | KEY_0 = 11, 332 | KEY_MINUS = 12, 333 | KEY_EQUAL = 13, 334 | KEY_BACKSPACE = 14, 335 | KEY_TAB = 15, 336 | KEY_Q = 16, 337 | KEY_W = 17, 338 | KEY_E = 18, 339 | KEY_R = 19, 340 | KEY_T = 20, 341 | KEY_Y = 21, 342 | KEY_U = 22, 343 | KEY_I = 23, 344 | KEY_O = 24, 345 | KEY_P = 25, 346 | KEY_LEFTBRACE = 26, 347 | KEY_RIGHTBRACE = 27, 348 | KEY_ENTER = 28, 349 | KEY_LEFTCTRL = 29, 350 | KEY_A = 30, 351 | KEY_S = 31, 352 | KEY_D = 32, 353 | KEY_F = 33, 354 | KEY_G = 34, 355 | KEY_H = 35, 356 | KEY_J = 36, 357 | KEY_K = 37, 358 | KEY_L = 38, 359 | KEY_SEMICOLON = 39, 360 | KEY_APOSTROPHE = 40, 361 | KEY_GRAVE = 41, 362 | KEY_LEFTSHIFT = 42, 363 | KEY_BACKSLASH = 43, 364 | KEY_Z = 44, 365 | KEY_X = 45, 366 | KEY_C = 46, 367 | KEY_V = 47, 368 | KEY_B = 48, 369 | KEY_N = 49, 370 | KEY_M = 50, 371 | KEY_COMMA = 51, 372 | KEY_DOT = 52, 373 | KEY_SLASH = 53, 374 | KEY_RIGHTSHIFT = 54, 375 | KEY_KPASTERISK = 55, 376 | KEY_LEFTALT = 56, 377 | KEY_SPACE = 57, 378 | KEY_CAPSLOCK = 58, 379 | KEY_F1 = 59, 380 | KEY_F2 = 60, 381 | KEY_F3 = 61, 382 | KEY_F4 = 62, 383 | KEY_F5 = 63, 384 | KEY_F6 = 64, 385 | KEY_F7 = 65, 386 | KEY_F8 = 66, 387 | KEY_F9 = 67, 388 | KEY_F10 = 68, 389 | KEY_NUMLOCK = 69, 390 | KEY_SCROLLLOCK = 70, 391 | KEY_KP7 = 71, 392 | KEY_KP8 = 72, 393 | KEY_KP9 = 73, 394 | KEY_KPMINUS = 74, 395 | KEY_KP4 = 75, 396 | KEY_KP5 = 76, 397 | KEY_KP6 = 77, 398 | KEY_KPPLUS = 78, 399 | KEY_KP1 = 79, 400 | KEY_KP2 = 80, 401 | KEY_KP3 = 81, 402 | KEY_KP0 = 82, 403 | KEY_KPDOT = 83, 404 | KEY_ZENKAKUHANKAKU = 85, 405 | KEY_102ND = 86, 406 | KEY_F11 = 87, 407 | KEY_F12 = 88, 408 | KEY_RO = 89, 409 | KEY_KATAKANA = 90, 410 | KEY_HIRAGANA = 91, 411 | KEY_HENKAN = 92, 412 | KEY_KATAKANAHIRAGANA = 93, 413 | KEY_MUHENKAN = 94, 414 | KEY_KPJPCOMMA = 95, 415 | KEY_KPENTER = 96, 416 | KEY_RIGHTCTRL = 97, 417 | KEY_KPSLASH = 98, 418 | KEY_SYSRQ = 99, 419 | KEY_RIGHTALT = 100, 420 | KEY_LINEFEED = 101, 421 | KEY_HOME = 102, 422 | KEY_UP = 103, 423 | KEY_PAGEUP = 104, 424 | KEY_LEFT = 105, 425 | KEY_RIGHT = 106, 426 | KEY_END = 107, 427 | KEY_DOWN = 108, 428 | KEY_PAGEDOWN = 109, 429 | KEY_INSERT = 110, 430 | KEY_DELETE = 111, 431 | KEY_MACRO = 112, 432 | KEY_MUTE = 113, 433 | KEY_VOLUMEDOWN = 114, 434 | KEY_VOLUMEUP = 115, 435 | KEY_POWER = 116, 436 | KEY_KPEQUAL = 117, 437 | KEY_KPPLUSMINUS = 118, 438 | KEY_PAUSE = 119, 439 | KEY_SCALE = 120, 440 | KEY_KPCOMMA = 121, 441 | KEY_HANGEUL = 122, 442 | KEY_HANJA = 123, 443 | KEY_YEN = 124, 444 | KEY_LEFTMETA = 125, 445 | KEY_RIGHTMETA = 126, 446 | KEY_COMPOSE = 127, 447 | KEY_STOP = 128, 448 | KEY_AGAIN = 129, 449 | KEY_PROPS = 130, 450 | KEY_UNDO = 131, 451 | KEY_FRONT = 132, 452 | KEY_COPY = 133, 453 | KEY_OPEN = 134, 454 | KEY_PASTE = 135, 455 | KEY_FIND = 136, 456 | KEY_CUT = 137, 457 | KEY_HELP = 138, 458 | KEY_MENU = 139, 459 | KEY_CALC = 140, 460 | KEY_SETUP = 141, 461 | KEY_SLEEP = 142, 462 | KEY_WAKEUP = 143, 463 | KEY_FILE = 144, 464 | KEY_SENDFILE = 145, 465 | KEY_DELETEFILE = 146, 466 | KEY_XFER = 147, 467 | KEY_PROG1 = 148, 468 | KEY_PROG2 = 149, 469 | KEY_WWW = 150, 470 | KEY_MSDOS = 151, 471 | KEY_COFFEE = 152, 472 | KEY_ROTATE_DISPLAY = 153, 473 | KEY_CYCLEWINDOWS = 154, 474 | KEY_MAIL = 155, 475 | KEY_BOOKMARKS = 156, 476 | KEY_COMPUTER = 157, 477 | KEY_BACK = 158, 478 | KEY_FORWARD = 159, 479 | KEY_CLOSECD = 160, 480 | KEY_EJECTCD = 161, 481 | KEY_EJECTCLOSECD = 162, 482 | KEY_NEXTSONG = 163, 483 | KEY_PLAYPAUSE = 164, 484 | KEY_PREVIOUSSONG = 165, 485 | KEY_STOPCD = 166, 486 | KEY_RECORD = 167, 487 | KEY_REWIND = 168, 488 | KEY_PHONE = 169, 489 | KEY_ISO = 170, 490 | KEY_CONFIG = 171, 491 | KEY_HOMEPAGE = 172, 492 | KEY_REFRESH = 173, 493 | KEY_EXIT = 174, 494 | KEY_MOVE = 175, 495 | KEY_EDIT = 176, 496 | KEY_SCROLLUP = 177, 497 | KEY_SCROLLDOWN = 178, 498 | KEY_KPLEFTPAREN = 179, 499 | KEY_KPRIGHTPAREN = 180, 500 | KEY_NEW = 181, 501 | KEY_REDO = 182, 502 | KEY_F13 = 183, 503 | KEY_F14 = 184, 504 | KEY_F15 = 185, 505 | KEY_F16 = 186, 506 | KEY_F17 = 187, 507 | KEY_F18 = 188, 508 | KEY_F19 = 189, 509 | KEY_F20 = 190, 510 | KEY_F21 = 191, 511 | KEY_F22 = 192, 512 | KEY_F23 = 193, 513 | KEY_F24 = 194, 514 | KEY_PLAYCD = 200, 515 | KEY_PAUSECD = 201, 516 | KEY_PROG3 = 202, 517 | KEY_PROG4 = 203, 518 | KEY_ALL_APPLICATIONS = 204, 519 | KEY_SUSPEND = 205, 520 | KEY_CLOSE = 206, 521 | KEY_PLAY = 207, 522 | KEY_FASTFORWARD = 208, 523 | KEY_BASSBOOST = 209, 524 | KEY_PRINT = 210, 525 | KEY_HP = 211, 526 | KEY_CAMERA = 212, 527 | KEY_SOUND = 213, 528 | KEY_QUESTION = 214, 529 | KEY_EMAIL = 215, 530 | KEY_CHAT = 216, 531 | KEY_SEARCH = 217, 532 | KEY_CONNECT = 218, 533 | KEY_FINANCE = 219, 534 | KEY_SPORT = 220, 535 | KEY_SHOP = 221, 536 | KEY_ALTERASE = 222, 537 | KEY_CANCEL = 223, 538 | KEY_BRIGHTNESSDOWN = 224, 539 | KEY_BRIGHTNESSUP = 225, 540 | KEY_MEDIA = 226, 541 | KEY_SWITCHVIDEOMODE = 227, 542 | KEY_KBDILLUMTOGGLE = 228, 543 | KEY_KBDILLUMDOWN = 229, 544 | KEY_KBDILLUMUP = 230, 545 | KEY_SEND = 231, 546 | KEY_REPLY = 232, 547 | KEY_FORWARDMAIL = 233, 548 | KEY_SAVE = 234, 549 | KEY_DOCUMENTS = 235, 550 | KEY_BATTERY = 236, 551 | KEY_BLUETOOTH = 237, 552 | KEY_WLAN = 238, 553 | KEY_UWB = 239, 554 | KEY_UNKNOWN = 240, 555 | KEY_VIDEO_NEXT = 241, 556 | KEY_VIDEO_PREV = 242, 557 | KEY_BRIGHTNESS_CYCLE = 243, 558 | KEY_BRIGHTNESS_AUTO = 244, 559 | KEY_DISPLAY_OFF = 245, 560 | KEY_WWAN = 246, 561 | KEY_RFKILL = 247, 562 | KEY_MICMUTE = 248, 563 | KEY_OK = 352, 564 | KEY_SELECT = 353, 565 | KEY_GOTO = 354, 566 | KEY_CLEAR = 355, 567 | KEY_POWER2 = 356, 568 | KEY_OPTION = 357, 569 | KEY_INFO = 358, 570 | KEY_TIME = 359, 571 | KEY_VENDOR = 360, 572 | KEY_ARCHIVE = 361, 573 | KEY_PROGRAM = 362, 574 | KEY_CHANNEL = 363, 575 | KEY_FAVORITES = 364, 576 | KEY_EPG = 365, 577 | KEY_PVR = 366, 578 | KEY_MHP = 367, 579 | KEY_LANGUAGE = 368, 580 | KEY_TITLE = 369, 581 | KEY_SUBTITLE = 370, 582 | KEY_ANGLE = 371, 583 | KEY_FULL_SCREEN = 372, 584 | KEY_MODE = 373, 585 | KEY_KEYBOARD = 374, 586 | KEY_ASPECT_RATIO = 375, 587 | KEY_PC = 376, 588 | KEY_TV = 377, 589 | KEY_TV2 = 378, 590 | KEY_VCR = 379, 591 | KEY_VCR2 = 380, 592 | KEY_SAT = 381, 593 | KEY_SAT2 = 382, 594 | KEY_CD = 383, 595 | KEY_TAPE = 384, 596 | KEY_RADIO = 385, 597 | KEY_TUNER = 386, 598 | KEY_PLAYER = 387, 599 | KEY_TEXT = 388, 600 | KEY_DVD = 389, 601 | KEY_AUX = 390, 602 | KEY_MP3 = 391, 603 | KEY_AUDIO = 392, 604 | KEY_VIDEO = 393, 605 | KEY_DIRECTORY = 394, 606 | KEY_LIST = 395, 607 | KEY_MEMO = 396, 608 | KEY_CALENDAR = 397, 609 | KEY_RED = 398, 610 | KEY_GREEN = 399, 611 | KEY_YELLOW = 400, 612 | KEY_BLUE = 401, 613 | KEY_CHANNELUP = 402, 614 | KEY_CHANNELDOWN = 403, 615 | KEY_FIRST = 404, 616 | KEY_LAST = 405, 617 | KEY_AB = 406, 618 | KEY_NEXT = 407, 619 | KEY_RESTART = 408, 620 | KEY_SLOW = 409, 621 | KEY_SHUFFLE = 410, 622 | KEY_BREAK = 411, 623 | KEY_PREVIOUS = 412, 624 | KEY_DIGITS = 413, 625 | KEY_TEEN = 414, 626 | KEY_TWEN = 415, 627 | KEY_VIDEOPHONE = 416, 628 | KEY_GAMES = 417, 629 | KEY_ZOOMIN = 418, 630 | KEY_ZOOMOUT = 419, 631 | KEY_ZOOMRESET = 420, 632 | KEY_WORDPROCESSOR = 421, 633 | KEY_EDITOR = 422, 634 | KEY_SPREADSHEET = 423, 635 | KEY_GRAPHICSEDITOR = 424, 636 | KEY_PRESENTATION = 425, 637 | KEY_DATABASE = 426, 638 | KEY_NEWS = 427, 639 | KEY_VOICEMAIL = 428, 640 | KEY_ADDRESSBOOK = 429, 641 | KEY_MESSENGER = 430, 642 | KEY_DISPLAYTOGGLE = 431, 643 | KEY_SPELLCHECK = 432, 644 | KEY_LOGOFF = 433, 645 | KEY_DOLLAR = 434, 646 | KEY_EURO = 435, 647 | KEY_FRAMEBACK = 436, 648 | KEY_FRAMEFORWARD = 437, 649 | KEY_CONTEXT_MENU = 438, 650 | KEY_MEDIA_REPEAT = 439, 651 | KEY_10CHANNELSUP = 440, 652 | KEY_10CHANNELSDOWN = 441, 653 | KEY_IMAGES = 442, 654 | KEY_NOTIFICATION_CENTER = 444, 655 | KEY_PICKUP_PHONE = 445, 656 | KEY_HANGUP_PHONE = 446, 657 | KEY_DEL_EOL = 448, 658 | KEY_DEL_EOS = 449, 659 | KEY_INS_LINE = 450, 660 | KEY_DEL_LINE = 451, 661 | KEY_FN = 464, 662 | KEY_FN_ESC = 465, 663 | KEY_FN_F1 = 466, 664 | KEY_FN_F2 = 467, 665 | KEY_FN_F3 = 468, 666 | KEY_FN_F4 = 469, 667 | KEY_FN_F5 = 470, 668 | KEY_FN_F6 = 471, 669 | KEY_FN_F7 = 472, 670 | KEY_FN_F8 = 473, 671 | KEY_FN_F9 = 474, 672 | KEY_FN_F10 = 475, 673 | KEY_FN_F11 = 476, 674 | KEY_FN_F12 = 477, 675 | KEY_FN_1 = 478, 676 | KEY_FN_2 = 479, 677 | KEY_FN_D = 480, 678 | KEY_FN_E = 481, 679 | KEY_FN_F = 482, 680 | KEY_FN_S = 483, 681 | KEY_FN_B = 484, 682 | KEY_FN_RIGHT_SHIFT = 485, 683 | KEY_BRL_DOT1 = 497, 684 | KEY_BRL_DOT2 = 498, 685 | KEY_BRL_DOT3 = 499, 686 | KEY_BRL_DOT4 = 500, 687 | KEY_BRL_DOT5 = 501, 688 | KEY_BRL_DOT6 = 502, 689 | KEY_BRL_DOT7 = 503, 690 | KEY_BRL_DOT8 = 504, 691 | KEY_BRL_DOT9 = 505, 692 | KEY_BRL_DOT10 = 506, 693 | KEY_NUMERIC_0 = 512, 694 | KEY_NUMERIC_1 = 513, 695 | KEY_NUMERIC_2 = 514, 696 | KEY_NUMERIC_3 = 515, 697 | KEY_NUMERIC_4 = 516, 698 | KEY_NUMERIC_5 = 517, 699 | KEY_NUMERIC_6 = 518, 700 | KEY_NUMERIC_7 = 519, 701 | KEY_NUMERIC_8 = 520, 702 | KEY_NUMERIC_9 = 521, 703 | KEY_NUMERIC_STAR = 522, 704 | KEY_NUMERIC_POUND = 523, 705 | KEY_NUMERIC_A = 524, 706 | KEY_NUMERIC_B = 525, 707 | KEY_NUMERIC_C = 526, 708 | KEY_NUMERIC_D = 527, 709 | KEY_CAMERA_FOCUS = 528, 710 | KEY_WPS_BUTTON = 529, 711 | KEY_TOUCHPAD_TOGGLE = 530, 712 | KEY_TOUCHPAD_ON = 531, 713 | KEY_TOUCHPAD_OFF = 532, 714 | KEY_CAMERA_ZOOMIN = 533, 715 | KEY_CAMERA_ZOOMOUT = 534, 716 | KEY_CAMERA_UP = 535, 717 | KEY_CAMERA_DOWN = 536, 718 | KEY_CAMERA_LEFT = 537, 719 | KEY_CAMERA_RIGHT = 538, 720 | KEY_ATTENDANT_ON = 539, 721 | KEY_ATTENDANT_OFF = 540, 722 | KEY_ATTENDANT_TOGGLE = 541, 723 | KEY_LIGHTS_TOGGLE = 542, 724 | KEY_ALS_TOGGLE = 560, 725 | KEY_ROTATE_LOCK_TOGGLE = 561, 726 | KEY_BUTTONCONFIG = 576, 727 | KEY_TASKMANAGER = 577, 728 | KEY_JOURNAL = 578, 729 | KEY_CONTROLPANEL = 579, 730 | KEY_APPSELECT = 580, 731 | KEY_SCREENSAVER = 581, 732 | KEY_VOICECOMMAND = 582, 733 | KEY_ASSISTANT = 583, 734 | KEY_KBD_LAYOUT_NEXT = 584, 735 | KEY_EMOJI_PICKER = 585, 736 | KEY_DICTATE = 586, 737 | KEY_CAMERA_ACCESS_ENABLE = 587, 738 | KEY_CAMERA_ACCESS_DISABLE = 588, 739 | KEY_CAMERA_ACCESS_TOGGLE = 589, 740 | KEY_BRIGHTNESS_MIN = 592, 741 | KEY_BRIGHTNESS_MAX = 593, 742 | KEY_KBDINPUTASSIST_PREV = 608, 743 | KEY_KBDINPUTASSIST_NEXT = 609, 744 | KEY_KBDINPUTASSIST_PREVGROUP = 610, 745 | KEY_KBDINPUTASSIST_NEXTGROUP = 611, 746 | KEY_KBDINPUTASSIST_ACCEPT = 612, 747 | KEY_KBDINPUTASSIST_CANCEL = 613, 748 | KEY_RIGHT_UP = 614, 749 | KEY_RIGHT_DOWN = 615, 750 | KEY_LEFT_UP = 616, 751 | KEY_LEFT_DOWN = 617, 752 | KEY_ROOT_MENU = 618, 753 | KEY_MEDIA_TOP_MENU = 619, 754 | KEY_NUMERIC_11 = 620, 755 | KEY_NUMERIC_12 = 621, 756 | KEY_AUDIO_DESC = 622, 757 | KEY_3D_MODE = 623, 758 | KEY_NEXT_FAVORITE = 624, 759 | KEY_STOP_RECORD = 625, 760 | KEY_PAUSE_RECORD = 626, 761 | KEY_VOD = 627, 762 | KEY_UNMUTE = 628, 763 | KEY_FASTREVERSE = 629, 764 | KEY_SLOWREVERSE = 630, 765 | KEY_DATA = 631, 766 | KEY_ONSCREEN_KEYBOARD = 632, 767 | KEY_PRIVACY_SCREEN_TOGGLE = 633, 768 | KEY_SELECTIVE_SCREENSHOT = 634, 769 | KEY_NEXT_ELEMENT = 635, 770 | KEY_PREVIOUS_ELEMENT = 636, 771 | KEY_AUTOPILOT_ENGAGE_TOGGLE = 637, 772 | KEY_MARK_WAYPOINT = 638, 773 | KEY_SOS = 639, 774 | KEY_NAV_CHART = 640, 775 | KEY_FISHING_CHART = 641, 776 | KEY_SINGLE_RANGE_RADAR = 642, 777 | KEY_DUAL_RANGE_RADAR = 643, 778 | KEY_RADAR_OVERLAY = 644, 779 | KEY_TRADITIONAL_SONAR = 645, 780 | KEY_CLEARVU_SONAR = 646, 781 | KEY_SIDEVU_SONAR = 647, 782 | KEY_NAV_INFO = 648, 783 | KEY_BRIGHTNESS_MENU = 649, 784 | KEY_MACRO1 = 656, 785 | KEY_MACRO2 = 657, 786 | KEY_MACRO3 = 658, 787 | KEY_MACRO4 = 659, 788 | KEY_MACRO5 = 660, 789 | KEY_MACRO6 = 661, 790 | KEY_MACRO7 = 662, 791 | KEY_MACRO8 = 663, 792 | KEY_MACRO9 = 664, 793 | KEY_MACRO10 = 665, 794 | KEY_MACRO11 = 666, 795 | KEY_MACRO12 = 667, 796 | KEY_MACRO13 = 668, 797 | KEY_MACRO14 = 669, 798 | KEY_MACRO15 = 670, 799 | KEY_MACRO16 = 671, 800 | KEY_MACRO17 = 672, 801 | KEY_MACRO18 = 673, 802 | KEY_MACRO19 = 674, 803 | KEY_MACRO20 = 675, 804 | KEY_MACRO21 = 676, 805 | KEY_MACRO22 = 677, 806 | KEY_MACRO23 = 678, 807 | KEY_MACRO24 = 679, 808 | KEY_MACRO25 = 680, 809 | KEY_MACRO26 = 681, 810 | KEY_MACRO27 = 682, 811 | KEY_MACRO28 = 683, 812 | KEY_MACRO29 = 684, 813 | KEY_MACRO30 = 685, 814 | KEY_MACRO_RECORD_START = 688, 815 | KEY_MACRO_RECORD_STOP = 689, 816 | KEY_MACRO_PRESET_CYCLE = 690, 817 | KEY_MACRO_PRESET1 = 691, 818 | KEY_MACRO_PRESET2 = 692, 819 | KEY_MACRO_PRESET3 = 693, 820 | KEY_KBD_LCD_MENU1 = 696, 821 | KEY_KBD_LCD_MENU2 = 697, 822 | KEY_KBD_LCD_MENU3 = 698, 823 | KEY_KBD_LCD_MENU4 = 699, 824 | KEY_KBD_LCD_MENU5 = 700, 825 | KEY_MAX = 767, 826 | BTN_0 = 256, 827 | BTN_1 = 257, 828 | BTN_2 = 258, 829 | BTN_3 = 259, 830 | BTN_4 = 260, 831 | BTN_5 = 261, 832 | BTN_6 = 262, 833 | BTN_7 = 263, 834 | BTN_8 = 264, 835 | BTN_9 = 265, 836 | BTN_LEFT = 272, 837 | BTN_RIGHT = 273, 838 | BTN_MIDDLE = 274, 839 | BTN_SIDE = 275, 840 | BTN_EXTRA = 276, 841 | BTN_FORWARD = 277, 842 | BTN_BACK = 278, 843 | BTN_TASK = 279, 844 | BTN_TRIGGER = 288, 845 | BTN_THUMB = 289, 846 | BTN_THUMB2 = 290, 847 | BTN_TOP = 291, 848 | BTN_TOP2 = 292, 849 | BTN_PINKIE = 293, 850 | BTN_BASE = 294, 851 | BTN_BASE2 = 295, 852 | BTN_BASE3 = 296, 853 | BTN_BASE4 = 297, 854 | BTN_BASE5 = 298, 855 | BTN_BASE6 = 299, 856 | BTN_DEAD = 303, 857 | BTN_SOUTH = 304, 858 | BTN_EAST = 305, 859 | BTN_C = 306, 860 | BTN_NORTH = 307, 861 | BTN_WEST = 308, 862 | BTN_Z = 309, 863 | BTN_TL = 310, 864 | BTN_TR = 311, 865 | BTN_TL2 = 312, 866 | BTN_TR2 = 313, 867 | BTN_SELECT = 314, 868 | BTN_START = 315, 869 | BTN_MODE = 316, 870 | BTN_THUMBL = 317, 871 | BTN_THUMBR = 318, 872 | BTN_TOOL_PEN = 320, 873 | BTN_TOOL_RUBBER = 321, 874 | BTN_TOOL_BRUSH = 322, 875 | BTN_TOOL_PENCIL = 323, 876 | BTN_TOOL_AIRBRUSH = 324, 877 | BTN_TOOL_FINGER = 325, 878 | BTN_TOOL_MOUSE = 326, 879 | BTN_TOOL_LENS = 327, 880 | BTN_TOOL_QUINTTAP = 328, 881 | BTN_STYLUS3 = 329, 882 | BTN_TOUCH = 330, 883 | BTN_STYLUS = 331, 884 | BTN_STYLUS2 = 332, 885 | BTN_TOOL_DOUBLETAP = 333, 886 | BTN_TOOL_TRIPLETAP = 334, 887 | BTN_TOOL_QUADTAP = 335, 888 | BTN_GEAR_DOWN = 336, 889 | BTN_GEAR_UP = 337, 890 | BTN_DPAD_UP = 544, 891 | BTN_DPAD_DOWN = 545, 892 | BTN_DPAD_LEFT = 546, 893 | BTN_DPAD_RIGHT = 547, 894 | BTN_TRIGGER_HAPPY1 = 704, 895 | BTN_TRIGGER_HAPPY2 = 705, 896 | BTN_TRIGGER_HAPPY3 = 706, 897 | BTN_TRIGGER_HAPPY4 = 707, 898 | BTN_TRIGGER_HAPPY5 = 708, 899 | BTN_TRIGGER_HAPPY6 = 709, 900 | BTN_TRIGGER_HAPPY7 = 710, 901 | BTN_TRIGGER_HAPPY8 = 711, 902 | BTN_TRIGGER_HAPPY9 = 712, 903 | BTN_TRIGGER_HAPPY10 = 713, 904 | BTN_TRIGGER_HAPPY11 = 714, 905 | BTN_TRIGGER_HAPPY12 = 715, 906 | BTN_TRIGGER_HAPPY13 = 716, 907 | BTN_TRIGGER_HAPPY14 = 717, 908 | BTN_TRIGGER_HAPPY15 = 718, 909 | BTN_TRIGGER_HAPPY16 = 719, 910 | BTN_TRIGGER_HAPPY17 = 720, 911 | BTN_TRIGGER_HAPPY18 = 721, 912 | BTN_TRIGGER_HAPPY19 = 722, 913 | BTN_TRIGGER_HAPPY20 = 723, 914 | BTN_TRIGGER_HAPPY21 = 724, 915 | BTN_TRIGGER_HAPPY22 = 725, 916 | BTN_TRIGGER_HAPPY23 = 726, 917 | BTN_TRIGGER_HAPPY24 = 727, 918 | BTN_TRIGGER_HAPPY25 = 728, 919 | BTN_TRIGGER_HAPPY26 = 729, 920 | BTN_TRIGGER_HAPPY27 = 730, 921 | BTN_TRIGGER_HAPPY28 = 731, 922 | BTN_TRIGGER_HAPPY29 = 732, 923 | BTN_TRIGGER_HAPPY30 = 733, 924 | BTN_TRIGGER_HAPPY31 = 734, 925 | BTN_TRIGGER_HAPPY32 = 735, 926 | BTN_TRIGGER_HAPPY33 = 736, 927 | BTN_TRIGGER_HAPPY34 = 737, 928 | BTN_TRIGGER_HAPPY35 = 738, 929 | BTN_TRIGGER_HAPPY36 = 739, 930 | BTN_TRIGGER_HAPPY37 = 740, 931 | BTN_TRIGGER_HAPPY38 = 741, 932 | BTN_TRIGGER_HAPPY39 = 742, 933 | BTN_TRIGGER_HAPPY40 = 743, 934 | } 935 | 936 | pub const fn int_to_ev_key(code: u32) -> Option { 937 | match code { 938 | 0 => Some(EV_KEY::KEY_RESERVED), 939 | 1 => Some(EV_KEY::KEY_ESC), 940 | 2 => Some(EV_KEY::KEY_1), 941 | 3 => Some(EV_KEY::KEY_2), 942 | 4 => Some(EV_KEY::KEY_3), 943 | 5 => Some(EV_KEY::KEY_4), 944 | 6 => Some(EV_KEY::KEY_5), 945 | 7 => Some(EV_KEY::KEY_6), 946 | 8 => Some(EV_KEY::KEY_7), 947 | 9 => Some(EV_KEY::KEY_8), 948 | 10 => Some(EV_KEY::KEY_9), 949 | 11 => Some(EV_KEY::KEY_0), 950 | 12 => Some(EV_KEY::KEY_MINUS), 951 | 13 => Some(EV_KEY::KEY_EQUAL), 952 | 14 => Some(EV_KEY::KEY_BACKSPACE), 953 | 15 => Some(EV_KEY::KEY_TAB), 954 | 16 => Some(EV_KEY::KEY_Q), 955 | 17 => Some(EV_KEY::KEY_W), 956 | 18 => Some(EV_KEY::KEY_E), 957 | 19 => Some(EV_KEY::KEY_R), 958 | 20 => Some(EV_KEY::KEY_T), 959 | 21 => Some(EV_KEY::KEY_Y), 960 | 22 => Some(EV_KEY::KEY_U), 961 | 23 => Some(EV_KEY::KEY_I), 962 | 24 => Some(EV_KEY::KEY_O), 963 | 25 => Some(EV_KEY::KEY_P), 964 | 26 => Some(EV_KEY::KEY_LEFTBRACE), 965 | 27 => Some(EV_KEY::KEY_RIGHTBRACE), 966 | 28 => Some(EV_KEY::KEY_ENTER), 967 | 29 => Some(EV_KEY::KEY_LEFTCTRL), 968 | 30 => Some(EV_KEY::KEY_A), 969 | 31 => Some(EV_KEY::KEY_S), 970 | 32 => Some(EV_KEY::KEY_D), 971 | 33 => Some(EV_KEY::KEY_F), 972 | 34 => Some(EV_KEY::KEY_G), 973 | 35 => Some(EV_KEY::KEY_H), 974 | 36 => Some(EV_KEY::KEY_J), 975 | 37 => Some(EV_KEY::KEY_K), 976 | 38 => Some(EV_KEY::KEY_L), 977 | 39 => Some(EV_KEY::KEY_SEMICOLON), 978 | 40 => Some(EV_KEY::KEY_APOSTROPHE), 979 | 41 => Some(EV_KEY::KEY_GRAVE), 980 | 42 => Some(EV_KEY::KEY_LEFTSHIFT), 981 | 43 => Some(EV_KEY::KEY_BACKSLASH), 982 | 44 => Some(EV_KEY::KEY_Z), 983 | 45 => Some(EV_KEY::KEY_X), 984 | 46 => Some(EV_KEY::KEY_C), 985 | 47 => Some(EV_KEY::KEY_V), 986 | 48 => Some(EV_KEY::KEY_B), 987 | 49 => Some(EV_KEY::KEY_N), 988 | 50 => Some(EV_KEY::KEY_M), 989 | 51 => Some(EV_KEY::KEY_COMMA), 990 | 52 => Some(EV_KEY::KEY_DOT), 991 | 53 => Some(EV_KEY::KEY_SLASH), 992 | 54 => Some(EV_KEY::KEY_RIGHTSHIFT), 993 | 55 => Some(EV_KEY::KEY_KPASTERISK), 994 | 56 => Some(EV_KEY::KEY_LEFTALT), 995 | 57 => Some(EV_KEY::KEY_SPACE), 996 | 58 => Some(EV_KEY::KEY_CAPSLOCK), 997 | 59 => Some(EV_KEY::KEY_F1), 998 | 60 => Some(EV_KEY::KEY_F2), 999 | 61 => Some(EV_KEY::KEY_F3), 1000 | 62 => Some(EV_KEY::KEY_F4), 1001 | 63 => Some(EV_KEY::KEY_F5), 1002 | 64 => Some(EV_KEY::KEY_F6), 1003 | 65 => Some(EV_KEY::KEY_F7), 1004 | 66 => Some(EV_KEY::KEY_F8), 1005 | 67 => Some(EV_KEY::KEY_F9), 1006 | 68 => Some(EV_KEY::KEY_F10), 1007 | 69 => Some(EV_KEY::KEY_NUMLOCK), 1008 | 70 => Some(EV_KEY::KEY_SCROLLLOCK), 1009 | 71 => Some(EV_KEY::KEY_KP7), 1010 | 72 => Some(EV_KEY::KEY_KP8), 1011 | 73 => Some(EV_KEY::KEY_KP9), 1012 | 74 => Some(EV_KEY::KEY_KPMINUS), 1013 | 75 => Some(EV_KEY::KEY_KP4), 1014 | 76 => Some(EV_KEY::KEY_KP5), 1015 | 77 => Some(EV_KEY::KEY_KP6), 1016 | 78 => Some(EV_KEY::KEY_KPPLUS), 1017 | 79 => Some(EV_KEY::KEY_KP1), 1018 | 80 => Some(EV_KEY::KEY_KP2), 1019 | 81 => Some(EV_KEY::KEY_KP3), 1020 | 82 => Some(EV_KEY::KEY_KP0), 1021 | 83 => Some(EV_KEY::KEY_KPDOT), 1022 | 85 => Some(EV_KEY::KEY_ZENKAKUHANKAKU), 1023 | 86 => Some(EV_KEY::KEY_102ND), 1024 | 87 => Some(EV_KEY::KEY_F11), 1025 | 88 => Some(EV_KEY::KEY_F12), 1026 | 89 => Some(EV_KEY::KEY_RO), 1027 | 90 => Some(EV_KEY::KEY_KATAKANA), 1028 | 91 => Some(EV_KEY::KEY_HIRAGANA), 1029 | 92 => Some(EV_KEY::KEY_HENKAN), 1030 | 93 => Some(EV_KEY::KEY_KATAKANAHIRAGANA), 1031 | 94 => Some(EV_KEY::KEY_MUHENKAN), 1032 | 95 => Some(EV_KEY::KEY_KPJPCOMMA), 1033 | 96 => Some(EV_KEY::KEY_KPENTER), 1034 | 97 => Some(EV_KEY::KEY_RIGHTCTRL), 1035 | 98 => Some(EV_KEY::KEY_KPSLASH), 1036 | 99 => Some(EV_KEY::KEY_SYSRQ), 1037 | 100 => Some(EV_KEY::KEY_RIGHTALT), 1038 | 101 => Some(EV_KEY::KEY_LINEFEED), 1039 | 102 => Some(EV_KEY::KEY_HOME), 1040 | 103 => Some(EV_KEY::KEY_UP), 1041 | 104 => Some(EV_KEY::KEY_PAGEUP), 1042 | 105 => Some(EV_KEY::KEY_LEFT), 1043 | 106 => Some(EV_KEY::KEY_RIGHT), 1044 | 107 => Some(EV_KEY::KEY_END), 1045 | 108 => Some(EV_KEY::KEY_DOWN), 1046 | 109 => Some(EV_KEY::KEY_PAGEDOWN), 1047 | 110 => Some(EV_KEY::KEY_INSERT), 1048 | 111 => Some(EV_KEY::KEY_DELETE), 1049 | 112 => Some(EV_KEY::KEY_MACRO), 1050 | 113 => Some(EV_KEY::KEY_MUTE), 1051 | 114 => Some(EV_KEY::KEY_VOLUMEDOWN), 1052 | 115 => Some(EV_KEY::KEY_VOLUMEUP), 1053 | 116 => Some(EV_KEY::KEY_POWER), 1054 | 117 => Some(EV_KEY::KEY_KPEQUAL), 1055 | 118 => Some(EV_KEY::KEY_KPPLUSMINUS), 1056 | 119 => Some(EV_KEY::KEY_PAUSE), 1057 | 120 => Some(EV_KEY::KEY_SCALE), 1058 | 121 => Some(EV_KEY::KEY_KPCOMMA), 1059 | 122 => Some(EV_KEY::KEY_HANGEUL), 1060 | 123 => Some(EV_KEY::KEY_HANJA), 1061 | 124 => Some(EV_KEY::KEY_YEN), 1062 | 125 => Some(EV_KEY::KEY_LEFTMETA), 1063 | 126 => Some(EV_KEY::KEY_RIGHTMETA), 1064 | 127 => Some(EV_KEY::KEY_COMPOSE), 1065 | 128 => Some(EV_KEY::KEY_STOP), 1066 | 129 => Some(EV_KEY::KEY_AGAIN), 1067 | 130 => Some(EV_KEY::KEY_PROPS), 1068 | 131 => Some(EV_KEY::KEY_UNDO), 1069 | 132 => Some(EV_KEY::KEY_FRONT), 1070 | 133 => Some(EV_KEY::KEY_COPY), 1071 | 134 => Some(EV_KEY::KEY_OPEN), 1072 | 135 => Some(EV_KEY::KEY_PASTE), 1073 | 136 => Some(EV_KEY::KEY_FIND), 1074 | 137 => Some(EV_KEY::KEY_CUT), 1075 | 138 => Some(EV_KEY::KEY_HELP), 1076 | 139 => Some(EV_KEY::KEY_MENU), 1077 | 140 => Some(EV_KEY::KEY_CALC), 1078 | 141 => Some(EV_KEY::KEY_SETUP), 1079 | 142 => Some(EV_KEY::KEY_SLEEP), 1080 | 143 => Some(EV_KEY::KEY_WAKEUP), 1081 | 144 => Some(EV_KEY::KEY_FILE), 1082 | 145 => Some(EV_KEY::KEY_SENDFILE), 1083 | 146 => Some(EV_KEY::KEY_DELETEFILE), 1084 | 147 => Some(EV_KEY::KEY_XFER), 1085 | 148 => Some(EV_KEY::KEY_PROG1), 1086 | 149 => Some(EV_KEY::KEY_PROG2), 1087 | 150 => Some(EV_KEY::KEY_WWW), 1088 | 151 => Some(EV_KEY::KEY_MSDOS), 1089 | 152 => Some(EV_KEY::KEY_COFFEE), 1090 | 153 => Some(EV_KEY::KEY_ROTATE_DISPLAY), 1091 | 154 => Some(EV_KEY::KEY_CYCLEWINDOWS), 1092 | 155 => Some(EV_KEY::KEY_MAIL), 1093 | 156 => Some(EV_KEY::KEY_BOOKMARKS), 1094 | 157 => Some(EV_KEY::KEY_COMPUTER), 1095 | 158 => Some(EV_KEY::KEY_BACK), 1096 | 159 => Some(EV_KEY::KEY_FORWARD), 1097 | 160 => Some(EV_KEY::KEY_CLOSECD), 1098 | 161 => Some(EV_KEY::KEY_EJECTCD), 1099 | 162 => Some(EV_KEY::KEY_EJECTCLOSECD), 1100 | 163 => Some(EV_KEY::KEY_NEXTSONG), 1101 | 164 => Some(EV_KEY::KEY_PLAYPAUSE), 1102 | 165 => Some(EV_KEY::KEY_PREVIOUSSONG), 1103 | 166 => Some(EV_KEY::KEY_STOPCD), 1104 | 167 => Some(EV_KEY::KEY_RECORD), 1105 | 168 => Some(EV_KEY::KEY_REWIND), 1106 | 169 => Some(EV_KEY::KEY_PHONE), 1107 | 170 => Some(EV_KEY::KEY_ISO), 1108 | 171 => Some(EV_KEY::KEY_CONFIG), 1109 | 172 => Some(EV_KEY::KEY_HOMEPAGE), 1110 | 173 => Some(EV_KEY::KEY_REFRESH), 1111 | 174 => Some(EV_KEY::KEY_EXIT), 1112 | 175 => Some(EV_KEY::KEY_MOVE), 1113 | 176 => Some(EV_KEY::KEY_EDIT), 1114 | 177 => Some(EV_KEY::KEY_SCROLLUP), 1115 | 178 => Some(EV_KEY::KEY_SCROLLDOWN), 1116 | 179 => Some(EV_KEY::KEY_KPLEFTPAREN), 1117 | 180 => Some(EV_KEY::KEY_KPRIGHTPAREN), 1118 | 181 => Some(EV_KEY::KEY_NEW), 1119 | 182 => Some(EV_KEY::KEY_REDO), 1120 | 183 => Some(EV_KEY::KEY_F13), 1121 | 184 => Some(EV_KEY::KEY_F14), 1122 | 185 => Some(EV_KEY::KEY_F15), 1123 | 186 => Some(EV_KEY::KEY_F16), 1124 | 187 => Some(EV_KEY::KEY_F17), 1125 | 188 => Some(EV_KEY::KEY_F18), 1126 | 189 => Some(EV_KEY::KEY_F19), 1127 | 190 => Some(EV_KEY::KEY_F20), 1128 | 191 => Some(EV_KEY::KEY_F21), 1129 | 192 => Some(EV_KEY::KEY_F22), 1130 | 193 => Some(EV_KEY::KEY_F23), 1131 | 194 => Some(EV_KEY::KEY_F24), 1132 | 200 => Some(EV_KEY::KEY_PLAYCD), 1133 | 201 => Some(EV_KEY::KEY_PAUSECD), 1134 | 202 => Some(EV_KEY::KEY_PROG3), 1135 | 203 => Some(EV_KEY::KEY_PROG4), 1136 | 204 => Some(EV_KEY::KEY_ALL_APPLICATIONS), 1137 | 205 => Some(EV_KEY::KEY_SUSPEND), 1138 | 206 => Some(EV_KEY::KEY_CLOSE), 1139 | 207 => Some(EV_KEY::KEY_PLAY), 1140 | 208 => Some(EV_KEY::KEY_FASTFORWARD), 1141 | 209 => Some(EV_KEY::KEY_BASSBOOST), 1142 | 210 => Some(EV_KEY::KEY_PRINT), 1143 | 211 => Some(EV_KEY::KEY_HP), 1144 | 212 => Some(EV_KEY::KEY_CAMERA), 1145 | 213 => Some(EV_KEY::KEY_SOUND), 1146 | 214 => Some(EV_KEY::KEY_QUESTION), 1147 | 215 => Some(EV_KEY::KEY_EMAIL), 1148 | 216 => Some(EV_KEY::KEY_CHAT), 1149 | 217 => Some(EV_KEY::KEY_SEARCH), 1150 | 218 => Some(EV_KEY::KEY_CONNECT), 1151 | 219 => Some(EV_KEY::KEY_FINANCE), 1152 | 220 => Some(EV_KEY::KEY_SPORT), 1153 | 221 => Some(EV_KEY::KEY_SHOP), 1154 | 222 => Some(EV_KEY::KEY_ALTERASE), 1155 | 223 => Some(EV_KEY::KEY_CANCEL), 1156 | 224 => Some(EV_KEY::KEY_BRIGHTNESSDOWN), 1157 | 225 => Some(EV_KEY::KEY_BRIGHTNESSUP), 1158 | 226 => Some(EV_KEY::KEY_MEDIA), 1159 | 227 => Some(EV_KEY::KEY_SWITCHVIDEOMODE), 1160 | 228 => Some(EV_KEY::KEY_KBDILLUMTOGGLE), 1161 | 229 => Some(EV_KEY::KEY_KBDILLUMDOWN), 1162 | 230 => Some(EV_KEY::KEY_KBDILLUMUP), 1163 | 231 => Some(EV_KEY::KEY_SEND), 1164 | 232 => Some(EV_KEY::KEY_REPLY), 1165 | 233 => Some(EV_KEY::KEY_FORWARDMAIL), 1166 | 234 => Some(EV_KEY::KEY_SAVE), 1167 | 235 => Some(EV_KEY::KEY_DOCUMENTS), 1168 | 236 => Some(EV_KEY::KEY_BATTERY), 1169 | 237 => Some(EV_KEY::KEY_BLUETOOTH), 1170 | 238 => Some(EV_KEY::KEY_WLAN), 1171 | 239 => Some(EV_KEY::KEY_UWB), 1172 | 240 => Some(EV_KEY::KEY_UNKNOWN), 1173 | 241 => Some(EV_KEY::KEY_VIDEO_NEXT), 1174 | 242 => Some(EV_KEY::KEY_VIDEO_PREV), 1175 | 243 => Some(EV_KEY::KEY_BRIGHTNESS_CYCLE), 1176 | 244 => Some(EV_KEY::KEY_BRIGHTNESS_AUTO), 1177 | 245 => Some(EV_KEY::KEY_DISPLAY_OFF), 1178 | 246 => Some(EV_KEY::KEY_WWAN), 1179 | 247 => Some(EV_KEY::KEY_RFKILL), 1180 | 248 => Some(EV_KEY::KEY_MICMUTE), 1181 | 352 => Some(EV_KEY::KEY_OK), 1182 | 353 => Some(EV_KEY::KEY_SELECT), 1183 | 354 => Some(EV_KEY::KEY_GOTO), 1184 | 355 => Some(EV_KEY::KEY_CLEAR), 1185 | 356 => Some(EV_KEY::KEY_POWER2), 1186 | 357 => Some(EV_KEY::KEY_OPTION), 1187 | 358 => Some(EV_KEY::KEY_INFO), 1188 | 359 => Some(EV_KEY::KEY_TIME), 1189 | 360 => Some(EV_KEY::KEY_VENDOR), 1190 | 361 => Some(EV_KEY::KEY_ARCHIVE), 1191 | 362 => Some(EV_KEY::KEY_PROGRAM), 1192 | 363 => Some(EV_KEY::KEY_CHANNEL), 1193 | 364 => Some(EV_KEY::KEY_FAVORITES), 1194 | 365 => Some(EV_KEY::KEY_EPG), 1195 | 366 => Some(EV_KEY::KEY_PVR), 1196 | 367 => Some(EV_KEY::KEY_MHP), 1197 | 368 => Some(EV_KEY::KEY_LANGUAGE), 1198 | 369 => Some(EV_KEY::KEY_TITLE), 1199 | 370 => Some(EV_KEY::KEY_SUBTITLE), 1200 | 371 => Some(EV_KEY::KEY_ANGLE), 1201 | 372 => Some(EV_KEY::KEY_FULL_SCREEN), 1202 | 373 => Some(EV_KEY::KEY_MODE), 1203 | 374 => Some(EV_KEY::KEY_KEYBOARD), 1204 | 375 => Some(EV_KEY::KEY_ASPECT_RATIO), 1205 | 376 => Some(EV_KEY::KEY_PC), 1206 | 377 => Some(EV_KEY::KEY_TV), 1207 | 378 => Some(EV_KEY::KEY_TV2), 1208 | 379 => Some(EV_KEY::KEY_VCR), 1209 | 380 => Some(EV_KEY::KEY_VCR2), 1210 | 381 => Some(EV_KEY::KEY_SAT), 1211 | 382 => Some(EV_KEY::KEY_SAT2), 1212 | 383 => Some(EV_KEY::KEY_CD), 1213 | 384 => Some(EV_KEY::KEY_TAPE), 1214 | 385 => Some(EV_KEY::KEY_RADIO), 1215 | 386 => Some(EV_KEY::KEY_TUNER), 1216 | 387 => Some(EV_KEY::KEY_PLAYER), 1217 | 388 => Some(EV_KEY::KEY_TEXT), 1218 | 389 => Some(EV_KEY::KEY_DVD), 1219 | 390 => Some(EV_KEY::KEY_AUX), 1220 | 391 => Some(EV_KEY::KEY_MP3), 1221 | 392 => Some(EV_KEY::KEY_AUDIO), 1222 | 393 => Some(EV_KEY::KEY_VIDEO), 1223 | 394 => Some(EV_KEY::KEY_DIRECTORY), 1224 | 395 => Some(EV_KEY::KEY_LIST), 1225 | 396 => Some(EV_KEY::KEY_MEMO), 1226 | 397 => Some(EV_KEY::KEY_CALENDAR), 1227 | 398 => Some(EV_KEY::KEY_RED), 1228 | 399 => Some(EV_KEY::KEY_GREEN), 1229 | 400 => Some(EV_KEY::KEY_YELLOW), 1230 | 401 => Some(EV_KEY::KEY_BLUE), 1231 | 402 => Some(EV_KEY::KEY_CHANNELUP), 1232 | 403 => Some(EV_KEY::KEY_CHANNELDOWN), 1233 | 404 => Some(EV_KEY::KEY_FIRST), 1234 | 405 => Some(EV_KEY::KEY_LAST), 1235 | 406 => Some(EV_KEY::KEY_AB), 1236 | 407 => Some(EV_KEY::KEY_NEXT), 1237 | 408 => Some(EV_KEY::KEY_RESTART), 1238 | 409 => Some(EV_KEY::KEY_SLOW), 1239 | 410 => Some(EV_KEY::KEY_SHUFFLE), 1240 | 411 => Some(EV_KEY::KEY_BREAK), 1241 | 412 => Some(EV_KEY::KEY_PREVIOUS), 1242 | 413 => Some(EV_KEY::KEY_DIGITS), 1243 | 414 => Some(EV_KEY::KEY_TEEN), 1244 | 415 => Some(EV_KEY::KEY_TWEN), 1245 | 416 => Some(EV_KEY::KEY_VIDEOPHONE), 1246 | 417 => Some(EV_KEY::KEY_GAMES), 1247 | 418 => Some(EV_KEY::KEY_ZOOMIN), 1248 | 419 => Some(EV_KEY::KEY_ZOOMOUT), 1249 | 420 => Some(EV_KEY::KEY_ZOOMRESET), 1250 | 421 => Some(EV_KEY::KEY_WORDPROCESSOR), 1251 | 422 => Some(EV_KEY::KEY_EDITOR), 1252 | 423 => Some(EV_KEY::KEY_SPREADSHEET), 1253 | 424 => Some(EV_KEY::KEY_GRAPHICSEDITOR), 1254 | 425 => Some(EV_KEY::KEY_PRESENTATION), 1255 | 426 => Some(EV_KEY::KEY_DATABASE), 1256 | 427 => Some(EV_KEY::KEY_NEWS), 1257 | 428 => Some(EV_KEY::KEY_VOICEMAIL), 1258 | 429 => Some(EV_KEY::KEY_ADDRESSBOOK), 1259 | 430 => Some(EV_KEY::KEY_MESSENGER), 1260 | 431 => Some(EV_KEY::KEY_DISPLAYTOGGLE), 1261 | 432 => Some(EV_KEY::KEY_SPELLCHECK), 1262 | 433 => Some(EV_KEY::KEY_LOGOFF), 1263 | 434 => Some(EV_KEY::KEY_DOLLAR), 1264 | 435 => Some(EV_KEY::KEY_EURO), 1265 | 436 => Some(EV_KEY::KEY_FRAMEBACK), 1266 | 437 => Some(EV_KEY::KEY_FRAMEFORWARD), 1267 | 438 => Some(EV_KEY::KEY_CONTEXT_MENU), 1268 | 439 => Some(EV_KEY::KEY_MEDIA_REPEAT), 1269 | 440 => Some(EV_KEY::KEY_10CHANNELSUP), 1270 | 441 => Some(EV_KEY::KEY_10CHANNELSDOWN), 1271 | 442 => Some(EV_KEY::KEY_IMAGES), 1272 | 444 => Some(EV_KEY::KEY_NOTIFICATION_CENTER), 1273 | 445 => Some(EV_KEY::KEY_PICKUP_PHONE), 1274 | 446 => Some(EV_KEY::KEY_HANGUP_PHONE), 1275 | 448 => Some(EV_KEY::KEY_DEL_EOL), 1276 | 449 => Some(EV_KEY::KEY_DEL_EOS), 1277 | 450 => Some(EV_KEY::KEY_INS_LINE), 1278 | 451 => Some(EV_KEY::KEY_DEL_LINE), 1279 | 464 => Some(EV_KEY::KEY_FN), 1280 | 465 => Some(EV_KEY::KEY_FN_ESC), 1281 | 466 => Some(EV_KEY::KEY_FN_F1), 1282 | 467 => Some(EV_KEY::KEY_FN_F2), 1283 | 468 => Some(EV_KEY::KEY_FN_F3), 1284 | 469 => Some(EV_KEY::KEY_FN_F4), 1285 | 470 => Some(EV_KEY::KEY_FN_F5), 1286 | 471 => Some(EV_KEY::KEY_FN_F6), 1287 | 472 => Some(EV_KEY::KEY_FN_F7), 1288 | 473 => Some(EV_KEY::KEY_FN_F8), 1289 | 474 => Some(EV_KEY::KEY_FN_F9), 1290 | 475 => Some(EV_KEY::KEY_FN_F10), 1291 | 476 => Some(EV_KEY::KEY_FN_F11), 1292 | 477 => Some(EV_KEY::KEY_FN_F12), 1293 | 478 => Some(EV_KEY::KEY_FN_1), 1294 | 479 => Some(EV_KEY::KEY_FN_2), 1295 | 480 => Some(EV_KEY::KEY_FN_D), 1296 | 481 => Some(EV_KEY::KEY_FN_E), 1297 | 482 => Some(EV_KEY::KEY_FN_F), 1298 | 483 => Some(EV_KEY::KEY_FN_S), 1299 | 484 => Some(EV_KEY::KEY_FN_B), 1300 | 485 => Some(EV_KEY::KEY_FN_RIGHT_SHIFT), 1301 | 497 => Some(EV_KEY::KEY_BRL_DOT1), 1302 | 498 => Some(EV_KEY::KEY_BRL_DOT2), 1303 | 499 => Some(EV_KEY::KEY_BRL_DOT3), 1304 | 500 => Some(EV_KEY::KEY_BRL_DOT4), 1305 | 501 => Some(EV_KEY::KEY_BRL_DOT5), 1306 | 502 => Some(EV_KEY::KEY_BRL_DOT6), 1307 | 503 => Some(EV_KEY::KEY_BRL_DOT7), 1308 | 504 => Some(EV_KEY::KEY_BRL_DOT8), 1309 | 505 => Some(EV_KEY::KEY_BRL_DOT9), 1310 | 506 => Some(EV_KEY::KEY_BRL_DOT10), 1311 | 512 => Some(EV_KEY::KEY_NUMERIC_0), 1312 | 513 => Some(EV_KEY::KEY_NUMERIC_1), 1313 | 514 => Some(EV_KEY::KEY_NUMERIC_2), 1314 | 515 => Some(EV_KEY::KEY_NUMERIC_3), 1315 | 516 => Some(EV_KEY::KEY_NUMERIC_4), 1316 | 517 => Some(EV_KEY::KEY_NUMERIC_5), 1317 | 518 => Some(EV_KEY::KEY_NUMERIC_6), 1318 | 519 => Some(EV_KEY::KEY_NUMERIC_7), 1319 | 520 => Some(EV_KEY::KEY_NUMERIC_8), 1320 | 521 => Some(EV_KEY::KEY_NUMERIC_9), 1321 | 522 => Some(EV_KEY::KEY_NUMERIC_STAR), 1322 | 523 => Some(EV_KEY::KEY_NUMERIC_POUND), 1323 | 524 => Some(EV_KEY::KEY_NUMERIC_A), 1324 | 525 => Some(EV_KEY::KEY_NUMERIC_B), 1325 | 526 => Some(EV_KEY::KEY_NUMERIC_C), 1326 | 527 => Some(EV_KEY::KEY_NUMERIC_D), 1327 | 528 => Some(EV_KEY::KEY_CAMERA_FOCUS), 1328 | 529 => Some(EV_KEY::KEY_WPS_BUTTON), 1329 | 530 => Some(EV_KEY::KEY_TOUCHPAD_TOGGLE), 1330 | 531 => Some(EV_KEY::KEY_TOUCHPAD_ON), 1331 | 532 => Some(EV_KEY::KEY_TOUCHPAD_OFF), 1332 | 533 => Some(EV_KEY::KEY_CAMERA_ZOOMIN), 1333 | 534 => Some(EV_KEY::KEY_CAMERA_ZOOMOUT), 1334 | 535 => Some(EV_KEY::KEY_CAMERA_UP), 1335 | 536 => Some(EV_KEY::KEY_CAMERA_DOWN), 1336 | 537 => Some(EV_KEY::KEY_CAMERA_LEFT), 1337 | 538 => Some(EV_KEY::KEY_CAMERA_RIGHT), 1338 | 539 => Some(EV_KEY::KEY_ATTENDANT_ON), 1339 | 540 => Some(EV_KEY::KEY_ATTENDANT_OFF), 1340 | 541 => Some(EV_KEY::KEY_ATTENDANT_TOGGLE), 1341 | 542 => Some(EV_KEY::KEY_LIGHTS_TOGGLE), 1342 | 560 => Some(EV_KEY::KEY_ALS_TOGGLE), 1343 | 561 => Some(EV_KEY::KEY_ROTATE_LOCK_TOGGLE), 1344 | 576 => Some(EV_KEY::KEY_BUTTONCONFIG), 1345 | 577 => Some(EV_KEY::KEY_TASKMANAGER), 1346 | 578 => Some(EV_KEY::KEY_JOURNAL), 1347 | 579 => Some(EV_KEY::KEY_CONTROLPANEL), 1348 | 580 => Some(EV_KEY::KEY_APPSELECT), 1349 | 581 => Some(EV_KEY::KEY_SCREENSAVER), 1350 | 582 => Some(EV_KEY::KEY_VOICECOMMAND), 1351 | 583 => Some(EV_KEY::KEY_ASSISTANT), 1352 | 584 => Some(EV_KEY::KEY_KBD_LAYOUT_NEXT), 1353 | 585 => Some(EV_KEY::KEY_EMOJI_PICKER), 1354 | 586 => Some(EV_KEY::KEY_DICTATE), 1355 | 587 => Some(EV_KEY::KEY_CAMERA_ACCESS_ENABLE), 1356 | 588 => Some(EV_KEY::KEY_CAMERA_ACCESS_DISABLE), 1357 | 589 => Some(EV_KEY::KEY_CAMERA_ACCESS_TOGGLE), 1358 | 592 => Some(EV_KEY::KEY_BRIGHTNESS_MIN), 1359 | 593 => Some(EV_KEY::KEY_BRIGHTNESS_MAX), 1360 | 608 => Some(EV_KEY::KEY_KBDINPUTASSIST_PREV), 1361 | 609 => Some(EV_KEY::KEY_KBDINPUTASSIST_NEXT), 1362 | 610 => Some(EV_KEY::KEY_KBDINPUTASSIST_PREVGROUP), 1363 | 611 => Some(EV_KEY::KEY_KBDINPUTASSIST_NEXTGROUP), 1364 | 612 => Some(EV_KEY::KEY_KBDINPUTASSIST_ACCEPT), 1365 | 613 => Some(EV_KEY::KEY_KBDINPUTASSIST_CANCEL), 1366 | 614 => Some(EV_KEY::KEY_RIGHT_UP), 1367 | 615 => Some(EV_KEY::KEY_RIGHT_DOWN), 1368 | 616 => Some(EV_KEY::KEY_LEFT_UP), 1369 | 617 => Some(EV_KEY::KEY_LEFT_DOWN), 1370 | 618 => Some(EV_KEY::KEY_ROOT_MENU), 1371 | 619 => Some(EV_KEY::KEY_MEDIA_TOP_MENU), 1372 | 620 => Some(EV_KEY::KEY_NUMERIC_11), 1373 | 621 => Some(EV_KEY::KEY_NUMERIC_12), 1374 | 622 => Some(EV_KEY::KEY_AUDIO_DESC), 1375 | 623 => Some(EV_KEY::KEY_3D_MODE), 1376 | 624 => Some(EV_KEY::KEY_NEXT_FAVORITE), 1377 | 625 => Some(EV_KEY::KEY_STOP_RECORD), 1378 | 626 => Some(EV_KEY::KEY_PAUSE_RECORD), 1379 | 627 => Some(EV_KEY::KEY_VOD), 1380 | 628 => Some(EV_KEY::KEY_UNMUTE), 1381 | 629 => Some(EV_KEY::KEY_FASTREVERSE), 1382 | 630 => Some(EV_KEY::KEY_SLOWREVERSE), 1383 | 631 => Some(EV_KEY::KEY_DATA), 1384 | 632 => Some(EV_KEY::KEY_ONSCREEN_KEYBOARD), 1385 | 633 => Some(EV_KEY::KEY_PRIVACY_SCREEN_TOGGLE), 1386 | 634 => Some(EV_KEY::KEY_SELECTIVE_SCREENSHOT), 1387 | 635 => Some(EV_KEY::KEY_NEXT_ELEMENT), 1388 | 636 => Some(EV_KEY::KEY_PREVIOUS_ELEMENT), 1389 | 637 => Some(EV_KEY::KEY_AUTOPILOT_ENGAGE_TOGGLE), 1390 | 638 => Some(EV_KEY::KEY_MARK_WAYPOINT), 1391 | 639 => Some(EV_KEY::KEY_SOS), 1392 | 640 => Some(EV_KEY::KEY_NAV_CHART), 1393 | 641 => Some(EV_KEY::KEY_FISHING_CHART), 1394 | 642 => Some(EV_KEY::KEY_SINGLE_RANGE_RADAR), 1395 | 643 => Some(EV_KEY::KEY_DUAL_RANGE_RADAR), 1396 | 644 => Some(EV_KEY::KEY_RADAR_OVERLAY), 1397 | 645 => Some(EV_KEY::KEY_TRADITIONAL_SONAR), 1398 | 646 => Some(EV_KEY::KEY_CLEARVU_SONAR), 1399 | 647 => Some(EV_KEY::KEY_SIDEVU_SONAR), 1400 | 648 => Some(EV_KEY::KEY_NAV_INFO), 1401 | 649 => Some(EV_KEY::KEY_BRIGHTNESS_MENU), 1402 | 656 => Some(EV_KEY::KEY_MACRO1), 1403 | 657 => Some(EV_KEY::KEY_MACRO2), 1404 | 658 => Some(EV_KEY::KEY_MACRO3), 1405 | 659 => Some(EV_KEY::KEY_MACRO4), 1406 | 660 => Some(EV_KEY::KEY_MACRO5), 1407 | 661 => Some(EV_KEY::KEY_MACRO6), 1408 | 662 => Some(EV_KEY::KEY_MACRO7), 1409 | 663 => Some(EV_KEY::KEY_MACRO8), 1410 | 664 => Some(EV_KEY::KEY_MACRO9), 1411 | 665 => Some(EV_KEY::KEY_MACRO10), 1412 | 666 => Some(EV_KEY::KEY_MACRO11), 1413 | 667 => Some(EV_KEY::KEY_MACRO12), 1414 | 668 => Some(EV_KEY::KEY_MACRO13), 1415 | 669 => Some(EV_KEY::KEY_MACRO14), 1416 | 670 => Some(EV_KEY::KEY_MACRO15), 1417 | 671 => Some(EV_KEY::KEY_MACRO16), 1418 | 672 => Some(EV_KEY::KEY_MACRO17), 1419 | 673 => Some(EV_KEY::KEY_MACRO18), 1420 | 674 => Some(EV_KEY::KEY_MACRO19), 1421 | 675 => Some(EV_KEY::KEY_MACRO20), 1422 | 676 => Some(EV_KEY::KEY_MACRO21), 1423 | 677 => Some(EV_KEY::KEY_MACRO22), 1424 | 678 => Some(EV_KEY::KEY_MACRO23), 1425 | 679 => Some(EV_KEY::KEY_MACRO24), 1426 | 680 => Some(EV_KEY::KEY_MACRO25), 1427 | 681 => Some(EV_KEY::KEY_MACRO26), 1428 | 682 => Some(EV_KEY::KEY_MACRO27), 1429 | 683 => Some(EV_KEY::KEY_MACRO28), 1430 | 684 => Some(EV_KEY::KEY_MACRO29), 1431 | 685 => Some(EV_KEY::KEY_MACRO30), 1432 | 688 => Some(EV_KEY::KEY_MACRO_RECORD_START), 1433 | 689 => Some(EV_KEY::KEY_MACRO_RECORD_STOP), 1434 | 690 => Some(EV_KEY::KEY_MACRO_PRESET_CYCLE), 1435 | 691 => Some(EV_KEY::KEY_MACRO_PRESET1), 1436 | 692 => Some(EV_KEY::KEY_MACRO_PRESET2), 1437 | 693 => Some(EV_KEY::KEY_MACRO_PRESET3), 1438 | 696 => Some(EV_KEY::KEY_KBD_LCD_MENU1), 1439 | 697 => Some(EV_KEY::KEY_KBD_LCD_MENU2), 1440 | 698 => Some(EV_KEY::KEY_KBD_LCD_MENU3), 1441 | 699 => Some(EV_KEY::KEY_KBD_LCD_MENU4), 1442 | 700 => Some(EV_KEY::KEY_KBD_LCD_MENU5), 1443 | 767 => Some(EV_KEY::KEY_MAX), 1444 | 256 => Some(EV_KEY::BTN_0), 1445 | 257 => Some(EV_KEY::BTN_1), 1446 | 258 => Some(EV_KEY::BTN_2), 1447 | 259 => Some(EV_KEY::BTN_3), 1448 | 260 => Some(EV_KEY::BTN_4), 1449 | 261 => Some(EV_KEY::BTN_5), 1450 | 262 => Some(EV_KEY::BTN_6), 1451 | 263 => Some(EV_KEY::BTN_7), 1452 | 264 => Some(EV_KEY::BTN_8), 1453 | 265 => Some(EV_KEY::BTN_9), 1454 | 272 => Some(EV_KEY::BTN_LEFT), 1455 | 273 => Some(EV_KEY::BTN_RIGHT), 1456 | 274 => Some(EV_KEY::BTN_MIDDLE), 1457 | 275 => Some(EV_KEY::BTN_SIDE), 1458 | 276 => Some(EV_KEY::BTN_EXTRA), 1459 | 277 => Some(EV_KEY::BTN_FORWARD), 1460 | 278 => Some(EV_KEY::BTN_BACK), 1461 | 279 => Some(EV_KEY::BTN_TASK), 1462 | 288 => Some(EV_KEY::BTN_TRIGGER), 1463 | 289 => Some(EV_KEY::BTN_THUMB), 1464 | 290 => Some(EV_KEY::BTN_THUMB2), 1465 | 291 => Some(EV_KEY::BTN_TOP), 1466 | 292 => Some(EV_KEY::BTN_TOP2), 1467 | 293 => Some(EV_KEY::BTN_PINKIE), 1468 | 294 => Some(EV_KEY::BTN_BASE), 1469 | 295 => Some(EV_KEY::BTN_BASE2), 1470 | 296 => Some(EV_KEY::BTN_BASE3), 1471 | 297 => Some(EV_KEY::BTN_BASE4), 1472 | 298 => Some(EV_KEY::BTN_BASE5), 1473 | 299 => Some(EV_KEY::BTN_BASE6), 1474 | 303 => Some(EV_KEY::BTN_DEAD), 1475 | 304 => Some(EV_KEY::BTN_SOUTH), 1476 | 305 => Some(EV_KEY::BTN_EAST), 1477 | 306 => Some(EV_KEY::BTN_C), 1478 | 307 => Some(EV_KEY::BTN_NORTH), 1479 | 308 => Some(EV_KEY::BTN_WEST), 1480 | 309 => Some(EV_KEY::BTN_Z), 1481 | 310 => Some(EV_KEY::BTN_TL), 1482 | 311 => Some(EV_KEY::BTN_TR), 1483 | 312 => Some(EV_KEY::BTN_TL2), 1484 | 313 => Some(EV_KEY::BTN_TR2), 1485 | 314 => Some(EV_KEY::BTN_SELECT), 1486 | 315 => Some(EV_KEY::BTN_START), 1487 | 316 => Some(EV_KEY::BTN_MODE), 1488 | 317 => Some(EV_KEY::BTN_THUMBL), 1489 | 318 => Some(EV_KEY::BTN_THUMBR), 1490 | 320 => Some(EV_KEY::BTN_TOOL_PEN), 1491 | 321 => Some(EV_KEY::BTN_TOOL_RUBBER), 1492 | 322 => Some(EV_KEY::BTN_TOOL_BRUSH), 1493 | 323 => Some(EV_KEY::BTN_TOOL_PENCIL), 1494 | 324 => Some(EV_KEY::BTN_TOOL_AIRBRUSH), 1495 | 325 => Some(EV_KEY::BTN_TOOL_FINGER), 1496 | 326 => Some(EV_KEY::BTN_TOOL_MOUSE), 1497 | 327 => Some(EV_KEY::BTN_TOOL_LENS), 1498 | 328 => Some(EV_KEY::BTN_TOOL_QUINTTAP), 1499 | 329 => Some(EV_KEY::BTN_STYLUS3), 1500 | 330 => Some(EV_KEY::BTN_TOUCH), 1501 | 331 => Some(EV_KEY::BTN_STYLUS), 1502 | 332 => Some(EV_KEY::BTN_STYLUS2), 1503 | 333 => Some(EV_KEY::BTN_TOOL_DOUBLETAP), 1504 | 334 => Some(EV_KEY::BTN_TOOL_TRIPLETAP), 1505 | 335 => Some(EV_KEY::BTN_TOOL_QUADTAP), 1506 | 336 => Some(EV_KEY::BTN_GEAR_DOWN), 1507 | 337 => Some(EV_KEY::BTN_GEAR_UP), 1508 | 544 => Some(EV_KEY::BTN_DPAD_UP), 1509 | 545 => Some(EV_KEY::BTN_DPAD_DOWN), 1510 | 546 => Some(EV_KEY::BTN_DPAD_LEFT), 1511 | 547 => Some(EV_KEY::BTN_DPAD_RIGHT), 1512 | 704 => Some(EV_KEY::BTN_TRIGGER_HAPPY1), 1513 | 705 => Some(EV_KEY::BTN_TRIGGER_HAPPY2), 1514 | 706 => Some(EV_KEY::BTN_TRIGGER_HAPPY3), 1515 | 707 => Some(EV_KEY::BTN_TRIGGER_HAPPY4), 1516 | 708 => Some(EV_KEY::BTN_TRIGGER_HAPPY5), 1517 | 709 => Some(EV_KEY::BTN_TRIGGER_HAPPY6), 1518 | 710 => Some(EV_KEY::BTN_TRIGGER_HAPPY7), 1519 | 711 => Some(EV_KEY::BTN_TRIGGER_HAPPY8), 1520 | 712 => Some(EV_KEY::BTN_TRIGGER_HAPPY9), 1521 | 713 => Some(EV_KEY::BTN_TRIGGER_HAPPY10), 1522 | 714 => Some(EV_KEY::BTN_TRIGGER_HAPPY11), 1523 | 715 => Some(EV_KEY::BTN_TRIGGER_HAPPY12), 1524 | 716 => Some(EV_KEY::BTN_TRIGGER_HAPPY13), 1525 | 717 => Some(EV_KEY::BTN_TRIGGER_HAPPY14), 1526 | 718 => Some(EV_KEY::BTN_TRIGGER_HAPPY15), 1527 | 719 => Some(EV_KEY::BTN_TRIGGER_HAPPY16), 1528 | 720 => Some(EV_KEY::BTN_TRIGGER_HAPPY17), 1529 | 721 => Some(EV_KEY::BTN_TRIGGER_HAPPY18), 1530 | 722 => Some(EV_KEY::BTN_TRIGGER_HAPPY19), 1531 | 723 => Some(EV_KEY::BTN_TRIGGER_HAPPY20), 1532 | 724 => Some(EV_KEY::BTN_TRIGGER_HAPPY21), 1533 | 725 => Some(EV_KEY::BTN_TRIGGER_HAPPY22), 1534 | 726 => Some(EV_KEY::BTN_TRIGGER_HAPPY23), 1535 | 727 => Some(EV_KEY::BTN_TRIGGER_HAPPY24), 1536 | 728 => Some(EV_KEY::BTN_TRIGGER_HAPPY25), 1537 | 729 => Some(EV_KEY::BTN_TRIGGER_HAPPY26), 1538 | 730 => Some(EV_KEY::BTN_TRIGGER_HAPPY27), 1539 | 731 => Some(EV_KEY::BTN_TRIGGER_HAPPY28), 1540 | 732 => Some(EV_KEY::BTN_TRIGGER_HAPPY29), 1541 | 733 => Some(EV_KEY::BTN_TRIGGER_HAPPY30), 1542 | 734 => Some(EV_KEY::BTN_TRIGGER_HAPPY31), 1543 | 735 => Some(EV_KEY::BTN_TRIGGER_HAPPY32), 1544 | 736 => Some(EV_KEY::BTN_TRIGGER_HAPPY33), 1545 | 737 => Some(EV_KEY::BTN_TRIGGER_HAPPY34), 1546 | 738 => Some(EV_KEY::BTN_TRIGGER_HAPPY35), 1547 | 739 => Some(EV_KEY::BTN_TRIGGER_HAPPY36), 1548 | 740 => Some(EV_KEY::BTN_TRIGGER_HAPPY37), 1549 | 741 => Some(EV_KEY::BTN_TRIGGER_HAPPY38), 1550 | 742 => Some(EV_KEY::BTN_TRIGGER_HAPPY39), 1551 | 743 => Some(EV_KEY::BTN_TRIGGER_HAPPY40), 1552 | _ => None, 1553 | } 1554 | } 1555 | 1556 | impl std::str::FromStr for EV_KEY { 1557 | type Err = (); 1558 | fn from_str(s: &str) -> Result { 1559 | match s { 1560 | "KEY_RESERVED" => Ok(EV_KEY::KEY_RESERVED), 1561 | "KEY_ESC" => Ok(EV_KEY::KEY_ESC), 1562 | "KEY_1" => Ok(EV_KEY::KEY_1), 1563 | "KEY_2" => Ok(EV_KEY::KEY_2), 1564 | "KEY_3" => Ok(EV_KEY::KEY_3), 1565 | "KEY_4" => Ok(EV_KEY::KEY_4), 1566 | "KEY_5" => Ok(EV_KEY::KEY_5), 1567 | "KEY_6" => Ok(EV_KEY::KEY_6), 1568 | "KEY_7" => Ok(EV_KEY::KEY_7), 1569 | "KEY_8" => Ok(EV_KEY::KEY_8), 1570 | "KEY_9" => Ok(EV_KEY::KEY_9), 1571 | "KEY_0" => Ok(EV_KEY::KEY_0), 1572 | "KEY_MINUS" => Ok(EV_KEY::KEY_MINUS), 1573 | "KEY_EQUAL" => Ok(EV_KEY::KEY_EQUAL), 1574 | "KEY_BACKSPACE" => Ok(EV_KEY::KEY_BACKSPACE), 1575 | "KEY_TAB" => Ok(EV_KEY::KEY_TAB), 1576 | "KEY_Q" => Ok(EV_KEY::KEY_Q), 1577 | "KEY_W" => Ok(EV_KEY::KEY_W), 1578 | "KEY_E" => Ok(EV_KEY::KEY_E), 1579 | "KEY_R" => Ok(EV_KEY::KEY_R), 1580 | "KEY_T" => Ok(EV_KEY::KEY_T), 1581 | "KEY_Y" => Ok(EV_KEY::KEY_Y), 1582 | "KEY_U" => Ok(EV_KEY::KEY_U), 1583 | "KEY_I" => Ok(EV_KEY::KEY_I), 1584 | "KEY_O" => Ok(EV_KEY::KEY_O), 1585 | "KEY_P" => Ok(EV_KEY::KEY_P), 1586 | "KEY_LEFTBRACE" => Ok(EV_KEY::KEY_LEFTBRACE), 1587 | "KEY_RIGHTBRACE" => Ok(EV_KEY::KEY_RIGHTBRACE), 1588 | "KEY_ENTER" => Ok(EV_KEY::KEY_ENTER), 1589 | "KEY_LEFTCTRL" => Ok(EV_KEY::KEY_LEFTCTRL), 1590 | "KEY_A" => Ok(EV_KEY::KEY_A), 1591 | "KEY_S" => Ok(EV_KEY::KEY_S), 1592 | "KEY_D" => Ok(EV_KEY::KEY_D), 1593 | "KEY_F" => Ok(EV_KEY::KEY_F), 1594 | "KEY_G" => Ok(EV_KEY::KEY_G), 1595 | "KEY_H" => Ok(EV_KEY::KEY_H), 1596 | "KEY_J" => Ok(EV_KEY::KEY_J), 1597 | "KEY_K" => Ok(EV_KEY::KEY_K), 1598 | "KEY_L" => Ok(EV_KEY::KEY_L), 1599 | "KEY_SEMICOLON" => Ok(EV_KEY::KEY_SEMICOLON), 1600 | "KEY_APOSTROPHE" => Ok(EV_KEY::KEY_APOSTROPHE), 1601 | "KEY_GRAVE" => Ok(EV_KEY::KEY_GRAVE), 1602 | "KEY_LEFTSHIFT" => Ok(EV_KEY::KEY_LEFTSHIFT), 1603 | "KEY_BACKSLASH" => Ok(EV_KEY::KEY_BACKSLASH), 1604 | "KEY_Z" => Ok(EV_KEY::KEY_Z), 1605 | "KEY_X" => Ok(EV_KEY::KEY_X), 1606 | "KEY_C" => Ok(EV_KEY::KEY_C), 1607 | "KEY_V" => Ok(EV_KEY::KEY_V), 1608 | "KEY_B" => Ok(EV_KEY::KEY_B), 1609 | "KEY_N" => Ok(EV_KEY::KEY_N), 1610 | "KEY_M" => Ok(EV_KEY::KEY_M), 1611 | "KEY_COMMA" => Ok(EV_KEY::KEY_COMMA), 1612 | "KEY_DOT" => Ok(EV_KEY::KEY_DOT), 1613 | "KEY_SLASH" => Ok(EV_KEY::KEY_SLASH), 1614 | "KEY_RIGHTSHIFT" => Ok(EV_KEY::KEY_RIGHTSHIFT), 1615 | "KEY_KPASTERISK" => Ok(EV_KEY::KEY_KPASTERISK), 1616 | "KEY_LEFTALT" => Ok(EV_KEY::KEY_LEFTALT), 1617 | "KEY_SPACE" => Ok(EV_KEY::KEY_SPACE), 1618 | "KEY_CAPSLOCK" => Ok(EV_KEY::KEY_CAPSLOCK), 1619 | "KEY_F1" => Ok(EV_KEY::KEY_F1), 1620 | "KEY_F2" => Ok(EV_KEY::KEY_F2), 1621 | "KEY_F3" => Ok(EV_KEY::KEY_F3), 1622 | "KEY_F4" => Ok(EV_KEY::KEY_F4), 1623 | "KEY_F5" => Ok(EV_KEY::KEY_F5), 1624 | "KEY_F6" => Ok(EV_KEY::KEY_F6), 1625 | "KEY_F7" => Ok(EV_KEY::KEY_F7), 1626 | "KEY_F8" => Ok(EV_KEY::KEY_F8), 1627 | "KEY_F9" => Ok(EV_KEY::KEY_F9), 1628 | "KEY_F10" => Ok(EV_KEY::KEY_F10), 1629 | "KEY_NUMLOCK" => Ok(EV_KEY::KEY_NUMLOCK), 1630 | "KEY_SCROLLLOCK" => Ok(EV_KEY::KEY_SCROLLLOCK), 1631 | "KEY_KP7" => Ok(EV_KEY::KEY_KP7), 1632 | "KEY_KP8" => Ok(EV_KEY::KEY_KP8), 1633 | "KEY_KP9" => Ok(EV_KEY::KEY_KP9), 1634 | "KEY_KPMINUS" => Ok(EV_KEY::KEY_KPMINUS), 1635 | "KEY_KP4" => Ok(EV_KEY::KEY_KP4), 1636 | "KEY_KP5" => Ok(EV_KEY::KEY_KP5), 1637 | "KEY_KP6" => Ok(EV_KEY::KEY_KP6), 1638 | "KEY_KPPLUS" => Ok(EV_KEY::KEY_KPPLUS), 1639 | "KEY_KP1" => Ok(EV_KEY::KEY_KP1), 1640 | "KEY_KP2" => Ok(EV_KEY::KEY_KP2), 1641 | "KEY_KP3" => Ok(EV_KEY::KEY_KP3), 1642 | "KEY_KP0" => Ok(EV_KEY::KEY_KP0), 1643 | "KEY_KPDOT" => Ok(EV_KEY::KEY_KPDOT), 1644 | "KEY_ZENKAKUHANKAKU" => Ok(EV_KEY::KEY_ZENKAKUHANKAKU), 1645 | "KEY_102ND" => Ok(EV_KEY::KEY_102ND), 1646 | "KEY_F11" => Ok(EV_KEY::KEY_F11), 1647 | "KEY_F12" => Ok(EV_KEY::KEY_F12), 1648 | "KEY_RO" => Ok(EV_KEY::KEY_RO), 1649 | "KEY_KATAKANA" => Ok(EV_KEY::KEY_KATAKANA), 1650 | "KEY_HIRAGANA" => Ok(EV_KEY::KEY_HIRAGANA), 1651 | "KEY_HENKAN" => Ok(EV_KEY::KEY_HENKAN), 1652 | "KEY_KATAKANAHIRAGANA" => Ok(EV_KEY::KEY_KATAKANAHIRAGANA), 1653 | "KEY_MUHENKAN" => Ok(EV_KEY::KEY_MUHENKAN), 1654 | "KEY_KPJPCOMMA" => Ok(EV_KEY::KEY_KPJPCOMMA), 1655 | "KEY_KPENTER" => Ok(EV_KEY::KEY_KPENTER), 1656 | "KEY_RIGHTCTRL" => Ok(EV_KEY::KEY_RIGHTCTRL), 1657 | "KEY_KPSLASH" => Ok(EV_KEY::KEY_KPSLASH), 1658 | "KEY_SYSRQ" => Ok(EV_KEY::KEY_SYSRQ), 1659 | "KEY_RIGHTALT" => Ok(EV_KEY::KEY_RIGHTALT), 1660 | "KEY_LINEFEED" => Ok(EV_KEY::KEY_LINEFEED), 1661 | "KEY_HOME" => Ok(EV_KEY::KEY_HOME), 1662 | "KEY_UP" => Ok(EV_KEY::KEY_UP), 1663 | "KEY_PAGEUP" => Ok(EV_KEY::KEY_PAGEUP), 1664 | "KEY_LEFT" => Ok(EV_KEY::KEY_LEFT), 1665 | "KEY_RIGHT" => Ok(EV_KEY::KEY_RIGHT), 1666 | "KEY_END" => Ok(EV_KEY::KEY_END), 1667 | "KEY_DOWN" => Ok(EV_KEY::KEY_DOWN), 1668 | "KEY_PAGEDOWN" => Ok(EV_KEY::KEY_PAGEDOWN), 1669 | "KEY_INSERT" => Ok(EV_KEY::KEY_INSERT), 1670 | "KEY_DELETE" => Ok(EV_KEY::KEY_DELETE), 1671 | "KEY_MACRO" => Ok(EV_KEY::KEY_MACRO), 1672 | "KEY_MUTE" => Ok(EV_KEY::KEY_MUTE), 1673 | "KEY_VOLUMEDOWN" => Ok(EV_KEY::KEY_VOLUMEDOWN), 1674 | "KEY_VOLUMEUP" => Ok(EV_KEY::KEY_VOLUMEUP), 1675 | "KEY_POWER" => Ok(EV_KEY::KEY_POWER), 1676 | "KEY_KPEQUAL" => Ok(EV_KEY::KEY_KPEQUAL), 1677 | "KEY_KPPLUSMINUS" => Ok(EV_KEY::KEY_KPPLUSMINUS), 1678 | "KEY_PAUSE" => Ok(EV_KEY::KEY_PAUSE), 1679 | "KEY_SCALE" => Ok(EV_KEY::KEY_SCALE), 1680 | "KEY_KPCOMMA" => Ok(EV_KEY::KEY_KPCOMMA), 1681 | "KEY_HANGEUL" => Ok(EV_KEY::KEY_HANGEUL), 1682 | "KEY_HANJA" => Ok(EV_KEY::KEY_HANJA), 1683 | "KEY_YEN" => Ok(EV_KEY::KEY_YEN), 1684 | "KEY_LEFTMETA" => Ok(EV_KEY::KEY_LEFTMETA), 1685 | "KEY_RIGHTMETA" => Ok(EV_KEY::KEY_RIGHTMETA), 1686 | "KEY_COMPOSE" => Ok(EV_KEY::KEY_COMPOSE), 1687 | "KEY_STOP" => Ok(EV_KEY::KEY_STOP), 1688 | "KEY_AGAIN" => Ok(EV_KEY::KEY_AGAIN), 1689 | "KEY_PROPS" => Ok(EV_KEY::KEY_PROPS), 1690 | "KEY_UNDO" => Ok(EV_KEY::KEY_UNDO), 1691 | "KEY_FRONT" => Ok(EV_KEY::KEY_FRONT), 1692 | "KEY_COPY" => Ok(EV_KEY::KEY_COPY), 1693 | "KEY_OPEN" => Ok(EV_KEY::KEY_OPEN), 1694 | "KEY_PASTE" => Ok(EV_KEY::KEY_PASTE), 1695 | "KEY_FIND" => Ok(EV_KEY::KEY_FIND), 1696 | "KEY_CUT" => Ok(EV_KEY::KEY_CUT), 1697 | "KEY_HELP" => Ok(EV_KEY::KEY_HELP), 1698 | "KEY_MENU" => Ok(EV_KEY::KEY_MENU), 1699 | "KEY_CALC" => Ok(EV_KEY::KEY_CALC), 1700 | "KEY_SETUP" => Ok(EV_KEY::KEY_SETUP), 1701 | "KEY_SLEEP" => Ok(EV_KEY::KEY_SLEEP), 1702 | "KEY_WAKEUP" => Ok(EV_KEY::KEY_WAKEUP), 1703 | "KEY_FILE" => Ok(EV_KEY::KEY_FILE), 1704 | "KEY_SENDFILE" => Ok(EV_KEY::KEY_SENDFILE), 1705 | "KEY_DELETEFILE" => Ok(EV_KEY::KEY_DELETEFILE), 1706 | "KEY_XFER" => Ok(EV_KEY::KEY_XFER), 1707 | "KEY_PROG1" => Ok(EV_KEY::KEY_PROG1), 1708 | "KEY_PROG2" => Ok(EV_KEY::KEY_PROG2), 1709 | "KEY_WWW" => Ok(EV_KEY::KEY_WWW), 1710 | "KEY_MSDOS" => Ok(EV_KEY::KEY_MSDOS), 1711 | "KEY_COFFEE" => Ok(EV_KEY::KEY_COFFEE), 1712 | "KEY_ROTATE_DISPLAY" => Ok(EV_KEY::KEY_ROTATE_DISPLAY), 1713 | "KEY_CYCLEWINDOWS" => Ok(EV_KEY::KEY_CYCLEWINDOWS), 1714 | "KEY_MAIL" => Ok(EV_KEY::KEY_MAIL), 1715 | "KEY_BOOKMARKS" => Ok(EV_KEY::KEY_BOOKMARKS), 1716 | "KEY_COMPUTER" => Ok(EV_KEY::KEY_COMPUTER), 1717 | "KEY_BACK" => Ok(EV_KEY::KEY_BACK), 1718 | "KEY_FORWARD" => Ok(EV_KEY::KEY_FORWARD), 1719 | "KEY_CLOSECD" => Ok(EV_KEY::KEY_CLOSECD), 1720 | "KEY_EJECTCD" => Ok(EV_KEY::KEY_EJECTCD), 1721 | "KEY_EJECTCLOSECD" => Ok(EV_KEY::KEY_EJECTCLOSECD), 1722 | "KEY_NEXTSONG" => Ok(EV_KEY::KEY_NEXTSONG), 1723 | "KEY_PLAYPAUSE" => Ok(EV_KEY::KEY_PLAYPAUSE), 1724 | "KEY_PREVIOUSSONG" => Ok(EV_KEY::KEY_PREVIOUSSONG), 1725 | "KEY_STOPCD" => Ok(EV_KEY::KEY_STOPCD), 1726 | "KEY_RECORD" => Ok(EV_KEY::KEY_RECORD), 1727 | "KEY_REWIND" => Ok(EV_KEY::KEY_REWIND), 1728 | "KEY_PHONE" => Ok(EV_KEY::KEY_PHONE), 1729 | "KEY_ISO" => Ok(EV_KEY::KEY_ISO), 1730 | "KEY_CONFIG" => Ok(EV_KEY::KEY_CONFIG), 1731 | "KEY_HOMEPAGE" => Ok(EV_KEY::KEY_HOMEPAGE), 1732 | "KEY_REFRESH" => Ok(EV_KEY::KEY_REFRESH), 1733 | "KEY_EXIT" => Ok(EV_KEY::KEY_EXIT), 1734 | "KEY_MOVE" => Ok(EV_KEY::KEY_MOVE), 1735 | "KEY_EDIT" => Ok(EV_KEY::KEY_EDIT), 1736 | "KEY_SCROLLUP" => Ok(EV_KEY::KEY_SCROLLUP), 1737 | "KEY_SCROLLDOWN" => Ok(EV_KEY::KEY_SCROLLDOWN), 1738 | "KEY_KPLEFTPAREN" => Ok(EV_KEY::KEY_KPLEFTPAREN), 1739 | "KEY_KPRIGHTPAREN" => Ok(EV_KEY::KEY_KPRIGHTPAREN), 1740 | "KEY_NEW" => Ok(EV_KEY::KEY_NEW), 1741 | "KEY_REDO" => Ok(EV_KEY::KEY_REDO), 1742 | "KEY_F13" => Ok(EV_KEY::KEY_F13), 1743 | "KEY_F14" => Ok(EV_KEY::KEY_F14), 1744 | "KEY_F15" => Ok(EV_KEY::KEY_F15), 1745 | "KEY_F16" => Ok(EV_KEY::KEY_F16), 1746 | "KEY_F17" => Ok(EV_KEY::KEY_F17), 1747 | "KEY_F18" => Ok(EV_KEY::KEY_F18), 1748 | "KEY_F19" => Ok(EV_KEY::KEY_F19), 1749 | "KEY_F20" => Ok(EV_KEY::KEY_F20), 1750 | "KEY_F21" => Ok(EV_KEY::KEY_F21), 1751 | "KEY_F22" => Ok(EV_KEY::KEY_F22), 1752 | "KEY_F23" => Ok(EV_KEY::KEY_F23), 1753 | "KEY_F24" => Ok(EV_KEY::KEY_F24), 1754 | "KEY_PLAYCD" => Ok(EV_KEY::KEY_PLAYCD), 1755 | "KEY_PAUSECD" => Ok(EV_KEY::KEY_PAUSECD), 1756 | "KEY_PROG3" => Ok(EV_KEY::KEY_PROG3), 1757 | "KEY_PROG4" => Ok(EV_KEY::KEY_PROG4), 1758 | "KEY_ALL_APPLICATIONS" => Ok(EV_KEY::KEY_ALL_APPLICATIONS), 1759 | "KEY_SUSPEND" => Ok(EV_KEY::KEY_SUSPEND), 1760 | "KEY_CLOSE" => Ok(EV_KEY::KEY_CLOSE), 1761 | "KEY_PLAY" => Ok(EV_KEY::KEY_PLAY), 1762 | "KEY_FASTFORWARD" => Ok(EV_KEY::KEY_FASTFORWARD), 1763 | "KEY_BASSBOOST" => Ok(EV_KEY::KEY_BASSBOOST), 1764 | "KEY_PRINT" => Ok(EV_KEY::KEY_PRINT), 1765 | "KEY_HP" => Ok(EV_KEY::KEY_HP), 1766 | "KEY_CAMERA" => Ok(EV_KEY::KEY_CAMERA), 1767 | "KEY_SOUND" => Ok(EV_KEY::KEY_SOUND), 1768 | "KEY_QUESTION" => Ok(EV_KEY::KEY_QUESTION), 1769 | "KEY_EMAIL" => Ok(EV_KEY::KEY_EMAIL), 1770 | "KEY_CHAT" => Ok(EV_KEY::KEY_CHAT), 1771 | "KEY_SEARCH" => Ok(EV_KEY::KEY_SEARCH), 1772 | "KEY_CONNECT" => Ok(EV_KEY::KEY_CONNECT), 1773 | "KEY_FINANCE" => Ok(EV_KEY::KEY_FINANCE), 1774 | "KEY_SPORT" => Ok(EV_KEY::KEY_SPORT), 1775 | "KEY_SHOP" => Ok(EV_KEY::KEY_SHOP), 1776 | "KEY_ALTERASE" => Ok(EV_KEY::KEY_ALTERASE), 1777 | "KEY_CANCEL" => Ok(EV_KEY::KEY_CANCEL), 1778 | "KEY_BRIGHTNESSDOWN" => Ok(EV_KEY::KEY_BRIGHTNESSDOWN), 1779 | "KEY_BRIGHTNESSUP" => Ok(EV_KEY::KEY_BRIGHTNESSUP), 1780 | "KEY_MEDIA" => Ok(EV_KEY::KEY_MEDIA), 1781 | "KEY_SWITCHVIDEOMODE" => Ok(EV_KEY::KEY_SWITCHVIDEOMODE), 1782 | "KEY_KBDILLUMTOGGLE" => Ok(EV_KEY::KEY_KBDILLUMTOGGLE), 1783 | "KEY_KBDILLUMDOWN" => Ok(EV_KEY::KEY_KBDILLUMDOWN), 1784 | "KEY_KBDILLUMUP" => Ok(EV_KEY::KEY_KBDILLUMUP), 1785 | "KEY_SEND" => Ok(EV_KEY::KEY_SEND), 1786 | "KEY_REPLY" => Ok(EV_KEY::KEY_REPLY), 1787 | "KEY_FORWARDMAIL" => Ok(EV_KEY::KEY_FORWARDMAIL), 1788 | "KEY_SAVE" => Ok(EV_KEY::KEY_SAVE), 1789 | "KEY_DOCUMENTS" => Ok(EV_KEY::KEY_DOCUMENTS), 1790 | "KEY_BATTERY" => Ok(EV_KEY::KEY_BATTERY), 1791 | "KEY_BLUETOOTH" => Ok(EV_KEY::KEY_BLUETOOTH), 1792 | "KEY_WLAN" => Ok(EV_KEY::KEY_WLAN), 1793 | "KEY_UWB" => Ok(EV_KEY::KEY_UWB), 1794 | "KEY_UNKNOWN" => Ok(EV_KEY::KEY_UNKNOWN), 1795 | "KEY_VIDEO_NEXT" => Ok(EV_KEY::KEY_VIDEO_NEXT), 1796 | "KEY_VIDEO_PREV" => Ok(EV_KEY::KEY_VIDEO_PREV), 1797 | "KEY_BRIGHTNESS_CYCLE" => Ok(EV_KEY::KEY_BRIGHTNESS_CYCLE), 1798 | "KEY_BRIGHTNESS_AUTO" => Ok(EV_KEY::KEY_BRIGHTNESS_AUTO), 1799 | "KEY_DISPLAY_OFF" => Ok(EV_KEY::KEY_DISPLAY_OFF), 1800 | "KEY_WWAN" => Ok(EV_KEY::KEY_WWAN), 1801 | "KEY_RFKILL" => Ok(EV_KEY::KEY_RFKILL), 1802 | "KEY_MICMUTE" => Ok(EV_KEY::KEY_MICMUTE), 1803 | "KEY_OK" => Ok(EV_KEY::KEY_OK), 1804 | "KEY_SELECT" => Ok(EV_KEY::KEY_SELECT), 1805 | "KEY_GOTO" => Ok(EV_KEY::KEY_GOTO), 1806 | "KEY_CLEAR" => Ok(EV_KEY::KEY_CLEAR), 1807 | "KEY_POWER2" => Ok(EV_KEY::KEY_POWER2), 1808 | "KEY_OPTION" => Ok(EV_KEY::KEY_OPTION), 1809 | "KEY_INFO" => Ok(EV_KEY::KEY_INFO), 1810 | "KEY_TIME" => Ok(EV_KEY::KEY_TIME), 1811 | "KEY_VENDOR" => Ok(EV_KEY::KEY_VENDOR), 1812 | "KEY_ARCHIVE" => Ok(EV_KEY::KEY_ARCHIVE), 1813 | "KEY_PROGRAM" => Ok(EV_KEY::KEY_PROGRAM), 1814 | "KEY_CHANNEL" => Ok(EV_KEY::KEY_CHANNEL), 1815 | "KEY_FAVORITES" => Ok(EV_KEY::KEY_FAVORITES), 1816 | "KEY_EPG" => Ok(EV_KEY::KEY_EPG), 1817 | "KEY_PVR" => Ok(EV_KEY::KEY_PVR), 1818 | "KEY_MHP" => Ok(EV_KEY::KEY_MHP), 1819 | "KEY_LANGUAGE" => Ok(EV_KEY::KEY_LANGUAGE), 1820 | "KEY_TITLE" => Ok(EV_KEY::KEY_TITLE), 1821 | "KEY_SUBTITLE" => Ok(EV_KEY::KEY_SUBTITLE), 1822 | "KEY_ANGLE" => Ok(EV_KEY::KEY_ANGLE), 1823 | "KEY_FULL_SCREEN" => Ok(EV_KEY::KEY_FULL_SCREEN), 1824 | "KEY_MODE" => Ok(EV_KEY::KEY_MODE), 1825 | "KEY_KEYBOARD" => Ok(EV_KEY::KEY_KEYBOARD), 1826 | "KEY_ASPECT_RATIO" => Ok(EV_KEY::KEY_ASPECT_RATIO), 1827 | "KEY_PC" => Ok(EV_KEY::KEY_PC), 1828 | "KEY_TV" => Ok(EV_KEY::KEY_TV), 1829 | "KEY_TV2" => Ok(EV_KEY::KEY_TV2), 1830 | "KEY_VCR" => Ok(EV_KEY::KEY_VCR), 1831 | "KEY_VCR2" => Ok(EV_KEY::KEY_VCR2), 1832 | "KEY_SAT" => Ok(EV_KEY::KEY_SAT), 1833 | "KEY_SAT2" => Ok(EV_KEY::KEY_SAT2), 1834 | "KEY_CD" => Ok(EV_KEY::KEY_CD), 1835 | "KEY_TAPE" => Ok(EV_KEY::KEY_TAPE), 1836 | "KEY_RADIO" => Ok(EV_KEY::KEY_RADIO), 1837 | "KEY_TUNER" => Ok(EV_KEY::KEY_TUNER), 1838 | "KEY_PLAYER" => Ok(EV_KEY::KEY_PLAYER), 1839 | "KEY_TEXT" => Ok(EV_KEY::KEY_TEXT), 1840 | "KEY_DVD" => Ok(EV_KEY::KEY_DVD), 1841 | "KEY_AUX" => Ok(EV_KEY::KEY_AUX), 1842 | "KEY_MP3" => Ok(EV_KEY::KEY_MP3), 1843 | "KEY_AUDIO" => Ok(EV_KEY::KEY_AUDIO), 1844 | "KEY_VIDEO" => Ok(EV_KEY::KEY_VIDEO), 1845 | "KEY_DIRECTORY" => Ok(EV_KEY::KEY_DIRECTORY), 1846 | "KEY_LIST" => Ok(EV_KEY::KEY_LIST), 1847 | "KEY_MEMO" => Ok(EV_KEY::KEY_MEMO), 1848 | "KEY_CALENDAR" => Ok(EV_KEY::KEY_CALENDAR), 1849 | "KEY_RED" => Ok(EV_KEY::KEY_RED), 1850 | "KEY_GREEN" => Ok(EV_KEY::KEY_GREEN), 1851 | "KEY_YELLOW" => Ok(EV_KEY::KEY_YELLOW), 1852 | "KEY_BLUE" => Ok(EV_KEY::KEY_BLUE), 1853 | "KEY_CHANNELUP" => Ok(EV_KEY::KEY_CHANNELUP), 1854 | "KEY_CHANNELDOWN" => Ok(EV_KEY::KEY_CHANNELDOWN), 1855 | "KEY_FIRST" => Ok(EV_KEY::KEY_FIRST), 1856 | "KEY_LAST" => Ok(EV_KEY::KEY_LAST), 1857 | "KEY_AB" => Ok(EV_KEY::KEY_AB), 1858 | "KEY_NEXT" => Ok(EV_KEY::KEY_NEXT), 1859 | "KEY_RESTART" => Ok(EV_KEY::KEY_RESTART), 1860 | "KEY_SLOW" => Ok(EV_KEY::KEY_SLOW), 1861 | "KEY_SHUFFLE" => Ok(EV_KEY::KEY_SHUFFLE), 1862 | "KEY_BREAK" => Ok(EV_KEY::KEY_BREAK), 1863 | "KEY_PREVIOUS" => Ok(EV_KEY::KEY_PREVIOUS), 1864 | "KEY_DIGITS" => Ok(EV_KEY::KEY_DIGITS), 1865 | "KEY_TEEN" => Ok(EV_KEY::KEY_TEEN), 1866 | "KEY_TWEN" => Ok(EV_KEY::KEY_TWEN), 1867 | "KEY_VIDEOPHONE" => Ok(EV_KEY::KEY_VIDEOPHONE), 1868 | "KEY_GAMES" => Ok(EV_KEY::KEY_GAMES), 1869 | "KEY_ZOOMIN" => Ok(EV_KEY::KEY_ZOOMIN), 1870 | "KEY_ZOOMOUT" => Ok(EV_KEY::KEY_ZOOMOUT), 1871 | "KEY_ZOOMRESET" => Ok(EV_KEY::KEY_ZOOMRESET), 1872 | "KEY_WORDPROCESSOR" => Ok(EV_KEY::KEY_WORDPROCESSOR), 1873 | "KEY_EDITOR" => Ok(EV_KEY::KEY_EDITOR), 1874 | "KEY_SPREADSHEET" => Ok(EV_KEY::KEY_SPREADSHEET), 1875 | "KEY_GRAPHICSEDITOR" => Ok(EV_KEY::KEY_GRAPHICSEDITOR), 1876 | "KEY_PRESENTATION" => Ok(EV_KEY::KEY_PRESENTATION), 1877 | "KEY_DATABASE" => Ok(EV_KEY::KEY_DATABASE), 1878 | "KEY_NEWS" => Ok(EV_KEY::KEY_NEWS), 1879 | "KEY_VOICEMAIL" => Ok(EV_KEY::KEY_VOICEMAIL), 1880 | "KEY_ADDRESSBOOK" => Ok(EV_KEY::KEY_ADDRESSBOOK), 1881 | "KEY_MESSENGER" => Ok(EV_KEY::KEY_MESSENGER), 1882 | "KEY_DISPLAYTOGGLE" => Ok(EV_KEY::KEY_DISPLAYTOGGLE), 1883 | "KEY_SPELLCHECK" => Ok(EV_KEY::KEY_SPELLCHECK), 1884 | "KEY_LOGOFF" => Ok(EV_KEY::KEY_LOGOFF), 1885 | "KEY_DOLLAR" => Ok(EV_KEY::KEY_DOLLAR), 1886 | "KEY_EURO" => Ok(EV_KEY::KEY_EURO), 1887 | "KEY_FRAMEBACK" => Ok(EV_KEY::KEY_FRAMEBACK), 1888 | "KEY_FRAMEFORWARD" => Ok(EV_KEY::KEY_FRAMEFORWARD), 1889 | "KEY_CONTEXT_MENU" => Ok(EV_KEY::KEY_CONTEXT_MENU), 1890 | "KEY_MEDIA_REPEAT" => Ok(EV_KEY::KEY_MEDIA_REPEAT), 1891 | "KEY_10CHANNELSUP" => Ok(EV_KEY::KEY_10CHANNELSUP), 1892 | "KEY_10CHANNELSDOWN" => Ok(EV_KEY::KEY_10CHANNELSDOWN), 1893 | "KEY_IMAGES" => Ok(EV_KEY::KEY_IMAGES), 1894 | "KEY_NOTIFICATION_CENTER" => Ok(EV_KEY::KEY_NOTIFICATION_CENTER), 1895 | "KEY_PICKUP_PHONE" => Ok(EV_KEY::KEY_PICKUP_PHONE), 1896 | "KEY_HANGUP_PHONE" => Ok(EV_KEY::KEY_HANGUP_PHONE), 1897 | "KEY_DEL_EOL" => Ok(EV_KEY::KEY_DEL_EOL), 1898 | "KEY_DEL_EOS" => Ok(EV_KEY::KEY_DEL_EOS), 1899 | "KEY_INS_LINE" => Ok(EV_KEY::KEY_INS_LINE), 1900 | "KEY_DEL_LINE" => Ok(EV_KEY::KEY_DEL_LINE), 1901 | "KEY_FN" => Ok(EV_KEY::KEY_FN), 1902 | "KEY_FN_ESC" => Ok(EV_KEY::KEY_FN_ESC), 1903 | "KEY_FN_F1" => Ok(EV_KEY::KEY_FN_F1), 1904 | "KEY_FN_F2" => Ok(EV_KEY::KEY_FN_F2), 1905 | "KEY_FN_F3" => Ok(EV_KEY::KEY_FN_F3), 1906 | "KEY_FN_F4" => Ok(EV_KEY::KEY_FN_F4), 1907 | "KEY_FN_F5" => Ok(EV_KEY::KEY_FN_F5), 1908 | "KEY_FN_F6" => Ok(EV_KEY::KEY_FN_F6), 1909 | "KEY_FN_F7" => Ok(EV_KEY::KEY_FN_F7), 1910 | "KEY_FN_F8" => Ok(EV_KEY::KEY_FN_F8), 1911 | "KEY_FN_F9" => Ok(EV_KEY::KEY_FN_F9), 1912 | "KEY_FN_F10" => Ok(EV_KEY::KEY_FN_F10), 1913 | "KEY_FN_F11" => Ok(EV_KEY::KEY_FN_F11), 1914 | "KEY_FN_F12" => Ok(EV_KEY::KEY_FN_F12), 1915 | "KEY_FN_1" => Ok(EV_KEY::KEY_FN_1), 1916 | "KEY_FN_2" => Ok(EV_KEY::KEY_FN_2), 1917 | "KEY_FN_D" => Ok(EV_KEY::KEY_FN_D), 1918 | "KEY_FN_E" => Ok(EV_KEY::KEY_FN_E), 1919 | "KEY_FN_F" => Ok(EV_KEY::KEY_FN_F), 1920 | "KEY_FN_S" => Ok(EV_KEY::KEY_FN_S), 1921 | "KEY_FN_B" => Ok(EV_KEY::KEY_FN_B), 1922 | "KEY_FN_RIGHT_SHIFT" => Ok(EV_KEY::KEY_FN_RIGHT_SHIFT), 1923 | "KEY_BRL_DOT1" => Ok(EV_KEY::KEY_BRL_DOT1), 1924 | "KEY_BRL_DOT2" => Ok(EV_KEY::KEY_BRL_DOT2), 1925 | "KEY_BRL_DOT3" => Ok(EV_KEY::KEY_BRL_DOT3), 1926 | "KEY_BRL_DOT4" => Ok(EV_KEY::KEY_BRL_DOT4), 1927 | "KEY_BRL_DOT5" => Ok(EV_KEY::KEY_BRL_DOT5), 1928 | "KEY_BRL_DOT6" => Ok(EV_KEY::KEY_BRL_DOT6), 1929 | "KEY_BRL_DOT7" => Ok(EV_KEY::KEY_BRL_DOT7), 1930 | "KEY_BRL_DOT8" => Ok(EV_KEY::KEY_BRL_DOT8), 1931 | "KEY_BRL_DOT9" => Ok(EV_KEY::KEY_BRL_DOT9), 1932 | "KEY_BRL_DOT10" => Ok(EV_KEY::KEY_BRL_DOT10), 1933 | "KEY_NUMERIC_0" => Ok(EV_KEY::KEY_NUMERIC_0), 1934 | "KEY_NUMERIC_1" => Ok(EV_KEY::KEY_NUMERIC_1), 1935 | "KEY_NUMERIC_2" => Ok(EV_KEY::KEY_NUMERIC_2), 1936 | "KEY_NUMERIC_3" => Ok(EV_KEY::KEY_NUMERIC_3), 1937 | "KEY_NUMERIC_4" => Ok(EV_KEY::KEY_NUMERIC_4), 1938 | "KEY_NUMERIC_5" => Ok(EV_KEY::KEY_NUMERIC_5), 1939 | "KEY_NUMERIC_6" => Ok(EV_KEY::KEY_NUMERIC_6), 1940 | "KEY_NUMERIC_7" => Ok(EV_KEY::KEY_NUMERIC_7), 1941 | "KEY_NUMERIC_8" => Ok(EV_KEY::KEY_NUMERIC_8), 1942 | "KEY_NUMERIC_9" => Ok(EV_KEY::KEY_NUMERIC_9), 1943 | "KEY_NUMERIC_STAR" => Ok(EV_KEY::KEY_NUMERIC_STAR), 1944 | "KEY_NUMERIC_POUND" => Ok(EV_KEY::KEY_NUMERIC_POUND), 1945 | "KEY_NUMERIC_A" => Ok(EV_KEY::KEY_NUMERIC_A), 1946 | "KEY_NUMERIC_B" => Ok(EV_KEY::KEY_NUMERIC_B), 1947 | "KEY_NUMERIC_C" => Ok(EV_KEY::KEY_NUMERIC_C), 1948 | "KEY_NUMERIC_D" => Ok(EV_KEY::KEY_NUMERIC_D), 1949 | "KEY_CAMERA_FOCUS" => Ok(EV_KEY::KEY_CAMERA_FOCUS), 1950 | "KEY_WPS_BUTTON" => Ok(EV_KEY::KEY_WPS_BUTTON), 1951 | "KEY_TOUCHPAD_TOGGLE" => Ok(EV_KEY::KEY_TOUCHPAD_TOGGLE), 1952 | "KEY_TOUCHPAD_ON" => Ok(EV_KEY::KEY_TOUCHPAD_ON), 1953 | "KEY_TOUCHPAD_OFF" => Ok(EV_KEY::KEY_TOUCHPAD_OFF), 1954 | "KEY_CAMERA_ZOOMIN" => Ok(EV_KEY::KEY_CAMERA_ZOOMIN), 1955 | "KEY_CAMERA_ZOOMOUT" => Ok(EV_KEY::KEY_CAMERA_ZOOMOUT), 1956 | "KEY_CAMERA_UP" => Ok(EV_KEY::KEY_CAMERA_UP), 1957 | "KEY_CAMERA_DOWN" => Ok(EV_KEY::KEY_CAMERA_DOWN), 1958 | "KEY_CAMERA_LEFT" => Ok(EV_KEY::KEY_CAMERA_LEFT), 1959 | "KEY_CAMERA_RIGHT" => Ok(EV_KEY::KEY_CAMERA_RIGHT), 1960 | "KEY_ATTENDANT_ON" => Ok(EV_KEY::KEY_ATTENDANT_ON), 1961 | "KEY_ATTENDANT_OFF" => Ok(EV_KEY::KEY_ATTENDANT_OFF), 1962 | "KEY_ATTENDANT_TOGGLE" => Ok(EV_KEY::KEY_ATTENDANT_TOGGLE), 1963 | "KEY_LIGHTS_TOGGLE" => Ok(EV_KEY::KEY_LIGHTS_TOGGLE), 1964 | "KEY_ALS_TOGGLE" => Ok(EV_KEY::KEY_ALS_TOGGLE), 1965 | "KEY_ROTATE_LOCK_TOGGLE" => Ok(EV_KEY::KEY_ROTATE_LOCK_TOGGLE), 1966 | "KEY_BUTTONCONFIG" => Ok(EV_KEY::KEY_BUTTONCONFIG), 1967 | "KEY_TASKMANAGER" => Ok(EV_KEY::KEY_TASKMANAGER), 1968 | "KEY_JOURNAL" => Ok(EV_KEY::KEY_JOURNAL), 1969 | "KEY_CONTROLPANEL" => Ok(EV_KEY::KEY_CONTROLPANEL), 1970 | "KEY_APPSELECT" => Ok(EV_KEY::KEY_APPSELECT), 1971 | "KEY_SCREENSAVER" => Ok(EV_KEY::KEY_SCREENSAVER), 1972 | "KEY_VOICECOMMAND" => Ok(EV_KEY::KEY_VOICECOMMAND), 1973 | "KEY_ASSISTANT" => Ok(EV_KEY::KEY_ASSISTANT), 1974 | "KEY_KBD_LAYOUT_NEXT" => Ok(EV_KEY::KEY_KBD_LAYOUT_NEXT), 1975 | "KEY_EMOJI_PICKER" => Ok(EV_KEY::KEY_EMOJI_PICKER), 1976 | "KEY_DICTATE" => Ok(EV_KEY::KEY_DICTATE), 1977 | "KEY_CAMERA_ACCESS_ENABLE" => Ok(EV_KEY::KEY_CAMERA_ACCESS_ENABLE), 1978 | "KEY_CAMERA_ACCESS_DISABLE" => Ok(EV_KEY::KEY_CAMERA_ACCESS_DISABLE), 1979 | "KEY_CAMERA_ACCESS_TOGGLE" => Ok(EV_KEY::KEY_CAMERA_ACCESS_TOGGLE), 1980 | "KEY_BRIGHTNESS_MIN" => Ok(EV_KEY::KEY_BRIGHTNESS_MIN), 1981 | "KEY_BRIGHTNESS_MAX" => Ok(EV_KEY::KEY_BRIGHTNESS_MAX), 1982 | "KEY_KBDINPUTASSIST_PREV" => Ok(EV_KEY::KEY_KBDINPUTASSIST_PREV), 1983 | "KEY_KBDINPUTASSIST_NEXT" => Ok(EV_KEY::KEY_KBDINPUTASSIST_NEXT), 1984 | "KEY_KBDINPUTASSIST_PREVGROUP" => Ok(EV_KEY::KEY_KBDINPUTASSIST_PREVGROUP), 1985 | "KEY_KBDINPUTASSIST_NEXTGROUP" => Ok(EV_KEY::KEY_KBDINPUTASSIST_NEXTGROUP), 1986 | "KEY_KBDINPUTASSIST_ACCEPT" => Ok(EV_KEY::KEY_KBDINPUTASSIST_ACCEPT), 1987 | "KEY_KBDINPUTASSIST_CANCEL" => Ok(EV_KEY::KEY_KBDINPUTASSIST_CANCEL), 1988 | "KEY_RIGHT_UP" => Ok(EV_KEY::KEY_RIGHT_UP), 1989 | "KEY_RIGHT_DOWN" => Ok(EV_KEY::KEY_RIGHT_DOWN), 1990 | "KEY_LEFT_UP" => Ok(EV_KEY::KEY_LEFT_UP), 1991 | "KEY_LEFT_DOWN" => Ok(EV_KEY::KEY_LEFT_DOWN), 1992 | "KEY_ROOT_MENU" => Ok(EV_KEY::KEY_ROOT_MENU), 1993 | "KEY_MEDIA_TOP_MENU" => Ok(EV_KEY::KEY_MEDIA_TOP_MENU), 1994 | "KEY_NUMERIC_11" => Ok(EV_KEY::KEY_NUMERIC_11), 1995 | "KEY_NUMERIC_12" => Ok(EV_KEY::KEY_NUMERIC_12), 1996 | "KEY_AUDIO_DESC" => Ok(EV_KEY::KEY_AUDIO_DESC), 1997 | "KEY_3D_MODE" => Ok(EV_KEY::KEY_3D_MODE), 1998 | "KEY_NEXT_FAVORITE" => Ok(EV_KEY::KEY_NEXT_FAVORITE), 1999 | "KEY_STOP_RECORD" => Ok(EV_KEY::KEY_STOP_RECORD), 2000 | "KEY_PAUSE_RECORD" => Ok(EV_KEY::KEY_PAUSE_RECORD), 2001 | "KEY_VOD" => Ok(EV_KEY::KEY_VOD), 2002 | "KEY_UNMUTE" => Ok(EV_KEY::KEY_UNMUTE), 2003 | "KEY_FASTREVERSE" => Ok(EV_KEY::KEY_FASTREVERSE), 2004 | "KEY_SLOWREVERSE" => Ok(EV_KEY::KEY_SLOWREVERSE), 2005 | "KEY_DATA" => Ok(EV_KEY::KEY_DATA), 2006 | "KEY_ONSCREEN_KEYBOARD" => Ok(EV_KEY::KEY_ONSCREEN_KEYBOARD), 2007 | "KEY_PRIVACY_SCREEN_TOGGLE" => Ok(EV_KEY::KEY_PRIVACY_SCREEN_TOGGLE), 2008 | "KEY_SELECTIVE_SCREENSHOT" => Ok(EV_KEY::KEY_SELECTIVE_SCREENSHOT), 2009 | "KEY_NEXT_ELEMENT" => Ok(EV_KEY::KEY_NEXT_ELEMENT), 2010 | "KEY_PREVIOUS_ELEMENT" => Ok(EV_KEY::KEY_PREVIOUS_ELEMENT), 2011 | "KEY_AUTOPILOT_ENGAGE_TOGGLE" => Ok(EV_KEY::KEY_AUTOPILOT_ENGAGE_TOGGLE), 2012 | "KEY_MARK_WAYPOINT" => Ok(EV_KEY::KEY_MARK_WAYPOINT), 2013 | "KEY_SOS" => Ok(EV_KEY::KEY_SOS), 2014 | "KEY_NAV_CHART" => Ok(EV_KEY::KEY_NAV_CHART), 2015 | "KEY_FISHING_CHART" => Ok(EV_KEY::KEY_FISHING_CHART), 2016 | "KEY_SINGLE_RANGE_RADAR" => Ok(EV_KEY::KEY_SINGLE_RANGE_RADAR), 2017 | "KEY_DUAL_RANGE_RADAR" => Ok(EV_KEY::KEY_DUAL_RANGE_RADAR), 2018 | "KEY_RADAR_OVERLAY" => Ok(EV_KEY::KEY_RADAR_OVERLAY), 2019 | "KEY_TRADITIONAL_SONAR" => Ok(EV_KEY::KEY_TRADITIONAL_SONAR), 2020 | "KEY_CLEARVU_SONAR" => Ok(EV_KEY::KEY_CLEARVU_SONAR), 2021 | "KEY_SIDEVU_SONAR" => Ok(EV_KEY::KEY_SIDEVU_SONAR), 2022 | "KEY_NAV_INFO" => Ok(EV_KEY::KEY_NAV_INFO), 2023 | "KEY_BRIGHTNESS_MENU" => Ok(EV_KEY::KEY_BRIGHTNESS_MENU), 2024 | "KEY_MACRO1" => Ok(EV_KEY::KEY_MACRO1), 2025 | "KEY_MACRO2" => Ok(EV_KEY::KEY_MACRO2), 2026 | "KEY_MACRO3" => Ok(EV_KEY::KEY_MACRO3), 2027 | "KEY_MACRO4" => Ok(EV_KEY::KEY_MACRO4), 2028 | "KEY_MACRO5" => Ok(EV_KEY::KEY_MACRO5), 2029 | "KEY_MACRO6" => Ok(EV_KEY::KEY_MACRO6), 2030 | "KEY_MACRO7" => Ok(EV_KEY::KEY_MACRO7), 2031 | "KEY_MACRO8" => Ok(EV_KEY::KEY_MACRO8), 2032 | "KEY_MACRO9" => Ok(EV_KEY::KEY_MACRO9), 2033 | "KEY_MACRO10" => Ok(EV_KEY::KEY_MACRO10), 2034 | "KEY_MACRO11" => Ok(EV_KEY::KEY_MACRO11), 2035 | "KEY_MACRO12" => Ok(EV_KEY::KEY_MACRO12), 2036 | "KEY_MACRO13" => Ok(EV_KEY::KEY_MACRO13), 2037 | "KEY_MACRO14" => Ok(EV_KEY::KEY_MACRO14), 2038 | "KEY_MACRO15" => Ok(EV_KEY::KEY_MACRO15), 2039 | "KEY_MACRO16" => Ok(EV_KEY::KEY_MACRO16), 2040 | "KEY_MACRO17" => Ok(EV_KEY::KEY_MACRO17), 2041 | "KEY_MACRO18" => Ok(EV_KEY::KEY_MACRO18), 2042 | "KEY_MACRO19" => Ok(EV_KEY::KEY_MACRO19), 2043 | "KEY_MACRO20" => Ok(EV_KEY::KEY_MACRO20), 2044 | "KEY_MACRO21" => Ok(EV_KEY::KEY_MACRO21), 2045 | "KEY_MACRO22" => Ok(EV_KEY::KEY_MACRO22), 2046 | "KEY_MACRO23" => Ok(EV_KEY::KEY_MACRO23), 2047 | "KEY_MACRO24" => Ok(EV_KEY::KEY_MACRO24), 2048 | "KEY_MACRO25" => Ok(EV_KEY::KEY_MACRO25), 2049 | "KEY_MACRO26" => Ok(EV_KEY::KEY_MACRO26), 2050 | "KEY_MACRO27" => Ok(EV_KEY::KEY_MACRO27), 2051 | "KEY_MACRO28" => Ok(EV_KEY::KEY_MACRO28), 2052 | "KEY_MACRO29" => Ok(EV_KEY::KEY_MACRO29), 2053 | "KEY_MACRO30" => Ok(EV_KEY::KEY_MACRO30), 2054 | "KEY_MACRO_RECORD_START" => Ok(EV_KEY::KEY_MACRO_RECORD_START), 2055 | "KEY_MACRO_RECORD_STOP" => Ok(EV_KEY::KEY_MACRO_RECORD_STOP), 2056 | "KEY_MACRO_PRESET_CYCLE" => Ok(EV_KEY::KEY_MACRO_PRESET_CYCLE), 2057 | "KEY_MACRO_PRESET1" => Ok(EV_KEY::KEY_MACRO_PRESET1), 2058 | "KEY_MACRO_PRESET2" => Ok(EV_KEY::KEY_MACRO_PRESET2), 2059 | "KEY_MACRO_PRESET3" => Ok(EV_KEY::KEY_MACRO_PRESET3), 2060 | "KEY_KBD_LCD_MENU1" => Ok(EV_KEY::KEY_KBD_LCD_MENU1), 2061 | "KEY_KBD_LCD_MENU2" => Ok(EV_KEY::KEY_KBD_LCD_MENU2), 2062 | "KEY_KBD_LCD_MENU3" => Ok(EV_KEY::KEY_KBD_LCD_MENU3), 2063 | "KEY_KBD_LCD_MENU4" => Ok(EV_KEY::KEY_KBD_LCD_MENU4), 2064 | "KEY_KBD_LCD_MENU5" => Ok(EV_KEY::KEY_KBD_LCD_MENU5), 2065 | "KEY_MAX" => Ok(EV_KEY::KEY_MAX), 2066 | "BTN_0" => Ok(EV_KEY::BTN_0), 2067 | "BTN_1" => Ok(EV_KEY::BTN_1), 2068 | "BTN_2" => Ok(EV_KEY::BTN_2), 2069 | "BTN_3" => Ok(EV_KEY::BTN_3), 2070 | "BTN_4" => Ok(EV_KEY::BTN_4), 2071 | "BTN_5" => Ok(EV_KEY::BTN_5), 2072 | "BTN_6" => Ok(EV_KEY::BTN_6), 2073 | "BTN_7" => Ok(EV_KEY::BTN_7), 2074 | "BTN_8" => Ok(EV_KEY::BTN_8), 2075 | "BTN_9" => Ok(EV_KEY::BTN_9), 2076 | "BTN_LEFT" => Ok(EV_KEY::BTN_LEFT), 2077 | "BTN_RIGHT" => Ok(EV_KEY::BTN_RIGHT), 2078 | "BTN_MIDDLE" => Ok(EV_KEY::BTN_MIDDLE), 2079 | "BTN_SIDE" => Ok(EV_KEY::BTN_SIDE), 2080 | "BTN_EXTRA" => Ok(EV_KEY::BTN_EXTRA), 2081 | "BTN_FORWARD" => Ok(EV_KEY::BTN_FORWARD), 2082 | "BTN_BACK" => Ok(EV_KEY::BTN_BACK), 2083 | "BTN_TASK" => Ok(EV_KEY::BTN_TASK), 2084 | "BTN_TRIGGER" => Ok(EV_KEY::BTN_TRIGGER), 2085 | "BTN_THUMB" => Ok(EV_KEY::BTN_THUMB), 2086 | "BTN_THUMB2" => Ok(EV_KEY::BTN_THUMB2), 2087 | "BTN_TOP" => Ok(EV_KEY::BTN_TOP), 2088 | "BTN_TOP2" => Ok(EV_KEY::BTN_TOP2), 2089 | "BTN_PINKIE" => Ok(EV_KEY::BTN_PINKIE), 2090 | "BTN_BASE" => Ok(EV_KEY::BTN_BASE), 2091 | "BTN_BASE2" => Ok(EV_KEY::BTN_BASE2), 2092 | "BTN_BASE3" => Ok(EV_KEY::BTN_BASE3), 2093 | "BTN_BASE4" => Ok(EV_KEY::BTN_BASE4), 2094 | "BTN_BASE5" => Ok(EV_KEY::BTN_BASE5), 2095 | "BTN_BASE6" => Ok(EV_KEY::BTN_BASE6), 2096 | "BTN_DEAD" => Ok(EV_KEY::BTN_DEAD), 2097 | "BTN_SOUTH" => Ok(EV_KEY::BTN_SOUTH), 2098 | "BTN_EAST" => Ok(EV_KEY::BTN_EAST), 2099 | "BTN_C" => Ok(EV_KEY::BTN_C), 2100 | "BTN_NORTH" => Ok(EV_KEY::BTN_NORTH), 2101 | "BTN_WEST" => Ok(EV_KEY::BTN_WEST), 2102 | "BTN_Z" => Ok(EV_KEY::BTN_Z), 2103 | "BTN_TL" => Ok(EV_KEY::BTN_TL), 2104 | "BTN_TR" => Ok(EV_KEY::BTN_TR), 2105 | "BTN_TL2" => Ok(EV_KEY::BTN_TL2), 2106 | "BTN_TR2" => Ok(EV_KEY::BTN_TR2), 2107 | "BTN_SELECT" => Ok(EV_KEY::BTN_SELECT), 2108 | "BTN_START" => Ok(EV_KEY::BTN_START), 2109 | "BTN_MODE" => Ok(EV_KEY::BTN_MODE), 2110 | "BTN_THUMBL" => Ok(EV_KEY::BTN_THUMBL), 2111 | "BTN_THUMBR" => Ok(EV_KEY::BTN_THUMBR), 2112 | "BTN_TOOL_PEN" => Ok(EV_KEY::BTN_TOOL_PEN), 2113 | "BTN_TOOL_RUBBER" => Ok(EV_KEY::BTN_TOOL_RUBBER), 2114 | "BTN_TOOL_BRUSH" => Ok(EV_KEY::BTN_TOOL_BRUSH), 2115 | "BTN_TOOL_PENCIL" => Ok(EV_KEY::BTN_TOOL_PENCIL), 2116 | "BTN_TOOL_AIRBRUSH" => Ok(EV_KEY::BTN_TOOL_AIRBRUSH), 2117 | "BTN_TOOL_FINGER" => Ok(EV_KEY::BTN_TOOL_FINGER), 2118 | "BTN_TOOL_MOUSE" => Ok(EV_KEY::BTN_TOOL_MOUSE), 2119 | "BTN_TOOL_LENS" => Ok(EV_KEY::BTN_TOOL_LENS), 2120 | "BTN_TOOL_QUINTTAP" => Ok(EV_KEY::BTN_TOOL_QUINTTAP), 2121 | "BTN_STYLUS3" => Ok(EV_KEY::BTN_STYLUS3), 2122 | "BTN_TOUCH" => Ok(EV_KEY::BTN_TOUCH), 2123 | "BTN_STYLUS" => Ok(EV_KEY::BTN_STYLUS), 2124 | "BTN_STYLUS2" => Ok(EV_KEY::BTN_STYLUS2), 2125 | "BTN_TOOL_DOUBLETAP" => Ok(EV_KEY::BTN_TOOL_DOUBLETAP), 2126 | "BTN_TOOL_TRIPLETAP" => Ok(EV_KEY::BTN_TOOL_TRIPLETAP), 2127 | "BTN_TOOL_QUADTAP" => Ok(EV_KEY::BTN_TOOL_QUADTAP), 2128 | "BTN_GEAR_DOWN" => Ok(EV_KEY::BTN_GEAR_DOWN), 2129 | "BTN_GEAR_UP" => Ok(EV_KEY::BTN_GEAR_UP), 2130 | "BTN_DPAD_UP" => Ok(EV_KEY::BTN_DPAD_UP), 2131 | "BTN_DPAD_DOWN" => Ok(EV_KEY::BTN_DPAD_DOWN), 2132 | "BTN_DPAD_LEFT" => Ok(EV_KEY::BTN_DPAD_LEFT), 2133 | "BTN_DPAD_RIGHT" => Ok(EV_KEY::BTN_DPAD_RIGHT), 2134 | "BTN_TRIGGER_HAPPY1" => Ok(EV_KEY::BTN_TRIGGER_HAPPY1), 2135 | "BTN_TRIGGER_HAPPY2" => Ok(EV_KEY::BTN_TRIGGER_HAPPY2), 2136 | "BTN_TRIGGER_HAPPY3" => Ok(EV_KEY::BTN_TRIGGER_HAPPY3), 2137 | "BTN_TRIGGER_HAPPY4" => Ok(EV_KEY::BTN_TRIGGER_HAPPY4), 2138 | "BTN_TRIGGER_HAPPY5" => Ok(EV_KEY::BTN_TRIGGER_HAPPY5), 2139 | "BTN_TRIGGER_HAPPY6" => Ok(EV_KEY::BTN_TRIGGER_HAPPY6), 2140 | "BTN_TRIGGER_HAPPY7" => Ok(EV_KEY::BTN_TRIGGER_HAPPY7), 2141 | "BTN_TRIGGER_HAPPY8" => Ok(EV_KEY::BTN_TRIGGER_HAPPY8), 2142 | "BTN_TRIGGER_HAPPY9" => Ok(EV_KEY::BTN_TRIGGER_HAPPY9), 2143 | "BTN_TRIGGER_HAPPY10" => Ok(EV_KEY::BTN_TRIGGER_HAPPY10), 2144 | "BTN_TRIGGER_HAPPY11" => Ok(EV_KEY::BTN_TRIGGER_HAPPY11), 2145 | "BTN_TRIGGER_HAPPY12" => Ok(EV_KEY::BTN_TRIGGER_HAPPY12), 2146 | "BTN_TRIGGER_HAPPY13" => Ok(EV_KEY::BTN_TRIGGER_HAPPY13), 2147 | "BTN_TRIGGER_HAPPY14" => Ok(EV_KEY::BTN_TRIGGER_HAPPY14), 2148 | "BTN_TRIGGER_HAPPY15" => Ok(EV_KEY::BTN_TRIGGER_HAPPY15), 2149 | "BTN_TRIGGER_HAPPY16" => Ok(EV_KEY::BTN_TRIGGER_HAPPY16), 2150 | "BTN_TRIGGER_HAPPY17" => Ok(EV_KEY::BTN_TRIGGER_HAPPY17), 2151 | "BTN_TRIGGER_HAPPY18" => Ok(EV_KEY::BTN_TRIGGER_HAPPY18), 2152 | "BTN_TRIGGER_HAPPY19" => Ok(EV_KEY::BTN_TRIGGER_HAPPY19), 2153 | "BTN_TRIGGER_HAPPY20" => Ok(EV_KEY::BTN_TRIGGER_HAPPY20), 2154 | "BTN_TRIGGER_HAPPY21" => Ok(EV_KEY::BTN_TRIGGER_HAPPY21), 2155 | "BTN_TRIGGER_HAPPY22" => Ok(EV_KEY::BTN_TRIGGER_HAPPY22), 2156 | "BTN_TRIGGER_HAPPY23" => Ok(EV_KEY::BTN_TRIGGER_HAPPY23), 2157 | "BTN_TRIGGER_HAPPY24" => Ok(EV_KEY::BTN_TRIGGER_HAPPY24), 2158 | "BTN_TRIGGER_HAPPY25" => Ok(EV_KEY::BTN_TRIGGER_HAPPY25), 2159 | "BTN_TRIGGER_HAPPY26" => Ok(EV_KEY::BTN_TRIGGER_HAPPY26), 2160 | "BTN_TRIGGER_HAPPY27" => Ok(EV_KEY::BTN_TRIGGER_HAPPY27), 2161 | "BTN_TRIGGER_HAPPY28" => Ok(EV_KEY::BTN_TRIGGER_HAPPY28), 2162 | "BTN_TRIGGER_HAPPY29" => Ok(EV_KEY::BTN_TRIGGER_HAPPY29), 2163 | "BTN_TRIGGER_HAPPY30" => Ok(EV_KEY::BTN_TRIGGER_HAPPY30), 2164 | "BTN_TRIGGER_HAPPY31" => Ok(EV_KEY::BTN_TRIGGER_HAPPY31), 2165 | "BTN_TRIGGER_HAPPY32" => Ok(EV_KEY::BTN_TRIGGER_HAPPY32), 2166 | "BTN_TRIGGER_HAPPY33" => Ok(EV_KEY::BTN_TRIGGER_HAPPY33), 2167 | "BTN_TRIGGER_HAPPY34" => Ok(EV_KEY::BTN_TRIGGER_HAPPY34), 2168 | "BTN_TRIGGER_HAPPY35" => Ok(EV_KEY::BTN_TRIGGER_HAPPY35), 2169 | "BTN_TRIGGER_HAPPY36" => Ok(EV_KEY::BTN_TRIGGER_HAPPY36), 2170 | "BTN_TRIGGER_HAPPY37" => Ok(EV_KEY::BTN_TRIGGER_HAPPY37), 2171 | "BTN_TRIGGER_HAPPY38" => Ok(EV_KEY::BTN_TRIGGER_HAPPY38), 2172 | "BTN_TRIGGER_HAPPY39" => Ok(EV_KEY::BTN_TRIGGER_HAPPY39), 2173 | "BTN_TRIGGER_HAPPY40" => Ok(EV_KEY::BTN_TRIGGER_HAPPY40), 2174 | _ => Err(()), 2175 | } 2176 | } 2177 | } 2178 | 2179 | impl std::fmt::Display for EV_KEY { 2180 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2181 | write!(f, "{:?}", self) 2182 | } 2183 | } 2184 | 2185 | #[allow(non_camel_case_types)] 2186 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2187 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2188 | pub enum EV_LED { 2189 | LED_NUML = 0, 2190 | LED_CAPSL = 1, 2191 | LED_SCROLLL = 2, 2192 | LED_COMPOSE = 3, 2193 | LED_KANA = 4, 2194 | LED_SLEEP = 5, 2195 | LED_SUSPEND = 6, 2196 | LED_MUTE = 7, 2197 | LED_MISC = 8, 2198 | LED_MAIL = 9, 2199 | LED_CHARGING = 10, 2200 | LED_MAX = 15, 2201 | } 2202 | 2203 | pub const fn int_to_ev_led(code: u32) -> Option { 2204 | match code { 2205 | 0 => Some(EV_LED::LED_NUML), 2206 | 1 => Some(EV_LED::LED_CAPSL), 2207 | 2 => Some(EV_LED::LED_SCROLLL), 2208 | 3 => Some(EV_LED::LED_COMPOSE), 2209 | 4 => Some(EV_LED::LED_KANA), 2210 | 5 => Some(EV_LED::LED_SLEEP), 2211 | 6 => Some(EV_LED::LED_SUSPEND), 2212 | 7 => Some(EV_LED::LED_MUTE), 2213 | 8 => Some(EV_LED::LED_MISC), 2214 | 9 => Some(EV_LED::LED_MAIL), 2215 | 10 => Some(EV_LED::LED_CHARGING), 2216 | 15 => Some(EV_LED::LED_MAX), 2217 | _ => None, 2218 | } 2219 | } 2220 | 2221 | impl std::str::FromStr for EV_LED { 2222 | type Err = (); 2223 | fn from_str(s: &str) -> Result { 2224 | match s { 2225 | "LED_NUML" => Ok(EV_LED::LED_NUML), 2226 | "LED_CAPSL" => Ok(EV_LED::LED_CAPSL), 2227 | "LED_SCROLLL" => Ok(EV_LED::LED_SCROLLL), 2228 | "LED_COMPOSE" => Ok(EV_LED::LED_COMPOSE), 2229 | "LED_KANA" => Ok(EV_LED::LED_KANA), 2230 | "LED_SLEEP" => Ok(EV_LED::LED_SLEEP), 2231 | "LED_SUSPEND" => Ok(EV_LED::LED_SUSPEND), 2232 | "LED_MUTE" => Ok(EV_LED::LED_MUTE), 2233 | "LED_MISC" => Ok(EV_LED::LED_MISC), 2234 | "LED_MAIL" => Ok(EV_LED::LED_MAIL), 2235 | "LED_CHARGING" => Ok(EV_LED::LED_CHARGING), 2236 | "LED_MAX" => Ok(EV_LED::LED_MAX), 2237 | _ => Err(()), 2238 | } 2239 | } 2240 | } 2241 | 2242 | impl std::fmt::Display for EV_LED { 2243 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2244 | write!(f, "{:?}", self) 2245 | } 2246 | } 2247 | 2248 | #[allow(non_camel_case_types)] 2249 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2250 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2251 | pub enum EV_SND { 2252 | SND_CLICK = 0, 2253 | SND_BELL = 1, 2254 | SND_TONE = 2, 2255 | SND_MAX = 7, 2256 | } 2257 | 2258 | pub const fn int_to_ev_snd(code: u32) -> Option { 2259 | match code { 2260 | 0 => Some(EV_SND::SND_CLICK), 2261 | 1 => Some(EV_SND::SND_BELL), 2262 | 2 => Some(EV_SND::SND_TONE), 2263 | 7 => Some(EV_SND::SND_MAX), 2264 | _ => None, 2265 | } 2266 | } 2267 | 2268 | impl std::str::FromStr for EV_SND { 2269 | type Err = (); 2270 | fn from_str(s: &str) -> Result { 2271 | match s { 2272 | "SND_CLICK" => Ok(EV_SND::SND_CLICK), 2273 | "SND_BELL" => Ok(EV_SND::SND_BELL), 2274 | "SND_TONE" => Ok(EV_SND::SND_TONE), 2275 | "SND_MAX" => Ok(EV_SND::SND_MAX), 2276 | _ => Err(()), 2277 | } 2278 | } 2279 | } 2280 | 2281 | impl std::fmt::Display for EV_SND { 2282 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2283 | write!(f, "{:?}", self) 2284 | } 2285 | } 2286 | 2287 | #[allow(non_camel_case_types)] 2288 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2289 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2290 | pub enum EV_MSC { 2291 | MSC_SERIAL = 0, 2292 | MSC_PULSELED = 1, 2293 | MSC_GESTURE = 2, 2294 | MSC_RAW = 3, 2295 | MSC_SCAN = 4, 2296 | MSC_TIMESTAMP = 5, 2297 | MSC_MAX = 7, 2298 | } 2299 | 2300 | pub const fn int_to_ev_msc(code: u32) -> Option { 2301 | match code { 2302 | 0 => Some(EV_MSC::MSC_SERIAL), 2303 | 1 => Some(EV_MSC::MSC_PULSELED), 2304 | 2 => Some(EV_MSC::MSC_GESTURE), 2305 | 3 => Some(EV_MSC::MSC_RAW), 2306 | 4 => Some(EV_MSC::MSC_SCAN), 2307 | 5 => Some(EV_MSC::MSC_TIMESTAMP), 2308 | 7 => Some(EV_MSC::MSC_MAX), 2309 | _ => None, 2310 | } 2311 | } 2312 | 2313 | impl std::str::FromStr for EV_MSC { 2314 | type Err = (); 2315 | fn from_str(s: &str) -> Result { 2316 | match s { 2317 | "MSC_SERIAL" => Ok(EV_MSC::MSC_SERIAL), 2318 | "MSC_PULSELED" => Ok(EV_MSC::MSC_PULSELED), 2319 | "MSC_GESTURE" => Ok(EV_MSC::MSC_GESTURE), 2320 | "MSC_RAW" => Ok(EV_MSC::MSC_RAW), 2321 | "MSC_SCAN" => Ok(EV_MSC::MSC_SCAN), 2322 | "MSC_TIMESTAMP" => Ok(EV_MSC::MSC_TIMESTAMP), 2323 | "MSC_MAX" => Ok(EV_MSC::MSC_MAX), 2324 | _ => Err(()), 2325 | } 2326 | } 2327 | } 2328 | 2329 | impl std::fmt::Display for EV_MSC { 2330 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2331 | write!(f, "{:?}", self) 2332 | } 2333 | } 2334 | 2335 | #[allow(non_camel_case_types)] 2336 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2337 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2338 | pub enum EV_SW { 2339 | SW_LID = 0, 2340 | SW_TABLET_MODE = 1, 2341 | SW_HEADPHONE_INSERT = 2, 2342 | SW_RFKILL_ALL = 3, 2343 | SW_MICROPHONE_INSERT = 4, 2344 | SW_DOCK = 5, 2345 | SW_LINEOUT_INSERT = 6, 2346 | SW_JACK_PHYSICAL_INSERT = 7, 2347 | SW_VIDEOOUT_INSERT = 8, 2348 | SW_CAMERA_LENS_COVER = 9, 2349 | SW_KEYPAD_SLIDE = 10, 2350 | SW_FRONT_PROXIMITY = 11, 2351 | SW_ROTATE_LOCK = 12, 2352 | SW_LINEIN_INSERT = 13, 2353 | SW_MUTE_DEVICE = 14, 2354 | SW_PEN_INSERTED = 15, 2355 | SW_MACHINE_COVER = 16, 2356 | } 2357 | 2358 | impl EV_SW { 2359 | pub const SW_MAX: EV_SW = EV_SW::SW_MACHINE_COVER; 2360 | } 2361 | 2362 | pub const fn int_to_ev_sw(code: u32) -> Option { 2363 | match code { 2364 | 0 => Some(EV_SW::SW_LID), 2365 | 1 => Some(EV_SW::SW_TABLET_MODE), 2366 | 2 => Some(EV_SW::SW_HEADPHONE_INSERT), 2367 | 3 => Some(EV_SW::SW_RFKILL_ALL), 2368 | 4 => Some(EV_SW::SW_MICROPHONE_INSERT), 2369 | 5 => Some(EV_SW::SW_DOCK), 2370 | 6 => Some(EV_SW::SW_LINEOUT_INSERT), 2371 | 7 => Some(EV_SW::SW_JACK_PHYSICAL_INSERT), 2372 | 8 => Some(EV_SW::SW_VIDEOOUT_INSERT), 2373 | 9 => Some(EV_SW::SW_CAMERA_LENS_COVER), 2374 | 10 => Some(EV_SW::SW_KEYPAD_SLIDE), 2375 | 11 => Some(EV_SW::SW_FRONT_PROXIMITY), 2376 | 12 => Some(EV_SW::SW_ROTATE_LOCK), 2377 | 13 => Some(EV_SW::SW_LINEIN_INSERT), 2378 | 14 => Some(EV_SW::SW_MUTE_DEVICE), 2379 | 15 => Some(EV_SW::SW_PEN_INSERTED), 2380 | 16 => Some(EV_SW::SW_MACHINE_COVER), 2381 | _ => None, 2382 | } 2383 | } 2384 | 2385 | impl std::str::FromStr for EV_SW { 2386 | type Err = (); 2387 | fn from_str(s: &str) -> Result { 2388 | match s { 2389 | "SW_LID" => Ok(EV_SW::SW_LID), 2390 | "SW_TABLET_MODE" => Ok(EV_SW::SW_TABLET_MODE), 2391 | "SW_HEADPHONE_INSERT" => Ok(EV_SW::SW_HEADPHONE_INSERT), 2392 | "SW_RFKILL_ALL" => Ok(EV_SW::SW_RFKILL_ALL), 2393 | "SW_MICROPHONE_INSERT" => Ok(EV_SW::SW_MICROPHONE_INSERT), 2394 | "SW_DOCK" => Ok(EV_SW::SW_DOCK), 2395 | "SW_LINEOUT_INSERT" => Ok(EV_SW::SW_LINEOUT_INSERT), 2396 | "SW_JACK_PHYSICAL_INSERT" => Ok(EV_SW::SW_JACK_PHYSICAL_INSERT), 2397 | "SW_VIDEOOUT_INSERT" => Ok(EV_SW::SW_VIDEOOUT_INSERT), 2398 | "SW_CAMERA_LENS_COVER" => Ok(EV_SW::SW_CAMERA_LENS_COVER), 2399 | "SW_KEYPAD_SLIDE" => Ok(EV_SW::SW_KEYPAD_SLIDE), 2400 | "SW_FRONT_PROXIMITY" => Ok(EV_SW::SW_FRONT_PROXIMITY), 2401 | "SW_ROTATE_LOCK" => Ok(EV_SW::SW_ROTATE_LOCK), 2402 | "SW_LINEIN_INSERT" => Ok(EV_SW::SW_LINEIN_INSERT), 2403 | "SW_MUTE_DEVICE" => Ok(EV_SW::SW_MUTE_DEVICE), 2404 | "SW_PEN_INSERTED" => Ok(EV_SW::SW_PEN_INSERTED), 2405 | "SW_MACHINE_COVER" => Ok(EV_SW::SW_MACHINE_COVER), 2406 | _ => Err(()), 2407 | } 2408 | } 2409 | } 2410 | 2411 | impl std::fmt::Display for EV_SW { 2412 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2413 | write!(f, "{:?}", self) 2414 | } 2415 | } 2416 | 2417 | #[allow(non_camel_case_types)] 2418 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2419 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2420 | pub enum EV_SYN { 2421 | SYN_REPORT = 0, 2422 | SYN_CONFIG = 1, 2423 | SYN_MT_REPORT = 2, 2424 | SYN_DROPPED = 3, 2425 | SYN_MAX = 15, 2426 | } 2427 | 2428 | pub const fn int_to_ev_syn(code: u32) -> Option { 2429 | match code { 2430 | 0 => Some(EV_SYN::SYN_REPORT), 2431 | 1 => Some(EV_SYN::SYN_CONFIG), 2432 | 2 => Some(EV_SYN::SYN_MT_REPORT), 2433 | 3 => Some(EV_SYN::SYN_DROPPED), 2434 | 15 => Some(EV_SYN::SYN_MAX), 2435 | _ => None, 2436 | } 2437 | } 2438 | 2439 | impl std::str::FromStr for EV_SYN { 2440 | type Err = (); 2441 | fn from_str(s: &str) -> Result { 2442 | match s { 2443 | "SYN_REPORT" => Ok(EV_SYN::SYN_REPORT), 2444 | "SYN_CONFIG" => Ok(EV_SYN::SYN_CONFIG), 2445 | "SYN_MT_REPORT" => Ok(EV_SYN::SYN_MT_REPORT), 2446 | "SYN_DROPPED" => Ok(EV_SYN::SYN_DROPPED), 2447 | "SYN_MAX" => Ok(EV_SYN::SYN_MAX), 2448 | _ => Err(()), 2449 | } 2450 | } 2451 | } 2452 | 2453 | impl std::fmt::Display for EV_SYN { 2454 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2455 | write!(f, "{:?}", self) 2456 | } 2457 | } 2458 | 2459 | #[allow(non_camel_case_types)] 2460 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2461 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2462 | pub enum EV_REP { 2463 | REP_DELAY = 0, 2464 | REP_PERIOD = 1, 2465 | } 2466 | 2467 | impl EV_REP { 2468 | pub const REP_MAX: EV_REP = EV_REP::REP_PERIOD; 2469 | } 2470 | 2471 | pub const fn int_to_ev_rep(code: u32) -> Option { 2472 | match code { 2473 | 0 => Some(EV_REP::REP_DELAY), 2474 | 1 => Some(EV_REP::REP_PERIOD), 2475 | _ => None, 2476 | } 2477 | } 2478 | 2479 | impl std::str::FromStr for EV_REP { 2480 | type Err = (); 2481 | fn from_str(s: &str) -> Result { 2482 | match s { 2483 | "REP_DELAY" => Ok(EV_REP::REP_DELAY), 2484 | "REP_PERIOD" => Ok(EV_REP::REP_PERIOD), 2485 | _ => Err(()), 2486 | } 2487 | } 2488 | } 2489 | 2490 | impl std::fmt::Display for EV_REP { 2491 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2492 | write!(f, "{:?}", self) 2493 | } 2494 | } 2495 | 2496 | #[allow(non_camel_case_types)] 2497 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2498 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2499 | pub enum InputProp { 2500 | INPUT_PROP_POINTER = 0, 2501 | INPUT_PROP_DIRECT = 1, 2502 | INPUT_PROP_BUTTONPAD = 2, 2503 | INPUT_PROP_SEMI_MT = 3, 2504 | INPUT_PROP_TOPBUTTONPAD = 4, 2505 | INPUT_PROP_POINTING_STICK = 5, 2506 | INPUT_PROP_ACCELEROMETER = 6, 2507 | INPUT_PROP_MAX = 31, 2508 | } 2509 | 2510 | pub const fn int_to_input_prop(code: u32) -> Option { 2511 | match code { 2512 | 0 => Some(InputProp::INPUT_PROP_POINTER), 2513 | 1 => Some(InputProp::INPUT_PROP_DIRECT), 2514 | 2 => Some(InputProp::INPUT_PROP_BUTTONPAD), 2515 | 3 => Some(InputProp::INPUT_PROP_SEMI_MT), 2516 | 4 => Some(InputProp::INPUT_PROP_TOPBUTTONPAD), 2517 | 5 => Some(InputProp::INPUT_PROP_POINTING_STICK), 2518 | 6 => Some(InputProp::INPUT_PROP_ACCELEROMETER), 2519 | 31 => Some(InputProp::INPUT_PROP_MAX), 2520 | _ => None, 2521 | } 2522 | } 2523 | 2524 | impl std::str::FromStr for InputProp { 2525 | type Err = (); 2526 | fn from_str(s: &str) -> Result { 2527 | match s { 2528 | "INPUT_PROP_POINTER" => Ok(InputProp::INPUT_PROP_POINTER), 2529 | "INPUT_PROP_DIRECT" => Ok(InputProp::INPUT_PROP_DIRECT), 2530 | "INPUT_PROP_BUTTONPAD" => Ok(InputProp::INPUT_PROP_BUTTONPAD), 2531 | "INPUT_PROP_SEMI_MT" => Ok(InputProp::INPUT_PROP_SEMI_MT), 2532 | "INPUT_PROP_TOPBUTTONPAD" => Ok(InputProp::INPUT_PROP_TOPBUTTONPAD), 2533 | "INPUT_PROP_POINTING_STICK" => Ok(InputProp::INPUT_PROP_POINTING_STICK), 2534 | "INPUT_PROP_ACCELEROMETER" => Ok(InputProp::INPUT_PROP_ACCELEROMETER), 2535 | "INPUT_PROP_MAX" => Ok(InputProp::INPUT_PROP_MAX), 2536 | _ => Err(()), 2537 | } 2538 | } 2539 | } 2540 | 2541 | #[allow(non_camel_case_types)] 2542 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2543 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2544 | pub enum EV_FF { 2545 | FF_STATUS_STOPPED = 0, 2546 | FF_STATUS_PLAYING = 1, 2547 | FF_RUMBLE = 80, 2548 | FF_PERIODIC = 81, 2549 | FF_CONSTANT = 82, 2550 | FF_SPRING = 83, 2551 | FF_FRICTION = 84, 2552 | FF_DAMPER = 85, 2553 | FF_INERTIA = 86, 2554 | FF_RAMP = 87, 2555 | FF_SQUARE = 88, 2556 | FF_TRIANGLE = 89, 2557 | FF_SINE = 90, 2558 | FF_SAW_UP = 91, 2559 | FF_SAW_DOWN = 92, 2560 | FF_CUSTOM = 93, 2561 | FF_GAIN = 96, 2562 | FF_AUTOCENTER = 97, 2563 | FF_MAX = 127, 2564 | } 2565 | 2566 | impl EV_FF { 2567 | pub const FF_STATUS_MAX: EV_FF = EV_FF::FF_STATUS_PLAYING; 2568 | } 2569 | 2570 | pub const fn int_to_ev_ff(code: u32) -> Option { 2571 | match code { 2572 | 0 => Some(EV_FF::FF_STATUS_STOPPED), 2573 | 1 => Some(EV_FF::FF_STATUS_PLAYING), 2574 | 80 => Some(EV_FF::FF_RUMBLE), 2575 | 81 => Some(EV_FF::FF_PERIODIC), 2576 | 82 => Some(EV_FF::FF_CONSTANT), 2577 | 83 => Some(EV_FF::FF_SPRING), 2578 | 84 => Some(EV_FF::FF_FRICTION), 2579 | 85 => Some(EV_FF::FF_DAMPER), 2580 | 86 => Some(EV_FF::FF_INERTIA), 2581 | 87 => Some(EV_FF::FF_RAMP), 2582 | 88 => Some(EV_FF::FF_SQUARE), 2583 | 89 => Some(EV_FF::FF_TRIANGLE), 2584 | 90 => Some(EV_FF::FF_SINE), 2585 | 91 => Some(EV_FF::FF_SAW_UP), 2586 | 92 => Some(EV_FF::FF_SAW_DOWN), 2587 | 93 => Some(EV_FF::FF_CUSTOM), 2588 | 96 => Some(EV_FF::FF_GAIN), 2589 | 97 => Some(EV_FF::FF_AUTOCENTER), 2590 | 127 => Some(EV_FF::FF_MAX), 2591 | _ => None, 2592 | } 2593 | } 2594 | 2595 | impl std::str::FromStr for EV_FF { 2596 | type Err = (); 2597 | fn from_str(s: &str) -> Result { 2598 | match s { 2599 | "FF_STATUS_STOPPED" => Ok(EV_FF::FF_STATUS_STOPPED), 2600 | "FF_STATUS_PLAYING" => Ok(EV_FF::FF_STATUS_PLAYING), 2601 | "FF_RUMBLE" => Ok(EV_FF::FF_RUMBLE), 2602 | "FF_PERIODIC" => Ok(EV_FF::FF_PERIODIC), 2603 | "FF_CONSTANT" => Ok(EV_FF::FF_CONSTANT), 2604 | "FF_SPRING" => Ok(EV_FF::FF_SPRING), 2605 | "FF_FRICTION" => Ok(EV_FF::FF_FRICTION), 2606 | "FF_DAMPER" => Ok(EV_FF::FF_DAMPER), 2607 | "FF_INERTIA" => Ok(EV_FF::FF_INERTIA), 2608 | "FF_RAMP" => Ok(EV_FF::FF_RAMP), 2609 | "FF_SQUARE" => Ok(EV_FF::FF_SQUARE), 2610 | "FF_TRIANGLE" => Ok(EV_FF::FF_TRIANGLE), 2611 | "FF_SINE" => Ok(EV_FF::FF_SINE), 2612 | "FF_SAW_UP" => Ok(EV_FF::FF_SAW_UP), 2613 | "FF_SAW_DOWN" => Ok(EV_FF::FF_SAW_DOWN), 2614 | "FF_CUSTOM" => Ok(EV_FF::FF_CUSTOM), 2615 | "FF_GAIN" => Ok(EV_FF::FF_GAIN), 2616 | "FF_AUTOCENTER" => Ok(EV_FF::FF_AUTOCENTER), 2617 | "FF_MAX" => Ok(EV_FF::FF_MAX), 2618 | _ => Err(()), 2619 | } 2620 | } 2621 | } 2622 | 2623 | impl std::fmt::Display for EV_FF { 2624 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2625 | write!(f, "{:?}", self) 2626 | } 2627 | } 2628 | 2629 | #[allow(non_camel_case_types)] 2630 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 2631 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 2632 | pub enum BusType { 2633 | BUS_PCI = 1, 2634 | BUS_ISAPNP = 2, 2635 | BUS_USB = 3, 2636 | BUS_HIL = 4, 2637 | BUS_BLUETOOTH = 5, 2638 | BUS_VIRTUAL = 6, 2639 | BUS_ISA = 16, 2640 | BUS_I8042 = 17, 2641 | BUS_XTKBD = 18, 2642 | BUS_RS232 = 19, 2643 | BUS_GAMEPORT = 20, 2644 | BUS_PARPORT = 21, 2645 | BUS_AMIGA = 22, 2646 | BUS_ADB = 23, 2647 | BUS_I2C = 24, 2648 | BUS_HOST = 25, 2649 | BUS_GSC = 26, 2650 | BUS_ATARI = 27, 2651 | BUS_SPI = 28, 2652 | BUS_RMI = 29, 2653 | BUS_CEC = 30, 2654 | BUS_INTEL_ISHTP = 31, 2655 | BUS_AMD_SFH = 32, 2656 | } 2657 | 2658 | pub const fn int_to_bus_type(code: u32) -> Option { 2659 | match code { 2660 | 1 => Some(BusType::BUS_PCI), 2661 | 2 => Some(BusType::BUS_ISAPNP), 2662 | 3 => Some(BusType::BUS_USB), 2663 | 4 => Some(BusType::BUS_HIL), 2664 | 5 => Some(BusType::BUS_BLUETOOTH), 2665 | 6 => Some(BusType::BUS_VIRTUAL), 2666 | 16 => Some(BusType::BUS_ISA), 2667 | 17 => Some(BusType::BUS_I8042), 2668 | 18 => Some(BusType::BUS_XTKBD), 2669 | 19 => Some(BusType::BUS_RS232), 2670 | 20 => Some(BusType::BUS_GAMEPORT), 2671 | 21 => Some(BusType::BUS_PARPORT), 2672 | 22 => Some(BusType::BUS_AMIGA), 2673 | 23 => Some(BusType::BUS_ADB), 2674 | 24 => Some(BusType::BUS_I2C), 2675 | 25 => Some(BusType::BUS_HOST), 2676 | 26 => Some(BusType::BUS_GSC), 2677 | 27 => Some(BusType::BUS_ATARI), 2678 | 28 => Some(BusType::BUS_SPI), 2679 | 29 => Some(BusType::BUS_RMI), 2680 | 30 => Some(BusType::BUS_CEC), 2681 | 31 => Some(BusType::BUS_INTEL_ISHTP), 2682 | 32 => Some(BusType::BUS_AMD_SFH), 2683 | _ => None, 2684 | } 2685 | } 2686 | 2687 | impl std::str::FromStr for BusType { 2688 | type Err = (); 2689 | fn from_str(s: &str) -> Result { 2690 | match s { 2691 | "BUS_PCI" => Ok(BusType::BUS_PCI), 2692 | "BUS_ISAPNP" => Ok(BusType::BUS_ISAPNP), 2693 | "BUS_USB" => Ok(BusType::BUS_USB), 2694 | "BUS_HIL" => Ok(BusType::BUS_HIL), 2695 | "BUS_BLUETOOTH" => Ok(BusType::BUS_BLUETOOTH), 2696 | "BUS_VIRTUAL" => Ok(BusType::BUS_VIRTUAL), 2697 | "BUS_ISA" => Ok(BusType::BUS_ISA), 2698 | "BUS_I8042" => Ok(BusType::BUS_I8042), 2699 | "BUS_XTKBD" => Ok(BusType::BUS_XTKBD), 2700 | "BUS_RS232" => Ok(BusType::BUS_RS232), 2701 | "BUS_GAMEPORT" => Ok(BusType::BUS_GAMEPORT), 2702 | "BUS_PARPORT" => Ok(BusType::BUS_PARPORT), 2703 | "BUS_AMIGA" => Ok(BusType::BUS_AMIGA), 2704 | "BUS_ADB" => Ok(BusType::BUS_ADB), 2705 | "BUS_I2C" => Ok(BusType::BUS_I2C), 2706 | "BUS_HOST" => Ok(BusType::BUS_HOST), 2707 | "BUS_GSC" => Ok(BusType::BUS_GSC), 2708 | "BUS_ATARI" => Ok(BusType::BUS_ATARI), 2709 | "BUS_SPI" => Ok(BusType::BUS_SPI), 2710 | "BUS_RMI" => Ok(BusType::BUS_RMI), 2711 | "BUS_CEC" => Ok(BusType::BUS_CEC), 2712 | "BUS_INTEL_ISHTP" => Ok(BusType::BUS_INTEL_ISHTP), 2713 | "BUS_AMD_SFH" => Ok(BusType::BUS_AMD_SFH), 2714 | _ => Err(()), 2715 | } 2716 | } 2717 | } 2718 | 2719 | impl std::fmt::Display for BusType { 2720 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 2721 | write!(f, "{:?}", self) 2722 | } 2723 | } 2724 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Rust bindings to libevdev, a wrapper for evdev devices. 2 | //! 3 | //! This library intends to provide a safe interface to the libevdev library. It 4 | //! will look for the library on the local system, and link to the installed copy. 5 | //! 6 | //! # Examples 7 | //! 8 | //! ## Intializing a evdev device 9 | //! 10 | //! ```rust,no_run 11 | //! use evdev_rs::Device; 12 | //! use std::fs::File; 13 | //! 14 | //! let mut d = Device::new_from_path("/dev/input/event0").unwrap(); 15 | //! ``` 16 | //! 17 | //! ## Getting the next event 18 | //! 19 | //! ```rust,no_run 20 | //! use evdev_rs::Device; 21 | //! use std::fs::File; 22 | //! use evdev_rs::ReadFlag; 23 | //! 24 | //! let mut d = Device::new_from_path("/dev/input/event0").unwrap(); 25 | //! 26 | //! loop { 27 | //! let ev = d.next_event(ReadFlag::NORMAL).map(|val| val.1); 28 | //! match ev { 29 | //! Ok(ev) => println!("Event: time {}.{}, ++++++++++++++++++++ {} +++++++++++++++", 30 | //! ev.time.tv_sec, 31 | //! ev.time.tv_usec, 32 | //! ev.event_type().map(|ev_type| format!("{}", ev_type)).unwrap_or("".to_owned())), 33 | //! Err(e) => (), 34 | //! } 35 | //! } 36 | //! ``` 37 | //! 38 | //! ## Serialization 39 | //! to use serialization, you muse enable the `serde` feature. 40 | //! ```toml 41 | //! # Cargo.toml 42 | //! [dependencies] 43 | //! evdev-rs = { version = "0.4.0", features = ["serde"] } 44 | //! ``` 45 | 46 | #[macro_use] 47 | mod macros; 48 | mod device; 49 | pub mod enums; 50 | pub mod logging; 51 | mod uinput; 52 | pub mod util; 53 | 54 | use bitflags::bitflags; 55 | use libc::{c_uint, suseconds_t, time_t}; 56 | use std::convert::{TryFrom, TryInto}; 57 | use std::time::{Duration, SystemTime, SystemTimeError, UNIX_EPOCH}; 58 | 59 | use enums::*; 60 | use util::*; 61 | 62 | pub use util::EventCodeIterator; 63 | pub use util::EventTypeIterator; 64 | pub use util::InputPropIterator; 65 | 66 | use evdev_sys as raw; 67 | 68 | #[doc(inline)] 69 | pub use device::Device; 70 | #[doc(inline)] 71 | pub use device::DeviceWrapper; 72 | #[doc(inline)] 73 | pub use device::Enable; 74 | #[doc(inline)] 75 | pub use device::EnableCodeData; 76 | #[doc(inline)] 77 | pub use device::UninitDevice; 78 | #[doc(inline)] 79 | pub use uinput::UInputDevice; 80 | 81 | #[cfg(feature = "serde")] 82 | use serde::{Deserialize, Serialize}; 83 | 84 | pub enum GrabMode { 85 | /// Grab the device if not currently grabbed 86 | Grab = raw::LIBEVDEV_GRAB as isize, 87 | /// Ungrab the device if currently grabbed 88 | Ungrab = raw::LIBEVDEV_UNGRAB as isize, 89 | } 90 | 91 | bitflags! { 92 | pub struct ReadFlag: u32 { 93 | /// Process data in sync mode 94 | const SYNC = 1; 95 | /// Process data in normal mode 96 | const NORMAL = 2; 97 | /// Pretend the next event is a SYN_DROPPED and require the 98 | /// caller to sync 99 | const FORCE_SYNC = 4; 100 | /// The fd is not in O_NONBLOCK and a read may block 101 | const BLOCKING = 8; 102 | } 103 | } 104 | 105 | #[derive(PartialEq)] 106 | pub enum ReadStatus { 107 | /// `next_event` has finished without an error and an event is available 108 | /// for processing. 109 | Success = raw::LIBEVDEV_READ_STATUS_SUCCESS as isize, 110 | /// Depending on the `next_event` read flag: 111 | /// libevdev received a SYN_DROPPED from the device, and the caller should 112 | /// now resync the device, or, an event has been read in sync mode. 113 | Sync = raw::LIBEVDEV_READ_STATUS_SYNC as isize, 114 | } 115 | 116 | pub enum LedState { 117 | /// Turn the LED on 118 | On = raw::LIBEVDEV_LED_ON as isize, 119 | /// Turn the LED off 120 | Off = raw::LIBEVDEV_LED_OFF as isize, 121 | } 122 | 123 | #[derive(Debug)] 124 | pub struct DeviceId { 125 | pub bustype: BusType, 126 | pub vendor: u16, 127 | pub product: u16, 128 | pub version: u16, 129 | } 130 | 131 | #[derive(Clone, Copy, Debug)] 132 | /// used by EVIOCGABS/EVIOCSABS ioctls 133 | pub struct AbsInfo { 134 | /// latest reported value for the axis 135 | pub value: i32, 136 | /// specifies minimum value for the axis 137 | pub minimum: i32, 138 | /// specifies maximum value for the axis 139 | pub maximum: i32, 140 | /// specifies fuzz value that is used to filter noise from 141 | /// the event stream 142 | pub fuzz: i32, 143 | /// values that are within this value will be discarded by 144 | /// joydev interface and reported as 0 instead 145 | pub flat: i32, 146 | /// specifies resolution for the values reported for 147 | /// the axis 148 | pub resolution: i32, 149 | } 150 | 151 | impl AbsInfo { 152 | pub const fn from_raw(absinfo: libc::input_absinfo) -> AbsInfo { 153 | AbsInfo { 154 | value: absinfo.value, 155 | minimum: absinfo.minimum, 156 | maximum: absinfo.maximum, 157 | fuzz: absinfo.fuzz, 158 | flat: absinfo.flat, 159 | resolution: absinfo.resolution, 160 | } 161 | } 162 | 163 | pub const fn as_raw(&self) -> libc::input_absinfo { 164 | libc::input_absinfo { 165 | value: self.value, 166 | minimum: self.minimum, 167 | maximum: self.maximum, 168 | fuzz: self.fuzz, 169 | flat: self.flat, 170 | resolution: self.resolution, 171 | } 172 | } 173 | } 174 | 175 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 176 | #[derive(Copy, Clone, Eq, Hash, PartialOrd, Ord, Debug, PartialEq)] 177 | pub struct TimeVal { 178 | pub tv_sec: time_t, 179 | pub tv_usec: suseconds_t, 180 | } 181 | 182 | impl TryFrom for TimeVal { 183 | type Error = SystemTimeError; 184 | fn try_from(system_time: SystemTime) -> Result { 185 | let d = system_time.duration_since(UNIX_EPOCH)?; 186 | Ok(TimeVal { 187 | tv_sec: d.as_secs() as time_t, 188 | tv_usec: d.subsec_micros() as suseconds_t, 189 | }) 190 | } 191 | } 192 | 193 | impl TryInto for TimeVal { 194 | type Error = (); 195 | /// Fails if TimeVal.tv_usec is >= 10^6 or if the TimeVal is outside 196 | /// the range of SystemTime 197 | fn try_into(self) -> Result { 198 | let secs = self.tv_sec.try_into().map_err(|_| ())?; 199 | let nanos = (self.tv_usec * 1000).try_into().map_err(|_| ())?; 200 | let duration = Duration::new(secs, nanos); 201 | UNIX_EPOCH.checked_add(duration).ok_or(()) 202 | } 203 | } 204 | 205 | impl TimeVal { 206 | pub const fn new(tv_sec: time_t, tv_usec: suseconds_t) -> TimeVal { 207 | const MICROS_PER_SEC: suseconds_t = 1_000_000; 208 | TimeVal { 209 | tv_sec: tv_sec + tv_usec / MICROS_PER_SEC, 210 | tv_usec: tv_usec % MICROS_PER_SEC, 211 | } 212 | } 213 | 214 | pub const fn from_raw(timeval: &libc::timeval) -> TimeVal { 215 | TimeVal { 216 | tv_sec: timeval.tv_sec, 217 | tv_usec: timeval.tv_usec, 218 | } 219 | } 220 | 221 | pub const fn as_raw(&self) -> libc::timeval { 222 | libc::timeval { 223 | tv_sec: self.tv_sec, 224 | tv_usec: self.tv_usec, 225 | } 226 | } 227 | } 228 | 229 | /// The event structure itself 230 | #[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))] 231 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] 232 | pub struct InputEvent { 233 | /// The time at which event occured 234 | pub time: TimeVal, 235 | pub event_code: EventCode, 236 | pub value: i32, 237 | } 238 | 239 | impl InputEvent { 240 | pub const fn new(timeval: &TimeVal, code: &EventCode, value: i32) -> InputEvent { 241 | InputEvent { 242 | time: *timeval, 243 | event_code: *code, 244 | value, 245 | } 246 | } 247 | 248 | pub fn event_type(&self) -> Option { 249 | int_to_event_type(event_code_to_int(&self.event_code).0) 250 | } 251 | 252 | pub fn from_raw(event: &libc::input_event) -> InputEvent { 253 | let ev_type = event.type_ as u32; 254 | let event_code = int_to_event_code(ev_type, event.code as u32); 255 | InputEvent { 256 | time: TimeVal::from_raw(&event.time), 257 | event_code, 258 | value: event.value, 259 | } 260 | } 261 | 262 | pub fn as_raw(&self) -> libc::input_event { 263 | let (ev_type, ev_code) = event_code_to_int(&self.event_code); 264 | libc::input_event { 265 | time: self.time.as_raw(), 266 | type_: ev_type as u16, 267 | code: ev_code as u16, 268 | value: self.value, 269 | } 270 | } 271 | 272 | pub fn is_type(&self, ev_type: &EventType) -> bool { 273 | unsafe { raw::libevdev_event_is_type(&self.as_raw(), *ev_type as c_uint) == 1 } 274 | } 275 | 276 | pub fn is_code(&self, code: &EventCode) -> bool { 277 | let (ev_type, ev_code) = event_code_to_int(code); 278 | 279 | unsafe { raw::libevdev_event_is_code(&self.as_raw(), ev_type, ev_code) == 1 } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/logging.rs: -------------------------------------------------------------------------------- 1 | use evdev_sys as raw; 2 | 3 | pub enum LogPriority { 4 | /// critical errors and application bugs 5 | Error = raw::LIBEVDEV_LOG_ERROR as isize, 6 | /// informational messages 7 | Info = raw::LIBEVDEV_LOG_INFO as isize, 8 | /// debug information 9 | Debug = raw::LIBEVDEV_LOG_DEBUG as isize, 10 | } 11 | 12 | /// Define the minimum level to be printed to the log handler. 13 | /// Messages higher than this level are printed, others are discarded. This 14 | /// is a global setting and applies to any future logging messages. 15 | pub fn set_log_priority(priority: LogPriority) { 16 | unsafe { 17 | raw::libevdev_set_log_priority(priority as i32); 18 | } 19 | } 20 | 21 | /// Return the current log priority level. Messages higher than this level 22 | /// are printed, others are discarded. This is a global setting. 23 | pub fn get_log_priority() -> LogPriority { 24 | unsafe { 25 | let priority = raw::libevdev_get_log_priority(); 26 | match priority { 27 | raw::LIBEVDEV_LOG_ERROR => LogPriority::Error, 28 | raw::LIBEVDEV_LOG_INFO => LogPriority::Info, 29 | raw::LIBEVDEV_LOG_DEBUG => LogPriority::Debug, 30 | c => panic!("unknown log priority: {}", c), 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! string_getter { 2 | ( $( #[$doc:meta], $func_name:ident, $c_func: ident ),* ) => { 3 | $( 4 | #[$doc] 5 | fn $func_name (&self) -> Option<&str> { 6 | unsafe { 7 | ptr_to_str(raw::$c_func(self.raw())) 8 | } 9 | } 10 | )* 11 | }; 12 | } 13 | 14 | macro_rules! string_setter { 15 | ( $( $func_name:ident, $c_func: ident ),* ) => { 16 | $( 17 | fn $func_name (&self, field: &str) { 18 | let field = CString::new(field).unwrap(); 19 | unsafe { 20 | raw::$c_func(self.raw(), field.as_ptr()) 21 | } 22 | } 23 | )* 24 | }; 25 | } 26 | 27 | macro_rules! product_getter { 28 | ( $( $func_name:ident, $c_func: ident ),* ) => { 29 | $( 30 | fn $func_name (&self) -> u16 { 31 | unsafe { 32 | raw::$c_func(self.raw()) as u16 33 | } 34 | } 35 | )* 36 | }; 37 | } 38 | 39 | macro_rules! product_setter { 40 | ( $( $func_name:ident, $c_func: ident ),* ) => { 41 | $( 42 | fn $func_name (&self, field: u16) { 43 | unsafe { 44 | raw::$c_func(self.raw(), field as c_int); 45 | } 46 | } 47 | )* 48 | }; 49 | } 50 | 51 | macro_rules! abs_getter { 52 | ( $( $func_name:ident, $c_func: ident ),* ) => { 53 | $( 54 | fn $func_name (&self, 55 | code: u32) -> std::io::Result { 56 | let result = unsafe { 57 | raw::$c_func(self.raw(), code as c_uint) as i32 58 | }; 59 | 60 | match result { 61 | 0 => Err(std::io::Error::from_raw_os_error(0)), 62 | k => Ok(k) 63 | } 64 | } 65 | )* 66 | }; 67 | } 68 | 69 | macro_rules! abs_setter { 70 | ( $( $func_name:ident, $c_func: ident ),* ) => { 71 | $( 72 | fn $func_name (&self, 73 | code: u32, 74 | val: i32) { 75 | unsafe { 76 | raw::$c_func(self.raw(), code as c_uint, val as c_int); 77 | } 78 | } 79 | )* 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/uinput.rs: -------------------------------------------------------------------------------- 1 | use crate::{device::DeviceWrapper, InputEvent}; 2 | use libc::c_int; 3 | use std::io; 4 | use std::os::unix::io::RawFd; 5 | 6 | use crate::util::*; 7 | 8 | use evdev_sys as raw; 9 | 10 | /// Opaque struct representing an evdev uinput device 11 | pub struct UInputDevice { 12 | raw: *mut raw::libevdev_uinput, 13 | } 14 | 15 | unsafe impl Sync for UInputDevice {} 16 | unsafe impl Send for UInputDevice {} 17 | 18 | impl UInputDevice { 19 | fn raw(&self) -> *mut raw::libevdev_uinput { 20 | self.raw 21 | } 22 | 23 | /// Create a uinput device based on the given libevdev device. 24 | /// 25 | /// The uinput device will be an exact copy of the libevdev device, minus 26 | /// the bits that uinput doesn't allow to be set. 27 | pub fn create_from_device(device: &T) -> io::Result { 28 | let mut libevdev_uinput = std::ptr::null_mut(); 29 | let result = unsafe { 30 | raw::libevdev_uinput_create_from_device( 31 | device.raw(), 32 | raw::LIBEVDEV_UINPUT_OPEN_MANAGED, 33 | &mut libevdev_uinput, 34 | ) 35 | }; 36 | 37 | match result { 38 | 0 => Ok(UInputDevice { 39 | raw: libevdev_uinput, 40 | }), 41 | error => Err(io::Error::from_raw_os_error(-error)), 42 | } 43 | } 44 | 45 | ///Return the device node representing this uinput device. 46 | /// 47 | /// This relies on `libevdev_uinput_get_syspath()` to provide a valid syspath. 48 | pub fn devnode(&self) -> Option<&str> { 49 | unsafe { ptr_to_str(raw::libevdev_uinput_get_devnode(self.raw())) } 50 | } 51 | 52 | ///Return the syspath representing this uinput device. 53 | /// 54 | /// If the UI_GET_SYSNAME ioctl not available, libevdev makes an educated 55 | /// guess. The UI_GET_SYSNAME ioctl is available since Linux 3.15. 56 | /// 57 | /// The syspath returned is the one of the input node itself 58 | /// (e.g. /sys/devices/virtual/input/input123), not the syspath of the 59 | /// device node returned with libevdev_uinput_get_devnode(). 60 | pub fn syspath(&self) -> Option<&str> { 61 | unsafe { ptr_to_str(raw::libevdev_uinput_get_syspath(self.raw())) } 62 | } 63 | 64 | /// Return the file descriptor used to create this uinput device. 65 | /// 66 | /// This is the fd pointing to /dev/uinput. This file descriptor may be used 67 | /// to write events that are emitted by the uinput device. Closing this file 68 | /// descriptor will destroy the uinput device. 69 | pub fn as_fd(&self) -> Option { 70 | match unsafe { raw::libevdev_uinput_get_fd(self.raw()) } { 71 | 0 => None, 72 | result => Some(result), 73 | } 74 | } 75 | 76 | #[deprecated( 77 | since = "0.5.0", 78 | note = "Prefer `as_fd`. Some function names were changed so they 79 | more closely match their type signature. See issue 42 for discussion 80 | https://github.com/ndesh26/evdev-rs/issues/42" 81 | )] 82 | pub fn fd(&self) -> Option { 83 | self.as_fd() 84 | } 85 | 86 | /// Post an event through the uinput device. 87 | /// 88 | /// It is the caller's responsibility that any event sequence is terminated 89 | /// with an EV_SYN/SYN_REPORT/0 event. Otherwise, listeners on the device 90 | /// node will not see the events until the next EV_SYN event is posted. 91 | pub fn write_event(&self, event: &InputEvent) -> io::Result<()> { 92 | let (ev_type, ev_code) = event_code_to_int(&event.event_code); 93 | let ev_value = event.value as c_int; 94 | 95 | let result = unsafe { 96 | raw::libevdev_uinput_write_event(self.raw(), ev_type, ev_code, ev_value) 97 | }; 98 | 99 | match result { 100 | 0 => Ok(()), 101 | error => Err(io::Error::from_raw_os_error(-error)), 102 | } 103 | } 104 | } 105 | 106 | impl Drop for UInputDevice { 107 | fn drop(&mut self) { 108 | unsafe { 109 | raw::libevdev_uinput_destroy(self.raw()); 110 | } 111 | } 112 | } 113 | 114 | impl std::fmt::Debug for UInputDevice { 115 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 116 | f.debug_struct("UInputDevice") 117 | .field("devnode", &self.devnode()) 118 | .finish() 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use crate::enums::*; 2 | use libc::{c_char, c_uint}; 3 | use log::warn; 4 | use std::ffi::{CStr, CString}; 5 | use std::fmt; 6 | 7 | use evdev_sys as raw; 8 | 9 | pub(crate) unsafe fn ptr_to_str(ptr: *const c_char) -> Option<&'static str> { 10 | let slice = CStr::from_ptr(ptr.as_ref()?); 11 | let buf = slice.to_bytes(); 12 | std::str::from_utf8(buf).ok() 13 | } 14 | 15 | pub struct EventTypeIterator { 16 | current: EventType, 17 | } 18 | 19 | pub struct EventCodeIterator { 20 | current: EventCode, 21 | } 22 | 23 | pub struct InputPropIterator { 24 | current: InputProp, 25 | } 26 | 27 | impl EventTypeIterator { 28 | pub fn new() -> Self { 29 | EventTypeIterator { 30 | current: EventType::EV_SYN, 31 | } 32 | } 33 | } 34 | 35 | impl EventCodeIterator { 36 | pub fn new(event_type: &EventType) -> Self { 37 | let event_code = match *event_type { 38 | EventType::EV_SYN => EventCode::EV_SYN(EV_SYN::SYN_REPORT), 39 | EventType::EV_KEY => EventCode::EV_KEY(EV_KEY::KEY_RESERVED), 40 | EventType::EV_REL => EventCode::EV_REL(EV_REL::REL_X), 41 | EventType::EV_ABS => EventCode::EV_ABS(EV_ABS::ABS_X), 42 | EventType::EV_MSC => EventCode::EV_MSC(EV_MSC::MSC_SERIAL), 43 | EventType::EV_SW => EventCode::EV_SW(EV_SW::SW_LID), 44 | EventType::EV_LED => EventCode::EV_LED(EV_LED::LED_NUML), 45 | EventType::EV_SND => EventCode::EV_SND(EV_SND::SND_CLICK), 46 | EventType::EV_REP => EventCode::EV_REP(EV_REP::REP_DELAY), 47 | EventType::EV_FF => EventCode::EV_FF(EV_FF::FF_STATUS_STOPPED), 48 | EventType::EV_FF_STATUS => EventCode::EV_FF_STATUS(EV_FF::FF_STATUS_STOPPED), 49 | _ => EventCode::EV_MAX, 50 | }; 51 | 52 | EventCodeIterator { 53 | current: event_code, 54 | } 55 | } 56 | } 57 | 58 | impl InputPropIterator { 59 | pub fn new() -> Self { 60 | InputPropIterator { 61 | current: InputProp::INPUT_PROP_POINTER, 62 | } 63 | } 64 | } 65 | 66 | pub fn event_code_to_int(event_code: &EventCode) -> (c_uint, c_uint) { 67 | match *event_code { 68 | EventCode::EV_SYN(code) => (EventType::EV_SYN as c_uint, code as c_uint), 69 | EventCode::EV_KEY(code) => (EventType::EV_KEY as c_uint, code as c_uint), 70 | EventCode::EV_REL(code) => (EventType::EV_REL as c_uint, code as c_uint), 71 | EventCode::EV_ABS(code) => (EventType::EV_ABS as c_uint, code as c_uint), 72 | EventCode::EV_MSC(code) => (EventType::EV_MSC as c_uint, code as c_uint), 73 | EventCode::EV_SW(code) => (EventType::EV_SW as c_uint, code as c_uint), 74 | EventCode::EV_LED(code) => (EventType::EV_LED as c_uint, code as c_uint), 75 | EventCode::EV_SND(code) => (EventType::EV_SND as c_uint, code as c_uint), 76 | EventCode::EV_REP(code) => (EventType::EV_REP as c_uint, code as c_uint), 77 | EventCode::EV_FF(code) => (EventType::EV_FF as c_uint, code as c_uint), 78 | EventCode::EV_FF_STATUS(code) => { 79 | (EventType::EV_FF_STATUS as c_uint, code as c_uint) 80 | } 81 | EventCode::EV_UNK { 82 | event_type, 83 | event_code, 84 | } => (event_type as c_uint, event_code as c_uint), 85 | _ => { 86 | warn!("Event code not found"); 87 | (0, 0) 88 | } 89 | } 90 | } 91 | 92 | pub fn int_to_event_code(event_type: c_uint, event_code: c_uint) -> EventCode { 93 | let ev_type: EventType = int_to_event_type(event_type as u32).unwrap(); 94 | let code = event_code as u32; 95 | 96 | let ev_code = match ev_type { 97 | EventType::EV_SYN => int_to_ev_syn(code).map(EventCode::EV_SYN), 98 | EventType::EV_KEY => int_to_ev_key(code).map(EventCode::EV_KEY), 99 | EventType::EV_ABS => int_to_ev_abs(code).map(EventCode::EV_ABS), 100 | EventType::EV_REL => int_to_ev_rel(code).map(EventCode::EV_REL), 101 | EventType::EV_MSC => int_to_ev_msc(code).map(EventCode::EV_MSC), 102 | EventType::EV_SW => int_to_ev_sw(code).map(EventCode::EV_SW), 103 | EventType::EV_LED => int_to_ev_led(code).map(EventCode::EV_LED), 104 | EventType::EV_SND => int_to_ev_snd(code).map(EventCode::EV_SND), 105 | EventType::EV_REP => int_to_ev_rep(code).map(EventCode::EV_REP), 106 | EventType::EV_FF => int_to_ev_ff(code).map(EventCode::EV_FF), 107 | EventType::EV_PWR => Some(EventCode::EV_PWR), 108 | EventType::EV_FF_STATUS => int_to_ev_ff(code).map(EventCode::EV_FF_STATUS), 109 | EventType::EV_UNK => None, 110 | EventType::EV_MAX => Some(EventCode::EV_MAX), 111 | }; 112 | 113 | ev_code.unwrap_or(EventCode::EV_UNK { 114 | event_type, 115 | event_code, 116 | }) 117 | } 118 | 119 | impl fmt::Display for EventType { 120 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 121 | write!( 122 | f, 123 | "{}", 124 | unsafe { ptr_to_str(raw::libevdev_event_type_get_name(*self as c_uint)) } 125 | .unwrap_or("") 126 | ) 127 | } 128 | } 129 | 130 | impl fmt::Display for EventCode { 131 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 132 | let (ev_type, ev_code) = event_code_to_int(self); 133 | write!( 134 | f, 135 | "{}", 136 | unsafe { ptr_to_str(raw::libevdev_event_code_get_name(ev_type, ev_code)) } 137 | .unwrap_or("") 138 | ) 139 | } 140 | } 141 | 142 | impl fmt::Display for InputProp { 143 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 144 | write!( 145 | f, 146 | "{}", 147 | unsafe { ptr_to_str(raw::libevdev_property_get_name(*self as c_uint)) } 148 | .unwrap_or("") 149 | ) 150 | } 151 | } 152 | 153 | impl EventType { 154 | pub fn iter(&self) -> EventTypeIterator { 155 | EventTypeIterator { current: *self } 156 | } 157 | 158 | /// The given type constant for the passed name or Errno if not found. 159 | pub fn from_str(name: &str) -> Option { 160 | let name = CString::new(name).unwrap(); 161 | let result = unsafe { raw::libevdev_event_type_from_name(name.as_ptr()) }; 162 | 163 | match result { 164 | -1 => None, 165 | k => int_to_event_type(k as u32), 166 | } 167 | } 168 | 169 | /// The max value defined for the given event type, e.g. ABS_MAX for a type 170 | /// of EV_ABS, or Errno for an invalid type. 171 | pub fn get_max(ev_type: &EventType) -> Option { 172 | let result = unsafe { raw::libevdev_event_type_get_max(*ev_type as c_uint) }; 173 | 174 | match result { 175 | k if k < 0 => None, 176 | k => Some(k as u32), 177 | } 178 | } 179 | } 180 | 181 | impl EventCode { 182 | pub fn iter(&self) -> EventCodeIterator { 183 | EventCodeIterator { current: *self } 184 | } 185 | 186 | /// Look up an event code by its type and name. Event codes start with a fixed 187 | /// prefix followed by their name (eg., "ABS_X"). The prefix must be included in 188 | /// the name. It returns the constant assigned to the event code or Errno if not 189 | /// found. 190 | pub fn from_str(ev_type: &EventType, name: &str) -> Option { 191 | let name = CString::new(name).unwrap(); 192 | let result = unsafe { 193 | raw::libevdev_event_code_from_name(*ev_type as c_uint, name.as_ptr()) 194 | }; 195 | 196 | match result { 197 | -1 => None, 198 | k => Some(int_to_event_code(*ev_type as u32, k as u32)), 199 | } 200 | } 201 | } 202 | 203 | impl InputProp { 204 | pub fn iter(&self) -> InputPropIterator { 205 | InputPropIterator { current: *self } 206 | } 207 | 208 | /// Look up an input property by its name. Properties start with the fixed 209 | /// prefix "INPUT_PROP_" followed by their name (eg., "INPUT_PROP_POINTER"). 210 | /// The prefix must be included in the name. It returns the constant assigned 211 | /// to the property or Errno if not found. 212 | pub fn from_str(name: &str) -> Option { 213 | let name = CString::new(name).unwrap(); 214 | let result = unsafe { raw::libevdev_property_from_name(name.as_ptr()) }; 215 | 216 | match result { 217 | -1 => None, 218 | k => int_to_input_prop(k as u32), 219 | } 220 | } 221 | } 222 | 223 | // Iterator trait for the enum iterators 224 | impl Iterator for EventTypeIterator { 225 | type Item = EventType; 226 | 227 | fn next(&mut self) -> Option { 228 | match self.current { 229 | EventType::EV_MAX => None, 230 | _ => { 231 | let mut raw_code = (self.current as u32) + 1; 232 | loop { 233 | match int_to_event_type(raw_code) { 234 | // TODO: Find a way to iterate over Unknown types 235 | Some(EventType::EV_UNK) => raw_code += 1, 236 | Some(x) => { 237 | let code = self.current; 238 | self.current = x; 239 | return Some(code); 240 | } 241 | None => raw_code += 1, 242 | } 243 | } 244 | } 245 | } 246 | } 247 | } 248 | 249 | impl Iterator for EventCodeIterator { 250 | type Item = EventCode; 251 | 252 | fn next(&mut self) -> Option { 253 | match self.current { 254 | EventCode::EV_SYN(code) => match code { 255 | EV_SYN::SYN_MAX => None, 256 | _ => { 257 | let mut raw_code = (code as u32) + 1; 258 | loop { 259 | match int_to_ev_syn(raw_code) { 260 | Some(x) => { 261 | let ev_code = self.current; 262 | self.current = EventCode::EV_SYN(x); 263 | return Some(ev_code); 264 | } 265 | None => raw_code += 1, 266 | } 267 | } 268 | } 269 | }, 270 | EventCode::EV_KEY(code) => match code { 271 | EV_KEY::KEY_MAX => None, 272 | _ => { 273 | let mut raw_code = (code as u32) + 1; 274 | loop { 275 | match int_to_ev_key(raw_code) { 276 | Some(x) => { 277 | let ev_code = self.current; 278 | self.current = EventCode::EV_KEY(x); 279 | return Some(ev_code); 280 | } 281 | None => raw_code += 1, 282 | } 283 | } 284 | } 285 | }, 286 | EventCode::EV_REL(code) => match code { 287 | EV_REL::REL_MAX => None, 288 | _ => { 289 | let mut raw_code = (code as u32) + 1; 290 | loop { 291 | match int_to_ev_rel(raw_code) { 292 | Some(x) => { 293 | let ev_code = self.current; 294 | self.current = EventCode::EV_REL(x); 295 | return Some(ev_code); 296 | } 297 | None => raw_code += 1, 298 | } 299 | } 300 | } 301 | }, 302 | EventCode::EV_ABS(code) => match code { 303 | EV_ABS::ABS_MAX => None, 304 | _ => { 305 | let mut raw_code = (code as u32) + 1; 306 | loop { 307 | match int_to_ev_abs(raw_code) { 308 | Some(x) => { 309 | let ev_code = self.current; 310 | self.current = EventCode::EV_ABS(x); 311 | return Some(ev_code); 312 | } 313 | None => raw_code += 1, 314 | } 315 | } 316 | } 317 | }, 318 | EventCode::EV_MSC(code) => match code { 319 | EV_MSC::MSC_MAX => None, 320 | _ => { 321 | let mut raw_code = (code as u32) + 1; 322 | loop { 323 | match int_to_ev_msc(raw_code) { 324 | Some(x) => { 325 | let ev_code = self.current; 326 | self.current = EventCode::EV_MSC(x); 327 | return Some(ev_code); 328 | } 329 | None => raw_code += 1, 330 | } 331 | } 332 | } 333 | }, 334 | EventCode::EV_SW(code) => match code { 335 | EV_SW::SW_MAX => None, 336 | _ => { 337 | let mut raw_code = (code as u32) + 1; 338 | loop { 339 | match int_to_ev_sw(raw_code) { 340 | Some(x) => { 341 | let ev_code = self.current; 342 | self.current = EventCode::EV_SW(x); 343 | return Some(ev_code); 344 | } 345 | None => raw_code += 1, 346 | } 347 | } 348 | } 349 | }, 350 | EventCode::EV_LED(code) => match code { 351 | EV_LED::LED_MAX => None, 352 | _ => { 353 | let mut raw_code = (code as u32) + 1; 354 | loop { 355 | match int_to_ev_led(raw_code) { 356 | Some(x) => { 357 | let ev_code = self.current; 358 | self.current = EventCode::EV_LED(x); 359 | return Some(ev_code); 360 | } 361 | None => raw_code += 1, 362 | } 363 | } 364 | } 365 | }, 366 | EventCode::EV_SND(code) => match code { 367 | EV_SND::SND_MAX => None, 368 | _ => { 369 | let mut raw_code = (code as u32) + 1; 370 | loop { 371 | match int_to_ev_snd(raw_code) { 372 | Some(x) => { 373 | let ev_code = self.current; 374 | self.current = EventCode::EV_SND(x); 375 | return Some(ev_code); 376 | } 377 | None => raw_code += 1, 378 | } 379 | } 380 | } 381 | }, 382 | EventCode::EV_REP(code) => match code { 383 | EV_REP::REP_MAX => None, 384 | _ => { 385 | let mut raw_code = (code as u32) + 1; 386 | loop { 387 | match int_to_ev_rep(raw_code) { 388 | Some(x) => { 389 | let ev_code = self.current; 390 | self.current = EventCode::EV_REP(x); 391 | return Some(ev_code); 392 | } 393 | None => raw_code += 1, 394 | } 395 | } 396 | } 397 | }, 398 | EventCode::EV_FF(code) => match code { 399 | EV_FF::FF_MAX => None, 400 | _ => { 401 | let mut raw_code = (code as u32) + 1; 402 | loop { 403 | match int_to_ev_ff(raw_code) { 404 | Some(x) => { 405 | let ev_code = self.current; 406 | self.current = EventCode::EV_FF(x); 407 | return Some(ev_code); 408 | } 409 | None => raw_code += 1, 410 | } 411 | } 412 | } 413 | }, 414 | _ => None, 415 | } 416 | } 417 | } 418 | 419 | impl Iterator for InputPropIterator { 420 | type Item = InputProp; 421 | 422 | fn next(&mut self) -> Option { 423 | match self.current { 424 | InputProp::INPUT_PROP_MAX => None, 425 | _ => { 426 | let mut raw_enum = (self.current as u32) + 1; 427 | loop { 428 | match int_to_input_prop(raw_enum) { 429 | Some(x) => { 430 | let prop = self.current; 431 | self.current = x; 432 | return Some(prop); 433 | } 434 | None => raw_enum += 1, 435 | } 436 | } 437 | } 438 | } 439 | } 440 | } 441 | -------------------------------------------------------------------------------- /tests/all.rs: -------------------------------------------------------------------------------- 1 | use evdev_rs::enums::*; 2 | use evdev_rs::*; 3 | use std::fs::File; 4 | use std::os::unix::io::AsRawFd; 5 | 6 | #[test] 7 | fn context_create() { 8 | assert!(UninitDevice::new().is_some()); 9 | } 10 | 11 | #[test] 12 | fn context_create_with_file() { 13 | let f = File::open("/dev/input/event0").unwrap(); 14 | let _d = Device::new_from_file(f).unwrap(); 15 | } 16 | 17 | #[test] 18 | fn context_create_with_path() { 19 | let _d = Device::new_from_path("/dev/input/event0").unwrap(); 20 | } 21 | 22 | #[test] 23 | fn context_set_file() { 24 | let d = UninitDevice::new().unwrap(); 25 | let f = File::open("/dev/input/event0").unwrap(); 26 | let _device = d.set_file(f).unwrap(); 27 | } 28 | 29 | #[test] 30 | fn context_change_file() { 31 | let d = UninitDevice::new().unwrap(); 32 | let f1 = File::open("/dev/input/event0").unwrap(); 33 | let f2 = File::open("/dev/input/event0").unwrap(); 34 | let f2_fd = f2.as_raw_fd(); 35 | 36 | let mut d = d.set_file(f1).unwrap(); 37 | d.change_file(f2).unwrap(); 38 | 39 | assert_eq!(d.file().as_raw_fd(), f2_fd); 40 | } 41 | 42 | #[test] 43 | fn context_grab() { 44 | let mut d = Device::new_from_path("/dev/input/event0").unwrap(); 45 | d.grab(GrabMode::Grab).unwrap(); 46 | d.grab(GrabMode::Ungrab).unwrap(); 47 | } 48 | 49 | #[test] 50 | fn device_get_name() { 51 | let d = UninitDevice::new().unwrap(); 52 | 53 | d.set_name("hello"); 54 | assert_eq!(d.name().unwrap(), "hello"); 55 | } 56 | 57 | #[test] 58 | fn device_get_uniq() { 59 | let d = UninitDevice::new().unwrap(); 60 | 61 | d.set_uniq("test"); 62 | assert_eq!(d.uniq().unwrap(), "test"); 63 | } 64 | 65 | #[test] 66 | fn device_get_phys() { 67 | let d = UninitDevice::new().unwrap(); 68 | 69 | d.set_phys("test"); 70 | assert_eq!(d.phys().unwrap(), "test"); 71 | } 72 | 73 | #[test] 74 | fn device_get_product_id() { 75 | let d = UninitDevice::new().unwrap(); 76 | 77 | d.set_product_id(5); 78 | assert_eq!(d.product_id(), 5); 79 | } 80 | 81 | #[test] 82 | fn device_get_vendor_id() { 83 | let d = UninitDevice::new().unwrap(); 84 | 85 | d.set_vendor_id(5); 86 | assert_eq!(d.vendor_id(), 5); 87 | } 88 | 89 | #[test] 90 | fn device_get_bustype() { 91 | let d = UninitDevice::new().unwrap(); 92 | 93 | d.set_bustype(5); 94 | assert_eq!(d.bustype(), 5); 95 | } 96 | 97 | #[test] 98 | fn device_get_version() { 99 | let d = UninitDevice::new().unwrap(); 100 | 101 | d.set_version(5); 102 | assert_eq!(d.version(), 5); 103 | } 104 | 105 | #[test] 106 | fn device_get_absinfo() { 107 | let d = Device::new_from_path("/dev/input/event0").unwrap(); 108 | for code in EventCode::EV_SYN(EV_SYN::SYN_REPORT).iter() { 109 | let absinfo: Option = d.abs_info(&code); 110 | 111 | match absinfo { 112 | None => .., 113 | Some(_a) => .., 114 | }; 115 | } 116 | } 117 | 118 | #[test] 119 | fn device_has_property() { 120 | let d = Device::new_from_path("/dev/input/event0").unwrap(); 121 | for prop in InputProp::INPUT_PROP_POINTER.iter() { 122 | if d.has_property(&prop) { 123 | panic!("Prop {} is set, shouldn't be", prop); 124 | } 125 | } 126 | } 127 | 128 | #[test] 129 | fn device_enable_disable() { 130 | #[cfg(feature = "libevdev-1-10")] 131 | let prop = InputProp::INPUT_PROP_POINTER; 132 | let ev_type = EventType::EV_KEY; 133 | let code = EventCode::EV_KEY(EV_KEY::KEY_LEFTSHIFT); 134 | let d = UninitDevice::new().unwrap(); 135 | #[cfg(feature = "libevdev-1-10")] 136 | assert!(!d.has(prop)); 137 | assert!(!d.has(ev_type)); 138 | assert!(!d.has(code)); 139 | #[cfg(feature = "libevdev-1-10")] 140 | d.enable(prop).unwrap(); 141 | d.enable(ev_type).unwrap(); 142 | d.enable(code).unwrap(); 143 | #[cfg(feature = "libevdev-1-10")] 144 | assert!(d.has(prop)); 145 | assert!(d.has(ev_type)); 146 | assert!(d.has(code)); 147 | #[cfg(feature = "libevdev-1-10")] 148 | d.disable(prop).unwrap(); 149 | d.disable(ev_type).unwrap(); 150 | d.disable(code).unwrap(); 151 | #[cfg(feature = "libevdev-1-10")] 152 | assert!(!d.has(prop)); 153 | assert!(!d.has(ev_type)); 154 | assert!(!d.has(code)); 155 | } 156 | 157 | #[test] 158 | fn device_has_syn() { 159 | let d = UninitDevice::new().unwrap(); 160 | let f = File::open("/dev/input/event0").unwrap(); 161 | 162 | let d = d.set_file(f).unwrap(); 163 | 164 | assert!(d.has(EventType::EV_SYN)); // EV_SYN 165 | assert!(d.has(EventCode::EV_SYN(EV_SYN::SYN_REPORT))); // SYN_REPORT 166 | } 167 | 168 | #[test] 169 | fn device_get_value() { 170 | let d = UninitDevice::new().unwrap(); 171 | let f = File::open("/dev/input/event0").unwrap(); 172 | 173 | let d = d.set_file(f).unwrap(); 174 | 175 | let v2 = d.event_value(&EventCode::EV_SYN(EV_SYN::SYN_REPORT)); // SYN_REPORT 176 | assert_eq!(v2, Some(0)); 177 | } 178 | 179 | #[test] 180 | fn check_event_name() { 181 | assert_eq!("EV_ABS", EventType::EV_ABS.to_string()); 182 | } 183 | 184 | #[test] 185 | fn test_timeval() { 186 | assert_eq!(TimeVal::new(1, 1_000_000), TimeVal::new(2, 0)); 187 | assert_eq!(TimeVal::new(-1, -1_000_000), TimeVal::new(-2, 0)); 188 | assert_eq!(TimeVal::new(1, -1_000_000), TimeVal::new(0, 0)); 189 | assert_eq!(TimeVal::new(-100, 1_000_000 * 100), TimeVal::new(0, 0)); 190 | } 191 | -------------------------------------------------------------------------------- /tools/make-enums.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eux 4 | 5 | HEADER_DIR=evdev-sys/libevdev/include/linux/linux 6 | 7 | ./tools/make-event-names.py $HEADER_DIR/input-event-codes.h $HEADER_DIR/input.h | head -n -1 > src/enums.rs 8 | -------------------------------------------------------------------------------- /tools/make-event-names.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Parses linux/input.h scanning for #define KEY_FOO 134 3 | # Prints Rust source header files that can be used for 4 | # mapping and lookup tables. 5 | # 6 | # The original version of this file is in libevdev 7 | # 8 | 9 | import re 10 | import sys 11 | 12 | 13 | class Bits(object): 14 | pass 15 | 16 | 17 | prefixes = [ 18 | "EV_", 19 | "REL_", 20 | "ABS_", 21 | "KEY_", 22 | "BTN_", 23 | "LED_", 24 | "SND_", 25 | "MSC_", 26 | "SW_", 27 | "FF_", 28 | "SYN_", 29 | "REP_", 30 | "INPUT_PROP_", 31 | "BUS_", 32 | ] 33 | 34 | prefix_additional = {"key": ["btn"]} 35 | 36 | blacklist = [ 37 | "EV_VERSION", 38 | "BTN_MISC", 39 | "BTN_MOUSE", 40 | "BTN_JOYSTICK", 41 | "BTN_GAMEPAD", 42 | "BTN_DIGI", 43 | "BTN_WHEEL", 44 | "BTN_TRIGGER_HAPPY", 45 | ] 46 | 47 | btn_additional = [ 48 | [0, "BTN_A"], 49 | [0, "BTN_B"], 50 | [0, "BTN_X"], 51 | [0, "BTN_Y"], 52 | ] 53 | 54 | event_names = [ 55 | "REL_", 56 | "ABS_", 57 | "KEY_", 58 | "BTN_", 59 | "LED_", 60 | "SND_", 61 | "MSC_", 62 | "SW_", 63 | "FF_", 64 | "SYN_", 65 | "REP_", 66 | ] 67 | 68 | fmt_blacklist = [ 69 | "EventType", 70 | "InputProp", 71 | ] 72 | 73 | 74 | def convert(name): 75 | s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) 76 | return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() 77 | 78 | 79 | def get_enum_name(prefix): 80 | if prefix == "ev": 81 | return "EventType" 82 | elif prefix == "input_prop": 83 | return "InputProp" 84 | elif prefix == "bus": 85 | return "BusType" 86 | else: 87 | return "EV_" + prefix.upper() 88 | 89 | 90 | def print_enums(bits, prefix): 91 | if not hasattr(bits, prefix): 92 | return 93 | 94 | enum_name = get_enum_name(prefix) 95 | associated_names = [] 96 | 97 | print("#[allow(non_camel_case_types)]") 98 | print('#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]') 99 | print("#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]") 100 | print("pub enum %s {" % enum_name) 101 | for val, names in list(getattr(bits, prefix).items()): 102 | # Note(ndesh): We use EV_MAX as proxy to write the UNKnown event 103 | if names[0] == "EV_MAX": 104 | print(" EV_UNK,") 105 | print(" %s = %s," % (names[0], val)) 106 | if len(names) > 1: 107 | associated_names.extend([(names[0], names[1:])]) 108 | if prefix == "key": 109 | for val, names in list(getattr(bits, "btn").items()): 110 | print(" %s = %s," % (names[0], val)) 111 | if len(names) > 1: 112 | associated_names.extend([(names[0], names[1:])]) 113 | print("}") 114 | print("") 115 | 116 | if len(associated_names) > 0: 117 | print("impl %s {" % enum_name) 118 | for orig, names in associated_names: 119 | for name in names: 120 | print( 121 | " pub const %s: %s = %s::%s;" 122 | % (name, enum_name, enum_name, orig) 123 | ) 124 | print("}") 125 | print("") 126 | 127 | 128 | def print_enums_convert_fn(bits, prefix): 129 | if prefix == "ev": 130 | fn_name = "EventType" 131 | elif prefix == "input_prop": 132 | fn_name = "InputProp" 133 | elif prefix == "bus": 134 | fn_name = "BusType" 135 | else: 136 | fn_name = "EV_" + prefix.upper() 137 | 138 | if not hasattr(bits, prefix): 139 | return 140 | 141 | print( 142 | "pub const fn %s(code: u32) -> Option<%s> {" 143 | % ("int_to_" + convert(fn_name), fn_name) 144 | ) 145 | print(" match code {") 146 | for val, names in list(getattr(bits, prefix).items()): 147 | # Note(ndesh): We use EV_MAX as proxy to write the UNKnown event 148 | if names[0] == "EV_MAX": 149 | print(" c if c < 31 => Some(EventType::EV_UNK),") 150 | print(" %s => Some(%s::%s)," % (val, fn_name, names[0])) 151 | if prefix == "key": 152 | for val, names in list(getattr(bits, "btn").items()): 153 | print(" %s => Some(%s::%s)," % (val, fn_name, names[0])) 154 | print(" _ => None,") 155 | print(" }") 156 | print("}") 157 | print("") 158 | 159 | 160 | def print_enums_fromstr(bits, prefix): 161 | if not hasattr(bits, prefix): 162 | return 163 | 164 | enum_name = get_enum_name(prefix) 165 | 166 | print("impl std::str::FromStr for %s {" % enum_name) 167 | print(" type Err = ();") 168 | print(" fn from_str(s: &str) -> Result {") 169 | print(" match s {") 170 | 171 | for p in (prefix, *prefix_additional.get(prefix, ())): 172 | for _val, names in list(getattr(bits, p).items()): 173 | name = names[0] 174 | print(' "%s" => Ok(%s::%s),' % (name, enum_name, name)) 175 | print(" _ => Err(()),") 176 | print(" }") 177 | print(" }") 178 | print("}") 179 | print("") 180 | 181 | 182 | def print_enums_fmt(bits, prefix): 183 | if not hasattr(bits, prefix): 184 | return 185 | 186 | enum_name = get_enum_name(prefix) 187 | 188 | if enum_name in fmt_blacklist: 189 | return 190 | 191 | print("impl std::fmt::Display for %s {" % enum_name) 192 | print(" fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {") 193 | print(' write!(f, "{:?}", self)') 194 | print(" }") 195 | print("}") 196 | print("") 197 | 198 | 199 | def print_event_code(bits, prefix): 200 | if not hasattr(bits, prefix): 201 | return 202 | 203 | print("#[allow(non_camel_case_types)]") 204 | print('#[cfg_attr(feature = "serde", derive(Serialize), derive(Deserialize))]') 205 | print("#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]") 206 | print("pub enum EventCode {") 207 | for val, [name] in list(getattr(bits, prefix).items()): 208 | if name[3:] + "_" in event_names: 209 | print(" %s(%s)," % (name, name)) 210 | elif name == "EV_FF_STATUS": 211 | print(" EV_FF_STATUS(EV_FF),") 212 | else: 213 | # Note(ndesh): We use EV_MAX as proxy to write the UNKnown event 214 | if name == "EV_MAX": 215 | print(" EV_UNK { event_type: u32, event_code: u32 },") 216 | print(" %s," % (name)) 217 | if prefix == "key": 218 | for val, names in list(getattr(bits, "btn").items()): 219 | for name in names: 220 | print(" %s = %s," % (name, val)) 221 | print("}") 222 | print("") 223 | 224 | 225 | def print_mapping_table(bits): 226 | for prefix in prefixes: 227 | if prefix == "BTN_": 228 | continue 229 | print_enums(bits, prefix[:-1].lower()) 230 | print_enums_convert_fn(bits, prefix[:-1].lower()) 231 | print_enums_fromstr(bits, prefix[:-1].lower()) 232 | print_enums_fmt(bits, prefix[:-1].lower()) 233 | if prefix == "EV_": 234 | print_event_code(bits, prefix[:-1].lower()) 235 | 236 | 237 | def parse_define(bits, line): 238 | m = re.match(r"^#define\s+(\w+)\s+(\w+)", line) 239 | if m is None: 240 | return 241 | 242 | name = m.group(1) 243 | 244 | if name in blacklist: 245 | return 246 | 247 | try: 248 | value = int(m.group(2), 0) 249 | except ValueError: 250 | return 251 | 252 | for prefix in prefixes: 253 | if not name.startswith(prefix): 254 | continue 255 | 256 | attrname = prefix[:-1].lower() 257 | 258 | if not hasattr(bits, attrname): 259 | setattr(bits, attrname, {}) 260 | b = getattr(bits, attrname) 261 | if value in b: 262 | b[value].append(name) 263 | else: 264 | b[value] = [name] 265 | 266 | 267 | def parse(fp): 268 | bits = Bits() 269 | 270 | lines = fp.readlines() 271 | for line in lines: 272 | if not line.startswith("#define"): 273 | continue 274 | parse_define(bits, line) 275 | 276 | return bits 277 | 278 | 279 | def usage(prog): 280 | print("Usage: {} ".format(prog)) 281 | 282 | 283 | if __name__ == "__main__": 284 | if len(sys.argv) <= 1: 285 | usage(sys.argv[0]) 286 | sys.exit(2) 287 | 288 | print("/* THIS FILE IS GENERATED, DO NOT EDIT */") 289 | print("") 290 | print('#[cfg(feature = "serde")]') 291 | print("use serde::{Deserialize, Serialize};") 292 | print("") 293 | 294 | for arg in sys.argv[1:]: 295 | with open(arg) as f: 296 | bits = parse(f) 297 | print_mapping_table(bits) 298 | --------------------------------------------------------------------------------