drm/control/
connector.rs

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("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 Info {
64    /// Returns the handle to this connector.
65    pub fn handle(&self) -> Handle {
66        self.handle
67    }
68
69    /// Returns the type of `Interface` of this connector.
70    pub fn interface(&self) -> Interface {
71        self.interface
72    }
73
74    /// Returns the interface ID of this connector.
75    ///
76    /// When multiple connectors have the same `Interface`, they will have
77    /// different interface IDs.
78    pub fn interface_id(&self) -> u32 {
79        self.interface_id
80    }
81
82    /// Returns the `State` of this connector.
83    pub fn state(&self) -> State {
84        self.connection
85    }
86
87    /// Returns the size of the display (in millimeters) if connected.
88    pub fn size(&self) -> Option<(u32, u32)> {
89        self.size
90    }
91
92    /// Returns a list of encoders that can be possibly used by this connector.
93    pub fn encoders(&self) -> &[control::encoder::Handle] {
94        &self.encoders
95    }
96
97    /// Returns a list of modes this connector reports as supported.
98    pub fn modes(&self) -> &[control::Mode] {
99        &self.modes
100    }
101
102    /// Returns the current encoder attached to this connector.
103    pub fn current_encoder(&self) -> Option<control::encoder::Handle> {
104        self.curr_enc
105    }
106
107    /// Subpixel order of the connected sink
108    pub fn subpixel(&self) -> SubPixel {
109        self.subpixel
110    }
111}
112
113/// A physical interface type.
114#[allow(missing_docs)]
115#[allow(clippy::upper_case_acronyms)]
116#[non_exhaustive]
117#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
118pub enum Interface {
119    Unknown,
120    VGA,
121    DVII,
122    DVID,
123    DVIA,
124    Composite,
125    SVideo,
126    LVDS,
127    Component,
128    NinePinDIN,
129    DisplayPort,
130    HDMIA,
131    HDMIB,
132    TV,
133    EmbeddedDisplayPort,
134    Virtual,
135    DSI,
136    DPI,
137    Writeback,
138    SPI,
139    USB,
140}
141
142impl Interface {
143    /// Get interface name as string
144    pub fn as_str(&self) -> &'static str {
145        // source: https://github.com/torvalds/linux/blob/489fa31ea873282b41046d412ec741f93946fc2d/drivers/gpu/drm/drm_connector.c#L89
146        match self {
147            Interface::Unknown => "Unknown",
148            Interface::VGA => "VGA",
149            Interface::DVII => "DVI-I",
150            Interface::DVID => "DVI-D",
151            Interface::DVIA => "DVI-A",
152            Interface::Composite => "Composite",
153            Interface::SVideo => "SVIDEO",
154            Interface::LVDS => "LVDS",
155            Interface::Component => "Component",
156            Interface::NinePinDIN => "DIN",
157            Interface::DisplayPort => "DP",
158            Interface::HDMIA => "HDMI-A",
159            Interface::HDMIB => "HDMI-B",
160            Interface::TV => "TV",
161            Interface::EmbeddedDisplayPort => "eDP",
162            Interface::Virtual => "Virtual",
163            Interface::DSI => "DSI",
164            Interface::DPI => "DPI",
165            Interface::Writeback => "Writeback",
166            Interface::SPI => "SPI",
167            Interface::USB => "USB",
168        }
169    }
170}
171
172impl From<u32> for Interface {
173    fn from(n: u32) -> Self {
174        match n {
175            ffi::DRM_MODE_CONNECTOR_Unknown => Interface::Unknown,
176            ffi::DRM_MODE_CONNECTOR_VGA => Interface::VGA,
177            ffi::DRM_MODE_CONNECTOR_DVII => Interface::DVII,
178            ffi::DRM_MODE_CONNECTOR_DVID => Interface::DVID,
179            ffi::DRM_MODE_CONNECTOR_DVIA => Interface::DVIA,
180            ffi::DRM_MODE_CONNECTOR_Composite => Interface::Composite,
181            ffi::DRM_MODE_CONNECTOR_SVIDEO => Interface::SVideo,
182            ffi::DRM_MODE_CONNECTOR_LVDS => Interface::LVDS,
183            ffi::DRM_MODE_CONNECTOR_Component => Interface::Component,
184            ffi::DRM_MODE_CONNECTOR_9PinDIN => Interface::NinePinDIN,
185            ffi::DRM_MODE_CONNECTOR_DisplayPort => Interface::DisplayPort,
186            ffi::DRM_MODE_CONNECTOR_HDMIA => Interface::HDMIA,
187            ffi::DRM_MODE_CONNECTOR_HDMIB => Interface::HDMIB,
188            ffi::DRM_MODE_CONNECTOR_TV => Interface::TV,
189            ffi::DRM_MODE_CONNECTOR_eDP => Interface::EmbeddedDisplayPort,
190            ffi::DRM_MODE_CONNECTOR_VIRTUAL => Interface::Virtual,
191            ffi::DRM_MODE_CONNECTOR_DSI => Interface::DSI,
192            ffi::DRM_MODE_CONNECTOR_DPI => Interface::DPI,
193            ffi::DRM_MODE_CONNECTOR_WRITEBACK => Interface::Writeback,
194            ffi::DRM_MODE_CONNECTOR_SPI => Interface::SPI,
195            ffi::DRM_MODE_CONNECTOR_USB => Interface::USB,
196            _ => Interface::Unknown,
197        }
198    }
199}
200
201impl From<Interface> for u32 {
202    fn from(interface: Interface) -> Self {
203        match interface {
204            Interface::Unknown => ffi::DRM_MODE_CONNECTOR_Unknown,
205            Interface::VGA => ffi::DRM_MODE_CONNECTOR_VGA,
206            Interface::DVII => ffi::DRM_MODE_CONNECTOR_DVII,
207            Interface::DVID => ffi::DRM_MODE_CONNECTOR_DVID,
208            Interface::DVIA => ffi::DRM_MODE_CONNECTOR_DVIA,
209            Interface::Composite => ffi::DRM_MODE_CONNECTOR_Composite,
210            Interface::SVideo => ffi::DRM_MODE_CONNECTOR_SVIDEO,
211            Interface::LVDS => ffi::DRM_MODE_CONNECTOR_LVDS,
212            Interface::Component => ffi::DRM_MODE_CONNECTOR_Component,
213            Interface::NinePinDIN => ffi::DRM_MODE_CONNECTOR_9PinDIN,
214            Interface::DisplayPort => ffi::DRM_MODE_CONNECTOR_DisplayPort,
215            Interface::HDMIA => ffi::DRM_MODE_CONNECTOR_HDMIA,
216            Interface::HDMIB => ffi::DRM_MODE_CONNECTOR_HDMIB,
217            Interface::TV => ffi::DRM_MODE_CONNECTOR_TV,
218            Interface::EmbeddedDisplayPort => ffi::DRM_MODE_CONNECTOR_eDP,
219            Interface::Virtual => ffi::DRM_MODE_CONNECTOR_VIRTUAL,
220            Interface::DSI => ffi::DRM_MODE_CONNECTOR_DSI,
221            Interface::DPI => ffi::DRM_MODE_CONNECTOR_DPI,
222            Interface::Writeback => ffi::DRM_MODE_CONNECTOR_WRITEBACK,
223            Interface::SPI => ffi::DRM_MODE_CONNECTOR_SPI,
224            Interface::USB => ffi::DRM_MODE_CONNECTOR_USB,
225        }
226    }
227}
228
229/// The state of a connector.
230#[allow(missing_docs)]
231#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
232pub enum State {
233    Connected,
234    Disconnected,
235    Unknown,
236}
237
238impl From<u32> for State {
239    fn from(n: u32) -> Self {
240        // These variables are not defined in drm_mode.h for some reason.
241        // They were copied from libdrm's xf86DrmMode.h
242        match n {
243            1 => State::Connected,
244            2 => State::Disconnected,
245            _ => State::Unknown,
246        }
247    }
248}
249
250impl From<State> for u32 {
251    fn from(state: State) -> Self {
252        // These variables are not defined in drm_mode.h for some reason.
253        // They were copied from libdrm's xf86DrmMode.h
254        match state {
255            State::Connected => 1,
256            State::Disconnected => 2,
257            State::Unknown => 3,
258        }
259    }
260}
261
262/// Subpixel order of the connected sink
263#[non_exhaustive]
264#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
265pub enum SubPixel {
266    /// Unknown geometry
267    Unknown,
268    /// Horizontal RGB
269    HorizontalRgb,
270    /// Horizontal BGR
271    HorizontalBgr,
272    /// Vertical RGB
273    VerticalRgb,
274    /// Vertical BGR
275    VerticalBgr,
276    /// No geometry
277    None,
278    /// Encountered value not supported by drm-rs
279    NotImplemented,
280}
281
282impl SubPixel {
283    pub(super) fn from_raw(n: u32) -> Self {
284        // These values are not defined in drm_mode.h
285        // They were copied from linux's drm_connector.h
286        // Don't mistake those for ones used in xf86DrmMode.h (libdrm offsets those by 1)
287        match n {
288            0 => Self::Unknown,
289            1 => Self::HorizontalRgb,
290            2 => Self::HorizontalBgr,
291            3 => Self::VerticalRgb,
292            4 => Self::VerticalBgr,
293            5 => Self::None,
294            _ => Self::NotImplemented,
295        }
296    }
297}