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 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}