1*f0687c8aSRaman Tenneti #include <algorithm>
2*f0687c8aSRaman Tenneti #include <cinttypes>
3*f0687c8aSRaman Tenneti #include <cstdio>
4*f0687c8aSRaman Tenneti #include <iostream>
5*f0687c8aSRaman Tenneti #include <string>
6*f0687c8aSRaman Tenneti #include <unistd.h>
7*f0687c8aSRaman Tenneti #include <fmt/format.h>
8*f0687c8aSRaman Tenneti
9*f0687c8aSRaman Tenneti #include <kms++/kms++.h>
10*f0687c8aSRaman Tenneti #include <kms++util/kms++util.h>
11*f0687c8aSRaman Tenneti
12*f0687c8aSRaman Tenneti using namespace std;
13*f0687c8aSRaman Tenneti using namespace kms;
14*f0687c8aSRaman Tenneti
15*f0687c8aSRaman Tenneti static struct {
16*f0687c8aSRaman Tenneti bool print_props;
17*f0687c8aSRaman Tenneti bool print_modes;
18*f0687c8aSRaman Tenneti bool print_list;
19*f0687c8aSRaman Tenneti bool x_modeline;
20*f0687c8aSRaman Tenneti } s_opts;
21*f0687c8aSRaman Tenneti
format_mode(const Videomode & m,unsigned idx)22*f0687c8aSRaman Tenneti static string format_mode(const Videomode& m, unsigned idx)
23*f0687c8aSRaman Tenneti {
24*f0687c8aSRaman Tenneti string str;
25*f0687c8aSRaman Tenneti
26*f0687c8aSRaman Tenneti str = fmt::format(" {:2} ", idx);
27*f0687c8aSRaman Tenneti
28*f0687c8aSRaman Tenneti if (s_opts.x_modeline) {
29*f0687c8aSRaman Tenneti str += fmt::format("{:12} {:6} {:4} {:4} {:4} {:4} {:4} {:4} {:4} {:4} {:3} {:#x} {:#x}",
30*f0687c8aSRaman Tenneti m.name,
31*f0687c8aSRaman Tenneti m.clock,
32*f0687c8aSRaman Tenneti m.hdisplay, m.hsync_start, m.hsync_end, m.htotal,
33*f0687c8aSRaman Tenneti m.vdisplay, m.vsync_start, m.vsync_end, m.vtotal,
34*f0687c8aSRaman Tenneti m.vrefresh,
35*f0687c8aSRaman Tenneti m.flags,
36*f0687c8aSRaman Tenneti m.type);
37*f0687c8aSRaman Tenneti } else {
38*f0687c8aSRaman Tenneti str += m.to_string_long_padded();
39*f0687c8aSRaman Tenneti }
40*f0687c8aSRaman Tenneti
41*f0687c8aSRaman Tenneti return str;
42*f0687c8aSRaman Tenneti }
43*f0687c8aSRaman Tenneti
format_mode_short(const Videomode & m)44*f0687c8aSRaman Tenneti static string format_mode_short(const Videomode& m)
45*f0687c8aSRaman Tenneti {
46*f0687c8aSRaman Tenneti return m.to_string_long();
47*f0687c8aSRaman Tenneti }
48*f0687c8aSRaman Tenneti
format_connector(Connector & c)49*f0687c8aSRaman Tenneti static string format_connector(Connector& c)
50*f0687c8aSRaman Tenneti {
51*f0687c8aSRaman Tenneti string str;
52*f0687c8aSRaman Tenneti
53*f0687c8aSRaman Tenneti str = fmt::format("Connector {} ({}) {}",
54*f0687c8aSRaman Tenneti c.idx(), c.id(), c.fullname());
55*f0687c8aSRaman Tenneti
56*f0687c8aSRaman Tenneti switch (c.connector_status()) {
57*f0687c8aSRaman Tenneti case ConnectorStatus::Connected:
58*f0687c8aSRaman Tenneti str += " (connected)";
59*f0687c8aSRaman Tenneti break;
60*f0687c8aSRaman Tenneti case ConnectorStatus::Disconnected:
61*f0687c8aSRaman Tenneti str += " (disconnected)";
62*f0687c8aSRaman Tenneti break;
63*f0687c8aSRaman Tenneti default:
64*f0687c8aSRaman Tenneti str += " (unknown)";
65*f0687c8aSRaman Tenneti break;
66*f0687c8aSRaman Tenneti }
67*f0687c8aSRaman Tenneti
68*f0687c8aSRaman Tenneti return str;
69*f0687c8aSRaman Tenneti }
70*f0687c8aSRaman Tenneti
format_encoder(Encoder & e)71*f0687c8aSRaman Tenneti static string format_encoder(Encoder& e)
72*f0687c8aSRaman Tenneti {
73*f0687c8aSRaman Tenneti return fmt::format("Encoder {} ({}) {}",
74*f0687c8aSRaman Tenneti e.idx(), e.id(), e.get_encoder_type());
75*f0687c8aSRaman Tenneti }
76*f0687c8aSRaman Tenneti
format_crtc(Crtc & c)77*f0687c8aSRaman Tenneti static string format_crtc(Crtc& c)
78*f0687c8aSRaman Tenneti {
79*f0687c8aSRaman Tenneti string str;
80*f0687c8aSRaman Tenneti
81*f0687c8aSRaman Tenneti str = fmt::format("Crtc {} ({})", c.idx(), c.id());
82*f0687c8aSRaman Tenneti
83*f0687c8aSRaman Tenneti if (c.mode_valid())
84*f0687c8aSRaman Tenneti str += " " + format_mode_short(c.mode());
85*f0687c8aSRaman Tenneti
86*f0687c8aSRaman Tenneti return str;
87*f0687c8aSRaman Tenneti }
88*f0687c8aSRaman Tenneti
format_plane(Plane & p)89*f0687c8aSRaman Tenneti static string format_plane(Plane& p)
90*f0687c8aSRaman Tenneti {
91*f0687c8aSRaman Tenneti string str;
92*f0687c8aSRaman Tenneti
93*f0687c8aSRaman Tenneti str = fmt::format("Plane {} ({})", p.idx(), p.id());
94*f0687c8aSRaman Tenneti
95*f0687c8aSRaman Tenneti if (p.fb_id())
96*f0687c8aSRaman Tenneti str += fmt::format(" fb-id: {}", p.fb_id());
97*f0687c8aSRaman Tenneti
98*f0687c8aSRaman Tenneti string crtcs = join<Crtc*>(p.get_possible_crtcs(), " ", [](Crtc* crtc) { return to_string(crtc->idx()); });
99*f0687c8aSRaman Tenneti
100*f0687c8aSRaman Tenneti str += fmt::format(" (crtcs: {})", crtcs);
101*f0687c8aSRaman Tenneti
102*f0687c8aSRaman Tenneti if (p.card().has_atomic()) {
103*f0687c8aSRaman Tenneti str += fmt::format(" {},{} {}x{} -> {},{} {}x{}",
104*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("SRC_X") >> 16,
105*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("SRC_Y") >> 16,
106*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("SRC_W") >> 16,
107*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("SRC_H") >> 16,
108*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("CRTC_X"),
109*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("CRTC_Y"),
110*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("CRTC_W"),
111*f0687c8aSRaman Tenneti (uint32_t)p.get_prop_value("CRTC_H"));
112*f0687c8aSRaman Tenneti }
113*f0687c8aSRaman Tenneti
114*f0687c8aSRaman Tenneti string fmts = join<PixelFormat>(p.get_formats(), " ", [](PixelFormat fmt) { return PixelFormatToFourCC(fmt); });
115*f0687c8aSRaman Tenneti
116*f0687c8aSRaman Tenneti str += fmt::format(" ({})", fmts);
117*f0687c8aSRaman Tenneti
118*f0687c8aSRaman Tenneti return str;
119*f0687c8aSRaman Tenneti }
120*f0687c8aSRaman Tenneti
format_fb(Framebuffer & fb)121*f0687c8aSRaman Tenneti static string format_fb(Framebuffer& fb)
122*f0687c8aSRaman Tenneti {
123*f0687c8aSRaman Tenneti return fmt::format("FB {} {}x{}",
124*f0687c8aSRaman Tenneti fb.id(), fb.width(), fb.height());
125*f0687c8aSRaman Tenneti }
126*f0687c8aSRaman Tenneti
format_property(const Property * prop,uint64_t val)127*f0687c8aSRaman Tenneti static string format_property(const Property* prop, uint64_t val)
128*f0687c8aSRaman Tenneti {
129*f0687c8aSRaman Tenneti string ret = fmt::format("{} ({}) = ", prop->name(), prop->id());
130*f0687c8aSRaman Tenneti
131*f0687c8aSRaman Tenneti switch (prop->type()) {
132*f0687c8aSRaman Tenneti case PropertyType::Bitmask: {
133*f0687c8aSRaman Tenneti vector<string> v, vall;
134*f0687c8aSRaman Tenneti
135*f0687c8aSRaman Tenneti for (auto kvp : prop->get_enums()) {
136*f0687c8aSRaman Tenneti if (val & (1 << kvp.first))
137*f0687c8aSRaman Tenneti v.push_back(kvp.second);
138*f0687c8aSRaman Tenneti vall.push_back(fmt::format("{}={:#x}", kvp.second, 1 << kvp.first));
139*f0687c8aSRaman Tenneti }
140*f0687c8aSRaman Tenneti
141*f0687c8aSRaman Tenneti // XXX
142*f0687c8aSRaman Tenneti ret += fmt::format("{:#x} ({}) [{}]", val, join(v, "|"), join(vall, "|"));
143*f0687c8aSRaman Tenneti
144*f0687c8aSRaman Tenneti break;
145*f0687c8aSRaman Tenneti }
146*f0687c8aSRaman Tenneti
147*f0687c8aSRaman Tenneti case PropertyType::Blob: {
148*f0687c8aSRaman Tenneti uint32_t blob_id = (uint32_t)val;
149*f0687c8aSRaman Tenneti
150*f0687c8aSRaman Tenneti if (blob_id) {
151*f0687c8aSRaman Tenneti Blob blob(prop->card(), blob_id);
152*f0687c8aSRaman Tenneti auto data = blob.data();
153*f0687c8aSRaman Tenneti
154*f0687c8aSRaman Tenneti ret += fmt::format("blob-id {} len {}", blob_id, data.size());
155*f0687c8aSRaman Tenneti } else {
156*f0687c8aSRaman Tenneti ret += fmt::format("blob-id {}", blob_id);
157*f0687c8aSRaman Tenneti }
158*f0687c8aSRaman Tenneti
159*f0687c8aSRaman Tenneti break;
160*f0687c8aSRaman Tenneti }
161*f0687c8aSRaman Tenneti
162*f0687c8aSRaman Tenneti case PropertyType::Enum: {
163*f0687c8aSRaman Tenneti string cur;
164*f0687c8aSRaman Tenneti vector<string> vall;
165*f0687c8aSRaman Tenneti
166*f0687c8aSRaman Tenneti for (auto kvp : prop->get_enums()) {
167*f0687c8aSRaman Tenneti if (val == kvp.first)
168*f0687c8aSRaman Tenneti cur = kvp.second;
169*f0687c8aSRaman Tenneti vall.push_back(fmt::format("{}={}", kvp.second, kvp.first));
170*f0687c8aSRaman Tenneti }
171*f0687c8aSRaman Tenneti
172*f0687c8aSRaman Tenneti ret += fmt::format("{} ({}) [{}]", val, cur, join(vall, "|"));
173*f0687c8aSRaman Tenneti
174*f0687c8aSRaman Tenneti break;
175*f0687c8aSRaman Tenneti }
176*f0687c8aSRaman Tenneti
177*f0687c8aSRaman Tenneti case PropertyType::Object: {
178*f0687c8aSRaman Tenneti ret += fmt::format("object id {}", val);
179*f0687c8aSRaman Tenneti break;
180*f0687c8aSRaman Tenneti }
181*f0687c8aSRaman Tenneti
182*f0687c8aSRaman Tenneti case PropertyType::Range: {
183*f0687c8aSRaman Tenneti auto values = prop->get_values();
184*f0687c8aSRaman Tenneti
185*f0687c8aSRaman Tenneti ret += fmt::format("{} [{} - {}]",
186*f0687c8aSRaman Tenneti val, values[0], values[1]);
187*f0687c8aSRaman Tenneti
188*f0687c8aSRaman Tenneti break;
189*f0687c8aSRaman Tenneti }
190*f0687c8aSRaman Tenneti
191*f0687c8aSRaman Tenneti case PropertyType::SignedRange: {
192*f0687c8aSRaman Tenneti auto values = prop->get_values();
193*f0687c8aSRaman Tenneti
194*f0687c8aSRaman Tenneti ret += fmt::format("{} [{} - {}]",
195*f0687c8aSRaman Tenneti (int64_t)val, (int64_t)values[0], (int64_t)values[1]);
196*f0687c8aSRaman Tenneti
197*f0687c8aSRaman Tenneti break;
198*f0687c8aSRaman Tenneti }
199*f0687c8aSRaman Tenneti }
200*f0687c8aSRaman Tenneti
201*f0687c8aSRaman Tenneti if (prop->is_pending())
202*f0687c8aSRaman Tenneti ret += " (pending)";
203*f0687c8aSRaman Tenneti if (prop->is_immutable())
204*f0687c8aSRaman Tenneti ret += " (immutable)";
205*f0687c8aSRaman Tenneti
206*f0687c8aSRaman Tenneti return ret;
207*f0687c8aSRaman Tenneti }
208*f0687c8aSRaman Tenneti
format_props(DrmPropObject * o)209*f0687c8aSRaman Tenneti static vector<string> format_props(DrmPropObject* o)
210*f0687c8aSRaman Tenneti {
211*f0687c8aSRaman Tenneti vector<string> lines;
212*f0687c8aSRaman Tenneti
213*f0687c8aSRaman Tenneti auto pmap = o->get_prop_map();
214*f0687c8aSRaman Tenneti for (auto pp : pmap) {
215*f0687c8aSRaman Tenneti const Property* p = o->card().get_prop(pp.first);
216*f0687c8aSRaman Tenneti lines.push_back(format_property(p, pp.second));
217*f0687c8aSRaman Tenneti }
218*f0687c8aSRaman Tenneti
219*f0687c8aSRaman Tenneti return lines;
220*f0687c8aSRaman Tenneti }
221*f0687c8aSRaman Tenneti
format_ob(DrmObject * ob)222*f0687c8aSRaman Tenneti static string format_ob(DrmObject* ob)
223*f0687c8aSRaman Tenneti {
224*f0687c8aSRaman Tenneti if (auto o = dynamic_cast<Connector*>(ob))
225*f0687c8aSRaman Tenneti return format_connector(*o);
226*f0687c8aSRaman Tenneti else if (auto o = dynamic_cast<Encoder*>(ob))
227*f0687c8aSRaman Tenneti return format_encoder(*o);
228*f0687c8aSRaman Tenneti else if (auto o = dynamic_cast<Crtc*>(ob))
229*f0687c8aSRaman Tenneti return format_crtc(*o);
230*f0687c8aSRaman Tenneti else if (auto o = dynamic_cast<Plane*>(ob))
231*f0687c8aSRaman Tenneti return format_plane(*o);
232*f0687c8aSRaman Tenneti else if (auto o = dynamic_cast<Framebuffer*>(ob))
233*f0687c8aSRaman Tenneti return format_fb(*o);
234*f0687c8aSRaman Tenneti else
235*f0687c8aSRaman Tenneti EXIT("Unkown DRM Object type\n");
236*f0687c8aSRaman Tenneti }
237*f0687c8aSRaman Tenneti
238*f0687c8aSRaman Tenneti template<class T>
filter(const vector<T> & sequence,function<bool (T)> predicate)239*f0687c8aSRaman Tenneti vector<T> filter(const vector<T>& sequence, function<bool(T)> predicate)
240*f0687c8aSRaman Tenneti {
241*f0687c8aSRaman Tenneti vector<T> result;
242*f0687c8aSRaman Tenneti
243*f0687c8aSRaman Tenneti for (auto it = sequence.begin(); it != sequence.end(); ++it)
244*f0687c8aSRaman Tenneti if (predicate(*it))
245*f0687c8aSRaman Tenneti result.push_back(*it);
246*f0687c8aSRaman Tenneti
247*f0687c8aSRaman Tenneti return result;
248*f0687c8aSRaman Tenneti }
249*f0687c8aSRaman Tenneti
250*f0687c8aSRaman Tenneti struct Entry {
251*f0687c8aSRaman Tenneti string title;
252*f0687c8aSRaman Tenneti vector<string> lines;
253*f0687c8aSRaman Tenneti vector<Entry> children;
254*f0687c8aSRaman Tenneti };
255*f0687c8aSRaman Tenneti
add_entry(vector<Entry> & entries)256*f0687c8aSRaman Tenneti static Entry& add_entry(vector<Entry>& entries)
257*f0687c8aSRaman Tenneti {
258*f0687c8aSRaman Tenneti entries.emplace_back();
259*f0687c8aSRaman Tenneti return entries.back();
260*f0687c8aSRaman Tenneti }
261*f0687c8aSRaman Tenneti /*
262*f0687c8aSRaman Tenneti static bool on_tty()
263*f0687c8aSRaman Tenneti {
264*f0687c8aSRaman Tenneti return isatty(STDOUT_FILENO) > 0;
265*f0687c8aSRaman Tenneti }
266*f0687c8aSRaman Tenneti */
267*f0687c8aSRaman Tenneti enum class TreeGlyphMode {
268*f0687c8aSRaman Tenneti None,
269*f0687c8aSRaman Tenneti ASCII,
270*f0687c8aSRaman Tenneti UTF8,
271*f0687c8aSRaman Tenneti };
272*f0687c8aSRaman Tenneti
273*f0687c8aSRaman Tenneti static TreeGlyphMode s_glyph_mode = TreeGlyphMode::None;
274*f0687c8aSRaman Tenneti
275*f0687c8aSRaman Tenneti enum class TreeGlyph {
276*f0687c8aSRaman Tenneti Vertical,
277*f0687c8aSRaman Tenneti Branch,
278*f0687c8aSRaman Tenneti Right,
279*f0687c8aSRaman Tenneti Space,
280*f0687c8aSRaman Tenneti };
281*f0687c8aSRaman Tenneti
282*f0687c8aSRaman Tenneti static const map<TreeGlyph, string> glyphs_utf8 = {
283*f0687c8aSRaman Tenneti { TreeGlyph::Vertical, "│ " },
284*f0687c8aSRaman Tenneti { TreeGlyph::Branch, "├─" },
285*f0687c8aSRaman Tenneti { TreeGlyph::Right, "└─" },
286*f0687c8aSRaman Tenneti { TreeGlyph::Space, " " },
287*f0687c8aSRaman Tenneti
288*f0687c8aSRaman Tenneti };
289*f0687c8aSRaman Tenneti
290*f0687c8aSRaman Tenneti static const map<TreeGlyph, string> glyphs_ascii = {
291*f0687c8aSRaman Tenneti { TreeGlyph::Vertical, "| " },
292*f0687c8aSRaman Tenneti { TreeGlyph::Branch, "|-" },
293*f0687c8aSRaman Tenneti { TreeGlyph::Right, "`-" },
294*f0687c8aSRaman Tenneti { TreeGlyph::Space, " " },
295*f0687c8aSRaman Tenneti
296*f0687c8aSRaman Tenneti };
297*f0687c8aSRaman Tenneti
get_glyph(TreeGlyph glyph)298*f0687c8aSRaman Tenneti const string& get_glyph(TreeGlyph glyph)
299*f0687c8aSRaman Tenneti {
300*f0687c8aSRaman Tenneti static const string s_empty = " ";
301*f0687c8aSRaman Tenneti
302*f0687c8aSRaman Tenneti if (s_glyph_mode == TreeGlyphMode::None)
303*f0687c8aSRaman Tenneti return s_empty;
304*f0687c8aSRaman Tenneti
305*f0687c8aSRaman Tenneti const map<TreeGlyph, string>& glyphs = s_glyph_mode == TreeGlyphMode::UTF8 ? glyphs_utf8 : glyphs_ascii;
306*f0687c8aSRaman Tenneti
307*f0687c8aSRaman Tenneti return glyphs.at(glyph);
308*f0687c8aSRaman Tenneti }
309*f0687c8aSRaman Tenneti
print_entry(const Entry & e,const string & prefix,bool is_child,bool is_last)310*f0687c8aSRaman Tenneti static void print_entry(const Entry& e, const string& prefix, bool is_child, bool is_last)
311*f0687c8aSRaman Tenneti {
312*f0687c8aSRaman Tenneti string prefix1;
313*f0687c8aSRaman Tenneti string prefix2;
314*f0687c8aSRaman Tenneti
315*f0687c8aSRaman Tenneti if (is_child) {
316*f0687c8aSRaman Tenneti prefix1 = prefix + (is_last ? get_glyph(TreeGlyph::Right) : get_glyph(TreeGlyph::Branch));
317*f0687c8aSRaman Tenneti prefix2 = prefix + (is_last ? get_glyph(TreeGlyph::Space) : get_glyph(TreeGlyph::Vertical));
318*f0687c8aSRaman Tenneti }
319*f0687c8aSRaman Tenneti
320*f0687c8aSRaman Tenneti fmt::print("{}{}\n", prefix1, e.title);
321*f0687c8aSRaman Tenneti
322*f0687c8aSRaman Tenneti bool has_children = e.children.size() > 0;
323*f0687c8aSRaman Tenneti
324*f0687c8aSRaman Tenneti string data_prefix = prefix2 + (has_children ? get_glyph(TreeGlyph::Vertical) : get_glyph(TreeGlyph::Space));
325*f0687c8aSRaman Tenneti
326*f0687c8aSRaman Tenneti for (const string& str : e.lines) {
327*f0687c8aSRaman Tenneti string p = data_prefix + get_glyph(TreeGlyph::Space);
328*f0687c8aSRaman Tenneti fmt::print("{}{}\n", p, str);
329*f0687c8aSRaman Tenneti }
330*f0687c8aSRaman Tenneti
331*f0687c8aSRaman Tenneti for (const Entry& child : e.children) {
332*f0687c8aSRaman Tenneti bool is_last = &child == &e.children.back();
333*f0687c8aSRaman Tenneti
334*f0687c8aSRaman Tenneti print_entry(child, prefix2, true, is_last);
335*f0687c8aSRaman Tenneti }
336*f0687c8aSRaman Tenneti }
337*f0687c8aSRaman Tenneti
print_entries(const vector<Entry> & entries,const string & prefix)338*f0687c8aSRaman Tenneti static void print_entries(const vector<Entry>& entries, const string& prefix)
339*f0687c8aSRaman Tenneti {
340*f0687c8aSRaman Tenneti for (const Entry& e : entries) {
341*f0687c8aSRaman Tenneti print_entry(e, "", false, false);
342*f0687c8aSRaman Tenneti }
343*f0687c8aSRaman Tenneti }
344*f0687c8aSRaman Tenneti
345*f0687c8aSRaman Tenneti template<class T>
append(vector<DrmObject * > & dst,const vector<T * > & src)346*f0687c8aSRaman Tenneti static void append(vector<DrmObject*>& dst, const vector<T*>& src)
347*f0687c8aSRaman Tenneti {
348*f0687c8aSRaman Tenneti dst.insert(dst.end(), src.begin(), src.end());
349*f0687c8aSRaman Tenneti }
350*f0687c8aSRaman Tenneti
print_as_list(Card & card)351*f0687c8aSRaman Tenneti static void print_as_list(Card& card)
352*f0687c8aSRaman Tenneti {
353*f0687c8aSRaman Tenneti vector<DrmPropObject*> obs;
354*f0687c8aSRaman Tenneti vector<Framebuffer*> fbs;
355*f0687c8aSRaman Tenneti
356*f0687c8aSRaman Tenneti for (Connector* conn : card.get_connectors()) {
357*f0687c8aSRaman Tenneti obs.push_back(conn);
358*f0687c8aSRaman Tenneti }
359*f0687c8aSRaman Tenneti
360*f0687c8aSRaman Tenneti for (Encoder* enc : card.get_encoders()) {
361*f0687c8aSRaman Tenneti obs.push_back(enc);
362*f0687c8aSRaman Tenneti }
363*f0687c8aSRaman Tenneti
364*f0687c8aSRaman Tenneti for (Crtc* crtc : card.get_crtcs()) {
365*f0687c8aSRaman Tenneti obs.push_back(crtc);
366*f0687c8aSRaman Tenneti if (crtc->buffer_id() && !card.has_universal_planes()) {
367*f0687c8aSRaman Tenneti Framebuffer* fb = new Framebuffer(card, crtc->buffer_id());
368*f0687c8aSRaman Tenneti fbs.push_back(fb);
369*f0687c8aSRaman Tenneti }
370*f0687c8aSRaman Tenneti }
371*f0687c8aSRaman Tenneti
372*f0687c8aSRaman Tenneti for (Plane* plane : card.get_planes()) {
373*f0687c8aSRaman Tenneti obs.push_back(plane);
374*f0687c8aSRaman Tenneti if (plane->fb_id()) {
375*f0687c8aSRaman Tenneti Framebuffer* fb = new Framebuffer(card, plane->fb_id());
376*f0687c8aSRaman Tenneti fbs.push_back(fb);
377*f0687c8aSRaman Tenneti }
378*f0687c8aSRaman Tenneti }
379*f0687c8aSRaman Tenneti
380*f0687c8aSRaman Tenneti for (DrmPropObject* ob : obs) {
381*f0687c8aSRaman Tenneti fmt::print("{}\n", format_ob(ob));
382*f0687c8aSRaman Tenneti
383*f0687c8aSRaman Tenneti if (s_opts.print_props) {
384*f0687c8aSRaman Tenneti for (string str : format_props(ob))
385*f0687c8aSRaman Tenneti fmt::print(" {}\n", str);
386*f0687c8aSRaman Tenneti }
387*f0687c8aSRaman Tenneti }
388*f0687c8aSRaman Tenneti
389*f0687c8aSRaman Tenneti for (Framebuffer* fb : fbs) {
390*f0687c8aSRaman Tenneti fmt::print("{}\n", format_ob(fb));
391*f0687c8aSRaman Tenneti }
392*f0687c8aSRaman Tenneti }
393*f0687c8aSRaman Tenneti
print_as_tree(Card & card)394*f0687c8aSRaman Tenneti static void print_as_tree(Card& card)
395*f0687c8aSRaman Tenneti {
396*f0687c8aSRaman Tenneti vector<Entry> entries;
397*f0687c8aSRaman Tenneti
398*f0687c8aSRaman Tenneti for (Connector* conn : card.get_connectors()) {
399*f0687c8aSRaman Tenneti Entry& e1 = add_entry(entries);
400*f0687c8aSRaman Tenneti e1.title = format_ob(conn);
401*f0687c8aSRaman Tenneti if (s_opts.print_props)
402*f0687c8aSRaman Tenneti e1.lines = format_props(conn);
403*f0687c8aSRaman Tenneti
404*f0687c8aSRaman Tenneti for (Encoder* enc : conn->get_encoders()) {
405*f0687c8aSRaman Tenneti Entry& e2 = add_entry(e1.children);
406*f0687c8aSRaman Tenneti e2.title = format_ob(enc);
407*f0687c8aSRaman Tenneti if (s_opts.print_props)
408*f0687c8aSRaman Tenneti e2.lines = format_props(enc);
409*f0687c8aSRaman Tenneti
410*f0687c8aSRaman Tenneti if (Crtc* crtc = enc->get_crtc()) {
411*f0687c8aSRaman Tenneti Entry& e3 = add_entry(e2.children);
412*f0687c8aSRaman Tenneti e3.title = format_ob(crtc);
413*f0687c8aSRaman Tenneti if (s_opts.print_props)
414*f0687c8aSRaman Tenneti e3.lines = format_props(crtc);
415*f0687c8aSRaman Tenneti
416*f0687c8aSRaman Tenneti if (crtc->buffer_id() && !card.has_universal_planes()) {
417*f0687c8aSRaman Tenneti Framebuffer fb(card, crtc->buffer_id());
418*f0687c8aSRaman Tenneti Entry& e5 = add_entry(e3.children);
419*f0687c8aSRaman Tenneti
420*f0687c8aSRaman Tenneti e5.title = format_ob(&fb);
421*f0687c8aSRaman Tenneti }
422*f0687c8aSRaman Tenneti
423*f0687c8aSRaman Tenneti for (Plane* plane : card.get_planes()) {
424*f0687c8aSRaman Tenneti if (plane->crtc_id() != crtc->id())
425*f0687c8aSRaman Tenneti continue;
426*f0687c8aSRaman Tenneti
427*f0687c8aSRaman Tenneti Entry& e4 = add_entry(e3.children);
428*f0687c8aSRaman Tenneti e4.title = format_ob(plane);
429*f0687c8aSRaman Tenneti if (s_opts.print_props)
430*f0687c8aSRaman Tenneti e4.lines = format_props(plane);
431*f0687c8aSRaman Tenneti
432*f0687c8aSRaman Tenneti uint32_t fb_id = plane->fb_id();
433*f0687c8aSRaman Tenneti if (fb_id) {
434*f0687c8aSRaman Tenneti Framebuffer fb(card, fb_id);
435*f0687c8aSRaman Tenneti
436*f0687c8aSRaman Tenneti Entry& e5 = add_entry(e4.children);
437*f0687c8aSRaman Tenneti
438*f0687c8aSRaman Tenneti e5.title = format_ob(&fb);
439*f0687c8aSRaman Tenneti }
440*f0687c8aSRaman Tenneti }
441*f0687c8aSRaman Tenneti }
442*f0687c8aSRaman Tenneti }
443*f0687c8aSRaman Tenneti }
444*f0687c8aSRaman Tenneti
445*f0687c8aSRaman Tenneti print_entries(entries, "");
446*f0687c8aSRaman Tenneti }
447*f0687c8aSRaman Tenneti
print_modes(Card & card)448*f0687c8aSRaman Tenneti static void print_modes(Card& card)
449*f0687c8aSRaman Tenneti {
450*f0687c8aSRaman Tenneti for (Connector* conn : card.get_connectors()) {
451*f0687c8aSRaman Tenneti if (!conn->connected())
452*f0687c8aSRaman Tenneti continue;
453*f0687c8aSRaman Tenneti
454*f0687c8aSRaman Tenneti fmt::print("{}\n", format_ob(conn));
455*f0687c8aSRaman Tenneti
456*f0687c8aSRaman Tenneti auto modes = conn->get_modes();
457*f0687c8aSRaman Tenneti for (unsigned i = 0; i < modes.size(); ++i)
458*f0687c8aSRaman Tenneti fmt::print("{}\n", format_mode(modes[i], i));
459*f0687c8aSRaman Tenneti }
460*f0687c8aSRaman Tenneti }
461*f0687c8aSRaman Tenneti
462*f0687c8aSRaman Tenneti static const char* usage_str =
463*f0687c8aSRaman Tenneti "Usage: kmsprint [OPTIONS]\n\n"
464*f0687c8aSRaman Tenneti "Options:\n"
465*f0687c8aSRaman Tenneti " --device=DEVICE DEVICE is the path to DRM card to open\n"
466*f0687c8aSRaman Tenneti " -l, --list Print list instead of tree\n"
467*f0687c8aSRaman Tenneti " -m, --modes Print modes\n"
468*f0687c8aSRaman Tenneti " --xmode Print modes using X modeline\n"
469*f0687c8aSRaman Tenneti " -p, --props Print properties\n";
470*f0687c8aSRaman Tenneti
usage()471*f0687c8aSRaman Tenneti static void usage()
472*f0687c8aSRaman Tenneti {
473*f0687c8aSRaman Tenneti puts(usage_str);
474*f0687c8aSRaman Tenneti }
475*f0687c8aSRaman Tenneti
main(int argc,char ** argv)476*f0687c8aSRaman Tenneti int main(int argc, char** argv)
477*f0687c8aSRaman Tenneti {
478*f0687c8aSRaman Tenneti string dev_path;
479*f0687c8aSRaman Tenneti
480*f0687c8aSRaman Tenneti OptionSet optionset = {
481*f0687c8aSRaman Tenneti Option("|device=", [&dev_path](string s) {
482*f0687c8aSRaman Tenneti dev_path = s;
483*f0687c8aSRaman Tenneti }),
484*f0687c8aSRaman Tenneti Option("l|list", []() {
485*f0687c8aSRaman Tenneti s_opts.print_list = true;
486*f0687c8aSRaman Tenneti }),
487*f0687c8aSRaman Tenneti Option("m|modes", []() {
488*f0687c8aSRaman Tenneti s_opts.print_modes = true;
489*f0687c8aSRaman Tenneti }),
490*f0687c8aSRaman Tenneti Option("p|props", []() {
491*f0687c8aSRaman Tenneti s_opts.print_props = true;
492*f0687c8aSRaman Tenneti }),
493*f0687c8aSRaman Tenneti Option("|xmode", []() {
494*f0687c8aSRaman Tenneti s_opts.x_modeline = true;
495*f0687c8aSRaman Tenneti }),
496*f0687c8aSRaman Tenneti Option("h|help", []() {
497*f0687c8aSRaman Tenneti usage();
498*f0687c8aSRaman Tenneti exit(-1);
499*f0687c8aSRaman Tenneti }),
500*f0687c8aSRaman Tenneti };
501*f0687c8aSRaman Tenneti
502*f0687c8aSRaman Tenneti optionset.parse(argc, argv);
503*f0687c8aSRaman Tenneti
504*f0687c8aSRaman Tenneti if (optionset.params().size() > 0) {
505*f0687c8aSRaman Tenneti usage();
506*f0687c8aSRaman Tenneti exit(-1);
507*f0687c8aSRaman Tenneti }
508*f0687c8aSRaman Tenneti
509*f0687c8aSRaman Tenneti Card card(dev_path);
510*f0687c8aSRaman Tenneti
511*f0687c8aSRaman Tenneti if (s_opts.print_modes) {
512*f0687c8aSRaman Tenneti print_modes(card);
513*f0687c8aSRaman Tenneti return 0;
514*f0687c8aSRaman Tenneti }
515*f0687c8aSRaman Tenneti
516*f0687c8aSRaman Tenneti if (s_opts.print_list)
517*f0687c8aSRaman Tenneti print_as_list(card);
518*f0687c8aSRaman Tenneti else
519*f0687c8aSRaman Tenneti print_as_tree(card);
520*f0687c8aSRaman Tenneti }
521