linux_drm/event.rs
1pub mod raw;
2
3extern crate alloc;
4use alloc::vec::Vec;
5
6/// An event emitted from a [`crate::Card`].
7///
8/// DRM supports both generic events that are supported by all drivers and
9/// some driver-specific event types. This library only directly supports
10/// the generic ones, but does still expose driver-specific events in a
11/// raw form for callers to decode themselves.
12#[derive(Debug, Clone)]
13pub enum DrmEvent {
14 /// An event of a generic type that's defined for all DRM drivers.
15 Generic(GenericDrmEvent),
16
17 /// An event of a driver-specific type.
18 Driver(UnsupportedDrmEvent),
19
20 /// An event that is neither driver-specific nor recognized as a
21 /// supported generic event type.
22 ///
23 /// This is included primarily for error-reporting purposes. A
24 /// generic event type that's currently unsupported might become
25 /// supported by an additional [`GenericDrmEvent`] variant in
26 /// a future version, so callers that wish to continue working
27 /// against future releases should not use this to actually handle
28 /// any events beyond reporting that an event is unsupported.
29 Unsupported(UnsupportedDrmEvent),
30}
31
32impl DrmEvent {
33 pub fn from_raw(raw: &raw::DrmEvent) -> Self {
34 if raw.hdr.typ >= 0x80000000 {
35 let evt = UnsupportedDrmEvent::from_raw(raw);
36 Self::Driver(evt)
37 } else if let Ok(evt) = GenericDrmEvent::try_from_raw(raw) {
38 Self::Generic(evt)
39 } else {
40 let evt = UnsupportedDrmEvent::from_raw(raw);
41 Self::Unsupported(evt)
42 }
43 }
44}
45
46/// Enumeration of generic DRM event types.
47#[derive(Debug, Clone, Copy)]
48#[non_exhaustive]
49pub enum GenericDrmEvent {
50 VBlank(DrmVblankEvent),
51 FlipComplete(DrmVblankEvent),
52 CrtcSequence(DrmCrtcSequenceEvent),
53}
54
55impl GenericDrmEvent {
56 /// Try to interpret the given raw event as one of the generic event types.
57 pub fn try_from_raw(raw: &raw::DrmEvent) -> Result<Self, ()> {
58 match raw.hdr.typ {
59 raw::DRM_EVENT_VBLANK => {
60 // Safety: All bit patterns are defined for DrmEventVblank
61 let body = unsafe { raw.body_as::<raw::DrmEventVblank>() }.ok_or(())?;
62 Ok(Self::VBlank(body.into()))
63 }
64 raw::DRM_EVENT_FLIP_COMPLETE => {
65 // Safety: All bit patterns are defined for DrmEventVblank
66 let body = unsafe { raw.body_as::<raw::DrmEventVblank>() }.ok_or(())?;
67 Ok(Self::FlipComplete(body.into()))
68 }
69 raw::DRM_EVENT_CRTC_SEQUENCE => {
70 // Safety: All bit patterns are defined for DrmEventCrtcSequence
71 let body = unsafe { raw.body_as::<raw::DrmEventCrtcSequence>() }.ok_or(())?;
72 Ok(Self::CrtcSequence(body.into()))
73 }
74 _ => Err(()),
75 }
76 }
77}
78
79/// Signals the beginning of a vertical blanking period.
80#[derive(Debug, Clone, Copy)]
81pub struct DrmVblankEvent {
82 pub user_data: u64,
83 pub tv_sec: u32,
84 pub tv_usec: u32,
85 pub sequence: u32,
86 pub crtc_id: u32,
87}
88
89impl From<&raw::DrmEventVblank> for DrmVblankEvent {
90 fn from(value: &raw::DrmEventVblank) -> Self {
91 Self {
92 user_data: value.user_data,
93 tv_sec: value.tv_sec,
94 tv_usec: value.tv_usec,
95 sequence: value.sequence,
96 crtc_id: value.crtc_id,
97 }
98 }
99}
100
101#[derive(Debug, Clone, Copy)]
102pub struct DrmCrtcSequenceEvent {
103 pub user_data: u64,
104 pub time_ns: i64,
105 pub sequence: u64,
106}
107
108impl From<&raw::DrmEventCrtcSequence> for DrmCrtcSequenceEvent {
109 fn from(value: &raw::DrmEventCrtcSequence) -> Self {
110 Self {
111 user_data: value.user_data,
112 time_ns: value.time_ns,
113 sequence: value.sequence,
114 }
115 }
116}
117
118/// Raw owned representation of a DRM event of a type that this
119/// crate doesn't directly support.
120#[derive(Debug, Clone)]
121pub struct UnsupportedDrmEvent {
122 typ: u32,
123 body: Vec<u8>,
124}
125
126impl UnsupportedDrmEvent {
127 pub fn from_raw(raw: &raw::DrmEvent) -> Self {
128 let typ = raw.hdr.typ;
129 let body = raw.body_bytes().to_vec();
130 Self { typ, body }
131 }
132
133 #[inline(always)]
134 pub fn typ(&self) -> u32 {
135 self.typ
136 }
137
138 #[inline(always)]
139 pub fn body_len(&self) -> usize {
140 self.body.len()
141 }
142
143 /// Get the body of the event as a raw byte slice.
144 #[inline(always)]
145 pub fn body_bytes(&self) -> &[u8] {
146 &self.body
147 }
148
149 /// Get a pointer to the event body that interprets it as a
150 /// value of `T`.
151 ///
152 /// Dereferencing the returned pointer is undefined behavior
153 /// unless the body is long enough to contain a `T` and
154 /// contains a valid representation of `T`.
155 #[inline(always)]
156 pub fn body_ptr<T: Sized>(&self) -> *const T {
157 &self.body as *const _ as *const T
158 }
159
160 /// Get a reference to the body interpreted as type `T`
161 /// only if the body is at least long enough to fit
162 /// a value of that type.
163 ///
164 /// # Safety
165 ///
166 /// Caller must ensure that the raw body is a valid
167 /// representation of `T`. If all bit patterns are
168 /// valid representations of `T` then this is always
169 /// safe but the result might still be nonsense.
170 pub unsafe fn body_as<T>(&self) -> Option<&T> {
171 let min_size = core::mem::size_of::<T>();
172 if self.body_len() < min_size {
173 return None;
174 }
175 Some(self.body_as_unchecked::<T>())
176 }
177
178 /// Returns a reference to the body interpreted as type `T`
179 /// without checking whether the header's indicated length
180 /// is long enough for that type.
181 ///
182 /// # Safety
183 ///
184 /// Caller must ensure that there's enough valid memory after
185 /// the event header for a `T` and that the data there is
186 /// a valid representation of `T`.
187 #[inline(always)]
188 pub unsafe fn body_as_unchecked<T>(&self) -> &T {
189 let ptr = self.body_ptr::<T>();
190 &*ptr
191 }
192}