• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2013-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 <string.h>
27 #include <sys/stat.h>
28 #include <libudev.h>
29 
30 #include "evdev.h"
31 
32 struct path_input {
33 	struct libinput base;
34 	struct udev *udev;
35 	struct list path_list;
36 };
37 
38 struct path_device {
39 	struct list link;
40 	struct udev_device *udev_device;
41 };
42 
43 struct path_seat {
44 	struct libinput_seat base;
45 };
46 
47 
48 static const char default_seat[] = "seat0";
49 static const char default_seat_name[] = "default";
50 
51 static void
path_disable_device(struct libinput * libinput,struct evdev_device * device)52 path_disable_device(struct libinput *libinput,
53 		    struct evdev_device *device)
54 {
55 	struct libinput_seat *seat = device->base.seat;
56 	struct evdev_device *dev, *next;
57 
58 	list_for_each_safe(dev, next,
59 			   &seat->devices_list, base.link) {
60 		if (dev != device)
61 			continue;
62 
63 		evdev_device_remove(device);
64 		break;
65 	}
66 }
67 
68 static void
path_input_disable(struct libinput * libinput)69 path_input_disable(struct libinput *libinput)
70 {
71 	struct path_input *input = (struct path_input*)libinput;
72 	struct path_seat *seat, *tmp;
73 	struct evdev_device *device, *next;
74 
75 	list_for_each_safe(seat, tmp, &input->base.seat_list, base.link) {
76 		libinput_seat_ref(&seat->base);
77 		list_for_each_safe(device, next,
78 				   &seat->base.devices_list, base.link)
79 			path_disable_device(libinput, device);
80 		libinput_seat_unref(&seat->base);
81 	}
82 }
83 
84 static void
path_seat_destroy(struct libinput_seat * seat)85 path_seat_destroy(struct libinput_seat *seat)
86 {
87 	struct path_seat *pseat = (struct path_seat*)seat;
88 	free(pseat);
89 }
90 
91 static struct path_seat*
path_seat_create(struct path_input * input,const char * seat_name,const char * seat_logical_name)92 path_seat_create(struct path_input *input,
93 		 const char *seat_name,
94 		 const char *seat_logical_name)
95 {
96 	struct path_seat *seat;
97 
98 	seat = zalloc(sizeof(*seat));
99 
100 	libinput_seat_init(&seat->base, &input->base, seat_name,
101 			   seat_logical_name, path_seat_destroy);
102 
103 	return seat;
104 }
105 
106 static struct path_seat*
path_seat_get_named(struct path_input * input,const char * seat_name_physical,const char * seat_name_logical)107 path_seat_get_named(struct path_input *input,
108 		    const char *seat_name_physical,
109 		    const char *seat_name_logical)
110 {
111 	struct path_seat *seat;
112 
113 	list_for_each(seat, &input->base.seat_list, base.link) {
114 		if (streq(seat->base.physical_name, seat_name_physical) &&
115 		    streq(seat->base.logical_name, seat_name_logical))
116 			return seat;
117 	}
118 
119 	return NULL;
120 }
121 
122 static struct path_seat *
path_seat_get_for_device(struct path_input * input,struct udev_device * udev_device,const char * seat_logical_name_override)123 path_seat_get_for_device(struct path_input *input,
124 			 struct udev_device *udev_device,
125 			 const char *seat_logical_name_override)
126 {
127 	struct path_seat *seat = NULL;
128 	char *seat_name = NULL, *seat_logical_name = NULL;
129 	const char *seat_prop;
130 
131 	const char *devnode, *sysname;
132 
133 	devnode = udev_device_get_devnode(udev_device);
134 	sysname = udev_device_get_sysname(udev_device);
135 
136 	seat_prop = udev_device_get_property_value(udev_device, "ID_SEAT");
137 	seat_name = safe_strdup(seat_prop ? seat_prop : default_seat);
138 
139 	if (seat_logical_name_override) {
140 		seat_logical_name = safe_strdup(seat_logical_name_override);
141 	} else {
142 		seat_prop = udev_device_get_property_value(udev_device, "WL_SEAT");
143 		seat_logical_name = strdup(seat_prop ? seat_prop : default_seat_name);
144 	}
145 
146 	if (!seat_logical_name) {
147 		log_error(&input->base,
148 			  "%s: failed to create seat name for device '%s'.\n",
149 			  sysname,
150 			  devnode);
151 		goto out;
152 	}
153 
154 	seat = path_seat_get_named(input, seat_name, seat_logical_name);
155 
156 	if (!seat)
157 		seat = path_seat_create(input, seat_name, seat_logical_name);
158 	if (!seat) {
159 		log_info(&input->base,
160 			 "%s: failed to create seat for device '%s'.\n",
161 			 sysname,
162 			 devnode);
163 		goto out;
164 	}
165 
166 	libinput_seat_ref(&seat->base);
167 out:
168 	free(seat_name);
169 	free(seat_logical_name);
170 
171 	return seat;
172 }
173 
174 static struct libinput_device *
path_device_enable(struct path_input * input,struct udev_device * udev_device,const char * seat_logical_name_override)175 path_device_enable(struct path_input *input,
176 		   struct udev_device *udev_device,
177 		   const char *seat_logical_name_override)
178 {
179 	struct path_seat *seat;
180 	struct evdev_device *device = NULL;
181 	const char *output_name;
182 	const char *devnode, *sysname;
183 
184 	devnode = udev_device_get_devnode(udev_device);
185 	sysname = udev_device_get_sysname(udev_device);
186 
187 	seat = path_seat_get_for_device(input, udev_device, seat_logical_name_override);
188 	if (!seat)
189 		goto out;
190 
191 	device = evdev_device_create(&seat->base, udev_device);
192 	libinput_seat_unref(&seat->base);
193 
194 	if (device == EVDEV_UNHANDLED_DEVICE) {
195 		device = NULL;
196 		log_info(&input->base,
197 			 "%-7s - not using input device '%s'.\n",
198 			 sysname,
199 			 devnode);
200 		goto out;
201 	} else if (device == NULL) {
202 		log_info(&input->base,
203 			 "%-7s - failed to create input device '%s'.\n",
204 			 sysname,
205 			 devnode);
206 		goto out;
207 	}
208 
209 	evdev_read_calibration_prop(device);
210 	output_name = udev_device_get_property_value(udev_device, "WL_OUTPUT");
211 	device->output_name = safe_strdup(output_name);
212 
213 out:
214 	return device ? &device->base : NULL;
215 }
216 
217 static int
path_input_enable(struct libinput * libinput)218 path_input_enable(struct libinput *libinput)
219 {
220 	struct path_input *input = (struct path_input*)libinput;
221 	struct path_device *dev;
222 
223 	list_for_each(dev, &input->path_list, link) {
224 		if (path_device_enable(input, dev->udev_device, NULL) == NULL) {
225 			path_input_disable(libinput);
226 			return -1;
227 		}
228 	}
229 
230 	return 0;
231 }
232 
233 static void
path_device_destroy(struct path_device * dev)234 path_device_destroy(struct path_device *dev)
235 {
236 	list_remove(&dev->link);
237 	udev_device_unref(dev->udev_device);
238 	free(dev);
239 }
240 
241 static void
path_input_destroy(struct libinput * input)242 path_input_destroy(struct libinput *input)
243 {
244 	struct path_input *path_input = (struct path_input*)input;
245 	struct path_device *dev, *tmp;
246 
247 	udev_unref(path_input->udev);
248 
249 	list_for_each_safe(dev, tmp, &path_input->path_list, link)
250 		path_device_destroy(dev);
251 
252 }
253 
254 static struct libinput_device *
path_create_device(struct libinput * libinput,struct udev_device * udev_device,const char * seat_name)255 path_create_device(struct libinput *libinput,
256 		   struct udev_device *udev_device,
257 		   const char *seat_name)
258 {
259 	struct path_input *input = (struct path_input*)libinput;
260 	struct path_device *dev;
261 	struct libinput_device *device;
262 
263 	dev = zalloc(sizeof *dev);
264 	dev->udev_device = udev_device_ref(udev_device);
265 
266 	list_insert(&input->path_list, &dev->link);
267 
268 	device = path_device_enable(input, udev_device, seat_name);
269 
270 	if (!device)
271 		path_device_destroy(dev);
272 
273 	return device;
274 }
275 
276 static int
path_device_change_seat(struct libinput_device * device,const char * seat_name)277 path_device_change_seat(struct libinput_device *device,
278 			const char *seat_name)
279 {
280 	struct libinput *libinput = device->seat->libinput;
281 	struct evdev_device *evdev = evdev_device(device);
282 	struct udev_device *udev_device = NULL;
283 	int rc = -1;
284 
285 	udev_device = evdev->udev_device;
286 	udev_device_ref(udev_device);
287 	libinput_path_remove_device(device);
288 
289 	if (path_create_device(libinput, udev_device, seat_name) != NULL)
290 		rc = 0;
291 	udev_device_unref(udev_device);
292 	return rc;
293 }
294 
295 static const struct libinput_interface_backend interface_backend = {
296 	.resume = path_input_enable,
297 	.suspend = path_input_disable,
298 	.destroy = path_input_destroy,
299 	.device_change_seat = path_device_change_seat,
300 };
301 
302 LIBINPUT_EXPORT struct libinput *
libinput_path_create_context(const struct libinput_interface * interface,void * user_data)303 libinput_path_create_context(const struct libinput_interface *interface,
304 			     void *user_data)
305 {
306 	struct path_input *input;
307 	struct udev *udev;
308 
309 	if (!interface)
310 		return NULL;
311 
312 	udev = udev_new();
313 	if (!udev)
314 		return NULL;
315 
316 	input = zalloc(sizeof *input);
317 	if (libinput_init(&input->base, interface,
318 			  &interface_backend, user_data) != 0) {
319 		udev_unref(udev);
320 		free(input);
321 		return NULL;
322 	}
323 
324 	input->udev = udev;
325 	list_init(&input->path_list);
326 
327 	return &input->base;
328 }
329 
330 static inline struct udev_device *
udev_device_from_devnode(struct libinput * libinput,struct udev * udev,const char * devnode)331 udev_device_from_devnode(struct libinput *libinput,
332 			 struct udev *udev,
333 			 const char *devnode)
334 {
335 	struct udev_device *dev;
336 	struct stat st;
337 	size_t count = 0;
338 
339 	if (stat(devnode, &st) < 0)
340 		return NULL;
341 
342 	dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
343 
344 	while (dev && !udev_device_get_is_initialized(dev)) {
345 		udev_device_unref(dev);
346 		count++;
347 		if (count > 200) {
348 			log_bug_libinput(libinput,
349 					"udev device never initialized (%s)\n",
350 					devnode);
351 			return NULL;
352 		}
353 		msleep(10);
354 		dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
355 	}
356 
357 	return dev;
358 }
359 
360 LIBINPUT_EXPORT struct libinput_device *
libinput_path_add_device(struct libinput * libinput,const char * path)361 libinput_path_add_device(struct libinput *libinput,
362 			 const char *path)
363 {
364 	struct path_input *input = (struct path_input *)libinput;
365 	struct udev *udev = input->udev;
366 	struct udev_device *udev_device;
367 	struct libinput_device *device;
368 
369 	if (strlen(path) > PATH_MAX) {
370 		log_bug_client(libinput,
371 			       "Unexpected path, limited to %d characters.\n",
372 			       PATH_MAX);
373 		return NULL;
374 	}
375 
376 	if (libinput->interface_backend != &interface_backend) {
377 		log_bug_client(libinput, "Mismatching backends.\n");
378 		return NULL;
379 	}
380 
381 	udev_device = udev_device_from_devnode(libinput, udev, path);
382 	if (!udev_device) {
383 		log_bug_client(libinput, "Invalid path %s\n", path);
384 		return NULL;
385 	}
386 
387 	if (ignore_litest_test_suite_device(udev_device)) {
388 		udev_device_unref(udev_device);
389 		return NULL;
390 	}
391 
392 	/* We cannot do this during path_create_context because the log
393 	 * handler isn't set up there but we really want to log to the right
394 	 * place if the quirks run into parser errors. So we have to do it
395 	 * on the first call to add_device.
396 	 */
397 	libinput_init_quirks(libinput);
398 
399 	device = path_create_device(libinput, udev_device, NULL);
400 	udev_device_unref(udev_device);
401 	return device;
402 }
403 
404 LIBINPUT_EXPORT void
libinput_path_remove_device(struct libinput_device * device)405 libinput_path_remove_device(struct libinput_device *device)
406 {
407 	struct libinput *libinput = device->seat->libinput;
408 	struct path_input *input = (struct path_input*)libinput;
409 	struct libinput_seat *seat;
410 	struct evdev_device *evdev = evdev_device(device);
411 	struct path_device *dev;
412 
413 	if (libinput->interface_backend != &interface_backend) {
414 		log_bug_client(libinput, "Mismatching backends.\n");
415 		return;
416 	}
417 
418 	list_for_each(dev, &input->path_list, link) {
419 		if (dev->udev_device == evdev->udev_device) {
420 			path_device_destroy(dev);
421 			break;
422 		}
423 	}
424 
425 	seat = device->seat;
426 	libinput_seat_ref(seat);
427 	path_disable_device(libinput, evdev);
428 	libinput_seat_unref(seat);
429 }
430