1 #include <cstdio>
2 #include <unistd.h>
3 #include <algorithm>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <cstring>
8
9 #include <libevdev/libevdev.h>
10 #include <libevdev/libevdev-uinput.h>
11
12 #include <kms++/kms++.h>
13 #include <kms++util/kms++util.h>
14
15 using namespace std;
16 using namespace kms;
17
18 static const char* usage_str =
19 "Usage: kmstouch [OPTION]...\n\n"
20 "Simple touchscreen tester\n\n"
21 "Options:\n"
22 " --input=DEVICE DEVICE is the path to input device to open\n"
23 " --device=DEVICE DEVICE is the path to DRM card to open\n"
24 " -c, --connector=CONN CONN is <connector>\n"
25 "\n";
26
usage()27 static void usage()
28 {
29 puts(usage_str);
30 }
31
32 static bool s_print_ev = false;
33
34 static vector<pair<int32_t, int32_t>> s_coords;
35
36 // axis -> min,max
37 static map<int, pair<int32_t, int32_t>> s_abs_map;
38 // axis -> value
39 static map<int, int32_t> s_abs_vals;
40
print_abs_bits(struct libevdev * dev,int axis)41 static void print_abs_bits(struct libevdev* dev, int axis)
42 {
43 const struct input_absinfo* abs;
44
45 if (!libevdev_has_event_code(dev, EV_ABS, axis))
46 return;
47
48 abs = libevdev_get_abs_info(dev, axis);
49
50 printf(" Value %6d\n", abs->value);
51 printf(" Min %6d\n", abs->minimum);
52 printf(" Max %6d\n", abs->maximum);
53 if (abs->fuzz)
54 printf(" Fuzz %6d\n", abs->fuzz);
55 if (abs->flat)
56 printf(" Flat %6d\n", abs->flat);
57 if (abs->resolution)
58 printf(" Resolution %6d\n", abs->resolution);
59 }
60
print_code_bits(struct libevdev * dev,unsigned int type,unsigned int max)61 static void print_code_bits(struct libevdev* dev, unsigned int type, unsigned int max)
62 {
63 for (uint32_t i = 0; i <= max; i++) {
64 if (!libevdev_has_event_code(dev, type, i))
65 continue;
66
67 printf(" Event code %i (%s)\n", i, libevdev_event_code_get_name(type, i));
68 if (type == EV_ABS)
69 print_abs_bits(dev, i);
70 }
71 }
72
print_bits(struct libevdev * dev)73 static void print_bits(struct libevdev* dev)
74 {
75 printf("Supported events:\n");
76
77 for (uint32_t i = 0; i <= EV_MAX; i++) {
78 if (!libevdev_has_event_type(dev, i))
79 continue;
80
81 printf(" Event type %d (%s)\n", i, libevdev_event_type_get_name(i));
82
83 switch (i) {
84 case EV_KEY:
85 print_code_bits(dev, EV_KEY, KEY_MAX);
86 break;
87 case EV_REL:
88 print_code_bits(dev, EV_REL, REL_MAX);
89 break;
90 case EV_ABS:
91 print_code_bits(dev, EV_ABS, ABS_MAX);
92 break;
93 case EV_LED:
94 print_code_bits(dev, EV_LED, LED_MAX);
95 break;
96 }
97 }
98 }
99
collect_current(struct libevdev * dev)100 static void collect_current(struct libevdev* dev)
101 {
102 for (uint32_t i = 0; i <= ABS_MAX; i++) {
103 if (!libevdev_has_event_code(dev, EV_ABS, i))
104 continue;
105
106 const struct input_absinfo* abs;
107
108 abs = libevdev_get_abs_info(dev, i);
109
110 s_abs_vals[i] = abs->value;
111 s_abs_map[i] = make_pair(abs->minimum, abs->maximum);
112 }
113 }
114
print_props(struct libevdev * dev)115 static void print_props(struct libevdev* dev)
116 {
117 printf("Properties:\n");
118
119 for (uint32_t i = 0; i <= INPUT_PROP_MAX; i++) {
120 if (!libevdev_has_property(dev, i))
121 continue;
122
123 printf(" Property type %d (%s)\n", i, libevdev_property_get_name(i));
124 }
125 }
126
handle_event(struct input_event & ev,DumbFramebuffer * fb)127 static void handle_event(struct input_event& ev, DumbFramebuffer* fb)
128 {
129 static vector<pair<uint16_t, int32_t>> s_event_vec;
130
131 if (s_print_ev)
132 printf("%-6s %20s %6d\n",
133 libevdev_event_type_get_name(ev.type),
134 libevdev_event_code_get_name(ev.type, ev.code),
135 ev.value);
136
137 switch (ev.type) {
138 case EV_ABS:
139 s_event_vec.emplace_back(ev.code, ev.value);
140 break;
141
142 case EV_KEY:
143 s_event_vec.emplace_back(ev.code, ev.value);
144 break;
145
146 case EV_SYN:
147 switch (ev.code) {
148 case SYN_REPORT: {
149 int32_t min_x = s_abs_map[ABS_X].first;
150 int32_t max_x = s_abs_map[ABS_X].second;
151
152 int32_t min_y = s_abs_map[ABS_Y].first;
153 int32_t max_y = s_abs_map[ABS_Y].second;
154
155 for (const auto& p : s_event_vec) {
156 switch (p.first) {
157 case ABS_X:
158 case ABS_Y:
159 s_abs_vals[p.first] = p.second;
160 break;
161 default:
162 break;
163 }
164 }
165
166 int32_t abs_x = s_abs_vals[ABS_X];
167 int32_t abs_y = s_abs_vals[ABS_Y];
168
169 int32_t x = (abs_x - min_x) * (fb->width() - 1) / (max_x - min_x);
170 int32_t y = (abs_y - min_y) * (fb->height() - 1) / (max_y - min_y);
171
172 printf("%d, %d -> %d, %d\n", abs_x, abs_y, x, y);
173
174 draw_rgb_pixel(*fb, x, y, RGB(255, 255, 255));
175
176 s_event_vec.clear();
177
178 if (s_print_ev)
179 printf("----\n");
180 break;
181 }
182
183 default:
184 EXIT("Unhandled syn event code %u\n", ev.code);
185 break;
186 }
187
188 break;
189
190 default:
191 EXIT("Unhandled event type %u\n", ev.type);
192 break;
193 }
194 }
195
main(int argc,char ** argv)196 int main(int argc, char** argv)
197 {
198 string drm_dev_path = "/dev/dri/card0";
199 string input_dev_path = "/dev/input/event0";
200 string conn_name;
201
202 OptionSet optionset = {
203 Option("i|input=", [&input_dev_path](string s) {
204 input_dev_path = s;
205 }),
206 Option("|device=", [&drm_dev_path](string s) {
207 drm_dev_path = s;
208 }),
209 Option("c|connector=", [&conn_name](string s) {
210 conn_name = s;
211 }),
212 Option("h|help", []() {
213 usage();
214 exit(-1);
215 }),
216 };
217
218 optionset.parse(argc, argv);
219
220 if (optionset.params().size() > 0) {
221 usage();
222 exit(-1);
223 }
224
225 struct libevdev* dev = nullptr;
226
227 int fd = open(input_dev_path.c_str(), O_RDONLY | O_NONBLOCK);
228 FAIL_IF(fd < 0, "Failed to open input device %s: %s\n", input_dev_path.c_str(), strerror(errno));
229 int rc = libevdev_new_from_fd(fd, &dev);
230 FAIL_IF(rc < 0, "Failed to init libevdev (%s)\n", strerror(-rc));
231
232 printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
233 printf("Input device ID: bus %#x vendor %#x product %#x\n",
234 libevdev_get_id_bustype(dev),
235 libevdev_get_id_vendor(dev),
236 libevdev_get_id_product(dev));
237
238 if (!libevdev_has_event_type(dev, EV_ABS) ||
239 !libevdev_has_event_code(dev, EV_KEY, BTN_TOUCH)) {
240 printf("This device does not look like a mouse\n");
241 exit(1);
242 }
243
244 print_bits(dev);
245 print_props(dev);
246
247 collect_current(dev);
248
249 Card card(drm_dev_path);
250 ResourceManager resman(card);
251
252 auto pixfmt = PixelFormat::XRGB8888;
253
254 Connector* conn = resman.reserve_connector(conn_name);
255 Crtc* crtc = resman.reserve_crtc(conn);
256 Plane* plane = resman.reserve_overlay_plane(crtc, pixfmt);
257
258 Videomode mode = conn->get_default_mode();
259
260 uint32_t w = mode.hdisplay;
261 uint32_t h = mode.vdisplay;
262
263 auto fb = new DumbFramebuffer(card, w, h, pixfmt);
264
265 AtomicReq req(card);
266
267 req.add(plane, "CRTC_ID", crtc->id());
268 req.add(plane, "FB_ID", fb->id());
269
270 req.add(plane, "CRTC_X", 0);
271 req.add(plane, "CRTC_Y", 0);
272 req.add(plane, "CRTC_W", w);
273 req.add(plane, "CRTC_H", h);
274
275 req.add(plane, "SRC_X", 0);
276 req.add(plane, "SRC_Y", 0);
277 req.add(plane, "SRC_W", w << 16);
278 req.add(plane, "SRC_H", h << 16);
279
280 int r = req.commit_sync();
281 FAIL_IF(r, "initial plane setup failed");
282
283 do {
284 struct input_event ev {
285 };
286 rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
287 if (rc == 0)
288 handle_event(ev, fb);
289
290 } while (rc == 1 || rc == 0 || rc == -EAGAIN);
291
292 delete fb;
293 }
294