blob: def22b9d4cdc605e61826bd2bf0e7de45ac072ac [file] [log] [blame]
Kristian Høgsberg43db4012011-01-14 14:45:42 -05001/*
2 * Copyright © 2010 Intel Corporation
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 <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <linux/input.h>
27#include <unistd.h>
28#include <fcntl.h>
29
30#include "compositor.h"
31
32struct evdev_input {
33 struct wlsc_input_device base;
34};
35
36struct evdev_input_device {
37 struct evdev_input *master;
38 struct wl_event_source *source;
39 int tool, new_x, new_y;
40 int base_x, base_y;
41 int fd;
Kristian Høgsberg96c8be92011-01-14 14:49:46 -050042 int min_x, max_x, min_y, max_y;
Kristian Høgsberg43db4012011-01-14 14:45:42 -050043};
44
Kristian Høgsbergb1868472011-04-22 12:27:57 -040045static int
46evdev_input_device_data(int fd, uint32_t mask, void *data)
Kristian Høgsberg43db4012011-01-14 14:45:42 -050047{
48 struct wlsc_compositor *ec;
49 struct evdev_input_device *device = data;
50 struct input_event ev[8], *e, *end;
51 int len, value, dx, dy, absolute_event;
52 int x, y;
53 uint32_t time;
54
Kristian Høgsberg96c8be92011-01-14 14:49:46 -050055 /* FIXME: Obviously we need to not hardcode these here, but
56 * instead get the values from the output it's associated with. */
57 const int screen_width = 1024, screen_height = 600;
58
Kristian Høgsberg43db4012011-01-14 14:45:42 -050059 ec = (struct wlsc_compositor *)
60 device->master->base.input_device.compositor;
61 if (!ec->focus)
Kristian Høgsbergb1868472011-04-22 12:27:57 -040062 return 1;
Kristian Høgsberg43db4012011-01-14 14:45:42 -050063
64 dx = 0;
65 dy = 0;
66 absolute_event = 0;
67 x = device->master->base.input_device.x;
68 y = device->master->base.input_device.y;
69
70 len = read(fd, &ev, sizeof ev);
71 if (len < 0 || len % sizeof e[0] != 0) {
72 /* FIXME: handle error... reopen device? */;
Kristian Høgsbergb1868472011-04-22 12:27:57 -040073 return 1;
Kristian Høgsberg43db4012011-01-14 14:45:42 -050074 }
75
76 e = ev;
77 end = (void *) ev + len;
78 for (e = ev; e < end; e++) {
79 /* Get the signed value, earlier kernels had this as unsigned */
80 value = e->value;
81 time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
82
83 switch (e->type) {
84 case EV_REL:
85 switch (e->code) {
86 case REL_X:
87 dx += value;
88 break;
89
90 case REL_Y:
91 dy += value;
92 break;
93 }
94 break;
95
96 case EV_ABS:
Kristian Høgsberg43db4012011-01-14 14:45:42 -050097 switch (e->code) {
98 case ABS_X:
Kristian Høgsberg96c8be92011-01-14 14:49:46 -050099 absolute_event = device->tool;
100 x = (value - device->min_x) * screen_width /
101 (device->max_x - device->min_x);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500102 break;
103 case ABS_Y:
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500104 absolute_event = device->tool;
105 y = (value - device->min_y) * screen_height /
106 (device->max_y - device->min_y);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500107 break;
108 }
109 break;
110
111 case EV_KEY:
112 if (value == 2)
113 break;
114
115 switch (e->code) {
116 case BTN_TOUCH:
117 case BTN_TOOL_PEN:
118 case BTN_TOOL_RUBBER:
119 case BTN_TOOL_BRUSH:
120 case BTN_TOOL_PENCIL:
121 case BTN_TOOL_AIRBRUSH:
122 case BTN_TOOL_FINGER:
123 case BTN_TOOL_MOUSE:
124 case BTN_TOOL_LENS:
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500125 device->tool = value ? e->code : 0;
126 break;
127
128 case BTN_LEFT:
129 case BTN_RIGHT:
130 case BTN_MIDDLE:
131 case BTN_SIDE:
132 case BTN_EXTRA:
133 case BTN_FORWARD:
134 case BTN_BACK:
135 case BTN_TASK:
136 notify_button(&device->master->base.input_device,
137 time, e->code, value);
138 break;
139
140 default:
141 notify_key(&device->master->base.input_device,
142 time, e->code, value);
143 break;
144 }
145 }
146 }
147
148 if (dx != 0 || dy != 0)
149 notify_motion(&device->master->base.input_device,
150 time, x + dx, y + dy);
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500151 if (absolute_event)
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500152 notify_motion(&device->master->base.input_device, time, x, y);
Kristian Høgsbergb1868472011-04-22 12:27:57 -0400153
154 return 1;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500155}
156
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500157#define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31)))
158
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500159static struct evdev_input_device *
160evdev_input_device_create(struct evdev_input *master,
161 struct wl_display *display, const char *path)
162{
163 struct evdev_input_device *device;
164 struct wl_event_loop *loop;
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500165 struct input_absinfo absinfo;
166 uint32_t ev_bits[EV_MAX];
167 uint32_t key_bits[KEY_MAX];
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500168
169 device = malloc(sizeof *device);
170 if (device == NULL)
171 return NULL;
172
173 device->tool = 1;
174 device->new_x = 1;
175 device->new_y = 1;
176 device->master = master;
177
178 device->fd = open(path, O_RDONLY);
179 if (device->fd < 0) {
180 free(device);
181 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
182 return NULL;
183 }
184
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500185 ioctl(device->fd, EVIOCGBIT(0, EV_MAX), ev_bits);
186 if (TEST_BIT(ev_bits, EV_ABS)) {
187 ioctl(device->fd, EVIOCGBIT(EV_ABS, EV_MAX), key_bits);
188 if (TEST_BIT(key_bits, ABS_X)) {
189 ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
190 device->min_x = absinfo.minimum;
191 device->max_x = absinfo.maximum;
192 }
193 if (TEST_BIT(key_bits, ABS_Y)) {
194 ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
195 device->min_y = absinfo.minimum;
196 device->max_y = absinfo.maximum;
197 }
198 }
199
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500200 loop = wl_display_get_event_loop(display);
201 device->source = wl_event_loop_add_fd(loop, device->fd,
202 WL_EVENT_READABLE,
203 evdev_input_device_data, device);
204 if (device->source == NULL) {
205 close(device->fd);
206 free(device);
207 return NULL;
208 }
209
210 return device;
211}
212
Kristian Høgsberg86ec8e82011-07-19 16:10:11 -0700213static const char default_seat[] = "seat0";
214
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500215void
Kristian Høgsberg86ec8e82011-07-19 16:10:11 -0700216evdev_input_add_devices(struct wlsc_compositor *c,
217 struct udev *udev, const char *seat)
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500218{
219 struct evdev_input *input;
220 struct udev_enumerate *e;
221 struct udev_list_entry *entry;
222 struct udev_device *device;
Kristian Høgsberg86ec8e82011-07-19 16:10:11 -0700223 const char *device_seat;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500224 const char *path;
225
226 input = malloc(sizeof *input);
227 if (input == NULL)
228 return;
229
230 memset(input, 0, sizeof *input);
231 wlsc_input_device_init(&input->base, c);
232
233 e = udev_enumerate_new(udev);
234 udev_enumerate_add_match_subsystem(e, "input");
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500235 udev_enumerate_scan_devices(e);
236 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
237 path = udev_list_entry_get_name(entry);
238 device = udev_device_new_from_syspath(udev, path);
Kristian Høgsberg86ec8e82011-07-19 16:10:11 -0700239
240 device_seat =
241 udev_device_get_property_value(device, "ID_SEAT");
242 if (!device_seat)
243 device_seat = default_seat;
244
245 if (strcmp(device_seat, seat) == 0) {
246 evdev_input_device_create(input, c->wl_display,
247 udev_device_get_devnode(device));
248 }
249
250 udev_device_unref(device);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500251 }
252 udev_enumerate_unref(e);
253
254 c->input_device = &input->base.input_device;
255}