1 /*
2  * Copyright © 2018 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 <sys/epoll.h>
28 #include <inttypes.h>
29 #include <linux/input.h>
30 #include <libevdev/libevdev.h>
31 #include <libudev.h>
32 #include <sys/signalfd.h>
33 #include <sys/timerfd.h>
34 #include <sys/utsname.h>
35 #include <sys/stat.h>
36 #include <string.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 #include <getopt.h>
40 #include <poll.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <stdbool.h>
44 #include <time.h>
45 
46 #include "libinput-versionsort.h"
47 #include "libinput-version.h"
48 #include "libinput-git-version.h"
49 #include "shared.h"
50 #include "builddir.h"
51 #include "util-bits.h"
52 #include "util-list.h"
53 #include "util-time.h"
54 #include "util-input-event.h"
55 #include "util-macros.h"
56 
57 static const int FILE_VERSION_NUMBER = 1;
58 
59 /* Indentation levels for the various data nodes */
60 enum indent {
61 	I_NONE = 0,
62 	I_TOPLEVEL = 0,
63 	I_LIBINPUT = 2,			/* nodes inside libinput: */
64 	I_SYSTEM = 2,			/* nodes inside system:   */
65 	I_DEVICE = 2,			/* nodes inside devices:  */
66 	I_EVDEV = 4,			/* nodes inside evdev:    */
67 	I_EVDEV_DATA = 6,		/* nodes below evdev:	  */
68 	I_UDEV = 4,			/* nodes inside udev:     */
69 	I_UDEV_DATA = 6,		/* nodes below udev:      */
70 	I_QUIRKS = 4,			/* nodes inside quirks:	  */
71 	I_LIBINPUTDEV = 4,		/* nodes inside libinput: (the
72 					   device description */
73 	I_EVENTTYPE = 4,		/* event type (evdev:, libinput:,
74 					   hidraw:) */
75 	I_EVENT = 6,			/* event data */
76 };
77 
78 struct record_device {
79 	struct record_context *ctx;
80 	struct list link;
81 	char *devnode;		/* device node of the source device */
82 	struct libevdev *evdev;
83 	struct libevdev *evdev_prev; /* previous value, used for EV_ABS
84 					deltas */
85 	struct libinput_device *device;
86 	struct list hidraw_devices;
87 
88 	struct {
89 		bool is_touch_device;
90 		uint16_t slot_state;
91 		uint16_t last_slot_state;
92 	} touch;
93 
94 	FILE *fp;
95 };
96 
97 struct hidraw {
98 	struct list link;
99 	struct record_device *device;
100 	int fd;
101 	char *name;
102 };
103 
104 struct record_context {
105 	int timeout;
106 	bool show_keycodes;
107 
108 	uint64_t offset;
109 
110 	/* The first device to be added */
111 	struct record_device *first_device;
112 
113 	struct list devices;
114 	int ndevices;
115 
116 	struct {
117 		char *name;		 /* file name given on cmdline */
118 		char *name_with_suffix;  /* full file name with suffix */
119 	} output_file;
120 
121 	struct libinput *libinput;
122 
123 	int epoll_fd;
124 	struct list sources;
125 
126 	struct {
127 		bool had_events_since_last_time;
128 		bool skipped_timer_print;
129 	} timestamps;
130 
131 	bool had_events;
132 	bool stop;
133 };
134 
135 #define resize(array_, sz_) \
136 { \
137 	size_t new_size = (sz_) + 1000; \
138 	void *tmp = realloc((array_), new_size * sizeof(*(array_))); \
139 	assert(tmp); \
140 	(array_)  = tmp; \
141 	(sz_) = new_size; \
142 }
143 
144 typedef void (*source_dispatch_t)(struct record_context *ctx,
145 				  int fd,
146 				  void *user_data);
147 
148 struct source {
149 	source_dispatch_t dispatch;
150 	void *user_data;
151 	int fd;
152 	struct list link;
153 };
154 
155 static bool
obfuscate_keycode(struct input_event *ev)156 obfuscate_keycode(struct input_event *ev)
157 {
158 	switch (ev->type) {
159 	case EV_KEY:
160 		switch (ev->code) {
161 		case KEY_ESC:
162 		case KEY_TAB:
163 		case KEY_ENTER:
164 		case KEY_LEFTCTRL:
165 			break;
166 		default:
167 			if ((ev->code > KEY_ESC && ev->code < KEY_CAPSLOCK) ||
168 			    (ev->code >= KEY_KP7 && ev->code <= KEY_KPDOT)) {
169 				ev->code = KEY_A;
170 				return true;
171 			}
172 		}
173 		break;
174 	case EV_MSC:
175 		if (ev->code == MSC_SCAN) {
176 			ev->value = 30; /* KEY_A scancode */
177 			return true;
178 		}
179 		break;
180 	}
181 
182 	return false;
183 }
184 
185 /**
186  * Indented dprintf, indentation is in the context
187  */
188 LIBINPUT_ATTRIBUTE_PRINTF(3, 4)
189 static void
iprintf(FILE *fp, enum indent indent, const char *format, ...)190 iprintf(FILE *fp,
191 	enum indent indent,
192 	const char *format, ...)
193 {
194 	va_list args;
195 	char fmt[1024];
196 	static const char space[] = "                                     ";
197 	static const size_t len = sizeof(space);
198 	int rc;
199 
200 	assert(indent < len);
201 	assert(strlen(format) >= 1);
202 
203 	/* Special case: if we're printing a new list item, we want less
204 	 * indentation because the '- ' takes up one level of indentation
205 	 *
206 	 * This is only needed because I don't want to deal with open/close
207 	 * lists statements.
208 	 */
209 	if (format[0] == '-' && indent > 0)
210 		indent -= 2;
211 
212 	snprintf(fmt, sizeof(fmt), "%s%s", &space[len - indent - 1], format);
213 	va_start(args, format);
214 #pragma GCC diagnostic push
215 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
216 	rc = vfprintf(fp, fmt, args);
217 #pragma GCC diagnostic pop
218 	va_end(args);
219 
220 	assert(rc != -1 && (unsigned int)rc > indent);
221 }
222 
223 static uint64_t
time_offset(struct record_context *ctx, uint64_t time)224 time_offset(struct record_context *ctx, uint64_t time)
225 {
226 	return ctx->offset ? time - ctx->offset : 0;
227 }
228 
229 static void
print_evdev_event(struct record_device *dev, struct input_event *ev)230 print_evdev_event(struct record_device *dev,
231 		  struct input_event *ev)
232 {
233 	const char *tname, *cname;
234 	bool was_modified = false;
235 	char desc[1024];
236 	uint64_t time = input_event_time(ev) - dev->ctx->offset;
237 
238 	input_event_set_time(ev, time);
239 
240 	/* Don't leak passwords unless the user wants to */
241 	if (!dev->ctx->show_keycodes)
242 		was_modified = obfuscate_keycode(ev);
243 
244 	tname = libevdev_event_type_get_name(ev->type);
245 	cname = libevdev_event_code_get_name(ev->type, ev->code);
246 
247 	if (ev->type == EV_SYN && ev->code == SYN_MT_REPORT) {
248 		snprintf(desc,
249 			 sizeof(desc),
250 			 "++++++++++++ %s (%d) ++++++++++",
251 			 cname,
252 			 ev->value);
253 	} else if (ev->type == EV_SYN) {
254 		static unsigned long last_ms = 0;
255 		unsigned long time, dt;
256 
257 		time = us2ms(input_event_time(ev));
258 		dt = time - last_ms;
259 		last_ms = time;
260 
261 		snprintf(desc,
262 			 sizeof(desc),
263 			"------------ %s (%d) ---------- %+ldms",
264 			cname,
265 			ev->value,
266 			dt);
267 	} else if (ev->type == EV_ABS) {
268 		int oldval = 0;
269 		enum { DELTA, SLOT_DELTA, NO_DELTA } want = DELTA;
270 		int delta = 0;
271 
272 		/* We want to print deltas for abs axes but there are a few
273 		 * that we don't care about for actual deltas because
274 		 * they're meaningless.
275 		 *
276 		 * Also, any slotted axis needs to be printed per slot
277 		 */
278 		switch (ev->code) {
279 		case ABS_MT_SLOT:
280 			libevdev_set_event_value(dev->evdev_prev,
281 						 ev->type,
282 						 ev->code,
283 						 ev->value);
284 			want = NO_DELTA;
285 			break;
286 		case ABS_MT_TRACKING_ID:
287 		case ABS_MT_BLOB_ID:
288 			want = NO_DELTA;
289 			break;
290 		case ABS_MT_TOUCH_MAJOR ... ABS_MT_POSITION_Y:
291 		case ABS_MT_PRESSURE ... ABS_MT_TOOL_Y:
292 			if (libevdev_get_num_slots(dev->evdev_prev) > 0)
293 				want = SLOT_DELTA;
294 			break;
295 		default:
296 			break;
297 		}
298 
299 		switch (want) {
300 		case DELTA:
301 			oldval = libevdev_get_event_value(dev->evdev_prev,
302 							  ev->type,
303 							  ev->code);
304 			libevdev_set_event_value(dev->evdev_prev,
305 						 ev->type,
306 						 ev->code,
307 						 ev->value);
308 			break;
309 		case SLOT_DELTA: {
310 			int slot = libevdev_get_current_slot(dev->evdev_prev);
311 			oldval = libevdev_get_slot_value(dev->evdev_prev,
312 							 slot,
313 							 ev->code);
314 			libevdev_set_slot_value(dev->evdev_prev,
315 						slot,
316 						ev->code,
317 						ev->value);
318 			break;
319 		}
320 		case NO_DELTA:
321 			break;
322 
323 		}
324 
325 		delta = ev->value - oldval;
326 
327 		switch (want) {
328 		case DELTA:
329 		case SLOT_DELTA:
330 			snprintf(desc,
331 				 sizeof(desc),
332 				 "%s / %-20s %6d (%+d)",
333 				 tname,
334 				 cname,
335 				 ev->value,
336 				 delta);
337 			break;
338 		case NO_DELTA:
339 			snprintf(desc,
340 				 sizeof(desc),
341 				 "%s / %-20s %6d",
342 				 tname,
343 				 cname,
344 				 ev->value);
345 			break;
346 		}
347 	} else {
348 		snprintf(desc,
349 			 sizeof(desc),
350 			 "%s / %-20s %6d%s",
351 			 tname,
352 			 cname,
353 			 ev->value,
354 			 was_modified ? " (obfuscated)" : "");
355 	}
356 
357 	iprintf(dev->fp,
358 		I_EVENT,
359 		"- [%3lu, %6u, %3d, %3d, %7d] # %s\n",
360 		ev->input_event_sec,
361 		(unsigned int)ev->input_event_usec,
362 		ev->type,
363 		ev->code,
364 		ev->value,
365 		desc);
366 }
367 
368 static bool
handle_evdev_frame(struct record_device *d)369 handle_evdev_frame(struct record_device *d)
370 {
371 	struct libevdev *evdev = d->evdev;
372 	struct input_event e;
373 
374 	if (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &e) !=
375 		LIBEVDEV_READ_STATUS_SUCCESS)
376 		return false;
377 
378 	iprintf(d->fp, I_EVENTTYPE, "- evdev:\n");
379 	do {
380 
381 		if (d->ctx->offset == 0) {
382 			uint64_t time = input_event_time(&e);
383 			d->ctx->offset = time;
384 		}
385 
386 		print_evdev_event(d, &e);
387 
388 		if (d->touch.is_touch_device &&
389 		    e.type == EV_ABS &&
390 		    e.code == ABS_MT_TRACKING_ID) {
391 			unsigned int slot = libevdev_get_current_slot(evdev);
392 			assert(slot < sizeof(d->touch.slot_state) * 8);
393 
394 			if (e.value != -1)
395 				d->touch.slot_state |= bit(slot);
396 			else
397 				d->touch.slot_state &= ~bit(slot);
398 		}
399 
400 		if (e.type == EV_SYN && e.code == SYN_REPORT)
401 			break;
402 	} while (libevdev_next_event(evdev,
403 				     LIBEVDEV_READ_FLAG_NORMAL,
404 				     &e) == LIBEVDEV_READ_STATUS_SUCCESS);
405 
406 	if (d->touch.slot_state != d->touch.last_slot_state) {
407 		d->touch.last_slot_state = d->touch.slot_state;
408 		if (d->touch.slot_state == 0) {
409 			iprintf(d->fp,
410 				I_EVENT,
411 				 "                                 # Touch device in neutral state\n");
412 		}
413 	}
414 
415 	return true;
416 }
417 
418 static void
print_device_notify(struct record_device *dev, struct libinput_event *e)419 print_device_notify(struct record_device *dev, struct libinput_event *e)
420 {
421 	struct libinput_device *d = libinput_event_get_device(e);
422 	struct libinput_seat *seat = libinput_device_get_seat(d);
423 	const char *type = NULL;
424 
425 	switch(libinput_event_get_type(e)) {
426 	case LIBINPUT_EVENT_DEVICE_ADDED:
427 		type = "DEVICE_ADDED";
428 		break;
429 	case LIBINPUT_EVENT_DEVICE_REMOVED:
430 		type = "DEVICE_REMOVED";
431 		break;
432 	default:
433 		abort();
434 	}
435 
436 	iprintf(dev->fp,
437 		I_EVENT,
438 		"- {type: %s, seat: %5s, logical_seat: %7s}\n",
439 		type,
440 		libinput_seat_get_physical_name(seat),
441 		libinput_seat_get_logical_name(seat));
442 }
443 
444 static void
print_key_event(struct record_device *dev, struct libinput_event *e)445 print_key_event(struct record_device *dev, struct libinput_event *e)
446 {
447 	struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(e);
448 	enum libinput_key_state state;
449 	uint32_t key;
450 	uint64_t time;
451 	const char *type;
452 
453 	switch(libinput_event_get_type(e)) {
454 	case LIBINPUT_EVENT_KEYBOARD_KEY:
455 		type = "KEYBOARD_KEY";
456 		break;
457 	default:
458 		abort();
459 	}
460 
461 	time = time_offset(dev->ctx, libinput_event_keyboard_get_time_usec(k));
462 	state = libinput_event_keyboard_get_key_state(k);
463 
464 	key = libinput_event_keyboard_get_key(k);
465 	if (!dev->ctx->show_keycodes &&
466 	    (key >= KEY_ESC && key < KEY_ZENKAKUHANKAKU))
467 		key = -1;
468 
469 	iprintf(dev->fp,
470 		I_EVENT,
471 		"- {time: %ld.%06ld, type: %s, key: %d, state: %s}\n",
472 		(long)(time / (int)1e6),
473 		(long)(time % (int)1e6),
474 		type,
475 		key,
476 		state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
477 }
478 
479 static void
print_motion_event(struct record_device *dev, struct libinput_event *e)480 print_motion_event(struct record_device *dev, struct libinput_event *e)
481 {
482 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
483 	double x = libinput_event_pointer_get_dx(p),
484 	       y = libinput_event_pointer_get_dy(p);
485 	double uax = libinput_event_pointer_get_dx_unaccelerated(p),
486 	       uay = libinput_event_pointer_get_dy_unaccelerated(p);
487 	uint64_t time;
488 	const char *type;
489 
490 	switch(libinput_event_get_type(e)) {
491 	case LIBINPUT_EVENT_POINTER_MOTION:
492 		type = "POINTER_MOTION";
493 		break;
494 	default:
495 		abort();
496 	}
497 
498 	time = time_offset(dev->ctx, libinput_event_pointer_get_time_usec(p));
499 	iprintf(dev->fp,
500 		I_EVENT,
501 		"- {time: %ld.%06ld, type: %s, delta: [%6.2f, %6.2f], unaccel: [%6.2f, %6.2f]}\n",
502 		(long)(time / (int)1e6),
503 		(long)(time % (int)1e6),
504 		type,
505 		x, y,
506 		uax, uay);
507 }
508 
509 static void
print_absmotion_event(struct record_device *dev, struct libinput_event *e)510 print_absmotion_event(struct record_device *dev, struct libinput_event *e)
511 {
512 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
513 	double x = libinput_event_pointer_get_absolute_x(p),
514 	       y = libinput_event_pointer_get_absolute_y(p);
515 	double tx = libinput_event_pointer_get_absolute_x_transformed(p, 100),
516 	       ty = libinput_event_pointer_get_absolute_y_transformed(p, 100);
517 	uint64_t time;
518 	const char *type;
519 
520 	switch(libinput_event_get_type(e)) {
521 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
522 		type = "POINTER_MOTION_ABSOLUTE";
523 		break;
524 	default:
525 		abort();
526 	}
527 
528 	time = time_offset(dev->ctx, libinput_event_pointer_get_time_usec(p));
529 
530 	iprintf(dev->fp,
531 		I_EVENT,
532 		"- {time: %ld.%06ld, type: %s, point: [%6.2f, %6.2f], transformed: [%6.2f, %6.2f]}\n",
533 		(long)(time / (int)1e6),
534 		(long)(time % (int)1e6),
535 		type,
536 		x, y,
537 		tx, ty);
538 }
539 
540 static void
print_pointer_button_event(struct record_device *dev, struct libinput_event *e)541 print_pointer_button_event(struct record_device *dev, struct libinput_event *e)
542 {
543 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
544 	enum libinput_button_state state;
545 	int button;
546 	uint64_t time;
547 	const char *type;
548 
549 	switch(libinput_event_get_type(e)) {
550 	case LIBINPUT_EVENT_POINTER_BUTTON:
551 		type = "POINTER_BUTTON";
552 		break;
553 	default:
554 		abort();
555 	}
556 
557 	time = time_offset(dev->ctx, libinput_event_pointer_get_time_usec(p));
558 	button = libinput_event_pointer_get_button(p);
559 	state = libinput_event_pointer_get_button_state(p);
560 
561 	iprintf(dev->fp,
562 		I_EVENT,
563 		"- {time: %ld.%06ld, type: %s, button: %d, state: %s, seat_count: %u}\n",
564 		(long)(time / (int)1e6),
565 		(long)(time % (int)1e6),
566 		type,
567 		button,
568 		state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
569 		libinput_event_pointer_get_seat_button_count(p));
570 }
571 
572 static void
print_pointer_axis_event(struct record_device *dev, struct libinput_event *e)573 print_pointer_axis_event(struct record_device *dev, struct libinput_event *e)
574 {
575 	struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
576 	uint64_t time;
577 	const char *type, *source;
578 	double h = 0, v = 0;
579 	int hd = 0, vd = 0;
580 
581 	switch(libinput_event_get_type(e)) {
582 	case LIBINPUT_EVENT_POINTER_AXIS:
583 		type = "POINTER_AXIS";
584 		break;
585 	default:
586 		abort();
587 	}
588 
589 	time = time_offset(dev->ctx, libinput_event_pointer_get_time_usec(p));
590 	if (libinput_event_pointer_has_axis(p,
591 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
592 		h = libinput_event_pointer_get_axis_value(p,
593 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
594 		hd = libinput_event_pointer_get_axis_value_discrete(p,
595 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
596 	}
597 	if (libinput_event_pointer_has_axis(p,
598 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
599 		v = libinput_event_pointer_get_axis_value(p,
600 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
601 		vd = libinput_event_pointer_get_axis_value_discrete(p,
602 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
603 	}
604 	switch(libinput_event_pointer_get_axis_source(p)) {
605 	case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: source = "wheel"; break;
606 	case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: source = "finger"; break;
607 	case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: source = "continuous"; break;
608 	case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT: source = "wheel-tilt"; break;
609 	default:
610 		source = "unknown";
611 		break;
612 	}
613 
614 	iprintf(dev->fp,
615 		I_EVENT,
616 		"- {time: %ld.%06ld, type: %s, axes: [%2.2f, %2.2f], discrete: [%d, %d], source: %s}\n",
617 		(long)(time / (int)1e6),
618 		(long)(time % (int)1e6),
619 		type,
620 		h, v,
621 		hd, vd,
622 		source);
623 }
624 
625 static void
print_touch_event(struct record_device *dev, struct libinput_event *e)626 print_touch_event(struct record_device *dev, struct libinput_event *e)
627 {
628 	enum libinput_event_type etype = libinput_event_get_type(e);
629 	struct libinput_event_touch *t = libinput_event_get_touch_event(e);
630 	const char *type;
631 	double x, y;
632 	double tx, ty;
633 	uint64_t time;
634 	int32_t slot, seat_slot;
635 
636 	switch(etype) {
637 	case LIBINPUT_EVENT_TOUCH_DOWN:
638 		type = "TOUCH_DOWN";
639 		break;
640 	case LIBINPUT_EVENT_TOUCH_UP:
641 		type = "TOUCH_UP";
642 		break;
643 	case LIBINPUT_EVENT_TOUCH_MOTION:
644 		type = "TOUCH_MOTION";
645 		break;
646 	case LIBINPUT_EVENT_TOUCH_CANCEL:
647 		type = "TOUCH_CANCEL";
648 		break;
649 	case LIBINPUT_EVENT_TOUCH_FRAME:
650 		type = "TOUCH_FRAME";
651 		break;
652 	default:
653 		abort();
654 	}
655 
656 	time = time_offset(dev->ctx, libinput_event_touch_get_time_usec(t));
657 
658 	if (etype != LIBINPUT_EVENT_TOUCH_FRAME) {
659 		slot = libinput_event_touch_get_slot(t);
660 		seat_slot = libinput_event_touch_get_seat_slot(t);
661 	}
662 
663 	switch (etype) {
664 	case LIBINPUT_EVENT_TOUCH_FRAME:
665 		iprintf(dev->fp,
666 			I_EVENT,
667 			"- {time: %ld.%06ld, type: %s}\n",
668 			(long)(time / (int)1e6),
669 			(long)(time % (int)1e6),
670 			type);
671 		break;
672 	case LIBINPUT_EVENT_TOUCH_DOWN:
673 	case LIBINPUT_EVENT_TOUCH_MOTION:
674 		x = libinput_event_touch_get_x(t);
675 		y = libinput_event_touch_get_y(t);
676 		tx = libinput_event_touch_get_x_transformed(t, 100);
677 		ty = libinput_event_touch_get_y_transformed(t, 100);
678 		iprintf(dev->fp,
679 			I_EVENT,
680 			"- {time: %ld.%06ld, type: %s, slot: %d, seat_slot: %d, "
681 			"point: [%6.2f, %6.2f], transformed: [%6.2f, %6.2f]}\n",
682 			(long)(time / (int)1e6),
683 			(long)(time % (int)1e6),
684 			type,
685 			slot,
686 			seat_slot,
687 			x, y,
688 			tx, ty);
689 		break;
690 	case LIBINPUT_EVENT_TOUCH_UP:
691 	case LIBINPUT_EVENT_TOUCH_CANCEL:
692 		iprintf(dev->fp,
693 			I_EVENT,
694 			"- {time: %ld.%06ld, type: %s, slot: %d, seat_slot: %d}\n",
695 			(long)(time / (int)1e6),
696 			(long)(time % (int)1e6),
697 			type,
698 			slot,
699 			seat_slot);
700 		break;
701 	default:
702 		abort();
703 	}
704 }
705 
706 static void
print_gesture_event(struct record_device *dev, struct libinput_event *e)707 print_gesture_event(struct record_device *dev, struct libinput_event *e)
708 {
709 	enum libinput_event_type etype = libinput_event_get_type(e);
710 	struct libinput_event_gesture *g = libinput_event_get_gesture_event(e);
711 	const char *type;
712 	uint64_t time;
713 
714 	switch(etype) {
715 	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
716 		type = "GESTURE_PINCH_BEGIN";
717 		break;
718 	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
719 		type = "GESTURE_PINCH_UPDATE";
720 		break;
721 	case LIBINPUT_EVENT_GESTURE_PINCH_END:
722 		type = "GESTURE_PINCH_END";
723 		break;
724 	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
725 		type = "GESTURE_SWIPE_BEGIN";
726 		break;
727 	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
728 		type = "GESTURE_SWIPE_UPDATE";
729 		break;
730 	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
731 		type = "GESTURE_SWIPE_END";
732 		break;
733 	default:
734 		abort();
735 	}
736 
737 	time = time_offset(dev->ctx, libinput_event_gesture_get_time_usec(g));
738 
739 	switch (etype) {
740 	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
741 	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
742 	case LIBINPUT_EVENT_GESTURE_PINCH_END:
743 		iprintf(dev->fp,
744 			I_EVENT,
745 			"- {time: %ld.%06ld, type: %s, nfingers: %d, "
746 			"delta: [%6.2f, %6.2f], unaccel: [%6.2f, %6.2f], "
747 			"angle_delta: %6.2f, scale: %6.2f}\n",
748 			(long)(time / (int)1e6),
749 			(long)(time % (int)1e6),
750 			type,
751 			libinput_event_gesture_get_finger_count(g),
752 			libinput_event_gesture_get_dx(g),
753 			libinput_event_gesture_get_dy(g),
754 			libinput_event_gesture_get_dx_unaccelerated(g),
755 			libinput_event_gesture_get_dy_unaccelerated(g),
756 			libinput_event_gesture_get_angle_delta(g),
757 			libinput_event_gesture_get_scale(g)
758 		       );
759 		break;
760 	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
761 	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
762 	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
763 		iprintf(dev->fp,
764 			I_EVENT,
765 			"- {time: %ld.%06ld, type: %s, nfingers: %d, "
766 			"delta: [%6.2f, %6.2f], unaccel: [%6.2f, %6.2f]}\n",
767 			(long)(time / (int)1e6),
768 			(long)(time % (int)1e6),
769 			type,
770 			libinput_event_gesture_get_finger_count(g),
771 			libinput_event_gesture_get_dx(g),
772 			libinput_event_gesture_get_dy(g),
773 			libinput_event_gesture_get_dx_unaccelerated(g),
774 			libinput_event_gesture_get_dy_unaccelerated(g)
775 		       );
776 		break;
777 	default:
778 		abort();
779 	}
780 }
781 
782 static char *
buffer_tablet_axes(struct libinput_event_tablet_tool *t)783 buffer_tablet_axes(struct libinput_event_tablet_tool *t)
784 {
785 	const int MAX_AXES = 10;
786 	struct libinput_tablet_tool *tool;
787 	char *s = NULL;
788 	int idx = 0;
789 	int len;
790 	double x, y;
791 	char **strv;
792 
793 	tool = libinput_event_tablet_tool_get_tool(t);
794 
795 	strv = zalloc(MAX_AXES * sizeof *strv);
796 
797 	x = libinput_event_tablet_tool_get_x(t);
798 	y = libinput_event_tablet_tool_get_y(t);
799 	len = xasprintf(&strv[idx++], "point: [%.2f, %.2f]", x, y);
800 	if (len <= 0)
801 		goto out;
802 
803 	if (libinput_tablet_tool_has_tilt(tool)) {
804 		x = libinput_event_tablet_tool_get_tilt_x(t);
805 		y = libinput_event_tablet_tool_get_tilt_y(t);
806 		len = xasprintf(&strv[idx++], "tilt: [%.2f, %.2f]", x, y);
807 		if (len <= 0)
808 			goto out;
809 	}
810 
811 	if (libinput_tablet_tool_has_distance(tool) ||
812 	    libinput_tablet_tool_has_pressure(tool)) {
813 		double dist, pressure;
814 
815 		dist = libinput_event_tablet_tool_get_distance(t);
816 		pressure = libinput_event_tablet_tool_get_pressure(t);
817 		if (dist)
818 			len = xasprintf(&strv[idx++], "distance: %.2f", dist);
819 		else
820 			len = xasprintf(&strv[idx++], "pressure: %.2f", pressure);
821 		if (len <= 0)
822 			goto out;
823 	}
824 
825 	if (libinput_tablet_tool_has_rotation(tool)) {
826 		double rotation;
827 
828 		rotation = libinput_event_tablet_tool_get_rotation(t);
829 		len = xasprintf(&strv[idx++], "rotation: %.2f", rotation);
830 		if (len <= 0)
831 			goto out;
832 	}
833 
834 	if (libinput_tablet_tool_has_slider(tool)) {
835 		double slider;
836 
837 		slider = libinput_event_tablet_tool_get_slider_position(t);
838 		len = xasprintf(&strv[idx++], "slider: %.2f", slider);
839 		if (len <= 0)
840 			goto out;
841 
842 	}
843 
844 	if (libinput_tablet_tool_has_wheel(tool)) {
845 		double wheel;
846 		int delta;
847 
848 		wheel = libinput_event_tablet_tool_get_wheel_delta(t);
849 		len = xasprintf(&strv[idx++], "wheel: %.2f", wheel);
850 		if (len <= 0)
851 			goto out;
852 
853 		delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t);
854 		len = xasprintf(&strv[idx++], "wheel-discrete: %d", delta);
855 		if (len <= 0)
856 			goto out;
857 	}
858 
859 	assert(idx < MAX_AXES);
860 
861 	s = strv_join(strv, ", ");
862 out:
863 	strv_free(strv);
864 	return s;
865 }
866 
867 static void
print_tablet_tool_proximity_event(struct record_device *dev, struct libinput_event *e)868 print_tablet_tool_proximity_event(struct record_device *dev, struct libinput_event *e)
869 {
870 	struct libinput_event_tablet_tool *t =
871 		libinput_event_get_tablet_tool_event(e);
872 	struct libinput_tablet_tool *tool =
873 		libinput_event_tablet_tool_get_tool(t);
874 	uint64_t time;
875 	const char *type, *tool_type;
876 	char *axes;
877 	char caps[10] = {0};
878 	enum libinput_tablet_tool_proximity_state prox;
879 	size_t idx;
880 
881 	switch (libinput_event_get_type(e)) {
882 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
883 		type = "TABLET_TOOL_PROXIMITY";
884 		break;
885 	default:
886 		abort();
887 	}
888 
889 	switch (libinput_tablet_tool_get_type(tool)) {
890 	case LIBINPUT_TABLET_TOOL_TYPE_PEN:
891 		tool_type = "pen";
892 		break;
893 	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
894 		tool_type = "eraser";
895 		break;
896 	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
897 		tool_type = "brush";
898 		break;
899 	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
900 		tool_type = "brush";
901 		break;
902 	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
903 		tool_type = "airbrush";
904 		break;
905 	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
906 		tool_type = "mouse";
907 		break;
908 	case LIBINPUT_TABLET_TOOL_TYPE_LENS:
909 		tool_type = "lens";
910 		break;
911 	default:
912 		tool_type = "unknown";
913 		break;
914 	}
915 
916 	prox = libinput_event_tablet_tool_get_proximity_state(t);
917 	time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t));
918 	axes = buffer_tablet_axes(t);
919 
920 	idx = 0;
921 	if (libinput_tablet_tool_has_pressure(tool))
922 		caps[idx++] = 'p';
923 	if (libinput_tablet_tool_has_distance(tool))
924 		caps[idx++] = 'd';
925 	if (libinput_tablet_tool_has_tilt(tool))
926 		caps[idx++] = 't';
927 	if (libinput_tablet_tool_has_rotation(tool))
928 		caps[idx++] = 'r';
929 	if (libinput_tablet_tool_has_slider(tool))
930 		caps[idx++] = 's';
931 	if (libinput_tablet_tool_has_wheel(tool))
932 		caps[idx++] = 'w';
933 	assert(idx <= ARRAY_LENGTH(caps));
934 
935 	iprintf(dev->fp,
936 		I_EVENT,
937 		"- {time: %ld.%06ld, type: %s, proximity: %s, tool-type: %s, serial: %" PRIu64 ", axes: %s, %s}\n",
938 		(long)(time / (int)1e6),
939 		(long)(time % (int)1e6),
940 		type,
941 		prox ? "in" : "out",
942 		tool_type,
943 		libinput_tablet_tool_get_serial(tool),
944 		caps,
945 		axes);
946 	free(axes);
947 }
948 
949 static void
print_tablet_tool_button_event(struct record_device *dev, struct libinput_event *e)950 print_tablet_tool_button_event(struct record_device *dev,
951 			       struct libinput_event *e)
952 {
953 	struct libinput_event_tablet_tool *t =
954 		libinput_event_get_tablet_tool_event(e);
955 	uint64_t time;
956 	const char *type;
957 	uint32_t button;
958 	enum libinput_button_state state;
959 
960 	switch(libinput_event_get_type(e)) {
961 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
962 		type = "TABLET_TOOL_BUTTON";
963 		break;
964 	default:
965 		abort();
966 	}
967 
968 	button = libinput_event_tablet_tool_get_button(t);
969 	state = libinput_event_tablet_tool_get_button_state(t);
970 	time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t));
971 
972 	iprintf(dev->fp,
973 		I_EVENT,
974 		"- {time: %ld.%06ld, type: %s, button: %d, state: %s}\n",
975 		(long)(time / (int)1e6),
976 		(long)(time % (int)1e6),
977 		type,
978 		button,
979 		state ? "pressed" : "released");
980 }
981 
982 static void
print_tablet_tool_event(struct record_device *dev, struct libinput_event *e)983 print_tablet_tool_event(struct record_device *dev, struct libinput_event *e)
984 {
985 	struct libinput_event_tablet_tool *t =
986 		libinput_event_get_tablet_tool_event(e);
987 	uint64_t time;
988 	const char *type;
989 	char *axes;
990 	enum libinput_tablet_tool_tip_state tip;
991 	char btn_buffer[30] = {0};
992 
993 	switch(libinput_event_get_type(e)) {
994 	case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
995 		type = "TABLET_TOOL_AXIS";
996 		break;
997 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
998 		type = "TABLET_TOOL_TIP";
999 		break;
1000 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
1001 		type = "TABLET_TOOL_BUTTON";
1002 		break;
1003 	default:
1004 		abort();
1005 	}
1006 
1007 	if (libinput_event_get_type(e) == LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
1008 		uint32_t button;
1009 		enum libinput_button_state state;
1010 
1011 		button = libinput_event_tablet_tool_get_button(t);
1012 		state = libinput_event_tablet_tool_get_button_state(t);
1013 		snprintf(btn_buffer, sizeof(btn_buffer),
1014 			 ", button: %d, state: %s\n",
1015 			 button,
1016 			 state ? "pressed" : "released");
1017 	}
1018 
1019 	tip = libinput_event_tablet_tool_get_tip_state(t);
1020 	time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t));
1021 	axes = buffer_tablet_axes(t);
1022 
1023 	iprintf(dev->fp,
1024 		I_EVENT,
1025 		"- {time: %ld.%06ld, type: %s%s, tip: %s, %s}\n",
1026 		(long)(time / (int)1e6),
1027 		(long)(time % (int)1e6),
1028 		type,
1029 		btn_buffer, /* may be empty string */
1030 		tip ? "down" : "up",
1031 		axes);
1032 	free(axes);
1033 }
1034 
1035 static void
print_tablet_pad_button_event(struct record_device *dev, struct libinput_event *e)1036 print_tablet_pad_button_event(struct record_device *dev,
1037 			      struct libinput_event *e)
1038 {
1039 	struct libinput_event_tablet_pad *p =
1040 		libinput_event_get_tablet_pad_event(e);
1041 	struct libinput_tablet_pad_mode_group *group;
1042 	enum libinput_button_state state;
1043 	unsigned int button, mode;
1044 	const char *type;
1045 	uint64_t time;
1046 
1047 	switch(libinput_event_get_type(e)) {
1048 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
1049 		type = "TABLET_PAD_BUTTON";
1050 		break;
1051 	default:
1052 		abort();
1053 	}
1054 
1055 	time = time_offset(dev->ctx, libinput_event_tablet_pad_get_time_usec(p));
1056 	button = libinput_event_tablet_pad_get_button_number(p),
1057 	state = libinput_event_tablet_pad_get_button_state(p);
1058 	mode = libinput_event_tablet_pad_get_mode(p);
1059 	group = libinput_event_tablet_pad_get_mode_group(p);
1060 
1061 	iprintf(dev->fp,
1062 		I_EVENT,
1063 		"- {time: %ld.%06ld, type: %s, button: %d, state: %s, mode: %d, is-toggle: %s}\n",
1064 		(long)(time / (int)1e6),
1065 		(long)(time % (int)1e6),
1066 		type,
1067 		button,
1068 		state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
1069 		mode,
1070 		libinput_tablet_pad_mode_group_button_is_toggle(group, button) ? "true" : "false"
1071 	       );
1072 
1073 }
1074 
1075 static void
print_tablet_pad_ringstrip_event(struct record_device *dev, struct libinput_event *e)1076 print_tablet_pad_ringstrip_event(struct record_device *dev, struct libinput_event *e)
1077 {
1078 	struct libinput_event_tablet_pad *p =
1079 		libinput_event_get_tablet_pad_event(e);
1080 	const char *source = NULL;
1081 	unsigned int mode, number;
1082 	const char *type;
1083 	uint64_t time;
1084 	double pos;
1085 
1086 	switch(libinput_event_get_type(e)) {
1087 	case LIBINPUT_EVENT_TABLET_PAD_RING:
1088 		type = "TABLET_PAD_RING";
1089 		number = libinput_event_tablet_pad_get_ring_number(p);
1090 	        pos = libinput_event_tablet_pad_get_ring_position(p);
1091 
1092 		switch (libinput_event_tablet_pad_get_ring_source(p)) {
1093 		case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
1094 			source = "finger";
1095 			break;
1096 		case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
1097 			source = "unknown";
1098 			break;
1099 		}
1100 		break;
1101 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
1102 		type = "TABLET_PAD_STRIP";
1103 		number = libinput_event_tablet_pad_get_strip_number(p);
1104 	        pos = libinput_event_tablet_pad_get_strip_position(p);
1105 
1106 		switch (libinput_event_tablet_pad_get_strip_source(p)) {
1107 		case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
1108 			source = "finger";
1109 			break;
1110 		case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
1111 			source = "unknown";
1112 			break;
1113 		}
1114 		break;
1115 	default:
1116 		abort();
1117 	}
1118 
1119 	time = time_offset(dev->ctx, libinput_event_tablet_pad_get_time_usec(p));
1120 	mode = libinput_event_tablet_pad_get_mode(p);
1121 
1122 	iprintf(dev->fp,
1123 		I_EVENT,
1124 		"- {time: %ld.%06ld, type: %s, number: %d, position: %.2f, source: %s, mode: %d}\n",
1125 		(long)(time / (int)1e6),
1126 		(long)(time % (int)1e6),
1127 		type,
1128 		number,
1129 		pos,
1130 		source,
1131 		mode);
1132 }
1133 
1134 static void
print_switch_event(struct record_device *dev, struct libinput_event *e)1135 print_switch_event(struct record_device *dev, struct libinput_event *e)
1136 {
1137 	struct libinput_event_switch *s = libinput_event_get_switch_event(e);
1138 	enum libinput_switch_state state;
1139 	uint32_t sw;
1140 	const char *type;
1141 	uint64_t time;
1142 
1143 	switch(libinput_event_get_type(e)) {
1144 	case LIBINPUT_EVENT_SWITCH_TOGGLE:
1145 		type = "SWITCH_TOGGLE";
1146 		break;
1147 	default:
1148 		abort();
1149 	}
1150 
1151 	time = time_offset(dev->ctx, libinput_event_switch_get_time_usec(s));
1152 	sw = libinput_event_switch_get_switch(s);
1153 	state = libinput_event_switch_get_switch_state(s);
1154 
1155 	iprintf(dev->fp,
1156 		I_EVENT,
1157 		"- {time: %ld.%06ld, type: %s, switch: %d, state: %s}\n",
1158 		(long)(time / (int)1e6),
1159 		(long)(time % (int)1e6),
1160 		type,
1161 		sw,
1162 		state == LIBINPUT_SWITCH_STATE_ON ? "on" : "off");
1163 }
1164 
1165 static void
print_libinput_event(struct record_device *dev, struct libinput_event *e)1166 print_libinput_event(struct record_device *dev, struct libinput_event *e)
1167 {
1168 	switch (libinput_event_get_type(e)) {
1169 	case LIBINPUT_EVENT_NONE:
1170 		abort();
1171 	case LIBINPUT_EVENT_DEVICE_ADDED:
1172 	case LIBINPUT_EVENT_DEVICE_REMOVED:
1173 		print_device_notify(dev, e);
1174 		break;
1175 	case LIBINPUT_EVENT_KEYBOARD_KEY:
1176 		print_key_event(dev, e);
1177 		break;
1178 	case LIBINPUT_EVENT_POINTER_MOTION:
1179 		print_motion_event(dev, e);
1180 		break;
1181 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
1182 		print_absmotion_event(dev, e);
1183 		break;
1184 	case LIBINPUT_EVENT_POINTER_BUTTON:
1185 		print_pointer_button_event(dev, e);
1186 		break;
1187 	case LIBINPUT_EVENT_POINTER_AXIS:
1188 		print_pointer_axis_event(dev, e);
1189 		break;
1190 	case LIBINPUT_EVENT_TOUCH_DOWN:
1191 	case LIBINPUT_EVENT_TOUCH_UP:
1192 	case LIBINPUT_EVENT_TOUCH_MOTION:
1193 	case LIBINPUT_EVENT_TOUCH_CANCEL:
1194 	case LIBINPUT_EVENT_TOUCH_FRAME:
1195 		print_touch_event(dev, e);
1196 		break;
1197 	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
1198 	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
1199 	case LIBINPUT_EVENT_GESTURE_PINCH_END:
1200 	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
1201 	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
1202 	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
1203 		print_gesture_event(dev, e);
1204 		break;
1205 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
1206 		print_tablet_tool_proximity_event(dev, e);
1207 		break;
1208 	case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
1209 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
1210 		print_tablet_tool_event(dev, e);
1211 		break;
1212 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
1213 		print_tablet_tool_button_event(dev, e);
1214 		break;
1215 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
1216 		print_tablet_pad_button_event(dev, e);
1217 		break;
1218 	case LIBINPUT_EVENT_TABLET_PAD_RING:
1219 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
1220 		print_tablet_pad_ringstrip_event(dev, e);
1221 		break;
1222 	case LIBINPUT_EVENT_SWITCH_TOGGLE:
1223 		print_switch_event(dev, e);
1224 		break;
1225 	default:
1226 		break;
1227 	}
1228 }
1229 
1230 static bool
handle_hidraw(struct hidraw *hidraw)1231 handle_hidraw(struct hidraw *hidraw)
1232 {
1233 	struct record_device *d = hidraw->device;
1234 	unsigned char report[4096];
1235 	const char *sep = "";
1236 	struct timespec ts;
1237 	struct timeval tv;
1238 	uint64_t time;
1239 
1240 	int rc = read(hidraw->fd, report, sizeof(report));
1241 	if (rc <= 0)
1242 		return false;
1243 
1244 	/* hidraw doesn't give us a timestamps, we have to make them up */
1245 	clock_gettime(CLOCK_MONOTONIC, &ts);
1246 	time = s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
1247 
1248 	/* The first evdev event is guaranteed to have an event time earlier
1249 	   than now, so we don't set the offset here, we rely on the evdev
1250 	   events to do so. This potentially leaves us with multiple hidraw
1251 	   events at timestap 0 but it's too niche to worry about.  */
1252 	if (d->ctx->offset == 0)
1253 		time = 0;
1254 	else
1255 		time = time_offset(d->ctx, time);
1256 
1257 	tv = us2tv(time);
1258 
1259 	iprintf(d->fp, I_EVENTTYPE, "- hid:\n");
1260 	iprintf(d->fp, I_EVENT, "time: [%3lu, %6lu]\n", tv.tv_sec, tv.tv_usec);
1261 	iprintf(d->fp, I_EVENT, "%s: [", hidraw->name);
1262 
1263 	for (int byte = 0; byte < rc; byte++) {
1264 		if (byte % 16 == 0) {
1265 			iprintf(d->fp, I_NONE, "%s\n", sep);
1266 			iprintf(d->fp, I_EVENT, "  ");
1267 			iprintf(d->fp, I_NONE, "0x%02x", report[byte]);
1268 		} else {
1269 			iprintf(d->fp, I_NONE, "%s0x%02x", sep, report[byte]);
1270 		}
1271 		sep = ", ";
1272 	}
1273 	iprintf(d->fp, I_NONE, "\n");
1274 	iprintf(d->fp, I_EVENT, "]\n");
1275 
1276 	return true;
1277 }
1278 
1279 static bool
handle_libinput_events(struct record_context *ctx, struct record_device *d, bool start_frame)1280 handle_libinput_events(struct record_context *ctx,
1281 		       struct record_device *d,
1282 		       bool start_frame)
1283 {
1284 	struct libinput_event *e;
1285 	struct record_device *current = d;
1286 
1287 	libinput_dispatch(ctx->libinput);
1288 	e = libinput_get_event(ctx->libinput);
1289 	if (!e)
1290 		return false;
1291 
1292 	if (start_frame)
1293 		iprintf(d->fp, I_EVENTTYPE, "- libinput:\n");
1294 	else
1295 		iprintf(d->fp, I_EVENTTYPE, "libinput:\n");
1296 	do {
1297 		struct libinput_device *device = libinput_event_get_device(e);
1298 
1299 		if (device != current->device) {
1300 			struct record_device *tmp;
1301 			bool found = false;
1302 			list_for_each(tmp, &ctx->devices, link) {
1303 				if (device == tmp->device) {
1304 					current = tmp;
1305 					found = true;
1306 					break;
1307 				}
1308 			}
1309 			assert(found);
1310 		}
1311 
1312 		print_libinput_event(current, e);
1313 		libinput_event_destroy(e);
1314 	} while ((e = libinput_get_event(ctx->libinput)) != NULL);
1315 
1316 	return true;
1317 }
1318 
1319 static void
handle_events(struct record_context *ctx, struct record_device *d)1320 handle_events(struct record_context *ctx, struct record_device *d)
1321 {
1322 	bool has_events = true;
1323 
1324 	while (has_events) {
1325 		has_events = handle_evdev_frame(d);
1326 
1327 		if (ctx->libinput)
1328 			has_events |= handle_libinput_events(ctx,
1329 							     d,
1330 							     !has_events);
1331 	}
1332 
1333 	fflush(d->fp);
1334 }
1335 
1336 static void
print_libinput_header(FILE *fp, int timeout)1337 print_libinput_header(FILE *fp, int timeout)
1338 {
1339 	iprintf(fp, I_TOPLEVEL, "libinput:\n");
1340 	iprintf(fp, I_LIBINPUT, "version: \"%s\"\n", LIBINPUT_VERSION);
1341 	iprintf(fp, I_LIBINPUT, "git: \"%s\"\n", LIBINPUT_GIT_VERSION);
1342 	if (timeout > 0)
1343 		iprintf(fp, I_LIBINPUT, "autorestart: %d\n", timeout);
1344 }
1345 
1346 static void
print_system_header(FILE *fp)1347 print_system_header(FILE *fp)
1348 {
1349 	struct utsname u;
1350 	const char *kernel = "unknown";
1351 	FILE *dmi, *osrelease;
1352 	char dmistr[2048] = "unknown";
1353 
1354 	iprintf(fp, I_TOPLEVEL, "system:\n");
1355 
1356 	/* /etc/os-release version and distribution name */
1357 	osrelease = fopen("/etc/os-release", "r");
1358 	if (!osrelease)
1359 		osrelease = fopen("/usr/lib/os-release", "r");
1360 	if (osrelease) {
1361 		char *distro = NULL, *version = NULL;
1362 		char osrstr[256] = "unknown";
1363 
1364 		while (fgets(osrstr, sizeof(osrstr), osrelease)) {
1365 			osrstr[strlen(osrstr) - 1] = '\0'; /* linebreak */
1366 
1367 			if (!distro && strneq(osrstr, "ID=", 3))
1368 				distro = strstrip(&osrstr[3], "\"'");
1369 			else if (!version && strneq(osrstr, "VERSION_ID=", 11))
1370 				version = strstrip(&osrstr[11], "\"'");
1371 
1372 			if (distro && version) {
1373 				iprintf(fp,
1374 					I_SYSTEM,
1375 					"os: \"%s:%s\"\n",
1376 					distro,
1377 					version);
1378 				break;
1379 			}
1380 		}
1381 		free(distro);
1382 		free(version);
1383 		fclose(osrelease);
1384 	}
1385 
1386 	/* kernel version */
1387 	if (uname(&u) != -1)
1388 		kernel = u.release;
1389 	iprintf(fp, I_SYSTEM, "kernel: \"%s\"\n", kernel);
1390 
1391 	/* dmi modalias */
1392 	dmi = fopen("/sys/class/dmi/id/modalias", "r");
1393 	if (dmi) {
1394 		if (fgets(dmistr, sizeof(dmistr), dmi)) {
1395 			dmistr[strlen(dmistr) - 1] = '\0'; /* linebreak */
1396 		} else {
1397 			sprintf(dmistr, "unknown");
1398 		}
1399 		fclose(dmi);
1400 	}
1401 	iprintf(fp, I_SYSTEM, "dmi: \"%s\"\n", dmistr);
1402 }
1403 
1404 static void
print_header(FILE *fp, struct record_context *ctx)1405 print_header(FILE *fp, struct record_context *ctx)
1406 {
1407 	iprintf(fp, I_TOPLEVEL, "# libinput record\n");
1408 	iprintf(fp, I_TOPLEVEL, "version: %d\n", FILE_VERSION_NUMBER);
1409 	iprintf(fp, I_TOPLEVEL, "ndevices: %d\n", ctx->ndevices);
1410 	print_libinput_header(fp, ctx->timeout);
1411 	print_system_header(fp);
1412 }
1413 
1414 static void
print_description_abs(FILE *fp, struct libevdev *dev, unsigned int code)1415 print_description_abs(FILE *fp,
1416 		      struct libevdev *dev,
1417 		      unsigned int code)
1418 {
1419 	const struct input_absinfo *abs;
1420 
1421 	abs = libevdev_get_abs_info(dev, code);
1422 	assert(abs);
1423 
1424 	iprintf(fp, I_EVDEV, "#       Value      %6d\n", abs->value);
1425 	iprintf(fp, I_EVDEV, "#       Min        %6d\n", abs->minimum);
1426 	iprintf(fp, I_EVDEV, "#       Max        %6d\n", abs->maximum);
1427 	iprintf(fp, I_EVDEV, "#       Fuzz       %6d\n", abs->fuzz);
1428 	iprintf(fp, I_EVDEV, "#       Flat       %6d\n", abs->flat);
1429 	iprintf(fp, I_EVDEV, "#       Resolution %6d\n", abs->resolution);
1430 }
1431 
1432 static void
print_description_state(FILE *fp, struct libevdev *dev, unsigned int type, unsigned int code)1433 print_description_state(FILE *fp,
1434 			struct libevdev *dev,
1435 			unsigned int type,
1436 			unsigned int code)
1437 {
1438 	int state = libevdev_get_event_value(dev, type, code);
1439 	iprintf(fp, I_EVDEV, "#       State %d\n", state);
1440 }
1441 
1442 static void
print_description_codes(FILE *fp, struct libevdev *dev, unsigned int type)1443 print_description_codes(FILE *fp,
1444 			struct libevdev *dev,
1445 			unsigned int type)
1446 {
1447 	int max;
1448 
1449 	max = libevdev_event_type_get_max(type);
1450 	if (max == -1)
1451 		return;
1452 
1453 	iprintf(fp,
1454 		I_EVDEV,
1455 		"# Event type %d (%s)\n",
1456 		type,
1457 		libevdev_event_type_get_name(type));
1458 
1459 	if (type == EV_SYN)
1460 		return;
1461 
1462 	for (unsigned int code = 0; code <= (unsigned int)max; code++) {
1463 		if (!libevdev_has_event_code(dev, type, code))
1464 			continue;
1465 
1466 		iprintf(fp,
1467 			I_EVDEV,
1468 			"#   Event code %d (%s)\n",
1469 			code,
1470 			libevdev_event_code_get_name(type,
1471 						     code));
1472 
1473 		switch (type) {
1474 		case EV_ABS:
1475 			print_description_abs(fp, dev, code);
1476 			break;
1477 		case EV_LED:
1478 		case EV_SW:
1479 			print_description_state(fp, dev, type, code);
1480 			break;
1481 		}
1482 	}
1483 }
1484 
1485 static void
print_description(FILE *fp, struct libevdev *dev)1486 print_description(FILE *fp, struct libevdev *dev)
1487 {
1488 	const struct input_absinfo *x, *y;
1489 	int bustype;
1490 	const char *busname;
1491 
1492 	bustype = libevdev_get_id_bustype(dev);
1493 	switch (bustype) {
1494 	case BUS_USB:
1495 		busname = " (usb) ";
1496 		break;
1497 	case BUS_BLUETOOTH:
1498 		busname = " (bluetooth) ";
1499 		break;
1500 	case BUS_I2C:
1501 		busname = " (i2c) ";
1502 		break;
1503 	case BUS_SPI:
1504 		busname = " (spi) ";
1505 		break;
1506 	case BUS_RMI:
1507 		busname = " (rmi) ";
1508 		break;
1509 	default:
1510 		busname = " ";
1511 		break;
1512 	}
1513 
1514 	iprintf(fp, I_EVDEV, "# Name: %s\n", libevdev_get_name(dev));
1515 	iprintf(fp,
1516 		I_EVDEV,
1517 		"# ID: bus 0x%04x%svendor 0x%04x product 0x%04x version 0x%04x\n",
1518 		bustype,
1519 		busname,
1520 		libevdev_get_id_vendor(dev),
1521 		libevdev_get_id_product(dev),
1522 		libevdev_get_id_version(dev));
1523 
1524 	x = libevdev_get_abs_info(dev, ABS_X);
1525 	y = libevdev_get_abs_info(dev, ABS_Y);
1526 	if (x && y) {
1527 		if (x->resolution && y->resolution) {
1528 			int w, h;
1529 
1530 			w = (x->maximum - x->minimum)/x->resolution;
1531 			h = (y->maximum - y->minimum)/y->resolution;
1532 			iprintf(fp, I_EVDEV, "# Size in mm: %dx%d\n", w, h);
1533 		} else {
1534 			iprintf(fp,
1535 				I_EVDEV,
1536 				"# Size in mm: unknown, missing resolution\n");
1537 		}
1538 	}
1539 
1540 	iprintf(fp, I_EVDEV, "# Supported Events:\n");
1541 
1542 	for (unsigned int type = 0; type < EV_CNT; type++) {
1543 		if (!libevdev_has_event_type(dev, type))
1544 			continue;
1545 
1546 		print_description_codes(fp, dev, type);
1547 	}
1548 
1549 	iprintf(fp, I_EVDEV, "# Properties:\n");
1550 
1551 	for (unsigned int prop = 0; prop < INPUT_PROP_CNT; prop++) {
1552 		if (libevdev_has_property(dev, prop)) {
1553 			iprintf(fp,
1554 				I_EVDEV,
1555 				"#    Property %d (%s)\n",
1556 				prop,
1557 				libevdev_property_get_name(prop));
1558 		}
1559 	}
1560 }
1561 
1562 static void
print_bits_info(FILE *fp, struct libevdev *dev)1563 print_bits_info(FILE *fp, struct libevdev *dev)
1564 {
1565 	iprintf(fp, I_EVDEV, "name: \"%s\"\n", libevdev_get_name(dev));
1566 	iprintf(fp,
1567 		I_EVDEV,
1568 		"id: [%d, %d, %d, %d]\n",
1569 		libevdev_get_id_bustype(dev),
1570 		libevdev_get_id_vendor(dev),
1571 		libevdev_get_id_product(dev),
1572 		libevdev_get_id_version(dev));
1573 }
1574 
1575 static void
print_bits_absinfo(FILE *fp, struct libevdev *dev)1576 print_bits_absinfo(FILE *fp, struct libevdev *dev)
1577 {
1578 	const struct input_absinfo *abs;
1579 
1580 	if (!libevdev_has_event_type(dev, EV_ABS))
1581 		return;
1582 
1583 	iprintf(fp, I_EVDEV, "absinfo:\n");
1584 	for (unsigned int code = 0; code < ABS_CNT; code++) {
1585 		abs = libevdev_get_abs_info(dev, code);
1586 		if (!abs)
1587 			continue;
1588 
1589 		iprintf(fp,
1590 			I_EVDEV_DATA,
1591 			"%d: [%d, %d, %d, %d, %d]\n",
1592 			code,
1593 			abs->minimum,
1594 			abs->maximum,
1595 			abs->fuzz,
1596 			abs->flat,
1597 			abs->resolution);
1598 	}
1599 }
1600 
1601 static void
print_bits_codes(FILE *fp, struct libevdev *dev, unsigned int type)1602 print_bits_codes(FILE *fp, struct libevdev *dev, unsigned int type)
1603 {
1604 	int max;
1605 	const char *sep = "";
1606 
1607 	max = libevdev_event_type_get_max(type);
1608 	if (max == -1)
1609 		return;
1610 
1611 	iprintf(fp, I_EVDEV_DATA, "%d: [", type);
1612 
1613 	for (unsigned int code = 0; code <= (unsigned int)max; code++) {
1614 		if (!libevdev_has_event_code(dev, type, code))
1615 			continue;
1616 
1617 		iprintf(fp, I_NONE, "%s%d", sep, code);
1618 		sep = ", ";
1619 	}
1620 
1621 	iprintf(fp, I_NONE, "] # %s\n", libevdev_event_type_get_name(type));
1622 }
1623 
1624 static void
print_bits_types(FILE *fp, struct libevdev *dev)1625 print_bits_types(FILE *fp, struct libevdev *dev)
1626 {
1627 	iprintf(fp, I_EVDEV, "codes:\n");
1628 	for (unsigned int type = 0; type < EV_CNT; type++) {
1629 		if (!libevdev_has_event_type(dev, type))
1630 			continue;
1631 		print_bits_codes(fp, dev, type);
1632 	}
1633 }
1634 
1635 static void
print_bits_props(FILE *fp, struct libevdev *dev)1636 print_bits_props(FILE *fp, struct libevdev *dev)
1637 {
1638 	const char *sep = "";
1639 
1640 	iprintf(fp, I_EVDEV, "properties: [");
1641 	for (unsigned int prop = 0; prop < INPUT_PROP_CNT; prop++) {
1642 		if (libevdev_has_property(dev, prop)) {
1643 			iprintf(fp, I_NONE, "%s%d", sep, prop);
1644 			sep = ", ";
1645 		}
1646 	}
1647 	iprintf(fp, I_NONE, "]\n"); /* last entry, no comma */
1648 }
1649 
1650 static void
print_evdev_description(struct record_device *dev)1651 print_evdev_description(struct record_device *dev)
1652 {
1653 	struct libevdev *evdev = dev->evdev;
1654 
1655 	iprintf(dev->fp, I_DEVICE, "evdev:\n");
1656 
1657 	print_description(dev->fp, evdev);
1658 	print_bits_info(dev->fp, evdev);
1659 	print_bits_types(dev->fp, evdev);
1660 	print_bits_absinfo(dev->fp, evdev);
1661 	print_bits_props(dev->fp, evdev);
1662 }
1663 
1664 static void
print_hid_report_descriptor(struct record_device *dev)1665 print_hid_report_descriptor(struct record_device *dev)
1666 {
1667 	const char *prefix = "/dev/input/event";
1668 	char syspath[PATH_MAX];
1669 	unsigned char buf[1024];
1670 	int len;
1671 	int fd;
1672 	const char *sep = "";
1673 
1674 	/* we take the shortcut rather than the proper udev approach, the
1675 	   report_descriptor is available in sysfs and two devices up from
1676 	   our device.
1677 	   This approach won't work for /dev/input/by-id devices. */
1678 	if (!strstartswith(dev->devnode, prefix))
1679 		return;
1680 
1681 	len = snprintf(syspath,
1682 		       sizeof(syspath),
1683 		       "/sys/class/input/%s/device/device/report_descriptor",
1684 		       safe_basename(dev->devnode));
1685 	if (len <= 0)
1686 		return;
1687 
1688 	fd = open(syspath, O_RDONLY);
1689 	if (fd == -1)
1690 		return;
1691 
1692 	iprintf(dev->fp, I_DEVICE, "hid: [");
1693 
1694 	while ((len = read(fd, buf, sizeof(buf))) > 0) {
1695 		for (int i = 0; i < len; i++) {
1696 			/* We can't have a trailing comma, so our line-break
1697 			 * handling is awkward.
1698 			 * For a linebreak: print the comma, break, indent,
1699 			 *    then just the hex code.
1700 			 * For the other values: print the comma plus the
1701 			 *    hex code, unindented.
1702 			 */
1703 			if (i % 16 == 0) {
1704 				iprintf(dev->fp, I_NONE, "%s\n", sep);
1705 				iprintf(dev->fp, I_DEVICE, "  ");
1706 				iprintf(dev->fp, I_NONE, "0x%02x", buf[i]);
1707 			} else {
1708 				iprintf(dev->fp, I_NONE, "%s0x%02x", sep, buf[i]);
1709 			}
1710 			sep = ", ";
1711 		}
1712 	}
1713 	iprintf(dev->fp, I_NONE, "\n");
1714 	iprintf(dev->fp, I_DEVICE, "]\n");
1715 
1716 	close(fd);
1717 }
1718 
1719 static void
print_udev_properties(struct record_device *dev)1720 print_udev_properties(struct record_device *dev)
1721 {
1722 	struct udev *udev = NULL;
1723 	struct udev_device *udev_device = NULL;
1724 	struct udev_list_entry *entry;
1725 	struct stat st;
1726 
1727 	if (stat(dev->devnode, &st) < 0)
1728 		return;
1729 
1730 	udev = udev_new();
1731 	if (!udev)
1732 		goto out;
1733 
1734 	udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
1735 	if (!udev_device)
1736 		goto out;
1737 
1738 	iprintf(dev->fp, I_DEVICE, "udev:\n");
1739 
1740 	iprintf(dev->fp, I_UDEV, "properties:\n");
1741 
1742 	entry = udev_device_get_properties_list_entry(udev_device);
1743 	while (entry) {
1744 		const char *key, *value;
1745 
1746 		key = udev_list_entry_get_name(entry);
1747 
1748 		if (strneq(key, "ID_INPUT", 8) ||
1749 		    strneq(key, "LIBINPUT", 8) ||
1750 		    strneq(key, "EVDEV_ABS", 9) ||
1751 		    strneq(key, "MOUSE_DPI", 9) ||
1752 		    strneq(key, "POINTINGSTICK_", 14)) {
1753 			value = udev_list_entry_get_value(entry);
1754 			iprintf(dev->fp, I_UDEV_DATA, "- %s=%s\n", key, value);
1755 		}
1756 
1757 		entry = udev_list_entry_get_next(entry);
1758 	}
1759 
1760 out:
1761 	udev_device_unref(udev_device);
1762 	udev_unref(udev);
1763 }
1764 
1765 static void
quirks_log_handler(struct libinput *this_is_null, enum libinput_log_priority priority, const char *format, va_list args)1766 quirks_log_handler(struct libinput *this_is_null,
1767 		   enum libinput_log_priority priority,
1768 		   const char *format,
1769 		   va_list args)
1770 {
1771 }
1772 
1773 static void
list_print(void *userdata, const char *val)1774 list_print(void *userdata, const char *val)
1775 {
1776 	FILE *fp = userdata;
1777 
1778 	iprintf(fp, I_QUIRKS, "- %s\n", val);
1779 }
1780 
1781 static void
print_device_quirks(struct record_device *dev)1782 print_device_quirks(struct record_device *dev)
1783 {
1784 	struct udev *udev = NULL;
1785 	struct udev_device *udev_device = NULL;
1786 	struct stat st;
1787 	struct quirks_context *quirks;
1788 	const char *data_path = LIBINPUT_QUIRKS_DIR;
1789 	const char *override_file = LIBINPUT_QUIRKS_OVERRIDE_FILE;
1790 	char *builddir = NULL;
1791 
1792 	if (stat(dev->devnode, &st) < 0)
1793 		return;
1794 
1795 	if ((builddir = builddir_lookup())) {
1796 		setenv("LIBINPUT_QUIRKS_DIR", LIBINPUT_QUIRKS_SRCDIR, 0);
1797 		data_path = LIBINPUT_QUIRKS_SRCDIR;
1798 		override_file = NULL;
1799 	}
1800 
1801 	free(builddir);
1802 
1803 	quirks = quirks_init_subsystem(data_path,
1804 				       override_file,
1805 				       quirks_log_handler,
1806 				       NULL,
1807 				       QLOG_CUSTOM_LOG_PRIORITIES);
1808 	if (!quirks) {
1809 		fprintf(stderr,
1810 			"Failed to load the device quirks from %s%s%s. "
1811 			"This will negatively affect device behavior. "
1812 			"See %s/device-quirks.html for details.\n",
1813 			data_path,
1814 			override_file ? " and " : "",
1815 			override_file ? override_file : "",
1816 			HTTP_DOC_LINK);
1817 		return;
1818 	}
1819 
1820 	udev = udev_new();
1821 	if (!udev)
1822 		goto out;
1823 
1824 	udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
1825 	if (!udev_device)
1826 		goto out;
1827 
1828 	iprintf(dev->fp, I_DEVICE, "quirks:\n");
1829 	tools_list_device_quirks(quirks, udev_device, list_print, dev->fp);
1830 out:
1831 	udev_device_unref(udev_device);
1832 	udev_unref(udev);
1833 	quirks_context_unref(quirks);
1834 }
1835 
1836 static void
print_libinput_description(struct record_device *dev)1837 print_libinput_description(struct record_device *dev)
1838 {
1839 	struct libinput_device *device = dev->device;
1840 	double w, h;
1841 	struct cap {
1842 		enum libinput_device_capability cap;
1843 		const char *name;
1844 	} caps[] =  {
1845 		{LIBINPUT_DEVICE_CAP_KEYBOARD, "keyboard"},
1846 		{LIBINPUT_DEVICE_CAP_POINTER, "pointer"},
1847 		{LIBINPUT_DEVICE_CAP_TOUCH, "touch"},
1848 		{LIBINPUT_DEVICE_CAP_TABLET_TOOL, "tablet"},
1849 		{LIBINPUT_DEVICE_CAP_TABLET_PAD, "pad"},
1850 		{LIBINPUT_DEVICE_CAP_GESTURE, "gesture"},
1851 		{LIBINPUT_DEVICE_CAP_SWITCH, "switch"},
1852 	};
1853 	const char *sep = "";
1854 
1855 	if (!device)
1856 		return;
1857 
1858 	iprintf(dev->fp, I_DEVICE, "libinput:\n");
1859 	if (libinput_device_get_size(device, &w, &h) == 0)
1860 		iprintf(dev->fp, I_LIBINPUTDEV, "size: [%.f, %.f]\n", w, h);
1861 
1862 	iprintf(dev->fp, I_LIBINPUTDEV, "capabilities: [");
1863 	ARRAY_FOR_EACH(caps, cap) {
1864 		if (!libinput_device_has_capability(device, cap->cap))
1865 			continue;
1866 		iprintf(dev->fp, I_NONE, "%s%s", sep, cap->name);
1867 		sep = ", ";
1868 	}
1869 	iprintf(dev->fp, I_NONE, "]\n");
1870 
1871 	/* Configuration options should be printed here, but since they
1872 	 * don't reflect the user-configured ones their usefulness is
1873 	 * questionable. We need the ability to specify the options like in
1874 	 * debug-events.
1875 	 */
1876 }
1877 
1878 static void
print_device_description(struct record_device *dev)1879 print_device_description(struct record_device *dev)
1880 {
1881 	iprintf(dev->fp, I_DEVICE, "- node: %s\n", dev->devnode);
1882 
1883 	print_evdev_description(dev);
1884 	print_hid_report_descriptor(dev);
1885 	print_udev_properties(dev);
1886 	print_device_quirks(dev);
1887 	print_libinput_description(dev);
1888 }
1889 
is_event_node(const struct dirent *dir)1890 static int is_event_node(const struct dirent *dir) {
1891 	return strneq(dir->d_name, "event", 5);
1892 }
1893 
1894 static char *
select_device(void)1895 select_device(void)
1896 {
1897 	struct dirent **namelist;
1898 	int ndev, selected_device;
1899 	int rc;
1900 	char *device_path;
1901 	bool has_eaccess = false;
1902 	int available_devices = 0;
1903 	const char *prefix = "";
1904 
1905 	if (!isatty(STDERR_FILENO))
1906 		prefix = "# ";
1907 
1908 	ndev = scandir("/dev/input", &namelist, is_event_node, versionsort);
1909 	if (ndev <= 0)
1910 		return NULL;
1911 
1912 	fprintf(stderr, "%sAvailable devices:\n", prefix);
1913 	for (int i = 0; i < ndev; i++) {
1914 		struct libevdev *device;
1915 		char path[PATH_MAX];
1916 		int fd = -1;
1917 
1918 		snprintf(path,
1919 			 sizeof(path),
1920 			 "/dev/input/%s",
1921 			 namelist[i]->d_name);
1922 		fd = open(path, O_RDONLY);
1923 		if (fd < 0) {
1924 			if (errno == EACCES)
1925 				has_eaccess = true;
1926 			continue;
1927 		}
1928 
1929 		rc = libevdev_new_from_fd(fd, &device);
1930 		close(fd);
1931 		if (rc != 0)
1932 			continue;
1933 
1934 		fprintf(stderr, "%s%s:	%s\n", prefix, path, libevdev_get_name(device));
1935 		libevdev_free(device);
1936 		available_devices++;
1937 	}
1938 
1939 	for (int i = 0; i < ndev; i++)
1940 		free(namelist[i]);
1941 	free(namelist);
1942 
1943 	if (available_devices == 0) {
1944 		fprintf(stderr,
1945 			"No devices available.%s\n",
1946 			has_eaccess ? " Please re-run as root." : "");
1947 		return NULL;
1948 	}
1949 
1950 	fprintf(stderr, "%sSelect the device event number: ", prefix);
1951 	rc = scanf("%d", &selected_device);
1952 
1953 	if (rc != 1 || selected_device < 0)
1954 		return NULL;
1955 
1956 	rc = xasprintf(&device_path, "/dev/input/event%d", selected_device);
1957 	if (rc == -1)
1958 		return NULL;
1959 
1960 	return device_path;
1961 }
1962 
1963 static char **
all_devices(void)1964 all_devices(void)
1965 {
1966 	struct dirent **namelist;
1967 	int ndev;
1968 	char **devices = NULL;
1969 
1970 	ndev = scandir("/dev/input", &namelist, is_event_node, versionsort);
1971 	if (ndev <= 0)
1972 		return NULL;
1973 
1974 	devices = zalloc((ndev + 1)* sizeof *devices); /* NULL-terminated */
1975 	for (int i = 0; i < ndev; i++) {
1976 		char *device_path;
1977 
1978 		int rc = xasprintf(&device_path,
1979 				   "/dev/input/%s",
1980 				   namelist[i]->d_name);
1981 		if (rc == -1)
1982 			goto error;
1983 
1984 		devices[i] = device_path;
1985 	}
1986 
1987 	return devices;
1988 
1989 error:
1990 	for (int i = 0; i < ndev; i++)
1991 		free(namelist[i]);
1992 	free(namelist);
1993 	if (devices)
1994 		strv_free(devices);
1995 	return NULL;
1996 }
1997 
1998 static char *
init_output_file(const char *file, bool is_prefix)1999 init_output_file(const char *file, bool is_prefix)
2000 {
2001 	char name[PATH_MAX];
2002 
2003 	assert(file != NULL);
2004 
2005 	if (is_prefix) {
2006 		struct tm *tm;
2007 		time_t t;
2008 		char suffix[64];
2009 
2010 		t = time(NULL);
2011 		tm = localtime(&t);
2012 		strftime(suffix, sizeof(suffix), "%F-%T", tm);
2013 		snprintf(name,
2014 			 sizeof(name),
2015 			 "%s.%s",
2016 			 file,
2017 			 suffix);
2018 	} else {
2019 		snprintf(name, sizeof(name), "%s", file);
2020 	}
2021 
2022 	return safe_strdup(name);
2023 }
2024 
2025 static bool
open_output_files(struct record_context *ctx, bool is_prefix)2026 open_output_files(struct record_context *ctx, bool is_prefix)
2027 {
2028 	FILE *out_file;
2029 	struct record_device *d;
2030 
2031 	if (ctx->output_file.name) {
2032 		char *fname = init_output_file(ctx->output_file.name, is_prefix);
2033 		ctx->output_file.name_with_suffix = fname;
2034 		out_file = fopen(fname, "w");
2035 		if (!out_file)
2036 			return false;
2037 	} else {
2038 		ctx->output_file.name_with_suffix = safe_strdup("stdout");
2039 		out_file = stdout;
2040 	}
2041 
2042 	ctx->first_device->fp = out_file;
2043 
2044 	list_for_each(d, &ctx->devices, link) {
2045 		if (d->fp)
2046 			continue;
2047 		d->fp = tmpfile();
2048 	}
2049 
2050 	return true;
2051 }
2052 
2053 static void
print_progress_bar(void)2054 print_progress_bar(void)
2055 {
2056 	static uint8_t foo = 0;
2057 
2058 	if (!isatty(STDERR_FILENO))
2059 		return;
2060 
2061 	if (++foo > 20)
2062 		foo = 1;
2063 	fprintf(stderr, "\rReceiving events: [%*s%*s]", foo, "*", 21 - foo, " ");
2064 }
2065 
2066 static void
print_wall_time(struct record_context *ctx)2067 print_wall_time(struct record_context *ctx)
2068 {
2069 	time_t t = time(NULL);
2070 	struct tm tm;
2071 	struct record_device *d;
2072 
2073 	localtime_r(&t, &tm);
2074 
2075 	list_for_each(d, &ctx->devices, link) {
2076 		iprintf(d->fp,
2077 			I_DEVICE,
2078 			"# Current time is %02d:%02d:%02d\n",
2079 			tm.tm_hour, tm.tm_min, tm.tm_sec);
2080 		fflush(d->fp);
2081 	}
2082 }
2083 
2084 static void
arm_timer(int timerfd)2085 arm_timer(int timerfd)
2086 {
2087 	time_t t = time(NULL);
2088 	struct tm tm;
2089 	struct itimerspec interval = {
2090 		.it_value = { 0, 0 },
2091 		.it_interval = { 5, 0 },
2092 	};
2093 
2094 	localtime_r(&t, &tm);
2095 	interval.it_value.tv_sec = 5 - (tm.tm_sec % 5);
2096 	timerfd_settime(timerfd, 0, &interval, NULL);
2097 }
2098 
2099 static struct source *
add_source(struct record_context *ctx, int fd, source_dispatch_t dispatch, void *user_data)2100 add_source(struct record_context *ctx,
2101 	   int fd,
2102 	   source_dispatch_t dispatch,
2103 	   void *user_data)
2104 {
2105 	struct source *source;
2106 	struct epoll_event ep;
2107 
2108 	assert(fd != -1);
2109 
2110 	source = zalloc(sizeof *source);
2111 	source->dispatch = dispatch;
2112 	source->user_data = user_data;
2113 	source->fd = fd;
2114 	list_append(&ctx->sources, &source->link);
2115 
2116 	memset(&ep, 0, sizeof ep);
2117 	ep.events = EPOLLIN;
2118 	ep.data.ptr = source;
2119 
2120 	if (epoll_ctl(ctx->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
2121 		free(source);
2122 		return NULL;
2123 	}
2124 
2125 	return source;
2126 }
2127 
2128 static void
destroy_source(struct record_context *ctx, struct source *source)2129 destroy_source(struct record_context *ctx, struct source *source)
2130 {
2131 	list_remove(&source->link);
2132 	epoll_ctl(ctx->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
2133 	close(source->fd);
2134 	free(source);
2135 }
2136 
2137 static void
signalfd_dispatch(struct record_context *ctx, int fd, void *data)2138 signalfd_dispatch(struct record_context *ctx, int fd, void *data)
2139 {
2140 	struct signalfd_siginfo fdsi;
2141 
2142 	(void)read(fd, &fdsi, sizeof(fdsi));
2143 
2144 	ctx->stop = true;
2145 }
2146 
2147 static void
timefd_dispatch(struct record_context *ctx, int fd, void *data)2148 timefd_dispatch(struct record_context *ctx, int fd, void *data)
2149 {
2150 	char discard[64];
2151 
2152 	(void)read(fd, discard, sizeof(discard));
2153 
2154 	if (ctx->timestamps.had_events_since_last_time) {
2155 		print_wall_time(ctx);
2156 		ctx->timestamps.had_events_since_last_time = false;
2157 		ctx->timestamps.skipped_timer_print = false;
2158 	} else {
2159 		ctx->timestamps.skipped_timer_print = true;
2160 	}
2161 }
2162 
2163 static void
evdev_dispatch(struct record_context *ctx, int fd, void *data)2164 evdev_dispatch(struct record_context *ctx, int fd, void *data)
2165 {
2166 	struct record_device *this_device = data;
2167 
2168 	if (ctx->timestamps.skipped_timer_print) {
2169 		print_wall_time(ctx);
2170 		ctx->timestamps.skipped_timer_print = false;
2171 	}
2172 
2173 	ctx->had_events = true;
2174 	ctx->timestamps.had_events_since_last_time = true;
2175 
2176 	handle_events(ctx, this_device);
2177 }
2178 
2179 static void
libinput_ctx_dispatch(struct record_context *ctx, int fd, void *data)2180 libinput_ctx_dispatch(struct record_context *ctx, int fd, void *data)
2181 {
2182 	/* This function should only handle events caused by internal
2183 	 * timeouts etc. The real input events caused by the evdev devices
2184 	 * are already processed in handle_events */
2185 	libinput_dispatch(ctx->libinput);
2186 	handle_libinput_events(ctx, ctx->first_device, true);
2187 }
2188 
2189 static void
hidraw_dispatch(struct record_context *ctx, int fd, void *data)2190 hidraw_dispatch(struct record_context *ctx, int fd, void *data)
2191 {
2192 	struct hidraw *hidraw = data;
2193 
2194 	ctx->had_events = true;
2195 	ctx->timestamps.had_events_since_last_time = true;
2196 	handle_hidraw(hidraw);
2197 }
2198 
2199 static int
dispatch_sources(struct record_context *ctx)2200 dispatch_sources(struct record_context *ctx)
2201 {
2202 	struct source *source;
2203 	struct epoll_event ep[64];
2204 	int i, count;
2205 
2206 	count = epoll_wait(ctx->epoll_fd, ep, ARRAY_LENGTH(ep), ctx->timeout);
2207 	if (count < 0)
2208 		return -errno;
2209 
2210 	for (i = 0; i < count; ++i) {
2211 		source = ep[i].data.ptr;
2212 		if (source->fd == -1)
2213 			continue;
2214 		source->dispatch(ctx, source->fd, source->user_data);
2215 	}
2216 
2217 	return count;
2218 }
2219 
2220 static int
mainloop(struct record_context *ctx)2221 mainloop(struct record_context *ctx)
2222 {
2223 	bool autorestart = (ctx->timeout > 0);
2224 	struct source *source;
2225 	struct record_device *d = NULL;
2226 	sigset_t mask;
2227 	int sigfd, timerfd;
2228 
2229 	assert(ctx->timeout != 0);
2230 	assert(!list_empty(&ctx->devices));
2231 
2232 	ctx->epoll_fd = epoll_create1(0);
2233 	assert(ctx->epoll_fd >= 0);
2234 
2235 	sigemptyset(&mask);
2236 	sigaddset(&mask, SIGINT);
2237 	sigaddset(&mask, SIGQUIT);
2238 	sigprocmask(SIG_BLOCK, &mask, NULL);
2239 
2240 	sigfd = signalfd(-1, &mask, SFD_NONBLOCK);
2241 	add_source(ctx, sigfd, signalfd_dispatch, NULL);
2242 
2243 	timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC|TFD_NONBLOCK);
2244 	add_source(ctx, timerfd, timefd_dispatch, NULL);
2245 	arm_timer(timerfd);
2246 
2247 	list_for_each(d, &ctx->devices, link) {
2248 		struct hidraw *hidraw;
2249 
2250 		add_source(ctx, libevdev_get_fd(d->evdev), evdev_dispatch, d);
2251 
2252 		list_for_each(hidraw, &d->hidraw_devices, link) {
2253 			add_source(ctx, hidraw->fd, hidraw_dispatch, hidraw);
2254 		}
2255 	}
2256 
2257 	if (ctx->libinput) {
2258 		/* See the note in the dispatch function */
2259 		add_source(ctx,
2260 			   libinput_get_fd(ctx->libinput),
2261 			   libinput_ctx_dispatch,
2262 			   NULL);
2263 	}
2264 
2265 	/* If we have more than one device, the time starts at recording
2266 	 * start time. Otherwise, the first event starts the recording time.
2267 	 */
2268 	if (ctx->ndevices > 1) {
2269 		struct timespec ts;
2270 
2271 		clock_gettime(CLOCK_MONOTONIC, &ts);
2272 		ctx->offset = s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
2273 	}
2274 
2275 	do {
2276 		struct record_device *d;
2277 
2278 		if (!open_output_files(ctx, autorestart)) {
2279 			fprintf(stderr,
2280 				"Failed to open '%s'\n",
2281 				ctx->output_file.name_with_suffix);
2282 			break;
2283 		}
2284 		fprintf(stderr, "%sRecording to '%s'.\n",
2285 			isatty(STDERR_FILENO) ? "" : "# ",
2286 			ctx->output_file.name_with_suffix);
2287 
2288 		ctx->had_events = false;
2289 
2290 		print_header(ctx->first_device->fp, ctx);
2291 		if (autorestart)
2292 			iprintf(ctx->first_device->fp,
2293 				I_NONE,
2294 				"# Autorestart timeout: %d\n",
2295 				ctx->timeout);
2296 
2297 		iprintf(ctx->first_device->fp, I_TOPLEVEL, "devices:\n");
2298 
2299 		/* we only print the first device's description, the
2300 		 * rest is assembled after CTRL+C */
2301 		list_for_each(d, &ctx->devices, link) {
2302 			print_device_description(d);
2303 			iprintf(d->fp, I_DEVICE, "events:\n");
2304 		}
2305 		print_wall_time(ctx);
2306 
2307 		if (ctx->libinput) {
2308 			libinput_dispatch(ctx->libinput);
2309 			handle_libinput_events(ctx, ctx->first_device, true);
2310 		}
2311 
2312 		while (true) {
2313 			int rc = dispatch_sources(ctx);
2314 			if (rc < 0) { /* error */
2315 				fprintf(stderr, "Error: %s\n", strerror(-rc));
2316 				ctx->stop = true;
2317 				break;
2318 			}
2319 
2320 			/* set by the signalfd handler */
2321 			if (ctx->stop)
2322 				break;
2323 
2324 			if (rc == 0) {
2325 				fprintf(stderr,
2326 					" ... timeout%s\n",
2327 					ctx->had_events ? "" : " (file is empty)");
2328 				break;
2329 
2330 			}
2331 
2332 			if (ctx->first_device->fp != stdout)
2333 				print_progress_bar();
2334 
2335 		}
2336 
2337 		if (autorestart) {
2338 			list_for_each(d, &ctx->devices, link) {
2339 				iprintf(d->fp,
2340 					I_NONE,
2341 					"# Closing after %ds inactivity",
2342 					ctx->timeout/1000);
2343 			}
2344 		}
2345 
2346 		/* First device is printed, now append all the data from the
2347 		 * other devices, if any */
2348 		list_for_each(d, &ctx->devices, link) {
2349 			char buf[4096];
2350 			size_t n;
2351 
2352 			if (d == ctx->first_device)
2353 				continue;
2354 
2355 			rewind(d->fp);
2356 			do {
2357 
2358 				n = fread(buf, 1, sizeof(buf), d->fp);
2359 				if (n > 0)
2360 					fwrite(buf, 1, n, ctx->first_device->fp);
2361 			} while (n == sizeof(buf));
2362 
2363 			fclose(d->fp);
2364 			d->fp = NULL;
2365 		}
2366 
2367 		/* If we didn't have events, delete the file. */
2368 		if (!isatty(fileno(ctx->first_device->fp))) {
2369 			struct record_device *d;
2370 
2371 			if (!ctx->had_events && ctx->output_file.name_with_suffix) {
2372 				fprintf(stderr,
2373 					"No events recorded, deleting '%s'\n",
2374 					ctx->output_file.name_with_suffix);
2375 				unlink(ctx->output_file.name_with_suffix);
2376 			}
2377 
2378 			list_for_each(d, &ctx->devices, link) {
2379 				if (d->fp && d->fp != stdout) {
2380 					fclose(d->fp);
2381 					d->fp = NULL;
2382 				}
2383 			}
2384 		}
2385 		free(ctx->output_file.name_with_suffix);
2386 		ctx->output_file.name_with_suffix = NULL;
2387 	} while (autorestart && !ctx->stop);
2388 
2389 	sigprocmask(SIG_UNBLOCK, &mask, NULL);
2390 
2391 	list_for_each_safe(source, &ctx->sources, link) {
2392 		destroy_source(ctx, source);
2393 	}
2394 	close(ctx->epoll_fd);
2395 
2396 	return 0;
2397 }
2398 
2399 static bool
init_device(struct record_context *ctx, const char *path, bool grab)2400 init_device(struct record_context *ctx, const char *path, bool grab)
2401 {
2402 	struct record_device *d;
2403 	int fd, rc;
2404 
2405 	d = zalloc(sizeof(*d));
2406 	d->ctx = ctx;
2407 	d->devnode = safe_strdup(path);
2408 
2409 	list_init(&d->hidraw_devices);
2410 
2411 	fd = open(d->devnode, O_RDONLY|O_NONBLOCK);
2412 	if (fd < 0) {
2413 		fprintf(stderr,
2414 			"Failed to open device %s (%m)\n",
2415 			d->devnode);
2416 		goto error;
2417 	}
2418 
2419 	rc = libevdev_new_from_fd(fd, &d->evdev);
2420 	if (rc == 0)
2421 		rc = libevdev_new_from_fd(fd, &d->evdev_prev);
2422 	if (rc != 0) {
2423 		fprintf(stderr,
2424 			"Failed to create context for %s (%s)\n",
2425 			d->devnode,
2426 			strerror(-rc));
2427 		goto error;
2428 	}
2429 
2430 	if (grab) {
2431 		rc = libevdev_grab(d->evdev, LIBEVDEV_GRAB);
2432 		if (rc != 0) {
2433 			fprintf(stderr,
2434 				"Grab failed on %s: %s\n",
2435 				path,
2436 				strerror(-rc));
2437 			goto error;
2438 		}
2439 	}
2440 
2441 	libevdev_set_clock_id(d->evdev, CLOCK_MONOTONIC);
2442 
2443 	if (libevdev_get_num_slots(d->evdev) > 0)
2444 		d->touch.is_touch_device = true;
2445 
2446 	list_append(&ctx->devices, &d->link);
2447 	if (!ctx->first_device)
2448 		ctx->first_device = d;
2449 	ctx->ndevices++;
2450 
2451 	return true;
2452 error:
2453 	close(fd);
2454 	free(d);
2455 	return false;
2456 
2457 }
2458 static int
open_restricted(const char *path, int flags, void *user_data)2459 open_restricted(const char *path, int flags, void *user_data)
2460 {
2461 	int fd = open(path, flags);
2462 	return fd == -1 ? -errno : fd;
2463 }
2464 
close_restricted(int fd, void *user_data)2465 static void close_restricted(int fd, void *user_data)
2466 {
2467 	close(fd);
2468 }
2469 
2470 static const struct libinput_interface interface = {
2471 	.open_restricted = open_restricted,
2472 	.close_restricted = close_restricted,
2473 };
2474 
2475 static bool
init_libinput(struct record_context *ctx)2476 init_libinput(struct record_context *ctx)
2477 {
2478 	struct record_device *dev;
2479 	struct libinput *li;
2480 
2481 	li = libinput_path_create_context(&interface, NULL);
2482 	if (li == NULL) {
2483 		fprintf(stderr,
2484 			"Failed to create libinput context\n");
2485 		return false;
2486 	}
2487 
2488 	ctx->libinput = li;
2489 
2490 	list_for_each(dev, &ctx->devices, link) {
2491 		struct libinput_device *d;
2492 
2493 		d = libinput_path_add_device(li, dev->devnode);
2494 		if (!d) {
2495 			fprintf(stderr,
2496 				"Failed to add device %s\n",
2497 				dev->devnode);
2498 			continue;
2499 		}
2500 		dev->device = libinput_device_ref(d);
2501 		/* FIXME: this needs to be a commandline option */
2502 		libinput_device_config_tap_set_enabled(d,
2503 					       LIBINPUT_CONFIG_TAP_ENABLED);
2504 	}
2505 
2506 	return true;
2507 }
2508 
2509 static bool
init_hidraw(struct record_context *ctx)2510 init_hidraw(struct record_context *ctx)
2511 {
2512 	struct record_device *dev;
2513 
2514 	list_for_each(dev, &ctx->devices, link) {
2515 		char syspath[PATH_MAX];
2516 		DIR *dir;
2517 		struct dirent *entry;
2518 
2519 		snprintf(syspath,
2520 			 sizeof(syspath),
2521 			 "/sys/class/input/%s/device/device/hidraw",
2522 			 safe_basename(dev->devnode));
2523 		dir = opendir(syspath);
2524 		if (!dir)
2525 			continue;
2526 
2527 		while ((entry = readdir(dir))) {
2528 			char hidraw_node[PATH_MAX];
2529 			int fd;
2530 			struct hidraw *hidraw = NULL;
2531 
2532 			if (!strstartswith(entry->d_name, "hidraw"))
2533 				continue;
2534 
2535 			snprintf(hidraw_node,
2536 				 sizeof(hidraw_node),
2537 				 "/dev/%s",
2538 				 entry->d_name);
2539 			fd = open(hidraw_node, O_RDONLY|O_NONBLOCK);
2540 			if (fd == -1)
2541 				continue;
2542 
2543 			hidraw = zalloc(sizeof(*hidraw));
2544 			hidraw->fd = fd;
2545 			hidraw->name = safe_strdup(entry->d_name);
2546 			hidraw->device = dev;
2547 			list_insert(&dev->hidraw_devices, &hidraw->link);
2548 		}
2549 		closedir(dir);
2550 	}
2551 
2552 	return true;
2553 }
2554 
2555 static void
usage(void)2556 usage(void)
2557 {
2558 	printf("Usage: %s [--help] [--all] [--autorestart] [--output-file filename] [/dev/input/event0] [...]\n"
2559 	       "Common use-cases:\n"
2560 	       "\n"
2561 	       " sudo %s -o recording.yml\n"
2562 	       "    Then select the device to record and it Ctrl+C to stop.\n"
2563 	       "    The recorded data is in recording.yml and can be attached to a bug report.\n"
2564 	       "\n"
2565 	       " sudo %s -o recording.yml --autorestart 2\n"
2566 	       "    As above, but restarts after 2s of inactivity on the device.\n"
2567 	       "    Note, the output file is only the prefix.\n"
2568 	       "\n"
2569 	       " sudo %s -o recording.yml /dev/input/event3 /dev/input/event4\n"
2570 	       "    Records the two devices into the same recordings file.\n"
2571 	       "\n"
2572 	       "For more information, see the %s(1) man page\n",
2573 	       program_invocation_short_name,
2574 	       program_invocation_short_name,
2575 	       program_invocation_short_name,
2576 	       program_invocation_short_name,
2577 	       program_invocation_short_name);
2578 }
2579 
2580 enum ftype {
2581 	F_FILE = 8,
2582 	F_DEVICE,
2583 	F_NOEXIST,
2584 };
2585 
2586 static enum ftype
is_char_dev(const char *path)2587 is_char_dev(const char *path)
2588 {
2589 	struct stat st;
2590 
2591 	if (strneq(path, "/dev", 4))
2592 		return F_DEVICE;
2593 
2594 	if (stat(path, &st) != 0) {
2595 		if (errno == ENOENT)
2596 			return F_NOEXIST;
2597 		return F_FILE;
2598 	}
2599 
2600 	return S_ISCHR(st.st_mode) ? F_DEVICE : F_FILE;
2601 }
2602 
2603 enum fposition {
2604 	ERROR,
2605 	NO_FILE,
2606 	FIRST,
2607 	LAST,
2608 };
2609 
2610 static enum fposition
find_output_file(int argc, char *argv[], const char **output_file)2611 find_output_file(int argc, char *argv[], const char **output_file)
2612 {
2613 	char *first, *last;
2614 	enum ftype ftype_first, ftype_last;
2615 
2616 	first = argv[0];
2617 
2618 	ftype_first = is_char_dev(first);
2619 	if (argc == 1) {
2620 		/* arg is *not* a char device, so let's assume it's
2621 		 * the output file */
2622 		if (ftype_first != F_DEVICE) {
2623 			*output_file = first;
2624 			return FIRST;
2625 		}
2626 	}
2627 
2628 	/* multiple arguments, yay */
2629 	last = argv[argc - 1];
2630 	ftype_last = is_char_dev(last);
2631 	/*
2632 	   first is device, last is file -> last
2633 	   first is device, last is device -> noop
2634 	   first is device, last !exist -> last
2635 	   first is file, last is device -> first
2636 	   first is file, last is file -> error
2637 	   first is file, last !exist -> error
2638 	   first !exist, last is device -> first
2639 	   first !exist, last is file -> error
2640 	   first !exit, last !exist -> error
2641 	 */
2642 #define _m(f, l) (((f) << 8) | (l))
2643 	switch (_m(ftype_first, ftype_last)) {
2644 	case _m(F_FILE,    F_DEVICE):
2645 	case _m(F_FILE,    F_NOEXIST):
2646 	case _m(F_NOEXIST, F_DEVICE):
2647 		*output_file = first;
2648 		return FIRST;
2649 	case _m(F_DEVICE,  F_FILE):
2650 	case _m(F_DEVICE,  F_NOEXIST):
2651 		*output_file = last;
2652 		return LAST;
2653 	case _m(F_DEVICE,  F_DEVICE):
2654 		break;
2655 	case _m(F_FILE,    F_FILE):
2656 	case _m(F_NOEXIST, F_FILE):
2657 	case _m(F_NOEXIST, F_NOEXIST):
2658 		return ERROR;
2659 	}
2660 #undef _m
2661 	return NO_FILE;
2662 }
2663 
2664 enum options {
2665 	OPT_AUTORESTART,
2666 	OPT_HELP,
2667 	OPT_OUTFILE,
2668 	OPT_KEYCODES,
2669 	OPT_MULTIPLE,
2670 	OPT_ALL,
2671 	OPT_LIBINPUT,
2672 	OPT_HIDRAW,
2673 	OPT_GRAB,
2674 };
2675 
2676 int
main(int argc, char **argv)2677 main(int argc, char **argv)
2678 {
2679 	struct record_context ctx = {
2680 		.timeout = -1,
2681 		.show_keycodes = false,
2682 	};
2683 	struct option opts[] = {
2684 		{ "autorestart", required_argument, 0, OPT_AUTORESTART },
2685 		{ "output-file", required_argument, 0, OPT_OUTFILE },
2686 		{ "show-keycodes", no_argument, 0, OPT_KEYCODES },
2687 		{ "multiple", no_argument, 0, OPT_MULTIPLE },
2688 		{ "all", no_argument, 0, OPT_ALL },
2689 		{ "help", no_argument, 0, OPT_HELP },
2690 		{ "with-libinput", no_argument, 0, OPT_LIBINPUT },
2691 		{ "with-hidraw", no_argument, 0, OPT_HIDRAW },
2692 		{ "grab", no_argument, 0, OPT_GRAB },
2693 		{ 0, 0, 0, 0 },
2694 	};
2695 	struct record_device *d;
2696 	const char *output_arg = NULL;
2697 	bool all = false,
2698 	     with_libinput = false,
2699 	     with_hidraw = false,
2700 	     grab = false;
2701 	int ndevices;
2702 	int rc = EXIT_FAILURE;
2703 	char **paths = NULL;
2704 
2705 	list_init(&ctx.devices);
2706 	list_init(&ctx.sources);
2707 
2708 	while (1) {
2709 		int c;
2710 		int option_index = 0;
2711 
2712 		c = getopt_long(argc, argv, "ho:", opts, &option_index);
2713 		if (c == -1)
2714 			break;
2715 
2716 		switch (c) {
2717 		case 'h':
2718 		case OPT_HELP:
2719 			usage();
2720 			rc = EXIT_SUCCESS;
2721 			goto out;
2722 		case OPT_AUTORESTART:
2723 			if (!safe_atoi(optarg, &ctx.timeout) ||
2724 			    ctx.timeout <= 0) {
2725 				usage();
2726 				rc = EXIT_INVALID_USAGE;
2727 				goto out;
2728 			}
2729 			ctx.timeout = ctx.timeout * 1000;
2730 			break;
2731 		case 'o':
2732 		case OPT_OUTFILE:
2733 			output_arg = optarg;
2734 			break;
2735 		case OPT_KEYCODES:
2736 			ctx.show_keycodes = true;
2737 			break;
2738 		case OPT_MULTIPLE: /* deprecated */
2739 			break;
2740 		case OPT_ALL:
2741 			all = true;
2742 			break;
2743 		case OPT_LIBINPUT:
2744 			with_libinput = true;
2745 			break;
2746 		case OPT_HIDRAW:
2747 			with_hidraw = true;
2748 			fprintf(stderr, "# WARNING: do not type passwords while recording HID reports\n");
2749 			break;
2750 		case OPT_GRAB:
2751 			grab = true;
2752 			break;
2753 		default:
2754 			usage();
2755 			rc = EXIT_INVALID_USAGE;
2756 			goto out;
2757 		}
2758 	}
2759 
2760 	ndevices = argc - optind;
2761 
2762 	/* We allow for multiple arguments after the options, *one* of which
2763 	 * may be the output file. That one must be the first or the last to
2764 	 * prevent users from running
2765 	 *   libinput record /dev/input/event0 output.yml /dev/input/event1
2766 	 * because this will only backfire anyway.
2767 	 */
2768 	if (ndevices >= 1 && output_arg == NULL) {
2769 		enum fposition pos = find_output_file(argc - optind,
2770 						      &argv[optind],
2771 						      &output_arg);
2772 		if (pos == ERROR) {
2773 			fprintf(stderr,
2774 				"Ambiguous device vs output file list. "
2775 				"Please use --output-file.\n");
2776 			return EXIT_INVALID_USAGE;
2777 		}
2778 
2779 		if (pos == FIRST || pos == LAST)
2780 			ndevices--;
2781 		if (pos == FIRST)
2782 			optind++;
2783 	}
2784 
2785 	if (ctx.timeout > 0 && output_arg == NULL) {
2786 		fprintf(stderr,
2787 			"Option --autorestart requires --output-file\n");
2788 		rc = EXIT_INVALID_USAGE;
2789 		goto out;
2790 	}
2791 
2792 	ctx.output_file.name = safe_strdup(output_arg);
2793 
2794 	if (output_arg == NULL && (all || ndevices > 1)) {
2795 		fprintf(stderr,
2796 			"Recording multiple devices requires an output file\n");
2797 		rc = EXIT_INVALID_USAGE;
2798 		goto out;
2799 	}
2800 
2801 	/* Now collect all device paths and init our device struct */
2802 	if (all) {
2803 		paths = all_devices();
2804 	} else if (ndevices >= 1) {
2805 		paths = strv_from_argv(ndevices, &argv[optind]);
2806 	} else {
2807 		char *path = select_device();
2808 		if (path == NULL) {
2809 			goto out;
2810 		}
2811 
2812 		paths = strv_from_argv(1, &path);
2813 		free(path);
2814 	}
2815 
2816 	for (char **p = paths; *p; p++) {
2817 		if (!init_device(&ctx, *p, grab)) {
2818 			goto out;
2819 		}
2820 	}
2821 
2822 	if (with_libinput && !init_libinput(&ctx))
2823 		goto out;
2824 
2825 	if (with_hidraw && !init_hidraw(&ctx))
2826 		goto out;
2827 
2828 	rc = mainloop(&ctx);
2829 out:
2830 	strv_free(paths);
2831 	list_for_each_safe(d, &ctx.devices, link) {
2832 		struct hidraw *hidraw;
2833 
2834 		list_for_each_safe(hidraw, &d->hidraw_devices, link) {
2835 			close(hidraw->fd);
2836 			list_remove(&hidraw->link);
2837 			free(hidraw->name);
2838 			free(hidraw);
2839 		}
2840 
2841 		if (d->device)
2842 			libinput_device_unref(d->device);
2843 		free(d->devnode);
2844 		libevdev_free(d->evdev);
2845 	}
2846 
2847 	libinput_unref(ctx.libinput);
2848 
2849 	return rc;
2850 }
2851