blob: 9df43071d43afac0b9e715a645dd496c056e5ffb [file] [log] [blame]
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -05001#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
11struct 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
20static const struct wl_method input_device_methods[] = {
21};
22
23static const struct wl_interface input_device_interface = {
24 "input_device", 1,
25 ARRAY_LENGTH(input_device_methods),
26 input_device_methods,
27};
28
29static 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
63 case EV_ABS:
64 absolute_event = 1;
65 switch (e->code) {
66 case ABS_X:
67 device->x = value;
68 break;
69 case ABS_Y:
70 device->y = value;
71 break;
72 }
73
74 case EV_KEY:
75 if (value == 2)
76 break;
77
78 switch (e->code) {
79 case BTN_TOUCH:
80 case BTN_TOOL_PEN:
81 case BTN_TOOL_RUBBER:
82 case BTN_TOOL_BRUSH:
83 case BTN_TOOL_PENCIL:
84 case BTN_TOOL_AIRBRUSH:
85 case BTN_TOOL_FINGER:
86 case BTN_TOOL_MOUSE:
87 case BTN_TOOL_LENS:
88 device->tool = value ? e->code : 0;
89 break;
90
91 case BTN_LEFT:
92 wl_display_post_button_event(device->display,
93 &device->base, 0, value);
94 break;
95
96 case BTN_RIGHT:
97 wl_display_post_button_event(device->display,
98 &device->base, 2, value);
99 break;
100
101 case BTN_MIDDLE:
102 wl_display_post_button_event(device->display,
103 &device->base, 1, value);
104 break;
105 }
106 }
107 }
108
109 if (dx != 0 || dy != 0)
110 wl_display_post_relative_event(device->display,
111 &device->base, dx, dy);
112 if (absolute_event && device->tool)
113 wl_display_post_absolute_event(device->display,
114 &device->base,
115 device->x, device->y);
116}
117
118struct wl_object *
119wl_input_device_create(struct wl_display *display,
120 const char *path, uint32_t id)
121{
122 struct wl_input_device *device;
123 struct wl_event_loop *loop;
124
125 device = malloc(sizeof *device);
126 if (device == NULL)
127 return NULL;
128
129 device->base.id = id;
130 device->base.interface = &input_device_interface;
131 device->display = display;
132 device->tool = 1;
133
134 device->fd = open(path, O_RDONLY);
135 if (device->fd < 0) {
136 free(device);
137 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
138 return NULL;
139 }
140
141 loop = wl_display_get_event_loop(display);
142 device->source = wl_event_loop_add_fd(loop, device->fd,
143 WL_EVENT_READABLE,
144 wl_input_device_data, device);
145 if (device->source == NULL) {
146 close(device->fd);
147 free(device);
148 return NULL;
149 }
150
151 return &device->base;
152}