pub mod raw;
extern crate alloc;
use alloc::vec::Vec;
#[derive(Debug, Clone)]
pub enum DrmEvent {
Generic(GenericDrmEvent),
Driver(UnsupportedDrmEvent),
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 => {
let body = unsafe { raw.body_as::<raw::DrmEventVblank>() }.ok_or(())?;
Ok(Self::VBlank(body.into()))
}
raw::DRM_EVENT_FLIP_COMPLETE => {
let body = unsafe { raw.body_as::<raw::DrmEventVblank>() }.ok_or(())?;
Ok(Self::FlipComplete(body.into()))
}
raw::DRM_EVENT_CRTC_SEQUENCE => {
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,
}
}
}
#[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()
}
#[inline(always)]
pub fn body_bytes(&self) -> &[u8] {
&self.body
}
#[inline(always)]
pub fn body_ptr<T: Sized>(&self) -> *const T {
&self.body as *const _ as *const T
}
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>())
}
#[inline(always)]
pub unsafe fn body_as_unchecked<T>(&self) -> &T {
let ptr = self.body_ptr::<T>();
&*ptr
}
}