1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
use super::ecodes;
use super::InputDevice;
use cgmath::Vector2;
use log::debug;
use once_cell::sync::Lazy;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::time::Duration;
pub const INITIAL_DEVS_AVAILABLE_FOR: Duration = Duration::from_millis(150);
pub static SCANNED: Lazy<EvDevs> = Lazy::new(EvDevs::new);
pub struct EvDevs {
pub wacom_path: PathBuf,
pub multitouch_path: PathBuf,
pub gpio_path: PathBuf,
pub wacom_width: u16,
pub wacom_height: u16,
pub mt_width: u16,
pub mt_height: u16,
pub wacom_orig_size: Vector2<u16>,
pub multitouch_orig_size: Vector2<u16>,
wacom_initial_dev: Arc<Mutex<Option<evdev::Device>>>,
multitouch_initial_dev: Arc<Mutex<Option<evdev::Device>>>,
gpio_initial_dev: Arc<Mutex<Option<evdev::Device>>>,
}
impl EvDevs {
fn new() -> Self {
let mut wacom = None;
let mut multitouch = None;
let mut gpio = None;
let mut event_file_paths: Vec<PathBuf> = Vec::new();
let input_dir = Path::new("/dev/input");
for entry in input_dir
.read_dir()
.unwrap_or_else(|_| panic!("Failed to list {:?}", input_dir))
{
let entry = entry.unwrap();
let file_name = entry.file_name().as_os_str().to_str().unwrap().to_owned();
if !file_name.starts_with("event") {
continue;
}
let evdev_path = input_dir.join(&file_name);
event_file_paths.push(evdev_path);
}
for evdev_path in event_file_paths {
let dev = evdev::Device::open(&evdev_path)
.unwrap_or_else(|_| panic!("Failed to scan {:?}", &evdev_path));
if dev.supported_events().contains(evdev::EventType::KEY) {
if dev
.supported_keys()
.map(|s| s.contains(evdev::Key::BTN_STYLUS))
.unwrap_or(false)
&& dev.supported_events().contains(evdev::EventType::ABSOLUTE)
{
wacom = Some((evdev_path.clone(), dev));
continue;
}
if dev
.supported_keys()
.map(|s| s.contains(evdev::Key::KEY_POWER))
.unwrap_or(false)
{
gpio = Some((evdev_path.clone(), dev));
continue;
}
}
if dev.supported_events().contains(evdev::EventType::RELATIVE)
&& dev
.supported_absolute_axes()
.map(|s| s.contains(evdev::AbsoluteAxisType::ABS_MT_SLOT))
.unwrap_or(false)
{
multitouch = Some((evdev_path.clone(), dev));
continue;
}
}
let (wacom_path, wacom_dev) = wacom.expect("Failed to find the wacom digitizer evdev!");
let (multitouch_path, multitouch_dev) =
multitouch.expect("Failed to find the multitouch evdev!");
let (gpio_path, gpio_dev) = gpio.expect("Failed to find the gpio evdev!");
let wacom_state = wacom_dev.get_abs_state().unwrap();
let wacom_orig_size = Vector2 {
x: wacom_state[ecodes::ABS_X as usize].maximum as u16,
y: wacom_state[ecodes::ABS_Y as usize].maximum as u16,
};
let (wacom_width, wacom_height) = crate::device::CURRENT_DEVICE
.get_wacom_placement()
.rotation
.rotated_size(&wacom_orig_size)
.into();
let mt_state = multitouch_dev.get_abs_state().unwrap();
let multitouch_orig_size = Vector2 {
x: mt_state[ecodes::ABS_MT_POSITION_X as usize].maximum as u16,
y: mt_state[ecodes::ABS_MT_POSITION_Y as usize].maximum as u16,
};
let (mt_width, mt_height) = crate::device::CURRENT_DEVICE
.get_multitouch_placement()
.rotation
.rotated_size(&multitouch_orig_size)
.into();
let wacom_initial_dev = Arc::new(Mutex::new(Some(wacom_dev)));
let multitouch_initial_dev = Arc::new(Mutex::new(Some(multitouch_dev)));
let gpio_initial_dev = Arc::new(Mutex::new(Some(gpio_dev)));
let wacom_initial_dev2 = wacom_initial_dev.clone();
let multitouch_initial_dev2 = multitouch_initial_dev.clone();
let gpio_initial_dev2 = gpio_initial_dev.clone();
std::thread::spawn(move || {
std::thread::sleep(INITIAL_DEVS_AVAILABLE_FOR);
(*(*wacom_initial_dev2).lock().unwrap()) = None;
(*(*multitouch_initial_dev2).lock().unwrap()) = None;
(*(*gpio_initial_dev2).lock().unwrap()) = None;
debug!("Closed initially opened evdev fds (if not used by now).");
});
Self {
wacom_path,
multitouch_path,
gpio_path,
wacom_width,
wacom_height,
mt_width,
mt_height,
multitouch_orig_size,
wacom_orig_size,
wacom_initial_dev,
multitouch_initial_dev,
gpio_initial_dev,
}
}
pub fn get_path(&self, device: InputDevice) -> &PathBuf {
match device {
InputDevice::Wacom => &self.wacom_path,
InputDevice::Multitouch => &self.multitouch_path,
InputDevice::GPIO => &self.gpio_path,
InputDevice::Unknown => panic!("\"InputDevice::Unkown\" is no device!"),
}
}
pub fn get_device(&self, device: InputDevice) -> Result<evdev::Device, impl std::error::Error> {
let dev_arc = match device {
InputDevice::Wacom => self.wacom_initial_dev.clone(),
InputDevice::Multitouch => self.multitouch_initial_dev.clone(),
InputDevice::GPIO => self.gpio_initial_dev.clone(),
InputDevice::Unknown => panic!("\"InputDevice::Unkown\" is no device!"),
};
let mut resuable_device = dev_arc.lock().unwrap();
if resuable_device.is_some() {
Ok(resuable_device.take().unwrap())
} else {
evdev::Device::open(self.get_path(device))
}
}
}