1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2007 The Android Open Source Project
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun * You may obtain a copy of the License at
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun * limitations under the License.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <stdio.h>
18*4882a593Smuzhiyun #include <stdlib.h>
19*4882a593Smuzhiyun #include <string.h>
20*4882a593Smuzhiyun #include <fcntl.h>
21*4882a593Smuzhiyun #include <dirent.h>
22*4882a593Smuzhiyun #include <sys/epoll.h>
23*4882a593Smuzhiyun #include <unistd.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <linux/input.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include "minui.h"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include <sys/poll.h>
30*4882a593Smuzhiyun #include "../common.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define MAX_DEVICES 16
34*4882a593Smuzhiyun #define MAX_MISC_FDS 16
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define BITS_PER_LONG (sizeof(unsigned long) * 8)
37*4882a593Smuzhiyun #define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define test_bit(bit, array) \
40*4882a593Smuzhiyun ((array)[(bit)/BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun struct fd_info {
43*4882a593Smuzhiyun int fd;
44*4882a593Smuzhiyun ev_callback cb;
45*4882a593Smuzhiyun void *data;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static int epollfd;
49*4882a593Smuzhiyun static struct epoll_event polledevents[MAX_DEVICES + MAX_MISC_FDS];
50*4882a593Smuzhiyun static int npolledevents;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun static struct fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS];
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static unsigned ev_count = 0;
55*4882a593Smuzhiyun static unsigned ev_dev_count = 0;
56*4882a593Smuzhiyun static unsigned ev_misc_count = 0;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun ///////////////////////////////////////////////////////////////////////////////
59*4882a593Smuzhiyun // add for tp
60*4882a593Smuzhiyun //#define _EVENT_LOGGING 0
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #define VIBRATOR_TIMEOUT_FILE "/sys/class/timed_output/vibrator/enable"
63*4882a593Smuzhiyun #define VIBRATOR_TIME_MS 50
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define SYN_REPORT 0x00
66*4882a593Smuzhiyun #define SYN_CONFIG 0x01
67*4882a593Smuzhiyun #define SYN_MT_REPORT 0x02
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define ABS_MT_POSITION 0x2a /* Group a set of X and Y */
70*4882a593Smuzhiyun #define ABS_MT_AMPLITUDE 0x2b /* Group a set of Z and W */
71*4882a593Smuzhiyun #define ABS_MT_SLOT 0x2f
72*4882a593Smuzhiyun #define ABS_MT_TOUCH_MAJOR 0x30
73*4882a593Smuzhiyun #define ABS_MT_TOUCH_MINOR 0x31
74*4882a593Smuzhiyun #define ABS_MT_WIDTH_MAJOR 0x32
75*4882a593Smuzhiyun #define ABS_MT_WIDTH_MINOR 0x33
76*4882a593Smuzhiyun #define ABS_MT_ORIENTATION 0x34
77*4882a593Smuzhiyun #define ABS_MT_POSITION_X 0x35
78*4882a593Smuzhiyun #define ABS_MT_POSITION_Y 0x36
79*4882a593Smuzhiyun #define ABS_MT_TOOL_TYPE 0x37
80*4882a593Smuzhiyun #define ABS_MT_BLOB_ID 0x38
81*4882a593Smuzhiyun #define ABS_MT_TRACKING_ID 0x39
82*4882a593Smuzhiyun #define ABS_MT_PRESSURE 0x3a
83*4882a593Smuzhiyun #define ABS_MT_DISTANCE 0x3b
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun enum {
86*4882a593Smuzhiyun DOWN_NOT,
87*4882a593Smuzhiyun DOWN_SENT,
88*4882a593Smuzhiyun DOWN_RELEASED,
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun struct virtualkey {
92*4882a593Smuzhiyun int scancode;
93*4882a593Smuzhiyun int centerx, centery;
94*4882a593Smuzhiyun int width, height;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun struct position {
98*4882a593Smuzhiyun int x, y;
99*4882a593Smuzhiyun int synced;
100*4882a593Smuzhiyun struct input_absinfo xi, yi;
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun struct ev {
104*4882a593Smuzhiyun struct pollfd *fd;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun struct virtualkey *vks;
107*4882a593Smuzhiyun int vk_count;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun char deviceName[64];
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun int ignored;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun struct position p, mt_p;
114*4882a593Smuzhiyun int down;
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun static struct pollfd ev_fds[MAX_DEVICES];
117*4882a593Smuzhiyun static struct ev evs[MAX_DEVICES];
118*4882a593Smuzhiyun
ABS(int x)119*4882a593Smuzhiyun static inline int ABS(int x) {
120*4882a593Smuzhiyun return x<0?-x:x;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
vibrate(int timeout_ms)123*4882a593Smuzhiyun int vibrate(int timeout_ms)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun char str[20];
126*4882a593Smuzhiyun int fd;
127*4882a593Smuzhiyun int ret;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun fd = open(VIBRATOR_TIMEOUT_FILE, O_WRONLY);
130*4882a593Smuzhiyun if (fd < 0)
131*4882a593Smuzhiyun return -1;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun ret = snprintf(str, sizeof(str), "%d", timeout_ms);
134*4882a593Smuzhiyun ret = write(fd, str, ret);
135*4882a593Smuzhiyun close(fd);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if (ret < 0)
138*4882a593Smuzhiyun return -1;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* Returns empty tokens */
vk_strtok_r(char * str,const char * delim,char ** save_str)144*4882a593Smuzhiyun static char *vk_strtok_r(char *str, const char *delim, char **save_str)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun if(!str)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun if(!*save_str)
149*4882a593Smuzhiyun return NULL;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun str = (*save_str) + 1;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun *save_str = strpbrk(str, delim);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (*save_str)
156*4882a593Smuzhiyun **save_str = '\0';
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun return str;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
vk_init(struct ev * e)161*4882a593Smuzhiyun static int vk_init(struct ev *e)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun char vk_path[PATH_MAX] = "/sys/board_properties/virtualkeys.";
164*4882a593Smuzhiyun char vks[2048], *ts = NULL;
165*4882a593Smuzhiyun ssize_t len;
166*4882a593Smuzhiyun int vk_fd;
167*4882a593Smuzhiyun int i;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun e->vk_count = 0;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun len = strlen(vk_path);
172*4882a593Smuzhiyun len = ioctl(e->fd->fd, EVIOCGNAME(sizeof(e->deviceName)), e->deviceName);
173*4882a593Smuzhiyun if (len <= 0)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun LOGE("Unable to query event object.\n");
176*4882a593Smuzhiyun return -1;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
179*4882a593Smuzhiyun LOGI("Event object: %s\n", e->deviceName);
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun // Blacklist these "input" devices
183*4882a593Smuzhiyun if (strcmp(e->deviceName, "bma250") == 0)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun e->ignored = 1;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun strcat(vk_path, e->deviceName);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun // Some devices split the keys from the touchscreen
191*4882a593Smuzhiyun e->vk_count = 0;
192*4882a593Smuzhiyun vk_fd = open(vk_path, O_RDONLY);
193*4882a593Smuzhiyun if (vk_fd >= 0)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun len = read(vk_fd, vks, sizeof(vks)-1);
196*4882a593Smuzhiyun close(vk_fd);
197*4882a593Smuzhiyun if (len <= 0)
198*4882a593Smuzhiyun return -1;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun vks[len] = '\0';
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* Parse a line like:
203*4882a593Smuzhiyun keytype:keycode:centerx:centery:width:height:keytype2:keycode2:centerx2:...
204*4882a593Smuzhiyun */
205*4882a593Smuzhiyun for (ts = vks, e->vk_count = 1; *ts; ++ts) {
206*4882a593Smuzhiyun if (*ts == ':')
207*4882a593Smuzhiyun ++e->vk_count;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (e->vk_count % 6) {
211*4882a593Smuzhiyun LOGW("minui: %s is %d %% 6\n", vk_path, e->vk_count % 6);
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun e->vk_count /= 6;
214*4882a593Smuzhiyun if (e->vk_count <= 0)
215*4882a593Smuzhiyun return -1;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun e->down = DOWN_NOT;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun ioctl(e->fd->fd, EVIOCGABS(ABS_X), &e->p.xi);
221*4882a593Smuzhiyun ioctl(e->fd->fd, EVIOCGABS(ABS_Y), &e->p.yi);
222*4882a593Smuzhiyun e->p.synced = 0;
223*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
224*4882a593Smuzhiyun LOGI("EV: ST minX: %d maxX: %d minY: %d maxY: %d\n", e->p.xi.minimum, e->p.xi.maximum, e->p.yi.minimum, e->p.yi.maximum);
225*4882a593Smuzhiyun #endif
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_X), &e->mt_p.xi);
228*4882a593Smuzhiyun ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_Y), &e->mt_p.yi);
229*4882a593Smuzhiyun e->mt_p.synced = 0;
230*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
231*4882a593Smuzhiyun LOGI("EV: MT minX: %d maxX: %d minY: %d maxY: %d\n", e->mt_p.xi.minimum, e->mt_p.xi.maximum, e->mt_p.yi.minimum, e->mt_p.yi.maximum);
232*4882a593Smuzhiyun #endif
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun e->vks = malloc(sizeof(*e->vks) * e->vk_count);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun for (i = 0; i < e->vk_count; ++i) {
237*4882a593Smuzhiyun char *token[6];
238*4882a593Smuzhiyun int j;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun for (j = 0; j < 6; ++j) {
241*4882a593Smuzhiyun token[j] = vk_strtok_r((i||j)?NULL:vks, ":", &ts);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun if (strcmp(token[0], "0x01") != 0) {
245*4882a593Smuzhiyun /* Java does string compare, so we do too. */
246*4882a593Smuzhiyun LOGW("minui: %s: ignoring unknown virtual key type %s\n", vk_path, token[0]);
247*4882a593Smuzhiyun continue;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun e->vks[i].scancode = strtol(token[1], NULL, 0);
251*4882a593Smuzhiyun e->vks[i].centerx = strtol(token[2], NULL, 0);
252*4882a593Smuzhiyun e->vks[i].centery = strtol(token[3], NULL, 0);
253*4882a593Smuzhiyun e->vks[i].width = strtol(token[4], NULL, 0);
254*4882a593Smuzhiyun e->vks[i].height = strtol(token[5], NULL, 0);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun ///////////////////////////////////////////////////////////////////////////////
261*4882a593Smuzhiyun // Add for tp
262*4882a593Smuzhiyun //
ev_init(void)263*4882a593Smuzhiyun int ev_init(void)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun DIR *dir;
266*4882a593Smuzhiyun struct dirent *de;
267*4882a593Smuzhiyun int fd;
268*4882a593Smuzhiyun char name[80];
269*4882a593Smuzhiyun dir = opendir("/dev/input");
270*4882a593Smuzhiyun if(dir != 0) {
271*4882a593Smuzhiyun while((de = readdir(dir))) {
272*4882a593Smuzhiyun // fprintf(stderr,"/dev/input/%s\n", de->d_name);
273*4882a593Smuzhiyun if(strncmp(de->d_name,"event",5))
274*4882a593Smuzhiyun continue;
275*4882a593Smuzhiyun fd = openat(dirfd(dir), de->d_name, O_RDONLY);
276*4882a593Smuzhiyun if(fd < 0) continue;
277*4882a593Smuzhiyun else
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun name[0] = '\0';
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun if (!strcmp(name, "gsensor")) //do not open gsensor here
284*4882a593Smuzhiyun continue;
285*4882a593Smuzhiyun LOGI("open %s\n",de->d_name);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun ev_fds[ev_count].fd = fd;
288*4882a593Smuzhiyun ev_fds[ev_count].events = POLLIN;
289*4882a593Smuzhiyun evs[ev_count].fd = &ev_fds[ev_count];
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun /* Load virtualkeys if there are any */
292*4882a593Smuzhiyun vk_init(&evs[ev_count]);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun ev_count++;
295*4882a593Smuzhiyun if(ev_count == MAX_DEVICES) break;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun return 0;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
ev_exit(void)302*4882a593Smuzhiyun void ev_exit(void)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun while (ev_count-- > 0) {
305*4882a593Smuzhiyun if (evs[ev_count].vk_count) {
306*4882a593Smuzhiyun free(evs[ev_count].vks);
307*4882a593Smuzhiyun evs[ev_count].vk_count = 0;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun close(ev_fds[ev_count].fd);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
vk_inside_display(__s32 value,struct input_absinfo * info,int screen_size)313*4882a593Smuzhiyun static int vk_inside_display(__s32 value, struct input_absinfo *info, int screen_size)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun int screen_pos;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun if (info->minimum == info->maximum)
318*4882a593Smuzhiyun return 0;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun screen_pos = (value - info->minimum) * (screen_size - 1) / (info->maximum - info->minimum);
321*4882a593Smuzhiyun return (screen_pos >= 0 && screen_pos < screen_size);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
vk_tp_to_screen(struct position * p,int * x,int * y)324*4882a593Smuzhiyun static int vk_tp_to_screen(struct position *p, int *x, int *y)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun if (p->xi.minimum == p->xi.maximum || p->yi.minimum == p->yi.maximum)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun // In this case, we assume the screen dimensions are the same.
329*4882a593Smuzhiyun *x = p->x;
330*4882a593Smuzhiyun *y = p->y;
331*4882a593Smuzhiyun return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
335*4882a593Smuzhiyun LOGI("EV: p->x=%d x-range=%d,%d fb-width=%d\n", p->x, p->xi.minimum, p->xi.maximum, gr_fb_width());
336*4882a593Smuzhiyun #endif
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun #ifndef RECOVERY_TOUCHSCREEN_SWAP_XY
339*4882a593Smuzhiyun int fb_width = gr_fb_width();
340*4882a593Smuzhiyun int fb_height = gr_fb_height();
341*4882a593Smuzhiyun #else
342*4882a593Smuzhiyun // We need to swap the scaling sizes, too
343*4882a593Smuzhiyun int fb_width = gr_fb_height();
344*4882a593Smuzhiyun int fb_height = gr_fb_width();
345*4882a593Smuzhiyun #endif
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun *x = (p->x - p->xi.minimum) * (fb_width - 1) / (p->xi.maximum - p->xi.minimum);
348*4882a593Smuzhiyun *y = (p->y - p->yi.minimum) * (fb_height - 1) / (p->yi.maximum - p->yi.minimum);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (*x >= 0 && *x < fb_width &&
351*4882a593Smuzhiyun *y >= 0 && *y < fb_height)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return 1;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /* Translate a virtual key in to a real key event, if needed */
360*4882a593Smuzhiyun /* Returns non-zero when the event should be consumed */
vk_modify(struct ev * e,struct input_event * ev)361*4882a593Smuzhiyun static int vk_modify(struct ev *e, struct input_event *ev)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun static int downX = -1, downY = -1;
364*4882a593Smuzhiyun static int discard = 0;
365*4882a593Smuzhiyun static int lastWasSynReport = 0;
366*4882a593Smuzhiyun static int touchReleaseOnNextSynReport = 0;
367*4882a593Smuzhiyun int i;
368*4882a593Smuzhiyun int x, y;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun // This is used to ditch useless event handlers, like an accelerometer
371*4882a593Smuzhiyun if (e->ignored) return 1;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun if (ev->type == EV_REL && ev->code == REL_Z)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun // This appears to be an accelerometer or another strange input device. It's not the touchscreen.
376*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
377*4882a593Smuzhiyun LOGI("EV: Device disabled due to non-touchscreen messages.\n");
378*4882a593Smuzhiyun #endif
379*4882a593Smuzhiyun e->ignored = 1;
380*4882a593Smuzhiyun return 1;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
384*4882a593Smuzhiyun LOGI("EV: %s => type: %x code: %x value: %d\n", e->deviceName, ev->type, ev->code, ev->value);
385*4882a593Smuzhiyun #endif
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun // Handle keyboard events, value of 1 indicates key down, 0 indicates key up
388*4882a593Smuzhiyun if (ev->type == EV_KEY) {
389*4882a593Smuzhiyun return 0;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun if (ev->type == EV_ABS) {
393*4882a593Smuzhiyun switch (ev->code) {
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun case ABS_X: //00
396*4882a593Smuzhiyun e->p.synced |= 0x01;
397*4882a593Smuzhiyun e->p.x = ev->value;
398*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
399*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_X %d\n", e->deviceName, ev->value);
400*4882a593Smuzhiyun #endif
401*4882a593Smuzhiyun break;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun case ABS_Y: //01
404*4882a593Smuzhiyun e->p.synced |= 0x02;
405*4882a593Smuzhiyun e->p.y = ev->value;
406*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
407*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_Y %d\n", e->deviceName, ev->value);
408*4882a593Smuzhiyun #endif
409*4882a593Smuzhiyun break;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun case ABS_MT_POSITION: //2a
412*4882a593Smuzhiyun e->mt_p.synced = 0x03;
413*4882a593Smuzhiyun if (ev->value == (1 << 31))
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun e->mt_p.x = 0;
416*4882a593Smuzhiyun e->mt_p.y = 0;
417*4882a593Smuzhiyun lastWasSynReport = 1;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun else
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun lastWasSynReport = 0;
422*4882a593Smuzhiyun e->mt_p.x = (ev->value & 0x7FFF0000) >> 16;
423*4882a593Smuzhiyun e->mt_p.y = (ev->value & 0xFFFF);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun break;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun case ABS_MT_TOUCH_MAJOR: //30
428*4882a593Smuzhiyun if (ev->value == 0)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun // We're in a touch release, although some devices will still send positions as well
431*4882a593Smuzhiyun e->mt_p.x = 0;
432*4882a593Smuzhiyun e->mt_p.y = 0;
433*4882a593Smuzhiyun touchReleaseOnNextSynReport = 1;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
436*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_TOUCH_MAJOR %d\n", e->deviceName, ev->value);
437*4882a593Smuzhiyun #endif
438*4882a593Smuzhiyun break;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun case ABS_MT_PRESSURE: //3a
441*4882a593Smuzhiyun if (ev->value == 0)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun // We're in a touch release, although some devices will still send positions as well
444*4882a593Smuzhiyun e->mt_p.x = 0;
445*4882a593Smuzhiyun e->mt_p.y = 0;
446*4882a593Smuzhiyun touchReleaseOnNextSynReport = 1;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
449*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_PRESSURE %d\n", e->deviceName, ev->value);
450*4882a593Smuzhiyun #endif
451*4882a593Smuzhiyun break;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun case ABS_MT_POSITION_X: //35
454*4882a593Smuzhiyun e->mt_p.synced |= 0x01;
455*4882a593Smuzhiyun e->mt_p.x = ev->value;
456*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
457*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_POSITION_X %d\n", e->deviceName, ev->value);
458*4882a593Smuzhiyun #endif
459*4882a593Smuzhiyun break;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun case ABS_MT_POSITION_Y: //36
462*4882a593Smuzhiyun e->mt_p.synced |= 0x02;
463*4882a593Smuzhiyun e->mt_p.y = ev->value;
464*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
465*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_POSITION_Y %d\n", e->deviceName, ev->value);
466*4882a593Smuzhiyun #endif
467*4882a593Smuzhiyun break;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
470*4882a593Smuzhiyun // All of these items are strictly for logging purposes only. Return 1 because they don't need to be handled.
471*4882a593Smuzhiyun case ABS_MT_TOUCH_MINOR: //31
472*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_TOUCH_MINOR %d\n", e->deviceName, ev->value);
473*4882a593Smuzhiyun return 1;
474*4882a593Smuzhiyun break;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun case ABS_MT_WIDTH_MAJOR: //32
477*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_WIDTH_MAJOR %d\n", e->deviceName, ev->value);
478*4882a593Smuzhiyun return 1;
479*4882a593Smuzhiyun break;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun case ABS_MT_WIDTH_MINOR: //33
482*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_WIDTH_MINOR %d\n", e->deviceName, ev->value);
483*4882a593Smuzhiyun return 1;
484*4882a593Smuzhiyun break;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun case ABS_MT_ORIENTATION: //34
487*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_ORIENTATION %d\n", e->deviceName, ev->value);
488*4882a593Smuzhiyun return 1;
489*4882a593Smuzhiyun break;
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun case ABS_MT_TOOL_TYPE: //37
492*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_TOOL_TYPE %d\n", e->deviceName, ev->value);
493*4882a593Smuzhiyun return 1;
494*4882a593Smuzhiyun break;
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun case ABS_MT_BLOB_ID: //38
497*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_BLOB_ID %d\n", e->deviceName, ev->value);
498*4882a593Smuzhiyun return 1;
499*4882a593Smuzhiyun break;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun case ABS_MT_TRACKING_ID: //39
502*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_TRACKING_ID %d\n", e->deviceName, ev->value);
503*4882a593Smuzhiyun return 1;
504*4882a593Smuzhiyun break;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun case ABS_MT_DISTANCE: //3b
507*4882a593Smuzhiyun LOGI("EV: %s => EV_ABS ABS_MT_DISTANCE %d\n", e->deviceName, ev->value);
508*4882a593Smuzhiyun return 1;
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun #endif
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun default:
513*4882a593Smuzhiyun // This is an unhandled message, just skip it
514*4882a593Smuzhiyun return 1;
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (ev->code != ABS_MT_POSITION)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun lastWasSynReport = 0;
520*4882a593Smuzhiyun return 1;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun // Check if we should ignore the message
525*4882a593Smuzhiyun if (ev->code != ABS_MT_POSITION && (ev->type != EV_SYN || (ev->code != SYN_REPORT && ev->code != SYN_MT_REPORT)))
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun lastWasSynReport = 0;
528*4882a593Smuzhiyun return 0;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
532*4882a593Smuzhiyun if (ev->type == EV_SYN && ev->code == SYN_REPORT) LOGI("EV: %s => EV_SYN SYN_REPORT\n", e->deviceName);
533*4882a593Smuzhiyun if (ev->type == EV_SYN && ev->code == SYN_MT_REPORT) LOGI("EV: %s => EV_SYN SYN_MT_REPORT\n", e->deviceName);
534*4882a593Smuzhiyun #endif
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun // Discard the MT versions
537*4882a593Smuzhiyun if (ev->code == SYN_MT_REPORT) return 0;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun if (lastWasSynReport == 1 || touchReleaseOnNextSynReport == 1)
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun // Reset the value
542*4882a593Smuzhiyun touchReleaseOnNextSynReport = 0;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun // We are a finger-up state
545*4882a593Smuzhiyun if (!discard)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun // Report the key up
548*4882a593Smuzhiyun ev->type = EV_ABS;
549*4882a593Smuzhiyun ev->code = 0;
550*4882a593Smuzhiyun ev->value = (downX << 16) | downY;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun downX = -1;
553*4882a593Smuzhiyun downY = -1;
554*4882a593Smuzhiyun if (discard)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun discard = 0;
557*4882a593Smuzhiyun return 1;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun return 0;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun lastWasSynReport = 1;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun // Retrieve where the x,y position is
564*4882a593Smuzhiyun if (e->p.synced & 0x03)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun vk_tp_to_screen(&e->p, &x, &y);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun else if (e->mt_p.synced & 0x03)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun vk_tp_to_screen(&e->mt_p, &x, &y);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun else
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun // We don't have useful information to convey
575*4882a593Smuzhiyun return 1;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun #ifdef RECOVERY_TOUCHSCREEN_SWAP_XY
579*4882a593Smuzhiyun x ^= y;
580*4882a593Smuzhiyun y ^= x;
581*4882a593Smuzhiyun x ^= y;
582*4882a593Smuzhiyun #endif
583*4882a593Smuzhiyun #ifdef RECOVERY_TOUCHSCREEN_FLIP_X
584*4882a593Smuzhiyun x = gr_fb_width() - x;
585*4882a593Smuzhiyun #endif
586*4882a593Smuzhiyun #ifdef RECOVERY_TOUCHSCREEN_FLIP_Y
587*4882a593Smuzhiyun y = gr_fb_height() - y;
588*4882a593Smuzhiyun #endif
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun #ifdef _EVENT_LOGGING
591*4882a593Smuzhiyun LOGI("EV: x: %d y: %d\n", x, y);
592*4882a593Smuzhiyun #endif
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun // Clear the current sync states
595*4882a593Smuzhiyun e->p.synced = e->mt_p.synced = 0;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun // If we have nothing useful to report, skip it
598*4882a593Smuzhiyun if (x == -1 || y == -1) return 1;
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun // On first touch, see if we're at a virtual key
601*4882a593Smuzhiyun if (downX == -1)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun // Attempt mapping to virtual key
604*4882a593Smuzhiyun for (i = 0; i < e->vk_count; ++i)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun int xd = ABS(e->vks[i].centerx - x);
607*4882a593Smuzhiyun int yd = ABS(e->vks[i].centery - y);
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun if (xd < e->vks[i].width/2 && yd < e->vks[i].height/2)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun ev->type = EV_KEY;
612*4882a593Smuzhiyun ev->code = e->vks[i].scancode;
613*4882a593Smuzhiyun ev->value = 1;
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun vibrate(VIBRATOR_TIME_MS);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun // Mark that all further movement until lift is discard,
618*4882a593Smuzhiyun // and make sure we don't come back into this area
619*4882a593Smuzhiyun discard = 1;
620*4882a593Smuzhiyun downX = 0;
621*4882a593Smuzhiyun return 0;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun // If we were originally a button press, discard this event
627*4882a593Smuzhiyun if (discard)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun return 1;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun // Record where we started the touch for deciding if this is a key or a scroll
633*4882a593Smuzhiyun downX = x;
634*4882a593Smuzhiyun downY = y;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun ev->type = EV_ABS;
637*4882a593Smuzhiyun ev->code = 1;
638*4882a593Smuzhiyun ev->value = (x << 16) | y;
639*4882a593Smuzhiyun return 0;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
ev_get(struct input_event * ev,unsigned dont_wait)642*4882a593Smuzhiyun int ev_get(struct input_event *ev, unsigned dont_wait)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun int r;
645*4882a593Smuzhiyun unsigned n;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun do {
648*4882a593Smuzhiyun r = poll(ev_fds, ev_count, dont_wait ? 0 : -1);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun if(r > 0) {
651*4882a593Smuzhiyun for(n = 0; n < ev_count; n++) {
652*4882a593Smuzhiyun if(ev_fds[n].revents & POLLIN) {
653*4882a593Smuzhiyun r = read(ev_fds[n].fd, ev, sizeof(*ev));
654*4882a593Smuzhiyun if(r == sizeof(*ev)) {
655*4882a593Smuzhiyun if (!vk_modify(&evs[n], ev))
656*4882a593Smuzhiyun return 0;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun } while(dont_wait == 0);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun return -1;
664*4882a593Smuzhiyun }
665