1/* 2 * Copyright � 1999 Henry Davies 3 * Copyright � 2001 Stefan Gmeiner 4 * Copyright � 2002 S. Lehner 5 * Copyright � 2002 Peter Osterlund 6 * Copyright � 2002 Linuxcare Inc. David Kennedy 7 * Copyright � 2003 Hartwig Felger 8 * Copyright � 2003 J�rg B�sner 9 * Copyright � 2003 Fred Hucht 10 * Copyright � 2004 Alexei Gilchrist 11 * Copyright � 2004 Matthias Ihmig 12 * Copyright � 2006 Stefan Bethge 13 * Copyright � 2006 Christian Thaeter 14 * Copyright � 2007 Joseph P. Skudlarek 15 * Copyright � 2008 Fedor P. Goncharov 16 * Copyright � 2008-2012 Red Hat, Inc. 17 * Copyright � 2011 The Chromium OS Authors 18 * 19 * Permission to use, copy, modify, distribute, and sell this software 20 * and its documentation for any purpose is hereby granted without 21 * fee, provided that the above copyright notice appear in all copies 22 * and that both that copyright notice and this permission notice 23 * appear in supporting documentation, and that the name of Red Hat 24 * not be used in advertising or publicity pertaining to distribution 25 * of the software without specific, written prior permission. Red 26 * Hat makes no representations about the suitability of this software 27 * for any purpose. It is provided "as is" without express or implied 28 * warranty. 29 * 30 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 31 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 32 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 33 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 34 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 35 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 36 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 37 * 38 * Authors: 39 * Joseph P. Skudlarek <Jskud@Jskud.com> 40 * Christian Thaeter <chth@gmx.net> 41 * Stefan Bethge <stefan.bethge@web.de> 42 * Matthias Ihmig <m.ihmig@gmx.net> 43 * Alexei Gilchrist <alexei@physics.uq.edu.au> 44 * J�rg B�sner <ich@joerg-boesner.de> 45 * Hartwig Felger <hgfelger@hgfelger.de> 46 * Peter Osterlund <petero2@telia.com> 47 * S. Lehner <sam_x@bluemail.ch> 48 * Stefan Gmeiner <riddlebox@freesurf.ch> 49 * Henry Davies <hdavies@ameritech.net> for the 50 * Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com> 51 * Fred Hucht <fred@thp.Uni-Duisburg.de> 52 * Fedor P. Goncharov <fedgo@gorodok.net> 53 * Simon Thum <simon.thum@gmx.de> 54 * 55 * Trademarks are the property of their respective owners. 56 */ 57 58#ifdef HAVE_CONFIG_H 59#include "config.h" 60#endif 61 62#include <xorg-server.h> 63#include <unistd.h> 64#include <misc.h> 65#include <xf86.h> 66#include <math.h> 67#include <stdio.h> 68#include <xf86_OSproc.h> 69#include <xf86Xinput.h> 70#include <exevents.h> 71 72#include <X11/Xatom.h> 73#include <X11/extensions/XI2.h> 74#include <xserver-properties.h> 75#include <ptrveloc.h> 76 77#include "synapticsstr.h" 78#include "synaptics-properties.h" 79 80enum EdgeType { 81 NO_EDGE = 0, 82 BOTTOM_EDGE = 1, 83 TOP_EDGE = 2, 84 LEFT_EDGE = 4, 85 RIGHT_EDGE = 8, 86 LEFT_BOTTOM_EDGE = BOTTOM_EDGE | LEFT_EDGE, 87 RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE, 88 RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE, 89 LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE 90}; 91 92/* 93 * We expect to be receiving a steady 80 packets/sec (which gives 40 94 * reports/sec with more than one finger on the pad, as Advanced Gesture Mode 95 * requires two PS/2 packets per report). Instead of a random scattering of 96 * magic 13 and 20ms numbers scattered throughout the driver, introduce 97 * POLL_MS as 14ms, which is slightly less than 80Hz. 13ms is closer to 98 * 80Hz, but if the kernel event reporting was even slightly delayed, 99 * we would produce synthetic motion followed immediately by genuine 100 * motion, so use 14. 101 * 102 * We use this to call back at a constant rate to at least produce the 103 * illusion of smooth motion. It works a lot better than you'd expect. 104*/ 105#define POLL_MS 14 106 107#define MAX(a, b) (((a)>(b))?(a):(b)) 108#define MIN(a, b) (((a)<(b))?(a):(b)) 109#define TIME_DIFF(a, b) ((int)((a)-(b))) 110 111#define SQR(x) ((x) * (x)) 112 113#ifndef M_PI 114#define M_PI 3.14159265358979323846 115#endif 116 117#define INPUT_BUFFER_SIZE 200 118 119/***************************************************************************** 120 * Forward declaration 121 ****************************************************************************/ 122static int SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 123static void SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 124static Bool DeviceControl(DeviceIntPtr, int); 125static void ReadInput(InputInfoPtr); 126static int HandleState(InputInfoPtr, struct SynapticsHwState *, CARD32 now, 127 Bool from_timer); 128static int ControlProc(InputInfoPtr, xDeviceCtl *); 129static int SwitchMode(ClientPtr, DeviceIntPtr, int); 130static int DeviceInit(DeviceIntPtr); 131static int DeviceOn(DeviceIntPtr); 132static int DeviceOff(DeviceIntPtr); 133static int DeviceClose(DeviceIntPtr); 134static Bool QueryHardware(InputInfoPtr); 135static void ReadDevDimensions(InputInfoPtr); 136static void ScaleCoordinates(SynapticsPrivate * priv, 137 struct SynapticsHwState *hw); 138static void CalculateScalingCoeffs(SynapticsPrivate * priv); 139static void SanitizeDimensions(InputInfoPtr pInfo); 140 141void InitDeviceProperties(InputInfoPtr pInfo); 142int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, 143 BOOL checkonly); 144 145const static struct { 146 const char *name; 147 struct SynapticsProtocolOperations *proto_ops; 148} protocols[] = { 149#ifdef BUILD_EVENTCOMM 150 { "event", &event_proto_operations }, 151#endif 152#ifdef BUILD_PSMCOMM 153 { "psm", &psm_proto_operations }, 154#endif 155#ifdef BUILD_PS2COMM 156 { "psaux", &psaux_proto_operations }, 157 { "alps", &alps_proto_operations }, 158#endif 159 { NULL, NULL } 160}; 161 162InputDriverRec SYNAPTICS = { 163 1, 164 "synaptics", 165 NULL, 166 SynapticsPreInit, 167 SynapticsUnInit, 168 NULL, 169}; 170 171static XF86ModuleVersionInfo VersionRec = { 172 "synaptics", 173 MODULEVENDORSTRING, 174 MODINFOSTRING1, 175 MODINFOSTRING2, 176 XORG_VERSION_CURRENT, 177 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 178 ABI_CLASS_XINPUT, 179 ABI_XINPUT_VERSION, 180 MOD_CLASS_XINPUT, 181 {0, 0, 0, 0} 182}; 183 184static pointer 185SetupProc(pointer module, pointer options, int *errmaj, int *errmin) 186{ 187 xf86AddInputDriver(&SYNAPTICS, module, 0); 188 return module; 189} 190 191_X_EXPORT XF86ModuleData synapticsModuleData = { 192 &VersionRec, 193 &SetupProc, 194 NULL 195}; 196 197/***************************************************************************** 198 * Function Definitions 199 ****************************************************************************/ 200/** 201 * Fill in default dimensions for backends that cannot query the hardware. 202 * Eventually, we want the edges to be 1900/5400 for x, 1900/4000 for y. 203 * These values are based so that calculate_edge_widths() will give us the 204 * right values. 205 * 206 * The default values 1900, etc. come from the dawn of time, when men where 207 * men, or possibly apes. 208 */ 209static void 210SanitizeDimensions(InputInfoPtr pInfo) 211{ 212 SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; 213 214 if (priv->minx >= priv->maxx) { 215 priv->minx = 1615; 216 priv->maxx = 5685; 217 priv->resx = 0; 218 219 xf86IDrvMsg(pInfo, X_PROBED, 220 "invalid x-axis range. defaulting to %d - %d\n", 221 priv->minx, priv->maxx); 222 } 223 224 if (priv->miny >= priv->maxy) { 225 priv->miny = 1729; 226 priv->maxy = 4171; 227 priv->resy = 0; 228 229 xf86IDrvMsg(pInfo, X_PROBED, 230 "invalid y-axis range. defaulting to %d - %d\n", 231 priv->miny, priv->maxy); 232 } 233 234 if (priv->minp >= priv->maxp) { 235 priv->minp = 0; 236 priv->maxp = 255; 237 238 xf86IDrvMsg(pInfo, X_PROBED, 239 "invalid pressure range. defaulting to %d - %d\n", 240 priv->minp, priv->maxp); 241 } 242 243 if (priv->minw >= priv->maxw) { 244 priv->minw = 0; 245 priv->maxw = 15; 246 247 xf86IDrvMsg(pInfo, X_PROBED, 248 "invalid finger width range. defaulting to %d - %d\n", 249 priv->minw, priv->maxw); 250 } 251} 252 253static Bool 254SetDeviceAndProtocol(InputInfoPtr pInfo) 255{ 256 SynapticsPrivate *priv = pInfo->private; 257 char *proto, *device; 258 int i; 259 260 proto = xf86SetStrOption(pInfo->options, "Protocol", NULL); 261 device = xf86SetStrOption(pInfo->options, "Device", NULL); 262 263 /* If proto is auto-dev, unset and let the code do the rest */ 264 if (proto && !strcmp(proto, "auto-dev")) { 265 free(proto); 266 proto = NULL; 267 } 268 269 for (i = 0; protocols[i].name; i++) { 270 if ((!device || !proto) && 271 protocols[i].proto_ops->AutoDevProbe && 272 protocols[i].proto_ops->AutoDevProbe(pInfo, device)) 273 break; 274 else if (proto && !strcmp(proto, protocols[i].name)) 275 break; 276 } 277 free(proto); 278 free(device); 279 280 priv->proto_ops = protocols[i].proto_ops; 281 282 return (priv->proto_ops != NULL); 283} 284 285static void 286calculate_edge_widths(SynapticsPrivate * priv, int *l, int *r, int *t, int *b) 287{ 288 int width, height; 289 int ewidth, eheight; /* edge width/height */ 290 291 width = abs(priv->maxx - priv->minx); 292 height = abs(priv->maxy - priv->miny); 293 294 if (priv->model == MODEL_SYNAPTICS) { 295 ewidth = width * .07; 296 eheight = height * .07; 297 } 298 else if (priv->model == MODEL_ALPS) { 299 ewidth = width * .15; 300 eheight = height * .15; 301 } 302 else if (priv->model == MODEL_APPLETOUCH || 303 priv->model == MODEL_UNIBODY_MACBOOK) { 304 ewidth = width * .085; 305 eheight = height * .085; 306 } 307 else { 308 ewidth = width * .04; 309 eheight = height * .054; 310 } 311 312 *l = priv->minx + ewidth; 313 *r = priv->maxx - ewidth; 314 *t = priv->miny + eheight; 315 *b = priv->maxy - eheight; 316} 317 318static void 319calculate_tap_hysteresis(SynapticsPrivate * priv, int range, 320 int *fingerLow, int *fingerHigh) 321{ 322 switch (priv->model) { 323 case MODEL_ELANTECH: 324 /* All Elantech touchpads don't need the Z filtering to get the 325 * number of fingers correctly. See Documentation/elantech.txt 326 * in the kernel. 327 */ 328 *fingerLow = priv->minp + 1; 329 *fingerHigh = priv->minp + 1; 330 break; 331 case MODEL_UNIBODY_MACBOOK: 332 *fingerLow = 70; 333 *fingerHigh = 75; 334 break; 335 default: 336 *fingerLow = priv->minp + range * (25.0 / 256); 337 *fingerHigh = priv->minp + range * (30.0 / 256); 338 break; 339 } 340} 341 342/* Area options support both percent values and absolute values. This is 343 * awkward. The xf86Set* calls will print to the log, but they'll 344 * also print an error if we request a percent value but only have an 345 * int. So - check first for percent, then call xf86Set* again to get 346 * the log message. 347 */ 348static int 349set_percent_option(pointer options, const char *optname, 350 const int range, const int offset, const int default_value) 351{ 352 int result; 353 double percent = xf86CheckPercentOption(options, optname, -1); 354 355 if (percent >= 0.0) { 356 percent = xf86SetPercentOption(options, optname, -1); 357 result = percent / 100.0 * range + offset; 358 } else 359 result = xf86SetIntOption(options, optname, default_value); 360 361 return result; 362} 363 364Bool 365SynapticsIsSoftButtonAreasValid(int *values) 366{ 367 Bool right_disabled = FALSE; 368 Bool middle_disabled = FALSE; 369 370 enum { 371 /* right button left, right, top, bottom */ 372 RBL = 0, 373 RBR = 1, 374 RBT = 2, 375 RBB = 3, 376 /* middle button left, right, top, bottom */ 377 MBL = 4, 378 MBR = 5, 379 MBT = 6, 380 MBB = 7, 381 }; 382 383 /* Check right button area */ 384 if ((((values[RBL] != 0) && (values[RBR] != 0)) && (values[RBL] > values[RBR])) || 385 (((values[RBT] != 0) && (values[RBB] != 0)) && (values[RBT] > values[RBB]))) 386 return FALSE; 387 388 /* Check middle button area */ 389 if ((((values[MBL] != 0) && (values[MBR] != 0)) && (values[MBL] > values[MBR])) || 390 (((values[MBT] != 0) && (values[MBB] != 0)) && (values[MBT] > values[MBB]))) 391 return FALSE; 392 393 if (values[RBL] == 0 && values[RBR] == 0 && values[RBT] == 0 && values[RBB] == 0) 394 right_disabled = TRUE; 395 396 if (values[MBL] == 0 && values[MBR] == 0 && values[MBT] == 0 && values[MBB] == 0) 397 middle_disabled = TRUE; 398 399 if (!right_disabled && 400 ((values[RBL] && values[RBL] == values[RBR]) || 401 (values[RBT] && values[RBT] == values[RBB]))) 402 return FALSE; 403 404 if (!middle_disabled && 405 ((values[MBL] && values[MBL] == values[MBR]) || 406 (values[MBT] && values[MBT] == values[MBB]))) 407 return FALSE; 408 409 /* Check for overlapping button areas */ 410 if (!right_disabled && !middle_disabled) { 411 int right_left = values[RBL] ? values[RBL] : INT_MIN; 412 int right_right = values[RBR] ? values[RBR] : INT_MAX; 413 int right_top = values[RBT] ? values[RBT] : INT_MIN; 414 int right_bottom = values[RBB] ? values[RBB] : INT_MAX; 415 int middle_left = values[MBL] ? values[MBL] : INT_MIN; 416 int middle_right = values[MBR] ? values[MBR] : INT_MAX; 417 int middle_top = values[MBT] ? values[MBT] : INT_MIN; 418 int middle_bottom = values[MBB] ? values[MBB] : INT_MAX; 419 420 /* If areas overlap in the Y axis */ 421 if ((right_bottom <= middle_bottom && right_bottom >= middle_top) || 422 (right_top <= middle_bottom && right_top >= middle_top)) { 423 /* Check for overlapping left edges */ 424 if ((right_left < middle_left && right_right > middle_left) || 425 (middle_left < right_left && middle_right > right_left)) 426 return FALSE; 427 428 /* Check for overlapping right edges */ 429 if ((right_right > middle_right && right_left < middle_right) || 430 (middle_right > right_right && middle_left < right_right)) 431 return FALSE; 432 } 433 434 /* If areas overlap in the X axis */ 435 if ((right_left >= middle_left && right_left <= middle_right) || 436 (right_right >= middle_left && right_right <= middle_right)) { 437 /* Check for overlapping top edges */ 438 if ((right_top < middle_top && right_bottom > middle_top) || 439 (middle_top < right_top && middle_bottom > right_top)) 440 return FALSE; 441 442 /* Check for overlapping bottom edges */ 443 if ((right_bottom > middle_bottom && right_top < middle_bottom) || 444 (middle_bottom > right_bottom && middle_top < right_bottom)) 445 return FALSE; 446 } 447 } 448 449 return TRUE; 450} 451 452static void 453set_softbutton_areas_option(InputInfoPtr pInfo) 454{ 455 SynapticsPrivate *priv = pInfo->private; 456 SynapticsParameters *pars = &priv->synpara; 457 int values[8]; 458 int in_percent = 0; /* bitmask for which ones are in % */ 459 char *option_string; 460 char *next_num; 461 char *end_str; 462 int i; 463 int width, height; 464 465 if (!pars->clickpad) 466 return; 467 468 option_string = xf86SetStrOption(pInfo->options, "SoftButtonAreas", NULL); 469 if (!option_string) 470 return; 471 472 next_num = option_string; 473 474 for (i = 0; i < 8 && *next_num != '\0'; i++) { 475 long int value = strtol(next_num, &end_str, 0); 476 477 if (value > INT_MAX || value < -INT_MAX) 478 goto fail; 479 480 values[i] = value; 481 482 if (next_num != end_str) { 483 if (end_str && *end_str == '%') { 484 in_percent |= 1 << i; 485 end_str++; 486 } 487 next_num = end_str; 488 } 489 else 490 goto fail; 491 } 492 493 if (i < 8 || *next_num != '\0') 494 goto fail; 495 496 width = priv->maxx - priv->minx; 497 height = priv->maxy - priv->miny; 498 499 for (i = 0; in_percent && i < 8; i++) { 500 int base, size; 501 502 if ((in_percent & (1 << i)) == 0 || values[i] == 0) 503 continue; 504 505 size = ((i % 4) < 2) ? width : height; 506 base = ((i % 4) < 2) ? priv->minx : priv->miny; 507 values[i] = base + size * values[i] / 100.0; 508 } 509 510 if (!SynapticsIsSoftButtonAreasValid(values)) 511 goto fail; 512 513 memcpy(pars->softbutton_areas[0], values, 4 * sizeof(int)); 514 memcpy(pars->softbutton_areas[1], values + 4, 4 * sizeof(int)); 515 516 free(option_string); 517 518 return; 519 520 fail: 521 xf86IDrvMsg(pInfo, X_ERROR, 522 "invalid SoftButtonAreas value '%s', keeping defaults\n", 523 option_string); 524 free(option_string); 525} 526 527static void 528set_default_parameters(InputInfoPtr pInfo) 529{ 530 SynapticsPrivate *priv = pInfo->private; /* read-only */ 531 pointer opts = pInfo->options; /* read-only */ 532 SynapticsParameters *pars = &priv->synpara; /* modified */ 533 534 int horizScrollDelta, vertScrollDelta; /* pixels */ 535 int tapMove; /* pixels */ 536 int l, r, t, b; /* left, right, top, bottom */ 537 double accelFactor; /* 1/pixels */ 538 int fingerLow, fingerHigh; /* pressure */ 539 int emulateTwoFingerMinZ; /* pressure */ 540 int emulateTwoFingerMinW; /* width */ 541 int pressureMotionMinZ, pressureMotionMaxZ; /* pressure */ 542 int palmMinWidth, palmMinZ; /* pressure */ 543 int tapButton1, tapButton2, tapButton3; 544 int clickFinger1, clickFinger2, clickFinger3; 545 Bool vertEdgeScroll, horizEdgeScroll; 546 Bool vertTwoFingerScroll, horizTwoFingerScroll; 547 int horizResolution = 1; 548 int vertResolution = 1; 549 int width, height, diag, range; 550 int horizHyst, vertHyst; 551 int middle_button_timeout; 552 553 /* The synaptics specs specify typical edge widths of 4% on x, and 5.4% on 554 * y (page 7) [Synaptics TouchPad Interfacing Guide, 510-000080 - A 555 * Second Edition, http://www.synaptics.com/support/dev_support.cfm, 8 Sep 556 * 2008]. We use 7% for both instead for synaptics devices, and 15% for 557 * ALPS models. 558 * http://bugs.freedesktop.org/show_bug.cgi?id=21214 559 * 560 * If the range was autodetected, apply these edge widths to all four 561 * sides. 562 */ 563 564 width = abs(priv->maxx - priv->minx); 565 height = abs(priv->maxy - priv->miny); 566 diag = sqrt(width * width + height * height); 567 568 calculate_edge_widths(priv, &l, &r, &t, &b); 569 570 /* Again, based on typical x/y range and defaults */ 571 horizScrollDelta = diag * .020; 572 vertScrollDelta = diag * .020; 573 tapMove = diag * .044; 574 accelFactor = 200.0 / diag; /* trial-and-error */ 575 576 /* hysteresis, assume >= 0 is a detected value (e.g. evdev fuzz) */ 577 horizHyst = pars->hyst_x >= 0 ? pars->hyst_x : diag * 0.005; 578 vertHyst = pars->hyst_y >= 0 ? pars->hyst_y : diag * 0.005; 579 580 range = priv->maxp - priv->minp + 1; 581 582 calculate_tap_hysteresis(priv, range, &fingerLow, &fingerHigh); 583 584 /* scaling based on defaults and a pressure of 256 */ 585 emulateTwoFingerMinZ = priv->minp + range * (282.0 / 256); 586 pressureMotionMinZ = priv->minp + range * (30.0 / 256); 587 pressureMotionMaxZ = priv->minp + range * (160.0 / 256); 588 palmMinZ = priv->minp + range * (200.0 / 256); 589 590 range = priv->maxw - priv->minw + 1; 591 592 /* scaling based on defaults below and a tool width of 16 */ 593 palmMinWidth = priv->minw + range * (10.0 / 16); 594 emulateTwoFingerMinW = priv->minw + range * (7.0 / 16); 595 596 /* Enable tap if we don't have a phys left button */ 597 tapButton1 = priv->has_left ? 0 : 1; 598 tapButton2 = priv->has_left ? 0 : 3; 599 tapButton3 = priv->has_left ? 0 : 2; 600 601 /* Enable multifinger-click if only have one physical button, 602 otherwise clickFinger is always button 1. */ 603 clickFinger1 = 1; 604 clickFinger2 = (priv->has_right || priv->has_middle) ? 1 : 3; 605 clickFinger3 = (priv->has_right || priv->has_middle) ? 1 : 2; 606 607 /* Enable vert edge scroll if we can't detect doubletap */ 608 vertEdgeScroll = priv->has_double ? FALSE : TRUE; 609 horizEdgeScroll = FALSE; 610 611 /* Enable twofinger scroll if we can detect doubletap */ 612 vertTwoFingerScroll = priv->has_double ? TRUE : FALSE; 613 horizTwoFingerScroll = FALSE; 614 615 /* Use resolution reported by hardware if available */ 616 if ((priv->resx > 0) && (priv->resy > 0)) { 617 horizResolution = priv->resx; 618 vertResolution = priv->resy; 619 } 620 621 /* set the parameters */ 622 pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l); 623 pars->right_edge = xf86SetIntOption(opts, "RightEdge", r); 624 pars->top_edge = xf86SetIntOption(opts, "TopEdge", t); 625 pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", b); 626 627 pars->area_top_edge = 628 set_percent_option(opts, "AreaTopEdge", height, priv->miny, 0); 629 pars->area_bottom_edge = 630 set_percent_option(opts, "AreaBottomEdge", height, priv->miny, 0); 631 pars->area_left_edge = 632 set_percent_option(opts, "AreaLeftEdge", width, priv->minx, 0); 633 pars->area_right_edge = 634 set_percent_option(opts, "AreaRightEdge", width, priv->minx, 0); 635 636 pars->hyst_x = 637 set_percent_option(opts, "HorizHysteresis", width, 0, horizHyst); 638 pars->hyst_y = 639 set_percent_option(opts, "VertHysteresis", height, 0, vertHyst); 640 641 pars->finger_low = xf86SetIntOption(opts, "FingerLow", fingerLow); 642 pars->finger_high = xf86SetIntOption(opts, "FingerHigh", fingerHigh); 643 pars->tap_time = xf86SetIntOption(opts, "MaxTapTime", 180); 644 pars->tap_move = xf86SetIntOption(opts, "MaxTapMove", tapMove); 645 pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180); 646 pars->click_time = xf86SetIntOption(opts, "ClickTime", 100); 647 pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad); /* Probed */ 648 /* middle mouse button emulation on a clickpad? nah, you're joking */ 649 middle_button_timeout = pars->clickpad ? 0 : 75; 650 pars->emulate_mid_button_time = 651 xf86SetIntOption(opts, "EmulateMidButtonTime", middle_button_timeout); 652 pars->emulate_twofinger_z = 653 xf86SetIntOption(opts, "EmulateTwoFingerMinZ", emulateTwoFingerMinZ); 654 pars->emulate_twofinger_w = 655 xf86SetIntOption(opts, "EmulateTwoFingerMinW", emulateTwoFingerMinW); 656 pars->scroll_dist_vert = 657 xf86SetIntOption(opts, "VertScrollDelta", vertScrollDelta); 658 pars->scroll_dist_horiz = 659 xf86SetIntOption(opts, "HorizScrollDelta", horizScrollDelta); 660 pars->scroll_edge_vert = 661 xf86SetBoolOption(opts, "VertEdgeScroll", vertEdgeScroll); 662 pars->scroll_edge_horiz = 663 xf86SetBoolOption(opts, "HorizEdgeScroll", horizEdgeScroll); 664 pars->scroll_edge_corner = xf86SetBoolOption(opts, "CornerCoasting", FALSE); 665 pars->scroll_twofinger_vert = 666 xf86SetBoolOption(opts, "VertTwoFingerScroll", vertTwoFingerScroll); 667 pars->scroll_twofinger_horiz = 668 xf86SetBoolOption(opts, "HorizTwoFingerScroll", horizTwoFingerScroll); 669 pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", TOUCHPAD_ON); 670 pars->locked_drags = xf86SetBoolOption(opts, "LockedDrags", FALSE); 671 pars->locked_drag_time = xf86SetIntOption(opts, "LockedDragTimeout", 5000); 672 pars->tap_action[RT_TAP] = xf86SetIntOption(opts, "RTCornerButton", 0); 673 pars->tap_action[RB_TAP] = xf86SetIntOption(opts, "RBCornerButton", 0); 674 pars->tap_action[LT_TAP] = xf86SetIntOption(opts, "LTCornerButton", 0); 675 pars->tap_action[LB_TAP] = xf86SetIntOption(opts, "LBCornerButton", 0); 676 pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1", tapButton1); 677 pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2", tapButton2); 678 pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3", tapButton3); 679 pars->click_action[F1_CLICK1] = 680 xf86SetIntOption(opts, "ClickFinger1", clickFinger1); 681 pars->click_action[F2_CLICK1] = 682 xf86SetIntOption(opts, "ClickFinger2", clickFinger2); 683 pars->click_action[F3_CLICK1] = 684 xf86SetIntOption(opts, "ClickFinger3", clickFinger3); 685 pars->circular_scrolling = 686 xf86SetBoolOption(opts, "CircularScrolling", FALSE); 687 pars->circular_trigger = xf86SetIntOption(opts, "CircScrollTrigger", 0); 688 pars->palm_detect = xf86SetBoolOption(opts, "PalmDetect", FALSE); 689 pars->palm_min_width = xf86SetIntOption(opts, "PalmMinWidth", palmMinWidth); 690 pars->palm_min_z = xf86SetIntOption(opts, "PalmMinZ", palmMinZ); 691 pars->single_tap_timeout = xf86SetIntOption(opts, "SingleTapTimeout", 180); 692 pars->press_motion_min_z = 693 xf86SetIntOption(opts, "PressureMotionMinZ", pressureMotionMinZ); 694 pars->press_motion_max_z = 695 xf86SetIntOption(opts, "PressureMotionMaxZ", pressureMotionMaxZ); 696 697 pars->min_speed = xf86SetRealOption(opts, "MinSpeed", 0.4); 698 pars->max_speed = xf86SetRealOption(opts, "MaxSpeed", 0.7); 699 pars->accl = xf86SetRealOption(opts, "AccelFactor", accelFactor); 700 pars->scroll_dist_circ = xf86SetRealOption(opts, "CircScrollDelta", 0.1); 701 pars->coasting_speed = xf86SetRealOption(opts, "CoastingSpeed", 20.0); 702 pars->coasting_friction = xf86SetRealOption(opts, "CoastingFriction", 50); 703 pars->press_motion_min_factor = 704 xf86SetRealOption(opts, "PressureMotionMinFactor", 1.0); 705 pars->press_motion_max_factor = 706 xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0); 707 pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", TRUE); 708 pars->tap_and_drag_gesture = 709 xf86SetBoolOption(opts, "TapAndDragGesture", TRUE); 710 pars->resolution_horiz = 711 xf86SetIntOption(opts, "HorizResolution", horizResolution); 712 pars->resolution_vert = 713 xf86SetIntOption(opts, "VertResolution", vertResolution); 714 715 /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */ 716 if (pars->top_edge > pars->bottom_edge) { 717 int tmp = pars->top_edge; 718 719 pars->top_edge = pars->bottom_edge; 720 pars->bottom_edge = tmp; 721 xf86IDrvMsg(pInfo, X_WARNING, 722 "TopEdge is bigger than BottomEdge. Fixing.\n"); 723 } 724 725 set_softbutton_areas_option(pInfo); 726} 727 728static double 729SynapticsAccelerationProfile(DeviceIntPtr dev, 730 DeviceVelocityPtr vel, 731 double velocity, double thr, double acc) 732{ 733 InputInfoPtr pInfo = dev->public.devicePrivate; 734 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 735 SynapticsParameters *para = &priv->synpara; 736 737 double accelfct; 738 739 /* 740 * synaptics accel was originally base on device coordinate based 741 * velocity, which we recover this way so para->accl retains its scale. 742 */ 743 velocity /= vel->const_acceleration; 744 745 /* speed up linear with finger velocity */ 746 accelfct = velocity * para->accl; 747 748 /* clip acceleration factor */ 749 if (accelfct > para->max_speed * acc) 750 accelfct = para->max_speed * acc; 751 else if (accelfct < para->min_speed) 752 accelfct = para->min_speed; 753 754 /* modify speed according to pressure */ 755 if (priv->moving_state == MS_TOUCHPAD_RELATIVE) { 756 int minZ = para->press_motion_min_z; 757 int maxZ = para->press_motion_max_z; 758 double minFctr = para->press_motion_min_factor; 759 double maxFctr = para->press_motion_max_factor; 760 761 if (priv->hwState->z <= minZ) { 762 accelfct *= minFctr; 763 } 764 else if (priv->hwState->z >= maxZ) { 765 accelfct *= maxFctr; 766 } 767 else { 768 accelfct *= 769 minFctr + (priv->hwState->z - minZ) * (maxFctr - 770 minFctr) / (maxZ - minZ); 771 } 772 } 773 774 return accelfct; 775} 776 777static int 778SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 779{ 780 SynapticsPrivate *priv; 781 782 /* allocate memory for SynapticsPrivateRec */ 783 priv = calloc(1, sizeof(SynapticsPrivate)); 784 if (!priv) 785 return BadAlloc; 786 787 pInfo->type_name = XI_TOUCHPAD; 788 pInfo->device_control = DeviceControl; 789 pInfo->read_input = ReadInput; 790 pInfo->control_proc = ControlProc; 791 pInfo->switch_mode = SwitchMode; 792 pInfo->private = priv; 793 794 /* allocate now so we don't allocate in the signal handler */ 795 priv->timer = TimerSet(NULL, 0, 0, NULL, NULL); 796 if (!priv->timer) { 797 free(priv); 798 return BadAlloc; 799 } 800 801 /* may change pInfo->options */ 802 if (!SetDeviceAndProtocol(pInfo)) { 803 xf86IDrvMsg(pInfo, X_ERROR, 804 "Synaptics driver unable to detect protocol\n"); 805 goto SetupProc_fail; 806 } 807 808 priv->device = xf86FindOptionValue(pInfo->options, "Device"); 809 810 /* open the touchpad device */ 811 pInfo->fd = xf86OpenSerial(pInfo->options); 812 if (pInfo->fd == -1) { 813 xf86IDrvMsg(pInfo, X_ERROR, "Synaptics driver unable to open device\n"); 814 goto SetupProc_fail; 815 } 816 xf86ErrorFVerb(6, "port opened successfully\n"); 817 818 /* initialize variables */ 819 priv->count_packet_finger = 0; 820 priv->tap_state = TS_START; 821 priv->tap_button = 0; 822 priv->tap_button_state = TBS_BUTTON_UP; 823 priv->touch_on.millis = 0; 824 priv->synpara.hyst_x = -1; 825 priv->synpara.hyst_y = -1; 826 827 /* read hardware dimensions */ 828 ReadDevDimensions(pInfo); 829 830 set_default_parameters(pInfo); 831 832 CalculateScalingCoeffs(priv); 833 834 priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE); 835 836 if (!QueryHardware(pInfo)) { 837 xf86IDrvMsg(pInfo, X_ERROR, 838 "Unable to query/initialize Synaptics hardware.\n"); 839 goto SetupProc_fail; 840 } 841 842 xf86ProcessCommonOptions(pInfo, pInfo->options); 843 844 if (pInfo->fd != -1) { 845 if (priv->comm.buffer) { 846 XisbFree(priv->comm.buffer); 847 priv->comm.buffer = NULL; 848 } 849 xf86CloseSerial(pInfo->fd); 850 } 851 pInfo->fd = -1; 852 853 return Success; 854 855 SetupProc_fail: 856 if (pInfo->fd >= 0) { 857 xf86CloseSerial(pInfo->fd); 858 pInfo->fd = -1; 859 } 860 861 if (priv->comm.buffer) 862 XisbFree(priv->comm.buffer); 863 free(priv->proto_data); 864 free(priv->timer); 865 free(priv); 866 pInfo->private = NULL; 867 return BadAlloc; 868} 869 870/* 871 * Uninitialize the device. 872 */ 873static void 874SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 875{ 876 SynapticsPrivate *priv = ((SynapticsPrivate *) pInfo->private); 877 878 if (priv && priv->timer) 879 free(priv->timer); 880 if (priv && priv->proto_data) 881 free(priv->proto_data); 882 if (priv && priv->scroll_events_mask) 883 valuator_mask_free(&priv->scroll_events_mask); 884 if (priv && priv->open_slots) 885 free(priv->open_slots); 886 free(pInfo->private); 887 pInfo->private = NULL; 888 xf86DeleteInput(pInfo, 0); 889} 890 891/* 892 * Alter the control parameters for the mouse. Note that all special 893 * protocol values are handled by dix. 894 */ 895static void 896SynapticsCtrl(DeviceIntPtr device, PtrCtrl * ctrl) 897{ 898} 899 900static int 901DeviceControl(DeviceIntPtr dev, int mode) 902{ 903 Bool RetValue; 904 905 switch (mode) { 906 case DEVICE_INIT: 907 RetValue = DeviceInit(dev); 908 break; 909 case DEVICE_ON: 910 RetValue = DeviceOn(dev); 911 break; 912 case DEVICE_OFF: 913 RetValue = DeviceOff(dev); 914 break; 915 case DEVICE_CLOSE: 916 RetValue = DeviceClose(dev); 917 break; 918 default: 919 RetValue = BadValue; 920 } 921 922 return RetValue; 923} 924 925static int 926DeviceOn(DeviceIntPtr dev) 927{ 928 InputInfoPtr pInfo = dev->public.devicePrivate; 929 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 930 931 DBG(3, "Synaptics DeviceOn called\n"); 932 933 pInfo->fd = xf86OpenSerial(pInfo->options); 934 if (pInfo->fd == -1) { 935 xf86IDrvMsg(pInfo, X_WARNING, "cannot open input device\n"); 936 return !Success; 937 } 938 939 if (priv->proto_ops->DeviceOnHook && 940 !priv->proto_ops->DeviceOnHook(pInfo, &priv->synpara)) 941 return !Success; 942 943 priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE); 944 if (!priv->comm.buffer) { 945 xf86CloseSerial(pInfo->fd); 946 pInfo->fd = -1; 947 return !Success; 948 } 949 950 xf86FlushInput(pInfo->fd); 951 952 /* reinit the pad */ 953 if (!QueryHardware(pInfo)) { 954 XisbFree(priv->comm.buffer); 955 priv->comm.buffer = NULL; 956 xf86CloseSerial(pInfo->fd); 957 pInfo->fd = -1; 958 return !Success; 959 } 960 961 xf86AddEnabledDevice(pInfo); 962 dev->public.on = TRUE; 963 964 return Success; 965} 966 967static void 968SynapticsReset(SynapticsPrivate * priv) 969{ 970 SynapticsResetHwState(priv->hwState); 971 SynapticsResetHwState(priv->local_hw_state); 972 SynapticsResetHwState(priv->old_hw_state); 973 SynapticsResetHwState(priv->comm.hwState); 974 975 memset(priv->move_hist, 0, sizeof(priv->move_hist)); 976 priv->hyst_center_x = 0; 977 priv->hyst_center_y = 0; 978 memset(&priv->scroll, 0, sizeof(priv->scroll)); 979 priv->count_packet_finger = 0; 980 priv->finger_state = FS_UNTOUCHED; 981 priv->last_motion_millis = 0; 982 priv->tap_state = TS_START; 983 priv->tap_button = 0; 984 priv->tap_button_state = TBS_BUTTON_UP; 985 priv->moving_state = MS_FALSE; 986 priv->vert_scroll_edge_on = FALSE; 987 priv->horiz_scroll_edge_on = FALSE; 988 priv->vert_scroll_twofinger_on = FALSE; 989 priv->horiz_scroll_twofinger_on = FALSE; 990 priv->circ_scroll_on = FALSE; 991 priv->circ_scroll_vert = FALSE; 992 priv->mid_emu_state = MBE_OFF; 993 priv->lastButtons = 0; 994 priv->prev_z = 0; 995 priv->prevFingers = 0; 996 priv->num_active_touches = 0; 997 memset(priv->open_slots, 0, priv->num_slots * sizeof(int)); 998} 999 1000static int 1001DeviceOff(DeviceIntPtr dev) 1002{ 1003 InputInfoPtr pInfo = dev->public.devicePrivate; 1004 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 1005 Bool rc = Success; 1006 1007 DBG(3, "Synaptics DeviceOff called\n"); 1008 1009 if (pInfo->fd != -1) { 1010 TimerCancel(priv->timer); 1011 xf86RemoveEnabledDevice(pInfo); 1012 SynapticsReset(priv); 1013 1014 if (priv->proto_ops->DeviceOffHook && 1015 !priv->proto_ops->DeviceOffHook(pInfo)) 1016 rc = !Success; 1017 if (priv->comm.buffer) { 1018 XisbFree(priv->comm.buffer); 1019 priv->comm.buffer = NULL; 1020 } 1021 xf86CloseSerial(pInfo->fd); 1022 pInfo->fd = -1; 1023 } 1024 dev->public.on = FALSE; 1025 return rc; 1026} 1027 1028static int 1029DeviceClose(DeviceIntPtr dev) 1030{ 1031 Bool RetValue; 1032 InputInfoPtr pInfo = dev->public.devicePrivate; 1033 SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; 1034 1035 RetValue = DeviceOff(dev); 1036 TimerFree(priv->timer); 1037 priv->timer = NULL; 1038 free(priv->touch_axes); 1039 priv->touch_axes = NULL; 1040 SynapticsHwStateFree(&priv->hwState); 1041 SynapticsHwStateFree(&priv->old_hw_state); 1042 SynapticsHwStateFree(&priv->local_hw_state); 1043 SynapticsHwStateFree(&priv->comm.hwState); 1044 return RetValue; 1045} 1046 1047static void 1048InitAxesLabels(Atom *labels, int nlabels, const SynapticsPrivate * priv) 1049{ 1050 int i; 1051 1052 memset(labels, 0, nlabels * sizeof(Atom)); 1053 switch (nlabels) { 1054 default: 1055 case 4: 1056 labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL); 1057 case 3: 1058 labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL); 1059 case 2: 1060 labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 1061 case 1: 1062 labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 1063 break; 1064 } 1065 1066 for (i = 0; i < priv->num_mt_axes; i++) { 1067 SynapticsTouchAxisRec *axis = &priv->touch_axes[i]; 1068 int axnum = nlabels - priv->num_mt_axes + i; 1069 1070 labels[axnum] = XIGetKnownProperty(axis->label); 1071 } 1072} 1073 1074static void 1075InitButtonLabels(Atom *labels, int nlabels) 1076{ 1077 memset(labels, 0, nlabels * sizeof(Atom)); 1078 switch (nlabels) { 1079 default: 1080 case 7: 1081 labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 1082 case 6: 1083 labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 1084 case 5: 1085 labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 1086 case 4: 1087 labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 1088 case 3: 1089 labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 1090 case 2: 1091 labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 1092 case 1: 1093 labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 1094 break; 1095 } 1096} 1097 1098static void 1099DeviceInitTouch(DeviceIntPtr dev, Atom *axes_labels) 1100{ 1101 InputInfoPtr pInfo = dev->public.devicePrivate; 1102 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 1103 int i; 1104 1105 if (priv->has_touch) { 1106 priv->num_slots = 1107 priv->max_touches ? priv->max_touches : SYNAPTICS_MAX_TOUCHES; 1108 1109 priv->open_slots = malloc(priv->num_slots * sizeof(int)); 1110 if (!priv->open_slots) { 1111 xf86IDrvMsg(pInfo, X_ERROR, 1112 "failed to allocate open touch slots array\n"); 1113 priv->has_touch = 0; 1114 priv->num_slots = 0; 1115 return; 1116 } 1117 1118 /* x/y + whatever other MT axes we found */ 1119 if (!InitTouchClassDeviceStruct(dev, priv->max_touches, 1120 XIDependentTouch, 1121 2 + priv->num_mt_axes)) { 1122 xf86IDrvMsg(pInfo, X_ERROR, 1123 "failed to initialize touch class device\n"); 1124 priv->has_touch = 0; 1125 priv->num_slots = 0; 1126 free(priv->open_slots); 1127 priv->open_slots = NULL; 1128 return; 1129 } 1130 1131 for (i = 0; i < priv->num_mt_axes; i++) { 1132 SynapticsTouchAxisRec *axis = &priv->touch_axes[i]; 1133 int axnum = 4 + i; /* Skip x, y, and scroll axes */ 1134 1135 if (!xf86InitValuatorAxisStruct(dev, axnum, axes_labels[axnum], 1136 axis->min, axis->max, axis->res, 0, 1137 axis->res, Absolute)) { 1138 xf86IDrvMsg(pInfo, X_WARNING, 1139 "failed to initialize axis %s, skipping\n", 1140 axis->label); 1141 continue; 1142 } 1143 1144 xf86InitValuatorDefaults(dev, axnum); 1145 } 1146 } 1147} 1148 1149static int 1150DeviceInit(DeviceIntPtr dev) 1151{ 1152 InputInfoPtr pInfo = dev->public.devicePrivate; 1153 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 1154 Atom float_type, prop; 1155 float tmpf; 1156 unsigned char map[SYN_MAX_BUTTONS + 1]; 1157 int i; 1158 int min, max; 1159 int num_axes = 2; 1160 Atom btn_labels[SYN_MAX_BUTTONS] = { 0 }; 1161 Atom *axes_labels; 1162 DeviceVelocityPtr pVel; 1163 1164 num_axes += 2; 1165 1166 num_axes += priv->num_mt_axes; 1167 1168 axes_labels = calloc(num_axes, sizeof(Atom)); 1169 if (!axes_labels) { 1170 xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate axis labels\n"); 1171 return !Success; 1172 } 1173 1174 InitAxesLabels(axes_labels, num_axes, priv); 1175 InitButtonLabels(btn_labels, SYN_MAX_BUTTONS); 1176 1177 DBG(3, "Synaptics DeviceInit called\n"); 1178 1179 for (i = 0; i <= SYN_MAX_BUTTONS; i++) 1180 map[i] = i; 1181 1182 dev->public.on = FALSE; 1183 1184 InitPointerDeviceStruct((DevicePtr) dev, map, 1185 SYN_MAX_BUTTONS, 1186 btn_labels, 1187 SynapticsCtrl, 1188 GetMotionHistorySize(), num_axes, axes_labels); 1189 1190 /* 1191 * setup dix acceleration to match legacy synaptics settings, and 1192 * etablish a device-specific profile to do stuff like pressure-related 1193 * acceleration. 1194 */ 1195 if (NULL != (pVel = GetDevicePredictableAccelData(dev))) { 1196 SetDeviceSpecificAccelerationProfile(pVel, 1197 SynapticsAccelerationProfile); 1198 1199 /* float property type */ 1200 float_type = XIGetKnownProperty(XATOM_FLOAT); 1201 1202 /* translate MinAcc to constant deceleration. 1203 * May be overridden in xf86InitValuatorDefaults */ 1204 tmpf = 1.0 / priv->synpara.min_speed; 1205 1206 xf86IDrvMsg(pInfo, X_CONFIG, 1207 "(accel) MinSpeed is now constant deceleration " "%.1f\n", 1208 tmpf); 1209 prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); 1210 XIChangeDeviceProperty(dev, prop, float_type, 32, 1211 PropModeReplace, 1, &tmpf, FALSE); 1212 1213 /* adjust accordingly */ 1214 priv->synpara.max_speed /= priv->synpara.min_speed; 1215 priv->synpara.min_speed = 1.0; 1216 1217 /* synaptics seems to report 80 packet/s, but dix scales for 1218 * 100 packet/s by default. */ 1219 pVel->corr_mul = 12.5f; /*1000[ms]/80[/s] = 12.5 */ 1220 1221 xf86IDrvMsg(pInfo, X_CONFIG, "(accel) MaxSpeed is now %.2f\n", 1222 priv->synpara.max_speed); 1223 xf86IDrvMsg(pInfo, X_CONFIG, "(accel) AccelFactor is now %.3f\n", 1224 priv->synpara.accl); 1225 1226 prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); 1227 i = AccelProfileDeviceSpecific; 1228 XIChangeDeviceProperty(dev, prop, XA_INTEGER, 32, 1229 PropModeReplace, 1, &i, FALSE); 1230 } 1231 1232 /* X valuator */ 1233 if (priv->minx < priv->maxx) { 1234 min = priv->minx; 1235 max = priv->maxx; 1236 } 1237 else { 1238 min = 0; 1239 max = -1; 1240 } 1241 1242 xf86InitValuatorAxisStruct(dev, 0, axes_labels[0], min, max, 1243 priv->resx * 1000, 0, priv->resx * 1000, 1244 Relative); 1245 xf86InitValuatorDefaults(dev, 0); 1246 1247 /* Y valuator */ 1248 if (priv->miny < priv->maxy) { 1249 min = priv->miny; 1250 max = priv->maxy; 1251 } 1252 else { 1253 min = 0; 1254 max = -1; 1255 } 1256 1257 xf86InitValuatorAxisStruct(dev, 1, axes_labels[1], min, max, 1258 priv->resy * 1000, 0, priv->resy * 1000, 1259 Relative); 1260 xf86InitValuatorDefaults(dev, 1); 1261 1262 xf86InitValuatorAxisStruct(dev, 2, axes_labels[2], 0, -1, 0, 0, 0, 1263 Relative); 1264 priv->scroll_axis_horiz = 2; 1265 xf86InitValuatorAxisStruct(dev, 3, axes_labels[3], 0, -1, 0, 0, 0, 1266 Relative); 1267 priv->scroll_axis_vert = 3; 1268 priv->scroll_events_mask = valuator_mask_new(MAX_VALUATORS); 1269 if (!priv->scroll_events_mask) { 1270 free(axes_labels); 1271 return !Success; 1272 } 1273 1274 SetScrollValuator(dev, priv->scroll_axis_horiz, SCROLL_TYPE_HORIZONTAL, 1275 priv->synpara.scroll_dist_horiz, 0); 1276 SetScrollValuator(dev, priv->scroll_axis_vert, SCROLL_TYPE_VERTICAL, 1277 priv->synpara.scroll_dist_vert, 0); 1278 1279 DeviceInitTouch(dev, axes_labels); 1280 1281 free(axes_labels); 1282 1283 priv->hwState = SynapticsHwStateAlloc(priv); 1284 if (!priv->hwState) 1285 goto fail; 1286 1287 priv->old_hw_state = SynapticsHwStateAlloc(priv); 1288 if (!priv->old_hw_state) 1289 goto fail; 1290 1291 priv->local_hw_state = SynapticsHwStateAlloc(priv); 1292 if (!priv->local_hw_state) 1293 goto fail; 1294 1295 priv->comm.hwState = SynapticsHwStateAlloc(priv); 1296 1297 InitDeviceProperties(pInfo); 1298 XIRegisterPropertyHandler(pInfo->dev, SetProperty, NULL, NULL); 1299 1300 return Success; 1301 1302 fail: 1303 free(priv->local_hw_state); 1304 free(priv->hwState); 1305 free(priv->open_slots); 1306 return !Success; 1307} 1308 1309/* return angle of point relative to center */ 1310static double 1311angle(SynapticsPrivate * priv, int x, int y) 1312{ 1313 double xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2.0; 1314 double yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2.0; 1315 1316 return atan2(-(y - yCenter), x - xCenter); 1317} 1318 1319/* return angle difference */ 1320static double 1321diffa(double a1, double a2) 1322{ 1323 double da = fmod(a2 - a1, 2 * M_PI); 1324 1325 if (da < 0) 1326 da += 2 * M_PI; 1327 if (da > M_PI) 1328 da -= 2 * M_PI; 1329 return da; 1330} 1331 1332static enum EdgeType 1333edge_detection(SynapticsPrivate * priv, int x, int y) 1334{ 1335 enum EdgeType edge = NO_EDGE; 1336 1337 if (x > priv->synpara.right_edge) 1338 edge |= RIGHT_EDGE; 1339 else if (x < priv->synpara.left_edge) 1340 edge |= LEFT_EDGE; 1341 1342 if (y < priv->synpara.top_edge) 1343 edge |= TOP_EDGE; 1344 else if (y > priv->synpara.bottom_edge) 1345 edge |= BOTTOM_EDGE; 1346 1347 return edge; 1348} 1349 1350/* Checks whether coordinates are in the Synaptics Area 1351 * or not. If no Synaptics Area is defined (i.e. if 1352 * priv->synpara.area_{left|right|top|bottom}_edge are 1353 * all set to zero), the function returns TRUE. 1354 */ 1355static Bool 1356is_inside_active_area(SynapticsPrivate * priv, int x, int y) 1357{ 1358 Bool inside_area = TRUE; 1359 1360 if ((priv->synpara.area_left_edge != 0) && 1361 (x < priv->synpara.area_left_edge)) 1362 inside_area = FALSE; 1363 else if ((priv->synpara.area_right_edge != 0) && 1364 (x > priv->synpara.area_right_edge)) 1365 inside_area = FALSE; 1366 1367 if ((priv->synpara.area_top_edge != 0) && (y < priv->synpara.area_top_edge)) 1368 inside_area = FALSE; 1369 else if ((priv->synpara.area_bottom_edge != 0) && 1370 (y > priv->synpara.area_bottom_edge)) 1371 inside_area = FALSE; 1372 1373 return inside_area; 1374} 1375 1376static Bool 1377is_inside_button_area(SynapticsParameters * para, int which, int x, int y) 1378{ 1379 Bool inside_area = TRUE; 1380 1381 enum { 1382 LEFT = 0, 1383 RIGHT = 1, 1384 TOP = 2, 1385 BOTTOM = 3 1386 }; 1387 1388 if (para->softbutton_areas[which][LEFT] == 0 && 1389 para->softbutton_areas[which][RIGHT] == 0 && 1390 para->softbutton_areas[which][TOP] == 0 && 1391 para->softbutton_areas[which][BOTTOM] == 0) 1392 return FALSE; 1393 1394 if (para->softbutton_areas[which][LEFT] && 1395 x < para->softbutton_areas[which][LEFT]) 1396 inside_area = FALSE; 1397 else if (para->softbutton_areas[which][RIGHT] && 1398 x > para->softbutton_areas[which][RIGHT]) 1399 inside_area = FALSE; 1400 else if (para->softbutton_areas[which][TOP] && 1401 y < para->softbutton_areas[which][TOP]) 1402 inside_area = FALSE; 1403 else if (para->softbutton_areas[which][BOTTOM] && 1404 y > para->softbutton_areas[which][BOTTOM]) 1405 inside_area = FALSE; 1406 1407 return inside_area; 1408} 1409 1410static Bool 1411is_inside_rightbutton_area(SynapticsParameters * para, int x, int y) 1412{ 1413 return is_inside_button_area(para, 0, x, y); 1414} 1415 1416static Bool 1417is_inside_middlebutton_area(SynapticsParameters * para, int x, int y) 1418{ 1419 return is_inside_button_area(para, 1, x, y); 1420} 1421 1422static CARD32 1423timerFunc(OsTimerPtr timer, CARD32 now, pointer arg) 1424{ 1425 InputInfoPtr pInfo = arg; 1426 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 1427 struct SynapticsHwState *hw = priv->local_hw_state; 1428 int delay; 1429 int sigstate; 1430 1431 sigstate = xf86BlockSIGIO(); 1432 1433 priv->hwState->millis += now - priv->timer_time; 1434 SynapticsCopyHwState(hw, priv->hwState); 1435 SynapticsResetTouchHwState(hw, FALSE); 1436 delay = HandleState(pInfo, hw, hw->millis, TRUE); 1437 1438 priv->timer_time = now; 1439 priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo); 1440 1441 xf86UnblockSIGIO(sigstate); 1442 1443 return 0; 1444} 1445 1446static int 1447clamp(int val, int min, int max) 1448{ 1449 if (val < min) 1450 return min; 1451 else if (val < max) 1452 return val; 1453 else 1454 return max; 1455} 1456 1457static Bool 1458SynapticsGetHwState(InputInfoPtr pInfo, SynapticsPrivate * priv, 1459 struct SynapticsHwState *hw) 1460{ 1461 return priv->proto_ops->ReadHwState(pInfo, &priv->comm, hw); 1462} 1463 1464/* 1465 * called for each full received packet from the touchpad 1466 */ 1467static void 1468ReadInput(InputInfoPtr pInfo) 1469{ 1470 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 1471 struct SynapticsHwState *hw = priv->local_hw_state; 1472 int delay = 0; 1473 Bool newDelay = FALSE; 1474 1475 SynapticsResetTouchHwState(hw, FALSE); 1476 1477 while (SynapticsGetHwState(pInfo, priv, hw)) { 1478 /* Semi-mt device touch slots do not track touches. When there is a 1479 * change in the number of touches, we must disregard the temporary 1480 * motion changes. */ 1481 if (priv->has_semi_mt && hw->numFingers != priv->hwState->numFingers) { 1482 hw->cumulative_dx = priv->hwState->cumulative_dx; 1483 hw->cumulative_dy = priv->hwState->cumulative_dy; 1484 } 1485 1486 /* timer may cause actual events to lag behind (#48777) */ 1487 if (priv->hwState->millis > hw->millis) 1488 hw->millis = priv->hwState->millis; 1489 1490 SynapticsCopyHwState(priv->hwState, hw); 1491 delay = HandleState(pInfo, hw, hw->millis, FALSE); 1492 newDelay = TRUE; 1493 } 1494 1495 if (newDelay) { 1496 priv->timer_time = GetTimeInMillis(); 1497 priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo); 1498 } 1499} 1500 1501static int 1502HandleMidButtonEmulation(SynapticsPrivate * priv, struct SynapticsHwState *hw, 1503 CARD32 now, int *delay) 1504{ 1505 SynapticsParameters *para = &priv->synpara; 1506 Bool done = FALSE; 1507 int timeleft; 1508 int mid = 0; 1509 1510 if (para->emulate_mid_button_time <= 0) 1511 return mid; 1512 1513 while (!done) { 1514 switch (priv->mid_emu_state) { 1515 case MBE_LEFT_CLICK: 1516 case MBE_RIGHT_CLICK: 1517 case MBE_OFF: 1518 priv->button_delay_millis = now; 1519 if (hw->left) { 1520 priv->mid_emu_state = MBE_LEFT; 1521 } 1522 else if (hw->right) { 1523 priv->mid_emu_state = MBE_RIGHT; 1524 } 1525 else { 1526 done = TRUE; 1527 } 1528 break; 1529 case MBE_LEFT: 1530 timeleft = 1531 TIME_DIFF(priv->button_delay_millis + 1532 para->emulate_mid_button_time, now); 1533 if (timeleft > 0) 1534 *delay = MIN(*delay, timeleft); 1535 1536 /* timeout, but within the same ReadInput cycle! */ 1537 if ((timeleft <= 0) && !hw->left) { 1538 priv->mid_emu_state = MBE_LEFT_CLICK; 1539 done = TRUE; 1540 } 1541 else if ((!hw->left) || (timeleft <= 0)) { 1542 hw->left = TRUE; 1543 priv->mid_emu_state = MBE_TIMEOUT; 1544 done = TRUE; 1545 } 1546 else if (hw->right) { 1547 priv->mid_emu_state = MBE_MID; 1548 } 1549 else { 1550 hw->left = FALSE; 1551 done = TRUE; 1552 } 1553 break; 1554 case MBE_RIGHT: 1555 timeleft = 1556 TIME_DIFF(priv->button_delay_millis + 1557 para->emulate_mid_button_time, now); 1558 if (timeleft > 0) 1559 *delay = MIN(*delay, timeleft); 1560 1561 /* timeout, but within the same ReadInput cycle! */ 1562 if ((timeleft <= 0) && !hw->right) { 1563 priv->mid_emu_state = MBE_RIGHT_CLICK; 1564 done = TRUE; 1565 } 1566 else if (!hw->right || (timeleft <= 0)) { 1567 hw->right = TRUE; 1568 priv->mid_emu_state = MBE_TIMEOUT; 1569 done = TRUE; 1570 } 1571 else if (hw->left) { 1572 priv->mid_emu_state = MBE_MID; 1573 } 1574 else { 1575 hw->right = FALSE; 1576 done = TRUE; 1577 } 1578 break; 1579 case MBE_MID: 1580 if (!hw->left && !hw->right) { 1581 priv->mid_emu_state = MBE_OFF; 1582 } 1583 else { 1584 mid = TRUE; 1585 hw->left = hw->right = FALSE; 1586 done = TRUE; 1587 } 1588 break; 1589 case MBE_TIMEOUT: 1590 if (!hw->left && !hw->right) { 1591 priv->mid_emu_state = MBE_OFF; 1592 } 1593 else { 1594 done = TRUE; 1595 } 1596 } 1597 } 1598 return mid; 1599} 1600 1601static enum FingerState 1602SynapticsDetectFinger(SynapticsPrivate * priv, struct SynapticsHwState *hw) 1603{ 1604 SynapticsParameters *para = &priv->synpara; 1605 enum FingerState finger; 1606 1607 /* finger detection thru pressure and threshold */ 1608 if (hw->z < para->finger_low) 1609 return FS_UNTOUCHED; 1610 1611 if (priv->finger_state == FS_BLOCKED) 1612 return FS_BLOCKED; 1613 1614 if (hw->z > para->finger_high && priv->finger_state == FS_UNTOUCHED) 1615 finger = FS_TOUCHED; 1616 else 1617 finger = priv->finger_state; 1618 1619 if (!para->palm_detect) 1620 return finger; 1621 1622 /* palm detection */ 1623 1624 if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width)) 1625 return FS_BLOCKED; 1626 1627 if (hw->x == 0 || priv->finger_state == FS_UNTOUCHED) 1628 priv->avg_width = 0; 1629 else 1630 priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2; 1631 1632 if (finger != FS_UNTOUCHED && priv->finger_state == FS_UNTOUCHED) { 1633 int safe_width = MAX(hw->fingerWidth, priv->avg_width); 1634 1635 if (hw->numFingers > 1 || /* more than one finger -> not a palm */ 1636 ((safe_width < 6) && (priv->prev_z < para->finger_high)) || /* thin finger, distinct touch -> not a palm */ 1637 ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))) { /* thin finger, distinct touch -> not a palm */ 1638 /* leave finger value as is */ 1639 } 1640 else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */ 1641 finger = FS_UNTOUCHED; 1642 else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */ 1643 finger = FS_UNTOUCHED; 1644 else if (hw->fingerWidth > para->palm_min_width) /* finger width too large -> probably palm */ 1645 finger = FS_UNTOUCHED; 1646 } 1647 priv->prev_z = hw->z; 1648 1649 return finger; 1650} 1651 1652static void 1653SelectTapButton(SynapticsPrivate * priv, enum EdgeType edge) 1654{ 1655 enum TapEvent tap; 1656 1657 if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF) { 1658 priv->tap_button = 0; 1659 return; 1660 } 1661 1662 switch (priv->tap_max_fingers) { 1663 case 1: 1664 switch (edge) { 1665 case RIGHT_TOP_EDGE: 1666 DBG(7, "right top edge\n"); 1667 tap = RT_TAP; 1668 break; 1669 case RIGHT_BOTTOM_EDGE: 1670 DBG(7, "right bottom edge\n"); 1671 tap = RB_TAP; 1672 break; 1673 case LEFT_TOP_EDGE: 1674 DBG(7, "left top edge\n"); 1675 tap = LT_TAP; 1676 break; 1677 case LEFT_BOTTOM_EDGE: 1678 DBG(7, "left bottom edge\n"); 1679 tap = LB_TAP; 1680 break; 1681 default: 1682 DBG(7, "no edge\n"); 1683 tap = F1_TAP; 1684 break; 1685 } 1686 break; 1687 case 2: 1688 DBG(7, "two finger tap\n"); 1689 tap = F2_TAP; 1690 break; 1691 case 3: 1692 DBG(7, "three finger tap\n"); 1693 tap = F3_TAP; 1694 break; 1695 default: 1696 priv->tap_button = 0; 1697 return; 1698 } 1699 1700 priv->tap_button = priv->synpara.tap_action[tap]; 1701 priv->tap_button = clamp(priv->tap_button, 0, SYN_MAX_BUTTONS); 1702} 1703 1704static void 1705SetTapState(SynapticsPrivate * priv, enum TapState tap_state, CARD32 millis) 1706{ 1707 DBG(3, "SetTapState - %d -> %d (millis:%u)\n", priv->tap_state, tap_state, 1708 millis); 1709 switch (tap_state) { 1710 case TS_START: 1711 priv->tap_button_state = TBS_BUTTON_UP; 1712 priv->tap_max_fingers = 0; 1713 break; 1714 case TS_1: 1715 priv->tap_button_state = TBS_BUTTON_UP; 1716 break; 1717 case TS_2A: 1718 priv->tap_button_state = TBS_BUTTON_UP; 1719 break; 1720 case TS_2B: 1721 priv->tap_button_state = TBS_BUTTON_UP; 1722 break; 1723 case TS_3: 1724 priv->tap_button_state = TBS_BUTTON_DOWN; 1725 break; 1726 case TS_SINGLETAP: 1727 priv->tap_button_state = TBS_BUTTON_DOWN; 1728 priv->touch_on.millis = millis; 1729 break; 1730 default: 1731 break; 1732 } 1733 priv->tap_state = tap_state; 1734} 1735 1736static void 1737SetMovingState(SynapticsPrivate * priv, enum MovingState moving_state, 1738 CARD32 millis) 1739{ 1740 DBG(7, "SetMovingState - %d -> %d center at %d/%d (millis:%u)\n", 1741 priv->moving_state, moving_state, priv->hwState->x, priv->hwState->y, 1742 millis); 1743 1744 priv->moving_state = moving_state; 1745} 1746 1747static int 1748GetTimeOut(SynapticsPrivate * priv) 1749{ 1750 SynapticsParameters *para = &priv->synpara; 1751 1752 switch (priv->tap_state) { 1753 case TS_1: 1754 case TS_3: 1755 case TS_5: 1756 return para->tap_time; 1757 case TS_SINGLETAP: 1758 return para->click_time; 1759 case TS_2A: 1760 return para->single_tap_timeout; 1761 case TS_2B: 1762 return para->tap_time_2; 1763 case TS_4: 1764 return para->locked_drag_time; 1765 default: 1766 return -1; /* No timeout */ 1767 } 1768} 1769 1770static int 1771HandleTapProcessing(SynapticsPrivate * priv, struct SynapticsHwState *hw, 1772 CARD32 now, enum FingerState finger, 1773 Bool inside_active_area) 1774{ 1775 SynapticsParameters *para = &priv->synpara; 1776 Bool touch, release, is_timeout, move, press; 1777 int timeleft, timeout; 1778 enum EdgeType edge; 1779 int delay = 1000000000; 1780 1781 if (priv->finger_state == FS_BLOCKED) 1782 return delay; 1783 1784 touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED; 1785 release = finger == FS_UNTOUCHED && priv->finger_state >= FS_TOUCHED; 1786 move = (finger >= FS_TOUCHED && 1787 (priv->tap_max_fingers <= 1788 ((priv->horiz_scroll_twofinger_on || 1789 priv->vert_scroll_twofinger_on) ? 2 : 1)) && 1790 ((abs(hw->x - priv->touch_on.x) >= para->tap_move) || 1791 (abs(hw->y - priv->touch_on.y) >= para->tap_move))); 1792 press = (hw->left || hw->right || hw->middle); 1793 1794 if (touch) { 1795 priv->touch_on.x = hw->x; 1796 priv->touch_on.y = hw->y; 1797 priv->touch_on.millis = now; 1798 } 1799 else if (release) { 1800 priv->touch_on.millis = now; 1801 } 1802 if (hw->z > para->finger_high) 1803 if (priv->tap_max_fingers < hw->numFingers) 1804 priv->tap_max_fingers = hw->numFingers; 1805 timeout = GetTimeOut(priv); 1806 timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now); 1807 is_timeout = timeleft <= 0; 1808 1809 restart: 1810 switch (priv->tap_state) { 1811 case TS_START: 1812 if (touch) 1813 SetTapState(priv, TS_1, now); 1814 break; 1815 case TS_1: 1816 if (para->clickpad && press) { 1817 SetTapState(priv, TS_CLICKPAD_MOVE, now); 1818 goto restart; 1819 } 1820 if (move) { 1821 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now); 1822 SetTapState(priv, TS_MOVE, now); 1823 goto restart; 1824 } 1825 else if (is_timeout) { 1826 if (finger == FS_TOUCHED) { 1827 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now); 1828 } 1829 SetTapState(priv, TS_MOVE, now); 1830 goto restart; 1831 } 1832 else if (release) { 1833 edge = edge_detection(priv, priv->touch_on.x, priv->touch_on.y); 1834 SelectTapButton(priv, edge); 1835 /* Disable taps outside of the active area */ 1836 if (!inside_active_area) { 1837 priv->tap_button = 0; 1838 } 1839 SetTapState(priv, TS_2A, now); 1840 } 1841 break; 1842 case TS_MOVE: 1843 if (para->clickpad && press) { 1844 SetTapState(priv, TS_CLICKPAD_MOVE, now); 1845 goto restart; 1846 } 1847 if (release) { 1848 SetMovingState(priv, MS_FALSE, now); 1849 SetTapState(priv, TS_START, now); 1850 } 1851 break; 1852 case TS_2A: 1853 if (touch) 1854 SetTapState(priv, TS_3, now); 1855 else if (is_timeout) 1856 SetTapState(priv, TS_SINGLETAP, now); 1857 break; 1858 case TS_2B: 1859 if (touch) { 1860 SetTapState(priv, TS_3, now); 1861 } 1862 else if (is_timeout) { 1863 SetTapState(priv, TS_START, now); 1864 priv->tap_button_state = TBS_BUTTON_DOWN_UP; 1865 } 1866 break; 1867 case TS_SINGLETAP: 1868 if (touch) 1869 SetTapState(priv, TS_1, now); 1870 else if (is_timeout) 1871 SetTapState(priv, TS_START, now); 1872 break; 1873 case TS_3: 1874 if (move) { 1875 if (para->tap_and_drag_gesture) { 1876 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now); 1877 SetTapState(priv, TS_DRAG, now); 1878 } 1879 else { 1880 SetTapState(priv, TS_1, now); 1881 } 1882 goto restart; 1883 } 1884 else if (is_timeout) { 1885 if (para->tap_and_drag_gesture) { 1886 if (finger == FS_TOUCHED) { 1887 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now); 1888 } 1889 SetTapState(priv, TS_DRAG, now); 1890 } 1891 else { 1892 SetTapState(priv, TS_1, now); 1893 } 1894 goto restart; 1895 } 1896 else if (release) { 1897 SetTapState(priv, TS_2B, now); 1898 } 1899 break; 1900 case TS_DRAG: 1901 if (para->clickpad && press) { 1902 SetTapState(priv, TS_CLICKPAD_MOVE, now); 1903 goto restart; 1904 } 1905 if (move) 1906 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now); 1907 if (release) { 1908 SetMovingState(priv, MS_FALSE, now); 1909 if (para->locked_drags) { 1910 SetTapState(priv, TS_4, now); 1911 } 1912 else { 1913 SetTapState(priv, TS_START, now); 1914 } 1915 } 1916 break; 1917 case TS_4: 1918 if (is_timeout) { 1919 SetTapState(priv, TS_START, now); 1920 goto restart; 1921 } 1922 if (touch) 1923 SetTapState(priv, TS_5, now); 1924 break; 1925 case TS_5: 1926 if (is_timeout || move) { 1927 SetTapState(priv, TS_DRAG, now); 1928 goto restart; 1929 } 1930 else if (release) { 1931 SetMovingState(priv, MS_FALSE, now); 1932 SetTapState(priv, TS_START, now); 1933 } 1934 break; 1935 case TS_CLICKPAD_MOVE: 1936 /* Disable scrolling once a button is pressed on a clickpad */ 1937 priv->vert_scroll_edge_on = FALSE; 1938 priv->horiz_scroll_edge_on = FALSE; 1939 priv->vert_scroll_twofinger_on = FALSE; 1940 priv->horiz_scroll_twofinger_on = FALSE; 1941 1942 /* Assume one touch is only for holding the clickpad button down */ 1943 if (hw->numFingers > 1) 1944 hw->numFingers--; 1945 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now); 1946 if (!press) { 1947 SetMovingState(priv, MS_FALSE, now); 1948 SetTapState(priv, TS_MOVE, now); 1949 priv->count_packet_finger = 0; 1950 } 1951 break; 1952 } 1953 1954 timeout = GetTimeOut(priv); 1955 if (timeout >= 0) { 1956 timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now); 1957 delay = clamp(timeleft, 1, delay); 1958 } 1959 return delay; 1960} 1961 1962#define HIST(a) (priv->move_hist[((priv->hist_index - (a) + SYNAPTICS_MOVE_HISTORY) % SYNAPTICS_MOVE_HISTORY)]) 1963#define HIST_DELTA(a, b, e) ((HIST((a)).e) - (HIST((b)).e)) 1964 1965static void 1966store_history(SynapticsPrivate * priv, int x, int y, CARD32 millis) 1967{ 1968 int idx = (priv->hist_index + 1) % SYNAPTICS_MOVE_HISTORY; 1969 1970 priv->move_hist[idx].x = x; 1971 priv->move_hist[idx].y = y; 1972 priv->move_hist[idx].millis = millis; 1973 priv->hist_index = idx; 1974 if (priv->count_packet_finger < SYNAPTICS_MOVE_HISTORY) 1975 priv->count_packet_finger++; 1976} 1977 1978/* 1979 * Estimate the slope for the data sequence [x3, x2, x1, x0] by using 1980 * linear regression to fit a line to the data and use the slope of the 1981 * line. 1982 */ 1983static double 1984estimate_delta(double x0, double x1, double x2, double x3) 1985{ 1986 return x0 * 0.3 + x1 * 0.1 - x2 * 0.1 - x3 * 0.3; 1987} 1988 1989/** 1990 * Applies hysteresis. center is shifted such that it is in range with 1991 * in by the margin again. The new center is returned. 1992 * @param in the current value 1993 * @param center the current center 1994 * @param margin the margin to center in which no change is applied 1995 * @return the new center (which might coincide with the previous) 1996 */ 1997static int 1998hysteresis(int in, int center, int margin) 1999{ 2000 int diff = in - center; 2001 2002 if (abs(diff) <= margin) { 2003 diff = 0; 2004 } 2005 else if (diff > margin) { 2006 diff -= margin; 2007 } 2008 else if (diff < -margin) { 2009 diff += margin; 2010 } 2011 return center + diff; 2012} 2013 2014static void 2015get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw, 2016 enum EdgeType edge, double *dx, double *dy) 2017{ 2018 double dtime = (hw->millis - HIST(0).millis) / 1000.0; 2019 double integral; 2020 double tmpf; 2021 int x_edge_speed = 0; 2022 int y_edge_speed = 0; 2023 2024 *dx = hw->x - HIST(0).x; 2025 *dy = hw->y - HIST(0).y; 2026 2027 /* report edge speed as synthetic motion. Of course, it would be 2028 * cooler to report floats than to buffer, but anyway. */ 2029 2030 /* FIXME: When these values go NaN, bad things happen. Root cause is unknown 2031 * thus far though. */ 2032 if (isnan(priv->frac_x)) 2033 priv->frac_x = 0; 2034 if (isnan(priv->frac_y)) 2035 priv->frac_y = 0; 2036 2037 tmpf = *dx + x_edge_speed * dtime + priv->frac_x; 2038 priv->frac_x = modf(tmpf, &integral); 2039 *dx = integral; 2040 tmpf = *dy + y_edge_speed * dtime + priv->frac_y; 2041 priv->frac_y = modf(tmpf, &integral); 2042 *dy = integral; 2043} 2044 2045/** 2046 * Compute relative motion ('deltas') including edge motion. 2047 */ 2048static int 2049ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw, 2050 enum EdgeType edge, int *dxP, int *dyP, Bool inside_area) 2051{ 2052 enum MovingState moving_state; 2053 double dx, dy; 2054 int delay = 1000000000; 2055 2056 dx = dy = 0; 2057 2058 moving_state = priv->moving_state; 2059 if (moving_state == MS_FALSE) { 2060 switch (priv->tap_state) { 2061 case TS_MOVE: 2062 case TS_DRAG: 2063 moving_state = MS_TOUCHPAD_RELATIVE; 2064 break; 2065 case TS_1: 2066 case TS_3: 2067 case TS_5: 2068 moving_state = MS_TOUCHPAD_RELATIVE; 2069 break; 2070 default: 2071 break; 2072 } 2073 } 2074 2075 if (!inside_area || !moving_state || priv->finger_state == FS_BLOCKED || 2076 priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on || 2077 priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on || 2078 priv->circ_scroll_on || priv->prevFingers != hw->numFingers || 2079 (moving_state == MS_TOUCHPAD_RELATIVE && hw->numFingers != 1)) { 2080 /* reset packet counter. */ 2081 priv->count_packet_finger = 0; 2082 goto out; 2083 } 2084 2085 /* To create the illusion of fluid motion, call back at roughly the report 2086 * rate, even in the absence of new hardware events; see comment above 2087 * POLL_MS declaration. */ 2088 delay = MIN(delay, POLL_MS); 2089 2090 if (priv->count_packet_finger <= 1) 2091 goto out; /* skip the lot */ 2092 2093 if (moving_state == MS_TOUCHPAD_RELATIVE) 2094 get_delta(priv, hw, edge, &dx, &dy); 2095 2096 out: 2097 priv->prevFingers = hw->numFingers; 2098 2099 *dxP = dx; 2100 *dyP = dy; 2101 2102 return delay; 2103} 2104 2105static double 2106estimate_delta_circ(SynapticsPrivate * priv) 2107{ 2108 double a1 = angle(priv, HIST(3).x, HIST(3).y); 2109 double a2 = angle(priv, HIST(2).x, HIST(2).y); 2110 double a3 = angle(priv, HIST(1).x, HIST(1).y); 2111 double a4 = angle(priv, HIST(0).x, HIST(0).y); 2112 double d1 = diffa(a2, a1); 2113 double d2 = d1 + diffa(a3, a2); 2114 double d3 = d2 + diffa(a4, a3); 2115 2116 return estimate_delta(d3, d2, d1, 0); 2117} 2118 2119/* vert and horiz are to know which direction to start coasting 2120 * circ is true if the user had been circular scrolling. 2121 */ 2122static void 2123start_coasting(SynapticsPrivate * priv, struct SynapticsHwState *hw, 2124 Bool vert, Bool horiz, Bool circ) 2125{ 2126 SynapticsParameters *para = &priv->synpara; 2127 2128 priv->scroll.coast_delta_y = 0.0; 2129 priv->scroll.coast_delta_x = 0.0; 2130 2131 if ((priv->scroll.packets_this_scroll > 3) && (para->coasting_speed > 0.0)) { 2132 double pkt_time = HIST_DELTA(0, 3, millis) / 1000.0; 2133 2134 if (vert && !circ) { 2135 double dy = 2136 estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y); 2137 if (pkt_time > 0) { 2138 double scrolls_per_sec = (dy / abs(para->scroll_dist_vert)) / pkt_time; 2139 2140 if (fabs(scrolls_per_sec) >= para->coasting_speed) { 2141 priv->scroll.coast_speed_y = scrolls_per_sec; 2142 priv->scroll.coast_delta_y = (hw->y - priv->scroll.last_y); 2143 } 2144 } 2145 } 2146 if (horiz && !circ) { 2147 double dx = 2148 estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x); 2149 if (pkt_time > 0) { 2150 double scrolls_per_sec = (dx / abs(para->scroll_dist_vert)) / pkt_time; 2151 2152 if (fabs(scrolls_per_sec) >= para->coasting_speed) { 2153 priv->scroll.coast_speed_x = scrolls_per_sec; 2154 priv->scroll.coast_delta_x = (hw->x - priv->scroll.last_x); 2155 } 2156 } 2157 } 2158 if (circ) { 2159 double da = estimate_delta_circ(priv); 2160 2161 if (pkt_time > 0) { 2162 double scrolls_per_sec = (da / para->scroll_dist_circ) / pkt_time; 2163 2164 if (fabs(scrolls_per_sec) >= para->coasting_speed) { 2165 if (vert) { 2166 priv->scroll.coast_speed_y = scrolls_per_sec; 2167 priv->scroll.coast_delta_y = 2168 diffa(priv->scroll.last_a, 2169 angle(priv, hw->x, hw->y)); 2170 } 2171 else if (horiz) { 2172 priv->scroll.coast_speed_x = scrolls_per_sec; 2173 priv->scroll.coast_delta_x = 2174 diffa(priv->scroll.last_a, 2175 angle(priv, hw->x, hw->y)); 2176 } 2177 } 2178 } 2179 } 2180 } 2181 priv->scroll.packets_this_scroll = 0; 2182} 2183 2184static void 2185stop_coasting(SynapticsPrivate * priv) 2186{ 2187 priv->scroll.coast_speed_x = 0; 2188 priv->scroll.coast_speed_y = 0; 2189 priv->scroll.packets_this_scroll = 0; 2190} 2191 2192static int 2193HandleScrolling(SynapticsPrivate * priv, struct SynapticsHwState *hw, 2194 enum EdgeType edge, Bool finger) 2195{ 2196 SynapticsParameters *para = &priv->synpara; 2197 int delay = 1000000000; 2198 2199 if ((priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF) || (priv->finger_state == FS_BLOCKED)) { 2200 stop_coasting(priv); 2201 priv->circ_scroll_on = FALSE; 2202 priv->vert_scroll_edge_on = FALSE; 2203 priv->horiz_scroll_edge_on = FALSE; 2204 priv->vert_scroll_twofinger_on = FALSE; 2205 priv->horiz_scroll_twofinger_on = FALSE; 2206 return delay; 2207 } 2208 2209 /* scroll detection */ 2210 if (finger && priv->finger_state == FS_UNTOUCHED) { 2211 stop_coasting(priv); 2212 priv->scroll.delta_y = 0; 2213 priv->scroll.delta_x = 0; 2214 if (para->circular_scrolling) { 2215 if ((para->circular_trigger == 0 && edge) || 2216 (para->circular_trigger == 1 && edge & TOP_EDGE) || 2217 (para->circular_trigger == 2 && edge & TOP_EDGE && 2218 edge & RIGHT_EDGE) || (para->circular_trigger == 3 && 2219 edge & RIGHT_EDGE) || 2220 (para->circular_trigger == 4 && edge & RIGHT_EDGE && 2221 edge & BOTTOM_EDGE) || (para->circular_trigger == 5 && 2222 edge & BOTTOM_EDGE) || 2223 (para->circular_trigger == 6 && edge & BOTTOM_EDGE && 2224 edge & LEFT_EDGE) || (para->circular_trigger == 7 && 2225 edge & LEFT_EDGE) || 2226 (para->circular_trigger == 8 && edge & LEFT_EDGE && 2227 edge & TOP_EDGE)) { 2228 priv->circ_scroll_on = TRUE; 2229 priv->circ_scroll_vert = TRUE; 2230 priv->scroll.last_a = angle(priv, hw->x, hw->y); 2231 DBG(7, "circular scroll detected on edge\n"); 2232 } 2233 } 2234 } 2235 if (!priv->circ_scroll_on) { 2236 if (finger) { 2237 if (hw->numFingers == 2) { 2238 if (!priv->vert_scroll_twofinger_on && 2239 (para->scroll_twofinger_vert) && 2240 (para->scroll_dist_vert != 0)) { 2241 stop_coasting(priv); 2242 priv->vert_scroll_twofinger_on = TRUE; 2243 priv->vert_scroll_edge_on = FALSE; 2244 priv->scroll.last_y = hw->y; 2245 DBG(7, "vert two-finger scroll detected\n"); 2246 } 2247 if (!priv->horiz_scroll_twofinger_on && 2248 (para->scroll_twofinger_horiz) && 2249 (para->scroll_dist_horiz != 0)) { 2250 stop_coasting(priv); 2251 priv->horiz_scroll_twofinger_on = TRUE; 2252 priv->horiz_scroll_edge_on = FALSE; 2253 priv->scroll.last_x = hw->x; 2254 DBG(7, "horiz two-finger scroll detected\n"); 2255 } 2256 } 2257 } 2258 if (finger && priv->finger_state == FS_UNTOUCHED) { 2259 if (!priv->vert_scroll_twofinger_on && 2260 !priv->horiz_scroll_twofinger_on) { 2261 if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) && 2262 (edge & RIGHT_EDGE)) { 2263 priv->vert_scroll_edge_on = TRUE; 2264 priv->scroll.last_y = hw->y; 2265 DBG(7, "vert edge scroll detected on right edge\n"); 2266 } 2267 if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0) 2268 && (edge & BOTTOM_EDGE)) { 2269 priv->horiz_scroll_edge_on = TRUE; 2270 priv->scroll.last_x = hw->x; 2271 DBG(7, "horiz edge scroll detected on bottom edge\n"); 2272 } 2273 } 2274 } 2275 } 2276 { 2277 Bool oldv = priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on 2278 || (priv->circ_scroll_on && priv->circ_scroll_vert); 2279 2280 Bool oldh = priv->horiz_scroll_twofinger_on || 2281 priv->horiz_scroll_edge_on || (priv->circ_scroll_on && 2282 !priv->circ_scroll_vert); 2283 2284 Bool oldc = priv->circ_scroll_on; 2285 2286 if (priv->circ_scroll_on && !finger) { 2287 /* circular scroll locks in until finger is raised */ 2288 DBG(7, "cicular scroll off\n"); 2289 priv->circ_scroll_on = FALSE; 2290 } 2291 2292 if (!finger || hw->numFingers != 2) { 2293 if (priv->vert_scroll_twofinger_on) { 2294 DBG(7, "vert two-finger scroll off\n"); 2295 priv->vert_scroll_twofinger_on = FALSE; 2296 } 2297 if (priv->horiz_scroll_twofinger_on) { 2298 DBG(7, "horiz two-finger scroll off\n"); 2299 priv->horiz_scroll_twofinger_on = FALSE; 2300 } 2301 } 2302 2303 if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) { 2304 DBG(7, "vert edge scroll off\n"); 2305 priv->vert_scroll_edge_on = FALSE; 2306 } 2307 if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) { 2308 DBG(7, "horiz edge scroll off\n"); 2309 priv->horiz_scroll_edge_on = FALSE; 2310 } 2311 /* If we were corner edge scrolling (coasting), 2312 * but no longer in corner or raised a finger, then stop coasting. */ 2313 if (para->scroll_edge_corner && 2314 (priv->scroll.coast_speed_x || priv->scroll.coast_speed_y)) { 2315 Bool is_in_corner = ((edge & RIGHT_EDGE) && 2316 (edge & (TOP_EDGE | BOTTOM_EDGE))) || 2317 ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))); 2318 if (!is_in_corner || !finger) { 2319 DBG(7, "corner edge scroll off\n"); 2320 stop_coasting(priv); 2321 } 2322 } 2323 /* if we were scrolling, but couldn't corner edge scroll, 2324 * and are no longer scrolling, then start coasting */ 2325 oldv = oldv && !(priv->vert_scroll_twofinger_on || 2326 priv->vert_scroll_edge_on || (priv->circ_scroll_on && 2327 priv->circ_scroll_vert)); 2328 2329 oldh = oldh && !(priv->horiz_scroll_twofinger_on || 2330 priv->horiz_scroll_edge_on || (priv->circ_scroll_on && 2331 !priv-> 2332 circ_scroll_vert)); 2333 2334 oldc = oldc && !priv->circ_scroll_on; 2335 2336 if ((oldv || oldh) && !para->scroll_edge_corner) { 2337 start_coasting(priv, hw, oldv, oldh, oldc); 2338 } 2339 } 2340 2341 /* if hitting a corner (top right or bottom right) while vertical 2342 * scrolling is active, consider starting corner edge scrolling or 2343 * switching over to circular scrolling smoothly */ 2344 if (priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on && 2345 (edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) { 2346 if (para->scroll_edge_corner) { 2347 if (priv->scroll.coast_speed_y == 0) { 2348 /* FYI: We can generate multiple start_coasting requests if 2349 * we're in the corner, but we were moving so slowly when we 2350 * got here that we didn't actually start coasting. */ 2351 DBG(7, "corner edge scroll on\n"); 2352 start_coasting(priv, hw, TRUE, FALSE, FALSE); 2353 } 2354 } 2355 else if (para->circular_scrolling) { 2356 priv->vert_scroll_edge_on = FALSE; 2357 priv->circ_scroll_on = TRUE; 2358 priv->circ_scroll_vert = TRUE; 2359 priv->scroll.last_a = angle(priv, hw->x, hw->y); 2360 DBG(7, "switching to circular scrolling\n"); 2361 } 2362 } 2363 /* Same treatment for horizontal scrolling */ 2364 if (priv->horiz_scroll_edge_on && !priv->vert_scroll_edge_on && 2365 (edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) { 2366 if (para->scroll_edge_corner) { 2367 if (priv->scroll.coast_speed_x == 0) { 2368 /* FYI: We can generate multiple start_coasting requests if 2369 * we're in the corner, but we were moving so slowly when we 2370 * got here that we didn't actually start coasting. */ 2371 DBG(7, "corner edge scroll on\n"); 2372 start_coasting(priv, hw, FALSE, TRUE, FALSE); 2373 } 2374 } 2375 else if (para->circular_scrolling) { 2376 priv->horiz_scroll_edge_on = FALSE; 2377 priv->circ_scroll_on = TRUE; 2378 priv->circ_scroll_vert = FALSE; 2379 priv->scroll.last_a = angle(priv, hw->x, hw->y); 2380 DBG(7, "switching to circular scrolling\n"); 2381 } 2382 } 2383 2384 if (priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on || 2385 priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on || 2386 priv->circ_scroll_on) { 2387 priv->scroll.packets_this_scroll++; 2388 } 2389 2390 if (priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on) { 2391 /* + = down, - = up */ 2392 if (para->scroll_dist_vert != 0 && hw->y != priv->scroll.last_y) { 2393 priv->scroll.delta_y += (hw->y - priv->scroll.last_y); 2394 priv->scroll.last_y = hw->y; 2395 } 2396 } 2397 if (priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on) { 2398 /* + = right, - = left */ 2399 if (para->scroll_dist_horiz != 0 && hw->x != priv->scroll.last_x) { 2400 priv->scroll.delta_x += (hw->x - priv->scroll.last_x); 2401 priv->scroll.last_x = hw->x; 2402 } 2403 } 2404 if (priv->circ_scroll_on) { 2405 /* + = counter clockwise, - = clockwise */ 2406 double delta = para->scroll_dist_circ; 2407 double diff = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y)); 2408 2409 if (delta >= 0.005 && diff != 0.0) { 2410 if (priv->circ_scroll_vert) 2411 priv->scroll.delta_y -= diff / delta * para->scroll_dist_vert; 2412 else 2413 priv->scroll.delta_x -= diff / delta * para->scroll_dist_horiz; 2414 priv->scroll.last_a = angle(priv, hw->x, hw->y); 2415 } 2416 } 2417 2418 if (priv->scroll.coast_speed_y) { 2419 double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0; 2420 double ddy = para->coasting_friction * dtime; 2421 2422 priv->scroll.delta_y += priv->scroll.coast_speed_y * dtime * abs(para->scroll_dist_vert); 2423 delay = MIN(delay, POLL_MS); 2424 if (abs(priv->scroll.coast_speed_y) < ddy) { 2425 priv->scroll.coast_speed_y = 0; 2426 priv->scroll.packets_this_scroll = 0; 2427 } 2428 else { 2429 priv->scroll.coast_speed_y += 2430 (priv->scroll.coast_speed_y < 0 ? ddy : -ddy); 2431 } 2432 } 2433 2434 if (priv->scroll.coast_speed_x) { 2435 double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0; 2436 double ddx = para->coasting_friction * dtime; 2437 priv->scroll.delta_x += priv->scroll.coast_speed_x * dtime * abs(para->scroll_dist_horiz); 2438 delay = MIN(delay, POLL_MS); 2439 if (abs(priv->scroll.coast_speed_x) < ddx) { 2440 priv->scroll.coast_speed_x = 0; 2441 priv->scroll.packets_this_scroll = 0; 2442 } 2443 else { 2444 priv->scroll.coast_speed_x += 2445 (priv->scroll.coast_speed_x < 0 ? ddx : -ddx); 2446 } 2447 } 2448 2449 return delay; 2450} 2451 2452/** 2453 * Check if any 2+ fingers are close enough together to assume this is a 2454 * ClickFinger action. 2455 */ 2456static int 2457clickpad_guess_clickfingers(SynapticsPrivate * priv, 2458 struct SynapticsHwState *hw) 2459{ 2460 int nfingers = 0; 2461 uint32_t close_point = 0; /* 1 bit for each point close to another one */ 2462 int i, j; 2463 2464 BUG_RETURN_VAL(hw->num_mt_mask > sizeof(close_point) * 8, 0); 2465 2466 for (i = 0; i < hw->num_mt_mask - 1; i++) { 2467 ValuatorMask *f1; 2468 2469 if (hw->slot_state[i] == SLOTSTATE_EMPTY || 2470 hw->slot_state[i] == SLOTSTATE_CLOSE) 2471 continue; 2472 2473 f1 = hw->mt_mask[i]; 2474 2475 for (j = i + 1; j < hw->num_mt_mask; j++) { 2476 ValuatorMask *f2; 2477 double x1, x2, y1, y2; 2478 2479 if (hw->slot_state[j] == SLOTSTATE_EMPTY || 2480 hw->slot_state[j] == SLOTSTATE_CLOSE) 2481 continue; 2482 2483 f2 = hw->mt_mask[j]; 2484 2485 x1 = valuator_mask_get_double(f1, 0); 2486 y1 = valuator_mask_get_double(f1, 1); 2487 2488 x2 = valuator_mask_get_double(f2, 0); 2489 y2 = valuator_mask_get_double(f2, 1); 2490 2491 /* FIXME: fingers closer together than 30% of touchpad width, but 2492 * really, this should be dependent on the touchpad size. Also, 2493 * you'll need to find a touchpad that doesn't lie about it's 2494 * size. Good luck. */ 2495 if (abs(x1 - x2) < (priv->maxx - priv->minx) * .3 && 2496 abs(y1 - y2) < (priv->maxy - priv->miny) * .3) { 2497 close_point |= (1 << j); 2498 close_point |= (1 << i); 2499 } 2500 } 2501 } 2502 2503 while (close_point > 0) { 2504 nfingers += close_point & 0x1; 2505 close_point >>= 1; 2506 } 2507 2508 return nfingers; 2509} 2510 2511static void 2512handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw) 2513{ 2514 SynapticsParameters *para = &priv->synpara; 2515 int action = 0; 2516 int nfingers = hw->numFingers; 2517 2518 /* if this is a clickpad, clickfinger handling is: 2519 * one finger down: no action, this is a normal click 2520 * two fingers down: F2_CLICK 2521 * three fingers down: F3_CLICK 2522 */ 2523 2524 if (para->clickpad) 2525 nfingers = clickpad_guess_clickfingers(priv, hw); 2526 2527 switch (nfingers) { 2528 case 1: 2529 action = para->click_action[F1_CLICK1]; 2530 break; 2531 case 2: 2532 action = para->click_action[F2_CLICK1]; 2533 break; 2534 case 3: 2535 action = para->click_action[F3_CLICK1]; 2536 break; 2537 } 2538 switch (action) { 2539 case 1: 2540 hw->left = 1 | BTN_EMULATED_FLAG; 2541 break; 2542 case 2: 2543 hw->left = 0; 2544 hw->middle = 1 | BTN_EMULATED_FLAG; 2545 break; 2546 case 3: 2547 hw->left = 0; 2548 hw->right = 1 | BTN_EMULATED_FLAG; 2549 break; 2550 } 2551} 2552 2553static void 2554update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw, 2555 struct SynapticsHwState *old, CARD32 now, int *delay) 2556{ 2557 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 2558 SynapticsParameters *para = &priv->synpara; 2559 2560 /* Treat the first two multi buttons as up/down for now. */ 2561 hw->up |= hw->multi[0]; 2562 hw->down |= hw->multi[1]; 2563 2564 /* 3rd button emulation */ 2565 hw->middle |= HandleMidButtonEmulation(priv, hw, now, delay); 2566 2567 /* If this is a clickpad and the user clicks in a soft button area, press 2568 * the soft button instead. */ 2569 if (para->clickpad) { 2570 /* hw->left is down, but no other buttons were already down */ 2571 if (!old->left && !old->right && !old->middle && 2572 hw->left && !hw->right && !hw->middle) { 2573 if (is_inside_rightbutton_area(para, hw->x, hw->y)) { 2574 hw->left = 0; 2575 hw->right = 1; 2576 } 2577 else if (is_inside_middlebutton_area(para, hw->x, hw->y)) { 2578 hw->left = 0; 2579 hw->middle = 1; 2580 } 2581 } 2582 else if (hw->left) { 2583 hw->left = old->left; 2584 hw->right = old->right; 2585 hw->middle = old->middle; 2586 } 2587 } 2588 2589 /* Fingers emulate other buttons. ClickFinger can only be 2590 triggered on transition, when left is pressed 2591 */ 2592 if (hw->left && !old->left && !old->middle && !old->right && 2593 hw->numFingers >= 1) { 2594 handle_clickfinger(priv, hw); 2595 } 2596 2597 /* Two finger emulation */ 2598 if (hw->numFingers == 1 && hw->z >= para->emulate_twofinger_z && 2599 hw->fingerWidth >= para->emulate_twofinger_w) { 2600 hw->numFingers = 2; 2601 } 2602} 2603 2604static void 2605post_button_click(const InputInfoPtr pInfo, const int button) 2606{ 2607 xf86PostButtonEvent(pInfo->dev, FALSE, button, TRUE, 0, 0); 2608 xf86PostButtonEvent(pInfo->dev, FALSE, button, FALSE, 0, 0); 2609} 2610 2611static void 2612post_scroll_events(const InputInfoPtr pInfo) 2613{ 2614 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 2615 2616 valuator_mask_zero(priv->scroll_events_mask); 2617 2618 if (priv->scroll.delta_y != 0.0) { 2619 valuator_mask_set_double(priv->scroll_events_mask, 2620 priv->scroll_axis_vert, priv->scroll.delta_y); 2621 priv->scroll.delta_y = 0; 2622 } 2623 if (priv->scroll.delta_x != 0.0) { 2624 valuator_mask_set_double(priv->scroll_events_mask, 2625 priv->scroll_axis_horiz, priv->scroll.delta_x); 2626 priv->scroll.delta_x = 0; 2627 } 2628 if (valuator_mask_num_valuators(priv->scroll_events_mask)) 2629 xf86PostMotionEventM(pInfo->dev, FALSE, priv->scroll_events_mask); 2630} 2631 2632/* Update the open slots and number of active touches */ 2633static void 2634UpdateTouchState(InputInfoPtr pInfo, struct SynapticsHwState *hw) 2635{ 2636 SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; 2637 int i; 2638 2639 for (i = 0; i < hw->num_mt_mask; i++) { 2640 if (hw->slot_state[i] == SLOTSTATE_OPEN) { 2641 priv->open_slots[priv->num_active_touches] = i; 2642 priv->num_active_touches++; 2643 BUG_WARN(priv->num_active_touches > priv->num_slots); 2644 } 2645 else if (hw->slot_state[i] == SLOTSTATE_CLOSE) { 2646 Bool found = FALSE; 2647 int j; 2648 2649 for (j = 0; j < priv->num_active_touches - 1; j++) { 2650 if (priv->open_slots[j] == i) 2651 found = TRUE; 2652 2653 if (found) 2654 priv->open_slots[j] = priv->open_slots[j + 1]; 2655 } 2656 2657 BUG_WARN(priv->num_active_touches == 0); 2658 if (priv->num_active_touches > 0) 2659 priv->num_active_touches--; 2660 } 2661 } 2662 2663 SynapticsResetTouchHwState(hw, FALSE); 2664} 2665 2666static void 2667HandleTouches(InputInfoPtr pInfo, struct SynapticsHwState *hw) 2668{ 2669 SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; 2670 SynapticsParameters *para = &priv->synpara; 2671 int new_active_touches = priv->num_active_touches; 2672 int min_touches = 2; 2673 Bool restart_touches = FALSE; 2674 int i; 2675 2676 if (para->click_action[F3_CLICK1] || para->tap_action[F3_TAP]) 2677 min_touches = 4; 2678 else if (para->click_action[F2_CLICK1] || para->tap_action[F2_TAP] || 2679 para->scroll_twofinger_vert || para->scroll_twofinger_horiz) 2680 min_touches = 3; 2681 2682 /* Count new number of active touches */ 2683 for (i = 0; i < hw->num_mt_mask; i++) { 2684 if (hw->slot_state[i] == SLOTSTATE_OPEN) 2685 new_active_touches++; 2686 else if (hw->slot_state[i] == SLOTSTATE_CLOSE) 2687 new_active_touches--; 2688 } 2689 2690 if (priv->has_semi_mt) 2691 goto out; 2692 2693 if (priv->num_active_touches < min_touches && 2694 new_active_touches < min_touches) { 2695 /* We stayed below number of touches needed to send events */ 2696 goto out; 2697 } 2698 else if (priv->num_active_touches >= min_touches && 2699 new_active_touches < min_touches) { 2700 /* We are transitioning to less than the number of touches needed to 2701 * send events. End all currently open touches. */ 2702 for (i = 0; i < priv->num_active_touches; i++) { 2703 int slot = priv->open_slots[i]; 2704 2705 xf86PostTouchEvent(pInfo->dev, slot, XI_TouchEnd, 0, 2706 hw->mt_mask[slot]); 2707 } 2708 2709 /* Don't send any more events */ 2710 goto out; 2711 } 2712 else if (priv->num_active_touches < min_touches && 2713 new_active_touches >= min_touches) { 2714 /* We are transitioning to more than the number of touches needed to 2715 * send events. Begin all already open touches. */ 2716 restart_touches = TRUE; 2717 for (i = 0; i < priv->num_active_touches; i++) { 2718 int slot = priv->open_slots[i]; 2719 2720 xf86PostTouchEvent(pInfo->dev, slot, XI_TouchBegin, 0, 2721 hw->mt_mask[slot]); 2722 } 2723 } 2724 2725 /* Send touch begin events for all new touches */ 2726 for (i = 0; i < hw->num_mt_mask; i++) 2727 if (hw->slot_state[i] == SLOTSTATE_OPEN) 2728 xf86PostTouchEvent(pInfo->dev, i, XI_TouchBegin, 0, hw->mt_mask[i]); 2729 2730 /* Send touch update/end events for all the rest */ 2731 for (i = 0; i < priv->num_active_touches; i++) { 2732 int slot = priv->open_slots[i]; 2733 2734 /* Don't send update event if we just reopened the touch above */ 2735 if (hw->slot_state[slot] == SLOTSTATE_UPDATE && !restart_touches) 2736 xf86PostTouchEvent(pInfo->dev, slot, XI_TouchUpdate, 0, 2737 hw->mt_mask[slot]); 2738 else if (hw->slot_state[slot] == SLOTSTATE_CLOSE) 2739 xf86PostTouchEvent(pInfo->dev, slot, XI_TouchEnd, 0, 2740 hw->mt_mask[slot]); 2741 } 2742 2743 out: 2744 UpdateTouchState(pInfo, hw); 2745} 2746 2747static void 2748filter_jitter(SynapticsPrivate * priv, int *x, int *y) 2749{ 2750 SynapticsParameters *para = &priv->synpara; 2751 2752 priv->hyst_center_x = hysteresis(*x, priv->hyst_center_x, para->hyst_x); 2753 priv->hyst_center_y = hysteresis(*y, priv->hyst_center_y, para->hyst_y); 2754 *x = priv->hyst_center_x; 2755 *y = priv->hyst_center_y; 2756} 2757 2758static void 2759reset_hw_state(struct SynapticsHwState *hw) 2760{ 2761 hw->x = 0; 2762 hw->y = 0; 2763 hw->z = 0; 2764 hw->numFingers = 0; 2765 hw->fingerWidth = 0; 2766} 2767 2768/* 2769 * React on changes in the hardware state. This function is called every time 2770 * the hardware state changes. The return value is used to specify how many 2771 * milliseconds to wait before calling the function again if no state change 2772 * occurs. 2773 * 2774 * from_timer denotes if HandleState was triggered from a timer (e.g. to 2775 * generate fake motion events, or for the tap-to-click state machine), rather 2776 * than from having received a motion event. 2777 */ 2778static int 2779HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, 2780 Bool from_timer) 2781{ 2782 SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private); 2783 SynapticsParameters *para = &priv->synpara; 2784 enum FingerState finger = FS_UNTOUCHED; 2785 int dx = 0, dy = 0, buttons, id; 2786 enum EdgeType edge = NO_EDGE; 2787 int change; 2788 int double_click = FALSE; 2789 int delay = 1000000000; 2790 int timeleft; 2791 Bool inside_active_area; 2792 2793 /* If touchpad is switched off, we skip the whole thing and return delay */ 2794 if (para->touchpad_off == TOUCHPAD_OFF) { 2795 UpdateTouchState(pInfo, hw); 2796 return delay; 2797 } 2798 2799 /* We need both and x/y, the driver can't handle just one of the two 2800 * yet. But since it's possible to hit a phys button on non-clickpads 2801 * without ever getting motion data first, we must continue with 0/0 for 2802 * that case. */ 2803 if (hw->x == INT_MIN || hw->y == INT_MAX) { 2804 if (para->clickpad) 2805 return delay; 2806 else if (hw->left || hw->right || hw->middle) { 2807 hw->x = (hw->x == INT_MIN) ? 0 : hw->x; 2808 hw->y = (hw->y == INT_MIN) ? 0 : hw->y; 2809 } 2810 } 2811 2812 /* If a physical button is pressed on a clickpad, use cumulative relative 2813 * touch movements for motion */ 2814 if (para->clickpad && (hw->left || hw->right || hw->middle)) { 2815 hw->x = hw->cumulative_dx; 2816 hw->y = hw->cumulative_dy; 2817 } 2818 2819 /* apply hysteresis before doing anything serious. This cancels 2820 * out a lot of noise which might surface in strange phenomena 2821 * like flicker in scrolling or noise motion. */ 2822 filter_jitter(priv, &hw->x, &hw->y); 2823 2824 inside_active_area = is_inside_active_area(priv, hw->x, hw->y); 2825 2826 /* these two just update hw->left, right, etc. */ 2827 update_hw_button_state(pInfo, hw, priv->old_hw_state, now, &delay); 2828 2829 /* now we know that these _coordinates_ aren't in the area. 2830 invalid are: x, y, z, numFingers, fingerWidth 2831 valid are: millis, left/right/middle/up/down/etc. 2832 */ 2833 if (!inside_active_area) { 2834 reset_hw_state(hw); 2835 2836 /* FIXME: if finger accidentally moves into the area and doesn't 2837 * really release, the finger should remain down. */ 2838 } 2839 2840 /* no edge or finger detection outside of area */ 2841 if (inside_active_area) { 2842 edge = edge_detection(priv, hw->x, hw->y); 2843 if (!from_timer) 2844 finger = SynapticsDetectFinger(priv, hw); 2845 else 2846 finger = priv->finger_state; 2847 } 2848 2849 /* tap and drag detection. Needs to be performed even if the finger is in 2850 * the dead area to reset the state. */ 2851 timeleft = HandleTapProcessing(priv, hw, now, finger, inside_active_area); 2852 if (timeleft > 0) 2853 delay = MIN(delay, timeleft); 2854 2855 if (inside_active_area) { 2856 /* Don't bother about scrolling in the dead area of the touchpad. */ 2857 timeleft = HandleScrolling(priv, hw, edge, (finger >= FS_TOUCHED)); 2858 if (timeleft > 0) 2859 delay = MIN(delay, timeleft); 2860 2861 /* 2862 * Compensate for unequal x/y resolution. This needs to be done after 2863 * calculations that require unadjusted coordinates, for example edge 2864 * detection. 2865 */ 2866 ScaleCoordinates(priv, hw); 2867 } 2868 2869 dx = dy = 0; 2870 2871 timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy, inside_active_area); 2872 delay = MIN(delay, timeleft); 2873 2874 buttons = ((hw->left ? 0x01 : 0) | 2875 (hw->middle ? 0x02 : 0) | 2876 (hw->right ? 0x04 : 0) | 2877 (hw->up ? 0x08 : 0) | 2878 (hw->down ? 0x10 : 0) | 2879 (hw->multi[2] ? 0x20 : 0) | (hw->multi[3] ? 0x40 : 0)); 2880 2881 if (priv->tap_button > 0) { 2882 int tap_mask = 1 << (priv->tap_button - 1); 2883 2884 if (priv->tap_button_state == TBS_BUTTON_DOWN_UP) { 2885 if (tap_mask != (priv->lastButtons & tap_mask)) { 2886 xf86PostButtonEvent(pInfo->dev, FALSE, priv->tap_button, TRUE, 2887 0, 0); 2888 priv->lastButtons |= tap_mask; 2889 } 2890 priv->tap_button_state = TBS_BUTTON_UP; 2891 } 2892 if (priv->tap_button_state == TBS_BUTTON_DOWN) 2893 buttons |= tap_mask; 2894 } 2895 2896 /* Post events */ 2897 if (finger >= FS_TOUCHED && (dx || dy)) 2898 xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy); 2899 2900 if (priv->mid_emu_state == MBE_LEFT_CLICK) { 2901 post_button_click(pInfo, 1); 2902 priv->mid_emu_state = MBE_OFF; 2903 } 2904 else if (priv->mid_emu_state == MBE_RIGHT_CLICK) { 2905 post_button_click(pInfo, 3); 2906 priv->mid_emu_state = MBE_OFF; 2907 } 2908 2909 change = buttons ^ priv->lastButtons; 2910 while (change) { 2911 id = ffs(change); /* number of first set bit 1..32 is returned */ 2912 change &= ~(1 << (id - 1)); 2913 xf86PostButtonEvent(pInfo->dev, FALSE, id, (buttons & (1 << (id - 1))), 2914 0, 0); 2915 } 2916 2917 /* Process scroll events only if coordinates are 2918 * in the Synaptics Area 2919 */ 2920 if (inside_active_area && 2921 (priv->scroll.delta_x != 0.0 || priv->scroll.delta_y != 0.0)) { 2922 post_scroll_events(pInfo); 2923 priv->scroll.last_millis = hw->millis; 2924 } 2925 2926 if (double_click) { 2927 post_button_click(pInfo, 1); 2928 post_button_click(pInfo, 1); 2929 } 2930 2931 HandleTouches(pInfo, hw); 2932 2933 /* Save old values of some state variables */ 2934 priv->finger_state = finger; 2935 priv->lastButtons = buttons; 2936 2937 /* generate a history of the absolute positions */ 2938 if (inside_active_area) 2939 store_history(priv, hw->x, hw->y, hw->millis); 2940 2941 /* Save logical state for transition comparisons */ 2942 SynapticsCopyHwState(priv->old_hw_state, hw); 2943 2944 return delay; 2945} 2946 2947static int 2948ControlProc(InputInfoPtr pInfo, xDeviceCtl * control) 2949{ 2950 DBG(3, "Control Proc called\n"); 2951 return Success; 2952} 2953 2954static int 2955SwitchMode(ClientPtr client, DeviceIntPtr dev, int mode) 2956{ 2957 DBG(3, "SwitchMode called\n"); 2958 2959 return XI_BadMode; 2960} 2961 2962static void 2963ReadDevDimensions(InputInfoPtr pInfo) 2964{ 2965 SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; 2966 2967 if (priv->proto_ops->ReadDevDimensions) 2968 priv->proto_ops->ReadDevDimensions(pInfo); 2969 2970 SanitizeDimensions(pInfo); 2971} 2972 2973static Bool 2974QueryHardware(InputInfoPtr pInfo) 2975{ 2976 SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private; 2977 2978 priv->comm.protoBufTail = 0; 2979 2980 if (!priv->proto_ops->QueryHardware(pInfo)) { 2981 xf86IDrvMsg(pInfo, X_PROBED, "no supported touchpad found\n"); 2982 if (priv->proto_ops->DeviceOffHook) 2983 priv->proto_ops->DeviceOffHook(pInfo); 2984 return FALSE; 2985 } 2986 2987 return TRUE; 2988} 2989 2990static void 2991ScaleCoordinates(SynapticsPrivate * priv, struct SynapticsHwState *hw) 2992{ 2993 int xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2; 2994 int yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2; 2995 2996 hw->x = (hw->x - xCenter) * priv->horiz_coeff + xCenter; 2997 hw->y = (hw->y - yCenter) * priv->vert_coeff + yCenter; 2998} 2999 3000void 3001CalculateScalingCoeffs(SynapticsPrivate * priv) 3002{ 3003 int vertRes = priv->synpara.resolution_vert; 3004 int horizRes = priv->synpara.resolution_horiz; 3005 3006 if ((horizRes > vertRes) && (horizRes > 0)) { 3007 priv->horiz_coeff = vertRes / (double) horizRes; 3008 priv->vert_coeff = 1; 3009 } 3010 else if ((horizRes < vertRes) && (vertRes > 0)) { 3011 priv->horiz_coeff = 1; 3012 priv->vert_coeff = horizRes / (double) vertRes; 3013 } 3014 else { 3015 priv->horiz_coeff = 1; 3016 priv->vert_coeff = 1; 3017 } 3018} 3019