Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright  2004-2007 Peter Osterlund
      3  * Copyright  2008-2012 Red Hat, Inc.
      4  *
      5  * Permission to use, copy, modify, distribute, and sell this software
      6  * and its documentation for any purpose is hereby granted without
      7  * fee, provided that the above copyright notice appear in all copies
      8  * and that both that copyright notice and this permission notice
      9  * appear in supporting documentation, and that the name of Red Hat
     10  * not be used in advertising or publicity pertaining to distribution
     11  * of the software without specific, written prior permission.  Red
     12  * Hat makes no representations about the suitability of this software
     13  * for any purpose.  It is provided "as is" without express or implied
     14  * warranty.
     15  *
     16  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
     18  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
     20  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     21  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     23  *
     24  * Authors:
     25  *      Peter Osterlund (petero2 (at) telia.com)
     26  */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include <xorg-server.h>
     33 #include <xserver-properties.h>
     34 #include "eventcomm.h"
     35 #include <errno.h>
     36 #include <sys/types.h>
     37 #include <sys/stat.h>
     38 #include <fcntl.h>
     39 #include <dirent.h>
     40 #include <string.h>
     41 #include <stdio.h>
     42 #include "synproto.h"
     43 #include "synapticsstr.h"
     44 #include <xf86.h>
     45 #include <mtdev.h>
     46 
     47 #ifndef INPUT_PROP_BUTTONPAD
     48 #define INPUT_PROP_BUTTONPAD 0x02
     49 #endif
     50 #ifndef INPUT_PROP_SEMI_MT
     51 #define INPUT_PROP_SEMI_MT 0x03
     52 #endif
     53 
     54 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
     55 
     56 #define LONG_BITS (sizeof(long) * 8)
     57 #define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
     58 #define OFF(x)   ((x) % LONG_BITS)
     59 #define LONG(x)  ((x) / LONG_BITS)
     60 #define TEST_BIT(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
     61 
     62 /**
     63  * Protocol-specific data.
     64  */
     65 struct eventcomm_proto_data {
     66     /**
     67      * Do we need to grab the event device?
     68      * Note that in the current flow, this variable is always false and
     69      * exists for readability of the code.
     70      */
     71     BOOL need_grab;
     72     int st_to_mt_offset[2];
     73     double st_to_mt_scale[2];
     74     struct mtdev *mtdev;
     75     int axis_map[MT_ABS_SIZE];
     76     int cur_slot;
     77     ValuatorMask **last_mt_vals;
     78     int num_touches;
     79 };
     80 
     81 struct eventcomm_proto_data *
     82 EventProtoDataAlloc(void)
     83 {
     84     struct eventcomm_proto_data *proto_data;
     85 
     86     proto_data = calloc(1, sizeof(struct eventcomm_proto_data));
     87     if (!proto_data)
     88         return NULL;
     89 
     90     proto_data->st_to_mt_scale[0] = 1;
     91     proto_data->st_to_mt_scale[1] = 1;
     92 
     93     return proto_data;
     94 }
     95 
     96 static int
     97 last_mt_vals_slot(const SynapticsPrivate * priv)
     98 {
     99     struct eventcomm_proto_data *proto_data =
    100         (struct eventcomm_proto_data *) priv->proto_data;
    101     int value = proto_data->cur_slot - proto_data->mtdev->caps.slot.minimum;
    102 
    103     return value < priv->num_slots ? value : -1;
    104 }
    105 
    106 static void
    107 UninitializeTouch(InputInfoPtr pInfo)
    108 {
    109     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    110     struct eventcomm_proto_data *proto_data =
    111         (struct eventcomm_proto_data *) priv->proto_data;
    112 
    113     if (!priv->has_touch)
    114         return;
    115 
    116     if (proto_data->last_mt_vals) {
    117         int i;
    118 
    119         for (i = 0; i < priv->num_slots; i++)
    120             valuator_mask_free(&proto_data->last_mt_vals[i]);
    121         free(proto_data->last_mt_vals);
    122         proto_data->last_mt_vals = NULL;
    123     }
    124 
    125     mtdev_close_delete(proto_data->mtdev);
    126     proto_data->mtdev = NULL;
    127     proto_data->num_touches = 0;
    128 }
    129 
    130 static void
    131 InitializeTouch(InputInfoPtr pInfo)
    132 {
    133     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    134     struct eventcomm_proto_data *proto_data =
    135         (struct eventcomm_proto_data *) priv->proto_data;
    136     int i;
    137 
    138     if (!priv->has_touch)
    139         return;
    140 
    141     proto_data->mtdev = mtdev_new_open(pInfo->fd);
    142     if (!proto_data->mtdev) {
    143         xf86IDrvMsg(pInfo, X_WARNING,
    144                     "failed to create mtdev instance, ignoring touch events\n");
    145         return;
    146     }
    147 
    148     proto_data->cur_slot = proto_data->mtdev->caps.slot.value;
    149     proto_data->num_touches = 0;
    150 
    151     proto_data->last_mt_vals = calloc(priv->num_slots, sizeof(ValuatorMask *));
    152     if (!proto_data->last_mt_vals) {
    153         xf86IDrvMsg(pInfo, X_WARNING,
    154                     "failed to allocate MT last values mask array\n");
    155         UninitializeTouch(pInfo);
    156         return;
    157     }
    158 
    159     for (i = 0; i < priv->num_slots; i++) {
    160         int j;
    161 
    162         proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes);
    163         if (!proto_data->last_mt_vals[i]) {
    164             xf86IDrvMsg(pInfo, X_WARNING,
    165                         "failed to allocate MT last values mask\n");
    166             UninitializeTouch(pInfo);
    167             return;
    168         }
    169 
    170         /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X
    171          * and Y. */
    172         valuator_mask_set(proto_data->last_mt_vals[i], 0, 0);
    173         valuator_mask_set(proto_data->last_mt_vals[i], 1, 0);
    174         for (j = 0; j < priv->num_mt_axes; j++)
    175             valuator_mask_set(proto_data->last_mt_vals[i], 4 + j, 0);
    176     }
    177 }
    178 
    179 static Bool
    180 EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters * para)
    181 {
    182     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    183     struct eventcomm_proto_data *proto_data =
    184         (struct eventcomm_proto_data *) priv->proto_data;
    185 
    186     if (para->grab_event_device) {
    187         /* Try to grab the event device so that data don't leak to /dev/input/mice */
    188         int ret;
    189 
    190         SYSCALL(ret = ioctl(pInfo->fd, EVIOCGRAB, (pointer) 1));
    191         if (ret < 0) {
    192             xf86IDrvMsg(pInfo, X_WARNING, "can't grab event device, errno=%d\n",
    193                         errno);
    194             return FALSE;
    195         }
    196     }
    197 
    198     proto_data->need_grab = FALSE;
    199 
    200     InitializeTouch(pInfo);
    201 
    202     return TRUE;
    203 }
    204 
    205 static Bool
    206 EventDeviceOffHook(InputInfoPtr pInfo)
    207 {
    208     UninitializeTouch(pInfo);
    209 
    210     return Success;
    211 }
    212 
    213 /**
    214  * Test if the device on the file descriptior is recognized as touchpad
    215  * device. Required bits for touchpad recognition are:
    216  * - ABS_X + ABS_Y for absolute axes
    217  * - ABS_PRESSURE or BTN_TOUCH
    218  * - BTN_TOOL_FINGER
    219  * - BTN_TOOL_PEN is _not_ set
    220  *
    221  * @param fd The file descriptor to an event device.
    222  * @param test_grab If true, test whether an EVIOCGRAB is possible on the
    223  * device. A failure to grab the event device returns in a failure.
    224  *
    225  * @return TRUE if the device is a touchpad or FALSE otherwise.
    226  */
    227 static Bool
    228 event_query_is_touchpad(int fd, BOOL test_grab)
    229 {
    230     int ret = FALSE, rc;
    231     unsigned long evbits[NBITS(EV_MAX)] = { 0 };
    232     unsigned long absbits[NBITS(ABS_MAX)] = { 0 };
    233     unsigned long keybits[NBITS(KEY_MAX)] = { 0 };
    234 
    235     if (test_grab) {
    236         SYSCALL(rc = ioctl(fd, EVIOCGRAB, (pointer) 1));
    237         if (rc < 0)
    238             return FALSE;
    239     }
    240 
    241     /* Check for ABS_X, ABS_Y, ABS_PRESSURE and BTN_TOOL_FINGER */
    242 
    243     SYSCALL(rc = ioctl(fd, EVIOCGBIT(0, sizeof(evbits)), evbits));
    244     if (rc < 0)
    245         goto unwind;
    246     if (!TEST_BIT(EV_SYN, evbits) ||
    247         !TEST_BIT(EV_ABS, evbits) || !TEST_BIT(EV_KEY, evbits))
    248         goto unwind;
    249 
    250     SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
    251     if (rc < 0)
    252         goto unwind;
    253     if (!TEST_BIT(ABS_X, absbits) || !TEST_BIT(ABS_Y, absbits))
    254         goto unwind;
    255 
    256     SYSCALL(rc = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
    257     if (rc < 0)
    258         goto unwind;
    259 
    260     /* we expect touchpad either report raw pressure or touches */
    261     if (!TEST_BIT(ABS_PRESSURE, absbits) && !TEST_BIT(BTN_TOUCH, keybits))
    262         goto unwind;
    263     /* all Synaptics-like touchpad report BTN_TOOL_FINGER */
    264     if (!TEST_BIT(BTN_TOOL_FINGER, keybits))
    265         goto unwind;
    266     if (TEST_BIT(BTN_TOOL_PEN, keybits))
    267         goto unwind;            /* Don't match wacom tablets */
    268 
    269     ret = TRUE;
    270 
    271  unwind:
    272     if (test_grab)
    273         SYSCALL(ioctl(fd, EVIOCGRAB, (pointer) 0));
    274 
    275     return (ret == TRUE);
    276 }
    277 
    278 #define PRODUCT_ANY 0x0000
    279 
    280 struct model_lookup_t {
    281     short vendor;
    282     short product_start;
    283     short product_end;
    284     enum TouchpadModel model;
    285 };
    286 
    287 
    288 static struct model_lookup_t model_lookup_table[] = {
    289     {0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS},
    290     {0x0002, 0x0008, 0x0008, MODEL_ALPS},
    291     {0x05ac, PRODUCT_ANY, 0x222, MODEL_APPLETOUCH},
    292     {0x05ac, 0x223, PRODUCT_ANY, MODEL_UNIBODY_MACBOOK},
    293     {0x0002, 0x000e, 0x000e, MODEL_ELANTECH},
    294     {0x0, 0x0, 0x0, 0x0}
    295 };
    296 
    297 /**
    298  * Check for the vendor/product id on the file descriptor and compare
    299  * with the built-in model LUT. This information is used in synaptics.c to
    300  * initialize model-specific dimensions.
    301  *
    302  * @param fd The file descriptor to a event device.
    303  * @param[out] model_out The type of touchpad model detected.
    304  *
    305  * @return TRUE on success or FALSE otherwise.
    306  */
    307 static Bool
    308 event_query_model(int fd, enum TouchpadModel *model_out,
    309                   unsigned short *vendor_id, unsigned short *product_id)
    310 {
    311     struct input_id id;
    312     int rc;
    313     struct model_lookup_t *model_lookup;
    314 
    315     SYSCALL(rc = ioctl(fd, EVIOCGID, &id));
    316     if (rc < 0)
    317         return FALSE;
    318 
    319     for (model_lookup = model_lookup_table; model_lookup->vendor;
    320          model_lookup++) {
    321         if (model_lookup->vendor == id.vendor &&
    322             (model_lookup->product_start == PRODUCT_ANY ||
    323              model_lookup->product_start <= id.product) &&
    324             (model_lookup->product_end == PRODUCT_ANY ||
    325              model_lookup->product_end >= id.product))
    326             *model_out = model_lookup->model;
    327     }
    328 
    329     *vendor_id = id.vendor;
    330     *product_id = id.product;
    331 
    332     return TRUE;
    333 }
    334 
    335 /**
    336  * Get absinfo information from the given file descriptor for the given
    337  * ABS_FOO code and store the information in min, max, fuzz and res.
    338  *
    339  * @param fd File descriptor to an event device
    340  * @param code Event code (e.g. ABS_X)
    341  * @param[out] min Minimum axis range
    342  * @param[out] max Maximum axis range
    343  * @param[out] fuzz Fuzz of this axis. If NULL, fuzz is ignored.
    344  * @param[out] res Axis resolution. If NULL or the current kernel does not
    345  * support the resolution field, res is ignored
    346  *
    347  * @return Zero on success, or errno otherwise.
    348  */
    349 static int
    350 event_get_abs(InputInfoPtr pInfo, int fd, int code,
    351               int *min, int *max, int *fuzz, int *res)
    352 {
    353     int rc;
    354     struct input_absinfo abs = { 0 };
    355 
    356     SYSCALL(rc = ioctl(fd, EVIOCGABS(code), &abs));
    357     if (rc < 0) {
    358         xf86IDrvMsg(pInfo, X_ERROR, "%s EVIOCGABS error on %d (%s)\n",
    359                     __func__, code, strerror(errno));
    360         return errno;
    361     }
    362 
    363     *min = abs.minimum;
    364     *max = abs.maximum;
    365     /* We dont trust a zero fuzz as it probably is just a lazy value */
    366     if (fuzz && abs.fuzz > 0)
    367         *fuzz = abs.fuzz;
    368 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
    369     if (res)
    370         *res = abs.resolution;
    371 #endif
    372 
    373     return 0;
    374 }
    375 
    376 /* Query device for axis ranges */
    377 static void
    378 event_query_axis_ranges(InputInfoPtr pInfo)
    379 {
    380     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    381     struct eventcomm_proto_data *proto_data = priv->proto_data;
    382     unsigned long absbits[NBITS(ABS_MAX)] = { 0 };
    383     unsigned long keybits[NBITS(KEY_MAX)] = { 0 };
    384     char buf[256] = { 0 };
    385     int rc;
    386 
    387     /* The kernel's fuzziness concept seems a bit weird, but it can more or
    388      * less be applied as hysteresis directly, i.e. no factor here. */
    389     event_get_abs(pInfo, pInfo->fd, ABS_X, &priv->minx, &priv->maxx,
    390                   &priv->synpara.hyst_x, &priv->resx);
    391 
    392     event_get_abs(pInfo, pInfo->fd, ABS_Y, &priv->miny, &priv->maxy,
    393                   &priv->synpara.hyst_y, &priv->resy);
    394 
    395     priv->has_pressure = FALSE;
    396     priv->has_width = FALSE;
    397     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits));
    398     if (rc >= 0) {
    399         priv->has_pressure = (TEST_BIT(ABS_PRESSURE, absbits) != 0);
    400         priv->has_width = (TEST_BIT(ABS_TOOL_WIDTH, absbits) != 0);
    401     }
    402     else
    403         xf86IDrvMsg(pInfo, X_ERROR, "failed to query ABS bits (%s)\n",
    404                     strerror(errno));
    405 
    406     if (priv->has_pressure)
    407         event_get_abs(pInfo, pInfo->fd, ABS_PRESSURE, &priv->minp, &priv->maxp,
    408                       NULL, NULL);
    409 
    410     if (priv->has_width)
    411         event_get_abs(pInfo, pInfo->fd, ABS_TOOL_WIDTH,
    412                       &priv->minw, &priv->maxw, NULL, NULL);
    413 
    414     if (priv->has_touch) {
    415         int st_minx = priv->minx;
    416         int st_maxx = priv->maxx;
    417         int st_miny = priv->miny;
    418         int st_maxy = priv->maxy;
    419 
    420         event_get_abs(pInfo, pInfo->fd, ABS_MT_POSITION_X, &priv->minx,
    421                       &priv->maxx, &priv->synpara.hyst_x, &priv->resx);
    422         event_get_abs(pInfo, pInfo->fd, ABS_MT_POSITION_Y, &priv->miny,
    423                       &priv->maxy, &priv->synpara.hyst_y, &priv->resy);
    424 
    425         proto_data->st_to_mt_offset[0] = priv->minx - st_minx;
    426         proto_data->st_to_mt_scale[0] =
    427             (priv->maxx - priv->minx) / (st_maxx - st_minx);
    428         proto_data->st_to_mt_offset[1] = priv->miny - st_miny;
    429         proto_data->st_to_mt_scale[1] =
    430             (priv->maxy - priv->miny) / (st_maxy - st_miny);
    431     }
    432 
    433     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits));
    434     if (rc >= 0) {
    435         priv->has_left = (TEST_BIT(BTN_LEFT, keybits) != 0);
    436         priv->has_right = (TEST_BIT(BTN_RIGHT, keybits) != 0);
    437         priv->has_middle = (TEST_BIT(BTN_MIDDLE, keybits) != 0);
    438         priv->has_double = (TEST_BIT(BTN_TOOL_DOUBLETAP, keybits) != 0);
    439         priv->has_triple = (TEST_BIT(BTN_TOOL_TRIPLETAP, keybits) != 0);
    440 
    441         if ((TEST_BIT(BTN_0, keybits) != 0) ||
    442             (TEST_BIT(BTN_1, keybits) != 0) ||
    443             (TEST_BIT(BTN_2, keybits) != 0) || (TEST_BIT(BTN_3, keybits) != 0))
    444             priv->has_scrollbuttons = 1;
    445     }
    446 
    447     /* Now print the device information */
    448     xf86IDrvMsg(pInfo, X_PROBED, "x-axis range %d - %d (res %d)\n",
    449                 priv->minx, priv->maxx, priv->resx);
    450     xf86IDrvMsg(pInfo, X_PROBED, "y-axis range %d - %d (res %d)\n",
    451                 priv->miny, priv->maxy, priv->resy);
    452     if (priv->has_pressure)
    453         xf86IDrvMsg(pInfo, X_PROBED, "pressure range %d - %d\n",
    454                     priv->minp, priv->maxp);
    455     else
    456         xf86IDrvMsg(pInfo, X_INFO,
    457                     "device does not report pressure, will use touch data.\n");
    458     if (priv->has_width)
    459         xf86IDrvMsg(pInfo, X_PROBED, "finger width range %d - %d\n",
    460                     priv->minw, priv->maxw);
    461     else
    462         xf86IDrvMsg(pInfo, X_INFO, "device does not report finger width.\n");
    463 
    464     if (priv->has_left)
    465         strcat(buf, " left");
    466     if (priv->has_right)
    467         strcat(buf, " right");
    468     if (priv->has_middle)
    469         strcat(buf, " middle");
    470     if (priv->has_double)
    471         strcat(buf, " double");
    472     if (priv->has_triple)
    473         strcat(buf, " triple");
    474     if (priv->has_scrollbuttons)
    475         strcat(buf, " scroll-buttons");
    476 
    477     xf86IDrvMsg(pInfo, X_PROBED, "buttons:%s\n", buf);
    478 }
    479 
    480 static Bool
    481 EventQueryHardware(InputInfoPtr pInfo)
    482 {
    483     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    484     struct eventcomm_proto_data *proto_data = priv->proto_data;
    485 
    486     if (!event_query_is_touchpad
    487         (pInfo->fd, (proto_data) ? proto_data->need_grab : TRUE))
    488         return FALSE;
    489 
    490     xf86IDrvMsg(pInfo, X_PROBED, "touchpad found\n");
    491 
    492     return TRUE;
    493 }
    494 
    495 static Bool
    496 SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
    497 {
    498     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    499     struct eventcomm_proto_data *proto_data = priv->proto_data;
    500     int rc = TRUE;
    501     ssize_t len;
    502 
    503     if (proto_data->mtdev)
    504         len = mtdev_get(proto_data->mtdev, pInfo->fd, ev, 1) *
    505             sizeof(struct input_event);
    506     else
    507         len = read(pInfo->fd, ev, sizeof(*ev));
    508     if (len <= 0) {
    509         /* We use X_NONE here because it doesn't alloc */
    510         if (errno != EAGAIN)
    511             LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error %d\n", pInfo->name,
    512                                   errno);
    513         rc = FALSE;
    514     }
    515     else if (len % sizeof(*ev)) {
    516         LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error, invalid number of bytes.",
    517                               pInfo->name);
    518         rc = FALSE;
    519     }
    520     return rc;
    521 }
    522 
    523 static Bool
    524 EventTouchSlotPreviouslyOpen(SynapticsPrivate * priv, int slot)
    525 {
    526     int i;
    527 
    528     for (i = 0; i < priv->num_active_touches; i++)
    529         if (priv->open_slots[i] == slot)
    530             return TRUE;
    531 
    532     return FALSE;
    533 }
    534 
    535 static void
    536 EventProcessTouchEvent(InputInfoPtr pInfo, struct SynapticsHwState *hw,
    537                        struct input_event *ev)
    538 {
    539     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    540     struct eventcomm_proto_data *proto_data = priv->proto_data;
    541 
    542     if (!priv->has_touch)
    543         return;
    544 
    545     if (ev->code == ABS_MT_SLOT) {
    546         proto_data->cur_slot = ev->value;
    547     }
    548     else {
    549         int slot_index = last_mt_vals_slot(priv);
    550 
    551         if (slot_index < 0)
    552             return;
    553 
    554         if (hw->slot_state[slot_index] == SLOTSTATE_OPEN_EMPTY)
    555             hw->slot_state[slot_index] = SLOTSTATE_UPDATE;
    556         if (ev->code == ABS_MT_TRACKING_ID) {
    557             if (ev->value >= 0) {
    558                 hw->slot_state[slot_index] = SLOTSTATE_OPEN;
    559                 proto_data->num_touches++;
    560                 valuator_mask_copy(hw->mt_mask[slot_index],
    561                                    proto_data->last_mt_vals[slot_index]);
    562             }
    563             else if (hw->slot_state[slot_index] != SLOTSTATE_EMPTY) {
    564                 hw->slot_state[slot_index] = SLOTSTATE_CLOSE;
    565                 proto_data->num_touches--;
    566             }
    567         }
    568         else {
    569             ValuatorMask *mask = proto_data->last_mt_vals[slot_index];
    570             int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR];
    571             int last_val = valuator_mask_get(mask, map);
    572 
    573             valuator_mask_set(hw->mt_mask[slot_index], map, ev->value);
    574             if (EventTouchSlotPreviouslyOpen(priv, slot_index)) {
    575                 if (ev->code == ABS_MT_POSITION_X)
    576                     hw->cumulative_dx += ev->value - last_val;
    577                 else if (ev->code == ABS_MT_POSITION_Y)
    578                     hw->cumulative_dy += ev->value - last_val;
    579             }
    580 
    581             valuator_mask_set(mask, map, ev->value);
    582         }
    583     }
    584 }
    585 
    586 /**
    587  * Count the number of fingers based on the CommData information.
    588  * The CommData struct contains the event information based on previous
    589  * struct input_events, now we're just counting based on that.
    590  *
    591  * @param comm Assembled information from previous events.
    592  * @return The number of fingers currently set.
    593  */
    594 static int
    595 count_fingers(InputInfoPtr pInfo, const struct CommData *comm)
    596 {
    597     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    598     struct eventcomm_proto_data *proto_data = priv->proto_data;
    599     int fingers = 0;
    600 
    601     if (comm->oneFinger)
    602         fingers = 1;
    603     else if (comm->twoFingers)
    604         fingers = 2;
    605     else if (comm->threeFingers)
    606         fingers = 3;
    607 
    608     if (priv->has_touch && proto_data->num_touches > fingers)
    609         fingers = proto_data->num_touches;
    610 
    611     return fingers;
    612 }
    613 
    614 static inline double
    615 apply_st_scaling(struct eventcomm_proto_data *proto_data, int value, int axis)
    616 {
    617     return value * proto_data->st_to_mt_scale[axis] +
    618         proto_data->st_to_mt_offset[axis];
    619 }
    620 
    621 Bool
    622 EventReadHwState(InputInfoPtr pInfo,
    623                  struct CommData *comm, struct SynapticsHwState *hwRet)
    624 {
    625     struct input_event ev;
    626     Bool v;
    627     struct SynapticsHwState *hw = comm->hwState;
    628     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    629     SynapticsParameters *para = &priv->synpara;
    630     struct eventcomm_proto_data *proto_data = priv->proto_data;
    631 
    632     SynapticsResetTouchHwState(hw, FALSE);
    633 
    634     /* Reset cumulative values if buttons were not previously pressed */
    635     if (!hw->left && !hw->right && !hw->middle) {
    636         hw->cumulative_dx = hw->x;
    637         hw->cumulative_dy = hw->y;
    638     }
    639 
    640     while (SynapticsReadEvent(pInfo, &ev)) {
    641         switch (ev.type) {
    642         case EV_SYN:
    643             switch (ev.code) {
    644             case SYN_REPORT:
    645                 hw->numFingers = count_fingers(pInfo, comm);
    646                 hw->millis = 1000 * ev.time.tv_sec + ev.time.tv_usec / 1000;
    647                 SynapticsCopyHwState(hwRet, hw);
    648                 return TRUE;
    649             }
    650             break;
    651         case EV_KEY:
    652             v = (ev.value ? TRUE : FALSE);
    653             switch (ev.code) {
    654             case BTN_LEFT:
    655                 hw->left = v;
    656                 break;
    657             case BTN_RIGHT:
    658                 hw->right = v;
    659                 break;
    660             case BTN_MIDDLE:
    661                 hw->middle = v;
    662                 break;
    663             case BTN_FORWARD:
    664                 hw->up = v;
    665                 break;
    666             case BTN_BACK:
    667                 hw->down = v;
    668                 break;
    669             case BTN_0:
    670                 hw->multi[0] = v;
    671                 break;
    672             case BTN_1:
    673                 hw->multi[1] = v;
    674                 break;
    675             case BTN_2:
    676                 hw->multi[2] = v;
    677                 break;
    678             case BTN_3:
    679                 hw->multi[3] = v;
    680                 break;
    681             case BTN_4:
    682                 hw->multi[4] = v;
    683                 break;
    684             case BTN_5:
    685                 hw->multi[5] = v;
    686                 break;
    687             case BTN_6:
    688                 hw->multi[6] = v;
    689                 break;
    690             case BTN_7:
    691                 hw->multi[7] = v;
    692                 break;
    693             case BTN_TOOL_FINGER:
    694                 comm->oneFinger = v;
    695                 break;
    696             case BTN_TOOL_DOUBLETAP:
    697                 comm->twoFingers = v;
    698                 break;
    699             case BTN_TOOL_TRIPLETAP:
    700                 comm->threeFingers = v;
    701                 break;
    702             case BTN_TOUCH:
    703                 if (!priv->has_pressure)
    704                     hw->z = v ? para->finger_high + 1 : 0;
    705                 break;
    706             }
    707             break;
    708         case EV_ABS:
    709             if (ev.code < ABS_MT_SLOT) {
    710                 switch (ev.code) {
    711                 case ABS_X:
    712                     hw->x = apply_st_scaling(proto_data, ev.value, 0);
    713                     break;
    714                 case ABS_Y:
    715                     hw->y = apply_st_scaling(proto_data, ev.value, 1);
    716                     break;
    717                 case ABS_PRESSURE:
    718                     hw->z = ev.value;
    719                     break;
    720                 case ABS_TOOL_WIDTH:
    721                     hw->fingerWidth = ev.value;
    722                     break;
    723                 }
    724             }
    725             else
    726                 EventProcessTouchEvent(pInfo, hw, &ev);
    727             break;
    728         }
    729     }
    730     return FALSE;
    731 }
    732 
    733 /* filter for the AutoDevProbe scandir on /dev/input */
    734 static int
    735 EventDevOnly(const struct dirent *dir)
    736 {
    737     return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
    738 }
    739 
    740 static void
    741 event_query_touch(InputInfoPtr pInfo)
    742 {
    743     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    744     SynapticsParameters *para = &priv->synpara;
    745     struct eventcomm_proto_data *proto_data = priv->proto_data;
    746     struct mtdev *mtdev;
    747     int i;
    748     int rc;
    749     uint8_t prop;
    750 
    751     priv->max_touches = 0;
    752     priv->num_mt_axes = 0;
    753 
    754 #ifdef EVIOCGPROP
    755     SYSCALL(rc = ioctl(pInfo->fd, EVIOCGPROP(sizeof(prop)), &prop));
    756     if (rc >= 0 && BitIsOn(&prop, INPUT_PROP_SEMI_MT)) {
    757         xf86IDrvMsg(pInfo, X_INFO,
    758                     "ignoring touch events for semi-multitouch device\n");
    759         priv->has_semi_mt = TRUE;
    760     }
    761 
    762     if (rc >= 0 && BitIsOn(&prop, INPUT_PROP_BUTTONPAD)) {
    763         xf86IDrvMsg(pInfo, X_INFO, "found clickpad property\n");
    764         para->clickpad = TRUE;
    765     }
    766 #endif
    767 
    768     mtdev = mtdev_new_open(pInfo->fd);
    769     if (!mtdev) {
    770         xf86IDrvMsg(pInfo, X_WARNING,
    771                     "failed to open mtdev when querying touch capabilities\n");
    772         return;
    773     }
    774 
    775     for (i = 0; i < MT_ABS_SIZE; i++) {
    776         if (mtdev->caps.has_abs[i]) {
    777             switch (i) {
    778                 /* X and Y axis info is handed by synaptics already */
    779             case ABS_MT_POSITION_X - ABS_MT_TOUCH_MAJOR:
    780             case ABS_MT_POSITION_Y - ABS_MT_TOUCH_MAJOR:
    781                 /* Skip tracking ID info */
    782             case ABS_MT_TRACKING_ID - ABS_MT_TOUCH_MAJOR:
    783                 break;
    784             default:
    785                 priv->num_mt_axes++;
    786                 break;
    787             }
    788             priv->has_touch = TRUE;
    789         }
    790     }
    791 
    792     if (priv->has_touch) {
    793         int axnum;
    794 
    795         static const char *labels[] = {
    796             AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR,
    797             AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR,
    798             AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR,
    799             AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR,
    800             AXIS_LABEL_PROP_ABS_MT_ORIENTATION,
    801             AXIS_LABEL_PROP_ABS_MT_POSITION_X,
    802             AXIS_LABEL_PROP_ABS_MT_POSITION_Y,
    803             AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE,
    804             AXIS_LABEL_PROP_ABS_MT_BLOB_ID,
    805             AXIS_LABEL_PROP_ABS_MT_TRACKING_ID,
    806             AXIS_LABEL_PROP_ABS_MT_PRESSURE,
    807         };
    808 
    809         if (mtdev->caps.slot.maximum > 0)
    810             priv->max_touches = mtdev->caps.slot.maximum -
    811                 mtdev->caps.slot.minimum + 1;
    812 
    813         priv->touch_axes = malloc(priv->num_mt_axes *
    814                                   sizeof(SynapticsTouchAxisRec));
    815         if (!priv->touch_axes) {
    816             priv->has_touch = FALSE;
    817             goto out;
    818         }
    819 
    820         axnum = 0;
    821         for (i = 0; i < MT_ABS_SIZE; i++) {
    822             if (mtdev->caps.has_abs[i]) {
    823                 switch (i) {
    824                     /* X and Y axis info is handed by synaptics already, we just
    825                      * need to map the evdev codes to the valuator numbers */
    826                 case ABS_MT_POSITION_X - ABS_MT_TOUCH_MAJOR:
    827                     proto_data->axis_map[i] = 0;
    828                     break;
    829 
    830                 case ABS_MT_POSITION_Y - ABS_MT_TOUCH_MAJOR:
    831                     proto_data->axis_map[i] = 1;
    832                     break;
    833 
    834                     /* Skip tracking ID info */
    835                 case ABS_MT_TRACKING_ID - ABS_MT_TOUCH_MAJOR:
    836                     break;
    837 
    838                 default:
    839                     priv->touch_axes[axnum].label = labels[i];
    840                     priv->touch_axes[axnum].min = mtdev->caps.abs[i].minimum;
    841                     priv->touch_axes[axnum].max = mtdev->caps.abs[i].maximum;
    842                     /* Kernel provides units/mm, X wants units/m */
    843                     priv->touch_axes[axnum].res =
    844                         mtdev->caps.abs[i].resolution * 1000;
    845                     /* Valuators 0-3 are used for X, Y, and scrolling */
    846                     proto_data->axis_map[i] = 4 + axnum;
    847                     axnum++;
    848                     break;
    849                 }
    850             }
    851         }
    852     }
    853 
    854  out:
    855     mtdev_close_delete(mtdev);
    856 }
    857 
    858 /**
    859  * Probe the open device for dimensions.
    860  */
    861 static void
    862 EventReadDevDimensions(InputInfoPtr pInfo)
    863 {
    864     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
    865     struct eventcomm_proto_data *proto_data = priv->proto_data;
    866     int i;
    867 
    868     proto_data = EventProtoDataAlloc();
    869     priv->proto_data = proto_data;
    870 
    871     for (i = 0; i < MT_ABS_SIZE; i++)
    872         proto_data->axis_map[i] = -1;
    873     proto_data->cur_slot = -1;
    874 
    875     if (event_query_is_touchpad(pInfo->fd, proto_data->need_grab)) {
    876         event_query_touch(pInfo);
    877         event_query_axis_ranges(pInfo);
    878     }
    879     event_query_model(pInfo->fd, &priv->model, &priv->id_vendor,
    880                       &priv->id_product);
    881 
    882     xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
    883                 priv->id_vendor, priv->id_product);
    884 }
    885 
    886 static Bool
    887 EventAutoDevProbe(InputInfoPtr pInfo, const char *device)
    888 {
    889     /* We are trying to find the right eventX device or fall back to
    890        the psaux protocol and the given device from XF86Config */
    891     int i;
    892     Bool touchpad_found = FALSE;
    893     struct dirent **namelist;
    894 
    895     if (device) {
    896         int fd = -1;
    897 
    898         SYSCALL(fd = open(device, O_RDONLY));
    899         if (fd >= 0) {
    900             touchpad_found = event_query_is_touchpad(fd, TRUE);
    901 
    902             SYSCALL(close(fd));
    903             /* if a device is set and not a touchpad (or already grabbed),
    904              * we must return FALSE.  Otherwise, we'll add a device that
    905              * wasn't requested for and repeat
    906              * f5687a6741a19ef3081e7fd83ac55f6df8bcd5c2. */
    907             return touchpad_found;
    908         }
    909     }
    910 
    911     i = scandir(DEV_INPUT_EVENT, &namelist, EventDevOnly, alphasort);
    912     if (i < 0) {
    913         xf86IDrvMsg(pInfo, X_ERROR, "Couldn't open %s\n", DEV_INPUT_EVENT);
    914         return FALSE;
    915     }
    916     else if (i == 0) {
    917         xf86IDrvMsg(pInfo, X_ERROR,
    918                     "The /dev/input/event* device nodes seem to be missing\n");
    919         free(namelist);
    920         return FALSE;
    921     }
    922 
    923     while (i--) {
    924         char fname[64];
    925         int fd = -1;
    926 
    927         if (!touchpad_found) {
    928             sprintf(fname, "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
    929             SYSCALL(fd = open(fname, O_RDONLY));
    930             if (fd < 0)
    931                 continue;
    932 
    933             if (event_query_is_touchpad(fd, TRUE)) {
    934                 touchpad_found = TRUE;
    935                 xf86IDrvMsg(pInfo, X_PROBED, "auto-dev sets device to %s\n",
    936                             fname);
    937                 pInfo->options =
    938                     xf86ReplaceStrOption(pInfo->options, "Device", fname);
    939             }
    940             SYSCALL(close(fd));
    941         }
    942         free(namelist[i]);
    943     }
    944 
    945     free(namelist);
    946 
    947     if (!touchpad_found) {
    948         xf86IDrvMsg(pInfo, X_ERROR, "no synaptics event device found\n");
    949         return FALSE;
    950     }
    951 
    952     return TRUE;
    953 }
    954 
    955 struct SynapticsProtocolOperations event_proto_operations = {
    956     EventDeviceOnHook,
    957     EventDeviceOffHook,
    958     EventQueryHardware,
    959     EventReadHwState,
    960     EventAutoDevProbe,
    961     EventReadDevDimensions
    962 };
    963