1 #include <stdio.h>
2 #include <iostream>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <cassert>
7 #include "kms++.h"
8 #include "helpers.h"
10 using namespace std;
12 namespace kms
13 {
16 static const map<int, string> connector_names = {
17 #define DEF_CONN(c) { DRM_MODE_CONNECTOR_##c, #c }
18 DEF_CONN(Unknown),
19 DEF_CONN(VGA),
20 DEF_CONN(DVII),
21 DEF_CONN(DVID),
22 DEF_CONN(DVIA),
23 DEF_CONN(Composite),
24 DEF_CONN(SVIDEO),
25 DEF_CONN(LVDS),
26 DEF_CONN(Component),
27 DEF_CONN(9PinDIN),
28 DEF_CONN(DisplayPort),
29 DEF_CONN(HDMIA),
30 DEF_CONN(HDMIB),
31 DEF_CONN(TV),
32 DEF_CONN(eDP),
33 DEF_CONN(VIRTUAL),
34 DEF_CONN(DSI),
35 #undef DEF_CONN
36 };
38 static const map<int, string> connection_str = {
39 { 0, "<unknown>" },
40 { DRM_MODE_CONNECTED, "Connected" },
41 { DRM_MODE_DISCONNECTED, "Disconnected" },
42 { DRM_MODE_UNKNOWNCONNECTION, "Unknown" },
43 };
45 struct ConnectorPriv
46 {
47 drmModeConnectorPtr drm_connector;
48 };
50 Connector::Connector(Card &card, uint32_t id, uint32_t idx)
51 :DrmObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx)
52 {
53 m_priv = new ConnectorPriv();
55 m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
56 assert(m_priv->drm_connector);
58 const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
59 m_fullname = name + to_string(m_priv->drm_connector->connector_type_id);
60 }
63 Connector::~Connector()
64 {
65 drmModeFreeConnector(m_priv->drm_connector);
66 delete m_priv;
67 }
69 void Connector::setup()
70 {
71 if (m_priv->drm_connector->encoder_id != 0)
72 m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id);
73 else
74 m_current_encoder = 0;
76 if (m_current_encoder)
77 m_saved_crtc = m_current_encoder->get_crtc();
78 else
79 m_saved_crtc = 0;
80 }
82 void Connector::restore_mode()
83 {
84 if (m_saved_crtc)
85 m_saved_crtc->restore_mode(this);
86 }
88 void Connector::print_short() const
89 {
90 auto c = m_priv->drm_connector;
92 printf("Connector %d, %s, %dx%dmm, %s\n", id(), m_fullname.c_str(),
93 c->mmWidth, c->mmHeight, connection_str.at(c->connection).c_str());
94 }
96 Videomode Connector::get_default_mode() const
97 {
98 drmModeModeInfo drmmode = m_priv->drm_connector->modes[0];
100 return drm_mode_to_video_mode(drmmode);
101 }
103 Videomode Connector::get_mode(const string& mode) const
104 {
105 auto c = m_priv->drm_connector;
107 for (int i = 0; i < c->count_modes; i++)
108 if (mode == c->modes[i].name)
109 return drm_mode_to_video_mode(c->modes[i]);
111 throw invalid_argument(mode + ": mode not found");
112 }
114 bool Connector::connected() const
115 {
116 return m_priv->drm_connector->connection == DRM_MODE_CONNECTED;
117 }
119 vector<Crtc*> Connector::get_possible_crtcs() const
120 {
121 vector<Crtc*> crtcs;
123 for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) {
124 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
126 auto l = enc->get_possible_crtcs();
128 crtcs.insert(crtcs.end(), l.begin(), l.end());
129 }
131 return crtcs;
132 }
134 Crtc* Connector::get_current_crtc() const
135 {
136 if (m_current_encoder)
137 return m_current_encoder->get_crtc();
138 else
139 return 0;
140 }
142 }