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}