2 * Copyright © 2013 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 static const char default_seat[] = "seat0";
34 static const char default_seat_name[] = "default";
36 int path_input_process_event(struct libinput_event);
37 static void path_seat_destroy(struct libinput_seat *seat);
40 path_disable_device(struct libinput *libinput,
41 struct evdev_device *device)
43 struct libinput_seat *seat = device->base.seat;
44 struct evdev_device *dev, *next;
46 list_for_each_safe(dev, next,
47 &seat->devices_list, base.link) {
51 evdev_device_remove(device);
57 path_input_disable(struct libinput *libinput)
59 struct path_input *input = (struct path_input*)libinput;
60 struct path_seat *seat, *tmp;
61 struct evdev_device *device, *next;
63 list_for_each_safe(seat, tmp, &input->base.seat_list, base.link) {
64 libinput_seat_ref(&seat->base);
65 list_for_each_safe(device, next,
66 &seat->base.devices_list, base.link)
67 path_disable_device(libinput, device);
68 libinput_seat_unref(&seat->base);
73 path_seat_destroy(struct libinput_seat *seat)
75 struct path_seat *pseat = (struct path_seat*)seat;
79 static struct path_seat*
80 path_seat_create(struct path_input *input,
81 const char *seat_name,
82 const char *seat_logical_name)
84 struct path_seat *seat;
86 seat = zalloc(sizeof(*seat));
90 libinput_seat_init(&seat->base, &input->base, seat_name,
91 seat_logical_name, path_seat_destroy);
96 static struct path_seat*
97 path_seat_get_named(struct path_input *input,
98 const char *seat_name_physical,
99 const char *seat_name_logical)
101 struct path_seat *seat;
103 list_for_each(seat, &input->base.seat_list, base.link) {
104 if (strcmp(seat->base.physical_name, seat_name_physical) == 0 &&
105 strcmp(seat->base.logical_name, seat_name_logical) == 0)
113 path_get_udev_properties(const char *path,
117 char **seat_logical_name)
119 struct udev *udev = NULL;
120 struct udev_device *device = NULL;
129 if (stat(path, &st) < 0)
132 device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
136 *sysname = strdup(udev_device_get_sysname(device));
137 *syspath = strdup(udev_device_get_syspath(device));
139 seat = udev_device_get_property_value(device, "ID_SEAT");
140 *seat_name = strdup(seat ? seat : default_seat);
142 seat = udev_device_get_property_value(device, "WL_SEAT");
143 *seat_logical_name = strdup(seat ? seat : default_seat_name);
149 udev_device_unref(device);
155 static struct libinput_device *
156 path_device_enable(struct path_input *input, const char *devnode)
158 struct path_seat *seat;
159 struct evdev_device *device = NULL;
160 char *sysname = NULL, *syspath = NULL;
161 char *seat_name = NULL, *seat_logical_name = NULL;
163 if (path_get_udev_properties(devnode, &sysname, &syspath,
164 &seat_name, &seat_logical_name) == -1) {
165 log_info(&input->base,
166 "failed to obtain sysname for device '%s'.\n",
171 seat = path_seat_get_named(input, seat_name, seat_logical_name);
174 libinput_seat_ref(&seat->base);
176 seat = path_seat_create(input, seat_name, seat_logical_name);
178 log_info(&input->base,
179 "failed to create seat for device '%s'.\n",
185 device = evdev_device_create(&seat->base, devnode, sysname, syspath);
186 libinput_seat_unref(&seat->base);
188 if (device == EVDEV_UNHANDLED_DEVICE) {
190 log_info(&input->base,
191 "not using input device '%s'.\n",
194 } else if (device == NULL) {
195 log_info(&input->base,
196 "failed to create input device '%s'.\n",
205 free(seat_logical_name);
207 return device ? &device->base : NULL;
211 path_input_enable(struct libinput *libinput)
213 struct path_input *input = (struct path_input*)libinput;
214 struct path_device *dev;
216 list_for_each(dev, &input->path_list, link) {
217 if (path_device_enable(input, dev->path) == NULL) {
218 path_input_disable(libinput);
227 path_input_destroy(struct libinput *input)
229 struct path_input *path_input = (struct path_input*)input;
230 struct path_device *dev, *tmp;
232 list_for_each_safe(dev, tmp, &path_input->path_list, link) {
239 static const struct libinput_interface_backend interface_backend = {
240 .resume = path_input_enable,
241 .suspend = path_input_disable,
242 .destroy = path_input_destroy,
245 LIBINPUT_EXPORT struct libinput *
246 libinput_path_create_context(const struct libinput_interface *interface,
249 struct path_input *input;
254 input = zalloc(sizeof *input);
258 if (libinput_init(&input->base, interface,
259 &interface_backend, user_data) != 0) {
264 list_init(&input->path_list);
269 LIBINPUT_EXPORT struct libinput_device *
270 libinput_path_add_device(struct libinput *libinput,
273 struct path_input *input = (struct path_input*)libinput;
274 struct path_device *dev;
275 struct libinput_device *device;
277 if (libinput->interface_backend != &interface_backend) {
278 log_bug_client(libinput, "Mismatching backends.\n");
282 dev = zalloc(sizeof *dev);
286 dev->path = strdup(path);
292 list_insert(&input->path_list, &dev->link);
294 device = path_device_enable(input, dev->path);
297 list_remove(&dev->link);
306 libinput_path_remove_device(struct libinput_device *device)
308 struct libinput *libinput = device->seat->libinput;
309 struct path_input *input = (struct path_input*)libinput;
310 struct libinput_seat *seat;
311 struct evdev_device *evdev = (struct evdev_device*)device;
312 struct path_device *dev;
314 if (libinput->interface_backend != &interface_backend) {
315 log_bug_client(libinput, "Mismatching backends.\n");
319 list_for_each(dev, &input->path_list, link) {
320 if (strcmp(evdev->devnode, dev->path) == 0) {
321 list_remove(&dev->link);
329 libinput_seat_ref(seat);
330 path_disable_device(libinput, evdev);
331 libinput_seat_unref(seat);