libgpiod/edge_event.rs
1// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2022 Linaro Ltd.
3// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
4
5use std::time::Duration;
6
7use super::{
8 Error, OperationType, Result, gpiod,
9 line::{EdgeKind, Offset},
10};
11
12/// Line edge events handling
13///
14/// An edge event object contains information about a single line edge event.
15/// It contains the event type, timestamp and the offset of the line on which
16/// the event occurred as well as two sequence numbers (global for all lines
17/// in the associated request and local for this line only).
18///
19/// Edge events are stored into an edge-event buffer object to improve
20/// performance and to limit the number of memory allocations when a large
21/// number of events are being read.
22
23#[derive(Debug, Eq, PartialEq)]
24pub struct Event(*mut gpiod::gpiod_edge_event);
25
26// SAFETY: Event models a wrapper around an owned gpiod_edge_event and may
27// be safely sent to other threads.
28unsafe impl Send for Event {}
29
30impl Event {
31 /// Makes a copy of the event object.
32 pub fn try_clone(event: &Event) -> Result<Event> {
33 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
34 let event = unsafe { gpiod::gpiod_edge_event_copy(event.0) };
35 if event.is_null() {
36 return Err(Error::OperationFailed(
37 OperationType::EdgeEventCopy,
38 errno::errno(),
39 ));
40 }
41
42 Ok(Self(event))
43 }
44
45 /// Get the event type.
46 pub fn event_type(&self) -> Result<EdgeKind> {
47 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
48 EdgeKind::new(unsafe { gpiod::gpiod_edge_event_get_event_type(self.0) })
49 }
50
51 /// Get the timestamp of the event.
52 pub fn timestamp(&self) -> Duration {
53 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
54 Duration::from_nanos(unsafe { gpiod::gpiod_edge_event_get_timestamp_ns(self.0) })
55 }
56
57 /// Get the offset of the line on which the event was triggered.
58 pub fn line_offset(&self) -> Offset {
59 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
60 unsafe { gpiod::gpiod_edge_event_get_line_offset(self.0) }
61 }
62
63 /// Get the global sequence number of the event.
64 ///
65 /// Returns sequence number of the event relative to all lines in the
66 /// associated line request.
67 pub fn global_seqno(&self) -> usize {
68 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
69 unsafe {
70 gpiod::gpiod_edge_event_get_global_seqno(self.0)
71 .try_into()
72 .unwrap()
73 }
74 }
75
76 /// Get the event sequence number specific to concerned line.
77 ///
78 /// Returns sequence number of the event relative to the line within the
79 /// lifetime of the associated line request.
80 pub fn line_seqno(&self) -> usize {
81 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
82 unsafe {
83 gpiod::gpiod_edge_event_get_line_seqno(self.0)
84 .try_into()
85 .unwrap()
86 }
87 }
88}
89
90impl Drop for Event {
91 /// Free the edge event.
92 fn drop(&mut self) {
93 // SAFETY: `gpiod_edge_event` is guaranteed to be valid here.
94 unsafe { gpiod::gpiod_edge_event_free(self.0) };
95 }
96}