blob: c0e5011325ae73e21a06c0535a5ec739af349954 [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 Kempin69c91ed2013-02-12 14:53:10 -080035static int EvdevWriteBitmask(FILE* fp, const char* name,
36 unsigned long* bitmask, size_t num_bytes);
Dennis Kempina9963ba2012-06-08 10:32:23 -070037
38int EvdevOpen(EvdevPtr evdev, const char* device) {
39 evdev->fd = open(device, O_RDWR | O_NONBLOCK, 0);
40 return evdev->fd;
41}
42
43int EvdevClose(EvdevPtr evdev) {
44 close(evdev->fd);
45 evdev->fd = -1;
46 return evdev->fd;
47}
48
49int EvdevRead(EvdevPtr evdev) {
50 struct input_event ev[NUM_EVENTS];
Andrew de los Reyesec028842012-08-16 18:08:12 -070051 EventStatePtr evstate = evdev->evstate;
Dennis Kempina9963ba2012-06-08 10:32:23 -070052 int i;
53 int len;
54 bool sync_evdev_state = false;
55
56 do {
57 len = read(evdev->fd, &ev, sizeof(ev));
58 if (len <= 0)
59 return errno;
60
Andrew de los Reyesec028842012-08-16 18:08:12 -070061 /* Read as many whole struct input_event objects as we can into the
62 circular buffer */
63 if (evstate->debug_buf) {
64 for (i = 0; i < len / sizeof(*ev); i++) {
65 evstate->debug_buf[evstate->debug_buf_tail] = ev[i];
66 evstate->debug_buf_tail =
67 (evstate->debug_buf_tail + 1) % DEBUG_BUF_SIZE;
68 }
69 }
70
Dennis Kempina9963ba2012-06-08 10:32:23 -070071 /* kernel always delivers complete events, so len must be sizeof *ev */
72 if (len % sizeof(*ev))
73 return errno;
74
75 /* Process events ... */
76 for (i = 0; i < len / sizeof(ev[0]); i++) {
77 if (sync_evdev_state)
78 break;
79 if (timercmp(&ev[i].time, &evdev->before_sync_time, <)) {
80 /* Ignore events before last sync time */
81 continue;
82 } else if (timercmp(&ev[i].time, &evdev->after_sync_time, >)) {
83 /* Event_Process returns TRUE if SYN_DROPPED detected */
84 sync_evdev_state = Event_Process(evdev, &ev[i]);
85 } else {
86 /* If the event occurred during sync, then sync again */
87 sync_evdev_state = true;
88 }
89 }
90
91 } while (len == sizeof(ev));
92 /* Keep reading if kernel supplied NUM_EVENTS events. */
93
94 if (sync_evdev_state)
95 Event_Sync_State(evdev);
96
97 return Success;
98}
99
100int EvdevProbe(EvdevPtr device) {
101 int len, i;
102 int fd;
103 EvdevInfoPtr info;
104
105 fd = device->fd;
106 info = &device->info;
107 if (ioctl(fd, EVIOCGID, &info->id) < 0) {
108 LOG_ERROR(device, "ioctl EVIOCGID failed: %s\n", strerror(errno));
109 return !Success;
110 }
111
112 if (ioctl(fd, EVIOCGNAME(sizeof(info->name) - 1),
113 info->name) < 0) {
114 LOG_ERROR(device, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
115 return !Success;
116 }
117
118 len = ioctl(fd, EVIOCGPROP(sizeof(info->prop_bitmask)),
119 info->prop_bitmask);
120 if (len < 0) {
121 LOG_ERROR(device, "ioctl EVIOCGPROP failed: %s\n", strerror(errno));
122 return !Success;
123 }
124 for (i = 0; i < len*8; i++) {
125 if (TestBit(i, info->prop_bitmask))
126 LOG_DEBUG(device, "Has Property: %d (%s)\n", i,
127 Event_Property_To_String(i));
128 }
129
130 len = ioctl(fd, EVIOCGBIT(0, sizeof(info->bitmask)),
131 info->bitmask);
132 if (len < 0) {
133 LOG_ERROR(device, "ioctl EVIOCGBIT failed: %s\n",
134 strerror(errno));
135 return !Success;
136 }
137 for (i = 0; i < len*8; i++) {
138 if (TestBit(i, info->bitmask))
139 LOG_DEBUG(device, "Has Event Type %d = %s\n", i,
140 Event_Type_To_String(i));
141 }
142
143 len = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info->key_bitmask)),
144 info->key_bitmask);
145 if (len < 0) {
146 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_KEY) failed: %s\n",
147 strerror(errno));
148 return !Success;
149 }
150 for (i = 0; i < len*8; i++) {
151 if (TestBit(i, info->key_bitmask))
152 LOG_DEBUG(device, "Has KEY[%d] = %s\n", i,
153 Event_To_String(EV_KEY, i));
154 }
155
156 len = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(info->led_bitmask)),
157 info->led_bitmask);
158 if (len < 0) {
159 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_LED) failed: %s\n",
160 strerror(errno));
161 return !Success;
162 }
163 for (i = 0; i < len*8; i++) {
164 if (TestBit(i, info->led_bitmask))
165 LOG_DEBUG(device, "Has LED[%d] = %s\n", i,
166 Event_To_String(EV_LED, i));
167 }
168
169 len = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(info->rel_bitmask)),
170 info->rel_bitmask);
171 if (len < 0) {
172 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_REL) failed: %s\n",
173 strerror(errno));
174 return !Success;
175 }
176 for (i = 0; i < len*8; i++) {
177 if (TestBit(i, info->rel_bitmask))
178 LOG_DEBUG(device, "Has REL[%d] = %s\n", i,
179 Event_To_String(EV_REL, i));
180 }
181
Dennis Kempina9963ba2012-06-08 10:32:23 -0700182 len = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(info->abs_bitmask)),
183 info->abs_bitmask);
184 if (len < 0) {
185 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_ABS) failed: %s\n",
186 strerror(errno));
187 return !Success;
188 }
189
190 for (i = ABS_X; i <= ABS_MAX; i++) {
191 if (TestBit(i, info->abs_bitmask)) {
192 struct input_absinfo* absinfo = &info->absinfo[i];
193 LOG_DEBUG(device, "Has ABS[%d] = %s\n", i,
194 Event_To_String(EV_ABS, i));
195 len = ioctl(fd, EVIOCGABS(i), absinfo);
196 if (len < 0) {
197 LOG_ERROR(device, "ioctl EVIOCGABS(%d) failed: %s\n", i,
198 strerror(errno));
199 return !Success;
200 }
201
202 Absinfo_Print(device, absinfo);
203 }
204 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800205
206 info->evdev_class = EvdevProbeClass(info);
207 LOG_DEBUG(device, "Has evdev device class = %s\n",
208 EvdevClassToString(info->evdev_class));
209 if (info->evdev_class == EvdevClassUnknown) {
210 LOG_ERROR(device, "Couldn't determine evdev class\n");
211 return !Success;
212 }
213
Dennis Kempina9963ba2012-06-08 10:32:23 -0700214 return Success;
215}
216
217int EvdevProbeAbsinfo(EvdevPtr device, size_t key) {
218 struct input_absinfo* absinfo;
219
220 absinfo = &device->info.absinfo[key];
221 if (ioctl(device->fd, EVIOCGABS(key), absinfo) < 0) {
Daniel Kurtz0d097082012-09-07 22:27:51 +0800222 LOG_ERROR(device, "ioctl EVIOCGABS(%zu) failed: %s\n", key,
Dennis Kempina9963ba2012-06-08 10:32:23 -0700223 strerror(errno));
224 return !Success;
225 } else {
226 return Success;
227 }
228}
229
Chung-yih Wang8b2fa0a2012-07-23 16:49:10 +0800230/*
231 * Check if the device is a single-pressure one which reports ABS_PRESSURE only.
232 */
233int EvdevIsSinglePressureDevice(EvdevPtr device) {
234 EvdevInfoPtr info = &device->info;
235
Chung-yih Wangaf883df2012-08-28 17:31:57 +0800236 return (!TestBit(ABS_MT_PRESSURE, info->abs_bitmask) &&
237 TestBit(ABS_PRESSURE, info->abs_bitmask));
Chung-yih Wang8b2fa0a2012-07-23 16:49:10 +0800238}
239
Dennis Kempina9963ba2012-06-08 10:32:23 -0700240int EvdevProbeMTSlot(EvdevPtr device, MTSlotInfoPtr req) {
Dennis Kempine9cc2642012-06-25 11:52:24 -0700241 if (ioctl(device->fd, EVIOCGMTSLOTS((sizeof(*req))), req) < 0) {
Dennis Kempina9963ba2012-06-08 10:32:23 -0700242 LOG_ERROR(device, "ioctl EVIOCGMTSLOTS(req.code=%d) failed: %s\n",
Dennis Kempine9cc2642012-06-25 11:52:24 -0700243 req->code, strerror(errno));
Dennis Kempina9963ba2012-06-08 10:32:23 -0700244 return !Success;
245 } else {
246 return Success;
247 }
248}
249
250int EvdevProbeKeyState(EvdevPtr device) {
251 int len = sizeof(device->key_state_bitmask);
252
253 memset(device->key_state_bitmask, 0, len);
254 if (ioctl(device->fd, EVIOCGKEY(len), device->key_state_bitmask) < 0) {
255 LOG_ERROR(device, "ioctl EVIOCGKEY failed: %s\n", strerror(errno));
256 return !Success;
257 } else {
258 return Success;
259 }
260}
261
262int EvdevEnableMonotonic(EvdevPtr device) {
263 unsigned int clk = CLOCK_MONOTONIC;
264 return (ioctl(device->fd, EVIOCSCLOCKID, &clk) == 0) ? Success : !Success;
265}
266
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800267int EvdevWriteInfoToFile(FILE* fp, const EvdevInfoPtr info) {
268 int ret;
269
270 ret = fprintf(fp, "# device: %s\n", info->name);
271 if (ret <= 0)
272 return ret;
273
274 for (int i = ABS_X; i <= ABS_MAX; i++) {
275 if (TestBit(i, info->abs_bitmask)) {
276 struct input_absinfo* abs = &info->absinfo[i];
277 ret = fprintf(fp, "# absinfo: %d %d %d %d %d %d\n",
278 i, abs->minimum, abs->maximum,
279 abs->fuzz, abs->flat, abs->resolution);
280 if (ret <= 0)
281 return ret;
282 }
283 }
284
285 ret = EvdevWriteBitmask(fp, "bit", info->bitmask, sizeof(info->bitmask));
286 if (ret <= 0)
287 return ret;
288
289 ret = EvdevWriteBitmask(fp, "key", info->key_bitmask,
290 sizeof(info->key_bitmask));
291 if (ret <= 0)
292 return ret;
293
294 ret = EvdevWriteBitmask(fp, "rel", info->rel_bitmask,
295 sizeof(info->rel_bitmask));
296 if (ret <= 0)
297 return ret;
298
299 ret = EvdevWriteBitmask(fp, "abs", info->abs_bitmask,
300 sizeof(info->abs_bitmask));
301 if (ret <= 0)
302 return ret;
303
304 ret = EvdevWriteBitmask(fp, "led", info->led_bitmask,
305 sizeof(info->led_bitmask));
306 if (ret <= 0)
307 return ret;
308
309 ret = EvdevWriteBitmask(fp, "prp", info->prop_bitmask,
310 sizeof(info->prop_bitmask));
311 if (ret <= 0)
312 return ret;
313
314 return 1;
315}
316
317int EvdevWriteEventToFile(FILE* fp, const struct input_event* ev) {
318 return fprintf(fp, "E: %lu.%06u %04x %04x %d\n",
319 ev->time.tv_sec, (unsigned)ev->time.tv_usec,
320 ev->type, ev->code, ev->value);
321}
322
323static int EvdevWriteBitmask(FILE* fp, const char* name,
324 unsigned long* bitmask, size_t num_bytes) {
325 int ret;
326
327 unsigned char* bytes = (unsigned char*)bitmask;
328 ret = fprintf(fp, "# %s:", name);
329 if (ret <= 0)
330 return ret;
331
332 for (int i = 0; i < num_bytes; ++i) {
333 ret = fprintf(fp, " %02X", bytes[i]);
334 if (ret <= 0)
335 return ret;
336 }
337 ret = fprintf(fp, "\n");
338 return ret;
339}
Dennis Kempina9963ba2012-06-08 10:32:23 -0700340
341static const char*
342Event_Property_To_String(int type) {
343 switch (type) {
344 case INPUT_PROP_POINTER: return "POINTER"; /* needs a pointer */
345 case INPUT_PROP_DIRECT: return "DIRECT"; /* direct input devices */
346 case INPUT_PROP_BUTTONPAD: return "BUTTONPAD"; /* has button under pad */
347 case INPUT_PROP_SEMI_MT: return "SEMI_MT"; /* touch rectangle only */
348 default: return "?";
349 }
350}
351
352static void
353Absinfo_Print(EvdevPtr device, struct input_absinfo* absinfo)
354{
355 LOG_DEBUG(device, " min = %d\n", absinfo->minimum);
356 LOG_DEBUG(device, " max = %d\n", absinfo->maximum);
357 if (absinfo->fuzz)
358 LOG_DEBUG(device, " fuzz = %d\n", absinfo->fuzz);
359 if (absinfo->resolution)
360 LOG_DEBUG(device, " res = %d\n", absinfo->resolution);
361}
362
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800363/*
364 * Heuristics for determining evdev device class; similar to those of
365 * xf86-input-evdev.
366 */
367static EvdevClass EvdevProbeClass(EvdevInfoPtr info) {
368 int bit;
369 for (bit = 0; bit < BTN_MISC; bit++)
370 if (TestBit(bit, info->key_bitmask))
371 return EvdevClassKeyboard;
372
373 if (TestBit(REL_X, info->rel_bitmask) &&
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800374 TestBit(REL_Y, info->rel_bitmask)) {
375 if (TestBit(ABS_MT_POSITION_X, info->abs_bitmask) &&
376 TestBit(ABS_MT_POSITION_Y, info->abs_bitmask))
377 return EvdevClassMultitouchMouse;
378 else
379 return EvdevClassMouse;
380 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800381
382 if (TestBit(ABS_X, info->abs_bitmask) &&
383 TestBit(ABS_Y, info->abs_bitmask)) {
384
385 if (TestBit(BTN_TOOL_PEN, info->key_bitmask) ||
386 TestBit(BTN_STYLUS, info->key_bitmask) ||
387 TestBit(BTN_STYLUS2, info->key_bitmask))
388 return EvdevClassTablet;
389
390 if (TestBit(ABS_PRESSURE, info->abs_bitmask) ||
391 TestBit(BTN_TOUCH, info->key_bitmask)) {
392 if (TestBit(BTN_LEFT, info->key_bitmask) ||
393 TestBit(BTN_MIDDLE, info->key_bitmask) ||
394 TestBit(BTN_RIGHT, info->key_bitmask) ||
395 TestBit(BTN_TOOL_FINGER, info->key_bitmask))
396 return EvdevClassTouchpad;
397 else
398 return EvdevClassTouchscreen;
399 }
400
401 /* Some touchscreens use BTN_LEFT rather than BTN_TOUCH */
402 if (TestBit(BTN_LEFT, info->key_bitmask))
403 return EvdevClassTouchscreen;
404 }
405
406 return EvdevClassUnknown;
407}
408
409static const char* EvdevClassToString(EvdevClass cls) {
410 switch (cls) {
411 case EvdevClassUnknown: return "EvdevClassUnknown";
412 case EvdevClassKeyboard: return "EvdevClassKeyboard";
413 case EvdevClassMouse: return "EvdevClassMouse";
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800414 case EvdevClassMultitouchMouse: return "EvdevClassMultitouchMouse";
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800415 case EvdevClassTablet: return "EvdevClassTablet";
416 case EvdevClassTouchpad: return "EvdevClassTouchpad";
417 case EvdevClassTouchscreen: return "EvdevClassTouchscreen";
418 }
419 return "Unhandled Evdev Class";
420}