diff src/uinput.rs @ 12:d43c31aff57c

Split uinput helpers into another module.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 01 Nov 2020 16:01:00 +0100
parents
children 478cf2a7d577
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/uinput.rs
@@ -0,0 +1,196 @@
+// Tablet emulator, for people who don’t own one
+// Copyright © 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+use std::fs::{File, OpenOptions};
+use crate::{MAX_X, MAX_Y};
+use input_linux::{
+    sys::input_event, sys::timeval, AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind,
+    InputId, InputProperty, Key, MiscKind, SynchronizeKind, UInputHandle,
+};
+
+pub fn create_uinput_device() -> std::io::Result<UInputHandle<File>> {
+    let file = OpenOptions::new().write(true).open("/dev/uinput")?;
+    let dev = UInputHandle::new(file);
+
+    dev.set_evbit(EventKind::Synchronize)?;
+    dev.set_evbit(EventKind::Key)?;
+    dev.set_evbit(EventKind::Absolute)?;
+    dev.set_evbit(EventKind::Misc)?;
+    dev.set_keybit(Key::ButtonToolPen)?;
+    dev.set_keybit(Key::ButtonToolRubber)?;
+    dev.set_keybit(Key::ButtonToolBrush)?;
+    dev.set_keybit(Key::ButtonToolPencil)?;
+    dev.set_keybit(Key::ButtonToolAirbrush)?;
+    dev.set_keybit(Key::ButtonTouch)?;
+    dev.set_keybit(Key::ButtonStylus)?;
+    dev.set_keybit(Key::ButtonStylus2)?;
+    dev.set_keybit(Key::ButtonStylus3)?;
+    dev.set_mscbit(MiscKind::Serial)?;
+    dev.set_propbit(InputProperty::Direct)?;
+
+    dev.set_absbit(AbsoluteAxis::X)?;
+    dev.set_absbit(AbsoluteAxis::Y)?;
+    dev.set_absbit(AbsoluteAxis::Z)?;
+    dev.set_absbit(AbsoluteAxis::Wheel)?;
+    dev.set_absbit(AbsoluteAxis::Pressure)?;
+    dev.set_absbit(AbsoluteAxis::Distance)?;
+    dev.set_absbit(AbsoluteAxis::TiltX)?;
+    dev.set_absbit(AbsoluteAxis::TiltY)?;
+    dev.set_absbit(AbsoluteAxis::Misc)?;
+
+    let id = InputId {
+        bustype: 3,
+        vendor: 0x56a,
+        product: 0x350,
+        version: 0xb,
+    };
+
+    let x = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::X,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: 0,
+            maximum: MAX_X,
+            fuzz: 0,
+            flat: 0,
+            resolution: 200,
+        },
+    };
+    let y = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::Y,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: 0,
+            maximum: MAX_Y,
+            fuzz: 0,
+            flat: 0,
+            resolution: 200,
+        },
+    };
+    let z = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::Z,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: -900,
+            maximum: 899,
+            fuzz: 0,
+            flat: 0,
+            resolution: 287,
+        },
+    };
+    let wheel = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::Wheel,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: 0,
+            maximum: 2047,
+            fuzz: 0,
+            flat: 0,
+            resolution: 0,
+        },
+    };
+    let pressure = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::Pressure,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: 0,
+            maximum: 8196,
+            fuzz: 0,
+            flat: 0,
+            resolution: 0,
+        },
+    };
+    let distance = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::Distance,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: 0,
+            maximum: 63,
+            fuzz: 0,
+            flat: 0,
+            resolution: 0,
+        },
+    };
+    let tilt_x = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::TiltX,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: -64,
+            maximum: 63,
+            fuzz: 0,
+            flat: 0,
+            resolution: 57,
+        },
+    };
+    let tilt_y = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::TiltY,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: -64,
+            maximum: 63,
+            fuzz: 0,
+            flat: 0,
+            resolution: 57,
+        },
+    };
+    let misc = AbsoluteInfoSetup {
+        axis: AbsoluteAxis::Misc,
+        info: AbsoluteInfo {
+            value: 0,
+            minimum: 0,
+            maximum: 0,
+            fuzz: 0,
+            flat: 0,
+            resolution: 0,
+        },
+    };
+
+    dev.create(
+        &id,
+        b"TabletEmu",
+        0,
+        &[x, y, z, wheel, pressure, distance, tilt_x, tilt_y, misc],
+    )?;
+    Ok(dev)
+}
+
+fn input_event_new(type_: EventKind, code: u16, value: i32) -> input_event {
+    input_event {
+        time: timeval {
+            tv_sec: 0,
+            tv_usec: 0,
+        },
+        type_: type_ as u16,
+        code,
+        value,
+    }
+}
+
+pub fn input_axis_new(code: AbsoluteAxis, value: i32) -> input_event {
+    input_event_new(EventKind::Absolute, code as u16, value)
+}
+
+pub fn input_key_new(code: Key, value: i32) -> input_event {
+    input_event_new(EventKind::Key, code as u16, value)
+}
+
+pub fn input_misc_new(code: MiscKind, value: i32) -> input_event {
+    input_event_new(EventKind::Misc, code as u16, value)
+}
+
+pub fn input_synchronize_new(code: SynchronizeKind, value: i32) -> input_event {
+    input_event_new(EventKind::Synchronize, code as u16, value)
+}