forked from canselcik/libremarkable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scan.rs
146 lines (128 loc) · 5.53 KB
/
scan.rs
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
use super::ecodes;
use super::InputDevice;
use std::path::{Path, PathBuf};
lazy_static! {
/// A singleton of the EvDevsScan object
pub static ref SCAN: EvDevsScan = EvDevsScan::new();
}
/// This struct contains the results of initially scaning all evdev devices,
/// which allows for device model independancy.
/// Some of its data is used by other constants.
///
/// EvDevsScan has some internal mutability to allow resuing the opened devices
/// for some time to increase performance.
/// TODO: Call this `EvDevsScanOutcome` or EvScanOutcome instead ??
pub struct EvDevsScan {
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,
}
impl EvDevsScan {
/// Scan all the evdev devices, figure out which is which
/// and get some additional data for lazy constants.
fn new() -> Self {
// All of these have to be found
let mut wacom_path: Option<PathBuf> = None;
let mut wacom_dev: Option<evdev::Device> = None;
let mut multitouch_path: Option<PathBuf> = None;
let mut multitouch_dev: Option<evdev::Device> = None;
let mut gpio_path: Option<PathBuf> = None;
let mut gpio_dev: Option<evdev::Device> = None;
// Get all /dev/input/event* file paths
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);
}
// Open and check capabilities of each event device
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.events_supported().contains(evdev::KEY) {
if dev.keys_supported().contains(evdev::BTN_STYLUS as usize)
&& dev.events_supported().contains(evdev::ABSOLUTE)
{
// The device with the wacom digitizer has the BTN_STYLUS event
// and support KEY as well as ABSOLUTE event types
wacom_path = Some(evdev_path.clone());
wacom_dev = Some(dev);
continue;
}
if dev.keys_supported().contains(evdev::KEY_POWER as usize) {
// The device for buttons has the KEY_POWER button and support KEY event types
gpio_path = Some(evdev_path.clone());
gpio_dev = Some(dev);
continue;
}
}
if dev.events_supported().contains(evdev::RELATIVE)
&& dev.absolute_axes_supported().contains(evdev::ABS_MT_SLOT)
{
// The touchscreen device has the ABS_MT_SLOT event and supports RELATIVE event types
multitouch_path = Some(evdev_path.clone());
multitouch_dev = Some(dev);
continue;
}
}
// Ensure that all devices were found
if wacom_path.is_none() || wacom_dev.is_none() {
panic!("Failed to find the wacom digitizer evdev!");
}
let wacom_path = wacom_path.unwrap();
let wacom_dev = wacom_dev.unwrap();
if multitouch_path.is_none() || multitouch_dev.is_none() {
panic!("Failed to find the multitouch evdev!");
}
let multitouch_path = multitouch_path.unwrap();
let multitouch_dev = multitouch_dev.unwrap();
if gpio_path.is_none() || gpio_dev.is_none() {
panic!("Failed to find the gpio evdev!");
}
let gpio_path = gpio_path.unwrap();
let gpio_dev = gpio_dev.unwrap();
// Figure out sizes
let wacom_state = wacom_dev.state();
// X and Y are swapped for the wacom since rM1 and rM2 have it rotated
let wacom_width = wacom_state.abs_vals[ecodes::ABS_Y as usize].maximum as u16;
let wacom_height = wacom_state.abs_vals[ecodes::ABS_X as usize].maximum as u16;
let mt_state = multitouch_dev.state();
let mt_width = mt_state.abs_vals[ecodes::ABS_MT_POSITION_X as usize].maximum as u16;
let mt_height = mt_state.abs_vals[ecodes::ABS_MT_POSITION_Y as usize].maximum as u16;
// Get values always from portrait view
Self {
wacom_path,
multitouch_path,
gpio_path,
wacom_width,
wacom_height,
mt_width,
mt_height,
}
}
/// Get the path to a InputDevice
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!"),
}
}
/// Get a ev device. If this is called early, it can get the device used for the initial scan.
pub fn get_device(&self, device: InputDevice) -> Result<evdev::Device, impl std::error::Error> {
evdev::Device::open(self.get_path(device))
}
}