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 <errno.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <libudev.h>
32 
33 #include <libinput.h>
34 #include <libinput-version.h>
35 #include "util-strings.h"
36 
37 #include "shared.h"
38 
39 static const char *
tap_default(struct libinput_device *device)40 tap_default(struct libinput_device *device)
41 {
42 	if (!libinput_device_config_tap_get_finger_count(device))
43 		return "n/a";
44 
45 	if (libinput_device_config_tap_get_default_enabled(device))
46 		return "enabled";
47 
48 	return "disabled";
49 }
50 
51 static const char *
drag_default(struct libinput_device *device)52 drag_default(struct libinput_device *device)
53 {
54 	if (!libinput_device_config_tap_get_finger_count(device))
55 		return "n/a";
56 
57 	if (libinput_device_config_tap_get_default_drag_enabled(device))
58 		return "enabled";
59 
60 	return "disabled";
61 }
62 
63 static const char *
draglock_default(struct libinput_device *device)64 draglock_default(struct libinput_device *device)
65 {
66 	if (!libinput_device_config_tap_get_finger_count(device))
67 		return "n/a";
68 
69 	if (libinput_device_config_tap_get_default_drag_lock_enabled(device))
70 		return "enabled";
71 
72 	return "disabled";
73 }
74 
75 static const char*
left_handed_default(struct libinput_device *device)76 left_handed_default(struct libinput_device *device)
77 {
78 	if (!libinput_device_config_left_handed_is_available(device))
79 		return "n/a";
80 
81 	if (libinput_device_config_left_handed_get_default(device))
82 		return "enabled";
83 
84 	return "disabled";
85 }
86 
87 static const char *
nat_scroll_default(struct libinput_device *device)88 nat_scroll_default(struct libinput_device *device)
89 {
90 	if (!libinput_device_config_scroll_has_natural_scroll(device))
91 		return "n/a";
92 
93 	if (libinput_device_config_scroll_get_default_natural_scroll_enabled(device))
94 		return "enabled";
95 
96 	return "disabled";
97 }
98 
99 static const char *
middle_emulation_default(struct libinput_device *device)100 middle_emulation_default(struct libinput_device *device)
101 {
102 	if (!libinput_device_config_middle_emulation_is_available(device))
103 		return "n/a";
104 
105 	if (libinput_device_config_middle_emulation_get_default_enabled(device))
106 		return "enabled";
107 
108 	return "disabled";
109 }
110 
111 static char *
calibration_default(struct libinput_device *device)112 calibration_default(struct libinput_device *device)
113 {
114 	char *str;
115 	float calibration[6];
116 
117 	if (!libinput_device_config_calibration_has_matrix(device)) {
118 		xasprintf(&str, "n/a");
119 		return str;
120 	}
121 
122 	if (libinput_device_config_calibration_get_default_matrix(device,
123 						  calibration) == 0) {
124 		xasprintf(&str, "identity matrix");
125 		return str;
126 	}
127 
128 	xasprintf(&str,
129 		 "%.2f %.2f %.2f %.2f %.2f %.2f",
130 		 calibration[0],
131 		 calibration[1],
132 		 calibration[2],
133 		 calibration[3],
134 		 calibration[4],
135 		 calibration[5]);
136 	return str;
137 }
138 
139 static char *
scroll_defaults(struct libinput_device *device)140 scroll_defaults(struct libinput_device *device)
141 {
142 	uint32_t scroll_methods;
143 	char *str;
144 	enum libinput_config_scroll_method method;
145 
146 	scroll_methods = libinput_device_config_scroll_get_methods(device);
147 	if (scroll_methods == LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
148 		xasprintf(&str, "none");
149 		return str;
150 	}
151 
152 	method = libinput_device_config_scroll_get_default_method(device);
153 
154 	xasprintf(&str,
155 		 "%s%s%s%s%s%s",
156 		 (method == LIBINPUT_CONFIG_SCROLL_2FG) ? "*" : "",
157 		 (scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG) ? "two-finger " : "",
158 		 (method == LIBINPUT_CONFIG_SCROLL_EDGE) ? "*" : "",
159 		 (scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE) ? "edge " : "",
160 		 (method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) ? "*" : "",
161 		 (scroll_methods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) ? "button" : "");
162 	return str;
163 }
164 
165 static char*
click_defaults(struct libinput_device *device)166 click_defaults(struct libinput_device *device)
167 {
168 	uint32_t click_methods;
169 	char *str;
170 	enum libinput_config_click_method method;
171 
172 	click_methods = libinput_device_config_click_get_methods(device);
173 	if (click_methods == LIBINPUT_CONFIG_CLICK_METHOD_NONE) {
174 		xasprintf(&str, "none");
175 		return str;
176 	}
177 
178 	method = libinput_device_config_click_get_default_method(device);
179 	xasprintf(&str,
180 		 "%s%s%s%s",
181 		 (method == LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) ? "*" : "",
182 		 (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) ? "button-areas " : "",
183 		 (method == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) ? "*" : "",
184 		 (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) ? "clickfinger " : "");
185 	return str;
186 }
187 
188 static char*
accel_profiles(struct libinput_device *device)189 accel_profiles(struct libinput_device *device)
190 {
191 	uint32_t profiles;
192 	char *str;
193 	enum libinput_config_accel_profile profile;
194 
195 	if (!libinput_device_config_accel_is_available(device)) {
196 		xasprintf(&str, "n/a");
197 		return str;
198 	}
199 
200 	profiles = libinput_device_config_accel_get_profiles(device);
201 	if (profiles == LIBINPUT_CONFIG_ACCEL_PROFILE_NONE) {
202 		xasprintf(&str, "none");
203 		return str;
204 	}
205 
206 	profile = libinput_device_config_accel_get_default_profile(device);
207 	xasprintf(&str,
208 		  "%s%s %s%s %s%s",
209 		  (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? "*" : "",
210 		  (profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? "flat" : "",
211 		  (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) ? "*" : "",
212 		  (profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) ? "adaptive" : "",
213 		  (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM) ? "*" : "",
214 		  (profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM) ? "custom" : "");
215 
216 	return str;
217 }
218 
219 static const char *
dwt_default(struct libinput_device *device)220 dwt_default(struct libinput_device *device)
221 {
222 	if (!libinput_device_config_dwt_is_available(device))
223 		return "n/a";
224 
225 	if (libinput_device_config_dwt_get_default_enabled(device))
226 		return "enabled";
227 
228 	return "disabled";
229 }
230 
231 static const char *
dwtp_default(struct libinput_device *device)232 dwtp_default(struct libinput_device *device)
233 {
234 	if (!libinput_device_config_dwtp_is_available(device))
235 		return "n/a";
236 
237 	if (libinput_device_config_dwtp_get_default_enabled(device))
238 		return "enabled";
239 
240 	return "disabled";
241 }
242 
243 static char *
rotation_default(struct libinput_device *device)244 rotation_default(struct libinput_device *device)
245 {
246 	char *str;
247 	double angle;
248 
249 	if (!libinput_device_config_rotation_is_available(device)) {
250 		xasprintf(&str, "n/a");
251 		return str;
252 	}
253 
254 	angle = libinput_device_config_rotation_get_angle(device);
255 	xasprintf(&str, "%.1f", angle);
256 	return str;
257 }
258 
259 static void
print_pad_info(struct libinput_device *device)260 print_pad_info(struct libinput_device *device)
261 {
262 	int nbuttons, nrings, nstrips, ngroups, nmodes;
263 	struct libinput_tablet_pad_mode_group *group;
264 
265 	nbuttons = libinput_device_tablet_pad_get_num_buttons(device);
266 	nrings = libinput_device_tablet_pad_get_num_rings(device);
267 	nstrips = libinput_device_tablet_pad_get_num_strips(device);
268 	ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
269 
270 	group = libinput_device_tablet_pad_get_mode_group(device, 0);
271 	nmodes = libinput_tablet_pad_mode_group_get_num_modes(group);
272 
273 	printf("Pad:\n");
274 	printf("	Rings:   %d\n", nrings);
275 	printf("	Strips:  %d\n", nstrips);
276 	printf("	Buttons: %d\n", nbuttons);
277 	printf("	Mode groups: %d (%d modes)\n", ngroups, nmodes);
278 
279 }
280 
281 static void
print_device_notify(struct libinput_event *ev)282 print_device_notify(struct libinput_event *ev)
283 {
284 	struct libinput_device *dev = libinput_event_get_device(ev);
285 	struct libinput_seat *seat = libinput_device_get_seat(dev);
286 	struct libinput_device_group *group;
287 	struct udev_device *udev_device;
288 	double w, h;
289 	static int next_group_id = 0;
290 	intptr_t group_id;
291 	const char *devnode;
292 	char *str;
293 
294 	group = libinput_device_get_device_group(dev);
295 	group_id = (intptr_t)libinput_device_group_get_user_data(group);
296 	if (!group_id) {
297 		group_id = ++next_group_id;
298 		libinput_device_group_set_user_data(group, (void*)group_id);
299 	}
300 
301 	udev_device = libinput_device_get_udev_device(dev);
302 	devnode = udev_device_get_devnode(udev_device);
303 
304 	printf("Device:           %s\n"
305 	       "Kernel:           %s\n"
306 	       "Group:            %d\n"
307 	       "Seat:             %s, %s\n",
308 	       libinput_device_get_name(dev),
309 	       devnode,
310 	       (int)group_id,
311 	       libinput_seat_get_physical_name(seat),
312 	       libinput_seat_get_logical_name(seat));
313 
314 	udev_device_unref(udev_device);
315 
316 	if (libinput_device_get_size(dev, &w, &h) == 0)
317 		printf("Size:             %.fx%.fmm\n", w, h);
318 	printf("Capabilities:     ");
319 	if (libinput_device_has_capability(dev,
320 					   LIBINPUT_DEVICE_CAP_KEYBOARD))
321 		printf("keyboard ");
322 	if (libinput_device_has_capability(dev,
323 					   LIBINPUT_DEVICE_CAP_POINTER))
324 		printf("pointer ");
325 	if (libinput_device_has_capability(dev,
326 					   LIBINPUT_DEVICE_CAP_TOUCH))
327 		printf("touch ");
328 	if (libinput_device_has_capability(dev,
329 					   LIBINPUT_DEVICE_CAP_TABLET_TOOL))
330 		printf("tablet ");
331 	if (libinput_device_has_capability(dev,
332 					   LIBINPUT_DEVICE_CAP_TABLET_PAD))
333 		printf("tablet-pad");
334 	if (libinput_device_has_capability(dev,
335 					   LIBINPUT_DEVICE_CAP_GESTURE))
336 		printf("gesture");
337 	if (libinput_device_has_capability(dev,
338 					   LIBINPUT_DEVICE_CAP_SWITCH))
339 		printf("switch");
340 	printf("\n");
341 
342 	printf("Tap-to-click:     %s\n", tap_default(dev));
343 	printf("Tap-and-drag:     %s\n",  drag_default(dev));
344 	printf("Tap drag lock:    %s\n", draglock_default(dev));
345 	printf("Left-handed:      %s\n", left_handed_default(dev));
346 	printf("Nat.scrolling:    %s\n", nat_scroll_default(dev));
347 	printf("Middle emulation: %s\n", middle_emulation_default(dev));
348 	str = calibration_default(dev);
349 	printf("Calibration:      %s\n", str);
350 	free(str);
351 
352 	str = scroll_defaults(dev);
353 	printf("Scroll methods:   %s\n", str);
354 	free(str);
355 
356 	str = click_defaults(dev);
357 	printf("Click methods:    %s\n", str);
358 	free(str);
359 
360 	printf("Disable-w-typing: %s\n", dwt_default(dev));
361 	printf("Disable-w-trackpointing: %s\n", dwtp_default(dev));
362 
363 	str = accel_profiles(dev);
364 	printf("Accel profiles:   %s\n", str);
365 	free(str);
366 
367 	str = rotation_default(dev);
368 	printf("Rotation:         %s\n", str);
369 	free(str);
370 
371 	if (libinput_device_has_capability(dev,
372 					   LIBINPUT_DEVICE_CAP_TABLET_PAD))
373 		print_pad_info(dev);
374 
375 	printf("\n");
376 }
377 
378 static inline void
usage(void)379 usage(void)
380 {
381 	printf("Usage: libinput list-devices [--help|--version]\n");
382 	printf("\n"
383 	       "--help ...... show this help and exit\n"
384 	       "--version ... show version information and exit\n"
385 	       "\n");
386 }
387 
388 int
main(int argc, char **argv)389 main(int argc, char **argv)
390 {
391 	struct libinput *li;
392 	struct libinput_event *ev;
393 	bool grab = false;
394 	const char *seat[2] = {"seat0", NULL};
395 
396 	/* This is kept for backwards-compatibility with the old
397 	   libinput-list-devices */
398 	if (argc > 1) {
399 		if (streq(argv[1], "--help")) {
400 			usage();
401 			return 0;
402 		}
403 
404 		if (streq(argv[1], "--version")) {
405 			printf("%s\n", LIBINPUT_VERSION);
406 			return 0;
407 		}
408 
409 		usage();
410 		return EXIT_INVALID_USAGE;
411 	}
412 
413 	li = tools_open_backend(BACKEND_UDEV, seat, false, &grab);
414 	if (!li)
415 		return 1;
416 
417 	libinput_dispatch(li);
418 	while ((ev = libinput_get_event(li))) {
419 
420 		if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
421 			print_device_notify(ev);
422 
423 		libinput_event_destroy(ev);
424 		libinput_dispatch(li);
425 	}
426 
427 	libinput_unref(li);
428 
429 	return EXIT_SUCCESS;
430 }
431