• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2015 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 <fcntl.h>
27 #include <stdio.h>
28 #include <stdint.h>
29 #include <unistd.h>
30 #include <libudev.h>
31 #include <linux/input.h>
32 #include <libevdev/libevdev.h>
33 
34 #include "util-prop-parsers.h"
35 #include "util-macros.h"
36 
37 /**
38  * For a non-zero fuzz on the x/y axes, print that fuzz as property and
39  * reset the kernel's fuzz to 0.
40  * https://bugs.freedesktop.org/show_bug.cgi?id=105202
41  */
42 static void
handle_absfuzz(struct udev_device * device)43 handle_absfuzz(struct udev_device *device)
44 {
45 	const char *devnode;
46 	struct libevdev *evdev = NULL;
47 	int fd = -1;
48 	int rc;
49 	unsigned int *code;
50 	unsigned int axes[] = {ABS_X,
51 			       ABS_Y,
52 			       ABS_MT_POSITION_X,
53 			       ABS_MT_POSITION_Y};
54 
55 	devnode = udev_device_get_devnode(device);
56 	if (!devnode)
57 		goto out;
58 
59 	fd = open(devnode, O_RDONLY);
60 	if (fd < 0)
61 		goto out;
62 
63 	rc = libevdev_new_from_fd(fd, &evdev);
64 	if (rc != 0)
65 		goto out;
66 
67 	if (!libevdev_has_event_type(evdev, EV_ABS))
68 		goto out;
69 
70 	ARRAY_FOR_EACH(axes, code) {
71 		int fuzz;
72 
73 		fuzz = libevdev_get_abs_fuzz(evdev, *code);
74 		if (fuzz)
75 			printf("LIBINPUT_FUZZ_%02x=%d\n", *code, fuzz);
76 	}
77 
78 out:
79 	close(fd);
80 	libevdev_free(evdev);
81 }
82 
83 /**
84  * Where a device has EVDEV_ABS_... set with a fuzz, that fuzz hasn't been
85  * applied to the kernel yet. So we need to extract it ourselves **and**
86  * update the property so the kernel won't actually set it later.
87  */
88 static void
handle_evdev_abs(struct udev_device * device)89 handle_evdev_abs(struct udev_device *device)
90 {
91 	unsigned int *code;
92 	unsigned int axes[] = {ABS_X,
93 			       ABS_Y,
94 			       ABS_MT_POSITION_X,
95 			       ABS_MT_POSITION_Y};
96 
97 	ARRAY_FOR_EACH(axes, code) {
98 		const char *prop;
99 		char name[64];
100 		uint32_t mask;
101 		struct input_absinfo abs;
102 
103 		snprintf(name, sizeof(name), "EVDEV_ABS_%02X", *code);
104 		prop = udev_device_get_property_value(device, name);
105 		if (!prop)
106 			continue;
107 
108 		mask = parse_evdev_abs_prop(prop, &abs);
109 		if (mask & ABS_MASK_FUZZ)
110 			printf("LIBINPUT_FUZZ_%02x=%d\n", *code, abs.fuzz);
111 	}
112 }
113 
main(int argc,char ** argv)114 int main(int argc, char **argv)
115 {
116 	int rc = 1;
117 	struct udev *udev = NULL;
118 	struct udev_device *device = NULL;
119 	const char *syspath;
120 
121 	if (argc != 2)
122 		return 1;
123 
124 	syspath = argv[1];
125 
126 	udev = udev_new();
127 	if (!udev)
128 		goto out;
129 
130 	device = udev_device_new_from_syspath(udev, syspath);
131 	if (!device)
132 		goto out;
133 
134 	handle_absfuzz(device);
135 	handle_evdev_abs(device);
136 
137 	rc = 0;
138 
139 out:
140 	if (device)
141 		udev_device_unref(device);
142 	if (udev)
143 		udev_unref(udev);
144 
145 	return rc;
146 }
147