tools: drop CLOCK_MONOTONIC call, no longer necessary
[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 <linux/input.h>
34 #include <sys/ioctl.h>
35 #include <sys/signalfd.h>
36
37 #include <libinput.h>
38
39 static enum {
40         MODE_UDEV,
41         MODE_DEVICE,
42 } mode = MODE_UDEV;
43 static const char *device;
44 static const char *seat = "seat0";
45 static struct udev *udev;
46 uint32_t start_time;
47 static const uint32_t screen_width = 100;
48 static const uint32_t screen_height = 100;
49
50 static void
51 usage(void)
52 {
53         printf("Usage: %s [--udev [<seat>]|--device /dev/input/event0]\n"
54                "--udev <seat>.... Use udev device discovery (default).\n"
55                "                  Specifying a seat ID is optional.\n"
56                "--device /path/to/device .... open the given device only\n",
57                 program_invocation_short_name);
58 }
59
60 static int
61 parse_args(int argc, char **argv)
62 {
63         while (1) {
64                 int c;
65                 int option_index = 0;
66                 static struct option opts[] = {
67                         { "device", 1, 0, 'd' },
68                         { "udev", 0, 0, 'u' },
69                         { "help", 0, 0, 'h' },
70                         { 0, 0, 0, 0}
71                 };
72
73                 c = getopt_long(argc, argv, "h", opts, &option_index);
74                 if (c == -1)
75                         break;
76
77                 switch(c) {
78                         case 'h': /* --help */
79                                 usage();
80                                 exit(0);
81                         case 'd': /* --device */
82                                 mode = MODE_DEVICE;
83                                 if (!optarg) {
84                                         usage();
85                                         return 1;
86                                 }
87                                 device = optarg;
88                                 break;
89                         case 'u': /* --udev */
90                                 mode = MODE_UDEV;
91                                 if (optarg)
92                                         seat = optarg;
93                                 break;
94                         default:
95                                 usage();
96                                 return 1;
97                 }
98
99         }
100
101         if (optind < argc) {
102                 usage();
103                 return 1;
104         }
105
106         return 0;
107 }
108
109 static int
110 open_restricted(const char *path, int flags, void *user_data)
111 {
112         int fd = open(path, flags);
113         return fd < 0 ? -errno : fd;
114 }
115
116 static void
117 close_restricted(int fd, void *user_data)
118 {
119         close(fd);
120 }
121
122 const static struct libinput_interface interface = {
123         .open_restricted = open_restricted,
124         .close_restricted = close_restricted,
125 };
126
127 static int
128 open_udev(struct libinput **li)
129 {
130         udev = udev_new();
131         if (!udev) {
132                 fprintf(stderr, "Failed to initialize udev\n");
133                 return 1;
134         }
135
136         *li = libinput_udev_create_for_seat(&interface, NULL, udev, seat);
137         if (!*li) {
138                 fprintf(stderr, "Failed to initialize context from udev\n");
139                 return 1;
140         }
141
142         return 0;
143 }
144
145 static int
146 open_device(struct libinput **li, const char *path)
147 {
148         struct libinput_device *device;
149
150         *li = libinput_path_create_context(&interface, NULL);
151         if (!*li) {
152                 fprintf(stderr, "Failed to initialize context from %s\n", path);
153                 return 1;
154         }
155
156         device = libinput_path_add_device(*li, path);
157         if (!device) {
158                 fprintf(stderr, "Failed to initialized device %s\n", path);
159                 libinput_destroy(*li);
160                 return 1;
161         }
162
163         return 0;
164 }
165
166 static void
167 print_event_header(struct libinput_event *ev)
168 {
169         struct libinput_device *dev = libinput_event_get_device(ev);
170         const char *type;
171
172         switch(libinput_event_get_type(ev)) {
173         case LIBINPUT_EVENT_NONE:
174                 abort();
175         case LIBINPUT_EVENT_DEVICE_ADDED:
176                 type = "DEVICE_ADDED";
177                 break;
178         case LIBINPUT_EVENT_DEVICE_REMOVED:
179                 type = "DEVICE_REMOVED";
180                 break;
181         case LIBINPUT_EVENT_KEYBOARD_KEY:
182                 type = "KEYBOARD_KEY";
183                 break;
184         case LIBINPUT_EVENT_POINTER_MOTION:
185                 type = "POINTER_MOTION";
186                 break;
187         case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
188                 type = "POINTER_MOTION_ABSOLUTE";
189                 break;
190         case LIBINPUT_EVENT_POINTER_BUTTON:
191                 type = "POINTER_BUTTON";
192                 break;
193         case LIBINPUT_EVENT_POINTER_AXIS:
194                 type = "POINTER_AXIS";
195                 break;
196         case LIBINPUT_EVENT_TOUCH_DOWN:
197                 type = "TOUCH_DOWN";
198                 break;
199         case LIBINPUT_EVENT_TOUCH_MOTION:
200                 type = "TOUCH_MOTION";
201                 break;
202         case LIBINPUT_EVENT_TOUCH_UP:
203                 type = "TOUCH_UP";
204                 break;
205         case LIBINPUT_EVENT_TOUCH_CANCEL:
206                 type = "TOUCH_CANCEL";
207                 break;
208         case LIBINPUT_EVENT_TOUCH_FRAME:
209                 type = "TOUCH_FRAME";
210                 break;
211         }
212
213         printf("%-7s    %s      ", libinput_device_get_sysname(dev), type);
214 }
215
216 static void
217 print_event_time(uint32_t time)
218 {
219         printf("%+6.2fs ", (time - start_time) / 1000.0);
220 }
221
222 static void
223 print_device_notify(struct libinput_event *ev)
224 {
225         struct libinput_device *dev = libinput_event_get_device(ev);
226         struct libinput_seat *seat = libinput_device_get_seat(dev);
227
228         printf("%s      %s\n",
229                libinput_seat_get_physical_name(seat),
230                libinput_seat_get_logical_name(seat));
231 }
232
233 static void
234 print_key_event(struct libinput_event *ev)
235 {
236         struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
237         enum libinput_keyboard_key_state state;
238
239         print_event_time(libinput_event_keyboard_get_time(k));
240         state = libinput_event_keyboard_get_key_state(k);
241         printf("%d %s\n",
242                libinput_event_keyboard_get_key(k),
243                state == LIBINPUT_KEYBOARD_KEY_STATE_PRESSED ? "pressed" : "released");
244 }
245
246 static void
247 print_motion_event(struct libinput_event *ev)
248 {
249         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
250         li_fixed_t x =  libinput_event_pointer_get_dx(p),
251                    y = libinput_event_pointer_get_dy(p);
252
253         print_event_time(libinput_event_pointer_get_time(p));
254
255         printf("%6.2f/%6.2f\n",
256                li_fixed_to_double(x),
257                li_fixed_to_double(y));
258 }
259
260 static void
261 print_absmotion_event(struct libinput_event *ev)
262 {
263         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
264         li_fixed_t x = libinput_event_pointer_get_absolute_x_transformed(
265                 p, screen_width);
266         li_fixed_t y = libinput_event_pointer_get_absolute_y_transformed(
267                 p, screen_height);
268
269         print_event_time(libinput_event_pointer_get_time(p));
270         printf("%6.2f/%6.2f\n",
271                li_fixed_to_double(x),
272                li_fixed_to_double(y));
273 }
274
275 static void
276 print_button_event(struct libinput_event *ev)
277 {
278         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
279         enum libinput_pointer_button_state state;
280
281         print_event_time(libinput_event_pointer_get_time(p));
282
283         state = libinput_event_pointer_get_button_state(p);
284         printf("%3d %s\n",
285                libinput_event_pointer_get_button(p),
286                state == LIBINPUT_POINTER_BUTTON_STATE_PRESSED ? "pressed" : "released");
287 }
288
289 static void
290 print_axis_event(struct libinput_event *ev)
291 {
292         struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
293         enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p);
294         const char *ax;
295         li_fixed_t val;
296
297         switch (axis) {
298         case LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL:
299                 ax = "vscroll";
300                 break;
301         case LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL:
302                 ax = "hscroll";
303                 break;
304         default:
305                 abort();
306         }
307
308         print_event_time(libinput_event_pointer_get_time(p));
309         val = libinput_event_pointer_get_axis_value(p);
310         printf("%s %.2f\n",
311                ax, li_fixed_to_double(val));
312 }
313
314 static void
315 print_touch_event_without_coords(struct libinput_event *ev)
316 {
317         struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
318
319         print_event_time(libinput_event_touch_get_time(t));
320         printf("\n");
321 }
322
323 static void
324 print_touch_event_with_coords(struct libinput_event *ev)
325 {
326         struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
327         li_fixed_t x = libinput_event_touch_get_x_transformed(t, screen_width),
328                    y = libinput_event_touch_get_y_transformed(t, screen_height);
329
330         print_event_time(libinput_event_touch_get_time(t));
331
332         printf("%d (%d) %5.2f/%5.2f\n",
333                libinput_event_touch_get_slot(t),
334                libinput_event_touch_get_seat_slot(t),
335                li_fixed_to_double(x),
336                li_fixed_to_double(y));
337 }
338
339 static int
340 handle_and_print_events(struct libinput *li)
341 {
342         int rc = -1;
343         struct libinput_event *ev;
344
345         libinput_dispatch(li);
346         while ((ev = libinput_get_event(li))) {
347                 print_event_header(ev);
348
349                 switch (libinput_event_get_type(ev)) {
350                 case LIBINPUT_EVENT_NONE:
351                         abort();
352                 case LIBINPUT_EVENT_DEVICE_ADDED:
353                 case LIBINPUT_EVENT_DEVICE_REMOVED:
354                         print_device_notify(ev);
355                         break;
356                 case LIBINPUT_EVENT_KEYBOARD_KEY:
357                         print_key_event(ev);
358                         break;
359                 case LIBINPUT_EVENT_POINTER_MOTION:
360                         print_motion_event(ev);
361                         break;
362                 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
363                         print_absmotion_event(ev);
364                         break;
365                 case LIBINPUT_EVENT_POINTER_BUTTON:
366                         print_button_event(ev);
367                         break;
368                 case LIBINPUT_EVENT_POINTER_AXIS:
369                         print_axis_event(ev);
370                         break;
371                 case LIBINPUT_EVENT_TOUCH_DOWN:
372                         print_touch_event_with_coords(ev);
373                         break;
374                 case LIBINPUT_EVENT_TOUCH_MOTION:
375                         print_touch_event_with_coords(ev);
376                         break;
377                 case LIBINPUT_EVENT_TOUCH_UP:
378                         print_touch_event_without_coords(ev);
379                         break;
380                 case LIBINPUT_EVENT_TOUCH_CANCEL:
381                         print_touch_event_without_coords(ev);
382                         break;
383                 case LIBINPUT_EVENT_TOUCH_FRAME:
384                         print_touch_event_without_coords(ev);
385                         break;
386                 }
387
388                 libinput_event_destroy(ev);
389                 libinput_dispatch(li);
390                 rc = 0;
391         }
392         return rc;
393 }
394
395 void
396 mainloop(struct libinput *li)
397 {
398         struct pollfd fds[2];
399         sigset_t mask;
400
401         fds[0].fd = libinput_get_fd(li);
402         fds[0].events = POLLIN;
403         fds[0].revents = 0;
404
405         sigemptyset(&mask);
406         sigaddset(&mask, SIGINT);
407
408         fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
409         fds[1].events = POLLIN;
410         fds[1].revents = 0;
411
412         if (fds[1].fd == -1 ||
413             sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
414                 fprintf(stderr, "Failed to set up signal handling (%s)\n",
415                                 strerror(errno));
416         }
417
418         /* Handle already-pending device added events */
419         if (handle_and_print_events(li))
420                 fprintf(stderr, "Expected device added events on startup but got none. "
421                                 "Maybe you don't have the right permissions?\n");
422
423         while (poll(fds, 2, -1) > -1) {
424                 if (fds[1].revents)
425                         break;
426
427                 handle_and_print_events(li);
428         }
429
430         close(fds[1].fd);
431 }
432
433 int
434 main(int argc, char **argv)
435 {
436         struct libinput *li;
437         struct timespec tp;
438
439         if (parse_args(argc, argv))
440                 return 1;
441
442         if (mode == MODE_UDEV) {
443                 if (open_udev(&li))
444                         return 1;
445         } else if (mode == MODE_DEVICE) {
446                 if (open_device(&li, device))
447                         return 1;
448         } else
449                 abort();
450
451         clock_gettime(CLOCK_MONOTONIC, &tp);
452         start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
453
454         mainloop(li);
455
456         if (udev)
457                 udev_unref(udev);
458
459         return 0;
460 }