1use crate::control::{RawResourceHandle, ResourceHandle};
15use drm_ffi as ffi;
16
17pub type RawValue = u64;
19
20#[repr(transparent)]
22#[derive(Copy, Clone, Hash, PartialEq, Eq)]
23pub struct Handle(RawResourceHandle);
24
25unsafe impl bytemuck::ZeroableInOption for Handle {}
27unsafe impl bytemuck::PodInOption for Handle {}
28
29impl From<Handle> for RawResourceHandle {
30 fn from(handle: Handle) -> Self {
31 handle.0
32 }
33}
34
35impl From<Handle> for u32 {
36 fn from(handle: Handle) -> Self {
37 handle.0.into()
38 }
39}
40
41impl From<RawResourceHandle> for Handle {
42 fn from(handle: RawResourceHandle) -> Self {
43 Handle(handle)
44 }
45}
46
47impl ResourceHandle for Handle {
48 const FFI_TYPE: u32 = ffi::DRM_MODE_OBJECT_PROPERTY;
49}
50
51impl std::fmt::Debug for Handle {
52 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
53 f.debug_tuple("property::Handle").field(&self.0).finish()
54 }
55}
56
57#[derive(Debug, Clone, Hash, PartialEq, Eq)]
59pub struct Info {
60 pub(crate) handle: Handle,
61 pub(crate) val_type: ValueType,
62 pub(crate) mutable: bool,
63 pub(crate) atomic: bool,
64 pub(crate) info: ffi::drm_mode_get_property,
65}
66
67impl Info {
68 pub fn handle(&self) -> Handle {
70 self.handle
71 }
72
73 pub fn name(&self) -> &std::ffi::CStr {
75 unsafe { std::ffi::CStr::from_ptr(&self.info.name[0] as _) }
76 }
77
78 pub fn value_type(&self) -> ValueType {
80 self.val_type.clone()
81 }
82
83 pub fn mutable(&self) -> bool {
85 self.mutable
86 }
87
88 pub fn atomic(&self) -> bool {
90 self.atomic
91 }
92}
93
94#[allow(clippy::upper_case_acronyms)]
96#[allow(clippy::large_enum_variant)]
97#[derive(Debug, Clone, Hash, PartialEq, Eq)]
98pub enum ValueType {
99 Unknown,
101 Boolean,
103 UnsignedRange(u64, u64),
105 SignedRange(i64, i64),
107 Enum(EnumValues),
109 Bitmask,
111 Blob,
113 Object,
115 CRTC,
117 Connector,
119 Encoder,
121 Framebuffer,
123 Plane,
125 Property,
127}
128
129impl ValueType {
130 pub fn convert_value(&self, value: RawValue) -> Value {
132 match self {
133 ValueType::Unknown => Value::Unknown(value),
134 ValueType::Boolean => Value::Boolean(value != 0),
135 ValueType::UnsignedRange(_, _) => Value::UnsignedRange(value),
136 ValueType::SignedRange(_, _) => Value::SignedRange(value as i64),
137 ValueType::Enum(values) => Value::Enum(values.get_value_from_raw_value(value)),
138 ValueType::Bitmask => Value::Bitmask(value),
139 ValueType::Blob => Value::Blob(value),
140 ValueType::Object => Value::Object(bytemuck::cast(value as u32)),
141 ValueType::CRTC => Value::CRTC(bytemuck::cast(value as u32)),
142 ValueType::Connector => Value::Connector(bytemuck::cast(value as u32)),
143 ValueType::Encoder => Value::Encoder(bytemuck::cast(value as u32)),
144 ValueType::Framebuffer => Value::Framebuffer(bytemuck::cast(value as u32)),
145 ValueType::Plane => Value::Plane(bytemuck::cast(value as u32)),
146 ValueType::Property => Value::Property(bytemuck::cast(value as u32)),
147 }
148 }
149}
150
151#[allow(missing_docs)]
153#[allow(clippy::upper_case_acronyms)]
154#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
155pub enum Value<'a> {
156 Unknown(RawValue),
158 Boolean(bool),
160 UnsignedRange(u64),
162 SignedRange(i64),
164 Enum(Option<&'a EnumValue>),
166 Bitmask(u64),
168 Blob(u64),
170 Object(Option<RawResourceHandle>),
172 CRTC(Option<super::crtc::Handle>),
174 Connector(Option<super::connector::Handle>),
176 Encoder(Option<super::encoder::Handle>),
178 Framebuffer(Option<super::framebuffer::Handle>),
180 Plane(Option<super::plane::Handle>),
182 Property(Option<Handle>),
184}
185
186impl<'a> From<Value<'a>> for RawValue {
187 fn from(value: Value<'a>) -> Self {
188 match value {
189 Value::Unknown(x) => x,
190 Value::Boolean(true) => 1,
191 Value::Boolean(false) => 0,
192 Value::UnsignedRange(x) => x,
193 Value::SignedRange(x) => x as u64,
194 Value::Enum(val) => val.map_or(0, EnumValue::value),
195 Value::Bitmask(x) => x,
196 Value::Blob(x) => x,
197 Value::Object(x) => bytemuck::cast::<_, u32>(x) as u64,
198 Value::CRTC(x) => bytemuck::cast::<_, u32>(x) as u64,
199 Value::Connector(x) => bytemuck::cast::<_, u32>(x) as u64,
200 Value::Encoder(x) => bytemuck::cast::<_, u32>(x) as u64,
201 Value::Framebuffer(x) => bytemuck::cast::<_, u32>(x) as u64,
202 Value::Plane(x) => bytemuck::cast::<_, u32>(x) as u64,
203 Value::Property(x) => bytemuck::cast::<_, u32>(x) as u64,
204 }
205 }
206}
207
208macro_rules! match_variant {
209 ($this:ident, $variant:ident) => {
210 if let Self::$variant(v) = *$this {
211 Some(v)
212 } else {
213 None
214 }
215 };
216}
217
218impl<'a> Value<'a> {
219 pub fn as_boolean(&self) -> Option<bool> {
221 match_variant!(self, Boolean)
222 }
223
224 pub fn as_unsigned_range(&self) -> Option<u64> {
226 match_variant!(self, UnsignedRange)
227 }
228
229 pub fn as_signed_range(&self) -> Option<i64> {
231 match_variant!(self, SignedRange)
232 }
233
234 pub fn as_enum(&self) -> Option<&'a EnumValue> {
236 match_variant!(self, Enum).flatten()
237 }
238
239 pub fn as_bitmask(&self) -> Option<u64> {
241 match_variant!(self, Bitmask)
242 }
243
244 pub fn as_blob(&self) -> Option<u64> {
246 match_variant!(self, Blob)
247 }
248
249 pub fn as_object(&self) -> Option<RawResourceHandle> {
251 match_variant!(self, Object).flatten()
252 }
253
254 pub fn as_crtc(&self) -> Option<super::crtc::Handle> {
256 match_variant!(self, CRTC).flatten()
257 }
258
259 pub fn as_connector(&self) -> Option<super::connector::Handle> {
261 match_variant!(self, Connector).flatten()
262 }
263
264 pub fn as_encoder(&self) -> Option<super::encoder::Handle> {
266 match_variant!(self, Encoder).flatten()
267 }
268
269 pub fn as_framebuffer(&self) -> Option<super::framebuffer::Handle> {
271 match_variant!(self, Framebuffer).flatten()
272 }
273
274 pub fn as_plane(&self) -> Option<super::plane::Handle> {
276 match_variant!(self, Plane).flatten()
277 }
278
279 pub fn as_property(&self) -> Option<Handle> {
281 match_variant!(self, Property).flatten()
282 }
283}
284
285#[repr(transparent)]
287#[derive(Copy, Clone, Hash, PartialEq, Eq, bytemuck::TransparentWrapper)]
288pub struct EnumValue(ffi::drm_mode_property_enum);
289
290impl EnumValue {
291 pub fn value(&self) -> RawValue {
293 self.0.value
294 }
295
296 pub fn name(&self) -> &std::ffi::CStr {
298 unsafe { std::ffi::CStr::from_ptr(&self.0.name[0] as _) }
299 }
300}
301
302impl From<ffi::drm_mode_property_enum> for EnumValue {
303 fn from(inner: ffi::drm_mode_property_enum) -> Self {
304 EnumValue(inner)
305 }
306}
307
308impl std::fmt::Debug for EnumValue {
309 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
310 f.debug_struct("EnumValue")
311 .field("value", &self.value())
312 .field("name", &self.name())
313 .finish()
314 }
315}
316
317#[derive(Debug, Clone, Hash, PartialEq, Eq)]
319pub struct EnumValues {
320 pub(crate) values: Vec<u64>,
321 pub(crate) enums: Vec<EnumValue>,
322}
323
324impl EnumValues {
325 pub fn values(&self) -> (&[RawValue], &[EnumValue]) {
327 (&self.values, &self.enums)
328 }
329
330 pub fn get_value_from_raw_value(&self, value: RawValue) -> Option<&EnumValue> {
333 let (values, enums) = self.values();
334 let index = if values.get(value as usize) == Some(&value) {
335 value as usize
337 } else {
338 values.iter().position(|&v| v == value)?
339 };
340 Some(&enums[index])
341 }
342}