| 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 { |
| 22 | fn from(handle: Handle) -> Self { |
| 23 | handle.0 |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | impl From<Handle> for u32 { |
| 28 | fn from(handle: Handle) -> Self { |
| 29 | handle.0.into() |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | impl From<control::RawResourceHandle> for Handle { |
| 34 | 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 { |
| 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)] |
| 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 { |
| 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 | |
| 69 | impl 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)] |
| 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 |
| 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 | |
| 178 | impl 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 | |
| 207 | impl 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)] |
| 238 | pub enum State { |
| 239 | Connected, |
| 240 | Disconnected, |
| 241 | Unknown, |
| 242 | } |
| 243 | |
| 244 | impl 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 | |
| 256 | impl 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)] |
| 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 { |
| 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 | |