rust_drm/
node.rs

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    /// # Examples
33    ///
34    /// DRM Node types:
35    ///
36    /// ```
37    /// let node_type = drm::DrmNodeType::from_minor_name("card0").unwrap();
38    /// assert_eq!(node_type, drm::DrmNodeType::Primary);
39    ///
40    /// let node_type = drm::DrmNodeType::from_minor_name("controlD128").unwrap();
41    /// assert_eq!(node_type, drm::DrmNodeType::Control);
42    ///
43    /// let node_type = drm::DrmNodeType::from_minor_name("renderD128").unwrap();
44    /// assert_eq!(node_type, drm::DrmNodeType::Render);
45    /// ```
46    ///
47    /// Unknown DRM Node type:
48    ///
49    /// ```
50    /// assert!(drm::DrmNodeType::from_minor_name("unknownD128").is_err());
51    /// ```
52    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}