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}