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 { from(handle: Handle) -> Self22 fn from(handle: Handle) -> Self { 23 handle.0 24 } 25 } 26 27 impl From<Handle> for u32 { from(handle: Handle) -> Self28 fn from(handle: Handle) -> Self { 29 handle.0.into() 30 } 31 } 32 33 impl From<control::RawResourceHandle> for Handle { from(handle: control::RawResourceHandle) -> Self34 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 { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result44 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)] 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 { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result64 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. handle(&self) -> Handle71 pub fn handle(&self) -> Handle { 72 self.handle 73 } 74 75 /// Returns the type of `Interface` of this connector. interface(&self) -> Interface76 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. interface_id(&self) -> u3284 pub fn interface_id(&self) -> u32 { 85 self.interface_id 86 } 87 88 /// Returns the `State` of this connector. state(&self) -> State89 pub fn state(&self) -> State { 90 self.connection 91 } 92 93 /// Returns the size of the display (in millimeters) if connected. size(&self) -> Option<(u32, u32)>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. encoders(&self) -> &[control::encoder::Handle]99 pub fn encoders(&self) -> &[control::encoder::Handle] { 100 &self.encoders 101 } 102 103 /// Returns a list of modes this connector reports as supported. modes(&self) -> &[control::Mode]104 pub fn modes(&self) -> &[control::Mode] { 105 &self.modes 106 } 107 108 /// Returns the current encoder attached to this connector. current_encoder(&self) -> Option<control::encoder::Handle>109 pub fn current_encoder(&self) -> Option<control::encoder::Handle> { 110 self.curr_enc 111 } 112 113 /// Subpixel order of the connected sink subpixel(&self) -> SubPixel114 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 as_str(&self) -> &'static str150 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 { from(n: u32) -> Self179 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 { from(interface: Interface) -> Self208 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 { from(n: u32) -> Self245 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 { from(state: State) -> Self257 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 { from_raw(n: u32) -> Self289 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