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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
pub mod raw;
extern crate alloc;
use alloc::vec::Vec;
#[derive(Debug, Clone)]
pub enum DrmEvent {
/// An event of a generic type that's defined for all DRM drivers.
Generic(GenericDrmEvent),
/// An event of a driver-specific type.
Driver(UnsupportedDrmEvent),
/// An event that is neither driver-specific nor recognized as a
/// supported generic event type.
///
/// This is included primarily for error-reporting purposes. A
/// generic event type that's currently unsupported might become
/// supported by an additional [`GenericDrmEvent`] variant in
/// a future version, so callers that wish to continue working
/// against future releases should not use this to actually handle
/// any events beyond reporting that an event is unsupported.
Unsupported(UnsupportedDrmEvent),
}
impl DrmEvent {
pub fn from_raw(raw: &raw::DrmEvent) -> Self {
if raw.hdr.typ >= 0x80000000 {
let evt = UnsupportedDrmEvent::from_raw(raw);
Self::Driver(evt)
} else if let Ok(evt) = GenericDrmEvent::try_from_raw(raw) {
Self::Generic(evt)
} else {
let evt = UnsupportedDrmEvent::from_raw(raw);
Self::Unsupported(evt)
}
}
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum GenericDrmEvent {
VBlank(DrmVblankEvent),
FlipComplete(DrmVblankEvent),
CrtcSequence(DrmCrtcSequenceEvent),
}
impl GenericDrmEvent {
pub fn try_from_raw(raw: &raw::DrmEvent) -> Result<Self, ()> {
match raw.hdr.typ {
raw::DRM_EVENT_VBLANK => {
// Safety: All bit patterns are defined for DrmEventVblank
let body = unsafe { raw.body_as::<raw::DrmEventVblank>() }.ok_or(())?;
Ok(Self::VBlank(body.into()))
}
raw::DRM_EVENT_FLIP_COMPLETE => {
// Safety: All bit patterns are defined for DrmEventVblank
let body = unsafe { raw.body_as::<raw::DrmEventVblank>() }.ok_or(())?;
Ok(Self::FlipComplete(body.into()))
}
raw::DRM_EVENT_CRTC_SEQUENCE => {
// Safety: All bit patterns are defined for DrmEventCrtcSequence
let body = unsafe { raw.body_as::<raw::DrmEventCrtcSequence>() }.ok_or(())?;
Ok(Self::CrtcSequence(body.into()))
}
_ => Err(()),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct DrmVblankEvent {
pub user_data: u64,
pub tv_sec: u32,
pub tv_usec: u32,
pub sequence: u32,
pub crtc_id: u32,
}
impl From<&raw::DrmEventVblank> for DrmVblankEvent {
fn from(value: &raw::DrmEventVblank) -> Self {
Self {
user_data: value.user_data,
tv_sec: value.tv_sec,
tv_usec: value.tv_usec,
sequence: value.sequence,
crtc_id: value.crtc_id,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct DrmCrtcSequenceEvent {
pub user_data: u64,
pub time_ns: i64,
pub sequence: u64,
}
impl From<&raw::DrmEventCrtcSequence> for DrmCrtcSequenceEvent {
fn from(value: &raw::DrmEventCrtcSequence) -> Self {
Self {
user_data: value.user_data,
time_ns: value.time_ns,
sequence: value.sequence,
}
}
}
/// Raw owned representation of a DRM event of a type that this
/// crate doesn't directly support.
#[derive(Debug, Clone)]
pub struct UnsupportedDrmEvent {
typ: u32,
body: Vec<u8>,
}
impl UnsupportedDrmEvent {
pub fn from_raw(raw: &raw::DrmEvent) -> Self {
let typ = raw.hdr.typ;
let body = raw.body_bytes().to_vec();
Self { typ, body }
}
#[inline(always)]
pub fn typ(&self) -> u32 {
self.typ
}
#[inline(always)]
pub fn body_len(&self) -> usize {
self.body.len()
}
/// Get the body of the event as a raw byte slice.
#[inline(always)]
pub fn body_bytes(&self) -> &[u8] {
&self.body
}
/// Get a pointer to the event body that interprets it as a
/// value of `T`.
///
/// Dereferencing the returned pointer is undefined behavior
/// unless the body is long enough to contain a `T` and
/// contains a valid representation of `T`.
#[inline(always)]
pub fn body_ptr<T: Sized>(&self) -> *const T {
&self.body as *const _ as *const T
}
/// Get a reference to the body interpreted as type `T`
/// only if the body is at least long enough to fit
/// a value of that type.
///
/// # Safety
///
/// Caller must ensure that the raw body is a valid
/// representation of `T`. If all bit patterns are
/// valid representations of `T` then this is always
/// safe but the result might still be nonsense.
pub unsafe fn body_as<T>(&self) -> Option<&T> {
let min_size = core::mem::size_of::<T>();
if self.body_len() < min_size {
return None;
}
Some(self.body_as_unchecked::<T>())
}
/// Returns a reference to the body interpreted as type `T`
/// without checking whether the header's indicated length
/// is long enough for that type.
///
/// # Safety
///
/// Caller must ensure that there's enough valid memory after
/// the event header for a `T` and that the data there is
/// a valid representation of `T`.
#[inline(always)]
pub unsafe fn body_as_unchecked<T>(&self) -> &T {
let ptr = self.body_ptr::<T>();
&*ptr
}
}