Rename egl-compositor to wayland-system-compositor.
[platform/upstream/libinput.git] / evdev.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <linux/input.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24
25 #include <linux/input.h>
26
27 #include "wayland.h"
28 #include "wayland-system-compositor.h"
29
30 struct evdev_input_device {
31         struct wlsc_input_device *device;
32         struct wl_event_source *source;
33         int tool, new_x, new_y;
34         int base_x, base_y;
35         int fd;
36 };
37
38 static void evdev_input_device_data(int fd, uint32_t mask, void *data)
39 {
40         struct evdev_input_device *device = data;
41         struct input_event ev[8], *e, *end;
42         int len, value, dx, dy, absolute_event;
43         int x, y;
44
45         dx = 0;
46         dy = 0;
47         absolute_event = 0;
48         wlsc_device_get_position(device->device, &x, &y);
49
50         len = read(fd, &ev, sizeof ev);
51         if (len < 0 || len % sizeof e[0] != 0) {
52                 /* FIXME: handle error... reopen device? */;
53                 return;
54         }
55
56         e = ev;
57         end = (void *) ev + len;
58         for (e = ev; e < end; e++) {
59                 /* Get the signed value, earlier kernels had this as unsigned */
60                 value = e->value;
61
62                 switch (e->type) {
63                 case EV_REL:
64                         switch (e->code) {
65                         case REL_X:
66                                 dx += value;
67                                 break;
68
69                         case REL_Y:
70                                 dy += value;
71                                 break;
72                         }
73                         break;
74
75                 case EV_ABS:
76                         absolute_event = 1;
77                         switch (e->code) {
78                         case ABS_X:
79                                 if (device->new_x) {
80                                         device->base_x = x - value;
81                                         device->new_x = 0;
82                                 }
83                                 x = device->base_x + value;
84                                 break;
85                         case ABS_Y:
86                                 if (device->new_y) {
87                                         device->base_y = y - value;
88                                         device->new_y = 0;
89                                 }
90                                 y = device->base_y + value;
91                                 break;
92                         }
93                         break;
94
95                 case EV_KEY:
96                         if (value == 2)
97                                 break;
98
99                         switch (e->code) {
100                         case BTN_TOUCH:
101                         case BTN_TOOL_PEN:
102                         case BTN_TOOL_RUBBER:
103                         case BTN_TOOL_BRUSH:
104                         case BTN_TOOL_PENCIL:
105                         case BTN_TOOL_AIRBRUSH:
106                         case BTN_TOOL_FINGER:
107                         case BTN_TOOL_MOUSE:
108                         case BTN_TOOL_LENS:
109                                 if (device->tool == 0 && value) {
110                                         device->new_x = 1;
111                                         device->new_y = 1;
112                                 }
113                                 device->tool = value ? e->code : 0;
114                                 break;
115
116                         case BTN_LEFT:
117                         case BTN_RIGHT:
118                         case BTN_MIDDLE:
119                         case BTN_SIDE:
120                         case BTN_EXTRA:
121                         case BTN_FORWARD:
122                         case BTN_BACK:
123                         case BTN_TASK:
124                                 notify_button(device->device, e->code, value);
125                                 break;
126
127                         default:
128                                 notify_key(device->device, e->code, value);
129                                 break;
130                         }
131                 }
132         }
133
134         if (dx != 0 || dy != 0)
135                 notify_motion(device->device, x + dx, y + dy);
136         if (absolute_event && device->tool)
137                 notify_motion(device->device, x, y);
138 }
139
140 struct evdev_input_device *
141 evdev_input_device_create(struct wlsc_input_device *master,
142                           struct wl_display *display, const char *path)
143 {
144         struct evdev_input_device *device;
145         struct wl_event_loop *loop;
146
147         device = malloc(sizeof *device);
148         if (device == NULL)
149                 return NULL;
150
151         device->tool = 1;
152         device->new_x = 1;
153         device->new_y = 1;
154         device->device = master;
155
156         device->fd = open(path, O_RDONLY);
157         if (device->fd < 0) {
158                 free(device);
159                 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
160                 return NULL;
161         }
162
163         loop = wl_display_get_event_loop(display);
164         device->source = wl_event_loop_add_fd(loop, device->fd,
165                                               WL_EVENT_READABLE,
166                                               evdev_input_device_data, device);
167         if (device->source == NULL) {
168                 close(device->fd);
169                 free(device);
170                 return NULL;
171         }
172
173         return device;
174 }