1use crate::core::Result;
2
3use std::os::linux::fs::MetadataExt;
4use std::path::Path;
5
6static DRM_DIR_NAME: &str = "/dev/dri";
7
8static DRM_PRIMARY_MINOR_NAME: &str = "card";
9static DRM_CONTROL_MINOR_NAME: &str = "controlD";
10static DRM_RENDER_MINOR_NAME: &str = "renderD";
11
12fn major(dev: u64) -> u64 {
13 let mut major = (dev & 0x00000000000fff00) >> 8;
14 major |= (dev & 0xfffff00000000000) >> 32;
15 major
16}
17
18fn minor(dev: u64) -> u64 {
19 let mut minor = (dev & 0x00000000000000ff) >> 0;
20 minor |= (dev & 0x00000ffffff00000) >> 12;
21 minor
22}
23
24#[derive(Debug, PartialEq)]
25pub enum DrmNodeType {
26 Primary = 0,
27 Control = 1,
28 Render = 2,
29}
30
31impl DrmNodeType {
32 pub fn from_minor_name(name: &str) -> Result<DrmNodeType> {
53 match name {
54 s if s.starts_with(DRM_PRIMARY_MINOR_NAME) => Ok(DrmNodeType::Primary),
55 s if s.starts_with(DRM_CONTROL_MINOR_NAME) => Ok(DrmNodeType::Control),
56 s if s.starts_with(DRM_RENDER_MINOR_NAME) => Ok(DrmNodeType::Render),
57 _ => Err(format!("Could not match {} to DRM Node Type", name))?,
58 }
59 }
60}
61
62pub struct DrmNode {
63 major: u64,
64 minor: u64,
65}
66
67impl DrmNode {
68 pub fn from_device_name(device_name: &str) -> Result<DrmNode> {
69 let node_path = Path::new(DRM_DIR_NAME).join(device_name);
70 let meta = std::fs::metadata(node_path)?;
71 let st_rdev = meta.st_rdev();
72
73 Ok(DrmNode {
74 major: major(st_rdev),
75 minor: minor(st_rdev),
76 })
77 }
78
79 pub fn device_dir_exists(&self) -> bool {
80 let drm_device_dir_name = format!("/sys/dev/char/{}:{}/device/drm", self.major, self.minor);
81 let drm_device_path = Path::new(&drm_device_dir_name);
82 drm_device_path.exists() && drm_device_path.is_dir()
83 }
84
85 pub fn get_device_path(&self) -> std::path::PathBuf {
86 let drm_device_dir_name = format!("/sys/dev/char/{}:{}/device", self.major, self.minor);
87 Path::new(&drm_device_dir_name).canonicalize().unwrap()
88 }
89
90 pub fn get_subsystem_path(&self) -> std::path::PathBuf {
91 let drm_device_dir_name = format!(
92 "/sys/dev/char/{}:{}/device/subsystem",
93 self.major, self.minor
94 );
95 Path::new(&drm_device_dir_name).canonicalize().unwrap()
96 }
97}