linux_drm/modeset/
props.rs1use alloc::boxed::Box;
2use alloc::sync::Weak;
3use alloc::vec::Vec;
4
5use crate::ioctl::DrmCardDevice;
6
7use super::{ConnectorId, CrtcId, EncoderId, FramebufferId, PlaneId};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[repr(transparent)]
11pub struct PropertyId(pub u32);
12
13#[derive(Debug)]
14pub struct ModeProp {
15 pub prop_id: PropertyId,
16 pub value: u64,
17}
18
19#[derive(Debug)]
20#[non_exhaustive]
21#[repr(u32)]
22pub enum PropertyType {
23 Unknown = 0,
24 Range = crate::ioctl::DRM_MODE_PROP_RANGE,
25 Enum = crate::ioctl::DRM_MODE_PROP_ENUM,
26 Blob = crate::ioctl::DRM_MODE_PROP_BLOB,
27 Bitmask = crate::ioctl::DRM_MODE_PROP_BITMASK,
28 Object = crate::ioctl::DRM_MODE_PROP_OBJECT,
29 SignedRange = crate::ioctl::DRM_MODE_PROP_SIGNED_RANGE,
30}
31
32impl PropertyType {
33 pub fn from_raw_flags(flags: u32) -> (Self, bool) {
34 let immutable = (flags & crate::ioctl::DRM_MODE_PROP_IMMUTABLE) != 0;
35 let type_raw = flags
36 & (crate::ioctl::DRM_MODE_PROP_LEGACY_TYPE | crate::ioctl::DRM_MODE_PROP_EXTENDED_TYPE);
37 let typ = match type_raw {
38 crate::ioctl::DRM_MODE_PROP_RANGE => Self::Range,
39 crate::ioctl::DRM_MODE_PROP_ENUM => Self::Enum,
40 crate::ioctl::DRM_MODE_PROP_BLOB => Self::Blob,
41 crate::ioctl::DRM_MODE_PROP_BITMASK => Self::Bitmask,
42 crate::ioctl::DRM_MODE_PROP_OBJECT => Self::Object,
43 crate::ioctl::DRM_MODE_PROP_SIGNED_RANGE => Self::SignedRange,
44 _ => Self::Unknown,
45 };
46 (typ, immutable)
47 }
48}
49
50#[derive(Debug)]
51pub struct ObjectPropMeta<'card> {
52 pub(crate) raw: crate::ioctl::DrmModeGetProperty,
53 pub(crate) card: &'card crate::Card,
54}
55
56impl<'card> ObjectPropMeta<'card> {
57 #[inline(always)]
58 pub(crate) fn new(raw: crate::ioctl::DrmModeGetProperty, card: &'card crate::Card) -> Self {
59 Self { raw, card }
60 }
61
62 #[inline]
63 pub fn property_id(&self) -> PropertyId {
64 PropertyId(self.raw.prop_id)
65 }
66
67 pub fn name(&self) -> &str {
68 let raw = &self.raw.name[..];
69 let raw = raw.split(|c| *c == 0).next().unwrap();
70 let raw = unsafe { raw.as_ascii_unchecked() };
74 raw.as_str()
75 }
76
77 #[inline]
78 pub fn property_type(&self) -> PropertyType {
79 let (ret, _) = PropertyType::from_raw_flags(self.raw.flags);
80 ret
81 }
82
83 #[inline]
84 pub fn is_immutable(&self) -> bool {
85 let (_, immut) = PropertyType::from_raw_flags(self.raw.flags);
86 immut
87 }
88
89 #[inline]
90 pub fn is_mutable(&self) -> bool {
91 !self.is_immutable()
92 }
93
94 pub fn range(&self) -> Result<(u64, u64), crate::Error> {
101 const RANGE_TYPES: u32 =
102 crate::ioctl::DRM_MODE_PROP_RANGE | crate::ioctl::DRM_MODE_PROP_SIGNED_RANGE;
103 let is_range = (self.raw.flags & RANGE_TYPES) != 0;
104 if !is_range {
105 return Err(crate::Error::NotSupported);
106 }
107 if self.raw.count_values() != 2 {
109 return Err(crate::Error::RemoteFailure);
110 }
111
112 let mut pair = [0_u64; 2];
113
114 let mut tmp = crate::ioctl::DrmModeGetProperty::zeroed();
115 tmp.prop_id = self.raw.prop_id;
116 unsafe { tmp.set_values_ptr(&mut pair as *mut u64, 2) };
117 self.card
118 .ioctl(crate::ioctl::DRM_IOCTL_MODE_GETPROPERTY, &mut tmp)
119 .unwrap();
120
121 if tmp.count_values() != 2 {
122 return Err(crate::Error::RemoteFailure);
124 }
125
126 Ok((pair[0], pair[1]))
127 }
128
129 pub fn values(&self) -> Result<Vec<u64>, crate::Error> {
143 let mut count = self.raw.count_values() as usize;
144 if count == 0 {
145 return Ok(Vec::new());
146 }
147 loop {
148 let mut values = crate::vec_with_capacity::<u64>(count)?;
149
150 let mut tmp = crate::ioctl::DrmModeGetProperty::zeroed();
151 tmp.prop_id = self.raw.prop_id;
152 unsafe { tmp.set_values_ptr(values.as_mut_ptr(), count as u32) };
153
154 self.card
155 .ioctl(crate::ioctl::DRM_IOCTL_MODE_GETPROPERTY, &mut tmp)
156 .unwrap();
157
158 let new_count = tmp.count_values() as usize;
159 if new_count != count {
160 count = new_count;
161 continue;
162 }
163
164 unsafe {
167 values.set_len(count);
168 }
169 return Ok(values);
170 }
171 }
172
173 pub fn enum_members(&self) -> Result<Vec<ObjectPropEnumMember>, crate::Error> {
176 const ENUM_TYPES: u32 =
177 crate::ioctl::DRM_MODE_PROP_ENUM | crate::ioctl::DRM_MODE_PROP_BITMASK;
178 let is_enum = (self.raw.flags & ENUM_TYPES) != 0;
179 if !is_enum {
180 return Ok(Vec::new());
181 }
182
183 let mut count = self.raw.count_enum_blobs() as usize;
184 loop {
185 let mut members = crate::vec_with_capacity::<ObjectPropEnumMember>(count)?;
189
190 let mut tmp = crate::ioctl::DrmModeGetProperty::zeroed();
191 tmp.prop_id = self.raw.prop_id;
192 unsafe {
193 tmp.set_enum_blob_ptr(
194 members.as_mut_ptr() as *mut crate::ioctl::DrmModePropertyEnum,
195 count as u32,
196 )
197 };
198
199 self.card
200 .ioctl(crate::ioctl::DRM_IOCTL_MODE_GETPROPERTY, &mut tmp)
201 .unwrap();
202
203 let new_count = tmp.count_enum_blobs() as usize;
204 if new_count != count {
205 count = new_count;
206 continue;
207 }
208
209 unsafe {
212 members.set_len(count);
213 }
214 return Ok(members);
215 }
216 }
217}
218
219#[derive(Debug)]
220#[repr(transparent)]
221pub struct ObjectPropEnumMember {
222 raw: crate::ioctl::DrmModePropertyEnum,
223}
224
225impl ObjectPropEnumMember {
226 #[inline]
227 pub fn value(&self) -> u64 {
228 self.raw.value
229 }
230
231 pub fn name(&self) -> &str {
232 let raw = &self.raw.name[..];
233 let raw = raw.split(|c| *c == 0).next().unwrap();
234 let raw = raw.as_ascii().unwrap();
238 raw.as_str()
239 }
240}
241
242pub trait AsRawPropertyValue {
249 fn as_raw_property_value(&self) -> u64;
250}
251
252pub trait IntoRawPropertyValue: AsRawPropertyValue {
259 fn into_raw_property_value(self) -> (u64, Option<Box<dyn core::any::Any>>);
266}
267
268macro_rules! trivial_as_property_value {
269 ($t:ty) => {
270 impl AsRawPropertyValue for $t {
271 #[inline(always)]
272 fn as_raw_property_value(&self) -> u64 {
273 *self as u64
274 }
275 }
276 impl IntoRawPropertyValue for $t {
277 #[inline(always)]
278 fn into_raw_property_value(self) -> (u64, Option<Box<dyn core::any::Any>>) {
279 (self as u64, None)
280 }
281 }
282 };
283}
284
285trivial_as_property_value!(u64);
286trivial_as_property_value!(u32);
287trivial_as_property_value!(u16);
288trivial_as_property_value!(u8);
289trivial_as_property_value!(usize);
290trivial_as_property_value!(i64);
291trivial_as_property_value!(i32);
292trivial_as_property_value!(i16);
293trivial_as_property_value!(i8);
294trivial_as_property_value!(isize);
295trivial_as_property_value!(bool);
296
297macro_rules! id_as_property_value {
298 ($t:ty) => {
299 impl AsRawPropertyValue for $t {
300 #[inline(always)]
301 fn as_raw_property_value(&self) -> u64 {
302 self.0 as u64
303 }
304 }
305 impl IntoRawPropertyValue for $t {
306 #[inline(always)]
307 fn into_raw_property_value(self) -> (u64, Option<Box<dyn core::any::Any>>) {
308 (self.0 as u64, None)
309 }
310 }
311 };
312}
313
314id_as_property_value!(CrtcId);
315id_as_property_value!(ConnectorId);
316id_as_property_value!(FramebufferId);
317id_as_property_value!(BlobId);
318id_as_property_value!(EncoderId);
319id_as_property_value!(PlaneId);
320
321#[derive(Debug, Clone, Copy, PartialEq, Eq)]
322#[repr(transparent)]
323pub struct BlobId(pub u32);
324
325#[derive(Debug)]
329pub struct BlobHandle {
330 pub(crate) id: Option<u32>,
331 pub(crate) f: Weak<linux_io::File<DrmCardDevice>>,
332}
333
334impl<'card> BlobHandle {
335 #[inline(always)]
336 pub const fn id(&self) -> u32 {
337 let Some(ret) = self.id else {
338 unreachable!();
339 };
340 ret
341 }
342
343 #[inline(always)]
345 pub fn destroy(mut self) -> Result<(), crate::result::Error> {
346 self.destroy_internal()
347 }
348
349 #[inline]
350 fn destroy_internal(&mut self) -> Result<(), crate::result::Error> {
351 if let Some(f) = self.f.upgrade() {
352 if let Some(blob_id) = self.id.take() {
353 let mut tmp = crate::ioctl::DrmModeDestroyBlob { blob_id };
354 crate::drm_ioctl(&f, crate::ioctl::DRM_IOCTL_MODE_DESTROYPROPBLOB, &mut tmp)?;
355 }
356 }
357 Ok(())
358 }
359}
360
361impl Drop for BlobHandle {
362 #[inline(always)]
363 fn drop(&mut self) {
364 let _ = self.destroy_internal();
365 }
366}
367
368impl AsRawPropertyValue for BlobHandle {
369 fn as_raw_property_value(&self) -> u64 {
370 self.id() as u64
371 }
372}
373
374impl IntoRawPropertyValue for BlobHandle {
375 fn into_raw_property_value(self) -> (u64, Option<Box<dyn core::any::Any>>) {
376 (self.id() as u64, Some(Box::new(self)))
377 }
378}