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 Info { 64 /// Returns the handle to this connector. handle(&self) -> Handle65 pub fn handle(&self) -> Handle { 66 self.handle 67 } 68 69 /// Returns the type of `Interface` of this connector. interface(&self) -> Interface70 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. interface_id(&self) -> u3278 pub fn interface_id(&self) -> u32 { 79 self.interface_id 80 } 81 82 /// Returns the `State` of this connector. state(&self) -> State83 pub fn state(&self) -> State { 84 self.connection 85 } 86 87 /// Returns the size of the display (in millimeters) if connected. size(&self) -> Option<(u32, u32)>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. encoders(&self) -> &[control::encoder::Handle]93 pub fn encoders(&self) -> &[control::encoder::Handle] { 94 &self.encoders 95 } 96 97 /// Returns a list of modes this connector reports as supported. modes(&self) -> &[control::Mode]98 pub fn modes(&self) -> &[control::Mode] { 99 &self.modes 100 } 101 102 /// Returns the current encoder attached to this connector. current_encoder(&self) -> Option<control::encoder::Handle>103 pub fn current_encoder(&self) -> Option<control::encoder::Handle> { 104 self.curr_enc 105 } 106 107 /// Subpixel order of the connected sink subpixel(&self) -> SubPixel108 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)] 118 pub 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 142 impl Interface { 143 /// Get interface name as string as_str(&self) -> &'static str144 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 172 impl From<u32> for Interface { from(n: u32) -> Self173 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 201 impl From<Interface> for u32 { from(interface: Interface) -> Self202 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)] 232 pub enum State { 233 Connected, 234 Disconnected, 235 Unknown, 236 } 237 238 impl From<u32> for State { from(n: u32) -> Self239 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 250 impl From<State> for u32 { from(state: State) -> Self251 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)] 265 pub 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 282 impl SubPixel { from_raw(n: u32) -> Self283 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 } 298