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