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@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 */ 65struct 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 81struct eventcomm_proto_data * 82EventProtoDataAlloc(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 96static int 97last_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 106static void 107UninitializeTouch(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 130static void 131InitializeTouch(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 179static Bool 180EventDeviceOnHook(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 205static Bool 206EventDeviceOffHook(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 */ 227static Bool 228event_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 280struct model_lookup_t { 281 short vendor; 282 short product_start; 283 short product_end; 284 enum TouchpadModel model; 285}; 286 287 288static 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 */ 307static Bool 308event_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 */ 349static int 350event_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 */ 377static void 378event_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 480static Bool 481EventQueryHardware(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 495static Bool 496SynapticsReadEvent(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 523static Bool 524EventTouchSlotPreviouslyOpen(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 535static void 536EventProcessTouchEvent(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 */ 594static int 595count_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 614static inline double 615apply_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 621Bool 622EventReadHwState(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 */ 734static int 735EventDevOnly(const struct dirent *dir) 736{ 737 return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0; 738} 739 740static void 741event_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 */ 861static void 862EventReadDevDimensions(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 886static Bool 887EventAutoDevProbe(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 955struct SynapticsProtocolOperations event_proto_operations = { 956 EventDeviceOnHook, 957 EventDeviceOffHook, 958 EventQueryHardware, 959 EventReadHwState, 960 EventAutoDevProbe, 961 EventReadDevDimensions 962}; 963