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