1 | //! # Connector |
2 | //! |
3 | //! Represents the physical output, such as a DisplayPort or VGA connector. |
4 | //! |
5 | //! A Connector is the physical connection between the display controller and |
6 | //! a display. These objects keep track of connection information and state, |
7 | //! including the modes that the current display supports. |
8 | |
9 | use crate::control; |
10 | use drm_ffi as ffi; |
11 | |
12 | /// A handle to a connector |
13 | #[repr (transparent)] |
14 | #[derive (Copy, Clone, Hash, PartialEq, Eq)] |
15 | pub struct Handle(control::RawResourceHandle); |
16 | |
17 | // Safety: Handle is repr(transparent) over NonZeroU32 |
18 | unsafe impl bytemuck::ZeroableInOption for Handle {} |
19 | unsafe impl bytemuck::PodInOption for Handle {} |
20 | |
21 | impl From<Handle> for control::RawResourceHandle { |
22 | fn from(handle: Handle) -> Self { |
23 | handle.0 |
24 | } |
25 | } |
26 | |
27 | impl From<Handle> for u32 { |
28 | fn from(handle: Handle) -> Self { |
29 | handle.0.into() |
30 | } |
31 | } |
32 | |
33 | impl From<control::RawResourceHandle> for Handle { |
34 | fn from(handle: control::RawResourceHandle) -> Self { |
35 | Handle(handle) |
36 | } |
37 | } |
38 | |
39 | impl control::ResourceHandle for Handle { |
40 | const FFI_TYPE: u32 = ffi::DRM_MODE_OBJECT_CONNECTOR; |
41 | } |
42 | |
43 | impl std::fmt::Debug for Handle { |
44 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
45 | f.debug_tuple(name:"connector::Handle" ).field(&self.0).finish() |
46 | } |
47 | } |
48 | |
49 | /// Information about a connector |
50 | #[derive (Debug, Clone, Hash, PartialEq, Eq)] |
51 | pub struct Info { |
52 | pub(crate) handle: Handle, |
53 | pub(crate) interface: Interface, |
54 | pub(crate) interface_id: u32, |
55 | pub(crate) connection: State, |
56 | pub(crate) size: Option<(u32, u32)>, |
57 | pub(crate) modes: Vec<control::Mode>, |
58 | pub(crate) encoders: Vec<control::encoder::Handle>, |
59 | pub(crate) curr_enc: Option<control::encoder::Handle>, |
60 | pub(crate) subpixel: SubPixel, |
61 | } |
62 | |
63 | impl std::fmt::Display for Info { |
64 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
65 | write!(f, " {}- {}" , self.interface.as_str(), self.interface_id) |
66 | } |
67 | } |
68 | |
69 | impl Info { |
70 | /// Returns the handle to this connector. |
71 | pub fn handle(&self) -> Handle { |
72 | self.handle |
73 | } |
74 | |
75 | /// Returns the type of `Interface` of this connector. |
76 | pub fn interface(&self) -> Interface { |
77 | self.interface |
78 | } |
79 | |
80 | /// Returns the interface ID of this connector. |
81 | /// |
82 | /// When multiple connectors have the same `Interface`, they will have |
83 | /// different interface IDs. |
84 | pub fn interface_id(&self) -> u32 { |
85 | self.interface_id |
86 | } |
87 | |
88 | /// Returns the `State` of this connector. |
89 | pub fn state(&self) -> State { |
90 | self.connection |
91 | } |
92 | |
93 | /// Returns the size of the display (in millimeters) if connected. |
94 | pub fn size(&self) -> Option<(u32, u32)> { |
95 | self.size |
96 | } |
97 | |
98 | /// Returns a list of encoders that can be possibly used by this connector. |
99 | pub fn encoders(&self) -> &[control::encoder::Handle] { |
100 | &self.encoders |
101 | } |
102 | |
103 | /// Returns a list of modes this connector reports as supported. |
104 | pub fn modes(&self) -> &[control::Mode] { |
105 | &self.modes |
106 | } |
107 | |
108 | /// Returns the current encoder attached to this connector. |
109 | pub fn current_encoder(&self) -> Option<control::encoder::Handle> { |
110 | self.curr_enc |
111 | } |
112 | |
113 | /// Subpixel order of the connected sink |
114 | pub fn subpixel(&self) -> SubPixel { |
115 | self.subpixel |
116 | } |
117 | } |
118 | |
119 | /// A physical interface type. |
120 | #[allow (missing_docs)] |
121 | #[allow (clippy::upper_case_acronyms)] |
122 | #[non_exhaustive ] |
123 | #[derive (Debug, Copy, Clone, Hash, PartialEq, Eq)] |
124 | pub enum Interface { |
125 | Unknown, |
126 | VGA, |
127 | DVII, |
128 | DVID, |
129 | DVIA, |
130 | Composite, |
131 | SVideo, |
132 | LVDS, |
133 | Component, |
134 | NinePinDIN, |
135 | DisplayPort, |
136 | HDMIA, |
137 | HDMIB, |
138 | TV, |
139 | EmbeddedDisplayPort, |
140 | Virtual, |
141 | DSI, |
142 | DPI, |
143 | Writeback, |
144 | SPI, |
145 | USB, |
146 | } |
147 | |
148 | impl Interface { |
149 | /// Get interface name as string |
150 | pub fn as_str(&self) -> &'static str { |
151 | // source: https://github.com/torvalds/linux/blob/489fa31ea873282b41046d412ec741f93946fc2d/drivers/gpu/drm/drm_connector.c#L89 |
152 | match self { |
153 | Interface::Unknown => "Unknown" , |
154 | Interface::VGA => "VGA" , |
155 | Interface::DVII => "DVI-I" , |
156 | Interface::DVID => "DVI-D" , |
157 | Interface::DVIA => "DVI-A" , |
158 | Interface::Composite => "Composite" , |
159 | Interface::SVideo => "SVIDEO" , |
160 | Interface::LVDS => "LVDS" , |
161 | Interface::Component => "Component" , |
162 | Interface::NinePinDIN => "DIN" , |
163 | Interface::DisplayPort => "DP" , |
164 | Interface::HDMIA => "HDMI-A" , |
165 | Interface::HDMIB => "HDMI-B" , |
166 | Interface::TV => "TV" , |
167 | Interface::EmbeddedDisplayPort => "eDP" , |
168 | Interface::Virtual => "Virtual" , |
169 | Interface::DSI => "DSI" , |
170 | Interface::DPI => "DPI" , |
171 | Interface::Writeback => "Writeback" , |
172 | Interface::SPI => "SPI" , |
173 | Interface::USB => "USB" , |
174 | } |
175 | } |
176 | } |
177 | |
178 | impl From<u32> for Interface { |
179 | fn from(n: u32) -> Self { |
180 | match n { |
181 | ffi::DRM_MODE_CONNECTOR_Unknown => Interface::Unknown, |
182 | ffi::DRM_MODE_CONNECTOR_VGA => Interface::VGA, |
183 | ffi::DRM_MODE_CONNECTOR_DVII => Interface::DVII, |
184 | ffi::DRM_MODE_CONNECTOR_DVID => Interface::DVID, |
185 | ffi::DRM_MODE_CONNECTOR_DVIA => Interface::DVIA, |
186 | ffi::DRM_MODE_CONNECTOR_Composite => Interface::Composite, |
187 | ffi::DRM_MODE_CONNECTOR_SVIDEO => Interface::SVideo, |
188 | ffi::DRM_MODE_CONNECTOR_LVDS => Interface::LVDS, |
189 | ffi::DRM_MODE_CONNECTOR_Component => Interface::Component, |
190 | ffi::DRM_MODE_CONNECTOR_9PinDIN => Interface::NinePinDIN, |
191 | ffi::DRM_MODE_CONNECTOR_DisplayPort => Interface::DisplayPort, |
192 | ffi::DRM_MODE_CONNECTOR_HDMIA => Interface::HDMIA, |
193 | ffi::DRM_MODE_CONNECTOR_HDMIB => Interface::HDMIB, |
194 | ffi::DRM_MODE_CONNECTOR_TV => Interface::TV, |
195 | ffi::DRM_MODE_CONNECTOR_eDP => Interface::EmbeddedDisplayPort, |
196 | ffi::DRM_MODE_CONNECTOR_VIRTUAL => Interface::Virtual, |
197 | ffi::DRM_MODE_CONNECTOR_DSI => Interface::DSI, |
198 | ffi::DRM_MODE_CONNECTOR_DPI => Interface::DPI, |
199 | ffi::DRM_MODE_CONNECTOR_WRITEBACK => Interface::Writeback, |
200 | ffi::DRM_MODE_CONNECTOR_SPI => Interface::SPI, |
201 | ffi::DRM_MODE_CONNECTOR_USB => Interface::USB, |
202 | _ => Interface::Unknown, |
203 | } |
204 | } |
205 | } |
206 | |
207 | impl From<Interface> for u32 { |
208 | fn from(interface: Interface) -> Self { |
209 | match interface { |
210 | Interface::Unknown => ffi::DRM_MODE_CONNECTOR_Unknown, |
211 | Interface::VGA => ffi::DRM_MODE_CONNECTOR_VGA, |
212 | Interface::DVII => ffi::DRM_MODE_CONNECTOR_DVII, |
213 | Interface::DVID => ffi::DRM_MODE_CONNECTOR_DVID, |
214 | Interface::DVIA => ffi::DRM_MODE_CONNECTOR_DVIA, |
215 | Interface::Composite => ffi::DRM_MODE_CONNECTOR_Composite, |
216 | Interface::SVideo => ffi::DRM_MODE_CONNECTOR_SVIDEO, |
217 | Interface::LVDS => ffi::DRM_MODE_CONNECTOR_LVDS, |
218 | Interface::Component => ffi::DRM_MODE_CONNECTOR_Component, |
219 | Interface::NinePinDIN => ffi::DRM_MODE_CONNECTOR_9PinDIN, |
220 | Interface::DisplayPort => ffi::DRM_MODE_CONNECTOR_DisplayPort, |
221 | Interface::HDMIA => ffi::DRM_MODE_CONNECTOR_HDMIA, |
222 | Interface::HDMIB => ffi::DRM_MODE_CONNECTOR_HDMIB, |
223 | Interface::TV => ffi::DRM_MODE_CONNECTOR_TV, |
224 | Interface::EmbeddedDisplayPort => ffi::DRM_MODE_CONNECTOR_eDP, |
225 | Interface::Virtual => ffi::DRM_MODE_CONNECTOR_VIRTUAL, |
226 | Interface::DSI => ffi::DRM_MODE_CONNECTOR_DSI, |
227 | Interface::DPI => ffi::DRM_MODE_CONNECTOR_DPI, |
228 | Interface::Writeback => ffi::DRM_MODE_CONNECTOR_WRITEBACK, |
229 | Interface::SPI => ffi::DRM_MODE_CONNECTOR_SPI, |
230 | Interface::USB => ffi::DRM_MODE_CONNECTOR_USB, |
231 | } |
232 | } |
233 | } |
234 | |
235 | /// The state of a connector. |
236 | #[allow (missing_docs)] |
237 | #[derive (Debug, Copy, Clone, Hash, PartialEq, Eq)] |
238 | pub enum State { |
239 | Connected, |
240 | Disconnected, |
241 | Unknown, |
242 | } |
243 | |
244 | impl From<u32> for State { |
245 | fn from(n: u32) -> Self { |
246 | // These variables are not defined in drm_mode.h for some reason. |
247 | // They were copied from libdrm's xf86DrmMode.h |
248 | match n { |
249 | 1 => State::Connected, |
250 | 2 => State::Disconnected, |
251 | _ => State::Unknown, |
252 | } |
253 | } |
254 | } |
255 | |
256 | impl From<State> for u32 { |
257 | fn from(state: State) -> Self { |
258 | // These variables are not defined in drm_mode.h for some reason. |
259 | // They were copied from libdrm's xf86DrmMode.h |
260 | match state { |
261 | State::Connected => 1, |
262 | State::Disconnected => 2, |
263 | State::Unknown => 3, |
264 | } |
265 | } |
266 | } |
267 | |
268 | /// Subpixel order of the connected sink |
269 | #[non_exhaustive ] |
270 | #[derive (Debug, Copy, Clone, Hash, PartialEq, Eq)] |
271 | pub enum SubPixel { |
272 | /// Unknown geometry |
273 | Unknown, |
274 | /// Horizontal RGB |
275 | HorizontalRgb, |
276 | /// Horizontal BGR |
277 | HorizontalBgr, |
278 | /// Vertical RGB |
279 | VerticalRgb, |
280 | /// Vertical BGR |
281 | VerticalBgr, |
282 | /// No geometry |
283 | None, |
284 | /// Encountered value not supported by drm-rs |
285 | NotImplemented, |
286 | } |
287 | |
288 | impl SubPixel { |
289 | pub(super) fn from_raw(n: u32) -> Self { |
290 | // These values are not defined in drm_mode.h |
291 | // They were copied from linux's drm_connector.h |
292 | // Don't mistake those for ones used in xf86DrmMode.h (libdrm offsets those by 1) |
293 | match n { |
294 | 0 => Self::Unknown, |
295 | 1 => Self::HorizontalRgb, |
296 | 2 => Self::HorizontalBgr, |
297 | 3 => Self::VerticalRgb, |
298 | 4 => Self::VerticalBgr, |
299 | 5 => Self::None, |
300 | _ => Self::NotImplemented, |
301 | } |
302 | } |
303 | } |
304 | |