libgpiod/
info_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::{self, InfoChangeKind},
10};
11
12/// Line status watch events
13///
14/// Accessors for the info event objects allowing to monitor changes in GPIO
15/// line state.
16///
17/// Callers can be notified about changes in line's state using the interfaces
18/// exposed by GPIO chips. Each info event contains information about the event
19/// itself (timestamp, type) as well as a snapshot of line's state in the form
20/// of a line-info object.
21
22#[derive(Debug, Eq, PartialEq)]
23pub struct Event {
24    pub(crate) event: *mut gpiod::gpiod_info_event,
25}
26
27// SAFETY: Event models a wrapper around an owned gpiod_info_event and may be
28// safely sent to other threads.
29unsafe impl Send for Event {}
30
31impl Event {
32    /// Get a single chip's line's status change event.
33    ///
34    /// SAFETY: The pointer must point to an instance that is valid. After
35    /// constructing an [Event] the pointer MUST NOT be used for any other
36    /// purpose anymore. All interactions with the libgpiod API have to happen
37    /// through this object.
38    pub(crate) unsafe fn from_raw(event: *mut gpiod::gpiod_info_event) -> Self {
39        Self { event }
40    }
41
42    /// Get the event type of the status change event.
43    pub fn event_type(&self) -> Result<InfoChangeKind> {
44        // SAFETY: `gpiod_info_event` is guaranteed to be valid here.
45        InfoChangeKind::new(unsafe { gpiod::gpiod_info_event_get_event_type(self.event) })
46    }
47
48    /// Get the timestamp of the event, read from the monotonic clock.
49    pub fn timestamp(&self) -> Duration {
50        // SAFETY: `gpiod_info_event` is guaranteed to be valid here.
51        Duration::from_nanos(unsafe { gpiod::gpiod_info_event_get_timestamp_ns(self.event) })
52    }
53
54    /// Get the line-info object associated with the event.
55    pub fn line_info(&self) -> Result<&line::InfoRef> {
56        // SAFETY: `gpiod_line_info` is guaranteed to be valid here.
57        let info = unsafe { gpiod::gpiod_info_event_get_line_info(self.event) };
58
59        if info.is_null() {
60            return Err(Error::OperationFailed(
61                OperationType::InfoEventGetLineInfo,
62                errno::errno(),
63            ));
64        }
65
66        // SAFETY: The pointer is valid. The returned reference receives the
67        // lifetime '0 - the same as &self. &self also controls lifetime and
68        // ownership of the owning object. Therefore, the borrow prevents moving
69        // of the owning object to another thread.
70        Ok(unsafe { line::InfoRef::from_raw(info) })
71    }
72}
73
74impl Drop for Event {
75    /// Free the info event object and release all associated resources.
76    fn drop(&mut self) {
77        // SAFETY: `gpiod_info_event` is guaranteed to be valid here.
78        unsafe { gpiod::gpiod_info_event_free(self.event) }
79    }
80}