libamdgpu_top/
drm_mode.rs1use std::fmt::Write;
2use std::fs::File;
3use crate::{
4 LibDrm,
5 drmModePropType,
6 drmModeConnectorType,
7 drmModeConnection,
8 drmModeCrtc,
9 drmModeModeInfo,
10 drm_mode_property_enum,
11};
12use crate::DevicePath;
13
14#[derive(Debug, Clone)]
15pub struct ConnectorInfo {
16 pub connector_id: u32,
17 pub connector_type: drmModeConnectorType,
18 pub connector_type_id: u32,
19 pub connection: drmModeConnection,
20 pub mode_info: Vec<drmModeModeInfo>,
21 pub mode_props: Vec<(ModeProp, u64)>,
22 pub crtc: Option<drmModeCrtc>,
23}
24
25impl ConnectorInfo {
26 pub fn name(&self) -> String {
27 format!(
28 "Connector {} ({}-{}), {}",
29 self.connector_id,
30 self.connector_type,
31 self.connector_type_id,
32 self.connection,
33 )
34 }
35}
36
37#[derive(Debug, Clone)]
38pub struct ModeProp {
39 pub prop_type: drmModePropType,
40 pub prop_id: u32,
41 pub flags: u32,
42 pub name: String,
43 pub values: Vec<u64>,
44 pub enums: Vec<drm_mode_property_enum>,
45}
46
47impl ModeProp {
48 pub fn enums_string(&self) -> String {
49 let mut s = self.enums.iter().fold(String::new(), |mut s, enum_| {
50 let _ = write!(s, "{:?}={}, ", enum_.name(), enum_.value);
51 s
52 });
53 let len = s.len();
54 let _ = s.split_off(len-2);
55
56 s
57 }
58}
59
60pub fn connector_info(device_path: &DevicePath) -> Vec<ConnectorInfo> {
61 let Some(libdrm) = device_path.libdrm_amdgpu.clone().map(LibDrm::from) else {
62 return Vec::new();
63 };
64 let fd = {
65 use std::os::fd::IntoRawFd;
66
67 let Some(f) = File::open(&device_path.card).ok() else { return Vec::new() };
68
69 f.into_raw_fd()
70 };
71
72 libdrm.set_all_client_caps(fd);
73 let Some(drm_mode_res) = libdrm.get_drm_mode_resources(fd) else { return Vec::new() };
74 let current_connectors = drm_mode_res.get_drm_mode_all_connector_current(fd);
75
76 let conn_info: Vec<ConnectorInfo> = current_connectors.iter().filter_map(|conn| {
77 let connector_id = conn.connector_id();
78 let connector_type = conn.connector_type();
79 let connector_type_id = conn.connector_type_id();
80 let connection = conn.connection();
81
82 let conn_prop = conn.get_drm_mode_connector_properties(fd)?;
83 let mode_info = conn.get_modes();
84 let mode_props = conn_prop.get_mode_property(fd);
85
86 let mode_props: Vec<(ModeProp, u64)> = mode_props.iter().map(|(prop, value)| {
87 let prop_type = prop.property_type();
88 let flags = prop.flags();
89 let name = prop.name();
90 let prop_id = prop.prop_id();
91 let enums = prop.enums();
92 let values = prop.values();
93
94 let mode_prop = ModeProp {
95 prop_type,
96 prop_id,
97 flags,
98 name,
99 enums,
100 values,
101 };
102
103 (mode_prop, *value)
104 }).collect();
105
106 let crtc_id = mode_props
107 .iter()
108 .find(|prop| prop.0.name == "CRTC_ID")
109 .map(|prop| prop.1);
110
111 let crtc = if let Some(crtc_id) = crtc_id {
112 drm_mode_res
113 .get_drm_mode_all_crtcs(fd)
114 .iter()
115 .copied()
116 .find(|crtc| crtc.crtc_id as u64 == crtc_id)
117 } else {
118 None
119 };
120
121 Some(ConnectorInfo {
122 connector_id,
123 connector_type,
124 connector_type_id,
125 connection,
126 mode_info,
127 mode_props,
128 crtc,
129 })
130 }).collect();
131
132 conn_info
133}