blob: c1e11d385f6a48b0a196cc7de0a4b20adf6bd56c [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
Daniel Stonec228e232013-05-22 18:03:19 +030023#include "config.h"
24
Kristian Høgsberg43db4012011-01-14 14:45:42 -050025#include <stdlib.h>
26#include <string.h>
27#include <linux/input.h>
28#include <unistd.h>
29#include <fcntl.h>
Tiago Vignatti23fdeed2012-03-16 17:33:03 -030030#include <mtdev.h>
Neil Robertsdaf7d472013-09-24 12:09:03 +010031#include <assert.h>
Kristian Høgsberg43db4012011-01-14 14:45:42 -050032
33#include "compositor.h"
Tiago Vignattice03ec32011-12-19 01:14:03 +020034#include "evdev.h"
Kristian Høgsberg43db4012011-01-14 14:45:42 -050035
Jonas Ådahlb984e402012-10-03 22:56:58 +020036#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
37
Pekka Paalanen88594b62012-08-03 14:39:05 +030038void
Pekka Paalanen3eb47612012-08-06 14:57:08 +030039evdev_led_update(struct evdev_device *device, enum weston_led leds)
Daniel Stone7bbd5b32012-05-30 16:31:49 +010040{
41 static const struct {
42 enum weston_led weston;
43 int evdev;
44 } map[] = {
45 { LED_NUM_LOCK, LED_NUML },
46 { LED_CAPS_LOCK, LED_CAPSL },
47 { LED_SCROLL_LOCK, LED_SCROLLL },
48 };
Rolf Morel14c98922013-08-09 16:32:17 +020049 struct input_event ev[ARRAY_LENGTH(map) + 1];
Daniel Stone7bbd5b32012-05-30 16:31:49 +010050 unsigned int i;
51
Pekka Paalanenb9d38f42012-08-06 14:57:07 +030052 if (!device->caps & EVDEV_KEYBOARD)
53 return;
54
Daniel Stone7bbd5b32012-05-30 16:31:49 +010055 memset(ev, 0, sizeof(ev));
56 for (i = 0; i < ARRAY_LENGTH(map); i++) {
57 ev[i].type = EV_LED;
58 ev[i].code = map[i].evdev;
59 ev[i].value = !!(leds & map[i].weston);
60 }
Rolf Morel14c98922013-08-09 16:32:17 +020061 ev[i].type = EV_SYN;
62 ev[i].code = SYN_REPORT;
Daniel Stone7bbd5b32012-05-30 16:31:49 +010063
Pekka Paalanenb9d38f42012-08-06 14:57:07 +030064 i = write(device->fd, ev, sizeof ev);
65 (void)i; /* no, we really don't care about the return value */
Daniel Stone7bbd5b32012-05-30 16:31:49 +010066}
67
Neil Robertsdaf7d472013-09-24 12:09:03 +010068static void
69transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y)
70{
71 if (!device->abs.apply_calibration) {
72 *x = device->abs.x;
73 *y = device->abs.y;
74 return;
75 } else {
76 *x = device->abs.x * device->abs.calibration[0] +
77 device->abs.y * device->abs.calibration[1] +
78 device->abs.calibration[2];
79
80 *y = device->abs.x * device->abs.calibration[3] +
81 device->abs.y * device->abs.calibration[4] +
82 device->abs.calibration[5];
83 }
84}
85
86static void
87evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
88{
89 struct weston_seat *master = device->seat;
90 wl_fixed_t x, y;
91 int32_t cx, cy;
92 int slot;
93
94 slot = device->mt.slot;
95
96 switch (device->pending_event) {
97 case EVDEV_NONE:
98 return;
99 case EVDEV_RELATIVE_MOTION:
100 notify_motion(master, time, device->rel.dx, device->rel.dy);
101 device->rel.dx = 0;
102 device->rel.dy = 0;
103 goto handled;
104 case EVDEV_ABSOLUTE_MT_DOWN:
105 weston_output_transform_coordinate(device->output,
106 device->mt.slots[slot].x,
107 device->mt.slots[slot].y,
108 &x, &y);
109 notify_touch(master, time,
110 slot, x, y, WL_TOUCH_DOWN);
111 goto handled;
112 case EVDEV_ABSOLUTE_MT_MOTION:
113 weston_output_transform_coordinate(device->output,
114 device->mt.slots[slot].x,
115 device->mt.slots[slot].y,
116 &x, &y);
117 notify_touch(master, time,
118 slot, x, y, WL_TOUCH_MOTION);
119 goto handled;
120 case EVDEV_ABSOLUTE_MT_UP:
121 notify_touch(master, time, slot, 0, 0,
122 WL_TOUCH_UP);
123 goto handled;
124 case EVDEV_ABSOLUTE_MOTION:
125 transform_absolute(device, &cx, &cy);
126 weston_output_transform_coordinate(device->output,
127 cx, cy, &x, &y);
128
129 if (device->caps & EVDEV_TOUCH) {
130 if (master->num_tp == 0)
131 notify_touch(master, time, 0,
132 x, y, WL_TOUCH_DOWN);
133 else
134 notify_touch(master, time, 0,
135 x, y, WL_TOUCH_MOTION);
136 } else
137 notify_motion_absolute(master, time, x, y);
138 goto handled;
139 }
140
141 assert(0 && "Unknown pending event type");
142
143handled:
144 device->pending_event = EVDEV_NONE;
145}
146
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300147static inline void
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300148evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300149{
Peter Hutterer89af60e2013-08-07 11:04:42 +1000150 /* ignore kernel key repeat */
Tiago Vignatti8755ff92011-11-10 14:47:30 +0200151 if (e->value == 2)
152 return;
153
Neil Robertsdaf7d472013-09-24 12:09:03 +0100154 evdev_flush_pending_event(device, time);
155
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300156 switch (e->code) {
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300157 case BTN_LEFT:
158 case BTN_RIGHT:
159 case BTN_MIDDLE:
160 case BTN_SIDE:
161 case BTN_EXTRA:
162 case BTN_FORWARD:
163 case BTN_BACK:
164 case BTN_TASK:
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -0400165 notify_button(device->seat,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100166 time, e->code,
167 e->value ? WL_POINTER_BUTTON_STATE_PRESSED :
168 WL_POINTER_BUTTON_STATE_RELEASED);
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300169 break;
170
Kristian Høgsberg0af26c42013-07-26 10:43:26 -0700171 case BTN_TOUCH:
172 if (e->value == 0 && !device->is_mt)
Rusty Lynch92e83922013-08-08 21:08:17 -0700173 notify_touch(device->seat, time, 0, 0, 0,
Kristian Høgsberg0af26c42013-07-26 10:43:26 -0700174 WL_TOUCH_UP);
175 break;
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300176 default:
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -0400177 notify_key(device->seat,
Daniel Stonec9785ea2012-05-30 16:31:52 +0100178 time, e->code,
179 e->value ? WL_KEYBOARD_KEY_STATE_PRESSED :
Daniel Stone1b4e11f2012-06-22 13:21:37 +0100180 WL_KEYBOARD_KEY_STATE_RELEASED,
181 STATE_UPDATE_AUTOMATIC);
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300182 break;
183 }
184}
185
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200186static void
Neil Robertsdaf7d472013-09-24 12:09:03 +0100187evdev_process_touch(struct evdev_device *device,
188 struct input_event *e,
189 uint32_t time)
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200190{
Hardeningff39efa2013-09-18 23:56:35 +0200191 const int screen_width = device->output->current_mode->width;
192 const int screen_height = device->output->current_mode->height;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200193
194 switch (e->code) {
195 case ABS_MT_SLOT:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100196 evdev_flush_pending_event(device, time);
Kristian Høgsberg39373542011-12-21 22:18:36 -0500197 device->mt.slot = e->value;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200198 break;
199 case ABS_MT_TRACKING_ID:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100200 if (device->pending_event != EVDEV_NONE &&
201 device->pending_event != EVDEV_ABSOLUTE_MT_MOTION)
202 evdev_flush_pending_event(device, time);
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200203 if (e->value >= 0)
Neil Robertsdaf7d472013-09-24 12:09:03 +0100204 device->pending_event = EVDEV_ABSOLUTE_MT_DOWN;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200205 else
Neil Robertsdaf7d472013-09-24 12:09:03 +0100206 device->pending_event = EVDEV_ABSOLUTE_MT_UP;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200207 break;
208 case ABS_MT_POSITION_X:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100209 device->mt.slots[device->mt.slot].x =
Kristian Høgsberg39373542011-12-21 22:18:36 -0500210 (e->value - device->abs.min_x) * screen_width /
Kristian Høgsberg97e806f2013-07-22 15:09:30 -0700211 (device->abs.max_x - device->abs.min_x);
Neil Robertsdaf7d472013-09-24 12:09:03 +0100212 if (device->pending_event == EVDEV_NONE)
213 device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200214 break;
215 case ABS_MT_POSITION_Y:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100216 device->mt.slots[device->mt.slot].y =
Kristian Høgsberg39373542011-12-21 22:18:36 -0500217 (e->value - device->abs.min_y) * screen_height /
Kristian Høgsberg97e806f2013-07-22 15:09:30 -0700218 (device->abs.max_y - device->abs.min_y);
Neil Robertsdaf7d472013-09-24 12:09:03 +0100219 if (device->pending_event == EVDEV_NONE)
220 device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200221 break;
222 }
223}
224
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300225static inline void
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300226evdev_process_absolute_motion(struct evdev_device *device,
Kristian Høgsberg39373542011-12-21 22:18:36 -0500227 struct input_event *e)
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300228{
Hardeningff39efa2013-09-18 23:56:35 +0200229 const int screen_width = device->output->current_mode->width;
230 const int screen_height = device->output->current_mode->height;
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300231
232 switch (e->code) {
233 case ABS_X:
Kristian Høgsberg39373542011-12-21 22:18:36 -0500234 device->abs.x =
235 (e->value - device->abs.min_x) * screen_width /
Kristian Høgsbergcee407e2013-07-26 10:40:32 -0700236 (device->abs.max_x - device->abs.min_x);
Neil Robertsdaf7d472013-09-24 12:09:03 +0100237 if (device->pending_event == EVDEV_NONE)
238 device->pending_event = EVDEV_ABSOLUTE_MOTION;
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300239 break;
240 case ABS_Y:
Kristian Høgsberg39373542011-12-21 22:18:36 -0500241 device->abs.y =
242 (e->value - device->abs.min_y) * screen_height /
Kristian Høgsbergcee407e2013-07-26 10:40:32 -0700243 (device->abs.max_y - device->abs.min_y);
Neil Robertsdaf7d472013-09-24 12:09:03 +0100244 if (device->pending_event == EVDEV_NONE)
245 device->pending_event = EVDEV_ABSOLUTE_MOTION;
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300246 break;
247 }
248}
249
250static inline void
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300251evdev_process_relative(struct evdev_device *device,
Jonas Ådahl1df17af2012-05-17 12:18:17 +0200252 struct input_event *e, uint32_t time)
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300253{
254 switch (e->code) {
255 case REL_X:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100256 if (device->pending_event != EVDEV_RELATIVE_MOTION)
257 evdev_flush_pending_event(device, time);
Jonas Ådahlc0ca3992012-05-10 16:46:48 -0400258 device->rel.dx += wl_fixed_from_int(e->value);
Neil Robertsdaf7d472013-09-24 12:09:03 +0100259 device->pending_event = EVDEV_RELATIVE_MOTION;
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300260 break;
261 case REL_Y:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100262 if (device->pending_event != EVDEV_RELATIVE_MOTION)
263 evdev_flush_pending_event(device, time);
Jonas Ådahlc0ca3992012-05-10 16:46:48 -0400264 device->rel.dy += wl_fixed_from_int(e->value);
Neil Robertsdaf7d472013-09-24 12:09:03 +0100265 device->pending_event = EVDEV_RELATIVE_MOTION;
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300266 break;
Scott Moreau210d0792012-03-22 10:47:01 -0600267 case REL_WHEEL:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100268 evdev_flush_pending_event(device, time);
Jonas Ådahlb984e402012-10-03 22:56:58 +0200269 switch (e->value) {
270 case -1:
271 /* Scroll down */
272 case 1:
273 /* Scroll up */
274 notify_axis(device->seat,
275 time,
276 WL_POINTER_AXIS_VERTICAL_SCROLL,
277 -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
278 break;
279 default:
280 break;
281 }
Scott Moreau210d0792012-03-22 10:47:01 -0600282 break;
283 case REL_HWHEEL:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100284 evdev_flush_pending_event(device, time);
Jonas Ådahlb984e402012-10-03 22:56:58 +0200285 switch (e->value) {
286 case -1:
287 /* Scroll left */
288 case 1:
289 /* Scroll right */
290 notify_axis(device->seat,
291 time,
292 WL_POINTER_AXIS_HORIZONTAL_SCROLL,
293 e->value * DEFAULT_AXIS_STEP_DISTANCE);
294 break;
295 default:
296 break;
297
298 }
Tiago Vignatti8be003b2011-09-01 19:00:03 +0300299 }
300}
301
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200302static inline void
Neil Robertsdaf7d472013-09-24 12:09:03 +0100303evdev_process_absolute(struct evdev_device *device,
304 struct input_event *e,
305 uint32_t time)
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200306{
Jonas Ådahl1df17af2012-05-17 12:18:17 +0200307 if (device->is_mt) {
Neil Robertsdaf7d472013-09-24 12:09:03 +0100308 evdev_process_touch(device, e, time);
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200309 } else {
Kristian Høgsberg39373542011-12-21 22:18:36 -0500310 evdev_process_absolute_motion(device, e);
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200311 }
312}
313
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400314static void
Jonas Ådahl4136d822012-05-17 12:18:16 +0200315fallback_process(struct evdev_dispatch *dispatch,
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300316 struct evdev_device *device,
Jonas Ådahl4136d822012-05-17 12:18:16 +0200317 struct input_event *event,
318 uint32_t time)
319{
320 switch (event->type) {
321 case EV_REL:
322 evdev_process_relative(device, event, time);
323 break;
324 case EV_ABS:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100325 evdev_process_absolute(device, event, time);
Jonas Ådahl4136d822012-05-17 12:18:16 +0200326 break;
327 case EV_KEY:
328 evdev_process_key(device, event, time);
329 break;
Satyeshwar Singh964a3422013-02-27 15:26:23 -0500330 case EV_SYN:
Neil Robertsdaf7d472013-09-24 12:09:03 +0100331 evdev_flush_pending_event(device, time);
Satyeshwar Singh964a3422013-02-27 15:26:23 -0500332 break;
Jonas Ådahl4136d822012-05-17 12:18:16 +0200333 }
334}
335
336static void
337fallback_destroy(struct evdev_dispatch *dispatch)
338{
339 free(dispatch);
340}
341
342struct evdev_dispatch_interface fallback_interface = {
343 fallback_process,
344 fallback_destroy
345};
346
347static struct evdev_dispatch *
348fallback_dispatch_create(void)
349{
350 struct evdev_dispatch *dispatch = malloc(sizeof *dispatch);
351 if (dispatch == NULL)
352 return NULL;
353
354 dispatch->interface = &fallback_interface;
355
356 return dispatch;
357}
358
359static void
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300360evdev_process_events(struct evdev_device *device,
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400361 struct input_event *ev, int count)
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500362{
Jonas Ådahl4136d822012-05-17 12:18:16 +0200363 struct evdev_dispatch *dispatch = device->dispatch;
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400364 struct input_event *e, *end;
Kristian Høgsberg865f9b82011-12-02 06:39:02 -0500365 uint32_t time = 0;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500366
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500367 e = ev;
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400368 end = e + count;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500369 for (e = ev; e < end; e++) {
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500370 time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
371
Jonas Ådahl4136d822012-05-17 12:18:16 +0200372 dispatch->interface->process(dispatch, device, e, time);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500373 }
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400374}
375
376static int
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300377evdev_device_data(int fd, uint32_t mask, void *data)
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400378{
379 struct weston_compositor *ec;
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300380 struct evdev_device *device = data;
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400381 struct input_event ev[32];
382 int len;
383
Pekka Paalanen5618d6f2012-08-03 14:39:00 +0300384 ec = device->seat->compositor;
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400385 if (!ec->focus)
386 return 1;
387
388 /* If the compositor is repainting, this function is called only once
389 * per frame and we have to process all the events available on the
390 * fd, otherwise there will be input lag. */
391 do {
392 if (device->mtdev)
393 len = mtdev_get(device->mtdev, fd, ev,
394 ARRAY_LENGTH(ev)) *
395 sizeof (struct input_event);
396 else
397 len = read(fd, &ev, sizeof ev);
398
399 if (len < 0 || len % sizeof ev[0] != 0) {
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300400 /* FIXME: call evdev_device_destroy when errno is ENODEV. */
Ander Conselvan de Oliveira29d95562012-03-20 19:52:57 -0400401 return 1;
402 }
403
404 evdev_process_events(device, ev, len / sizeof ev[0]);
405
406 } while (len > 0);
Kristian Høgsbergb1868472011-04-22 12:27:57 -0400407
408 return 1;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500409}
410
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300411static int
Kristian Høgsberg2f07ef62013-02-16 14:29:24 -0500412evdev_handle_device(struct evdev_device *device)
Tiago Vignattid9c82502011-08-19 15:06:20 +0300413{
414 struct input_absinfo absinfo;
415 unsigned long ev_bits[NBITS(EV_MAX)];
416 unsigned long abs_bits[NBITS(ABS_MAX)];
Daniel Stone33965c22012-05-30 16:31:48 +0100417 unsigned long rel_bits[NBITS(REL_MAX)];
Tiago Vignattid9c82502011-08-19 15:06:20 +0300418 unsigned long key_bits[NBITS(KEY_MAX)];
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300419 int has_key, has_abs;
Daniel Stone33965c22012-05-30 16:31:48 +0100420 unsigned int i;
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300421
422 has_key = 0;
423 has_abs = 0;
Daniel Stone33965c22012-05-30 16:31:48 +0100424 device->caps = 0;
Tiago Vignattid9c82502011-08-19 15:06:20 +0300425
426 ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
427 if (TEST_BIT(ev_bits, EV_ABS)) {
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300428 has_abs = 1;
Tiago Vignattia157fc12011-11-21 16:39:55 +0200429
Tiago Vignattid9c82502011-08-19 15:06:20 +0300430 ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)),
431 abs_bits);
Kristian Høgsbergb1c02a82013-08-13 14:55:39 -0700432
433 if (TEST_BIT(abs_bits, ABS_WHEEL) ||
434 TEST_BIT(abs_bits, ABS_GAS) ||
435 TEST_BIT(abs_bits, ABS_BRAKE) ||
436 TEST_BIT(abs_bits, ABS_HAT0X)) {
437 weston_log("device %s is a joystick, ignoring\n",
438 device->devnode);
439 return 0;
440 }
441
Tiago Vignattid9c82502011-08-19 15:06:20 +0300442 if (TEST_BIT(abs_bits, ABS_X)) {
443 ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
Tiago Vignattia157fc12011-11-21 16:39:55 +0200444 device->abs.min_x = absinfo.minimum;
445 device->abs.max_x = absinfo.maximum;
Daniel Stone33965c22012-05-30 16:31:48 +0100446 device->caps |= EVDEV_MOTION_ABS;
Tiago Vignattid9c82502011-08-19 15:06:20 +0300447 }
448 if (TEST_BIT(abs_bits, ABS_Y)) {
449 ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
Tiago Vignattia157fc12011-11-21 16:39:55 +0200450 device->abs.min_y = absinfo.minimum;
451 device->abs.max_y = absinfo.maximum;
Daniel Stone33965c22012-05-30 16:31:48 +0100452 device->caps |= EVDEV_MOTION_ABS;
Tiago Vignattid9c82502011-08-19 15:06:20 +0300453 }
Peter Hutterer45d659d2013-08-08 12:03:08 +1000454 /* We only handle the slotted Protocol B in weston.
455 Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
456 require mtdev for conversion. */
457 if (TEST_BIT(abs_bits, ABS_MT_POSITION_X) &&
458 TEST_BIT(abs_bits, ABS_MT_POSITION_Y)) {
Pekka Paalanen2fc7cce2012-07-31 13:21:07 +0300459 ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X),
460 &absinfo);
461 device->abs.min_x = absinfo.minimum;
462 device->abs.max_x = absinfo.maximum;
463 ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_Y),
464 &absinfo);
465 device->abs.min_y = absinfo.minimum;
466 device->abs.max_y = absinfo.maximum;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200467 device->is_mt = 1;
Daniel Stone33965c22012-05-30 16:31:48 +0100468 device->caps |= EVDEV_TOUCH;
Peter Hutterer0d061e32013-08-07 11:04:45 +1000469
470 if (!TEST_BIT(abs_bits, ABS_MT_SLOT)) {
471 device->mtdev = mtdev_new_open(device->fd);
472 if (!device->mtdev) {
473 weston_log("mtdev required but failed to open for %s\n",
474 device->devnode);
475 return 0;
476 }
Peter Huttererdf66c5b2013-08-07 11:04:46 +1000477 device->mt.slot = device->mtdev->caps.slot.value;
478 } else {
479 ioctl(device->fd, EVIOCGABS(ABS_MT_SLOT),
480 &absinfo);
481 device->mt.slot = absinfo.value;
Peter Hutterer0d061e32013-08-07 11:04:45 +1000482 }
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200483 }
Tiago Vignattid9c82502011-08-19 15:06:20 +0300484 }
Daniel Stone33965c22012-05-30 16:31:48 +0100485 if (TEST_BIT(ev_bits, EV_REL)) {
486 ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)),
487 rel_bits);
488 if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y))
489 device->caps |= EVDEV_MOTION_REL;
490 }
Tiago Vignattid9c82502011-08-19 15:06:20 +0300491 if (TEST_BIT(ev_bits, EV_KEY)) {
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300492 has_key = 1;
Tiago Vignattid9c82502011-08-19 15:06:20 +0300493 ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)),
494 key_bits);
495 if (TEST_BIT(key_bits, BTN_TOOL_FINGER) &&
Jonas Ådahl1df17af2012-05-17 12:18:17 +0200496 !TEST_BIT(key_bits, BTN_TOOL_PEN) &&
Peter Hutterer4477fee2013-08-07 11:04:49 +1000497 has_abs) {
Jonas Ådahl1df17af2012-05-17 12:18:17 +0200498 device->dispatch = evdev_touchpad_create(device);
Peter Hutterer4477fee2013-08-07 11:04:49 +1000499 weston_log("input device %s, %s is a touchpad\n",
500 device->devname, device->devnode);
501 }
Daniel Stone33965c22012-05-30 16:31:48 +0100502 for (i = KEY_ESC; i < KEY_MAX; i++) {
503 if (i >= BTN_MISC && i < KEY_OK)
504 continue;
505 if (TEST_BIT(key_bits, i)) {
506 device->caps |= EVDEV_KEYBOARD;
507 break;
508 }
509 }
510 for (i = BTN_MISC; i < KEY_OK; i++) {
511 if (TEST_BIT(key_bits, i)) {
512 device->caps |= EVDEV_BUTTON;
513 break;
514 }
515 }
Kristian Høgsberg0af26c42013-07-26 10:43:26 -0700516 if (TEST_BIT(key_bits, BTN_TOUCH)) {
517 device->caps |= EVDEV_TOUCH;
518 }
519
Tiago Vignattid9c82502011-08-19 15:06:20 +0300520 }
Daniel Stonecfd0e722012-06-01 12:13:59 +0100521 if (TEST_BIT(ev_bits, EV_LED)) {
522 device->caps |= EVDEV_KEYBOARD;
523 }
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300524
525 /* This rule tries to catch accelerometer devices and opt out. We may
526 * want to adjust the protocol later adding a proper event for dealing
527 * with accelerometers and implement here accordingly */
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300528 if (has_abs && !has_key && !device->is_mt) {
529 weston_log("input device %s, %s "
530 "ignored: unsupported device type\n",
531 device->devname, device->devnode);
Kristian Høgsberg2f07ef62013-02-16 14:29:24 -0500532 return 0;
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300533 }
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300534
Kristian Høgsberg2f07ef62013-02-16 14:29:24 -0500535 return 1;
536}
537
538static int
539evdev_configure_device(struct evdev_device *device)
540{
Daniel Stone74419a22012-05-30 16:32:02 +0100541 if ((device->caps &
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300542 (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) {
Pekka Paalanen5618d6f2012-08-03 14:39:00 +0300543 weston_seat_init_pointer(device->seat);
Rob Bradford80137f32012-12-03 19:44:13 +0000544 weston_log("input device %s, %s is a pointer caps =%s%s%s\n",
545 device->devname, device->devnode,
546 device->caps & EVDEV_MOTION_ABS ? " absolute-motion" : "",
547 device->caps & EVDEV_MOTION_REL ? " relative-motion": "",
548 device->caps & EVDEV_BUTTON ? " button" : "");
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300549 }
550 if ((device->caps & EVDEV_KEYBOARD)) {
Kristian Høgsberg2f07ef62013-02-16 14:29:24 -0500551 if (weston_seat_init_keyboard(device->seat, NULL) < 0)
552 return -1;
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300553 weston_log("input device %s, %s is a keyboard\n",
554 device->devname, device->devnode);
555 }
556 if ((device->caps & EVDEV_TOUCH)) {
Pekka Paalanen5618d6f2012-08-03 14:39:00 +0300557 weston_seat_init_touch(device->seat);
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300558 weston_log("input device %s, %s is a touch device\n",
559 device->devname, device->devnode);
560 }
Daniel Stone74419a22012-05-30 16:32:02 +0100561
Tiago Vignattic0827fd2011-08-19 17:07:40 +0300562 return 0;
Tiago Vignattid9c82502011-08-19 15:06:20 +0300563}
564
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300565struct evdev_device *
566evdev_device_create(struct weston_seat *seat, const char *path, int device_fd)
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500567{
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300568 struct evdev_device *device;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500569 struct weston_compositor *ec;
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300570 char devname[256] = "unknown";
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500571
Peter Huttererf3d62272013-08-08 11:57:05 +1000572 device = zalloc(sizeof *device);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500573 if (device == NULL)
574 return NULL;
575
Pekka Paalanen43f0a1e2012-08-03 14:39:03 +0300576 ec = seat->compositor;
Tiago Vignattiac9cfd32011-10-28 13:15:25 -0400577 device->output =
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500578 container_of(ec->output_list.next, struct weston_output, link);
Kristian Høgsberge7b5b412011-09-01 13:25:50 -0400579
Pekka Paalanen43f0a1e2012-08-03 14:39:03 +0300580 device->seat = seat;
Tiago Vignatti22c6bce2011-12-21 19:34:09 +0200581 device->is_mt = 0;
Tiago Vignatti23fdeed2012-03-16 17:33:03 -0300582 device->mtdev = NULL;
Tiago Vignattiac2dc6a2011-10-28 13:05:06 -0400583 device->devnode = strdup(path);
Kristian Høgsberg39373542011-12-21 22:18:36 -0500584 device->mt.slot = -1;
585 device->rel.dx = 0;
586 device->rel.dy = 0;
Jonas Ådahl4136d822012-05-17 12:18:16 +0200587 device->dispatch = NULL;
Pekka Paalanen5a6383b2012-08-03 14:38:58 +0300588 device->fd = device_fd;
Neil Robertsdaf7d472013-09-24 12:09:03 +0100589 device->pending_event = EVDEV_NONE;
Kristian Høgsberg4e55d062013-08-26 14:35:32 -0700590 wl_list_init(&device->link);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500591
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300592 ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname);
Peter Hutterer11f5bfb2013-08-07 11:04:41 +1000593 devname[sizeof(devname) - 1] = '\0';
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300594 device->devname = strdup(devname);
595
Kristian Høgsberg2f07ef62013-02-16 14:29:24 -0500596 if (!evdev_handle_device(device)) {
Peter Hutterer6bb15cd2013-08-07 11:04:48 +1000597 evdev_device_destroy(device);
Kristian Høgsberg2f07ef62013-02-16 14:29:24 -0500598 return EVDEV_UNHANDLED_DEVICE;
599 }
600
Tiago Vignattiac9cfd32011-10-28 13:15:25 -0400601 if (evdev_configure_device(device) == -1)
Peter Hutterer6bb15cd2013-08-07 11:04:48 +1000602 goto err;
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500603
Jonas Ådahl4136d822012-05-17 12:18:16 +0200604 /* If the dispatch was not set up use the fallback. */
605 if (device->dispatch == NULL)
606 device->dispatch = fallback_dispatch_create();
607 if (device->dispatch == NULL)
Peter Hutterer6bb15cd2013-08-07 11:04:48 +1000608 goto err;
Jonas Ådahl4136d822012-05-17 12:18:16 +0200609
Kristian Høgsberg7ea10862012-03-05 17:49:30 -0500610 device->source = wl_event_loop_add_fd(ec->input_loop, device->fd,
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500611 WL_EVENT_READABLE,
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300612 evdev_device_data, device);
Tiago Vignattiac9cfd32011-10-28 13:15:25 -0400613 if (device->source == NULL)
Peter Hutterer6bb15cd2013-08-07 11:04:48 +1000614 goto err;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500615
616 return device;
Tiago Vignattiac9cfd32011-10-28 13:15:25 -0400617
Peter Hutterer6bb15cd2013-08-07 11:04:48 +1000618err:
619 evdev_device_destroy(device);
Tiago Vignattiac9cfd32011-10-28 13:15:25 -0400620 return NULL;
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500621}
622
Pekka Paalanen88594b62012-08-03 14:39:05 +0300623void
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300624evdev_device_destroy(struct evdev_device *device)
Pekka Paalanena123e5c2012-08-03 14:38:57 +0300625{
626 struct evdev_dispatch *dispatch;
627
628 dispatch = device->dispatch;
629 if (dispatch)
630 dispatch->interface->destroy(dispatch);
631
Peter Hutterer6bb15cd2013-08-07 11:04:48 +1000632 if (device->source)
633 wl_event_source_remove(device->source);
Kristian Høgsberg4e55d062013-08-26 14:35:32 -0700634 wl_list_remove(&device->link);
Pekka Paalanena123e5c2012-08-03 14:38:57 +0300635 if (device->mtdev)
636 mtdev_close_delete(device->mtdev);
637 close(device->fd);
Pekka Paalanenbf639ab2012-08-03 14:39:07 +0300638 free(device->devname);
Pekka Paalanena123e5c2012-08-03 14:38:57 +0300639 free(device->devnode);
640 free(device);
641}
642
Pekka Paalanen88594b62012-08-03 14:39:05 +0300643void
Pekka Paalanen3bfb2012012-08-03 14:39:02 +0300644evdev_notify_keyboard_focus(struct weston_seat *seat,
645 struct wl_list *evdev_devices)
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400646{
Pekka Paalanen3eb47612012-08-06 14:57:08 +0300647 struct evdev_device *device;
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400648 struct wl_array keys;
649 unsigned int i, set;
Pekka Paalanend8583512012-08-03 14:39:11 +0300650 char evdev_keys[(KEY_CNT + 7) / 8];
651 char all_keys[(KEY_CNT + 7) / 8];
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400652 uint32_t *k;
653 int ret;
654
Kristian Høgsberge3148752013-05-06 23:19:49 -0400655 if (!seat->keyboard)
Pekka Paalanend8583512012-08-03 14:39:11 +0300656 return;
657
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400658 memset(all_keys, 0, sizeof all_keys);
Pekka Paalanen3bfb2012012-08-03 14:39:02 +0300659 wl_list_for_each(device, evdev_devices, link) {
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400660 memset(evdev_keys, 0, sizeof evdev_keys);
661 ret = ioctl(device->fd,
662 EVIOCGKEY(sizeof evdev_keys), evdev_keys);
663 if (ret < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +0200664 weston_log("failed to get keys for device %s\n",
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400665 device->devnode);
666 continue;
667 }
668 for (i = 0; i < ARRAY_LENGTH(evdev_keys); i++)
669 all_keys[i] |= evdev_keys[i];
670 }
671
672 wl_array_init(&keys);
673 for (i = 0; i < KEY_CNT; i++) {
674 set = all_keys[i >> 3] & (1 << (i & 7));
675 if (set) {
676 k = wl_array_add(&keys, sizeof *k);
677 *k = i;
678 }
679 }
680
Kristian Høgsbergcb3eaae2012-08-10 09:50:11 -0400681 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Kristian Høgsberga00d60f2012-04-10 00:03:30 -0400682
683 wl_array_release(&keys);
684}