1pub(crate) mod analyze;
2mod read;
3pub(crate) mod touch_group;
4
5use std::{
6 collections::HashMap,
7 error::Error,
8 fs,
9 ops::Deref,
10 sync::{
11 atomic::AtomicUsize,
12 mpsc::{self, Receiver},
13 Arc,
14 },
15 thread,
16 time::Duration,
17};
18
19use atomic::{Atomic, Ordering};
20use evdev::{Device, EventType};
21
22#[derive(Debug)]
45pub struct TouchListener {
46 status_map: HashMap<usize, Arc<AtomicTouchStatus>>,
47 wait: Receiver<()>,
48 min_pixel: Arc<AtomicUsize>,
49}
50
51pub(crate) type AtomicTouchStatus = Atomic<TouchStatus>;
52
53#[derive(Debug, Clone, Copy, Eq, PartialEq)]
61pub enum TouchStatus {
62 Slide,
63 Click,
64 None,
65}
66
67impl Deref for TouchListener {
68 type Target = HashMap<usize, Arc<AtomicTouchStatus>>;
69
70 fn deref(&self) -> &Self::Target {
71 &self.status_map
72 }
73}
74
75impl TouchListener {
76 pub fn new(min_pixel: usize) -> Result<Self, Box<dyn Error>> {
86 let devices: Vec<_> = fs::read_dir("/dev/input")?
87 .filter_map(|f| {
88 let f = f.ok()?;
89 let path = f.path();
90 let device = Device::open(path).ok()?;
91
92 let event_len = "event".len();
93 let id: usize = f.file_name().into_string().ok()?[event_len..]
94 .trim()
95 .parse()
96 .ok()?;
97
98 Some((id, device))
99 })
100 .filter(|(_, d)| d.supported_events().contains(EventType::ABSOLUTE))
101 .collect();
102
103 if devices.is_empty() {
104 return Err("No usable touch device".into());
105 }
106
107 let mut status_map = HashMap::new();
108 let (sx, rx) = mpsc::sync_channel(1);
109 let min_pixel = Arc::new(AtomicUsize::new(min_pixel));
110
111 for (id, device) in devices {
112 let touch_status = Arc::new(Atomic::new(TouchStatus::None));
113 let touch_status_clone = touch_status.clone();
114 let sx = sx.clone();
115 let min_pixel = min_pixel.clone();
116
117 status_map.insert(id, touch_status);
118
119 thread::Builder::new()
120 .name("TouchDeviceListener".into())
121 .spawn(move || read::daemon_thread(device, &touch_status_clone, &sx, &min_pixel))?;
122 }
123
124 if status_map.is_empty() {
125 return Err("No usable touch device".into());
126 }
127
128 Ok(Self {
129 status_map,
130 wait: rx,
131 min_pixel,
132 })
133 }
134
135 pub fn min_pixel(&self, p: usize) {
137 self.min_pixel.store(p, Ordering::Release);
138 }
139
140 #[inline]
146 pub fn wait(&self) -> Result<(), &'static str> {
147 self.wait.recv().map_err(|_| "Monitor threads had paniced")
148 }
149
150 #[inline]
156 pub fn wait_timeout(&self, t: Duration) -> Result<(), &'static str> {
157 self.wait
158 .recv_timeout(t)
159 .map_err(|_| "Monitor threads had paniced")
160 }
161
162 pub fn status(&self) -> (bool, bool, bool) {
168 let slide = self
169 .status_map
170 .values()
171 .any(|s| s.load(Ordering::Acquire) == TouchStatus::Slide);
172 let click = self
173 .status_map
174 .values()
175 .any(|s| s.load(Ordering::Acquire) == TouchStatus::Click);
176 let none = self
177 .status_map
178 .values()
179 .any(|s| s.load(Ordering::Acquire) == TouchStatus::None);
180
181 (slide, click, none)
182 }
183}