1 /*
2  * Copyright © 2014 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "config.h"
25 
26 #include <errno.h>
27 #include <inttypes.h>
28 #include <getopt.h>
29 #include <poll.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include "linux/input.h"
37 
38 #include <libinput.h>
39 #include <libevdev/libevdev.h>
40 
41 #include "libinput-version.h"
42 #include "util-strings.h"
43 #include "util-macros.h"
44 #include "shared.h"
45 
46 static uint32_t start_time;
47 static const uint32_t screen_width = 100;
48 static const uint32_t screen_height = 100;
49 static struct tools_options options;
50 static bool show_keycodes;
51 static volatile sig_atomic_t stop = 0;
52 static bool be_quiet = false;
53 
54 #define printq(...) ({ if (!be_quiet)  printf(__VA_ARGS__); })
55 
56 static void
print_event_header(struct libinput_event *ev)57 print_event_header(struct libinput_event *ev)
58 {
59 	/* use for pointer value only, do not dereference */
60 	static void *last_device = NULL;
61 	struct libinput_device *dev = libinput_event_get_device(ev);
62 	const char *type = NULL;
63 	char prefix;
64 
65 	switch(libinput_event_get_type(ev)) {
66 	case LIBINPUT_EVENT_NONE:
67 		abort();
68 	case LIBINPUT_EVENT_DEVICE_ADDED:
69 		type = "DEVICE_ADDED";
70 		break;
71 	case LIBINPUT_EVENT_DEVICE_REMOVED:
72 		type = "DEVICE_REMOVED";
73 		break;
74 	case LIBINPUT_EVENT_KEYBOARD_KEY:
75 		type = "KEYBOARD_KEY";
76 		break;
77 	case LIBINPUT_EVENT_POINTER_MOTION:
78 		type = "POINTER_MOTION";
79 		break;
80 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
81 		type = "POINTER_MOTION_ABSOLUTE";
82 		break;
83 	case LIBINPUT_EVENT_POINTER_BUTTON:
84 		type = "POINTER_BUTTON";
85 		break;
86 	case LIBINPUT_EVENT_POINTER_AXIS:
87 		type = "POINTER_AXIS";
88 		break;
89 	case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
90 		type = "POINTER_SCROLL_WHEEL";
91 		break;
92 	case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
93 		type = "POINTER_SCROLL_FINGER";
94 		break;
95 	case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
96 		type = "POINTER_SCROLL_CONTINUOUS";
97 		break;
98 	case LIBINPUT_EVENT_TOUCH_DOWN:
99 		type = "TOUCH_DOWN";
100 		break;
101 	case LIBINPUT_EVENT_TOUCH_MOTION:
102 		type = "TOUCH_MOTION";
103 		break;
104 	case LIBINPUT_EVENT_TOUCH_UP:
105 		type = "TOUCH_UP";
106 		break;
107 	case LIBINPUT_EVENT_TOUCH_CANCEL:
108 		type = "TOUCH_CANCEL";
109 		break;
110 	case LIBINPUT_EVENT_TOUCH_FRAME:
111 		type = "TOUCH_FRAME";
112 		break;
113 	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
114 		type = "GESTURE_SWIPE_BEGIN";
115 		break;
116 	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
117 		type = "GESTURE_SWIPE_UPDATE";
118 		break;
119 	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
120 		type = "GESTURE_SWIPE_END";
121 		break;
122 	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
123 		type = "GESTURE_PINCH_BEGIN";
124 		break;
125 	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
126 		type = "GESTURE_PINCH_UPDATE";
127 		break;
128 	case LIBINPUT_EVENT_GESTURE_PINCH_END:
129 		type = "GESTURE_PINCH_END";
130 		break;
131 	case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
132 		type = "GESTURE_HOLD_BEGIN";
133 		break;
134 	case LIBINPUT_EVENT_GESTURE_HOLD_END:
135 		type = "GESTURE_HOLD_END";
136 		break;
137 	case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
138 		type = "TABLET_TOOL_AXIS";
139 		break;
140 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
141 		type = "TABLET_TOOL_PROXIMITY";
142 		break;
143 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
144 		type = "TABLET_TOOL_TIP";
145 		break;
146 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
147 		type = "TABLET_TOOL_BUTTON";
148 		break;
149 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
150 		type = "TABLET_PAD_BUTTON";
151 		break;
152 	case LIBINPUT_EVENT_TABLET_PAD_RING:
153 		type = "TABLET_PAD_RING";
154 		break;
155 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
156 		type = "TABLET_PAD_STRIP";
157 		break;
158 	case LIBINPUT_EVENT_TABLET_PAD_KEY:
159 		type = "TABLET_PAD_KEY";
160 		break;
161 	case LIBINPUT_EVENT_SWITCH_TOGGLE:
162 		type = "SWITCH_TOGGLE";
163 		break;
164 	}
165 
166 	prefix = (last_device != dev) ? '-' : ' ';
167 
168 	printq("%c%-7s  %-23s ",
169 	       prefix,
170 	       libinput_device_get_sysname(dev),
171 	       type);
172 
173 	last_device = dev;
174 }
175 
176 static void
print_event_time(uint32_t time)177 print_event_time(uint32_t time)
178 {
179 	printq("%+6.3fs	", start_time ? (time - start_time) / 1000.0 : 0);
180 }
181 
182 static inline void
print_device_options(struct libinput_device *dev)183 print_device_options(struct libinput_device *dev)
184 {
185 	uint32_t scroll_methods, click_methods;
186 
187 	if (libinput_device_config_tap_get_finger_count(dev)) {
188 	    printq(" tap");
189 	    if (libinput_device_config_tap_get_drag_lock_enabled(dev))
190 		    printq("(dl on)");
191 	    else
192 		    printq("(dl off)");
193 	}
194 	if (libinput_device_config_left_handed_is_available(dev))
195 	    printq(" left");
196 	if (libinput_device_config_scroll_has_natural_scroll(dev))
197 	    printq(" scroll-nat");
198 	if (libinput_device_config_calibration_has_matrix(dev))
199 	    printq(" calib");
200 
201 	scroll_methods = libinput_device_config_scroll_get_methods(dev);
202 	if (scroll_methods != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
203 		printq(" scroll");
204 		if (scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG)
205 			printq("-2fg");
206 		if (scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE)
207 			printq("-edge");
208 		if (scroll_methods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)
209 			printq("-button");
210 	}
211 
212 	click_methods = libinput_device_config_click_get_methods(dev);
213 	if (click_methods != LIBINPUT_CONFIG_CLICK_METHOD_NONE) {
214 		printq(" click");
215 		if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
216 			printq("-buttonareas");
217 		if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER)
218 			printq("-clickfinger");
219 	}
220 
221 	if (libinput_device_config_dwt_is_available(dev)) {
222 		if (libinput_device_config_dwt_get_enabled(dev) ==
223 		    LIBINPUT_CONFIG_DWT_ENABLED)
224 			printq(" dwt-on");
225 		else
226 			printq(" dwt-off)");
227 	}
228 
229 	if (libinput_device_config_dwtp_is_available(dev)) {
230 		if (libinput_device_config_dwtp_get_enabled(dev) ==
231 		    LIBINPUT_CONFIG_DWTP_ENABLED)
232 			printq(" dwtp-on");
233 		else
234 			printq(" dwtp-off)");
235 	}
236 
237 	if (libinput_device_has_capability(dev,
238 					   LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
239 		int nbuttons, nstrips, nrings, ngroups;
240 
241 		nbuttons = libinput_device_tablet_pad_get_num_buttons(dev);
242 		nstrips = libinput_device_tablet_pad_get_num_strips(dev);
243 		nrings = libinput_device_tablet_pad_get_num_rings(dev);
244 		ngroups = libinput_device_tablet_pad_get_num_mode_groups(dev);
245 
246 		printq(" buttons:%d strips:%d rings:%d mode groups:%d",
247 		       nbuttons,
248 		       nstrips,
249 		       nrings,
250 		       ngroups);
251 	}
252 }
253 
254 static void
print_device_notify(struct libinput_event *ev)255 print_device_notify(struct libinput_event *ev)
256 {
257 	struct libinput_device *dev = libinput_event_get_device(ev);
258 	struct libinput_seat *seat = libinput_device_get_seat(dev);
259 	struct libinput_device_group *group;
260 	double w, h;
261 	static int next_group_id = 0;
262 	intptr_t group_id;
263 
264 	group = libinput_device_get_device_group(dev);
265 	group_id = (intptr_t)libinput_device_group_get_user_data(group);
266 	if (!group_id) {
267 		group_id = ++next_group_id;
268 		libinput_device_group_set_user_data(group, (void*)group_id);
269 	}
270 
271 	printq("%-33s %5s %7s group%-2d",
272 	       libinput_device_get_name(dev),
273 	       libinput_seat_get_physical_name(seat),
274 	       libinput_seat_get_logical_name(seat),
275 	       (int)group_id);
276 
277 	printq(" cap:");
278 	if (libinput_device_has_capability(dev,
279 					   LIBINPUT_DEVICE_CAP_KEYBOARD))
280 		printq("k");
281 	if (libinput_device_has_capability(dev,
282 					   LIBINPUT_DEVICE_CAP_POINTER))
283 		printq("p");
284 	if (libinput_device_has_capability(dev,
285 					   LIBINPUT_DEVICE_CAP_TOUCH))
286 		printq("t");
287 	if (libinput_device_has_capability(dev,
288 					   LIBINPUT_DEVICE_CAP_GESTURE))
289 		printq("g");
290 	if (libinput_device_has_capability(dev,
291 					   LIBINPUT_DEVICE_CAP_TABLET_TOOL))
292 		printq("T");
293 	if (libinput_device_has_capability(dev,
294 					   LIBINPUT_DEVICE_CAP_TABLET_PAD))
295 		printq("P");
296 	if (libinput_device_has_capability(dev,
297 					   LIBINPUT_DEVICE_CAP_SWITCH))
298 		printq("S");
299 
300 	if (libinput_device_get_size(dev, &w, &h) == 0)
301 		printq("  size %.0fx%.0fmm", w, h);
302 
303 	if (libinput_device_has_capability(dev,
304 					   LIBINPUT_DEVICE_CAP_TOUCH))
305 		printq(" ntouches %d", libinput_device_touch_get_touch_count(dev));
306 
307 	if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
308 		print_device_options(dev);
309 
310 	printq("\n");
311 
312 }
313 
314 static void
print_key_event(struct libinput_event *ev)315 print_key_event(struct libinput_event *ev)
316 {
317 	struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
318 	enum libinput_key_state state;
319 	uint32_t key;
320 	const char *keyname;
321 
322 	print_event_time(libinput_event_keyboard_get_time(k));
323 	state = libinput_event_keyboard_get_key_state(k);
324 
325 	key = libinput_event_keyboard_get_key(k);
326 	if (!show_keycodes && (key >= KEY_ESC && key < KEY_ZENKAKUHANKAKU)) {
327 		keyname = "***";
328 		key = -1;
329 	} else {
330 		keyname = libevdev_event_code_get_name(EV_KEY, key);
331 		keyname = keyname ? keyname : "???";
332 	}
333 	printq("%s (%d) %s\n",
334 	       keyname,
335 	       key,
336 	       state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
337 }
338 
339 static void
print_motion_event(struct libinput_event *ev)340 print_motion_event(struct libinput_event *ev)
341 {
342 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
343 	double x = libinput_event_pointer_get_dx(p);
344 	double y = libinput_event_pointer_get_dy(p);
345 	double ux = libinput_event_pointer_get_dx_unaccelerated(p);
346 	double uy = libinput_event_pointer_get_dy_unaccelerated(p);
347 
348 	print_event_time(libinput_event_pointer_get_time(p));
349 
350 	printq("%6.2f/%6.2f (%+6.2f/%+6.2f)\n", x, y, ux, uy);
351 }
352 
353 static void
print_absmotion_event(struct libinput_event *ev)354 print_absmotion_event(struct libinput_event *ev)
355 {
356 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
357 	double x = libinput_event_pointer_get_absolute_x_transformed(
358 		p, screen_width);
359 	double y = libinput_event_pointer_get_absolute_y_transformed(
360 		p, screen_height);
361 
362 	print_event_time(libinput_event_pointer_get_time(p));
363 	printq("%6.2f/%6.2f\n", x, y);
364 }
365 
366 static void
print_pointer_button_event(struct libinput_event *ev)367 print_pointer_button_event(struct libinput_event *ev)
368 {
369 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
370 	enum libinput_button_state state;
371 	const char *buttonname;
372 	int button;
373 
374 	print_event_time(libinput_event_pointer_get_time(p));
375 
376 	button = libinput_event_pointer_get_button(p);
377 	buttonname = libevdev_event_code_get_name(EV_KEY, button);
378 
379 	state = libinput_event_pointer_get_button_state(p);
380 	printq("%s (%d) %s, seat count: %u\n",
381 	       buttonname ? buttonname : "???",
382 	       button,
383 	       state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
384 	       libinput_event_pointer_get_seat_button_count(p));
385 }
386 
387 static void
print_tablet_axes(struct libinput_event_tablet_tool *t)388 print_tablet_axes(struct libinput_event_tablet_tool *t)
389 {
390 	struct libinput_tablet_tool *tool = libinput_event_tablet_tool_get_tool(t);
391 	double x, y;
392 	double dist, pressure;
393 	double rotation, slider, wheel;
394 	double delta;
395 	double major, minor;
396 
397 #define changed_sym(ev, ax) \
398 	(libinput_event_tablet_tool_##ax##_has_changed(ev) ? "*" : "")
399 
400 	x = libinput_event_tablet_tool_get_x(t);
401 	y = libinput_event_tablet_tool_get_y(t);
402 	printq("\t%.2f%s/%.2f%s",
403 	       x, changed_sym(t, x),
404 	       y, changed_sym(t, y));
405 
406 	if (libinput_tablet_tool_has_tilt(tool)) {
407 		x = libinput_event_tablet_tool_get_tilt_x(t);
408 		y = libinput_event_tablet_tool_get_tilt_y(t);
409 		printq("\ttilt: %.2f%s/%.2f%s",
410 		       x, changed_sym(t, tilt_x),
411 		       y, changed_sym(t, tilt_y));
412 	}
413 
414 	if (libinput_tablet_tool_has_distance(tool) ||
415 	    libinput_tablet_tool_has_pressure(tool)) {
416 		dist = libinput_event_tablet_tool_get_distance(t);
417 		pressure = libinput_event_tablet_tool_get_pressure(t);
418 		if (dist)
419 			printq("\tdistance: %.2f%s",
420 			       dist, changed_sym(t, distance));
421 		else
422 			printq("\tpressure: %.2f%s",
423 			       pressure, changed_sym(t, pressure));
424 	}
425 
426 	if (libinput_tablet_tool_has_rotation(tool)) {
427 		rotation = libinput_event_tablet_tool_get_rotation(t);
428 		printq("\trotation: %6.2f%s",
429 		       rotation, changed_sym(t, rotation));
430 	}
431 
432 	if (libinput_tablet_tool_has_slider(tool)) {
433 		slider = libinput_event_tablet_tool_get_slider_position(t);
434 		printq("\tslider: %.2f%s",
435 		       slider, changed_sym(t, slider));
436 	}
437 
438 	if (libinput_tablet_tool_has_wheel(tool)) {
439 		wheel = libinput_event_tablet_tool_get_wheel_delta(t);
440 		delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t);
441 		printq("\twheel: %.2f%s (%d)",
442 		       wheel, changed_sym(t, wheel),
443 		       (int)delta);
444 	}
445 
446 	if (libinput_tablet_tool_has_size(tool)) {
447 		major = libinput_event_tablet_tool_get_size_major(t);
448 		minor = libinput_event_tablet_tool_get_size_minor(t);
449 		printq("\tsize: %.2f%s/%.2f%s",
450 		       major, changed_sym(t, size_major),
451 		       minor, changed_sym(t, size_minor));
452 	}
453 }
454 
455 static void
print_tablet_tip_event(struct libinput_event *ev)456 print_tablet_tip_event(struct libinput_event *ev)
457 {
458 	struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
459 	enum libinput_tablet_tool_tip_state state;
460 
461 	print_event_time(libinput_event_tablet_tool_get_time(t));
462 
463 	print_tablet_axes(t);
464 
465 	state = libinput_event_tablet_tool_get_tip_state(t);
466 	printq(" %s\n", state == LIBINPUT_TABLET_TOOL_TIP_DOWN ? "down" : "up");
467 }
468 
469 static void
print_tablet_button_event(struct libinput_event *ev)470 print_tablet_button_event(struct libinput_event *ev)
471 {
472 	struct libinput_event_tablet_tool *p = libinput_event_get_tablet_tool_event(ev);
473 	enum libinput_button_state state;
474 	const char *buttonname;
475 	int button;
476 
477 	print_event_time(libinput_event_tablet_tool_get_time(p));
478 
479 	button = libinput_event_tablet_tool_get_button(p);
480 	buttonname = libevdev_event_code_get_name(EV_KEY, button);
481 
482 	state = libinput_event_tablet_tool_get_button_state(p);
483 	printq("%3d (%s) %s, seat count: %u\n",
484 	       button,
485 	       buttonname ? buttonname : "???",
486 	       state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
487 	       libinput_event_tablet_tool_get_seat_button_count(p));
488 }
489 
490 static void
print_pointer_axis_event(struct libinput_event *ev)491 print_pointer_axis_event(struct libinput_event *ev)
492 {
493 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
494 	double v = 0, h = 0, v120 = 0, h120 = 0;
495 	const char *have_vert = "",
496 		   *have_horiz = "";
497 	const char *source = NULL;
498 	enum libinput_pointer_axis axis;
499 	enum libinput_event_type type;
500 
501 	type = libinput_event_get_type(ev);
502 
503 	switch (type) {
504 	case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
505 		source = "wheel";
506 		break;
507 	case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
508 		source = "finger";
509 		break;
510 	case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
511 		source = "continuous";
512 		break;
513 	default:
514 		abort();
515 		break;
516 	}
517 
518 	axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
519 	if (libinput_event_pointer_has_axis(p, axis)) {
520 		v = libinput_event_pointer_get_scroll_value(p, axis);
521 		if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL)
522 			v120 = libinput_event_pointer_get_scroll_value_v120(p, axis);
523 		have_vert = "*";
524 	}
525 	axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
526 	if (libinput_event_pointer_has_axis(p, axis)) {
527 		h = libinput_event_pointer_get_scroll_value(p, axis);
528 		if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL)
529 			h120 = libinput_event_pointer_get_scroll_value_v120(p, axis);
530 		have_horiz = "*";
531 	}
532 
533 	print_event_time(libinput_event_pointer_get_time(p));
534 	printq("vert %.2f/%.1f%s horiz %.2f/%.1f%s (%s)\n",
535 	       v, v120, have_vert,
536 	       h, h120, have_horiz, source);
537 }
538 
539 static void
print_tablet_axis_event(struct libinput_event *ev)540 print_tablet_axis_event(struct libinput_event *ev)
541 {
542 	struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
543 
544 	print_event_time(libinput_event_tablet_tool_get_time(t));
545 	print_tablet_axes(t);
546 	printq("\n");
547 }
548 
549 static void
print_proximity_event(struct libinput_event *ev)550 print_proximity_event(struct libinput_event *ev)
551 {
552 	struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
553 	struct libinput_tablet_tool *tool = libinput_event_tablet_tool_get_tool(t);
554 	enum libinput_tablet_tool_proximity_state state;
555 	const char *tool_str,
556 	           *state_str;
557 
558 	switch (libinput_tablet_tool_get_type(tool)) {
559 	case LIBINPUT_TABLET_TOOL_TYPE_PEN:
560 		tool_str = "pen";
561 		break;
562 	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
563 		tool_str = "eraser";
564 		break;
565 	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
566 		tool_str = "brush";
567 		break;
568 	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
569 		tool_str = "pencil";
570 		break;
571 	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
572 		tool_str = "airbrush";
573 		break;
574 	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
575 		tool_str = "mouse";
576 		break;
577 	case LIBINPUT_TABLET_TOOL_TYPE_LENS:
578 		tool_str = "lens";
579 		break;
580 	case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
581 		tool_str = "totem";
582 		break;
583 	default:
584 		abort();
585 	}
586 
587 	state = libinput_event_tablet_tool_get_proximity_state(t);
588 
589 	print_event_time(libinput_event_tablet_tool_get_time(t));
590 
591 	if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) {
592 		print_tablet_axes(t);
593 		state_str = "proximity-in";
594 	} else if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) {
595 		print_tablet_axes(t);
596 		state_str = "proximity-out";
597 	} else {
598 		abort();
599 	}
600 
601 	printq("\t%-8s (%#" PRIx64 ", id %#" PRIx64 ") %s ",
602 	       tool_str,
603 	       libinput_tablet_tool_get_serial(tool),
604 	       libinput_tablet_tool_get_tool_id(tool),
605 	       state_str);
606 
607 	if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) {
608 		printq("\taxes:");
609 		if (libinput_tablet_tool_has_distance(tool))
610 			printq("d");
611 		if (libinput_tablet_tool_has_pressure(tool))
612 			printq("p");
613 		if (libinput_tablet_tool_has_tilt(tool))
614 			printq("t");
615 		if (libinput_tablet_tool_has_rotation(tool))
616 			printq("r");
617 		if (libinput_tablet_tool_has_slider(tool))
618 			printq("s");
619 		if (libinput_tablet_tool_has_wheel(tool))
620 			printq("w");
621 		if (libinput_tablet_tool_has_size(tool))
622 			printq("S");
623 
624 		printq("\tbtn:");
625 		if (libinput_tablet_tool_has_button(tool, BTN_TOUCH))
626 			printq("T");
627 		if (libinput_tablet_tool_has_button(tool, BTN_STYLUS))
628 			printq("S");
629 		if (libinput_tablet_tool_has_button(tool, BTN_STYLUS2))
630 			printq("S2");
631 		if (libinput_tablet_tool_has_button(tool, BTN_LEFT))
632 			printq("L");
633 		if (libinput_tablet_tool_has_button(tool, BTN_MIDDLE))
634 			printq("M");
635 		if (libinput_tablet_tool_has_button(tool, BTN_RIGHT))
636 			printq("R");
637 		if (libinput_tablet_tool_has_button(tool, BTN_SIDE))
638 			printq("Sd");
639 		if (libinput_tablet_tool_has_button(tool, BTN_EXTRA))
640 			printq("Ex");
641 		if (libinput_tablet_tool_has_button(tool, BTN_0))
642 			printq("0");
643 	}
644 
645 	printq("\n");
646 }
647 
648 static void
print_touch_event(struct libinput_event *ev)649 print_touch_event(struct libinput_event *ev)
650 {
651 	struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
652 	enum libinput_event_type type = libinput_event_get_type(ev);
653 
654 	print_event_time(libinput_event_touch_get_time(t));
655 
656 	if (type != LIBINPUT_EVENT_TOUCH_FRAME) {
657 		printq("%d (%d)",
658 		       libinput_event_touch_get_slot(t),
659 		       libinput_event_touch_get_seat_slot(t));
660 	}
661 
662 	if (type == LIBINPUT_EVENT_TOUCH_DOWN ||
663 	    type == LIBINPUT_EVENT_TOUCH_MOTION) {
664 		double x = libinput_event_touch_get_x_transformed(t, screen_width);
665 		double y = libinput_event_touch_get_y_transformed(t, screen_height);
666 		double xmm = libinput_event_touch_get_x(t);
667 		double ymm = libinput_event_touch_get_y(t);
668 
669 		printq(" %5.2f/%5.2f (%5.2f/%5.2fmm)", x, y, xmm, ymm);
670 	}
671 
672 	printq("\n");
673 }
674 
675 static void
print_gesture_event_without_coords(struct libinput_event *ev)676 print_gesture_event_without_coords(struct libinput_event *ev)
677 {
678 	struct libinput_event_gesture *t = libinput_event_get_gesture_event(ev);
679 	int finger_count = libinput_event_gesture_get_finger_count(t);
680 	int cancelled = 0;
681 	enum libinput_event_type type;
682 
683 	type = libinput_event_get_type(ev);
684 
685 	if (type == LIBINPUT_EVENT_GESTURE_SWIPE_END ||
686 	    type == LIBINPUT_EVENT_GESTURE_PINCH_END ||
687 	    type == LIBINPUT_EVENT_GESTURE_HOLD_END)
688 	    cancelled = libinput_event_gesture_get_cancelled(t);
689 
690 	print_event_time(libinput_event_gesture_get_time(t));
691 	printq("%d%s\n", finger_count, cancelled ? " cancelled" : "");
692 }
693 
694 static void
print_gesture_event_with_coords(struct libinput_event *ev)695 print_gesture_event_with_coords(struct libinput_event *ev)
696 {
697 	struct libinput_event_gesture *t = libinput_event_get_gesture_event(ev);
698 	double dx = libinput_event_gesture_get_dx(t);
699 	double dy = libinput_event_gesture_get_dy(t);
700 	double dx_unaccel = libinput_event_gesture_get_dx_unaccelerated(t);
701 	double dy_unaccel = libinput_event_gesture_get_dy_unaccelerated(t);
702 
703 	print_event_time(libinput_event_gesture_get_time(t));
704 
705 	printq("%d %5.2f/%5.2f (%5.2f/%5.2f unaccelerated)",
706 	       libinput_event_gesture_get_finger_count(t),
707 	       dx, dy, dx_unaccel, dy_unaccel);
708 
709 	if (libinput_event_get_type(ev) ==
710 	    LIBINPUT_EVENT_GESTURE_PINCH_UPDATE) {
711 		double scale = libinput_event_gesture_get_scale(t);
712 		double angle = libinput_event_gesture_get_angle_delta(t);
713 
714 		printq(" %5.2f @ %5.2f\n", scale, angle);
715 	} else {
716 		printq("\n");
717 	}
718 }
719 
720 static void
print_tablet_pad_button_event(struct libinput_event *ev)721 print_tablet_pad_button_event(struct libinput_event *ev)
722 {
723 	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
724 	struct libinput_tablet_pad_mode_group *group;
725 	enum libinput_button_state state;
726 	unsigned int button, mode;
727 
728 	print_event_time(libinput_event_tablet_pad_get_time(p));
729 
730 	button = libinput_event_tablet_pad_get_button_number(p),
731 	state = libinput_event_tablet_pad_get_button_state(p);
732 	mode = libinput_event_tablet_pad_get_mode(p);
733 	printq("%3d %s (mode %d)",
734 	       button,
735 	       state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
736 	       mode);
737 
738 	group = libinput_event_tablet_pad_get_mode_group(p);
739 	if (libinput_tablet_pad_mode_group_button_is_toggle(group, button))
740 		printq(" <mode toggle>");
741 
742 	printq("\n");
743 }
744 
745 static void
print_tablet_pad_ring_event(struct libinput_event *ev)746 print_tablet_pad_ring_event(struct libinput_event *ev)
747 {
748 	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
749 	const char *source = NULL;
750 	unsigned int mode;
751 
752 	print_event_time(libinput_event_tablet_pad_get_time(p));
753 
754 	switch (libinput_event_tablet_pad_get_ring_source(p)) {
755 	case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
756 		source = "finger";
757 		break;
758 	case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
759 		source = "unknown";
760 		break;
761 	}
762 
763 	mode = libinput_event_tablet_pad_get_mode(p);
764 	printq("ring %d position %.2f (source %s) (mode %d)\n",
765 	       libinput_event_tablet_pad_get_ring_number(p),
766 	       libinput_event_tablet_pad_get_ring_position(p),
767 	       source,
768 	       mode);
769 }
770 
771 static void
print_tablet_pad_strip_event(struct libinput_event *ev)772 print_tablet_pad_strip_event(struct libinput_event *ev)
773 {
774 	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
775 	const char *source = NULL;
776 	unsigned int mode;
777 
778 	print_event_time(libinput_event_tablet_pad_get_time(p));
779 
780 	switch (libinput_event_tablet_pad_get_strip_source(p)) {
781 	case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
782 		source = "finger";
783 		break;
784 	case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
785 		source = "unknown";
786 		break;
787 	}
788 
789 	mode = libinput_event_tablet_pad_get_mode(p);
790 	printq("strip %d position %.2f (source %s) (mode %d)\n",
791 	       libinput_event_tablet_pad_get_strip_number(p),
792 	       libinput_event_tablet_pad_get_strip_position(p),
793 	       source,
794 	       mode);
795 }
796 
797 static void
print_tablet_pad_key_event(struct libinput_event *ev)798 print_tablet_pad_key_event(struct libinput_event *ev)
799 {
800 	struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
801 	enum libinput_key_state state;
802 	uint32_t key;
803 	const char *keyname;
804 
805 	print_event_time(libinput_event_tablet_pad_get_time(p));
806 
807 	key = libinput_event_tablet_pad_get_key(p);
808 	if (!show_keycodes && (key >= KEY_ESC && key < KEY_ZENKAKUHANKAKU)) {
809 		keyname = "***";
810 		key = -1;
811 	} else {
812 		keyname = libevdev_event_code_get_name(EV_KEY, key);
813 		keyname = keyname ? keyname : "???";
814 	}
815 	state = libinput_event_tablet_pad_get_key_state(p);
816 	printq("%s (%d) %s\n",
817 	       keyname,
818 	       key,
819 	       state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
820 }
821 
822 static void
print_switch_event(struct libinput_event *ev)823 print_switch_event(struct libinput_event *ev)
824 {
825 	struct libinput_event_switch *sw = libinput_event_get_switch_event(ev);
826 	enum libinput_switch_state state;
827 	const char *which;
828 
829 	print_event_time(libinput_event_switch_get_time(sw));
830 
831 	switch (libinput_event_switch_get_switch(sw)) {
832 	case LIBINPUT_SWITCH_LID:
833 		which = "lid";
834 		break;
835 	case LIBINPUT_SWITCH_TABLET_MODE:
836 		which = "tablet-mode";
837 		break;
838 	default:
839 		abort();
840 	}
841 
842 	state = libinput_event_switch_get_switch_state(sw);
843 
844 	printq("switch %s state %d\n", which, state);
845 }
846 
847 static int
handle_and_print_events(struct libinput *li)848 handle_and_print_events(struct libinput *li)
849 {
850 	int rc = -1;
851 	struct libinput_event *ev;
852 
853 	tools_dispatch(li);
854 	while ((ev = libinput_get_event(li))) {
855 		enum libinput_event_type type = libinput_event_get_type(ev);
856 
857 		if (type != LIBINPUT_EVENT_POINTER_AXIS)
858 			print_event_header(ev);
859 
860 		switch (type) {
861 		case LIBINPUT_EVENT_NONE:
862 			abort();
863 		case LIBINPUT_EVENT_DEVICE_ADDED:
864 			print_device_notify(ev);
865 			tools_device_apply_config(libinput_event_get_device(ev),
866 						  &options);
867 			break;
868 		case LIBINPUT_EVENT_DEVICE_REMOVED:
869 			print_device_notify(ev);
870 			break;
871 		case LIBINPUT_EVENT_KEYBOARD_KEY:
872 			print_key_event(ev);
873 			break;
874 		case LIBINPUT_EVENT_POINTER_MOTION:
875 			print_motion_event(ev);
876 			break;
877 		case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
878 			print_absmotion_event(ev);
879 			break;
880 		case LIBINPUT_EVENT_POINTER_BUTTON:
881 			print_pointer_button_event(ev);
882 			break;
883 		case LIBINPUT_EVENT_POINTER_AXIS:
884 			/* ignore */
885 			break;
886 		case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
887 		case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
888 		case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
889 			print_pointer_axis_event(ev);
890 			break;
891 		case LIBINPUT_EVENT_TOUCH_DOWN:
892 		case LIBINPUT_EVENT_TOUCH_MOTION:
893 		case LIBINPUT_EVENT_TOUCH_UP:
894 		case LIBINPUT_EVENT_TOUCH_CANCEL:
895 		case LIBINPUT_EVENT_TOUCH_FRAME:
896 			print_touch_event(ev);
897 			break;
898 		case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
899 			print_gesture_event_without_coords(ev);
900 			break;
901 		case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
902 			print_gesture_event_with_coords(ev);
903 			break;
904 		case LIBINPUT_EVENT_GESTURE_SWIPE_END:
905 			print_gesture_event_without_coords(ev);
906 			break;
907 		case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
908 			print_gesture_event_without_coords(ev);
909 			break;
910 		case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
911 			print_gesture_event_with_coords(ev);
912 			break;
913 		case LIBINPUT_EVENT_GESTURE_PINCH_END:
914 			print_gesture_event_without_coords(ev);
915 			break;
916 		case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
917 			print_gesture_event_without_coords(ev);
918 			break;
919 		case LIBINPUT_EVENT_GESTURE_HOLD_END:
920 			print_gesture_event_without_coords(ev);
921 			break;
922 		case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
923 			print_tablet_axis_event(ev);
924 			break;
925 		case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
926 			print_proximity_event(ev);
927 			break;
928 		case LIBINPUT_EVENT_TABLET_TOOL_TIP:
929 			print_tablet_tip_event(ev);
930 			break;
931 		case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
932 			print_tablet_button_event(ev);
933 			break;
934 		case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
935 			print_tablet_pad_button_event(ev);
936 			break;
937 		case LIBINPUT_EVENT_TABLET_PAD_RING:
938 			print_tablet_pad_ring_event(ev);
939 			break;
940 		case LIBINPUT_EVENT_TABLET_PAD_STRIP:
941 			print_tablet_pad_strip_event(ev);
942 			break;
943 		case LIBINPUT_EVENT_TABLET_PAD_KEY:
944 			print_tablet_pad_key_event(ev);
945 			break;
946 		case LIBINPUT_EVENT_SWITCH_TOGGLE:
947 			print_switch_event(ev);
948 			break;
949 		}
950 
951 		libinput_event_destroy(ev);
952 		rc = 0;
953 	}
954 
955 	fflush(stdout);
956 
957 	return rc;
958 }
959 
960 static void
sighandler(int signal, siginfo_t *siginfo, void *userdata)961 sighandler(int signal, siginfo_t *siginfo, void *userdata)
962 {
963 	stop = 1;
964 }
965 
966 static void
mainloop(struct libinput *li)967 mainloop(struct libinput *li)
968 {
969 	struct pollfd fds;
970 
971 	fds.fd = libinput_get_fd(li);
972 	fds.events = POLLIN;
973 	fds.revents = 0;
974 
975 	/* Handle already-pending device added events */
976 	if (handle_and_print_events(li))
977 		fprintf(stderr, "Expected device added events on startup but got none. "
978 				"Maybe you don't have the right permissions?\n");
979 
980 	/* time offset starts with our first received event */
981 	if (poll(&fds, 1, -1) > -1) {
982 		struct timespec tp;
983 
984 		clock_gettime(CLOCK_MONOTONIC, &tp);
985 		start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
986 		do {
987 			handle_and_print_events(li);
988 		} while (!stop && poll(&fds, 1, -1) > -1);
989 	}
990 
991 	printf("\n");
992 }
993 
994 static void
usage(void)995 usage(void) {
996 	printf("Usage: libinput debug-events [options] [--udev <seat>|--device /dev/input/event0 ...]\n");
997 }
998 
999 int
main(int argc, char **argv)1000 main(int argc, char **argv)
1001 {
1002 	struct libinput *li;
1003 	enum tools_backend backend = BACKEND_NONE;
1004 	const char *seat_or_devices[60] = {NULL};
1005 	size_t ndevices = 0;
1006 	bool grab = false;
1007 	bool verbose = false;
1008 	struct sigaction act;
1009 
1010 	tools_init_options(&options);
1011 
1012 	while (1) {
1013 		int c;
1014 		int option_index = 0;
1015 		enum {
1016 			OPT_DEVICE = 1,
1017 			OPT_UDEV,
1018 			OPT_GRAB,
1019 			OPT_VERBOSE,
1020 			OPT_SHOW_KEYCODES,
1021 			OPT_QUIET,
1022 		};
1023 		static struct option opts[] = {
1024 			CONFIGURATION_OPTIONS,
1025 			{ "help",                      no_argument,       0, 'h' },
1026 			{ "show-keycodes",             no_argument,       0, OPT_SHOW_KEYCODES },
1027 			{ "device",                    required_argument, 0, OPT_DEVICE },
1028 			{ "udev",                      required_argument, 0, OPT_UDEV },
1029 			{ "grab",                      no_argument,       0, OPT_GRAB },
1030 			{ "verbose",                   no_argument,       0, OPT_VERBOSE },
1031 			{ "quiet",                     no_argument,       0, OPT_QUIET },
1032 			{ 0, 0, 0, 0}
1033 		};
1034 
1035 		c = getopt_long(argc, argv, "h", opts, &option_index);
1036 		if (c == -1)
1037 			break;
1038 
1039 		switch(c) {
1040 		case '?':
1041 			exit(EXIT_INVALID_USAGE);
1042 			break;
1043 		case 'h':
1044 			usage();
1045 			exit(EXIT_SUCCESS);
1046 			break;
1047 		case OPT_SHOW_KEYCODES:
1048 			show_keycodes = true;
1049 			break;
1050 		case OPT_QUIET:
1051 			be_quiet = true;
1052 			break;
1053 		case OPT_DEVICE:
1054 			if (backend == BACKEND_UDEV ||
1055 			    ndevices >= ARRAY_LENGTH(seat_or_devices)) {
1056 				usage();
1057 				return EXIT_INVALID_USAGE;
1058 
1059 			}
1060 			backend = BACKEND_DEVICE;
1061 			seat_or_devices[ndevices++] = optarg;
1062 			break;
1063 		case OPT_UDEV:
1064 			if (backend == BACKEND_DEVICE ||
1065 			    ndevices >= ARRAY_LENGTH(seat_or_devices)) {
1066 				usage();
1067 				return EXIT_INVALID_USAGE;
1068 
1069 			}
1070 			backend = BACKEND_UDEV;
1071 			seat_or_devices[0] = optarg;
1072 			ndevices = 1;
1073 			break;
1074 		case OPT_GRAB:
1075 			grab = true;
1076 			break;
1077 		case OPT_VERBOSE:
1078 			verbose = true;
1079 			break;
1080 		default:
1081 			if (tools_parse_option(c, optarg, &options) != 0) {
1082 				usage();
1083 				return EXIT_INVALID_USAGE;
1084 			}
1085 			break;
1086 		}
1087 
1088 	}
1089 
1090 	if (optind < argc) {
1091 		if (backend == BACKEND_UDEV) {
1092 			usage();
1093 			return EXIT_INVALID_USAGE;
1094 		}
1095 		backend = BACKEND_DEVICE;
1096 		do {
1097 			if (ndevices >= ARRAY_LENGTH(seat_or_devices)) {
1098 				usage();
1099 				return EXIT_INVALID_USAGE;
1100 			}
1101 			seat_or_devices[ndevices++] = argv[optind];
1102 		} while(++optind < argc);
1103 	} else if (backend == BACKEND_NONE) {
1104 		backend = BACKEND_UDEV;
1105 		seat_or_devices[0] = "seat0";
1106 	}
1107 
1108 	memset(&act, 0, sizeof(act));
1109 	act.sa_sigaction = sighandler;
1110 	act.sa_flags = SA_SIGINFO;
1111 
1112 	if (sigaction(SIGINT, &act, NULL) == -1) {
1113 		fprintf(stderr, "Failed to set up signal handling (%s)\n",
1114 				strerror(errno));
1115 		return EXIT_FAILURE;
1116 	}
1117 
1118 	if (verbose)
1119 		printf("libinput version: %s\n", LIBINPUT_VERSION);
1120 
1121 	li = tools_open_backend(backend, seat_or_devices, verbose, &grab);
1122 	if (!li)
1123 		return EXIT_FAILURE;
1124 
1125 	mainloop(li);
1126 
1127 	libinput_unref(li);
1128 
1129 	return EXIT_SUCCESS;
1130 }
1131