blob: 8efff0f035ba1e0a23458cc3613655c5c95b1cf9 [file] [log] [blame]
Dennis Kempina9963ba2012-06-08 10:32:23 -07001/*
2 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
Dennis Kempin320aef12012-06-11 15:26:52 -07006#include <libevdev/libevdev.h>
Dennis Kempina9963ba2012-06-08 10:32:23 -07007
8#include <errno.h>
9#include <fcntl.h>
10#include <linux/input.h>
11#include <stdio.h>
12#include <time.h>
13#include <unistd.h>
14
Dennis Kempin320aef12012-06-11 15:26:52 -070015#include <libevdev/libevdev_event.h>
16#include <libevdev/libevdev_log.h>
17#include <libevdev/libevdev_util.h>
Dennis Kempina9963ba2012-06-08 10:32:23 -070018
19/* Number of events to attempt to read from kernel on each SIGIO */
20#define NUM_EVENTS 16
21
22#ifndef EVIOCGMTSLOTS
23#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
24#endif
25
26/* Set clockid to be used for timestamps */
27#ifndef EVIOCSCLOCKID
28#define EVIOCSCLOCKID _IOW('E', 0xa0, int)
29#endif
30
31static void Absinfo_Print(EvdevPtr device, struct input_absinfo*);
32static const char* Event_Property_To_String(int type);
Che-Liang Chioub9fc9732012-11-26 15:49:02 -080033static EvdevClass EvdevProbeClass(EvdevInfoPtr info);
34static const char* EvdevClassToString(EvdevClass cls);
Dennis Kempina9963ba2012-06-08 10:32:23 -070035
36int EvdevOpen(EvdevPtr evdev, const char* device) {
37 evdev->fd = open(device, O_RDWR | O_NONBLOCK, 0);
38 return evdev->fd;
39}
40
41int EvdevClose(EvdevPtr evdev) {
42 close(evdev->fd);
43 evdev->fd = -1;
44 return evdev->fd;
45}
46
47int EvdevRead(EvdevPtr evdev) {
48 struct input_event ev[NUM_EVENTS];
Andrew de los Reyesec028842012-08-16 18:08:12 -070049 EventStatePtr evstate = evdev->evstate;
Dennis Kempina9963ba2012-06-08 10:32:23 -070050 int i;
51 int len;
52 bool sync_evdev_state = false;
53
54 do {
55 len = read(evdev->fd, &ev, sizeof(ev));
56 if (len <= 0)
57 return errno;
58
Andrew de los Reyesec028842012-08-16 18:08:12 -070059 /* Read as many whole struct input_event objects as we can into the
60 circular buffer */
61 if (evstate->debug_buf) {
62 for (i = 0; i < len / sizeof(*ev); i++) {
63 evstate->debug_buf[evstate->debug_buf_tail] = ev[i];
64 evstate->debug_buf_tail =
65 (evstate->debug_buf_tail + 1) % DEBUG_BUF_SIZE;
66 }
67 }
68
Dennis Kempina9963ba2012-06-08 10:32:23 -070069 /* kernel always delivers complete events, so len must be sizeof *ev */
70 if (len % sizeof(*ev))
71 return errno;
72
73 /* Process events ... */
74 for (i = 0; i < len / sizeof(ev[0]); i++) {
75 if (sync_evdev_state)
76 break;
77 if (timercmp(&ev[i].time, &evdev->before_sync_time, <)) {
78 /* Ignore events before last sync time */
79 continue;
80 } else if (timercmp(&ev[i].time, &evdev->after_sync_time, >)) {
81 /* Event_Process returns TRUE if SYN_DROPPED detected */
82 sync_evdev_state = Event_Process(evdev, &ev[i]);
83 } else {
84 /* If the event occurred during sync, then sync again */
85 sync_evdev_state = true;
86 }
87 }
88
89 } while (len == sizeof(ev));
90 /* Keep reading if kernel supplied NUM_EVENTS events. */
91
92 if (sync_evdev_state)
93 Event_Sync_State(evdev);
94
95 return Success;
96}
97
98int EvdevProbe(EvdevPtr device) {
99 int len, i;
100 int fd;
101 EvdevInfoPtr info;
102
103 fd = device->fd;
104 info = &device->info;
105 if (ioctl(fd, EVIOCGID, &info->id) < 0) {
106 LOG_ERROR(device, "ioctl EVIOCGID failed: %s\n", strerror(errno));
107 return !Success;
108 }
109
110 if (ioctl(fd, EVIOCGNAME(sizeof(info->name) - 1),
111 info->name) < 0) {
112 LOG_ERROR(device, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
113 return !Success;
114 }
115
116 len = ioctl(fd, EVIOCGPROP(sizeof(info->prop_bitmask)),
117 info->prop_bitmask);
118 if (len < 0) {
119 LOG_ERROR(device, "ioctl EVIOCGPROP failed: %s\n", strerror(errno));
120 return !Success;
121 }
122 for (i = 0; i < len*8; i++) {
123 if (TestBit(i, info->prop_bitmask))
124 LOG_DEBUG(device, "Has Property: %d (%s)\n", i,
125 Event_Property_To_String(i));
126 }
127
128 len = ioctl(fd, EVIOCGBIT(0, sizeof(info->bitmask)),
129 info->bitmask);
130 if (len < 0) {
131 LOG_ERROR(device, "ioctl EVIOCGBIT failed: %s\n",
132 strerror(errno));
133 return !Success;
134 }
135 for (i = 0; i < len*8; i++) {
136 if (TestBit(i, info->bitmask))
137 LOG_DEBUG(device, "Has Event Type %d = %s\n", i,
138 Event_Type_To_String(i));
139 }
140
141 len = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info->key_bitmask)),
142 info->key_bitmask);
143 if (len < 0) {
144 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_KEY) failed: %s\n",
145 strerror(errno));
146 return !Success;
147 }
148 for (i = 0; i < len*8; i++) {
149 if (TestBit(i, info->key_bitmask))
150 LOG_DEBUG(device, "Has KEY[%d] = %s\n", i,
151 Event_To_String(EV_KEY, i));
152 }
153
154 len = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(info->led_bitmask)),
155 info->led_bitmask);
156 if (len < 0) {
157 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_LED) failed: %s\n",
158 strerror(errno));
159 return !Success;
160 }
161 for (i = 0; i < len*8; i++) {
162 if (TestBit(i, info->led_bitmask))
163 LOG_DEBUG(device, "Has LED[%d] = %s\n", i,
164 Event_To_String(EV_LED, i));
165 }
166
167 len = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(info->rel_bitmask)),
168 info->rel_bitmask);
169 if (len < 0) {
170 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_REL) failed: %s\n",
171 strerror(errno));
172 return !Success;
173 }
174 for (i = 0; i < len*8; i++) {
175 if (TestBit(i, info->rel_bitmask))
176 LOG_DEBUG(device, "Has REL[%d] = %s\n", i,
177 Event_To_String(EV_REL, i));
178 }
179
Dennis Kempina9963ba2012-06-08 10:32:23 -0700180 len = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(info->abs_bitmask)),
181 info->abs_bitmask);
182 if (len < 0) {
183 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_ABS) failed: %s\n",
184 strerror(errno));
185 return !Success;
186 }
187
188 for (i = ABS_X; i <= ABS_MAX; i++) {
189 if (TestBit(i, info->abs_bitmask)) {
190 struct input_absinfo* absinfo = &info->absinfo[i];
191 LOG_DEBUG(device, "Has ABS[%d] = %s\n", i,
192 Event_To_String(EV_ABS, i));
193 len = ioctl(fd, EVIOCGABS(i), absinfo);
194 if (len < 0) {
195 LOG_ERROR(device, "ioctl EVIOCGABS(%d) failed: %s\n", i,
196 strerror(errno));
197 return !Success;
198 }
199
200 Absinfo_Print(device, absinfo);
201 }
202 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800203
204 info->evdev_class = EvdevProbeClass(info);
205 LOG_DEBUG(device, "Has evdev device class = %s\n",
206 EvdevClassToString(info->evdev_class));
207 if (info->evdev_class == EvdevClassUnknown) {
208 LOG_ERROR(device, "Couldn't determine evdev class\n");
209 return !Success;
210 }
211
Dennis Kempina9963ba2012-06-08 10:32:23 -0700212 return Success;
213}
214
215int EvdevProbeAbsinfo(EvdevPtr device, size_t key) {
216 struct input_absinfo* absinfo;
217
218 absinfo = &device->info.absinfo[key];
219 if (ioctl(device->fd, EVIOCGABS(key), absinfo) < 0) {
Daniel Kurtz0d097082012-09-07 22:27:51 +0800220 LOG_ERROR(device, "ioctl EVIOCGABS(%zu) failed: %s\n", key,
Dennis Kempina9963ba2012-06-08 10:32:23 -0700221 strerror(errno));
222 return !Success;
223 } else {
224 return Success;
225 }
226}
227
Chung-yih Wang8b2fa0a2012-07-23 16:49:10 +0800228/*
229 * Check if the device is a single-pressure one which reports ABS_PRESSURE only.
230 */
231int EvdevIsSinglePressureDevice(EvdevPtr device) {
232 EvdevInfoPtr info = &device->info;
233
Chung-yih Wangaf883df2012-08-28 17:31:57 +0800234 return (!TestBit(ABS_MT_PRESSURE, info->abs_bitmask) &&
235 TestBit(ABS_PRESSURE, info->abs_bitmask));
Chung-yih Wang8b2fa0a2012-07-23 16:49:10 +0800236}
237
Dennis Kempina9963ba2012-06-08 10:32:23 -0700238int EvdevProbeMTSlot(EvdevPtr device, MTSlotInfoPtr req) {
Dennis Kempine9cc2642012-06-25 11:52:24 -0700239 if (ioctl(device->fd, EVIOCGMTSLOTS((sizeof(*req))), req) < 0) {
Dennis Kempina9963ba2012-06-08 10:32:23 -0700240 LOG_ERROR(device, "ioctl EVIOCGMTSLOTS(req.code=%d) failed: %s\n",
Dennis Kempine9cc2642012-06-25 11:52:24 -0700241 req->code, strerror(errno));
Dennis Kempina9963ba2012-06-08 10:32:23 -0700242 return !Success;
243 } else {
244 return Success;
245 }
246}
247
248int EvdevProbeKeyState(EvdevPtr device) {
249 int len = sizeof(device->key_state_bitmask);
250
251 memset(device->key_state_bitmask, 0, len);
252 if (ioctl(device->fd, EVIOCGKEY(len), device->key_state_bitmask) < 0) {
253 LOG_ERROR(device, "ioctl EVIOCGKEY failed: %s\n", strerror(errno));
254 return !Success;
255 } else {
256 return Success;
257 }
258}
259
260int EvdevEnableMonotonic(EvdevPtr device) {
261 unsigned int clk = CLOCK_MONOTONIC;
262 return (ioctl(device->fd, EVIOCSCLOCKID, &clk) == 0) ? Success : !Success;
263}
264
265
266static const char*
267Event_Property_To_String(int type) {
268 switch (type) {
269 case INPUT_PROP_POINTER: return "POINTER"; /* needs a pointer */
270 case INPUT_PROP_DIRECT: return "DIRECT"; /* direct input devices */
271 case INPUT_PROP_BUTTONPAD: return "BUTTONPAD"; /* has button under pad */
272 case INPUT_PROP_SEMI_MT: return "SEMI_MT"; /* touch rectangle only */
273 default: return "?";
274 }
275}
276
277static void
278Absinfo_Print(EvdevPtr device, struct input_absinfo* absinfo)
279{
280 LOG_DEBUG(device, " min = %d\n", absinfo->minimum);
281 LOG_DEBUG(device, " max = %d\n", absinfo->maximum);
282 if (absinfo->fuzz)
283 LOG_DEBUG(device, " fuzz = %d\n", absinfo->fuzz);
284 if (absinfo->resolution)
285 LOG_DEBUG(device, " res = %d\n", absinfo->resolution);
286}
287
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800288/*
289 * Heuristics for determining evdev device class; similar to those of
290 * xf86-input-evdev.
291 */
292static EvdevClass EvdevProbeClass(EvdevInfoPtr info) {
293 int bit;
294 for (bit = 0; bit < BTN_MISC; bit++)
295 if (TestBit(bit, info->key_bitmask))
296 return EvdevClassKeyboard;
297
298 if (TestBit(REL_X, info->rel_bitmask) &&
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800299 TestBit(REL_Y, info->rel_bitmask)) {
300 if (TestBit(ABS_MT_POSITION_X, info->abs_bitmask) &&
301 TestBit(ABS_MT_POSITION_Y, info->abs_bitmask))
302 return EvdevClassMultitouchMouse;
303 else
304 return EvdevClassMouse;
305 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800306
307 if (TestBit(ABS_X, info->abs_bitmask) &&
308 TestBit(ABS_Y, info->abs_bitmask)) {
309
310 if (TestBit(BTN_TOOL_PEN, info->key_bitmask) ||
311 TestBit(BTN_STYLUS, info->key_bitmask) ||
312 TestBit(BTN_STYLUS2, info->key_bitmask))
313 return EvdevClassTablet;
314
315 if (TestBit(ABS_PRESSURE, info->abs_bitmask) ||
316 TestBit(BTN_TOUCH, info->key_bitmask)) {
317 if (TestBit(BTN_LEFT, info->key_bitmask) ||
318 TestBit(BTN_MIDDLE, info->key_bitmask) ||
319 TestBit(BTN_RIGHT, info->key_bitmask) ||
320 TestBit(BTN_TOOL_FINGER, info->key_bitmask))
321 return EvdevClassTouchpad;
322 else
323 return EvdevClassTouchscreen;
324 }
325
326 /* Some touchscreens use BTN_LEFT rather than BTN_TOUCH */
327 if (TestBit(BTN_LEFT, info->key_bitmask))
328 return EvdevClassTouchscreen;
329 }
330
331 return EvdevClassUnknown;
332}
333
334static const char* EvdevClassToString(EvdevClass cls) {
335 switch (cls) {
336 case EvdevClassUnknown: return "EvdevClassUnknown";
337 case EvdevClassKeyboard: return "EvdevClassKeyboard";
338 case EvdevClassMouse: return "EvdevClassMouse";
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800339 case EvdevClassMultitouchMouse: return "EvdevClassMultitouchMouse";
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800340 case EvdevClassTablet: return "EvdevClassTablet";
341 case EvdevClassTouchpad: return "EvdevClassTouchpad";
342 case EvdevClassTouchscreen: return "EvdevClassTouchscreen";
343 }
344 return "Unhandled Evdev Class";
345}