Tizen 2.0 Release
[adaptation/xorg-x11-drv-synaptics.git] / src / eventcomm.c
1 /*
2  * Copyright © 2004-2007 Peter Osterlund
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of Red Hat
9  * not be used in advertising or publicity pertaining to distribution
10  * of the software without specific, written prior permission.  Red
11  * Hat makes no representations about the suitability of this software
12  * for any purpose.  It is provided "as is" without express or implied
13  * warranty.
14  *
15  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors:
24  *      Peter Osterlund (petero2@telia.com)
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <xorg-server.h>
32 #include "eventcomm.h"
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <dirent.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include "synproto.h"
41 #include "synaptics.h"
42 #include "synapticsstr.h"
43 #include <xf86.h>
44
45
46 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
47
48 #define LONG_BITS (sizeof(long) * 8)
49 #define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
50 #define OFF(x)   ((x) % LONG_BITS)
51 #define LONG(x)  ((x) / LONG_BITS)
52 #define TEST_BIT(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
53
54 /*****************************************************************************
55  *      Function Definitions
56  ****************************************************************************/
57
58 static void
59 EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para)
60 {
61     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
62     BOOL *need_grab;
63
64     if (!priv->proto_data)
65         priv->proto_data = calloc(1, sizeof(BOOL));
66
67     need_grab = (BOOL*)priv->proto_data;
68
69     if (para->grab_event_device) {
70         /* Try to grab the event device so that data don't leak to /dev/input/mice */
71         int ret;
72         SYSCALL(ret = ioctl(pInfo->fd, EVIOCGRAB, (pointer)1));
73         if (ret < 0) {
74             xf86Msg(X_WARNING, "%s can't grab event device, errno=%d\n",
75                     pInfo->name, errno);
76         }
77     }
78
79     *need_grab = FALSE;
80 }
81
82 static Bool
83 event_query_is_touchpad(int fd, BOOL grab)
84 {
85     int ret = FALSE, rc;
86     unsigned long evbits[NBITS(EV_MAX)] = {0};
87     unsigned long absbits[NBITS(ABS_MAX)] = {0};
88     unsigned long keybits[NBITS(KEY_MAX)] = {0};
89
90     if (grab)
91     {
92         SYSCALL(rc = ioctl(fd, EVIOCGRAB, (pointer)1));
93         if (rc < 0)
94             return FALSE;
95     }
96
97     /* Check for ABS_X, ABS_Y, ABS_PRESSURE and BTN_TOOL_FINGER */
98
99     SYSCALL(rc = ioctl(fd, EVIOCGBIT(0, sizeof(evbits)), evbits));
100     if (rc < 0)
101         goto unwind;
102     if (!TEST_BIT(EV_SYN, evbits) ||
103         !TEST_BIT(EV_ABS, evbits) ||
104         !TEST_BIT(EV_KEY, evbits))
105         goto unwind;
106
107     SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
108     if (rc < 0)
109         goto unwind;
110     if (!TEST_BIT(ABS_X, absbits) ||
111         !TEST_BIT(ABS_Y, absbits))
112         goto unwind;
113
114     SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
115     if (rc < 0)
116         goto unwind;
117
118     /* we expect touchpad either report raw pressure or touches */
119     if (!TEST_BIT(ABS_PRESSURE, absbits) && !TEST_BIT(BTN_TOUCH, keybits))
120         goto unwind;
121     /* all Synaptics-like touchpad report BTN_TOOL_FINGER */
122     if (!TEST_BIT(BTN_TOOL_FINGER, keybits))
123         goto unwind;
124     if (TEST_BIT(BTN_TOOL_PEN, keybits))
125         goto unwind;                        /* Don't match wacom tablets */
126
127     ret = TRUE;
128
129 unwind:
130     if (grab)
131         SYSCALL(ioctl(fd, EVIOCGRAB, (pointer)0));
132
133     return (ret == TRUE);
134 }
135
136 typedef struct {
137         short vendor;
138         short product;
139         enum TouchpadModel model;
140 } model_lookup_t;
141 #define PRODUCT_ANY 0x0000
142
143 static model_lookup_t model_lookup_table[] = {
144         {0x0002, 0x0007, MODEL_SYNAPTICS},
145         {0x0002, 0x0008, MODEL_ALPS},
146         {0x05ac, PRODUCT_ANY, MODEL_APPLETOUCH},
147         {0x0, 0x0, 0x0}
148 };
149
150 static void
151 event_query_info(InputInfoPtr pInfo)
152 {
153     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
154     short id[4];
155     int rc;
156     model_lookup_t *model_lookup;
157
158     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGID, id));
159     if (rc < 0)
160         return;
161
162     for(model_lookup = model_lookup_table; model_lookup->vendor; model_lookup++) {
163         if(model_lookup->vendor == id[ID_VENDOR] &&
164            (model_lookup->product == id[ID_PRODUCT] || model_lookup->product == PRODUCT_ANY))
165             priv->model = model_lookup->model;
166     }
167 }
168
169 /* Query device for axis ranges */
170 static void
171 event_query_axis_ranges(InputInfoPtr pInfo)
172 {
173     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
174     struct input_absinfo abs = {0};
175     unsigned long absbits[NBITS(ABS_MAX)] = {0};
176     unsigned long keybits[NBITS(KEY_MAX)] = {0};
177     char buf[256];
178     int rc;
179
180     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGABS(ABS_X), &abs));
181     if (rc >= 0)
182     {
183         xf86Msg(X_PROBED, "%s: x-axis range %d - %d\n", pInfo->name,
184                 abs.minimum, abs.maximum);
185         priv->minx = abs.minimum;
186         priv->maxx = abs.maximum;
187         /* The kernel's fuzziness concept seems a bit weird, but it can more or
188          * less be applied as hysteresis directly, i.e. no factor here. Though,
189          * we don't trust a zero fuzz as it probably is just a lazy value. */
190         if (abs.fuzz > 0)
191             priv->synpara.hyst_x = abs.fuzz;
192 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
193         priv->resx = abs.resolution;
194 #endif
195     } else
196         xf86Msg(X_ERROR, "%s: failed to query axis range (%s)\n", pInfo->name,
197                 strerror(errno));
198
199     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGABS(ABS_Y), &abs));
200     if (rc >= 0)
201     {
202         xf86Msg(X_PROBED, "%s: y-axis range %d - %d\n", pInfo->name,
203                 abs.minimum, abs.maximum);
204         priv->miny = abs.minimum;
205         priv->maxy = abs.maximum;
206         /* don't trust a zero fuzz */
207         if (abs.fuzz > 0)
208             priv->synpara.hyst_y = abs.fuzz;
209 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
210         priv->resy = abs.resolution;
211 #endif
212     } else
213         xf86Msg(X_ERROR, "%s: failed to query axis range (%s)\n", pInfo->name,
214                 strerror(errno));
215
216     priv->has_pressure = FALSE;
217     priv->has_width = FALSE;
218     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
219     if (rc >= 0)
220     {
221         priv->has_pressure = (TEST_BIT(ABS_PRESSURE, absbits) != 0);
222         priv->has_width = (TEST_BIT(ABS_TOOL_WIDTH, absbits) != 0);
223     }
224     else
225         xf86Msg(X_ERROR, "%s: failed to query ABS bits (%s)\n", pInfo->name,
226                 strerror(errno));
227
228     if (priv->has_pressure)
229     {
230         SYSCALL(rc = ioctl(pInfo->fd, EVIOCGABS(ABS_PRESSURE), &abs));
231         if (rc >= 0)
232         {
233             xf86Msg(X_PROBED, "%s: pressure range %d - %d\n", pInfo->name,
234                     abs.minimum, abs.maximum);
235             priv->minp = abs.minimum;
236             priv->maxp = abs.maximum;
237         }
238     } else
239         xf86Msg(X_INFO,
240                 "%s: device does not report pressure, will use touch data.\n",
241                 pInfo->name);
242
243     if (priv->has_width)
244     {
245         SYSCALL(rc = ioctl(pInfo->fd, EVIOCGABS(ABS_TOOL_WIDTH), &abs));
246         if (rc >= 0)
247         {
248             xf86Msg(X_PROBED, "%s: finger width range %d - %d\n", pInfo->name,
249                     abs.minimum, abs.maximum);
250             priv->minw = abs.minimum;
251             priv->maxw = abs.maximum;
252         }
253     }
254
255     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
256     if (rc >= 0)
257     {
258         buf[0] = 0;
259         if ((priv->has_left = (TEST_BIT(BTN_LEFT, keybits) != 0)))
260            strcat(buf, " left");
261         if ((priv->has_right = (TEST_BIT(BTN_RIGHT, keybits) != 0)))
262            strcat(buf, " right");
263         if ((priv->has_middle = (TEST_BIT(BTN_MIDDLE, keybits) != 0)))
264            strcat(buf, " middle");
265         if ((priv->has_double = (TEST_BIT(BTN_TOOL_DOUBLETAP, keybits) != 0)))
266            strcat(buf, " double");
267         if ((priv->has_triple = (TEST_BIT(BTN_TOOL_TRIPLETAP, keybits) != 0)))
268            strcat(buf, " triple");
269
270         if ((TEST_BIT(BTN_0, keybits) != 0) ||
271             (TEST_BIT(BTN_1, keybits) != 0) ||
272             (TEST_BIT(BTN_2, keybits) != 0) ||
273             (TEST_BIT(BTN_3, keybits) != 0))
274         {
275             priv->has_scrollbuttons = 1;
276             strcat(buf, " scroll-buttons");
277         }
278
279         xf86Msg(X_PROBED, "%s: buttons:%s\n", pInfo->name, buf);
280     }
281 }
282
283 static Bool
284 EventQueryHardware(InputInfoPtr pInfo)
285 {
286     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
287     BOOL *need_grab = (BOOL*)priv->proto_data;
288
289     if (!event_query_is_touchpad(pInfo->fd, (need_grab) ? *need_grab : TRUE))
290         return FALSE;
291
292     xf86Msg(X_PROBED, "%s: touchpad found\n", pInfo->name);
293
294     return TRUE;
295 }
296
297 static Bool
298 SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
299 {
300     int rc = TRUE;
301     ssize_t len;
302
303     len = read(pInfo->fd, ev, sizeof(*ev));
304     if (len <= 0)
305     {
306         /* We use X_NONE here because it doesn't alloc */
307         if (errno != EAGAIN)
308             xf86MsgVerb(X_NONE, 0, "%s: Read error %s\n", pInfo->name, strerror(errno));
309         rc = FALSE;
310     } else if (len % sizeof(*ev)) {
311         xf86MsgVerb(X_NONE, 0, "%s: Read error, invalid number of bytes.", pInfo->name);
312         rc = FALSE;
313     }
314     return rc;
315 }
316
317 static Bool
318 EventReadHwState(InputInfoPtr pInfo,
319                  struct SynapticsProtocolOperations *proto_ops,
320                  struct CommData *comm, struct SynapticsHwState *hwRet)
321 {
322     struct input_event ev;
323     Bool v;
324     struct SynapticsHwState *hw = &(comm->hwState);
325     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
326     SynapticsParameters *para = &priv->synpara;
327
328     while (SynapticsReadEvent(pInfo, &ev)) {
329         switch (ev.type) {
330         case EV_SYN:
331             switch (ev.code) {
332             case SYN_REPORT:
333                 if (comm->oneFinger)
334                     hw->numFingers = 1;
335                 else if (comm->twoFingers)
336                     hw->numFingers = 2;
337                 else if (comm->threeFingers)
338                     hw->numFingers = 3;
339                 else
340                     hw->numFingers = 0;
341                 *hwRet = *hw;
342                 return TRUE;
343             }
344         case EV_KEY:
345             v = (ev.value ? TRUE : FALSE);
346             switch (ev.code) {
347             case BTN_LEFT:
348                 hw->left = v;
349                 break;
350             case BTN_RIGHT:
351                 hw->right = v;
352                 break;
353             case BTN_MIDDLE:
354                 hw->middle = v;
355                 break;
356             case BTN_FORWARD:
357                 hw->up = v;
358                 break;
359             case BTN_BACK:
360                 hw->down = v;
361                 break;
362             case BTN_0:
363                 hw->multi[0] = v;
364                 break;
365             case BTN_1:
366                 hw->multi[1] = v;
367                 break;
368             case BTN_2:
369                 hw->multi[2] = v;
370                 break;
371             case BTN_3:
372                 hw->multi[3] = v;
373                 break;
374             case BTN_4:
375                 hw->multi[4] = v;
376                 break;
377             case BTN_5:
378                 hw->multi[5] = v;
379                 break;
380             case BTN_6:
381                 hw->multi[6] = v;
382                 break;
383             case BTN_7:
384                 hw->multi[7] = v;
385                 break;
386             case BTN_TOOL_FINGER:
387                 comm->oneFinger = v;
388                 break;
389             case BTN_TOOL_DOUBLETAP:
390                 comm->twoFingers = v;
391                 break;
392             case BTN_TOOL_TRIPLETAP:
393                 comm->threeFingers = v;
394                 break;
395             case BTN_TOUCH:
396                 if (!priv->has_pressure)
397                         hw->z = v ? para->finger_high + 1 : 0;
398                 break;
399             }
400             break;
401         case EV_ABS:
402             switch (ev.code) {
403             case ABS_X:
404                 hw->x = ev.value;
405                 break;
406             case ABS_Y:
407                 hw->y = ev.value;
408                 break;
409             case ABS_PRESSURE:
410                 hw->z = ev.value;
411                 break;
412             case ABS_TOOL_WIDTH:
413                 hw->fingerWidth = ev.value;
414                 break;
415             }
416             break;
417         }
418     }
419     return FALSE;
420 }
421
422 /* filter for the AutoDevProbe scandir on /dev/input */
423 static int EventDevOnly(const struct dirent *dir) {
424         return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
425 }
426
427 /**
428  * Probe the open device for dimensions.
429  */
430 static void
431 EventReadDevDimensions(InputInfoPtr pInfo)
432 {
433     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
434     BOOL *need_grab = (BOOL*)priv->proto_data;
435
436     if (event_query_is_touchpad(pInfo->fd, (need_grab) ? *need_grab : TRUE))
437         event_query_axis_ranges(pInfo);
438     event_query_info(pInfo);
439 }
440
441 static Bool
442 EventAutoDevProbe(InputInfoPtr pInfo)
443 {
444     /* We are trying to find the right eventX device or fall back to
445        the psaux protocol and the given device from XF86Config */
446     int i;
447     Bool touchpad_found = FALSE;
448     struct dirent **namelist;
449
450     i = scandir(DEV_INPUT_EVENT, &namelist, EventDevOnly, alphasort);
451     if (i < 0) {
452                 xf86Msg(X_ERROR, "Couldn't open %s\n", DEV_INPUT_EVENT);
453                 return FALSE;
454     }
455     else if (i == 0) {
456                 xf86Msg(X_ERROR, "%s The /dev/input/event* device nodes seem to be missing\n",
457                                 pInfo->name);
458                 free(namelist);
459                 return FALSE;
460     }
461
462     while (i--) {
463                 char fname[64];
464                 int fd = -1;
465
466                 if (!touchpad_found) {
467                         sprintf(fname, "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
468                         SYSCALL(fd = open(fname, O_RDONLY));
469                         if (fd < 0)
470                                 continue;
471
472                         if (event_query_is_touchpad(fd, TRUE)) {
473                                 touchpad_found = TRUE;
474                             xf86Msg(X_PROBED, "%s auto-dev sets device to %s\n",
475                                     pInfo->name, fname);
476                             pInfo->options =
477                                 xf86ReplaceStrOption(pInfo->options, "Device", fname);
478                         }
479                         SYSCALL(close(fd));
480                 }
481                 free(namelist[i]);
482     }
483         free(namelist);
484
485         if (!touchpad_found) {
486                 xf86Msg(X_ERROR, "%s no synaptics event device found\n", pInfo->name);
487                 return FALSE;
488         }
489     return TRUE;
490 }
491
492 struct SynapticsProtocolOperations event_proto_operations = {
493     EventDeviceOnHook,
494     NULL,
495     EventQueryHardware,
496     EventReadHwState,
497     EventAutoDevProbe,
498     EventReadDevDimensions
499 };