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