-
Notifications
You must be signed in to change notification settings - Fork 53
/
ev.rs
143 lines (130 loc) · 5.55 KB
/
ev.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
use crate::input;
use input::scan::SCANNED;
use log::{error, info, warn};
use std::os::unix::prelude::AsRawFd;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
pub struct EvDevContext {
device: input::InputDevice,
pub state: input::InputDeviceState,
pub tx: std::sync::mpsc::Sender<input::InputEvent>,
exit_requested: Arc<AtomicBool>,
exited: Arc<AtomicBool>,
started: Arc<AtomicBool>,
}
impl EvDevContext {
pub fn started(&self) -> bool {
self.started.load(Ordering::Relaxed)
}
pub fn exited(&self) -> bool {
self.exited.load(Ordering::Relaxed)
}
/// After exit is requested, there will be one more event read from the device before
/// it is closed.
pub fn exit_requested(&self) -> bool {
self.exit_requested.load(Ordering::Relaxed)
}
pub fn stop(&mut self) {
self.exit_requested.store(true, Ordering::Relaxed);
}
pub fn new(
device: input::InputDevice,
tx: std::sync::mpsc::Sender<input::InputEvent>,
) -> EvDevContext {
EvDevContext {
device,
tx,
state: input::InputDeviceState::new(device),
started: Arc::new(AtomicBool::new(false)),
exit_requested: Arc::new(AtomicBool::new(false)),
exited: Arc::new(AtomicBool::new(false)),
}
}
/// Non-blocking function that will open the provided path and wait for more data with epoll
pub fn start(&mut self) {
let path = SCANNED.get_path(self.device);
self.started.store(true, Ordering::Relaxed);
self.exited.store(false, Ordering::Relaxed);
self.exit_requested.store(false, Ordering::Relaxed);
match SCANNED.get_device(self.device) {
Err(e) => error!("Error while reading events from epoll fd: {0}", e),
Ok(mut dev) => {
let mut v = [epoll::Event {
events: (epoll::Events::EPOLLET
| epoll::Events::EPOLLIN
| epoll::Events::EPOLLPRI)
.bits(),
data: 0,
}];
let epfd = epoll::create(false).unwrap();
epoll::ctl(
epfd,
epoll::ControlOptions::EPOLL_CTL_ADD,
dev.as_raw_fd(),
v[0],
)
.unwrap();
// init callback
info!("Init complete for {:?}", path);
let exit_req = Arc::clone(&self.exit_requested);
let exited = Arc::clone(&self.exited);
let device_type = self.device;
let state = self.state.clone();
let tx = self.tx.clone();
let _ = std::thread::spawn(move || {
while !exit_req.load(Ordering::Relaxed) {
// -1 indefinite wait but it is okay because our EPOLL FD
// is watching on ALL input devices at once.
let res = match epoll::wait(epfd, -1, &mut v[0..1]) {
Ok(res) => res,
Err(err) => {
warn!("epoll_wait failed: {}", err);
continue;
}
};
if res != 1 {
warn!("epoll_wait returned {0}", res);
}
for ev in dev.fetch_events().unwrap() {
// event callback
match device_type {
input::InputDevice::Multitouch => {
for event in input::multitouch::decode(&ev, &state) {
if let Err(e) = tx.send(event) {
error!(
"Failed to write InputEvent into the channel: {}",
e
);
}
}
}
input::InputDevice::Wacom => {
if let Some(event) = input::wacom::decode(&ev, &state) {
if let Err(e) = tx.send(event) {
error!(
"Failed to write InputEvent into the channel: {}",
e
);
}
}
}
input::InputDevice::GPIO => {
if let Some(event) = input::gpio::decode(&ev, &state) {
if let Err(e) = tx.send(event) {
error!(
"Failed to write InputEvent into the channel: {}",
e
);
}
}
}
_ => unreachable!(),
};
}
}
exited.store(true, Ordering::Relaxed);
});
}
}
}
}