ee51e0ef2e628ee9ff4eae464670b3ec39ba801d
[profile/ivi/wayland.git] / evdev.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <linux/input.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6
7 #include <linux/input.h>
8
9 #include "wayland.h"
10
11 struct wl_input_device {
12         struct wl_object base;
13         struct wl_event_source *source;
14         struct wl_display *display;
15         int fd;
16         int tool;
17         int32_t x, y;
18 };
19
20 static const struct wl_method input_device_methods[] = {
21 };
22
23 static const struct wl_interface input_device_interface = {
24         "input_device", 1,
25         ARRAY_LENGTH(input_device_methods),
26         input_device_methods,
27 };
28
29 static void wl_input_device_data(int fd, uint32_t mask, void *data)
30 {
31         struct wl_input_device *device = data;
32         struct input_event ev[8], *e, *end;
33         int len, value, dx, dy, absolute_event;
34
35         dx = 0;
36         dy = 0;
37         absolute_event = 0;
38
39         len = read(fd, &ev, sizeof ev);
40         if (len < 0 || len % sizeof e[0] != 0) {
41                 /* FIXME: handle error... reopen device? */;
42                 return;
43         }
44
45         e = ev;
46         end = (void *) ev + len;
47         for (e = ev; e < end; e++) {
48                 /* Get the signed value, earlier kernels had this as unsigned */
49                 value = e->value;
50
51                 switch (e->type) {
52                 case EV_REL:
53                         switch (e->code) {
54                         case REL_X:
55                                 dx += value;
56                                 break;
57
58                         case REL_Y:
59                                 dy += value;
60                                 break;
61                         }
62                         break;
63
64                 case EV_ABS:
65                         absolute_event = 1;
66                         switch (e->code) {
67                         case ABS_X:
68                                 device->x = value;
69                                 break;
70                         case ABS_Y:
71                                 device->y = value;
72                                 break;
73                         }
74                         break;
75
76                 case EV_KEY:
77                         if (value == 2)
78                                 break;
79
80                         switch (e->code) {
81                         case BTN_TOUCH:
82                         case BTN_TOOL_PEN:
83                         case BTN_TOOL_RUBBER:
84                         case BTN_TOOL_BRUSH:
85                         case BTN_TOOL_PENCIL:
86                         case BTN_TOOL_AIRBRUSH:
87                         case BTN_TOOL_FINGER:
88                         case BTN_TOOL_MOUSE:
89                         case BTN_TOOL_LENS:
90                                 device->tool = value ? e->code : 0;
91                                 break;
92
93                         case BTN_LEFT:
94                                 wl_display_post_button_event(device->display,
95                                                              &device->base, 0, value);
96                                 break;
97
98                         case BTN_RIGHT:
99                                 wl_display_post_button_event(device->display,
100                                                              &device->base, 2, value);
101                                 break;
102
103                         case BTN_MIDDLE:
104                                 wl_display_post_button_event(device->display,
105                                                              &device->base, 1, value);
106                                 break;
107                         }
108                 }
109         }
110
111         if (dx != 0 || dy != 0)
112                 wl_display_post_relative_event(device->display,
113                                                &device->base, dx, dy);
114         if (absolute_event && device->tool)
115                 wl_display_post_absolute_event(device->display,
116                                                &device->base,
117                                                device->x, device->y);
118 }
119
120 struct wl_object *
121 wl_input_device_create(struct wl_display *display,
122                        const char *path, uint32_t id)
123 {
124         struct wl_input_device *device;
125         struct wl_event_loop *loop;
126
127         device = malloc(sizeof *device);
128         if (device == NULL)
129                 return NULL;
130
131         device->base.interface = &input_device_interface;
132         device->display = display;
133         device->tool = 1;
134
135         device->fd = open(path, O_RDONLY);
136         if (device->fd < 0) {
137                 free(device);
138                 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
139                 return NULL;
140         }
141
142         loop = wl_display_get_event_loop(display);
143         device->source = wl_event_loop_add_fd(loop, device->fd,
144                                               WL_EVENT_READABLE,
145                                               wl_input_device_data, device);
146         if (device->source == NULL) {
147                 close(device->fd);
148                 free(device);
149                 return NULL;
150         }
151
152         return &device->base;
153 }