1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2013 Red Hat, Inc.
4 */
5
6#include "config.h"
7
8#include <assert.h>
9#include <errno.h>
10#include <fcntl.h>
11#include <linux/input.h>
12#include <stdio.h>
13#include <string.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16
17#include "libevdev/libevdev.h"
18
19static void
20print_abs_bits(struct libevdev *dev, int axis)
21{
22	const struct input_absinfo *abs;
23
24	if (!libevdev_has_event_code(dev, EV_ABS, axis))
25		return;
26
27	abs = libevdev_get_abs_info(dev, axis);
28
29	printf("	Value	%6d\n", abs->value);
30	printf("	Min	%6d\n", abs->minimum);
31	printf("	Max	%6d\n", abs->maximum);
32	if (abs->fuzz)
33		printf("	Fuzz	%6d\n", abs->fuzz);
34	if (abs->flat)
35		printf("	Flat	%6d\n", abs->flat);
36	if (abs->resolution)
37		printf("	Resolution	%6d\n", abs->resolution);
38}
39
40static void
41print_code_bits(struct libevdev *dev, unsigned int type, unsigned int max)
42{
43	unsigned int i;
44	for (i = 0; i <= max; i++) {
45		if (!libevdev_has_event_code(dev, type, i))
46			continue;
47
48		printf("    Event code %i (%s)\n", i, libevdev_event_code_get_name(type, i));
49		if (type == EV_ABS)
50			print_abs_bits(dev, i);
51	}
52}
53
54static void
55print_bits(struct libevdev *dev)
56{
57	unsigned int i;
58	printf("Supported events:\n");
59
60	for (i = 0; i <= EV_MAX; i++) {
61		if (libevdev_has_event_type(dev, i))
62			printf("  Event type %d (%s)\n", i, libevdev_event_type_get_name(i));
63		switch(i) {
64			case EV_KEY:
65				print_code_bits(dev, EV_KEY, KEY_MAX);
66				break;
67			case EV_REL:
68				print_code_bits(dev, EV_REL, REL_MAX);
69				break;
70			case EV_ABS:
71				print_code_bits(dev, EV_ABS, ABS_MAX);
72				break;
73			case EV_LED:
74				print_code_bits(dev, EV_LED, LED_MAX);
75				break;
76		}
77	}
78}
79
80static void
81print_props(struct libevdev *dev)
82{
83	unsigned int i;
84	printf("Properties:\n");
85
86	for (i = 0; i <= INPUT_PROP_MAX; i++) {
87		if (libevdev_has_property(dev, i))
88			printf("  Property type %d (%s)\n", i,
89					libevdev_property_get_name(i));
90	}
91}
92
93static int
94print_event(struct input_event *ev)
95{
96	if (ev->type == EV_SYN)
97		printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
98				ev->input_event_sec,
99				ev->input_event_usec,
100				libevdev_event_type_get_name(ev->type));
101	else
102		printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
103			ev->input_event_sec,
104			ev->input_event_usec,
105			ev->type,
106			libevdev_event_type_get_name(ev->type),
107			ev->code,
108			libevdev_event_code_get_name(ev->type, ev->code),
109			ev->value);
110	return 0;
111}
112
113static int
114print_sync_event(struct input_event *ev)
115{
116	printf("SYNC: ");
117	print_event(ev);
118	return 0;
119}
120
121int
122main(int argc, char **argv)
123{
124	struct libevdev *dev = NULL;
125	const char *file;
126	int fd;
127	int rc = 1;
128
129	if (argc < 2)
130		goto out;
131
132	file = argv[1];
133	fd = open(file, O_RDONLY);
134	if (fd < 0) {
135		perror("Failed to open device");
136		goto out;
137	}
138
139	rc = libevdev_new_from_fd(fd, &dev);
140	if (rc < 0) {
141		fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
142		goto out;
143	}
144
145	printf("Input device ID: bus %#x vendor %#x product %#x\n",
146			libevdev_get_id_bustype(dev),
147			libevdev_get_id_vendor(dev),
148			libevdev_get_id_product(dev));
149	printf("Evdev version: %x\n", libevdev_get_driver_version(dev));
150	printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
151	printf("Phys location: %s\n", libevdev_get_phys(dev));
152	printf("Uniq identifier: %s\n", libevdev_get_uniq(dev));
153	print_bits(dev);
154	print_props(dev);
155
156	do {
157		struct input_event ev;
158		rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL|LIBEVDEV_READ_FLAG_BLOCKING, &ev);
159		if (rc == LIBEVDEV_READ_STATUS_SYNC) {
160			printf("::::::::::::::::::::: dropped ::::::::::::::::::::::\n");
161			while (rc == LIBEVDEV_READ_STATUS_SYNC) {
162				print_sync_event(&ev);
163				rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
164			}
165			printf("::::::::::::::::::::: re-synced ::::::::::::::::::::::\n");
166		} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
167			print_event(&ev);
168	} while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == -EAGAIN);
169
170	if (rc != LIBEVDEV_READ_STATUS_SUCCESS && rc != -EAGAIN)
171		fprintf(stderr, "Failed to handle events: %s\n", strerror(-rc));
172
173	rc = 0;
174out:
175	libevdev_free(dev);
176
177	return rc;
178}
179