blob: a57ff943e5bd2e1d958e28badf97434cf3e9ade8 [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
Dennis Kempin0e265392013-02-22 12:59:03 -080031static int EvdevWriteBitmask(FILE* fp, const char* name,
32 unsigned long* bitmask, size_t num_bytes);
33static int EvdevReadBitmask(FILE* fp, const char* expected_name,
34 unsigned long* bitmask, size_t num_bytes);
35
36#ifndef EVDEV_HOLLOW
37
Dennis Kempina9963ba2012-06-08 10:32:23 -070038static void Absinfo_Print(EvdevPtr device, struct input_absinfo*);
39static const char* Event_Property_To_String(int type);
Che-Liang Chioub9fc9732012-11-26 15:49:02 -080040static EvdevClass EvdevProbeClass(EvdevInfoPtr info);
41static const char* EvdevClassToString(EvdevClass cls);
Dennis Kempina9963ba2012-06-08 10:32:23 -070042
43int EvdevOpen(EvdevPtr evdev, const char* device) {
44 evdev->fd = open(device, O_RDWR | O_NONBLOCK, 0);
45 return evdev->fd;
46}
47
48int EvdevClose(EvdevPtr evdev) {
49 close(evdev->fd);
50 evdev->fd = -1;
51 return evdev->fd;
52}
53
54int EvdevRead(EvdevPtr evdev) {
55 struct input_event ev[NUM_EVENTS];
Andrew de los Reyesec028842012-08-16 18:08:12 -070056 EventStatePtr evstate = evdev->evstate;
Dennis Kempina9963ba2012-06-08 10:32:23 -070057 int i;
58 int len;
59 bool sync_evdev_state = false;
60
61 do {
62 len = read(evdev->fd, &ev, sizeof(ev));
63 if (len <= 0)
64 return errno;
65
Andrew de los Reyesec028842012-08-16 18:08:12 -070066 /* Read as many whole struct input_event objects as we can into the
67 circular buffer */
68 if (evstate->debug_buf) {
69 for (i = 0; i < len / sizeof(*ev); i++) {
70 evstate->debug_buf[evstate->debug_buf_tail] = ev[i];
71 evstate->debug_buf_tail =
72 (evstate->debug_buf_tail + 1) % DEBUG_BUF_SIZE;
73 }
74 }
75
Dennis Kempina9963ba2012-06-08 10:32:23 -070076 /* kernel always delivers complete events, so len must be sizeof *ev */
77 if (len % sizeof(*ev))
78 return errno;
79
80 /* Process events ... */
81 for (i = 0; i < len / sizeof(ev[0]); i++) {
82 if (sync_evdev_state)
83 break;
84 if (timercmp(&ev[i].time, &evdev->before_sync_time, <)) {
85 /* Ignore events before last sync time */
86 continue;
87 } else if (timercmp(&ev[i].time, &evdev->after_sync_time, >)) {
88 /* Event_Process returns TRUE if SYN_DROPPED detected */
89 sync_evdev_state = Event_Process(evdev, &ev[i]);
90 } else {
91 /* If the event occurred during sync, then sync again */
92 sync_evdev_state = true;
93 }
94 }
95
96 } while (len == sizeof(ev));
97 /* Keep reading if kernel supplied NUM_EVENTS events. */
98
99 if (sync_evdev_state)
100 Event_Sync_State(evdev);
101
102 return Success;
103}
104
105int EvdevProbe(EvdevPtr device) {
106 int len, i;
107 int fd;
108 EvdevInfoPtr info;
109
110 fd = device->fd;
111 info = &device->info;
112 if (ioctl(fd, EVIOCGID, &info->id) < 0) {
113 LOG_ERROR(device, "ioctl EVIOCGID failed: %s\n", strerror(errno));
114 return !Success;
115 }
116
117 if (ioctl(fd, EVIOCGNAME(sizeof(info->name) - 1),
118 info->name) < 0) {
119 LOG_ERROR(device, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
120 return !Success;
121 }
122
123 len = ioctl(fd, EVIOCGPROP(sizeof(info->prop_bitmask)),
124 info->prop_bitmask);
125 if (len < 0) {
126 LOG_ERROR(device, "ioctl EVIOCGPROP failed: %s\n", strerror(errno));
127 return !Success;
128 }
129 for (i = 0; i < len*8; i++) {
130 if (TestBit(i, info->prop_bitmask))
131 LOG_DEBUG(device, "Has Property: %d (%s)\n", i,
132 Event_Property_To_String(i));
133 }
134
135 len = ioctl(fd, EVIOCGBIT(0, sizeof(info->bitmask)),
136 info->bitmask);
137 if (len < 0) {
138 LOG_ERROR(device, "ioctl EVIOCGBIT failed: %s\n",
139 strerror(errno));
140 return !Success;
141 }
142 for (i = 0; i < len*8; i++) {
143 if (TestBit(i, info->bitmask))
144 LOG_DEBUG(device, "Has Event Type %d = %s\n", i,
145 Event_Type_To_String(i));
146 }
147
148 len = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info->key_bitmask)),
149 info->key_bitmask);
150 if (len < 0) {
151 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_KEY) failed: %s\n",
152 strerror(errno));
153 return !Success;
154 }
155 for (i = 0; i < len*8; i++) {
156 if (TestBit(i, info->key_bitmask))
157 LOG_DEBUG(device, "Has KEY[%d] = %s\n", i,
158 Event_To_String(EV_KEY, i));
159 }
160
161 len = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(info->led_bitmask)),
162 info->led_bitmask);
163 if (len < 0) {
164 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_LED) failed: %s\n",
165 strerror(errno));
166 return !Success;
167 }
168 for (i = 0; i < len*8; i++) {
169 if (TestBit(i, info->led_bitmask))
170 LOG_DEBUG(device, "Has LED[%d] = %s\n", i,
171 Event_To_String(EV_LED, i));
172 }
173
174 len = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(info->rel_bitmask)),
175 info->rel_bitmask);
176 if (len < 0) {
177 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_REL) failed: %s\n",
178 strerror(errno));
179 return !Success;
180 }
181 for (i = 0; i < len*8; i++) {
182 if (TestBit(i, info->rel_bitmask))
183 LOG_DEBUG(device, "Has REL[%d] = %s\n", i,
184 Event_To_String(EV_REL, i));
185 }
186
Dennis Kempina9963ba2012-06-08 10:32:23 -0700187 len = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(info->abs_bitmask)),
188 info->abs_bitmask);
189 if (len < 0) {
190 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_ABS) failed: %s\n",
191 strerror(errno));
192 return !Success;
193 }
194
195 for (i = ABS_X; i <= ABS_MAX; i++) {
196 if (TestBit(i, info->abs_bitmask)) {
197 struct input_absinfo* absinfo = &info->absinfo[i];
198 LOG_DEBUG(device, "Has ABS[%d] = %s\n", i,
199 Event_To_String(EV_ABS, i));
200 len = ioctl(fd, EVIOCGABS(i), absinfo);
201 if (len < 0) {
202 LOG_ERROR(device, "ioctl EVIOCGABS(%d) failed: %s\n", i,
203 strerror(errno));
204 return !Success;
205 }
206
207 Absinfo_Print(device, absinfo);
208 }
209 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800210
211 info->evdev_class = EvdevProbeClass(info);
212 LOG_DEBUG(device, "Has evdev device class = %s\n",
213 EvdevClassToString(info->evdev_class));
214 if (info->evdev_class == EvdevClassUnknown) {
215 LOG_ERROR(device, "Couldn't determine evdev class\n");
216 return !Success;
217 }
218
Dennis Kempina9963ba2012-06-08 10:32:23 -0700219 return Success;
220}
221
222int EvdevProbeAbsinfo(EvdevPtr device, size_t key) {
223 struct input_absinfo* absinfo;
224
225 absinfo = &device->info.absinfo[key];
226 if (ioctl(device->fd, EVIOCGABS(key), absinfo) < 0) {
Daniel Kurtz0d097082012-09-07 22:27:51 +0800227 LOG_ERROR(device, "ioctl EVIOCGABS(%zu) failed: %s\n", key,
Dennis Kempina9963ba2012-06-08 10:32:23 -0700228 strerror(errno));
229 return !Success;
230 } else {
231 return Success;
232 }
233}
234
235int EvdevProbeMTSlot(EvdevPtr device, MTSlotInfoPtr req) {
Dennis Kempine9cc2642012-06-25 11:52:24 -0700236 if (ioctl(device->fd, EVIOCGMTSLOTS((sizeof(*req))), req) < 0) {
Dennis Kempina9963ba2012-06-08 10:32:23 -0700237 LOG_ERROR(device, "ioctl EVIOCGMTSLOTS(req.code=%d) failed: %s\n",
Dennis Kempine9cc2642012-06-25 11:52:24 -0700238 req->code, strerror(errno));
Dennis Kempina9963ba2012-06-08 10:32:23 -0700239 return !Success;
240 } else {
241 return Success;
242 }
243}
244
245int EvdevProbeKeyState(EvdevPtr device) {
246 int len = sizeof(device->key_state_bitmask);
247
248 memset(device->key_state_bitmask, 0, len);
249 if (ioctl(device->fd, EVIOCGKEY(len), device->key_state_bitmask) < 0) {
250 LOG_ERROR(device, "ioctl EVIOCGKEY failed: %s\n", strerror(errno));
251 return !Success;
252 } else {
253 return Success;
254 }
255}
256
257int EvdevEnableMonotonic(EvdevPtr device) {
258 unsigned int clk = CLOCK_MONOTONIC;
259 return (ioctl(device->fd, EVIOCSCLOCKID, &clk) == 0) ? Success : !Success;
260}
261
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800262#endif // #ifndef EVDEV_HOLLOW
263
264/*
265 * Check if the device is a single-pressure one which reports ABS_PRESSURE only.
266 */
267int EvdevIsSinglePressureDevice(EvdevPtr device) {
268 EvdevInfoPtr info = &device->info;
269
270 return (!TestBit(ABS_MT_PRESSURE, info->abs_bitmask) &&
271 TestBit(ABS_PRESSURE, info->abs_bitmask));
272}
273
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800274int EvdevWriteInfoToFile(FILE* fp, const EvdevInfoPtr info) {
275 int ret;
276
277 ret = fprintf(fp, "# device: %s\n", info->name);
278 if (ret <= 0)
279 return ret;
280
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800281 ret = EvdevWriteBitmask(fp, "bit", info->bitmask, sizeof(info->bitmask));
282 if (ret <= 0)
283 return ret;
284
285 ret = EvdevWriteBitmask(fp, "key", info->key_bitmask,
286 sizeof(info->key_bitmask));
287 if (ret <= 0)
288 return ret;
289
290 ret = EvdevWriteBitmask(fp, "rel", info->rel_bitmask,
291 sizeof(info->rel_bitmask));
292 if (ret <= 0)
293 return ret;
294
295 ret = EvdevWriteBitmask(fp, "abs", info->abs_bitmask,
296 sizeof(info->abs_bitmask));
297 if (ret <= 0)
298 return ret;
299
300 ret = EvdevWriteBitmask(fp, "led", info->led_bitmask,
301 sizeof(info->led_bitmask));
302 if (ret <= 0)
303 return ret;
304
305 ret = EvdevWriteBitmask(fp, "prp", info->prop_bitmask,
306 sizeof(info->prop_bitmask));
307 if (ret <= 0)
308 return ret;
309
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800310 // when reading the log we need to know which absinfos
311 // exist which is stored in the abs bitmask.
312 // so we have to write absinfo after the bitmasks.
313 for (int i = ABS_X; i <= ABS_MAX; i++) {
314 if (TestBit(i, info->abs_bitmask)) {
315 struct input_absinfo* abs = &info->absinfo[i];
316 ret = fprintf(fp, "# absinfo: %d %d %d %d %d %d\n",
317 i, abs->minimum, abs->maximum,
318 abs->fuzz, abs->flat, abs->resolution);
319 if (ret <= 0)
320 return ret;
321 }
322 }
323
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800324 return 1;
325}
326
327int EvdevWriteEventToFile(FILE* fp, const struct input_event* ev) {
Mike Frysinger7abec9e2012-12-23 13:00:24 -0500328 return fprintf(fp, "E: %ld.%06u %04x %04x %d\n",
329 (long)ev->time.tv_sec, (unsigned)ev->time.tv_usec,
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800330 ev->type, ev->code, ev->value);
331}
332
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800333int EvdevReadInfoFromFile(FILE* fp, EvdevInfoPtr info) {
334 int ret;
335
Dennis Kempinbb4375b2013-03-28 12:02:54 -0700336 ret = fscanf(fp, "# device: %1024[^\n]\n", info->name);
Dennis Kempin690b3b42013-05-29 11:45:32 -0700337 if (ret <= 0)
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800338 return ret;
339
340 ret = EvdevReadBitmask(fp, "bit", info->bitmask, sizeof(info->bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700341 if (ret <= 0) {
342 fprintf(stderr, "Parse device bit failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800343 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700344 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800345
346 ret = EvdevReadBitmask(fp, "key", info->key_bitmask,
347 sizeof(info->key_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700348 if (ret <= 0) {
349 fprintf(stderr, "Parse device key failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800350 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700351 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800352
353 ret = EvdevReadBitmask(fp, "rel", info->rel_bitmask,
354 sizeof(info->rel_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700355 if (ret <= 0) {
356 fprintf(stderr, "Parse device rel failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800357 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700358 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800359
360 ret = EvdevReadBitmask(fp, "abs", info->abs_bitmask,
361 sizeof(info->abs_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700362 if (ret <= 0) {
363 fprintf(stderr, "Parse device abs failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800364 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700365 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800366
367 ret = EvdevReadBitmask(fp, "led", info->led_bitmask,
368 sizeof(info->led_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700369 if (ret <= 0) {
370 fprintf(stderr, "Parse device led failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800371 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700372 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800373
374 ret = EvdevReadBitmask(fp, "prp", info->prop_bitmask,
375 sizeof(info->prop_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700376 if (ret <= 0) {
377 fprintf(stderr, "Parse device prp failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800378 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700379 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800380
381 for (int i = ABS_X; i <= ABS_MAX; i++) {
382 if (TestBit(i, info->abs_bitmask)) {
383 struct input_absinfo abs;
384 int abs_index;
385 ret = fscanf(fp, "# absinfo: %d %d %d %d %d %d\n",
386 &abs_index, &abs.minimum, &abs.maximum,
387 &abs.fuzz, &abs.flat, &abs.resolution);
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700388 if (ret <= 0 || abs_index != i) {
389 fprintf(stderr, "Parse device absinfo failed on %d\n", i);
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800390 return -1;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700391 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800392 info->absinfo[i] = abs;
393 }
394 }
395 return 1;
396}
397
398int EvdevReadEventFromFile(FILE* fp, struct input_event* ev) {
399 unsigned long sec;
400 unsigned usec, type, code;
401 int value;
402 int ret = fscanf(fp, "E: %lu.%06u %04x %04x %d\n",
403 &sec, &usec, &type, &code, &value);
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700404 if (ret == EOF)
405 return -1;
406 if (ret <= 0) {
407 int err = errno;
408 fprintf(stderr, "EvdevReadEventFromFile failed: %d, errno: %d\n", ret, err);
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800409 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700410 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800411
412 ev->time.tv_sec = sec;
413 ev->time.tv_usec = usec;
414 ev->type = type;
415 ev->code = code;
416 ev->value = value;
417 return ret;
418}
419
420static int EvdevReadBitmask(FILE* fp, const char* expected_name,
421 unsigned long* bitmask, size_t num_bytes) {
422 unsigned char* bytes = (unsigned char*)bitmask;
423 int ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700424 char name[64] = { 0 };
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800425
Chung-yih Wang2eeae932013-04-29 12:50:46 +0800426 ret = fscanf(fp, "# %63[^:]:", name);
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700427 if (ret <= 0 || strcmp(name, expected_name)) {
428 fprintf(stderr, "EvdevReadBitmask: %d <= 0 or [%s]!=[%s]\n",
429 ret, name, expected_name);
430 return -1;
431 }
432 memset(bitmask, 0, num_bytes);
433 for (size_t i = 0; i < num_bytes; ++i) {
434 // Make sure we don't go off the end of the line
435 int next_char = fgetc(fp);
436 if (next_char != EOF)
437 ungetc(next_char, fp);
438 if (next_char == '\n' || next_char == EOF)
439 break;
440
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800441 unsigned int tmp;
442 ret = fscanf(fp, " %02X", &tmp);
443 if (ret <= 0)
Dennis Kempin1ecc7e92013-03-29 16:58:08 -0700444 bytes[i] = 0;
445 else
446 bytes[i] = (unsigned char)tmp;
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800447 }
Chung-yih Wang2eeae932013-04-29 12:50:46 +0800448 // size(in bytes) of bitmask array may differs per platform, try to read
449 // remaining bytes if exists
450 do {
451 if (fgets(name, sizeof(name), fp) == NULL)
452 return -1;
453 } while (name[strlen(name) - 1] != '\n');
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800454 return 1;
455}
456
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800457static int EvdevWriteBitmask(FILE* fp, const char* name,
458 unsigned long* bitmask, size_t num_bytes) {
459 int ret;
460
461 unsigned char* bytes = (unsigned char*)bitmask;
462 ret = fprintf(fp, "# %s:", name);
463 if (ret <= 0)
464 return ret;
465
466 for (int i = 0; i < num_bytes; ++i) {
467 ret = fprintf(fp, " %02X", bytes[i]);
468 if (ret <= 0)
469 return ret;
470 }
471 ret = fprintf(fp, "\n");
472 return ret;
473}
Dennis Kempina9963ba2012-06-08 10:32:23 -0700474
Dennis Kempin0e265392013-02-22 12:59:03 -0800475#ifndef EVDEV_HOLLOW
476
Dennis Kempina9963ba2012-06-08 10:32:23 -0700477static const char*
478Event_Property_To_String(int type) {
479 switch (type) {
480 case INPUT_PROP_POINTER: return "POINTER"; /* needs a pointer */
481 case INPUT_PROP_DIRECT: return "DIRECT"; /* direct input devices */
482 case INPUT_PROP_BUTTONPAD: return "BUTTONPAD"; /* has button under pad */
483 case INPUT_PROP_SEMI_MT: return "SEMI_MT"; /* touch rectangle only */
484 default: return "?";
485 }
486}
487
488static void
489Absinfo_Print(EvdevPtr device, struct input_absinfo* absinfo)
490{
491 LOG_DEBUG(device, " min = %d\n", absinfo->minimum);
492 LOG_DEBUG(device, " max = %d\n", absinfo->maximum);
493 if (absinfo->fuzz)
494 LOG_DEBUG(device, " fuzz = %d\n", absinfo->fuzz);
495 if (absinfo->resolution)
496 LOG_DEBUG(device, " res = %d\n", absinfo->resolution);
497}
498
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800499/*
500 * Heuristics for determining evdev device class; similar to those of
501 * xf86-input-evdev.
502 */
503static EvdevClass EvdevProbeClass(EvdevInfoPtr info) {
504 int bit;
505 for (bit = 0; bit < BTN_MISC; bit++)
506 if (TestBit(bit, info->key_bitmask))
507 return EvdevClassKeyboard;
508
509 if (TestBit(REL_X, info->rel_bitmask) &&
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800510 TestBit(REL_Y, info->rel_bitmask)) {
511 if (TestBit(ABS_MT_POSITION_X, info->abs_bitmask) &&
512 TestBit(ABS_MT_POSITION_Y, info->abs_bitmask))
513 return EvdevClassMultitouchMouse;
514 else
515 return EvdevClassMouse;
516 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800517
518 if (TestBit(ABS_X, info->abs_bitmask) &&
519 TestBit(ABS_Y, info->abs_bitmask)) {
520
521 if (TestBit(BTN_TOOL_PEN, info->key_bitmask) ||
522 TestBit(BTN_STYLUS, info->key_bitmask) ||
523 TestBit(BTN_STYLUS2, info->key_bitmask))
524 return EvdevClassTablet;
525
526 if (TestBit(ABS_PRESSURE, info->abs_bitmask) ||
527 TestBit(BTN_TOUCH, info->key_bitmask)) {
528 if (TestBit(BTN_LEFT, info->key_bitmask) ||
529 TestBit(BTN_MIDDLE, info->key_bitmask) ||
530 TestBit(BTN_RIGHT, info->key_bitmask) ||
531 TestBit(BTN_TOOL_FINGER, info->key_bitmask))
532 return EvdevClassTouchpad;
533 else
534 return EvdevClassTouchscreen;
535 }
536
537 /* Some touchscreens use BTN_LEFT rather than BTN_TOUCH */
538 if (TestBit(BTN_LEFT, info->key_bitmask))
539 return EvdevClassTouchscreen;
540 }
541
542 return EvdevClassUnknown;
543}
544
545static const char* EvdevClassToString(EvdevClass cls) {
546 switch (cls) {
547 case EvdevClassUnknown: return "EvdevClassUnknown";
548 case EvdevClassKeyboard: return "EvdevClassKeyboard";
549 case EvdevClassMouse: return "EvdevClassMouse";
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800550 case EvdevClassMultitouchMouse: return "EvdevClassMultitouchMouse";
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800551 case EvdevClassTablet: return "EvdevClassTablet";
552 case EvdevClassTouchpad: return "EvdevClassTouchpad";
553 case EvdevClassTouchscreen: return "EvdevClassTouchscreen";
554 }
555 return "Unhandled Evdev Class";
556}
Dennis Kempin0e265392013-02-22 12:59:03 -0800557
558#endif // #ifndef EVDEV_HOLLOW