1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::ops::{BitAnd, BitOr};
4
5mod atomic;
6mod buffer;
7mod props;
8
9pub use atomic::*;
10pub use buffer::*;
11pub use props::*;
12
13macro_rules! id_newtype {
14 ($name:ident) => {
15 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
16 #[repr(transparent)]
17 pub struct $name(pub u32);
18
19 impl $name {
20 #[inline(always)]
22 pub const fn to_raw(self) -> u32 {
23 self.0
24 }
25
26 #[inline(always)]
28 pub const fn is_null(self) -> bool {
29 self.0 == 0
30 }
31 }
32
33 impl props::AsRawPropertyValue for $name {
34 #[inline(always)]
35 fn as_raw_property_value(&self) -> u64 {
36 self.0 as u64
37 }
38 }
39
40 impl props::IntoRawPropertyValue for $name {
41 #[inline(always)]
42 fn into_raw_property_value(self) -> (u64, Option<Box<dyn core::any::Any>>) {
43 (self.0 as u64, None)
44 }
45 }
46 };
47}
48
49id_newtype!(FramebufferId);
50id_newtype!(CrtcId);
51id_newtype!(ConnectorId);
52id_newtype!(EncoderId);
53id_newtype!(PlaneId);
54id_newtype!(BufferObjectId);
55id_newtype!(PropertyId);
56id_newtype!(BlobId);
57
58#[derive(Debug, Clone, Copy)]
59#[non_exhaustive]
60pub enum ObjectId {
61 Crtc(CrtcId),
62 Connector(ConnectorId),
63 Encoder(EncoderId),
64 Mode(u32),
65 Property(PropertyId),
66 Framebuffer(FramebufferId),
67 Blob(BlobId),
68 Plane(PlaneId),
69}
70
71impl ObjectId {
72 pub fn as_raw_type_and_id(self) -> (u32, u32) {
73 use crate::ioctl;
74 match self {
75 ObjectId::Crtc(id) => (ioctl::DRM_MODE_OBJECT_CRTC, id.0),
76 ObjectId::Connector(id) => (ioctl::DRM_MODE_OBJECT_CONNECTOR, id.0),
77 ObjectId::Encoder(id) => (ioctl::DRM_MODE_OBJECT_ENCODER, id.0),
78 ObjectId::Mode(id) => (ioctl::DRM_MODE_OBJECT_MODE, id),
79 ObjectId::Property(id) => (ioctl::DRM_MODE_OBJECT_PROPERTY, id.0),
80 ObjectId::Framebuffer(id) => (ioctl::DRM_MODE_OBJECT_FB, id.0),
81 ObjectId::Blob(id) => (ioctl::DRM_MODE_OBJECT_BLOB, id.0),
82 ObjectId::Plane(id) => (ioctl::DRM_MODE_OBJECT_PLANE, id.0),
83 }
84 }
85}
86
87impl From<CrtcId> for ObjectId {
88 fn from(value: CrtcId) -> Self {
89 Self::Crtc(value)
90 }
91}
92
93impl From<ConnectorId> for ObjectId {
94 fn from(value: ConnectorId) -> Self {
95 Self::Connector(value)
96 }
97}
98
99impl From<EncoderId> for ObjectId {
100 fn from(value: EncoderId) -> Self {
101 Self::Encoder(value)
102 }
103}
104
105impl From<PropertyId> for ObjectId {
106 fn from(value: PropertyId) -> Self {
107 Self::Property(value)
108 }
109}
110
111impl From<FramebufferId> for ObjectId {
112 fn from(value: FramebufferId) -> Self {
113 Self::Framebuffer(value)
114 }
115}
116
117impl From<BlobId> for ObjectId {
118 fn from(value: BlobId) -> Self {
119 Self::Blob(value)
120 }
121}
122
123impl From<PlaneId> for ObjectId {
124 fn from(value: PlaneId) -> Self {
125 Self::Plane(value)
126 }
127}
128
129#[derive(Debug)]
130pub struct CardResources {
131 pub fb_ids: Vec<FramebufferId>,
132 pub crtc_ids: Vec<CrtcId>,
133 pub connector_ids: Vec<ConnectorId>,
134 pub encoder_ids: Vec<EncoderId>,
135 pub plane_ids: Vec<PlaneId>,
136 pub min_width: u32,
137 pub max_width: u32,
138 pub min_height: u32,
139 pub max_height: u32,
140}
141
142#[derive(Debug)]
143pub struct ConnectorState {
144 pub id: ConnectorId,
145 pub current_encoder_id: EncoderId,
146 pub connector_type: ConnectorType,
147 pub connector_type_id: u32,
148 pub connection_state: ConnectionState,
149 pub width_mm: u32,
150 pub height_mm: u32,
151 pub subpixel_type: SubpixelType,
152 pub modes: Vec<ModeInfo>,
153 pub props: Vec<ModeProp>,
154 pub available_encoder_ids: Vec<u32>,
155}
156
157impl ConnectorState {
158 pub fn preferred_mode(&self) -> Option<&ModeInfo> {
159 for mode in &self.modes {
160 if (mode.typ & crate::ioctl::DRM_MODE_TYPE_PREFERRED) != 0 {
161 return Some(mode);
162 }
163 }
164 None
165 }
166}
167
168#[derive(Debug, PartialEq, Eq, Copy, Clone)]
169#[repr(u32)]
170pub enum ConnectionState {
171 Connected = 1,
172 Disconnected = 2,
173 Unknown = 3,
174}
175
176impl From<u32> for ConnectionState {
177 fn from(value: u32) -> Self {
178 match value {
179 1 => Self::Connected,
180 2 => Self::Disconnected,
181 _ => Self::Unknown,
182 }
183 }
184}
185
186#[derive(Debug, PartialEq, Eq, Clone, Copy)]
187#[repr(u32)]
188pub enum ConnectorType {
189 Unknown = 0,
190 Vga = 1,
191 DviI = 2,
192 DviD = 3,
193 DviA = 4,
194 Composite = 5,
195 SVideo = 6,
196 Lvds = 7,
197 Component = 8,
198 NinePinDin = 9,
199 DisplayPort = 10,
200 HdmiA = 11,
201 HdmiB = 12,
202 Tv = 13,
203 Edp = 14,
204 Virtual = 15,
205 Dsi = 16,
206 Dpi = 17,
207 Writeback = 18,
208 Spi = 19,
209 Usb = 20,
210 Other = !0, }
212
213impl From<u32> for ConnectorType {
214 #[inline]
215 fn from(value: u32) -> Self {
216 if value < 21 {
217 unsafe { core::mem::transmute(value) }
220 } else {
221 Self::Other
222 }
223 }
224}
225
226#[derive(Debug)]
227pub struct EncoderState {
228 pub encoder_id: EncoderId,
229 pub encoder_type: u32,
230 pub current_crtc_id: CrtcId,
231 pub possible_crtcs: u32,
232 pub possible_clones: u32,
233}
234
235#[derive(Debug)]
236pub struct CrtcState {
237 pub crtc_id: CrtcId,
238 pub fb_id: FramebufferId,
239 pub x: u32,
240 pub y: u32,
241 pub gamma_size: u32,
242 pub mode_valid: u32,
243 pub mode: ModeInfo,
244}
245
246impl From<crate::ioctl::DrmModeCrtc> for CrtcState {
247 fn from(value: crate::ioctl::DrmModeCrtc) -> Self {
248 Self {
249 crtc_id: CrtcId(value.crtc_id),
250 fb_id: FramebufferId(value.fb_id),
251 x: value.x,
252 y: value.y,
253 gamma_size: value.gamma_size,
254 mode_valid: value.mode_valid,
255 mode: value.mode.into(),
256 }
257 }
258}
259
260#[derive(Debug)]
261pub struct PlaneState {
262 pub id: PlaneId,
263 pub crtc_id: CrtcId,
264 pub fb_id: FramebufferId,
265 pub possible_crtcs: u32,
266 pub gamma_size: u32,
267}
268
269#[derive(Debug)]
270pub struct ModeInfo {
271 pub name: Vec<u8>,
272 pub clock: u32,
273 pub hdisplay: u16,
274 pub hsync_start: u16,
275 pub hsync_end: u16,
276 pub htotal: u16,
277 pub hskew: u16,
278 pub vdisplay: u16,
279 pub vsync_start: u16,
280 pub vsync_end: u16,
281 pub vtotal: u16,
282 pub vscan: u16,
283 pub vrefresh: u32,
284 pub flags: u32,
285 pub typ: u32,
286}
287
288impl From<crate::ioctl::DrmModeInfo> for ModeInfo {
289 fn from(value: crate::ioctl::DrmModeInfo) -> Self {
290 let name = value.name[..].split(|c| *c == 0).next().unwrap();
291 let name: &[u8] = unsafe { core::mem::transmute(name) };
292 Self {
293 name: name.to_vec(),
294 clock: value.clock,
295 hdisplay: value.hdisplay,
296 hsync_start: value.hsync_start,
297 hsync_end: value.hsync_end,
298 htotal: value.htotal,
299 hskew: value.hskew,
300 vdisplay: value.vdisplay,
301 vsync_start: value.vsync_start,
302 vsync_end: value.vsync_end,
303 vtotal: value.vtotal,
304 vscan: value.vscan,
305 vrefresh: value.vrefresh,
306 flags: value.flags,
307 typ: value.typ,
308 }
309 }
310}
311
312impl From<&ModeInfo> for crate::ioctl::DrmModeInfo {
313 fn from(value: &ModeInfo) -> Self {
314 let mut name_raw = [0_8; 32];
315 let name_len = core::cmp::min(name_raw.len() - 1, value.name.len());
316 let name_raw_slice = &mut name_raw[0..name_len];
317 name_raw_slice
318 .copy_from_slice(unsafe { core::mem::transmute(&value.name.as_slice()[0..name_len]) });
319 Self {
320 clock: value.clock,
321 hdisplay: value.hdisplay,
322 hsync_start: value.hsync_start,
323 hsync_end: value.hsync_end,
324 htotal: value.htotal,
325 hskew: value.hskew,
326 vdisplay: value.vdisplay,
327 vsync_start: value.vsync_start,
328 vsync_end: value.vsync_end,
329 vtotal: value.vtotal,
330 vscan: value.vscan,
331 vrefresh: value.vrefresh,
332 flags: value.flags,
333 typ: value.typ,
334 name: name_raw,
335 }
336 }
337}
338
339#[derive(Debug)]
340#[repr(u32)]
341pub enum SubpixelType {
342 Unknown = 1,
343 HorizontalRgb = 2,
344 HorizontalBgr = 3,
345 VerticalRgb = 4,
346 VerticalBgr = 5,
347 None = 6,
348}
349
350impl From<u32> for SubpixelType {
351 fn from(value: u32) -> Self {
352 match value {
353 2 => Self::HorizontalRgb,
354 3 => Self::HorizontalBgr,
355 4 => Self::VerticalRgb,
356 5 => Self::VerticalBgr,
357 _ => Self::Unknown,
358 }
359 }
360}
361
362#[derive(Debug)]
363#[repr(transparent)]
364pub struct PageFlipFlags(u32);
365
366impl PageFlipFlags {
367 pub const NONE: Self = Self(0);
368 pub const EVENT: Self = Self(crate::ioctl::DRM_MODE_PAGE_FLIP_EVENT);
369 pub const ASYNC: Self = Self(crate::ioctl::DRM_MODE_PAGE_FLIP_ASYNC);
370}
371
372impl BitOr for PageFlipFlags {
373 type Output = Self;
374
375 #[inline(always)]
376 fn bitor(self, rhs: Self) -> Self::Output {
377 Self(self.0 | rhs.0)
378 }
379}
380
381impl BitAnd for PageFlipFlags {
382 type Output = Self;
383
384 #[inline(always)]
385 fn bitand(self, rhs: Self) -> Self::Output {
386 Self(self.0 | rhs.0)
387 }
388}
389
390impl From<PageFlipFlags> for u32 {
391 #[inline(always)]
392 fn from(value: PageFlipFlags) -> Self {
393 value.0
394 }
395}