1 #include <cstdio>
2 #include <algorithm>
3 #include <iostream>
5 #include "kms++.h"
6 #include "opts.h"
8 using namespace std;
9 using namespace kms;
11 namespace kmsprint {
13 static struct {
14 bool print_props;
15 bool print_modes;
16 bool recurse;
17 } opts;
19 string width(int w, string str)
20 {
21 str.resize(w, ' ');
22 return str;
23 }
25 void print_mode(const Videomode &m, int ind)
26 {
27 printf("%s%s %6d %4d %4d %4d %4d %d %4d %4d %4d %4d %d %2d 0x%04x %2d\n",
28 width(ind, "").c_str(),
29 m.name[0] == '\0' ? "" : width(11, m.name).c_str(),
30 m.clock,
31 m.hdisplay,
32 m.hsync_start,
33 m.hsync_end,
34 m.htotal,
35 m.hskew,
36 m.vdisplay,
37 m.vsync_start,
38 m.vsync_end,
39 m.vtotal,
40 m.vscan,
41 m.vrefresh,
42 m.flags,
43 m.type);
44 }
46 void print_property(uint64_t val, const Property& p, int ind)
47 {
48 printf("%s%s (id %d) = %s\n", width(ind, "").c_str(),
49 p.name().c_str(), p.id(), p.to_str(val).c_str());
50 }
52 void print_properties(DrmPropObject& o, int ind)
53 {
54 auto pmap = o.get_prop_map();
55 printf("%sProperties, %u in total:\n", width(ind, "").c_str(),
56 (unsigned) pmap.size());
57 for (auto pp : pmap) {
58 const Property& p = *o.card().get_prop(pp.first);
59 print_property(pp.second, p, ind + 2);
60 }
61 }
63 void print_plane(Plane& p, int ind)
64 {
65 printf("%sPlane Id %d %d,%d -> %dx%d formats:", width(ind, "").c_str(),
66 p.id(), p.crtc_x(), p.crtc_y(), p.x(), p.y());
67 for (auto f : p.get_formats())
68 printf(" %s", PixelFormatToFourCC(f).c_str());
69 printf("\n");
71 if (opts.print_props)
72 print_properties(p, ind+2);
73 }
75 void print_crtc(Crtc& cc, int ind)
76 {
77 printf("%sCRTC Id %d BufferId %d %dx%d at %dx%d gamma_size %d\n",
78 width(ind, "").c_str(), cc.id(), cc.buffer_id(), cc.width(),
79 cc.height(), cc.x(), cc.y(), cc.gamma_size());
81 printf("%s Mode ", width(ind, "").c_str());
82 print_mode(cc.mode(), 0);
84 if (opts.print_props)
85 print_properties(cc, ind+2);
87 if (opts.recurse)
88 for (auto p : cc.get_possible_planes())
89 print_plane(*p, ind + 2);
90 }
92 void print_encoder(Encoder& e, int ind)
93 {
94 printf("%sEncoder Id %d type %s\n", width(ind, "").c_str(),
95 e.id(), e.get_encoder_type().c_str());
97 if (opts.print_props)
98 print_properties(e, ind+2);
100 if (opts.recurse)
101 for (auto cc : e.get_possible_crtcs())
102 print_crtc(*cc, ind + 2);
103 }
105 void print_connector(Connector& c, int ind)
106 {
107 printf("%sConnector %s Id %d %sconnected", width(ind, "").c_str(),
108 c.fullname().c_str(), c.id(), c.connected() ? "" : "dis");
109 if (c.subpixel() != 0)
110 printf(" Subpixel: %s", c.subpixel_str().c_str());
111 printf("\n");
113 if (opts.print_props)
114 print_properties(c, ind+2);
116 if (opts.recurse)
117 for (auto enc : c.get_encoders())
118 print_encoder(*enc, ind + 2);
120 if (opts.print_modes) {
121 auto modes = c.get_modes();
122 printf("%sModes, %u in total:\n", width(ind + 2, "").c_str(),
123 (unsigned) modes.size());
124 for (auto mode : modes)
125 print_mode(mode, ind + 3);
126 }
127 }
129 }
131 using namespace kmsprint;
133 static const char* usage_str =
134 "Usage: kmsprint [OPTIONS]\n\n"
135 "Options:\n"
136 " -m, --modes Print modes\n"
137 " -p, --props Print properties\n"
138 " -r, --recurse Recursively print all related objects\n"
139 " --id=<ID> Print object <ID>\n"
140 ;
142 static void usage()
143 {
144 puts(usage_str);
145 }
147 int main(int argc, char **argv)
148 {
149 string dev_path;
150 unsigned id = 0;
152 OptionSet optionset = {
153 Option("|device=",
154 [&](string s)
155 {
156 dev_path = s;
157 }),
158 Option("|id=",
159 [&](string s)
160 {
161 id = stoul(s);
162 }),
163 Option("p", [&](string s)
164 {
165 opts.print_props = true;
166 }),
167 Option("m", [&](string s)
168 {
169 opts.print_modes = true;
170 }),
171 Option("r", [&](string s)
172 {
173 opts.recurse = true;
174 }),
175 Option("h|help", [&]()
176 {
177 usage();
178 exit(-1);
179 }),
180 };
182 optionset.parse(argc, argv);
184 if (optionset.params().size() > 0) {
185 usage();
186 exit(-1);
187 }
189 Card card;
191 /* No options impliles recursion */
192 if (id == 0) {
193 opts.recurse = true;
194 for (auto conn : card.get_connectors())
195 print_connector(*conn, 0);
196 return 0;
197 } else {
198 auto ob = card.get_object(id);
199 if (!ob) {
200 cerr << "kmsprint" << ": Object id " <<
201 id << " not found." << endl;
202 return -1;
203 }
205 if (auto co = dynamic_cast<Connector*>(ob))
206 print_connector(*co, 0);
207 else if (auto en = dynamic_cast<Encoder*>(ob))
208 print_encoder(*en, 0);
209 else if (auto cr = dynamic_cast<Crtc*>(ob))
210 print_crtc(*cr, 0);
211 else if (auto pl = dynamic_cast<Plane*>(ob))
212 print_plane(*pl, 0);
213 else {
214 cerr << "kmsprint" << ": Unkown DRM Object type" <<
215 endl;
216 return -1;
217 }
219 return 0;
220 }
221 }