blob: 589cb28fd2f7c947ef53c34f3e4a813432ec00ea [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)
Chung-yih Wang53af0892013-06-27 18:13:37 +080064 break;
Dennis Kempina9963ba2012-06-08 10:32:23 -070065
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 */
Yunlian Jiang4f5d5052015-01-20 14:27:40 -080068 for (i = 0; i < len / sizeof(*ev); i++) {
69 evstate->debug_buf[evstate->debug_buf_tail] = ev[i];
70 evstate->debug_buf_tail =
71 (evstate->debug_buf_tail + 1) % DEBUG_BUF_SIZE;
Andrew de los Reyesec028842012-08-16 18:08:12 -070072 }
73
Dennis Kempina9963ba2012-06-08 10:32:23 -070074 /* kernel always delivers complete events, so len must be sizeof *ev */
75 if (len % sizeof(*ev))
Chung-yih Wang53af0892013-06-27 18:13:37 +080076 break;
Dennis Kempina9963ba2012-06-08 10:32:23 -070077
78 /* Process events ... */
79 for (i = 0; i < len / sizeof(ev[0]); i++) {
80 if (sync_evdev_state)
81 break;
82 if (timercmp(&ev[i].time, &evdev->before_sync_time, <)) {
83 /* Ignore events before last sync time */
84 continue;
85 } else if (timercmp(&ev[i].time, &evdev->after_sync_time, >)) {
86 /* Event_Process returns TRUE if SYN_DROPPED detected */
Chung-yih Wang53af0892013-06-27 18:13:37 +080087 sync_evdev_state |= Event_Process(evdev, &ev[i]);
Dennis Kempina9963ba2012-06-08 10:32:23 -070088 } else {
89 /* If the event occurred during sync, then sync again */
90 sync_evdev_state = true;
91 }
92 }
93
94 } while (len == sizeof(ev));
95 /* Keep reading if kernel supplied NUM_EVENTS events. */
96
97 if (sync_evdev_state)
98 Event_Sync_State(evdev);
99
100 return Success;
101}
102
103int EvdevProbe(EvdevPtr device) {
104 int len, i;
105 int fd;
106 EvdevInfoPtr info;
107
108 fd = device->fd;
109 info = &device->info;
110 if (ioctl(fd, EVIOCGID, &info->id) < 0) {
111 LOG_ERROR(device, "ioctl EVIOCGID failed: %s\n", strerror(errno));
112 return !Success;
113 }
114
115 if (ioctl(fd, EVIOCGNAME(sizeof(info->name) - 1),
116 info->name) < 0) {
117 LOG_ERROR(device, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
118 return !Success;
119 }
120
121 len = ioctl(fd, EVIOCGPROP(sizeof(info->prop_bitmask)),
122 info->prop_bitmask);
123 if (len < 0) {
124 LOG_ERROR(device, "ioctl EVIOCGPROP failed: %s\n", strerror(errno));
125 return !Success;
126 }
127 for (i = 0; i < len*8; i++) {
128 if (TestBit(i, info->prop_bitmask))
129 LOG_DEBUG(device, "Has Property: %d (%s)\n", i,
130 Event_Property_To_String(i));
131 }
132
133 len = ioctl(fd, EVIOCGBIT(0, sizeof(info->bitmask)),
134 info->bitmask);
135 if (len < 0) {
136 LOG_ERROR(device, "ioctl EVIOCGBIT failed: %s\n",
137 strerror(errno));
138 return !Success;
139 }
140 for (i = 0; i < len*8; i++) {
141 if (TestBit(i, info->bitmask))
142 LOG_DEBUG(device, "Has Event Type %d = %s\n", i,
143 Event_Type_To_String(i));
144 }
145
146 len = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info->key_bitmask)),
147 info->key_bitmask);
148 if (len < 0) {
149 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_KEY) failed: %s\n",
150 strerror(errno));
151 return !Success;
152 }
153 for (i = 0; i < len*8; i++) {
154 if (TestBit(i, info->key_bitmask))
155 LOG_DEBUG(device, "Has KEY[%d] = %s\n", i,
156 Event_To_String(EV_KEY, i));
157 }
158
159 len = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(info->led_bitmask)),
160 info->led_bitmask);
161 if (len < 0) {
162 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_LED) failed: %s\n",
163 strerror(errno));
164 return !Success;
165 }
166 for (i = 0; i < len*8; i++) {
167 if (TestBit(i, info->led_bitmask))
168 LOG_DEBUG(device, "Has LED[%d] = %s\n", i,
169 Event_To_String(EV_LED, i));
170 }
171
172 len = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(info->rel_bitmask)),
173 info->rel_bitmask);
174 if (len < 0) {
175 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_REL) failed: %s\n",
176 strerror(errno));
177 return !Success;
178 }
179 for (i = 0; i < len*8; i++) {
180 if (TestBit(i, info->rel_bitmask))
181 LOG_DEBUG(device, "Has REL[%d] = %s\n", i,
182 Event_To_String(EV_REL, i));
183 }
184
Dennis Kempina9963ba2012-06-08 10:32:23 -0700185 len = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(info->abs_bitmask)),
186 info->abs_bitmask);
187 if (len < 0) {
188 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_ABS) failed: %s\n",
189 strerror(errno));
190 return !Success;
191 }
192
193 for (i = ABS_X; i <= ABS_MAX; i++) {
194 if (TestBit(i, info->abs_bitmask)) {
195 struct input_absinfo* absinfo = &info->absinfo[i];
196 LOG_DEBUG(device, "Has ABS[%d] = %s\n", i,
197 Event_To_String(EV_ABS, i));
198 len = ioctl(fd, EVIOCGABS(i), absinfo);
199 if (len < 0) {
200 LOG_ERROR(device, "ioctl EVIOCGABS(%d) failed: %s\n", i,
201 strerror(errno));
202 return !Success;
203 }
204
205 Absinfo_Print(device, absinfo);
206 }
207 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800208
209 info->evdev_class = EvdevProbeClass(info);
210 LOG_DEBUG(device, "Has evdev device class = %s\n",
211 EvdevClassToString(info->evdev_class));
212 if (info->evdev_class == EvdevClassUnknown) {
213 LOG_ERROR(device, "Couldn't determine evdev class\n");
214 return !Success;
215 }
216
Dennis Kempina9963ba2012-06-08 10:32:23 -0700217 return Success;
218}
219
220int EvdevProbeAbsinfo(EvdevPtr device, size_t key) {
221 struct input_absinfo* absinfo;
222
223 absinfo = &device->info.absinfo[key];
224 if (ioctl(device->fd, EVIOCGABS(key), absinfo) < 0) {
Daniel Kurtz0d097082012-09-07 22:27:51 +0800225 LOG_ERROR(device, "ioctl EVIOCGABS(%zu) failed: %s\n", key,
Dennis Kempina9963ba2012-06-08 10:32:23 -0700226 strerror(errno));
227 return !Success;
228 } else {
229 return Success;
230 }
231}
232
233int EvdevProbeMTSlot(EvdevPtr device, MTSlotInfoPtr req) {
Dennis Kempine9cc2642012-06-25 11:52:24 -0700234 if (ioctl(device->fd, EVIOCGMTSLOTS((sizeof(*req))), req) < 0) {
Dennis Kempina9963ba2012-06-08 10:32:23 -0700235 LOG_ERROR(device, "ioctl EVIOCGMTSLOTS(req.code=%d) failed: %s\n",
Dennis Kempine9cc2642012-06-25 11:52:24 -0700236 req->code, strerror(errno));
Dennis Kempina9963ba2012-06-08 10:32:23 -0700237 return !Success;
238 } else {
239 return Success;
240 }
241}
242
243int EvdevProbeKeyState(EvdevPtr device) {
244 int len = sizeof(device->key_state_bitmask);
245
246 memset(device->key_state_bitmask, 0, len);
247 if (ioctl(device->fd, EVIOCGKEY(len), device->key_state_bitmask) < 0) {
248 LOG_ERROR(device, "ioctl EVIOCGKEY failed: %s\n", strerror(errno));
249 return !Success;
250 } else {
251 return Success;
252 }
253}
254
255int EvdevEnableMonotonic(EvdevPtr device) {
256 unsigned int clk = CLOCK_MONOTONIC;
257 return (ioctl(device->fd, EVIOCSCLOCKID, &clk) == 0) ? Success : !Success;
258}
259
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800260#endif // #ifndef EVDEV_HOLLOW
261
262/*
263 * Check if the device is a single-pressure one which reports ABS_PRESSURE only.
264 */
265int EvdevIsSinglePressureDevice(EvdevPtr device) {
266 EvdevInfoPtr info = &device->info;
267
268 return (!TestBit(ABS_MT_PRESSURE, info->abs_bitmask) &&
269 TestBit(ABS_PRESSURE, info->abs_bitmask));
270}
271
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800272int EvdevWriteInfoToFile(FILE* fp, const EvdevInfoPtr info) {
273 int ret;
274
275 ret = fprintf(fp, "# device: %s\n", info->name);
276 if (ret <= 0)
277 return ret;
278
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800279 ret = EvdevWriteBitmask(fp, "bit", info->bitmask, sizeof(info->bitmask));
280 if (ret <= 0)
281 return ret;
282
283 ret = EvdevWriteBitmask(fp, "key", info->key_bitmask,
284 sizeof(info->key_bitmask));
285 if (ret <= 0)
286 return ret;
287
288 ret = EvdevWriteBitmask(fp, "rel", info->rel_bitmask,
289 sizeof(info->rel_bitmask));
290 if (ret <= 0)
291 return ret;
292
293 ret = EvdevWriteBitmask(fp, "abs", info->abs_bitmask,
294 sizeof(info->abs_bitmask));
295 if (ret <= 0)
296 return ret;
297
298 ret = EvdevWriteBitmask(fp, "led", info->led_bitmask,
299 sizeof(info->led_bitmask));
300 if (ret <= 0)
301 return ret;
302
303 ret = EvdevWriteBitmask(fp, "prp", info->prop_bitmask,
304 sizeof(info->prop_bitmask));
305 if (ret <= 0)
306 return ret;
307
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800308 // when reading the log we need to know which absinfos
309 // exist which is stored in the abs bitmask.
310 // so we have to write absinfo after the bitmasks.
311 for (int i = ABS_X; i <= ABS_MAX; i++) {
312 if (TestBit(i, info->abs_bitmask)) {
313 struct input_absinfo* abs = &info->absinfo[i];
314 ret = fprintf(fp, "# absinfo: %d %d %d %d %d %d\n",
315 i, abs->minimum, abs->maximum,
316 abs->fuzz, abs->flat, abs->resolution);
317 if (ret <= 0)
318 return ret;
319 }
320 }
321
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800322 return 1;
323}
324
325int EvdevWriteEventToFile(FILE* fp, const struct input_event* ev) {
Mike Frysinger7abec9e2012-12-23 13:00:24 -0500326 return fprintf(fp, "E: %ld.%06u %04x %04x %d\n",
327 (long)ev->time.tv_sec, (unsigned)ev->time.tv_usec,
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800328 ev->type, ev->code, ev->value);
329}
330
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800331int EvdevReadInfoFromFile(FILE* fp, EvdevInfoPtr info) {
332 int ret;
333
Dennis Kempinbb4375b2013-03-28 12:02:54 -0700334 ret = fscanf(fp, "# device: %1024[^\n]\n", info->name);
Dennis Kempin690b3b42013-05-29 11:45:32 -0700335 if (ret <= 0)
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800336 return ret;
337
338 ret = EvdevReadBitmask(fp, "bit", info->bitmask, sizeof(info->bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700339 if (ret <= 0) {
340 fprintf(stderr, "Parse device bit failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800341 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700342 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800343
344 ret = EvdevReadBitmask(fp, "key", info->key_bitmask,
345 sizeof(info->key_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700346 if (ret <= 0) {
347 fprintf(stderr, "Parse device key failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800348 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700349 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800350
351 ret = EvdevReadBitmask(fp, "rel", info->rel_bitmask,
352 sizeof(info->rel_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700353 if (ret <= 0) {
354 fprintf(stderr, "Parse device rel failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800355 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700356 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800357
358 ret = EvdevReadBitmask(fp, "abs", info->abs_bitmask,
359 sizeof(info->abs_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700360 if (ret <= 0) {
361 fprintf(stderr, "Parse device abs failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800362 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700363 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800364
365 ret = EvdevReadBitmask(fp, "led", info->led_bitmask,
366 sizeof(info->led_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700367 if (ret <= 0) {
368 fprintf(stderr, "Parse device led failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800369 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700370 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800371
372 ret = EvdevReadBitmask(fp, "prp", info->prop_bitmask,
373 sizeof(info->prop_bitmask));
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700374 if (ret <= 0) {
375 fprintf(stderr, "Parse device prp failed\n");
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800376 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700377 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800378
379 for (int i = ABS_X; i <= ABS_MAX; i++) {
380 if (TestBit(i, info->abs_bitmask)) {
381 struct input_absinfo abs;
382 int abs_index;
383 ret = fscanf(fp, "# absinfo: %d %d %d %d %d %d\n",
384 &abs_index, &abs.minimum, &abs.maximum,
385 &abs.fuzz, &abs.flat, &abs.resolution);
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700386 if (ret <= 0 || abs_index != i) {
387 fprintf(stderr, "Parse device absinfo failed on %d\n", i);
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800388 return -1;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700389 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800390 info->absinfo[i] = abs;
391 }
392 }
393 return 1;
394}
395
396int EvdevReadEventFromFile(FILE* fp, struct input_event* ev) {
397 unsigned long sec;
398 unsigned usec, type, code;
399 int value;
400 int ret = fscanf(fp, "E: %lu.%06u %04x %04x %d\n",
401 &sec, &usec, &type, &code, &value);
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700402 if (ret == EOF)
403 return -1;
404 if (ret <= 0) {
405 int err = errno;
406 fprintf(stderr, "EvdevReadEventFromFile failed: %d, errno: %d\n", ret, err);
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800407 return ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700408 }
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800409
410 ev->time.tv_sec = sec;
411 ev->time.tv_usec = usec;
412 ev->type = type;
413 ev->code = code;
414 ev->value = value;
415 return ret;
416}
417
418static int EvdevReadBitmask(FILE* fp, const char* expected_name,
419 unsigned long* bitmask, size_t num_bytes) {
420 unsigned char* bytes = (unsigned char*)bitmask;
421 int ret;
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700422 char name[64] = { 0 };
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800423
Chung-yih Wang2eeae932013-04-29 12:50:46 +0800424 ret = fscanf(fp, "# %63[^:]:", name);
Andrew de los Reyes8fbd3c12013-05-08 09:30:50 -0700425 if (ret <= 0 || strcmp(name, expected_name)) {
426 fprintf(stderr, "EvdevReadBitmask: %d <= 0 or [%s]!=[%s]\n",
427 ret, name, expected_name);
428 return -1;
429 }
430 memset(bitmask, 0, num_bytes);
431 for (size_t i = 0; i < num_bytes; ++i) {
432 // Make sure we don't go off the end of the line
433 int next_char = fgetc(fp);
434 if (next_char != EOF)
435 ungetc(next_char, fp);
436 if (next_char == '\n' || next_char == EOF)
437 break;
438
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800439 unsigned int tmp;
440 ret = fscanf(fp, " %02X", &tmp);
441 if (ret <= 0)
Dennis Kempin1ecc7e92013-03-29 16:58:08 -0700442 bytes[i] = 0;
443 else
444 bytes[i] = (unsigned char)tmp;
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800445 }
Chung-yih Wang2eeae932013-04-29 12:50:46 +0800446 // size(in bytes) of bitmask array may differs per platform, try to read
447 // remaining bytes if exists
448 do {
449 if (fgets(name, sizeof(name), fp) == NULL)
450 return -1;
451 } while (name[strlen(name) - 1] != '\n');
Dennis Kempin9ec1b7c2013-02-19 14:28:48 -0800452 return 1;
453}
454
Dennis Kempin69c91ed2013-02-12 14:53:10 -0800455static int EvdevWriteBitmask(FILE* fp, const char* name,
456 unsigned long* bitmask, size_t num_bytes) {
457 int ret;
458
459 unsigned char* bytes = (unsigned char*)bitmask;
460 ret = fprintf(fp, "# %s:", name);
461 if (ret <= 0)
462 return ret;
463
464 for (int i = 0; i < num_bytes; ++i) {
465 ret = fprintf(fp, " %02X", bytes[i]);
466 if (ret <= 0)
467 return ret;
468 }
469 ret = fprintf(fp, "\n");
470 return ret;
471}
Dennis Kempina9963ba2012-06-08 10:32:23 -0700472
Dennis Kempin0e265392013-02-22 12:59:03 -0800473#ifndef EVDEV_HOLLOW
474
Dennis Kempina9963ba2012-06-08 10:32:23 -0700475static const char*
476Event_Property_To_String(int type) {
477 switch (type) {
478 case INPUT_PROP_POINTER: return "POINTER"; /* needs a pointer */
479 case INPUT_PROP_DIRECT: return "DIRECT"; /* direct input devices */
480 case INPUT_PROP_BUTTONPAD: return "BUTTONPAD"; /* has button under pad */
481 case INPUT_PROP_SEMI_MT: return "SEMI_MT"; /* touch rectangle only */
482 default: return "?";
483 }
484}
485
486static void
487Absinfo_Print(EvdevPtr device, struct input_absinfo* absinfo)
488{
489 LOG_DEBUG(device, " min = %d\n", absinfo->minimum);
490 LOG_DEBUG(device, " max = %d\n", absinfo->maximum);
491 if (absinfo->fuzz)
492 LOG_DEBUG(device, " fuzz = %d\n", absinfo->fuzz);
493 if (absinfo->resolution)
494 LOG_DEBUG(device, " res = %d\n", absinfo->resolution);
495}
496
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800497/*
498 * Heuristics for determining evdev device class; similar to those of
499 * xf86-input-evdev.
500 */
501static EvdevClass EvdevProbeClass(EvdevInfoPtr info) {
502 int bit;
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800503
504 if (TestBit(REL_X, info->rel_bitmask) &&
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800505 TestBit(REL_Y, info->rel_bitmask)) {
506 if (TestBit(ABS_MT_POSITION_X, info->abs_bitmask) &&
507 TestBit(ABS_MT_POSITION_Y, info->abs_bitmask))
508 return EvdevClassMultitouchMouse;
509 else
510 return EvdevClassMouse;
511 }
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800512
513 if (TestBit(ABS_X, info->abs_bitmask) &&
514 TestBit(ABS_Y, info->abs_bitmask)) {
515
516 if (TestBit(BTN_TOOL_PEN, info->key_bitmask) ||
517 TestBit(BTN_STYLUS, info->key_bitmask) ||
518 TestBit(BTN_STYLUS2, info->key_bitmask))
519 return EvdevClassTablet;
520
521 if (TestBit(ABS_PRESSURE, info->abs_bitmask) ||
522 TestBit(BTN_TOUCH, info->key_bitmask)) {
523 if (TestBit(BTN_LEFT, info->key_bitmask) ||
524 TestBit(BTN_MIDDLE, info->key_bitmask) ||
525 TestBit(BTN_RIGHT, info->key_bitmask) ||
526 TestBit(BTN_TOOL_FINGER, info->key_bitmask))
527 return EvdevClassTouchpad;
528 else
529 return EvdevClassTouchscreen;
530 }
531
532 /* Some touchscreens use BTN_LEFT rather than BTN_TOUCH */
533 if (TestBit(BTN_LEFT, info->key_bitmask))
534 return EvdevClassTouchscreen;
535 }
536
Andrew de los Reyesa63c82a2014-04-03 16:11:26 -0700537 for (bit = 0; bit < BTN_MISC; bit++)
538 if (TestBit(bit, info->key_bitmask))
539 return EvdevClassKeyboard;
540
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800541 return EvdevClassUnknown;
542}
543
544static const char* EvdevClassToString(EvdevClass cls) {
545 switch (cls) {
546 case EvdevClassUnknown: return "EvdevClassUnknown";
547 case EvdevClassKeyboard: return "EvdevClassKeyboard";
548 case EvdevClassMouse: return "EvdevClassMouse";
Che-Liang Chiou7e45cb22013-01-15 14:57:13 -0800549 case EvdevClassMultitouchMouse: return "EvdevClassMultitouchMouse";
Che-Liang Chioub9fc9732012-11-26 15:49:02 -0800550 case EvdevClassTablet: return "EvdevClassTablet";
551 case EvdevClassTouchpad: return "EvdevClassTouchpad";
552 case EvdevClassTouchscreen: return "EvdevClassTouchscreen";
553 }
554 return "Unhandled Evdev Class";
555}
Dennis Kempin0e265392013-02-22 12:59:03 -0800556
557#endif // #ifndef EVDEV_HOLLOW