blob: 19dfb5e033d61c2458db2233db8577c76664a4a3 [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);
33
34int EvdevOpen(EvdevPtr evdev, const char* device) {
35 evdev->fd = open(device, O_RDWR | O_NONBLOCK, 0);
36 return evdev->fd;
37}
38
39int EvdevClose(EvdevPtr evdev) {
40 close(evdev->fd);
41 evdev->fd = -1;
42 return evdev->fd;
43}
44
45int EvdevRead(EvdevPtr evdev) {
46 struct input_event ev[NUM_EVENTS];
Andrew de los Reyesec028842012-08-16 18:08:12 -070047 EventStatePtr evstate = evdev->evstate;
Dennis Kempina9963ba2012-06-08 10:32:23 -070048 int i;
49 int len;
50 bool sync_evdev_state = false;
51
52 do {
53 len = read(evdev->fd, &ev, sizeof(ev));
54 if (len <= 0)
55 return errno;
56
Andrew de los Reyesec028842012-08-16 18:08:12 -070057 /* Read as many whole struct input_event objects as we can into the
58 circular buffer */
59 if (evstate->debug_buf) {
60 for (i = 0; i < len / sizeof(*ev); i++) {
61 evstate->debug_buf[evstate->debug_buf_tail] = ev[i];
62 evstate->debug_buf_tail =
63 (evstate->debug_buf_tail + 1) % DEBUG_BUF_SIZE;
64 }
65 }
66
Dennis Kempina9963ba2012-06-08 10:32:23 -070067 /* kernel always delivers complete events, so len must be sizeof *ev */
68 if (len % sizeof(*ev))
69 return errno;
70
71 /* Process events ... */
72 for (i = 0; i < len / sizeof(ev[0]); i++) {
73 if (sync_evdev_state)
74 break;
75 if (timercmp(&ev[i].time, &evdev->before_sync_time, <)) {
76 /* Ignore events before last sync time */
77 continue;
78 } else if (timercmp(&ev[i].time, &evdev->after_sync_time, >)) {
79 /* Event_Process returns TRUE if SYN_DROPPED detected */
80 sync_evdev_state = Event_Process(evdev, &ev[i]);
81 } else {
82 /* If the event occurred during sync, then sync again */
83 sync_evdev_state = true;
84 }
85 }
86
87 } while (len == sizeof(ev));
88 /* Keep reading if kernel supplied NUM_EVENTS events. */
89
90 if (sync_evdev_state)
91 Event_Sync_State(evdev);
92
93 return Success;
94}
95
96int EvdevProbe(EvdevPtr device) {
97 int len, i;
98 int fd;
99 EvdevInfoPtr info;
100
101 fd = device->fd;
102 info = &device->info;
103 if (ioctl(fd, EVIOCGID, &info->id) < 0) {
104 LOG_ERROR(device, "ioctl EVIOCGID failed: %s\n", strerror(errno));
105 return !Success;
106 }
107
108 if (ioctl(fd, EVIOCGNAME(sizeof(info->name) - 1),
109 info->name) < 0) {
110 LOG_ERROR(device, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
111 return !Success;
112 }
113
114 len = ioctl(fd, EVIOCGPROP(sizeof(info->prop_bitmask)),
115 info->prop_bitmask);
116 if (len < 0) {
117 LOG_ERROR(device, "ioctl EVIOCGPROP failed: %s\n", strerror(errno));
118 return !Success;
119 }
120 for (i = 0; i < len*8; i++) {
121 if (TestBit(i, info->prop_bitmask))
122 LOG_DEBUG(device, "Has Property: %d (%s)\n", i,
123 Event_Property_To_String(i));
124 }
125
126 len = ioctl(fd, EVIOCGBIT(0, sizeof(info->bitmask)),
127 info->bitmask);
128 if (len < 0) {
129 LOG_ERROR(device, "ioctl EVIOCGBIT failed: %s\n",
130 strerror(errno));
131 return !Success;
132 }
133 for (i = 0; i < len*8; i++) {
134 if (TestBit(i, info->bitmask))
135 LOG_DEBUG(device, "Has Event Type %d = %s\n", i,
136 Event_Type_To_String(i));
137 }
138
139 len = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(info->key_bitmask)),
140 info->key_bitmask);
141 if (len < 0) {
142 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_KEY) failed: %s\n",
143 strerror(errno));
144 return !Success;
145 }
146 for (i = 0; i < len*8; i++) {
147 if (TestBit(i, info->key_bitmask))
148 LOG_DEBUG(device, "Has KEY[%d] = %s\n", i,
149 Event_To_String(EV_KEY, i));
150 }
151
152 len = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(info->led_bitmask)),
153 info->led_bitmask);
154 if (len < 0) {
155 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_LED) failed: %s\n",
156 strerror(errno));
157 return !Success;
158 }
159 for (i = 0; i < len*8; i++) {
160 if (TestBit(i, info->led_bitmask))
161 LOG_DEBUG(device, "Has LED[%d] = %s\n", i,
162 Event_To_String(EV_LED, i));
163 }
164
165 len = ioctl(fd, EVIOCGBIT(EV_REL, sizeof(info->rel_bitmask)),
166 info->rel_bitmask);
167 if (len < 0) {
168 LOG_ERROR(device, "ioctl EVIOCGBIT(EV_REL) failed: %s\n",
169 strerror(errno));
170 return !Success;
171 }
172 for (i = 0; i < len*8; i++) {
173 if (TestBit(i, info->rel_bitmask))
174 LOG_DEBUG(device, "Has REL[%d] = %s\n", i,
175 Event_To_String(EV_REL, i));
176 }
177
178 /*
179 * TODO(djkurtz): Solve the race condition between MT slot initialization
180 * from absinfo, and incoming/lost input events.
181 * Specifically, if kernel driver sends MT_SLOT event between absinfo
182 * probe and when we start listening for input events.
183 */
184
185 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 }
208 return Success;
209}
210
211int EvdevProbeAbsinfo(EvdevPtr device, size_t key) {
212 struct input_absinfo* absinfo;
213
214 absinfo = &device->info.absinfo[key];
215 if (ioctl(device->fd, EVIOCGABS(key), absinfo) < 0) {
216 LOG_ERROR(device, "ioctl EVIOCGABS(%d) failed: %s\n", key,
217 strerror(errno));
218 return !Success;
219 } else {
220 return Success;
221 }
222}
223
Chung-yih Wang8b2fa0a2012-07-23 16:49:10 +0800224/*
225 * Check if the device is a single-pressure one which reports ABS_PRESSURE only.
226 */
227int EvdevIsSinglePressureDevice(EvdevPtr device) {
228 EvdevInfoPtr info = &device->info;
229
230 return (!TestBit(ABS_MT_PRESSURE, info->bitmask) &&
231 TestBit(ABS_PRESSURE, info->bitmask));
232}
233
Dennis Kempina9963ba2012-06-08 10:32:23 -0700234int EvdevProbeMTSlot(EvdevPtr device, MTSlotInfoPtr req) {
Dennis Kempine9cc2642012-06-25 11:52:24 -0700235 if (ioctl(device->fd, EVIOCGMTSLOTS((sizeof(*req))), req) < 0) {
Dennis Kempina9963ba2012-06-08 10:32:23 -0700236 LOG_ERROR(device, "ioctl EVIOCGMTSLOTS(req.code=%d) failed: %s\n",
Dennis Kempine9cc2642012-06-25 11:52:24 -0700237 req->code, strerror(errno));
Dennis Kempina9963ba2012-06-08 10:32:23 -0700238 return !Success;
239 } else {
240 return Success;
241 }
242}
243
244int EvdevProbeKeyState(EvdevPtr device) {
245 int len = sizeof(device->key_state_bitmask);
246
247 memset(device->key_state_bitmask, 0, len);
248 if (ioctl(device->fd, EVIOCGKEY(len), device->key_state_bitmask) < 0) {
249 LOG_ERROR(device, "ioctl EVIOCGKEY failed: %s\n", strerror(errno));
250 return !Success;
251 } else {
252 return Success;
253 }
254}
255
256int EvdevEnableMonotonic(EvdevPtr device) {
257 unsigned int clk = CLOCK_MONOTONIC;
258 return (ioctl(device->fd, EVIOCSCLOCKID, &clk) == 0) ? Success : !Success;
259}
260
261
262static const char*
263Event_Property_To_String(int type) {
264 switch (type) {
265 case INPUT_PROP_POINTER: return "POINTER"; /* needs a pointer */
266 case INPUT_PROP_DIRECT: return "DIRECT"; /* direct input devices */
267 case INPUT_PROP_BUTTONPAD: return "BUTTONPAD"; /* has button under pad */
268 case INPUT_PROP_SEMI_MT: return "SEMI_MT"; /* touch rectangle only */
269 default: return "?";
270 }
271}
272
273static void
274Absinfo_Print(EvdevPtr device, struct input_absinfo* absinfo)
275{
276 LOG_DEBUG(device, " min = %d\n", absinfo->minimum);
277 LOG_DEBUG(device, " max = %d\n", absinfo->maximum);
278 if (absinfo->fuzz)
279 LOG_DEBUG(device, " fuzz = %d\n", absinfo->fuzz);
280 if (absinfo->resolution)
281 LOG_DEBUG(device, " res = %d\n", absinfo->resolution);
282}
283