linux_drm/event/raw.rs
1/// A raw DRM event.
2///
3/// This is a dynamically-sized type because DRM returns events of varying
4/// sizes. DRM events typically come from reading the file descriptor
5/// associated with a "card" device.
6///
7/// If you have a byte slice you've read from a card device then you can
8/// use [`DrmEvent::from_bytes`] to safely build a `DrmEvent` from the
9/// first event, if any.
10#[cfg_attr(feature = "stable_polyfill", derive(ptr_meta::Pointee))]
11#[repr(C)]
12pub struct DrmEvent {
13 pub hdr: DrmEventHeader,
14 pub body: [u8],
15}
16
17impl DrmEvent {
18 const HEADER_LEN: usize = core::mem::size_of::<DrmEventHeader>();
19
20 /// Given a reference to the header part of a valid event,
21 /// reinterprets it into a full [`DrmEvent`] object.
22 ///
23 /// # Safety
24 ///
25 /// The given reference must be to a valid header that is
26 /// at the start of an event object whose length matches that
27 /// given in the header. The result is a wide pointer
28 /// that tracks the body length, which safe Rust cannot
29 /// modify and so can be relied on by safe methods of
30 /// [`DrmEvent`] while the header length cannot.
31 pub unsafe fn from_event_header<'a>(hdr: &'a DrmEventHeader) -> &'a DrmEvent {
32 let ptr = hdr as *const _ as *const ();
33 #[cfg(feature = "stable_polyfill")]
34 let ptr = ptr_meta::from_raw_parts(ptr, hdr.len as usize - Self::HEADER_LEN);
35
36 #[cfg(not(feature = "stable_polyfill"))]
37 let ptr = core::ptr::from_raw_parts(ptr, hdr.len as usize - Self::HEADER_LEN);
38 &*ptr
39 }
40
41 /// Given a byte slice that contains zero or more DRM
42 /// events, obtain the first event and a slice of the remaining
43 /// bytes, or `None` if there aren't enough bytes left to extract
44 /// even one event.
45 ///
46 /// The returned event does not necessarily have valid
47 /// content. The only checking done by this function is
48 /// that there are enough bytes in the slice for the
49 /// length claimed in the header field.
50 pub fn from_bytes<'a>(buf: &'a [u8]) -> Option<(&'a DrmEvent, &'a [u8])> {
51 if buf.len() < Self::HEADER_LEN {
52 return None;
53 }
54 let hdr_bytes = &buf[0..Self::HEADER_LEN];
55 // Safety: We checked above that we have at least enough bytes for
56 // an event header, and all bit patterns are defined values for
57 // DrmEventHeader.
58 let hdr = unsafe { &*(hdr_bytes.as_ptr() as *const DrmEventHeader) };
59 let claimed_len = hdr.len as usize;
60 if buf.len() < claimed_len {
61 // The header thinks there are more bytes in this event
62 // than we have left in our slice, so clearly something
63 // has gone wrong here but we'll treat it as if there
64 // aren't any more events.
65 return None;
66 }
67 // Safety: We've checked that the header isn't asking for more
68 // bytes than we have.
69 let ret = unsafe { Self::from_event_header(hdr) };
70 Some((ret, &buf[claimed_len..]))
71 }
72
73 /// Get the length of the body in bytes.
74 ///
75 /// This is based on the information stored in the wide pointer
76 /// underlying `self`, and so ignores the length given in
77 /// the header.
78 pub fn body_len(&self) -> usize {
79 let ptr = self as *const DrmEvent;
80
81 #[cfg(not(feature = "stable_polyfill"))]
82 let (_, body_len) = ptr.to_raw_parts();
83
84 #[cfg(feature = "stable_polyfill")]
85 let (_, body_len) = ptr_meta::to_raw_parts(ptr);
86
87 body_len
88 }
89
90 /// Get the body of the event as a raw byte slice.
91 #[inline(always)]
92 pub fn body_bytes(&self) -> &[u8] {
93 &self.body
94 }
95
96 /// Get a pointer to the event body that interprets it as a
97 /// value of `T`.
98 ///
99 /// Dereferencing the returned pointer is undefined behavior
100 /// unless the body is long enough to contain a `T` and
101 /// contains a valid representation of `T`.
102 #[inline(always)]
103 pub fn body_ptr<T: Sized>(&self) -> *const T {
104 &self.body as *const _ as *const T
105 }
106
107 /// Get a reference to the body interpreted as type `T`
108 /// only if the body is at least long enough to fit
109 /// a value of that type.
110 ///
111 /// # Safety
112 ///
113 /// Caller must ensure that the raw body is a valid
114 /// representation of `T`. If all bit patterns are
115 /// valid representations of `T` then this is always
116 /// safe but the result might still be nonsense.
117 pub unsafe fn body_as<T>(&self) -> Option<&T> {
118 let min_size = core::mem::size_of::<T>();
119 if self.body_len() < min_size {
120 return None;
121 }
122 Some(self.body_as_unchecked::<T>())
123 }
124
125 /// Returns a reference to the body interpreted as type `T`
126 /// without checking whether the header's indicated length
127 /// is long enough for that type.
128 ///
129 /// # Safety
130 ///
131 /// Caller must ensure that there's enough valid memory after
132 /// the event header for a `T` and that the data there is
133 /// a valid representation of `T`.
134 #[inline(always)]
135 pub unsafe fn body_as_unchecked<T>(&self) -> &T {
136 let ptr = self.body_ptr::<T>();
137 &*ptr
138 }
139}
140
141/// Raw DRM event header.
142#[repr(C)]
143#[derive(Clone, Copy, Debug)]
144pub struct DrmEventHeader {
145 pub typ: u32,
146 pub len: u32,
147}
148
149/// Vertical blanking event.
150///
151/// This event is sent in response to `DRM_IOCTL_WAIT_VBLANK` with the
152/// `DRM_VBLANK_EVENT` flag set.
153///
154/// The event body type is [`DrmEventVblank`].
155pub const DRM_EVENT_VBLANK: u32 = 0x01;
156
157/// Page-flip completion event.
158///
159/// This event is sent in response to an atomic commit or legacy page-flip with
160/// the `DRM_MODE_PAGE_FLIP_EVENT` flag set.
161///
162/// The event body type is [`DrmEventVblank`].
163pub const DRM_EVENT_FLIP_COMPLETE: u32 = 0x02;
164
165/// CRTC sequence event.
166///
167/// This event is sent in response to `DRM_IOCTL_CRTC_QUEUE_SEQUENCE`.
168///
169/// The event body type is [`DrmEventCrtcSequence`].
170pub const DRM_EVENT_CRTC_SEQUENCE: u32 = 0x03;
171
172/// The body of a [`DRM_EVENT_VBLANK`] event.
173#[repr(C)]
174#[derive(Clone, Copy, Debug)]
175pub struct DrmEventVblank {
176 pub user_data: u64,
177 pub tv_sec: u32,
178 pub tv_usec: u32,
179 pub sequence: u32,
180 pub crtc_id: u32, // always zero in older kernels that don't support this
181}
182
183/// The body of a [`DRM_EVENT_CRTC_SEQUENCE`] event.
184#[repr(C)]
185#[derive(Clone, Copy, Debug)]
186pub struct DrmEventCrtcSequence {
187 pub user_data: u64,
188 pub time_ns: i64,
189 pub sequence: u64,
190}
191
192pub fn events_from_bytes<'a>(buf: &'a [u8]) -> impl Iterator<Item = &'a DrmEvent> + 'a {
193 DrmEventsFromBytes { remain: buf }
194}
195
196struct DrmEventsFromBytes<'a> {
197 remain: &'a [u8],
198}
199
200impl<'a> Iterator for DrmEventsFromBytes<'a> {
201 type Item = &'a DrmEvent;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 let (ret, remain) = DrmEvent::from_bytes(self.remain)?;
205 self.remain = remain;
206 Some(ret)
207 }
208}