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
9use crate::control;
10use drm_ffi as ffi;
11
12/// A handle to a connector
13#[repr(transparent)]
14#[derive(Copy, Clone, Hash, PartialEq, Eq)]
15pub struct Handle(control::RawResourceHandle);
16
17// Safety: Handle is repr(transparent) over NonZeroU32
18unsafe impl bytemuck::ZeroableInOption for Handle {}
19unsafe impl bytemuck::PodInOption for Handle {}
20
21impl From<Handle> for control::RawResourceHandle {
22 fn from(handle: Handle) -> Self {
23 handle.0
24 }
25}
26
27impl From<Handle> for u32 {
28 fn from(handle: Handle) -> Self {
29 handle.0.into()
30 }
31}
32
33impl From<control::RawResourceHandle> for Handle {
34 fn from(handle: control::RawResourceHandle) -> Self {
35 Handle(handle)
36 }
37}
38
39impl control::ResourceHandle for Handle {
40 const FFI_TYPE: u32 = ffi::DRM_MODE_OBJECT_CONNECTOR;
41}
42
43impl 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)]
51pub 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
63impl 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
69impl 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)]
124pub 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
148impl 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
178impl 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
207impl 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)]
238pub enum State {
239 Connected,
240 Disconnected,
241 Unknown,
242}
243
244impl 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
256impl 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)]
271pub 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
288impl 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