Mercurial > tablet-emu
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) +}