Reduce touch events to a single event type
[platform/upstream/libinput.git] / src / path.c
1 /*
2  * Copyright © 2013 Red Hat, Inc.
3  *
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.
13  *
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.
21  */
22
23 #include "config.h"
24
25 #include <fcntl.h>
26 #include <string.h>
27 #include <libudev.h>
28
29 #include "path.h"
30 #include "evdev.h"
31
32 int path_input_process_event(struct libinput_event);
33 static void path_seat_destroy(struct libinput_seat *seat);
34
35 static void
36 path_input_disable(struct libinput *libinput)
37 {
38         struct path_input *input = (struct path_input*)libinput;
39         struct evdev_device *device = input->device;
40         struct path_seat *seat, *tmp;
41
42         if (device) {
43                 close_restricted(libinput, device->fd);
44                 evdev_device_remove(device);
45                 input->device = NULL;
46         }
47
48         /* should only be one seat anyway */
49         list_for_each_safe(seat, tmp, &libinput->seat_list, base.link) {
50                 list_remove(&seat->base.link);
51                 list_init(&seat->base.link);
52                 libinput_seat_unref(&seat->base);
53         }
54 }
55
56 static void
57 path_seat_destroy(struct libinput_seat *seat)
58 {
59         struct path_seat *pseat = (struct path_seat*)seat;
60         free(pseat);
61 }
62
63 static struct path_seat*
64 path_seat_create(struct path_input *input)
65 {
66         struct path_seat *seat;
67
68         seat = zalloc(sizeof(*seat));
69         if (!seat)
70                 return NULL;
71
72         seat->name = "default";
73
74         /* FIXME: get physical seat from udev */
75         libinput_seat_init(&seat->base, &input->base, seat->name, seat->name, path_seat_destroy);
76         list_insert(&input->base.seat_list, &seat->base.link);
77
78         return seat;
79 }
80
81 static char *
82 path_get_sysname(const char *path)
83 {
84         struct udev *udev = NULL;
85         struct udev_device *device = NULL;
86         struct stat st;
87         char *syspath = NULL;
88
89         udev = udev_new();
90         if (!udev)
91                 goto out;
92
93         if (stat(path, &st) < 0)
94                 goto out;
95
96         device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
97         if (!device)
98                 goto out;
99
100         syspath = strdup(udev_device_get_syspath(device));
101 out:
102         if (device)
103                 udev_device_unref(device);
104         if (udev)
105                 udev_unref(udev);
106         return syspath;
107 }
108
109 static int
110 path_input_enable(struct libinput *libinput)
111 {
112         struct path_input *input = (struct path_input*)libinput;
113         struct path_seat *seat;
114         struct evdev_device *device;
115         const char *devnode = input->path;
116         char *syspath;
117         int fd;
118
119         if (input->device)
120                 return 0;
121
122         fd = open_restricted(libinput, input->path, O_RDWR|O_NONBLOCK);
123         if (fd < 0) {
124                 log_info("opening input device '%s' failed.\n", devnode);
125                 return -1;
126         }
127
128         syspath = path_get_sysname(devnode);
129         if (!syspath) {
130                 close_restricted(libinput, fd);
131                 log_info("failed to obtain syspath for device '%s'.\n", devnode);
132                 return -1;
133         }
134
135         seat = path_seat_create(input);
136
137         device = evdev_device_create(&seat->base, devnode, syspath, fd);
138         free(syspath);
139
140         if (device == EVDEV_UNHANDLED_DEVICE) {
141                 close_restricted(libinput, fd);
142                 log_info("not using input device '%s'.\n", devnode);
143                 libinput_seat_unref(&seat->base);
144                 return -1;
145         } else if (device == NULL) {
146                 close_restricted(libinput, fd);
147                 log_info("failed to create input device '%s'.\n", devnode);
148                 libinput_seat_unref(&seat->base);
149                 return -1;
150         }
151
152         input->device = device;
153
154         return 0;
155 }
156
157 static void
158 path_input_destroy(struct libinput *input)
159 {
160         struct path_input *path_input = (struct path_input*)input;
161         free(path_input->path);
162 }
163
164 static const struct libinput_interface_backend interface_backend = {
165         .resume = path_input_enable,
166         .suspend = path_input_disable,
167         .destroy = path_input_destroy,
168 };
169
170 LIBINPUT_EXPORT struct libinput *
171 libinput_create_from_path(const struct libinput_interface *interface,
172                           void *user_data,
173                           const char *path)
174 {
175         struct path_input *input;
176
177         if (!interface || !path)
178                 return NULL;
179
180         input = zalloc(sizeof *input);
181         if (!input)
182                 return NULL;
183
184         if (libinput_init(&input->base, interface,
185                           &interface_backend, user_data) != 0) {
186                 free(input);
187                 return NULL;
188         }
189
190         input->path = strdup(path);
191
192         if (path_input_enable(&input->base) < 0) {
193                 libinput_destroy(&input->base);
194                 return NULL;
195         }
196
197         return &input->base;
198 }