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 static const map<int, string> subpix_str = {
46 #define DEF_SUBPIX(c) { DRM_MODE_SUBPIXEL_##c, #c }
47 DEF_SUBPIX(UNKNOWN),
48 DEF_SUBPIX(HORIZONTAL_RGB),
49 DEF_SUBPIX(HORIZONTAL_BGR),
50 DEF_SUBPIX(VERTICAL_RGB),
51 DEF_SUBPIX(VERTICAL_BGR),
52 DEF_SUBPIX(NONE),
53 #undef DEF_SUBPIX
54 };
56 struct ConnectorPriv
57 {
58 drmModeConnectorPtr drm_connector;
59 };
61 Connector::Connector(Card &card, uint32_t id, uint32_t idx)
62 :DrmObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx)
63 {
64 m_priv = new ConnectorPriv();
66 m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
67 assert(m_priv->drm_connector);
69 const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
70 m_fullname = name + to_string(m_priv->drm_connector->connector_type_id);
71 }
74 Connector::~Connector()
75 {
76 drmModeFreeConnector(m_priv->drm_connector);
77 delete m_priv;
78 }
80 void Connector::setup()
81 {
82 if (m_priv->drm_connector->encoder_id != 0)
83 m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id);
84 else
85 m_current_encoder = 0;
87 if (m_current_encoder)
88 m_saved_crtc = m_current_encoder->get_crtc();
89 else
90 m_saved_crtc = 0;
91 }
93 void Connector::restore_mode()
94 {
95 if (m_saved_crtc)
96 m_saved_crtc->restore_mode(this);
97 }
99 Videomode Connector::get_default_mode() const
100 {
101 drmModeModeInfo drmmode = m_priv->drm_connector->modes[0];
103 return drm_mode_to_video_mode(drmmode);
104 }
106 Videomode Connector::get_mode(const string& mode) const
107 {
108 auto c = m_priv->drm_connector;
110 for (int i = 0; i < c->count_modes; i++)
111 if (mode == c->modes[i].name)
112 return drm_mode_to_video_mode(c->modes[i]);
114 throw invalid_argument(mode + ": mode not found");
115 }
117 Videomode Connector::get_mode(unsigned xres, unsigned yres, unsigned refresh) const
118 {
119 auto c = m_priv->drm_connector;
121 for (int i = 0; i < c->count_modes; i++) {
122 drmModeModeInfo& m = c->modes[i];
124 if (m.hdisplay != xres || m.vdisplay != yres)
125 continue;
127 if (refresh && m.vrefresh != refresh)
128 continue;
130 return drm_mode_to_video_mode(c->modes[i]);
131 }
133 throw invalid_argument("mode not found");
134 }
136 bool Connector::connected() const
137 {
138 return m_priv->drm_connector->connection == DRM_MODE_CONNECTED ||
139 m_priv->drm_connector->connection == DRM_MODE_UNKNOWNCONNECTION;
140 }
142 vector<Crtc*> Connector::get_possible_crtcs() const
143 {
144 vector<Crtc*> crtcs;
146 for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) {
147 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
149 auto l = enc->get_possible_crtcs();
151 crtcs.insert(crtcs.end(), l.begin(), l.end());
152 }
154 return crtcs;
155 }
157 Crtc* Connector::get_current_crtc() const
158 {
159 if (m_current_encoder)
160 return m_current_encoder->get_crtc();
161 else
162 return 0;
163 }
165 uint32_t Connector::connector_type() const
166 {
167 return m_priv->drm_connector->connector_type;
168 }
170 uint32_t Connector::connector_type_id() const
171 {
172 return m_priv->drm_connector->connector_type_id;
173 }
175 uint32_t Connector::mmWidth() const
176 {
177 return m_priv->drm_connector->mmWidth;
178 }
180 uint32_t Connector::mmHeight() const
181 {
182 return m_priv->drm_connector->mmHeight;
183 }
185 uint32_t Connector::subpixel() const
186 {
187 return m_priv->drm_connector->subpixel;
188 }
190 const string& Connector::subpixel_str() const
191 {
192 return subpix_str.at(subpixel());
193 }
195 std::vector<Videomode> Connector::get_modes() const
196 {
197 vector<Videomode> modes;
199 for (int i = 0; i < m_priv->drm_connector->count_modes; i++)
200 modes.push_back(drm_mode_to_video_mode(
201 m_priv->drm_connector->modes[i]));
203 return modes;
204 }
206 std::vector<Encoder*> Connector::get_encoders() const
207 {
208 vector<Encoder*> encoders;
210 for (int i = 0; i < m_priv->drm_connector->count_encoders; i++) {
211 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
212 encoders.push_back(enc);
213 }
214 return encoders;
215 }
217 }