OSDN Git Service

ts_harvest: fix a few compiler warnings
[android-x86/external-tslib.git] / plugins / input-raw.c
1 /*
2  *  tslib/plugins/input-raw.c
3  *
4  *  Original version:
5  *  Copyright (C) 2001 Russell King.
6  *
7  *  Rewritten for the Linux input device API:
8  *  Copyright (C) 2002 Nicolas Pitre
9  *
10  * This file is placed under the LGPL.  Please see the file
11  * COPYING for more details.
12  *
13  *
14  * Read raw pressure, x, y, and timestamp from a touchscreen device.
15  */
16 #include "config.h"
17
18 #include <errno.h>
19 #include <stdio.h>
20 #include <limits.h>
21
22 #include <stdlib.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #include <sys/time.h>
27 #include <sys/types.h>
28
29 #include <linux/input.h>
30 #ifndef EV_SYN /* 2.4 kernel headers */
31 # define EV_SYN 0x00
32 #endif
33 #ifndef EV_CNT
34 # define EV_CNT (EV_MAX+1)
35 #endif
36 #ifndef ABS_CNT
37 # define ABS_CNT (ABS_MAX+1)
38 #endif
39 #ifndef KEY_CNT
40 # define KEY_CNT (KEY_MAX+1)
41 #endif
42
43 #include "tslib-private.h"
44
45 #define GRAB_EVENTS_WANTED      1
46 #define GRAB_EVENTS_ACTIVE      2
47
48 struct tslib_input {
49         struct tslib_module_info module;
50
51         int     current_x;
52         int     current_y;
53         int     current_p;
54
55         int     sane_fd;
56         int     using_syn;
57         int     grab_events;
58 };
59
60 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
61 #define BIT(nr)                 (1UL << (nr))
62 #define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
63 #define BIT_WORD(nr)            ((nr) / BITS_PER_LONG)
64 #define BITS_PER_BYTE           8
65 #define BITS_PER_LONG           (sizeof(long) * BITS_PER_BYTE)
66 #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
67
68 static int check_fd(struct tslib_input *i)
69 {
70         struct tsdev *ts = i->module.dev;
71         int version;
72         long evbit[BITS_TO_LONGS(EV_CNT)];
73         long absbit[BITS_TO_LONGS(ABS_CNT)];
74         long keybit[BITS_TO_LONGS(KEY_CNT)];
75
76         if (ioctl(ts->fd, EVIOCGVERSION, &version) < 0) {
77                 fprintf(stderr, "tslib: Selected device is not a Linux input event device\n");
78                 return -1;
79         }
80
81         if (version < EV_VERSION) {
82                 fprintf(stderr, "tslib: Selected device uses a different version of the event protocol than tslib was compiled for\n");
83                 return -1;
84         }
85
86         if ( (ioctl(ts->fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
87                 !(evbit[BIT_WORD(EV_ABS)] & BIT_MASK(EV_ABS)) ||
88                 !(evbit[BIT_WORD(EV_KEY)] & BIT_MASK(EV_KEY)) ) {
89                 fprintf(stderr, "tslib: Selected device is not a touchscreen (must support ABS and KEY event types)\n");
90                 return -1;
91         }
92
93         if ((ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit)) < 0 ||
94                 !(absbit[BIT_WORD(ABS_X)] & BIT_MASK(ABS_X)) ||
95                 !(absbit[BIT_WORD(ABS_Y)] & BIT_MASK(ABS_Y))) {
96                 fprintf(stderr, "tslib: Selected device is not a touchscreen (must support ABS_X and ABS_Y events)\n");
97                 return -1;
98         }
99
100         /* Since some touchscreens (eg. infrared) physically can't measure pressure,
101         the input system doesn't report it on those. Tslib relies on pressure, thus
102         we set it to constant 255. It's still controlled by BTN_TOUCH - when not
103         touched, the pressure is forced to 0. */
104
105         if (!(absbit[BIT_WORD(ABS_PRESSURE)] & BIT_MASK(ABS_PRESSURE))) {
106                 i->current_p = 255;
107
108                 if ((ioctl(ts->fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
109                         !(keybit[BIT_WORD(BTN_TOUCH)] & BIT_MASK(BTN_TOUCH)) ) {
110                         fprintf(stderr, "tslib: Selected device is not a touchscreen (must support BTN_TOUCH events)\n");
111                         return -1;
112                 }
113         }
114
115         if (evbit[BIT_WORD(EV_SYN)] & BIT_MASK(EV_SYN))
116                 i->using_syn = 1;
117
118         if (i->grab_events == GRAB_EVENTS_WANTED) {
119                 if (ioctl(ts->fd, EVIOCGRAB, (void *)1)) {
120                         fprintf(stderr, "tslib: Unable to grab selected input device\n");
121                         return -1;
122                 }
123                 i->grab_events = GRAB_EVENTS_ACTIVE;
124         }
125
126         return 0;
127 }
128
129 static int ts_input_read(struct tslib_module_info *inf,
130                          struct ts_sample *samp, int nr)
131 {
132         struct tslib_input *i = (struct tslib_input *)inf;
133         struct tsdev *ts = inf->dev;
134         struct input_event ev;
135         int ret = nr;
136         int total = 0;
137         int pen_up = 0;
138
139         if (i->sane_fd == 0)
140                 i->sane_fd = check_fd(i);
141
142         if (i->sane_fd == -1)
143                 return 0;
144
145         if (i->using_syn) {
146                 while (total < nr) {
147                         ret = read(ts->fd, &ev, sizeof(struct input_event));
148                         if (ret < (int)sizeof(struct input_event)) {
149                                 total = -1;
150                                 break;
151                         }
152
153                         switch (ev.type) {
154                         case EV_KEY:
155                                 switch (ev.code) {
156                                 case BTN_TOUCH:
157                                         if (ev.value == 0)
158                                                 pen_up = 1;
159                                         break;
160                                 }
161                                 break;
162                         case EV_SYN:
163                                 /* Fill out a new complete event */
164                                 if (pen_up) {
165                                         samp->x = 0;
166                                         samp->y = 0;
167                                         samp->pressure = 0;
168                                         pen_up = 0;
169                                 } else {
170                                         samp->x = i->current_x;
171                                         samp->y = i->current_y;
172                                         samp->pressure = i->current_p;
173                                 }
174                                 samp->tv = ev.time;
175         #ifdef DEBUG
176                                 fprintf(stderr, "RAW---------------------> %d %d %d %d.%d\n",
177                                                 samp->x, samp->y, samp->pressure, samp->tv.tv_sec,
178                                                 samp->tv.tv_usec);
179         #endif /* DEBUG */
180                                 samp++;
181                                 total++;
182                                 break;
183                         case EV_ABS:
184                                 switch (ev.code) {
185                                 case ABS_X:
186                                         i->current_x = ev.value;
187                                         break;
188                                 case ABS_Y:
189                                         i->current_y = ev.value;
190                                         break;
191                                 case ABS_PRESSURE:
192                                         i->current_p = ev.value;
193                                         break;
194                                 }
195                                 break;
196                         }
197                 }
198                 ret = total;
199         } else {
200                 unsigned char *p = (unsigned char *) &ev;
201                 int len = sizeof(struct input_event);
202
203                 while (total < nr) {
204                         ret = read(ts->fd, p, len);
205                         if (ret == -1) {
206                                 if (errno == EINTR) {
207                                         continue;
208                                 }
209                                 break;
210                         }
211
212                         if (ret < (int)sizeof(struct input_event)) {
213                                 /* short read
214                                  * restart read to get the rest of the event
215                                  */
216                                 p += ret;
217                                 len -= ret;
218                                 continue;
219                         }
220                         /* successful read of a whole event */
221
222                         if (ev.type == EV_ABS) {
223                                 switch (ev.code) {
224                                 case ABS_X:
225                                         if (ev.value != 0) {
226                                                 samp->x = i->current_x = ev.value;
227                                                 samp->y = i->current_y;
228                                                 samp->pressure = i->current_p;
229                                         } else {
230                                                 fprintf(stderr, "tslib: dropped x = 0\n");
231                                                 continue;
232                                         }
233                                         break;
234                                 case ABS_Y:
235                                         if (ev.value != 0) {
236                                                 samp->x = i->current_x;
237                                                 samp->y = i->current_y = ev.value;
238                                                 samp->pressure = i->current_p;
239                                         } else {
240                                                 fprintf(stderr, "tslib: dropped y = 0\n");
241                                                 continue;
242                                         }
243                                         break;
244                                 case ABS_PRESSURE:
245                                         samp->x = i->current_x;
246                                         samp->y = i->current_y;
247                                         samp->pressure = i->current_p = ev.value;
248                                         break;
249                                 }
250                                 samp->tv = ev.time;
251         #ifdef DEBUG
252                                 fprintf(stderr, "RAW---------------------------> %d %d %d\n",
253                                         samp->x, samp->y, samp->pressure);
254         #endif /* DEBUG */
255                                 samp++;
256                                 total++;
257                         } else if (ev.type == EV_KEY) {
258                                 switch (ev.code) {
259                                 case BTN_TOUCH:
260                                         if (ev.value == 0) {
261                                                 /* pen up */
262                                                 samp->x = 0;
263                                                 samp->y = 0;
264                                                 samp->pressure = 0;
265                                                 samp->tv = ev.time;
266                                                 samp++;
267                                                 total++;
268                                         }
269                                         break;
270                                 }
271                         } else {
272                                 fprintf(stderr, "tslib: Unknown event type %d\n", ev.type);
273                         }
274                         p = (unsigned char *) &ev;
275                 }
276                 ret = total;
277         }
278
279         return ret;
280 }
281
282 static int ts_input_fini(struct tslib_module_info *inf)
283 {
284         struct tslib_input *i = (struct tslib_input *)inf;
285         struct tsdev *ts = inf->dev;
286
287         if (i->grab_events == GRAB_EVENTS_ACTIVE) {
288                 if (ioctl(ts->fd, EVIOCGRAB, (void *)0)) {
289                         fprintf(stderr, "tslib: Unable to un-grab selected input device\n");
290                 }
291         }
292
293         free(inf);
294         return 0;
295 }
296
297 static const struct tslib_ops __ts_input_ops = {
298         .read   = ts_input_read,
299         .fini   = ts_input_fini,
300 };
301
302 static int parse_raw_grab(struct tslib_module_info *inf, char *str, void *data)
303 {
304         struct tslib_input *i = (struct tslib_input *)inf;
305         unsigned long v;
306         int err = errno;
307
308         v = strtoul(str, NULL, 0);
309
310         if (v == ULONG_MAX && errno == ERANGE)
311                 return -1;
312
313         errno = err;
314         switch ((int)data) {
315         case 1:
316                 if (v)
317                         i->grab_events = GRAB_EVENTS_WANTED;
318                 break;
319         default:
320                 return -1;
321         }
322         return 0;
323 }
324
325 static const struct tslib_vars raw_vars[] =
326 {
327         { "grab_events", (void *)1, parse_raw_grab },
328 };
329
330 #define NR_VARS (sizeof(raw_vars) / sizeof(raw_vars[0]))
331
332 TSAPI struct tslib_module_info *input_mod_init(struct tsdev *dev, const char *params)
333 {
334         struct tslib_input *i;
335
336         i = malloc(sizeof(struct tslib_input));
337         if (i == NULL)
338                 return NULL;
339
340         i->module.ops = &__ts_input_ops;
341         i->current_x = 0;
342         i->current_y = 0;
343         i->current_p = 0;
344         i->sane_fd = 0;
345         i->using_syn = 0;
346         i->grab_events = 0;
347
348         if (tslib_parse_vars(&i->module, raw_vars, NR_VARS, params)) {
349                 free(i);
350                 return NULL;
351         }
352
353         return &(i->module);
354 }
355
356 #ifndef TSLIB_STATIC_INPUT_MODULE
357         TSLIB_MODULE_INIT(input_mod_init);
358 #endif