remarkable_events/
lib.rs

1use std::{convert::TryFrom, error::Error as StdError, fmt, path::Path};
2
3use event_source::EventSourceError;
4
5mod event_source;
6mod raw_event;
7
8use {event_source::EventSource, raw_event::RawEvent};
9
10#[derive(Debug)]
11pub enum Error {
12    /// UnfinishedEvent occurs when a Sync is received
13    /// but we've not yet received X and Y coords.
14    UnfinishedEvent(ToolKind, &'static str),
15
16    /// UnknownEvent occurs when the input_event is unknown
17    /// and not (yet?) supported by this library.
18    UnknownEventRead(UnknownEvent),
19
20    Io(std::io::Error),
21}
22
23impl fmt::Display for Error {
24    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25        match self {
26            Self::UnfinishedEvent(kind, missing) => {
27                write!(f, "Unfinished {} event. Missing {}", kind, missing)
28            }
29            Self::UnknownEventRead(err) => write!(f, "Read Unknown event: {}", err),
30
31            Self::Io(err) => write!(f, "Io error: {}", err),
32        }
33    }
34}
35
36impl StdError for Error {
37    fn source(&self) -> Option<&(dyn StdError + 'static)> {
38        match self {
39            Self::Io(ref inner) => inner.source(),
40            _ => None,
41        }
42    }
43}
44
45impl From<EventSourceError<UnknownEvent>> for Error {
46    fn from(err: EventSourceError<UnknownEvent>) -> Self {
47        match err {
48            EventSourceError::Io(io_err) => Self::Io(io_err),
49            EventSourceError::Parse(ev_err) => Self::UnknownEventRead(ev_err),
50        }
51    }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
55pub enum ToolEvent {
56    Update(Tool),
57    Removed(ToolKind),
58}
59/// This should be generalised by making struct Pen
60/// be a struct Tool that has a kind field.
61/// For now, to get stuff going, just run with it as a Pen.
62pub struct ToolEventSource {
63    event_source: EventSource<Event>,
64    state: Option<ToolBuilder>,
65}
66
67impl ToolEventSource {
68    pub async fn open(path: impl AsRef<Path>) -> Result<Self, Error> {
69        let event_source = event_source::EventSource::open(path)
70            .await
71            .map_err(Error::Io)?;
72
73        Ok(Self {
74            event_source,
75            state: None,
76        })
77    }
78
79    pub async fn next(&mut self) -> Result<ToolEvent, Error> {
80        // Currently we need to listen to Tool events.
81        // Tool::Pen(true) means the Pen is close to the Pad, start to build.
82        // Tool::Pen(false) means the Pen was lifted and we need to reset.
83        //
84        // These events dictate what we should do.
85        // @TODO: Handle these events properly.
86
87        // Wait for an Appeared event.
88        let state = if let Some(ref mut state) = self.state {
89            state
90        } else {
91            // Wait for an add event.
92            loop {
93                match self.event_source.next().await? {
94                    Event::ToolAdded(ToolKind::Pen) => {
95                        let new_state = ToolBuilder::new(ToolKind::Pen);
96                        break self.state.insert(new_state);
97                    }
98
99                    Event::ToolAdded(_kind) => {
100
101                        // eprintln!("Ignoring add event for kind `{:?}`", kind);
102                    }
103
104                    _ev => {
105                        // eprintln!("Ignoring Event: {:?}", ev);
106                    }
107                }
108            }
109        };
110        loop {
111            match self.event_source.next().await? {
112                Event::Movement(mv) => match state {
113                    ToolBuilder::Building(unfinished) => unfinished.apply_movement(mv),
114                    ToolBuilder::Built(tool) => tool.apply_movement(mv),
115                },
116
117                Event::Sync => match state {
118                    ToolBuilder::Building(unfinished) => {
119                        let tool = unfinished.finish().expect("Could not finish tool");
120                        *state = ToolBuilder::Built(tool);
121                        return Ok(ToolEvent::Update(tool));
122                    }
123
124                    ToolBuilder::Built(tool) => {
125                        return Ok(ToolEvent::Update(*tool));
126                    }
127                },
128                Event::ToolRemoved(ToolKind::Pen) => {
129                    self.state = None;
130                    return Ok(ToolEvent::Removed(ToolKind::Pen));
131                }
132
133                Event::ToolRemoved(kind) => {
134                    // Should really wait for a sync....
135                    eprintln!("Ignoring non Pen ToolRemoved({:?})", kind);
136                }
137
138                Event::ToolAdded(kind) => {
139                    eprintln!("Ignoring ToolAdded({:?})", kind);
140                }
141            }
142        }
143    }
144}
145
146enum ToolBuilder {
147    Built(Tool),
148    Building(UnfinishedTool),
149}
150
151impl ToolBuilder {
152    fn new(kind: ToolKind) -> Self {
153        Self::Building(UnfinishedTool::kind(kind))
154    }
155}
156
157struct UnfinishedTool {
158    kind: ToolKind,
159    x: Option<u32>,
160    y: Option<u32>,
161    tilt_x: Option<u32>,
162    tilt_y: Option<u32>,
163    pressure: Option<u32>,
164    distance: Option<u32>,
165}
166
167impl UnfinishedTool {
168    fn kind(kind: ToolKind) -> Self {
169        Self {
170            kind,
171            x: None,
172            y: None,
173            tilt_x: None,
174            tilt_y: None,
175            pressure: None,
176            distance: None,
177        }
178    }
179
180    fn apply_movement(&mut self, mv: Movement) {
181        match mv {
182            Movement::X(n) => self.x.replace(n),
183            Movement::Y(n) => self.y.replace(n),
184            Movement::TiltX(n) => self.tilt_x.replace(n),
185            Movement::TiltY(n) => self.tilt_y.replace(n),
186            Movement::Pressure(n) => self.pressure.replace(n),
187            Movement::Distance(n) => self.distance.replace(n),
188        };
189    }
190
191    // @TODO: Change Return type to Result with an error saying what field is missing.
192    fn finish(&mut self) -> Result<Tool, &'static str> {
193        let x = self.x.take().ok_or("X")?;
194        let y = self.y.take().ok_or("Y")?;
195
196        let height = match (self.pressure.take(), self.distance.take()) {
197            (Some(pressure), Some(distance)) => {
198                if distance < 10 && 700 < pressure {
199                    Height::Touching(pressure)
200                } else {
201                    Height::Distance(distance)
202                }
203            }
204            (Some(pressure), None) => Height::Touching(pressure),
205            (None, Some(distance)) => Height::Distance(distance),
206            (None, None) => Height::Missing,
207        };
208
209        Ok(Tool {
210            kind: self.kind,
211            point: Point(x, y),
212            tilt_x: self.tilt_x.take(),
213            tilt_y: self.tilt_y.take(),
214            height,
215        })
216    }
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
220pub struct Tool {
221    kind: ToolKind,
222    point: Point,
223    tilt_x: Option<u32>,
224    tilt_y: Option<u32>,
225    height: Height,
226}
227
228impl Tool {
229    fn apply_movement(&mut self, ev: Movement) {
230        match ev {
231            Movement::X(n) => self.point.0 = n,
232            Movement::Y(n) => self.point.1 = n,
233            Movement::TiltX(n) => self.tilt_x = Some(n),
234            Movement::TiltY(n) => self.tilt_y = Some(n),
235            Movement::Pressure(n) => self.height = Height::Touching(n),
236            Movement::Distance(n) => self.height = Height::Distance(n),
237        }
238    }
239}
240
241impl fmt::Display for Tool {
242    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243        write!(
244            f,
245            "Tool at {}. tilt x{:?} y{:?}. {}",
246            self.point, self.tilt_x, self.tilt_y, self.height
247        )
248    }
249}
250
251#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
252pub enum Height {
253    Missing,
254    Distance(u32),
255    Touching(u32),
256}
257
258impl fmt::Display for Height {
259    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260        match self {
261            Self::Missing => f.write_str("distance missing"),
262            Self::Distance(n) => write!(f, "distance{}", n),
263            Self::Touching(n) => write!(f, "touching{}", n),
264        }
265    }
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
269pub struct Point(u32, u32);
270
271impl fmt::Display for Point {
272    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273        write!(f, "{},{}", self.0, self.1)
274    }
275}
276
277#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
278pub enum ToolKind {
279    Pen,
280    Rubber,
281    Touch,
282    Stylus,
283    Stylus2,
284}
285
286impl fmt::Display for ToolKind {
287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288        match *self {
289            Self::Pen => f.write_str("Pen"),
290            Self::Rubber => f.write_str("Rubber"),
291            Self::Touch => f.write_str("Touch"),
292            Self::Stylus => f.write_str("Stylus"),
293            Self::Stylus2 => f.write_str("Stylus2"),
294        }
295    }
296}
297
298impl ToolKind {
299    fn from_code(code: u16) -> Option<ToolKind> {
300        match code {
301            320 => Some(Self::Pen),
302            321 => Some(Self::Rubber),
303            330 => Some(Self::Touch),
304            331 => Some(Self::Stylus),
305            332 => Some(Self::Stylus2),
306            _ => None,
307        }
308    }
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
312pub enum Movement {
313    X(u32),
314    Y(u32),
315    TiltX(u32),
316    TiltY(u32),
317    Pressure(u32),
318    Distance(u32),
319}
320
321// More Movement, needed to parse events from /dev/input/event2
322// #define ABS_MT_TOUCH_MAJOR  0x30    /* Major axis of touching ellipse */
323// #define ABS_MT_TOUCH_MINOR  0x31    /* Minor axis (omit if circular) */
324// #define ABS_MT_WIDTH_MAJOR  0x32    /* Major axis of approaching ellipse */
325// #define ABS_MT_WIDTH_MINOR  0x33    /* Minor axis (omit if circular) */
326// #define ABS_MT_ORIENTATION  0x34    /* Ellipse orientation */
327// #define ABS_MT_POSITION_X   0x35    /* Center X touch position */
328// #define ABS_MT_POSITION_Y   0x36    /* Center Y touch position */
329// #define ABS_MT_TOOL_TYPE    0x37    /* Type of touching device */
330// #define ABS_MT_BLOB_ID      0x38    /* Group a set of packets as a blob */
331// #define ABS_MT_TRACKING_ID  0x39    /* Unique ID of initiated contact */
332// #define ABS_MT_PRESSURE     0x3a    /* Pressure on contact area */
333// #define ABS_MT_DISTANCE     0x3b    /* Contact hover distance */
334// #define ABS_MT_TOOL_X       0x3c    /* Center X tool position */
335// #define ABS_MT_TOOL_Y       0x3d    /* Center Y tool position */
336//
337//
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq)]
340/// Events read from event1 (Only registers the pen)
341enum Event {
342    Sync,
343    ToolAdded(ToolKind),
344    ToolRemoved(ToolKind),
345    Movement(Movement),
346}
347
348impl TryFrom<RawEvent> for Event {
349    type Error = UnknownEvent;
350
351    fn try_from(ev: RawEvent) -> std::result::Result<Self, Self::Error> {
352        match (ev.typ, ev.code) {
353            (0, _) => Ok(Event::Sync),
354            (1, code) => {
355                // type 1 is a tool event.
356                // the code tells what tool
357                // value tells if it appeared or went away
358                let tool = ToolKind::from_code(code).ok_or(UnknownEvent::ToolCode(code))?;
359                match ev.value {
360                    0 => Ok(Event::ToolRemoved(tool)),
361                    1 => Ok(Event::ToolAdded(tool)),
362                    v => Err(UnknownEvent::ToolValue(v)),
363                }
364            }
365
366            (3, 0) => Ok(Event::Movement(Movement::X(ev.value))),
367            (3, 1) => Ok(Event::Movement(Movement::Y(ev.value))),
368            (3, 24) => Ok(Event::Movement(Movement::Pressure(ev.value))),
369            (3, 25) => Ok(Event::Movement(Movement::Distance(ev.value))),
370            (3, 26) => Ok(Event::Movement(Movement::TiltX(ev.value))),
371            (3, 27) => Ok(Event::Movement(Movement::TiltY(ev.value))),
372
373            (3, _) => Err(UnknownEvent::MovementCode(ev.code)),
374
375            _ => Err(UnknownEvent::Type(ev)),
376        }
377    }
378}
379
380//
381
382#[derive(Debug, Clone, Copy, PartialEq, Eq)]
383pub enum UnknownEvent {
384    ToolCode(u16),
385    ToolValue(u32),
386    MovementCode(u16),
387
388    Type(RawEvent),
389}
390
391impl std::error::Error for UnknownEvent {
392    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
393        None
394    }
395}
396
397impl fmt::Display for UnknownEvent {
398    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
399        match self {
400            Self::ToolCode(code) => write!(f, "Unknown tool code`{:#04x}`", code),
401            Self::ToolValue(value) => write!(
402                f,
403                "Unexpected value for Tool event. Should be 0 or 1. Was:`{:#04x}`",
404                value
405            ),
406            Self::MovementCode(code) => write!(f, "Unknown movement code `{:#04x}`", code),
407            Self::Type(ev) => write!(
408                f,
409                "Unknown type: `{:#02x}`, code: `{:#04x}`, value: `{:#08x}`, ",
410                ev.typ, ev.code, ev.value
411            ),
412        }
413    }
414}