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}