tools/event-gui: Silence a couple of compiler warnings
[platform/upstream/libinput.git] / tools / event-debug.c
1 /*
2  * Copyright © 2014 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #define _GNU_SOURCE
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <getopt.h>
27 #include <poll.h>
28 #include <stdio.h>
29 #include <signal.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <libudev.h>
34 #include "linux/input.h"
35 #include <sys/ioctl.h>
36 #include <sys/signalfd.h>
37
38 #include <libinput.h>
39
40 static enum {
41         MODE_UDEV,
42         MODE_DEVICE,
43 } mode = MODE_UDEV;
44 static const char *device;
45 static const char *seat = "seat0";
46 static struct udev *udev;
47 uint32_t start_time;
48 static const uint32_t screen_width = 100;
49 static const uint32_t screen_height = 100;
50 static int verbose = 0;
51
52 static void
53 usage(void)
54 {
55         printf("Usage: %s [--verbose] [--udev [<seat>]|--device /dev/input/event0]\n"
56                "--verbose ....... Print debugging output.\n"
57                "--udev <seat>.... Use udev device discovery (default).\n"
58                "                  Specifying a seat ID is optional.\n"
59                "--device /path/to/device .... open the given device only\n",
60                 program_invocation_short_name);
61 }
62
63 static int
64 parse_args(int argc, char **argv)
65 {
66         while (1) {
67                 int c;
68                 int option_index = 0;
69                 static struct option opts[] = {
70                         { "device", 1, 0, 'd' },
71                         { "udev", 0, 0, 'u' },
72                         { "help", 0, 0, 'h' },
73                         { "verbose", 0, 0, 'v'},
74                         { 0, 0, 0, 0}
75                 };
76
77                 c = getopt_long(argc, argv, "h", opts, &option_index);
78                 if (c == -1)
79                         break;
80
81                 switch(c) {
82                         case 'h': /* --help */
83                                 usage();
84                                 exit(0);
85                         case 'd': /* --device */
86                                 mode = MODE_DEVICE;
87                                 if (!optarg) {
88                                         usage();
89                                         return 1;
90                                 }
91                                 device = optarg;
92                                 break;
93                         case 'u': /* --udev */
94                                 mode = MODE_UDEV;
95                                 if (optarg)
96                                         seat = optarg;
97                                 break;
98                         case 'v': /* --verbose */
99                                 verbose = 1;
100                                 break;
101                         default:
102                                 usage();
103                                 return 1;
104                 }
105
106         }
107
108         if (optind < argc) {
109                 usage();
110                 return 1;
111         }
112
113         return 0;
114 }
115
116 static int
117 open_restricted(const char *path, int flags, void *user_data)
118 {
119         int fd = open(path, flags);
120         return fd < 0 ? -errno : fd;
121 }
122
123 static void
124 close_restricted(int fd, void *user_data)
125 {
126         close(fd);
127 }
128
129 static const struct libinput_interface interface = {
130         .open_restricted = open_restricted,
131         .close_restricted = close_restricted,
132 };
133
134 static void
135 log_handler(struct libinput *li,
136             enum libinput_log_priority priority,
137             const char *format,
138             va_list args)
139 {
140         vprintf(format, args);
141 }
142
143 static int
144 open_udev(struct libinput **li)
145 {
146         udev = udev_new();
147         if (!udev) {
148                 fprintf(stderr, "Failed to initialize udev\n");
149                 return 1;
150         }
151
152         *li = libinput_udev_create_context(&interface, NULL, udev);
153         if (!*li) {
154                 fprintf(stderr, "Failed to initialize context from udev\n");
155                 return 1;
156         }
157
158         if (verbose) {
159                 libinput_log_set_handler(*li, log_handler);
160                 libinput_log_set_priority(*li, LIBINPUT_LOG_PRIORITY_DEBUG);
161         }
162
163         if (libinput_udev_assign_seat(*li, seat)) {
164                 fprintf(stderr, "Failed to set seat\n");
165                 libinput_unref(*li);
166                 return 1;
167         }
168
169         return 0;
170 }
171
172 static int
173 open_device(struct libinput **li, const char *path)
174 {
175         struct libinput_device *device;
176
177         *li = libinput_path_create_context(&interface, NULL);
178         if (!*li) {
179                 fprintf(stderr, "Failed to initialize context from %s\n", path);
180                 return 1;
181         }
182
183         if (verbose) {
184                 libinput_log_set_handler(*li, log_handler);
185                 libinput_log_set_priority(*li, LIBINPUT_LOG_PRIORITY_DEBUG);
186         }
187
188         device = libinput_path_add_device(*li, path);
189         if (!device) {
190                 fprintf(stderr, "Failed to initialized device %s\n", path);
191                 libinput_unref(*li);
192                 return 1;
193         }
194
195         return 0;
196 }
197
198 static void
199 print_event_header(struct libinput_event *ev)
200 {
201         struct libinput_device *dev = libinput_event_get_device(ev);
202         const char *type = NULL;
203
204         switch(libinput_event_get_type(ev)) {
205         case LIBINPUT_EVENT_NONE:
206                 abort();
207         case LIBINPUT_EVENT_DEVICE_ADDED:
208                 type = "DEVICE_ADDED";
209                 break;
210         case LIBINPUT_EVENT_DEVICE_REMOVED:
211                 type = "DEVICE_REMOVED";
212                 break;
213         case LIBINPUT_EVENT_KEYBOARD_KEY:
214                 type = "KEYBOARD_KEY";
215                 break;
216         case LIBINPUT_EVENT_POINTER_MOTION:
217                 type = "POINTER_MOTION";
218                 break;
219         case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
220                 type = "POINTER_MOTION_ABSOLUTE";
221                 break;
222         case LIBINPUT_EVENT_POINTER_BUTTON:
223                 type = "POINTER_BUTTON";
224                 break;
225         case LIBINPUT_EVENT_POINTER_AXIS:
226                 type = "POINTER_AXIS";
227                 break;
228         case LIBINPUT_EVENT_TOUCH_DOWN:
229                 type = "TOUCH_DOWN";
230                 break;
231         case LIBINPUT_EVENT_TOUCH_MOTION:
232                 type = "TOUCH_MOTION";
233                 break;
234         case LIBINPUT_EVENT_TOUCH_UP:
235                 type = "TOUCH_UP";
236                 break;
237         case LIBINPUT_EVENT_TOUCH_CANCEL:
238                 type = "TOUCH_CANCEL";
239                 break;
240         case LIBINPUT_EVENT_TOUCH_FRAME:
241                 type = "TOUCH_FRAME";
242                 break;
243         }
244
245         printf("%-7s    %s      ", libinput_device_get_sysname(dev), type);
246 }
247
248 static void
249 print_event_time(uint32_t time)
250 {
251         printf("%+6.2fs ", (time - start_time) / 1000.0);
252 }
253
254 static void
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         double w, h;
260
261         printf("%s      %s",
262                libinput_seat_get_physical_name(seat),
263                libinput_seat_get_logical_name(seat));
264
265         if (libinput_device_get_size(dev, &w, &h) == 0)
266                 printf("\tsize %.2f/%.2fmm", w, h);
267
268         printf("\n");
269 }
270
271 static void
272 print_key_event(struct libinput_event *ev)
273 {
274         struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
275         enum libinput_key_state state;
276
277         print_event_time(libinput_event_keyboard_get_time(k));
278         state = libinput_event_keyboard_get_key_state(k);
279         printf("%d %s\n",
280                libinput_event_keyboard_get_key(k),
281                state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
282 }
283
284 static void
285 print_motion_event(struct libinput_event *ev)
286 {
287         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
288         double x = libinput_event_pointer_get_dx(p);
289         double y = libinput_event_pointer_get_dy(p);
290
291         print_event_time(libinput_event_pointer_get_time(p));
292
293         printf("%6.2f/%6.2f\n", x, y);
294 }
295
296 static void
297 print_absmotion_event(struct libinput_event *ev)
298 {
299         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
300         double x = libinput_event_pointer_get_absolute_x_transformed(
301                 p, screen_width);
302         double y = libinput_event_pointer_get_absolute_y_transformed(
303                 p, screen_height);
304
305         print_event_time(libinput_event_pointer_get_time(p));
306         printf("%6.2f/%6.2f\n", x, y);
307 }
308
309 static void
310 print_button_event(struct libinput_event *ev)
311 {
312         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
313         enum libinput_button_state state;
314
315         print_event_time(libinput_event_pointer_get_time(p));
316
317         state = libinput_event_pointer_get_button_state(p);
318         printf("%3d %s, seat count: %u\n",
319                libinput_event_pointer_get_button(p),
320                state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
321                libinput_event_pointer_get_seat_button_count(p));
322 }
323
324 static void
325 print_axis_event(struct libinput_event *ev)
326 {
327         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
328         enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p);
329         const char *ax;
330         double val;
331
332         switch (axis) {
333         case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
334                 ax = "vscroll";
335                 break;
336         case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
337                 ax = "hscroll";
338                 break;
339         default:
340                 abort();
341         }
342
343         print_event_time(libinput_event_pointer_get_time(p));
344         val = libinput_event_pointer_get_axis_value(p);
345         printf("%s %.2f\n", ax, val);
346 }
347
348 static void
349 print_touch_event_without_coords(struct libinput_event *ev)
350 {
351         struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
352
353         print_event_time(libinput_event_touch_get_time(t));
354         printf("\n");
355 }
356
357 static void
358 print_touch_event_with_coords(struct libinput_event *ev)
359 {
360         struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
361         double x = libinput_event_touch_get_x_transformed(t, screen_width);
362         double y = libinput_event_touch_get_y_transformed(t, screen_height);
363         double xmm = libinput_event_touch_get_x(t);
364         double ymm = libinput_event_touch_get_y(t);
365
366         print_event_time(libinput_event_touch_get_time(t));
367
368         printf("%d (%d) %5.2f/%5.2f (%5.2f/%5.2fmm)\n",
369                libinput_event_touch_get_slot(t),
370                libinput_event_touch_get_seat_slot(t),
371                x, y,
372                xmm, ymm);
373 }
374
375 static int
376 handle_and_print_events(struct libinput *li)
377 {
378         int rc = -1;
379         struct libinput_event *ev;
380
381         libinput_dispatch(li);
382         while ((ev = libinput_get_event(li))) {
383                 print_event_header(ev);
384
385                 switch (libinput_event_get_type(ev)) {
386                 case LIBINPUT_EVENT_NONE:
387                         abort();
388                 case LIBINPUT_EVENT_DEVICE_ADDED:
389                 case LIBINPUT_EVENT_DEVICE_REMOVED:
390                         print_device_notify(ev);
391                         break;
392                 case LIBINPUT_EVENT_KEYBOARD_KEY:
393                         print_key_event(ev);
394                         break;
395                 case LIBINPUT_EVENT_POINTER_MOTION:
396                         print_motion_event(ev);
397                         break;
398                 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
399                         print_absmotion_event(ev);
400                         break;
401                 case LIBINPUT_EVENT_POINTER_BUTTON:
402                         print_button_event(ev);
403                         break;
404                 case LIBINPUT_EVENT_POINTER_AXIS:
405                         print_axis_event(ev);
406                         break;
407                 case LIBINPUT_EVENT_TOUCH_DOWN:
408                         print_touch_event_with_coords(ev);
409                         break;
410                 case LIBINPUT_EVENT_TOUCH_MOTION:
411                         print_touch_event_with_coords(ev);
412                         break;
413                 case LIBINPUT_EVENT_TOUCH_UP:
414                         print_touch_event_without_coords(ev);
415                         break;
416                 case LIBINPUT_EVENT_TOUCH_CANCEL:
417                         print_touch_event_without_coords(ev);
418                         break;
419                 case LIBINPUT_EVENT_TOUCH_FRAME:
420                         print_touch_event_without_coords(ev);
421                         break;
422                 }
423
424                 libinput_event_destroy(ev);
425                 libinput_dispatch(li);
426                 rc = 0;
427         }
428         return rc;
429 }
430
431 static void
432 mainloop(struct libinput *li)
433 {
434         struct pollfd fds[2];
435         sigset_t mask;
436
437         fds[0].fd = libinput_get_fd(li);
438         fds[0].events = POLLIN;
439         fds[0].revents = 0;
440
441         sigemptyset(&mask);
442         sigaddset(&mask, SIGINT);
443
444         fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
445         fds[1].events = POLLIN;
446         fds[1].revents = 0;
447
448         if (fds[1].fd == -1 ||
449             sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
450                 fprintf(stderr, "Failed to set up signal handling (%s)\n",
451                                 strerror(errno));
452         }
453
454         /* Handle already-pending device added events */
455         if (handle_and_print_events(li))
456                 fprintf(stderr, "Expected device added events on startup but got none. "
457                                 "Maybe you don't have the right permissions?\n");
458
459         while (poll(fds, 2, -1) > -1) {
460                 if (fds[1].revents)
461                         break;
462
463                 handle_and_print_events(li);
464         }
465
466         close(fds[1].fd);
467 }
468
469 int
470 main(int argc, char **argv)
471 {
472         struct libinput *li;
473         struct timespec tp;
474
475         if (parse_args(argc, argv))
476                 return 1;
477
478         if (mode == MODE_UDEV) {
479                 if (open_udev(&li))
480                         return 1;
481         } else if (mode == MODE_DEVICE) {
482                 if (open_device(&li, device))
483                         return 1;
484         } else
485                 abort();
486
487         clock_gettime(CLOCK_MONOTONIC, &tp);
488         start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
489
490         mainloop(li);
491
492         libinput_unref(li);
493         if (udev)
494                 udev_unref(udev);
495
496         return 0;
497 }