1 /* $NetBSD: synaptics.c,v 1.36 2017/12/05 18:04:21 jmcneill Exp $ */ 2 3 /* 4 * Copyright (c) 2005, Steve C. Woodford 5 * Copyright (c) 2004, Ales Krenek 6 * Copyright (c) 2004, Kentaro A. Kurahone 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided 18 * with the distribution. 19 * * Neither the name of the authors nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 * 36 */ 37 38 /* 39 * TODO: 40 * - Make the sysctl values per-instance instead of global. 41 * - Consider setting initial scaling factors at runtime according 42 * to the values returned by the 'Read Resolutions' command. 43 * - Support the serial protocol (we only support PS/2 for now) 44 * - Support auto-repeat for up/down button Z-axis emulation. 45 * - Maybe add some more gestures (can we use Palm support somehow?) 46 */ 47 48 #include "opt_pms.h" 49 50 #include <sys/cdefs.h> 51 __KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.36 2017/12/05 18:04:21 jmcneill Exp $"); 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/device.h> 56 #include <sys/ioctl.h> 57 #include <sys/sysctl.h> 58 #include <sys/kernel.h> 59 #include <sys/proc.h> 60 61 #include <sys/bus.h> 62 63 #include <dev/pckbport/pckbportvar.h> 64 65 #include <dev/pckbport/synapticsreg.h> 66 #include <dev/pckbport/synapticsvar.h> 67 68 #include <dev/pckbport/pmsreg.h> 69 #include <dev/pckbport/pmsvar.h> 70 71 #include <dev/wscons/wsconsio.h> 72 #include <dev/wscons/wsmousevar.h> 73 74 /* 75 * Absolute-mode packets are decoded and passed around using 76 * the following structure. 77 */ 78 struct synaptics_packet { 79 signed short sp_x; /* Unscaled absolute X/Y coordinates */ 80 signed short sp_y; 81 u_char sp_z; /* Z (pressure) */ 82 u_char sp_w; /* W (contact patch width) */ 83 signed short sp_sx; /* Secondary finger unscaled absolute */ 84 /* X/Y coordinates */ 85 signed short sp_xy; 86 u_char sp_finger; /* 0 for primary, 1 for secondary */ 87 char sp_left; /* Left mouse button status */ 88 char sp_right; /* Right mouse button status */ 89 char sp_middle; /* Middle button status (possibly emulated) */ 90 char sp_up; /* Up button status */ 91 char sp_down; /* Down button status */ 92 }; 93 94 static void pms_synaptics_input(void *, int); 95 static void pms_synaptics_process_packet(struct pms_softc *, 96 struct synaptics_packet *); 97 static void pms_sysctl_synaptics(struct sysctllog **); 98 static int pms_sysctl_synaptics_verify(SYSCTLFN_ARGS); 99 100 /* Controlled by sysctl. */ 101 static int synaptics_up_down_emul = 2; 102 static int synaptics_up_down_motion_delta = 1; 103 static int synaptics_gesture_move = 200; 104 static int synaptics_gesture_length = 20; 105 static int synaptics_edge_left = SYNAPTICS_EDGE_LEFT; 106 static int synaptics_edge_right = SYNAPTICS_EDGE_RIGHT; 107 static int synaptics_edge_top = SYNAPTICS_EDGE_TOP; 108 static int synaptics_edge_bottom = SYNAPTICS_EDGE_BOTTOM; 109 static int synaptics_edge_motion_delta = 32; 110 static u_int synaptics_finger_high = SYNAPTICS_FINGER_LIGHT + 5; 111 static u_int synaptics_finger_low = SYNAPTICS_FINGER_LIGHT - 10; 112 static int synaptics_button_boundary = SYNAPTICS_EDGE_BOTTOM + 720; 113 static int synaptics_button2 = SYNAPTICS_EDGE_LEFT + (SYNAPTICS_EDGE_RIGHT - SYNAPTICS_EDGE_LEFT) / 3; 114 static int synaptics_button3 = SYNAPTICS_EDGE_LEFT + 2 * (SYNAPTICS_EDGE_RIGHT - SYNAPTICS_EDGE_LEFT) / 3; 115 static int synaptics_two_fingers_emul = 0; 116 static int synaptics_scale_x = 16; 117 static int synaptics_scale_y = 16; 118 static int synaptics_max_speed_x = 32; 119 static int synaptics_max_speed_y = 32; 120 static int synaptics_movement_threshold = 4; 121 static int synaptics_movement_enable = 1; 122 123 /* Sysctl nodes. */ 124 static int synaptics_button_boundary_nodenum; 125 static int synaptics_button2_nodenum; 126 static int synaptics_button3_nodenum; 127 static int synaptics_up_down_emul_nodenum; 128 static int synaptics_up_down_motion_delta_nodenum; 129 static int synaptics_gesture_move_nodenum; 130 static int synaptics_gesture_length_nodenum; 131 static int synaptics_edge_left_nodenum; 132 static int synaptics_edge_right_nodenum; 133 static int synaptics_edge_top_nodenum; 134 static int synaptics_edge_bottom_nodenum; 135 static int synaptics_edge_motion_delta_nodenum; 136 static int synaptics_finger_high_nodenum; 137 static int synaptics_finger_low_nodenum; 138 static int synaptics_two_fingers_emul_nodenum; 139 static int synaptics_scale_x_nodenum; 140 static int synaptics_scale_y_nodenum; 141 static int synaptics_max_speed_x_nodenum; 142 static int synaptics_max_speed_y_nodenum; 143 static int synaptics_movement_threshold_nodenum; 144 static int synaptics_movement_enable_nodenum; 145 146 static int 147 synaptics_poll_cmd(struct pms_softc *psc, ...) 148 { 149 u_char cmd[4]; 150 size_t i; 151 va_list ap; 152 153 va_start(ap, psc); 154 155 for (i = 0; i < __arraycount(cmd); i++) 156 if ((cmd[i] = (u_char)va_arg(ap, int)) == 0) 157 break; 158 va_end(ap); 159 160 int res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, i, 0, 161 NULL, 0); 162 if (res) 163 aprint_error_dev(psc->sc_dev, "command error %#x\n", cmd[0]); 164 return res; 165 } 166 167 static int 168 synaptics_poll_reset(struct pms_softc *psc) 169 { 170 u_char resp[2]; 171 int res; 172 173 u_char cmd[1] = { PMS_RESET }; 174 res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 2, 175 resp, 1); 176 aprint_debug_dev(psc->sc_dev, "reset %d 0x%02x 0x%02x\n", 177 res, resp[0], resp[1]); 178 return res; 179 } 180 181 static int 182 synaptics_poll_status(struct pms_softc *psc, u_char slice, u_char resp[3]) 183 { 184 u_char cmd[1] = { PMS_SEND_DEV_STATUS }; 185 int res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, slice); 186 187 return res | pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, 188 cmd, 1, 3, resp, 0); 189 } 190 191 static void 192 pms_synaptics_probe_extended(struct pms_softc *psc) 193 { 194 struct synaptics_softc *sc = &psc->u.synaptics; 195 u_char resp[3]; 196 int res; 197 198 aprint_debug_dev(psc->sc_dev, 199 "synaptics_probe: Capabilities 0x%04x.\n", sc->caps); 200 if (sc->caps & SYNAPTICS_CAP_PASSTHROUGH) 201 sc->flags |= SYN_FLAG_HAS_PASSTHROUGH; 202 203 if (sc->caps & SYNAPTICS_CAP_PALMDETECT) 204 sc->flags |= SYN_FLAG_HAS_PALM_DETECT; 205 206 if (sc->caps & SYNAPTICS_CAP_MULTIDETECT) 207 sc->flags |= SYN_FLAG_HAS_MULTI_FINGER; 208 209 if (sc->caps & SYNAPTICS_CAP_MULTIFINGERREPORT) 210 sc->flags |= SYN_FLAG_HAS_MULTI_FINGER_REPORT; 211 212 /* Ask about extra buttons to detect up/down. */ 213 if (((sc->caps & SYNAPTICS_CAP_EXTNUM) + 0x08) 214 >= SYNAPTICS_EXTENDED_QUERY) 215 { 216 res = synaptics_poll_status(psc, SYNAPTICS_EXTENDED_QUERY, resp); 217 if (res == 0) { 218 int buttons = (resp[1] >> 4); 219 aprint_debug_dev(psc->sc_dev, 220 "%s: Extended Buttons: %d.\n", __func__, buttons); 221 222 aprint_debug_dev(psc->sc_dev, "%s: Extended " 223 "Capabilities: 0x%02x 0x%02x 0x%02x.\n", __func__, 224 resp[0], resp[1], resp[2]); 225 if (buttons >= 2) { 226 /* Yes. */ 227 sc->flags |= SYN_FLAG_HAS_UP_DOWN_BUTTONS; 228 } 229 if (resp[0] & 0x1) { 230 /* Vertical scroll area */ 231 sc->flags |= SYN_FLAG_HAS_VERTICAL_SCROLL; 232 } 233 if (resp[0] & 0x2) { 234 /* Horizontal scroll area */ 235 sc->flags |= SYN_FLAG_HAS_HORIZONTAL_SCROLL; 236 } 237 if (resp[0] & 0x4) { 238 /* Extended W-Mode */ 239 sc->flags |= SYN_FLAG_HAS_EXTENDED_WMODE; 240 } 241 } 242 } 243 244 /* Ask about click pad */ 245 if (((sc->caps & SYNAPTICS_CAP_EXTNUM) + 0x08) >= 246 SYNAPTICS_CONTINUED_CAPABILITIES) 247 { 248 res = synaptics_poll_status(psc, 249 SYNAPTICS_CONTINUED_CAPABILITIES, resp); 250 251 /* 252 * The following describes response for the 253 * SYNAPTICS_CONTINUED_CAPABILITIES query. 254 * 255 * byte mask name meaning 256 * ---- ---- ------- ------------ 257 * 0 0x01 adjustable threshold capacitive button sensitivity 258 * can be adjusted 259 * 0 0x02 report max query 0x0d gives max coord reported 260 * 0 0x04 clearpad sensor is ClearPad product 261 * 0 0x08 advanced gesture not particularly meaningful 262 * 0 0x10 clickpad bit 0 1-button ClickPad 263 * 0 0x60 multifinger mode identifies firmware finger counting 264 * (not reporting!) algorithm. 265 * Not particularly meaningful 266 * 0 0x80 covered pad W clipped to 14, 15 == pad mostly covered 267 * 1 0x01 clickpad bit 1 2-button ClickPad 268 * 1 0x02 deluxe LED controls touchpad support LED commands 269 * ala multimedia control bar 270 * 1 0x04 reduced filtering firmware does less filtering on 271 * position data, driver should watch 272 * for noise. 273 * 1 0x08 image sensor image sensor tracks 5 fingers, but only 274 * reports 2. 275 * 1 0x01 uniform clickpad whole clickpad moves instead of being 276 * hinged at the top. 277 * 1 0x20 report min query 0x0f gives min coord reported 278 */ 279 if (res == 0) { 280 u_char clickpad_type = (resp[0] & 0x10); 281 clickpad_type |= (resp[1] & 0x01); 282 283 aprint_debug_dev(psc->sc_dev, "%s: Continued " 284 "Capabilities 0x%02x 0x%02x 0x%02x.\n", __func__, 285 resp[0], resp[1], resp[2]); 286 switch (clickpad_type) { 287 case 0x10: 288 sc->flags |= SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD; 289 break; 290 case 0x01: 291 sc->flags |= SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD; 292 break; 293 default: 294 break; 295 } 296 } 297 } 298 } 299 300 int 301 pms_synaptics_probe_init(void *vsc) 302 { 303 struct pms_softc *psc = vsc; 304 struct synaptics_softc *sc = &psc->u.synaptics; 305 u_char cmd[1], resp[3]; 306 int res, ver_minor, ver_major; 307 struct sysctllog *clog = NULL; 308 309 res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, 310 SYNAPTICS_IDENTIFY_TOUCHPAD); 311 cmd[0] = PMS_SEND_DEV_STATUS; 312 res |= pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 3, 313 resp, 0); 314 if (res) { 315 aprint_debug_dev(psc->sc_dev, 316 "synaptics_probe: Identify Touchpad error.\n"); 317 /* 318 * Reset device in case the probe confused it. 319 */ 320 doreset: 321 (void)synaptics_poll_reset(psc); 322 return res; 323 } 324 325 if (resp[1] != SYNAPTICS_MAGIC_BYTE) { 326 aprint_debug_dev(psc->sc_dev, 327 "synaptics_probe: Not synaptics.\n"); 328 res = 1; 329 goto doreset; 330 } 331 332 sc->flags = 0; 333 334 /* Check for minimum version and print a nice message. */ 335 ver_major = resp[2] & 0x0f; 336 ver_minor = resp[0]; 337 aprint_normal_dev(psc->sc_dev, "Synaptics touchpad version %d.%d\n", 338 ver_major, ver_minor); 339 if (ver_major * 10 + ver_minor < SYNAPTICS_MIN_VERSION) { 340 /* No capability query support. */ 341 sc->caps = 0; 342 goto done; 343 } 344 345 346 /* Query the hardware capabilities. */ 347 res = synaptics_poll_status(psc, SYNAPTICS_READ_CAPABILITIES, resp); 348 if (res) { 349 /* Hmm, failed to get capabilites. */ 350 aprint_error_dev(psc->sc_dev, 351 "synaptics_probe: Failed to query capabilities.\n"); 352 goto doreset; 353 } 354 355 sc->caps = (resp[0] << 8) | resp[2]; 356 357 if (sc->caps & SYNAPTICS_CAP_MBUTTON) 358 sc->flags |= SYN_FLAG_HAS_MIDDLE_BUTTON; 359 360 if (sc->caps & SYNAPTICS_CAP_4BUTTON) 361 sc->flags |= SYN_FLAG_HAS_BUTTONS_4_5; 362 363 if (sc->caps & SYNAPTICS_CAP_EXTENDED) { 364 pms_synaptics_probe_extended(psc); 365 } 366 367 if (sc->flags) { 368 const char comma[] = ", "; 369 const char *sep = ""; 370 aprint_normal_dev(psc->sc_dev, ""); 371 if (sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) { 372 aprint_normal("%sExtended W mode", sep); 373 sep = comma; 374 } 375 if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) { 376 aprint_normal("%sPassthrough", sep); 377 sep = comma; 378 } 379 if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) { 380 aprint_normal("%sMiddle button", sep); 381 sep = comma; 382 } 383 if (sc->flags & SYN_FLAG_HAS_BUTTONS_4_5) { 384 aprint_normal("%sButtons 4/5", sep); 385 sep = comma; 386 } 387 if (sc->flags & SYN_FLAG_HAS_UP_DOWN_BUTTONS) { 388 aprint_normal("%sUp/down buttons", sep); 389 sep = comma; 390 } 391 if (sc->flags & SYN_FLAG_HAS_PALM_DETECT) { 392 aprint_normal("%sPalm detect", sep); 393 sep = comma; 394 } 395 if (sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) { 396 aprint_normal("%sOne button click pad", sep); 397 sep = comma; 398 } 399 if (sc->flags & SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD) { 400 aprint_normal("%sTwo button click pad", sep); 401 sep = comma; 402 } 403 if (sc->flags & SYN_FLAG_HAS_VERTICAL_SCROLL) { 404 aprint_normal("%sVertical scroll", sep); 405 sep = comma; 406 } 407 if (sc->flags & SYN_FLAG_HAS_HORIZONTAL_SCROLL) { 408 aprint_normal("%sHorizontal scroll", sep); 409 sep = comma; 410 } 411 if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER_REPORT) { 412 aprint_normal("%sMulti-finger Report", sep); 413 sep = comma; 414 } 415 if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER) 416 aprint_normal("%sMulti-finger", sep); 417 418 aprint_normal("\n"); 419 } 420 421 done: 422 pms_sysctl_synaptics(&clog); 423 pckbport_set_inputhandler(psc->sc_kbctag, psc->sc_kbcslot, 424 pms_synaptics_input, psc, device_xname(psc->sc_dev)); 425 426 return (0); 427 } 428 429 void 430 pms_synaptics_enable(void *vsc) 431 { 432 struct pms_softc *psc = vsc; 433 struct synaptics_softc *sc = &psc->u.synaptics; 434 u_char enable_modes; 435 int res; 436 437 if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) { 438 /* 439 * Extended capability probes can confuse the passthrough device; 440 * reset the touchpad now to cure that. 441 */ 442 res = synaptics_poll_reset(psc); 443 } 444 445 /* 446 * Enable Absolute mode with W (width) reporting, and set 447 * the packet rate to maximum (80 packets per second). Enable 448 * extended W mode if supported so we can report second finger 449 * position. 450 */ 451 enable_modes = 452 SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE; 453 454 if (sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) 455 enable_modes |= SYNAPTICS_MODE_EXTENDED_W; 456 457 /* 458 * Synaptics documentation says to disable device before 459 * setting mode. 460 */ 461 synaptics_poll_cmd(psc, PMS_DEV_DISABLE, 0); 462 /* a couple of set scales to clear out pending commands */ 463 for (int i = 0; i < 2; i++) 464 synaptics_poll_cmd(psc, PMS_SET_SCALE11, 0); 465 466 res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, 467 enable_modes); 468 if (res) 469 aprint_error("synaptics: set mode error\n"); 470 471 synaptics_poll_cmd(psc, PMS_SET_SAMPLE, SYNAPTICS_CMD_SET_MODE2, 0); 472 473 /* a couple of set scales to clear out pending commands */ 474 for (int i = 0; i < 2; i++) 475 synaptics_poll_cmd(psc, PMS_SET_SCALE11, 0); 476 477 synaptics_poll_cmd(psc, PMS_DEV_ENABLE, 0); 478 479 sc->up_down = 0; 480 sc->prev_fingers = 0; 481 sc->gesture_start_x = sc->gesture_start_y = 0; 482 sc->gesture_start_packet = 0; 483 sc->gesture_tap_packet = 0; 484 sc->gesture_type = 0; 485 sc->gesture_buttons = 0; 486 sc->rem_x[0] = sc->rem_y[0] = 0; 487 sc->rem_x[1] = sc->rem_y[1] = 0; 488 sc->movement_history[0] = 0; 489 sc->movement_history[1] = 0; 490 sc->button_history = 0; 491 } 492 493 void 494 pms_synaptics_resume(void *vsc) 495 { 496 (void)synaptics_poll_reset(vsc); 497 } 498 499 static void 500 pms_sysctl_synaptics(struct sysctllog **clog) 501 { 502 int rc, root_num; 503 const struct sysctlnode *node; 504 505 if ((rc = sysctl_createv(clog, 0, NULL, &node, 506 CTLFLAG_PERMANENT, CTLTYPE_NODE, "synaptics", 507 SYSCTL_DESCR("Synaptics touchpad controls"), 508 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) 509 goto err; 510 511 root_num = node->sysctl_num; 512 513 if ((rc = sysctl_createv(clog, 0, NULL, &node, 514 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 515 CTLTYPE_INT, "up_down_emulation", 516 SYSCTL_DESCR("Middle button/Z-axis emulation with up/down buttons"), 517 pms_sysctl_synaptics_verify, 0, 518 &synaptics_up_down_emul, 519 0, CTL_HW, root_num, CTL_CREATE, 520 CTL_EOL)) != 0) 521 goto err; 522 523 synaptics_up_down_emul_nodenum = node->sysctl_num; 524 525 if ((rc = sysctl_createv(clog, 0, NULL, &node, 526 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 527 CTLTYPE_INT, "up_down_motion_delta", 528 SYSCTL_DESCR("Up/down button Z-axis emulation rate"), 529 pms_sysctl_synaptics_verify, 0, 530 &synaptics_up_down_motion_delta, 531 0, CTL_HW, root_num, CTL_CREATE, 532 CTL_EOL)) != 0) 533 goto err; 534 535 synaptics_up_down_motion_delta_nodenum = node->sysctl_num; 536 537 if ((rc = sysctl_createv(clog, 0, NULL, &node, 538 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 539 CTLTYPE_INT, "gesture_move", 540 SYSCTL_DESCR("Movement greater than this between taps cancels gesture"), 541 pms_sysctl_synaptics_verify, 0, 542 &synaptics_gesture_move, 543 0, CTL_HW, root_num, CTL_CREATE, 544 CTL_EOL)) != 0) 545 goto err; 546 547 synaptics_gesture_move_nodenum = node->sysctl_num; 548 549 if ((rc = sysctl_createv(clog, 0, NULL, &node, 550 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 551 CTLTYPE_INT, "gesture_length", 552 SYSCTL_DESCR("Time period in which tap is recognised as a gesture"), 553 pms_sysctl_synaptics_verify, 0, 554 &synaptics_gesture_length, 555 0, CTL_HW, root_num, CTL_CREATE, 556 CTL_EOL)) != 0) 557 goto err; 558 559 synaptics_gesture_length_nodenum = node->sysctl_num; 560 561 if ((rc = sysctl_createv(clog, 0, NULL, &node, 562 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 563 CTLTYPE_INT, "edge_left", 564 SYSCTL_DESCR("Define left edge of touchpad"), 565 pms_sysctl_synaptics_verify, 0, 566 &synaptics_edge_left, 567 0, CTL_HW, root_num, CTL_CREATE, 568 CTL_EOL)) != 0) 569 goto err; 570 571 synaptics_edge_left_nodenum = node->sysctl_num; 572 573 if ((rc = sysctl_createv(clog, 0, NULL, &node, 574 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 575 CTLTYPE_INT, "edge_right", 576 SYSCTL_DESCR("Define right edge of touchpad"), 577 pms_sysctl_synaptics_verify, 0, 578 &synaptics_edge_right, 579 0, CTL_HW, root_num, CTL_CREATE, 580 CTL_EOL)) != 0) 581 goto err; 582 583 synaptics_edge_right_nodenum = node->sysctl_num; 584 585 if ((rc = sysctl_createv(clog, 0, NULL, &node, 586 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 587 CTLTYPE_INT, "edge_top", 588 SYSCTL_DESCR("Define top edge of touchpad"), 589 pms_sysctl_synaptics_verify, 0, 590 &synaptics_edge_top, 591 0, CTL_HW, root_num, CTL_CREATE, 592 CTL_EOL)) != 0) 593 goto err; 594 595 synaptics_edge_top_nodenum = node->sysctl_num; 596 597 if ((rc = sysctl_createv(clog, 0, NULL, &node, 598 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 599 CTLTYPE_INT, "edge_bottom", 600 SYSCTL_DESCR("Define bottom edge of touchpad"), 601 pms_sysctl_synaptics_verify, 0, 602 &synaptics_edge_bottom, 603 0, CTL_HW, root_num, CTL_CREATE, 604 CTL_EOL)) != 0) 605 goto err; 606 607 synaptics_edge_bottom_nodenum = node->sysctl_num; 608 609 if ((rc = sysctl_createv(clog, 0, NULL, &node, 610 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 611 CTLTYPE_INT, "edge_motion_delta", 612 SYSCTL_DESCR("Define edge motion rate"), 613 pms_sysctl_synaptics_verify, 0, 614 &synaptics_edge_motion_delta, 615 0, CTL_HW, root_num, CTL_CREATE, 616 CTL_EOL)) != 0) 617 goto err; 618 619 synaptics_edge_motion_delta_nodenum = node->sysctl_num; 620 621 if ((rc = sysctl_createv(clog, 0, NULL, &node, 622 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 623 CTLTYPE_INT, "finger_high", 624 SYSCTL_DESCR("Define finger applied pressure threshold"), 625 pms_sysctl_synaptics_verify, 0, 626 &synaptics_finger_high, 627 0, CTL_HW, root_num, CTL_CREATE, 628 CTL_EOL)) != 0) 629 goto err; 630 631 synaptics_finger_high_nodenum = node->sysctl_num; 632 633 if ((rc = sysctl_createv(clog, 0, NULL, &node, 634 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 635 CTLTYPE_INT, "finger_low", 636 SYSCTL_DESCR("Define finger removed pressure threshold"), 637 pms_sysctl_synaptics_verify, 0, 638 &synaptics_finger_low, 639 0, CTL_HW, root_num, CTL_CREATE, 640 CTL_EOL)) != 0) 641 goto err; 642 643 synaptics_finger_low_nodenum = node->sysctl_num; 644 645 if ((rc = sysctl_createv(clog, 0, NULL, &node, 646 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 647 CTLTYPE_INT, "two_fingers_emulation", 648 SYSCTL_DESCR("Map two fingers to middle button"), 649 pms_sysctl_synaptics_verify, 0, 650 &synaptics_two_fingers_emul, 651 0, CTL_HW, root_num, CTL_CREATE, 652 CTL_EOL)) != 0) 653 goto err; 654 655 synaptics_two_fingers_emul_nodenum = node->sysctl_num; 656 657 if ((rc = sysctl_createv(clog, 0, NULL, &node, 658 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 659 CTLTYPE_INT, "scale_x", 660 SYSCTL_DESCR("Horizontal movement scale factor"), 661 pms_sysctl_synaptics_verify, 0, 662 &synaptics_scale_x, 663 0, CTL_HW, root_num, CTL_CREATE, 664 CTL_EOL)) != 0) 665 goto err; 666 667 synaptics_scale_x_nodenum = node->sysctl_num; 668 669 if ((rc = sysctl_createv(clog, 0, NULL, &node, 670 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 671 CTLTYPE_INT, "scale_y", 672 SYSCTL_DESCR("Vertical movement scale factor"), 673 pms_sysctl_synaptics_verify, 0, 674 &synaptics_scale_y, 675 0, CTL_HW, root_num, CTL_CREATE, 676 CTL_EOL)) != 0) 677 goto err; 678 679 synaptics_scale_y_nodenum = node->sysctl_num; 680 681 if ((rc = sysctl_createv(clog, 0, NULL, &node, 682 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 683 CTLTYPE_INT, "max_speed_x", 684 SYSCTL_DESCR("Horizontal movement maximum speed"), 685 pms_sysctl_synaptics_verify, 0, 686 &synaptics_max_speed_x, 687 0, CTL_HW, root_num, CTL_CREATE, 688 CTL_EOL)) != 0) 689 goto err; 690 691 synaptics_max_speed_x_nodenum = node->sysctl_num; 692 693 if ((rc = sysctl_createv(clog, 0, NULL, &node, 694 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 695 CTLTYPE_INT, "max_speed_y", 696 SYSCTL_DESCR("Vertical movement maximum speed"), 697 pms_sysctl_synaptics_verify, 0, 698 &synaptics_max_speed_y, 699 0, CTL_HW, root_num, CTL_CREATE, 700 CTL_EOL)) != 0) 701 goto err; 702 703 synaptics_max_speed_y_nodenum = node->sysctl_num; 704 705 if ((rc = sysctl_createv(clog, 0, NULL, &node, 706 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 707 CTLTYPE_INT, "movement_threshold", 708 SYSCTL_DESCR("Minimum reported movement threshold"), 709 pms_sysctl_synaptics_verify, 0, 710 &synaptics_movement_threshold, 711 0, CTL_HW, root_num, CTL_CREATE, 712 CTL_EOL)) != 0) 713 goto err; 714 715 synaptics_movement_threshold_nodenum = node->sysctl_num; 716 717 if ((rc = sysctl_createv(clog, 0, NULL, &node, 718 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 719 CTLTYPE_INT, "movement_enable", 720 SYSCTL_DESCR("Enable movement reporting"), 721 pms_sysctl_synaptics_verify, 0, 722 &synaptics_movement_enable, 723 0, CTL_HW, root_num, CTL_CREATE, 724 CTL_EOL)) != 0) 725 goto err; 726 727 synaptics_movement_enable_nodenum = node->sysctl_num; 728 729 if ((rc = sysctl_createv(clog, 0, NULL, &node, 730 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 731 CTLTYPE_INT, "button_boundary", 732 SYSCTL_DESCR("Top edge of button area"), 733 pms_sysctl_synaptics_verify, 0, 734 &synaptics_button_boundary, 735 0, CTL_HW, root_num, CTL_CREATE, 736 CTL_EOL)) != 0) 737 goto err; 738 739 synaptics_button_boundary_nodenum = node->sysctl_num; 740 741 if ((rc = sysctl_createv(clog, 0, NULL, &node, 742 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 743 CTLTYPE_INT, "button2_edge", 744 SYSCTL_DESCR("Left edge of button 2 region"), 745 pms_sysctl_synaptics_verify, 0, 746 &synaptics_button2, 747 0, CTL_HW, root_num, CTL_CREATE, 748 CTL_EOL)) != 0) 749 goto err; 750 751 synaptics_button2_nodenum = node->sysctl_num; 752 753 if ((rc = sysctl_createv(clog, 0, NULL, &node, 754 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 755 CTLTYPE_INT, "button3_edge", 756 SYSCTL_DESCR("Left edge of button 3 region"), 757 pms_sysctl_synaptics_verify, 0, 758 &synaptics_button3, 759 0, CTL_HW, root_num, CTL_CREATE, 760 CTL_EOL)) != 0) 761 goto err; 762 763 synaptics_button3_nodenum = node->sysctl_num; 764 return; 765 766 err: 767 aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); 768 } 769 770 static int 771 pms_sysctl_synaptics_verify(SYSCTLFN_ARGS) 772 { 773 int error, t; 774 struct sysctlnode node; 775 776 node = *rnode; 777 t = *(int *)rnode->sysctl_data; 778 node.sysctl_data = &t; 779 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 780 if (error || newp == NULL) 781 return error; 782 783 /* Sanity check the params. */ 784 if (node.sysctl_num == synaptics_up_down_emul_nodenum || 785 node.sysctl_num == synaptics_two_fingers_emul_nodenum) { 786 if (t < 0 || t > 2) 787 return (EINVAL); 788 } else 789 if (node.sysctl_num == synaptics_gesture_length_nodenum || 790 node.sysctl_num == synaptics_edge_motion_delta_nodenum || 791 node.sysctl_num == synaptics_up_down_motion_delta_nodenum) { 792 if (t < 0) 793 return (EINVAL); 794 } else 795 if (node.sysctl_num == synaptics_edge_left_nodenum || 796 node.sysctl_num == synaptics_edge_bottom_nodenum) { 797 if (t < 0 || t > (SYNAPTICS_EDGE_MAX / 2)) 798 return (EINVAL); 799 } else 800 if (node.sysctl_num == synaptics_edge_right_nodenum || 801 node.sysctl_num == synaptics_edge_top_nodenum) { 802 if (t < (SYNAPTICS_EDGE_MAX / 2)) 803 return (EINVAL); 804 } else 805 if (node.sysctl_num == synaptics_scale_x_nodenum || 806 node.sysctl_num == synaptics_scale_y_nodenum) { 807 if (t < 1 || t > (SYNAPTICS_EDGE_MAX / 4)) 808 return (EINVAL); 809 } else 810 if (node.sysctl_num == synaptics_finger_high_nodenum) { 811 if (t < 0 || t > SYNAPTICS_FINGER_PALM || 812 t < synaptics_finger_low) 813 return (EINVAL); 814 } else 815 if (node.sysctl_num == synaptics_finger_low_nodenum) { 816 if (t < 0 || t > SYNAPTICS_FINGER_PALM || 817 t > synaptics_finger_high) 818 return (EINVAL); 819 } else 820 if (node.sysctl_num == synaptics_gesture_move_nodenum || 821 node.sysctl_num == synaptics_movement_threshold_nodenum) { 822 if (t < 0 || t > (SYNAPTICS_EDGE_MAX / 4)) 823 return (EINVAL); 824 } else 825 if (node.sysctl_num == synaptics_button_boundary_nodenum) { 826 if (t < 0 || t < SYNAPTICS_EDGE_BOTTOM || 827 t > SYNAPTICS_EDGE_TOP) 828 return (EINVAL); 829 } else 830 if (node.sysctl_num == synaptics_button2_nodenum || 831 node.sysctl_num == synaptics_button3_nodenum) { 832 if (t < SYNAPTICS_EDGE_LEFT || t > SYNAPTICS_EDGE_RIGHT) 833 return (EINVAL); 834 } else 835 if (node.sysctl_num == synaptics_movement_enable_nodenum) { 836 if (t < 0 || t > 1) 837 return (EINVAL); 838 } else 839 return (EINVAL); 840 841 *(int *)rnode->sysctl_data = t; 842 843 return (0); 844 } 845 846 /* Masks for the first byte of a packet */ 847 #define PMS_LBUTMASK 0x01 848 #define PMS_RBUTMASK 0x02 849 #define PMS_MBUTMASK 0x04 850 851 static void 852 pms_synaptics_parse(struct pms_softc *psc) 853 { 854 struct synaptics_softc *sc = &psc->u.synaptics; 855 struct synaptics_packet sp; 856 char new_buttons, ew_mode; 857 858 memset(&sp, 0, sizeof(sp)); 859 860 /* Width of finger */ 861 sp.sp_w = ((psc->packet[0] & 0x30) >> 2) + 862 ((psc->packet[0] & 0x04) >> 1) + 863 ((psc->packet[3] & 0x04) >> 2); 864 sp.sp_finger = 0; 865 if (sp.sp_w == SYNAPTICS_WIDTH_EXTENDED_W) { 866 ew_mode = psc->packet[5] >> 4; 867 switch (ew_mode) 868 { 869 case SYNAPTICS_EW_WHEEL: 870 /* scroll wheel report, ignore for now */ 871 aprint_debug_dev(psc->sc_dev, "mouse wheel packet\n"); 872 return; 873 874 case SYNAPTICS_EW_SECONDARY_FINGER: 875 /* parse the second finger report */ 876 877 sp.sp_finger = 1; /* just one other finger for now */ 878 sp.sp_x = psc->packet[1] 879 + ((psc->packet[4] & 0x0f) << 8); 880 sp.sp_y = psc->packet[2] 881 + ((psc->packet[4] & 0xf0) << 4); 882 sp.sp_z = (psc->packet[3] & 0x30) 883 + (psc->packet[5] & 0x0f); 884 885 /* keep same buttons down as primary */ 886 sp.sp_left = sc->button_history & PMS_LBUTMASK; 887 sp.sp_middle = sc->button_history & PMS_MBUTMASK; 888 sp.sp_right = sc->button_history & PMS_RBUTMASK; 889 break; 890 891 case SYNAPTICS_EW_FINGER_STATUS: 892 /* reports which finger is primary/secondary 893 * ignore for now. 894 */ 895 return; 896 897 default: 898 aprint_error_dev(psc->sc_dev, 899 "invalid extended w mode %d\n", 900 ew_mode); 901 return; 902 } 903 } else { 904 905 /* Absolute X/Y coordinates of finger */ 906 sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) + 907 ((psc->packet[3] & 0x10) << 8); 908 sp.sp_y = psc->packet[5] + ((psc->packet[1] & 0xf0) << 4) + 909 ((psc->packet[3] & 0x20) << 7); 910 911 /* Pressure */ 912 sp.sp_z = psc->packet[2]; 913 914 /* Left/Right button handling. */ 915 sp.sp_left = psc->packet[0] & PMS_LBUTMASK; 916 sp.sp_right = psc->packet[0] & PMS_RBUTMASK; 917 918 /* Up/Down buttons. */ 919 if (sc->flags & SYN_FLAG_HAS_BUTTONS_4_5) { 920 /* Old up/down buttons. */ 921 sp.sp_up = sp.sp_left ^ 922 (psc->packet[3] & PMS_LBUTMASK); 923 sp.sp_down = sp.sp_right ^ 924 (psc->packet[3] & PMS_RBUTMASK); 925 } else if (sc->flags & SYN_FLAG_HAS_UP_DOWN_BUTTONS && 926 ((psc->packet[0] & PMS_RBUTMASK) ^ 927 (psc->packet[3] & PMS_RBUTMASK))) { 928 /* New up/down button. */ 929 sp.sp_up = psc->packet[4] & SYN_1BUTMASK; 930 sp.sp_down = psc->packet[5] & SYN_2BUTMASK; 931 } else { 932 sp.sp_up = 0; 933 sp.sp_down = 0; 934 } 935 936 new_buttons = 0; 937 if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) { 938 /* This is not correctly specified. Read this button press 939 * from L/U bit. Emulate 3 buttons by checking the 940 * coordinates of the click and returning the appropriate 941 * button code. Outside the button region default to a 942 * left click. 943 */ 944 u_char bstate = (psc->packet[0] ^ psc->packet[3]) 945 & 0x01; 946 if (sp.sp_y < synaptics_button_boundary) { 947 if (sp.sp_x > synaptics_button3) { 948 sp.sp_right = 949 bstate ? PMS_RBUTMASK : 0; 950 } else if (sp.sp_x > synaptics_button2) { 951 sp.sp_middle = 952 bstate ? PMS_MBUTMASK : 0; 953 } else { 954 sp.sp_left = bstate ? PMS_LBUTMASK : 0; 955 } 956 } else 957 sp.sp_left = bstate ? 1 : 0; 958 new_buttons = sp.sp_left | sp.sp_middle | sp.sp_right; 959 if (new_buttons != sc->button_history) { 960 if (sc->button_history == 0) 961 sc->button_history = new_buttons; 962 else if (new_buttons == 0) { 963 sc->button_history = 0; 964 /* ensure all buttons are cleared just in 965 * case finger comes off in a different 966 * region. 967 */ 968 sp.sp_left = 0; 969 sp.sp_middle = 0; 970 sp.sp_right = 0; 971 } else { 972 /* make sure we keep the same button even 973 * if the finger moves to a different 974 * region. This precludes chording 975 * but, oh well. 976 */ 977 sp.sp_left = sc->button_history & PMS_LBUTMASK; 978 sp.sp_middle = sc->button_history 979 & PMS_MBUTMASK; 980 sp.sp_right = sc->button_history & PMS_RBUTMASK; 981 } 982 } 983 } else if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) { 984 /* Old style Middle Button. */ 985 sp.sp_middle = (psc->packet[0] & PMS_LBUTMASK) ^ 986 (psc->packet[3] & PMS_LBUTMASK); 987 } else if (synaptics_up_down_emul == 1) { 988 /* Do middle button emulation using up/down buttons */ 989 sp.sp_middle = sp.sp_up | sp.sp_down; 990 sp.sp_up = sp.sp_down = 0; 991 } else 992 sp.sp_middle = 0; 993 994 } 995 996 pms_synaptics_process_packet(psc, &sp); 997 } 998 999 static void 1000 pms_synaptics_passthrough(struct pms_softc *psc) 1001 { 1002 int dx, dy, dz; 1003 int buttons, changed; 1004 int s; 1005 1006 buttons = ((psc->packet[1] & PMS_LBUTMASK) ? 0x20 : 0) | 1007 ((psc->packet[1] & PMS_MBUTMASK) ? 0x40 : 0) | 1008 ((psc->packet[1] & PMS_RBUTMASK) ? 0x80 : 0); 1009 1010 dx = psc->packet[4]; 1011 if (dx >= 128) 1012 dx -= 256; 1013 if (dx == -128) 1014 dx = -127; 1015 1016 dy = psc->packet[5]; 1017 if (dy >= 128) 1018 dy -= 256; 1019 if (dy == -128) 1020 dy = -127; 1021 1022 dz = 0; 1023 1024 changed = buttons ^ (psc->buttons & 0xe0); 1025 psc->buttons ^= changed; 1026 1027 if (dx || dy || dz || changed) { 1028 buttons = (psc->buttons & 0x1f) | ((psc->buttons >> 5) & 0x7); 1029 s = spltty(); 1030 wsmouse_input(psc->sc_wsmousedev, 1031 buttons, dx, dy, dz, 0, 1032 WSMOUSE_INPUT_DELTA); 1033 splx(s); 1034 } 1035 } 1036 1037 static void 1038 pms_synaptics_input(void *vsc, int data) 1039 { 1040 struct pms_softc *psc = vsc; 1041 struct timeval diff; 1042 1043 if (!psc->sc_enabled) { 1044 /* Interrupts are not expected. Discard the byte. */ 1045 return; 1046 } 1047 1048 getmicrouptime(&psc->current); 1049 1050 if (psc->inputstate > 0) { 1051 timersub(&psc->current, &psc->last, &diff); 1052 if (diff.tv_sec > 0 || diff.tv_usec >= 40000) { 1053 aprint_debug_dev(psc->sc_dev, 1054 "pms_input: unusual delay (%ld.%06ld s), " 1055 "scheduling reset\n", 1056 (long)diff.tv_sec, (long)diff.tv_usec); 1057 printf("pms_input: unusual delay (%ld.%06ld s), " 1058 "scheduling reset\n", 1059 (long)diff.tv_sec, (long)diff.tv_usec); 1060 psc->inputstate = 0; 1061 psc->sc_enabled = 0; 1062 wakeup(&psc->sc_enabled); 1063 return; 1064 } 1065 } 1066 psc->last = psc->current; 1067 1068 switch (psc->inputstate) { 1069 case 0: 1070 if ((data & 0xc8) != 0x80) { 1071 aprint_debug_dev(psc->sc_dev, 1072 "pms_input: 0x%02x out of sync\n", data); 1073 return; /* not in sync yet, discard input */ 1074 } 1075 /*FALLTHROUGH*/ 1076 1077 case 3: 1078 if ((data & 8) == 8) { 1079 aprint_debug_dev(psc->sc_dev, 1080 "pms_input: dropped in relative mode, reset\n"); 1081 psc->inputstate = 0; 1082 psc->sc_enabled = 0; 1083 wakeup(&psc->sc_enabled); 1084 return; 1085 } 1086 } 1087 1088 psc->packet[psc->inputstate++] = data & 0xff; 1089 if (psc->inputstate == 6) { 1090 /* 1091 * We have a complete packet. 1092 * Extract the pertinent details. 1093 */ 1094 psc->inputstate = 0; 1095 if ((psc->packet[0] & 0xfc) == 0x84 && 1096 (psc->packet[3] & 0xcc) == 0xc4) { 1097 /* W = SYNAPTICS_WIDTH_PASSTHROUGH, PS/2 passthrough */ 1098 pms_synaptics_passthrough(psc); 1099 } else { 1100 pms_synaptics_parse(psc); 1101 } 1102 } 1103 } 1104 1105 static inline int 1106 synaptics_finger_detect(struct synaptics_softc *sc, struct synaptics_packet *sp, 1107 int *palmp) 1108 { 1109 int fingers; 1110 1111 /* Assume no palm */ 1112 *palmp = 0; 1113 1114 /* 1115 * Apply some hysteresis when checking for a finger. 1116 * When the finger is first applied, we ignore it until the 1117 * pressure exceeds the 'high' threshold. The finger is considered 1118 * removed only when pressure falls beneath the 'low' threshold. 1119 */ 1120 if ((sc->prev_fingers == 0 && sp->sp_z > synaptics_finger_high) || 1121 (sc->prev_fingers != 0 && sp->sp_z > synaptics_finger_low)) 1122 fingers = 1; 1123 else 1124 fingers = 0; 1125 1126 /* 1127 * If the pad can't do palm detection, skip the rest. 1128 */ 1129 if (fingers == 0 || (sc->flags & SYN_FLAG_HAS_PALM_DETECT) == 0) 1130 return (fingers); 1131 1132 /* 1133 * Palm detection 1134 */ 1135 if (sp->sp_z > SYNAPTICS_FINGER_FLAT && 1136 sp->sp_w >= SYNAPTICS_WIDTH_PALM_MIN) 1137 *palmp = 1; 1138 1139 if (sc->prev_fingers == 0 && 1140 (sp->sp_z > SYNAPTICS_FINGER_FLAT || 1141 sp->sp_w >= SYNAPTICS_WIDTH_PALM_MIN)) { 1142 /* 1143 * Contact area or pressure is too great to be a finger. 1144 * Just ignore it for now. 1145 */ 1146 return (0); 1147 } 1148 1149 /* 1150 * Detect 2 and 3 fingers if supported, but only if multiple 1151 * fingers appear within the tap gesture time period. 1152 */ 1153 if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER && 1154 SYN_TIME(sc, sc->gesture_start_packet, 1155 sp->sp_finger) < synaptics_gesture_length) { 1156 switch (sp->sp_w) { 1157 case SYNAPTICS_WIDTH_TWO_FINGERS: 1158 fingers = 2; 1159 break; 1160 1161 case SYNAPTICS_WIDTH_THREE_OR_MORE: 1162 fingers = 3; 1163 break; 1164 1165 case SYNAPTICS_WIDTH_PEN: 1166 fingers = 1; 1167 break; 1168 1169 default: 1170 /* 1171 * The width value can report spurious single-finger 1172 * events after a multi-finger event. 1173 */ 1174 if (sc->prev_fingers > 1) 1175 fingers = sc->prev_fingers; 1176 else 1177 fingers = 1; 1178 break; 1179 } 1180 } 1181 1182 return (fingers); 1183 } 1184 1185 static inline void 1186 synaptics_gesture_detect(struct synaptics_softc *sc, 1187 struct synaptics_packet *sp, int fingers) 1188 { 1189 int gesture_len, gesture_buttons; 1190 int set_buttons; 1191 1192 gesture_len = SYN_TIME(sc, sc->gesture_start_packet, sp->sp_finger); 1193 gesture_buttons = sc->gesture_buttons; 1194 1195 if (fingers > 0 && (fingers == sc->prev_fingers)) { 1196 /* Finger is still present */ 1197 sc->gesture_move_x = abs(sc->gesture_start_x - sp->sp_x); 1198 sc->gesture_move_y = abs(sc->gesture_start_y - sp->sp_y); 1199 } else 1200 if (fingers && sc->prev_fingers == 0) { 1201 /* 1202 * Finger was just applied. 1203 * If the previous gesture was a single-click, set things 1204 * up to deal with a possible drag or double-click gesture. 1205 * Basically, if the finger is removed again within 1206 * 'synaptics_gesture_length' packets, this is treated 1207 * as a double-click. Otherwise we will emulate holding 1208 * the left button down whilst dragging the mouse. 1209 */ 1210 if (SYN_IS_SINGLE_TAP(sc->gesture_type)) 1211 sc->gesture_type |= SYN_GESTURE_DRAG; 1212 1213 sc->gesture_start_x = abs(sp->sp_x); 1214 sc->gesture_start_y = abs(sp->sp_y); 1215 sc->gesture_move_x = 0; 1216 sc->gesture_move_y = 0; 1217 sc->gesture_start_packet = sc->total_packets[0]; 1218 1219 #ifdef DIAGNOSTIC 1220 aprint_debug("Finger applied: gesture_start_x: %d gesture_start_y: %d\n", 1221 sc->gesture_start_x, sc->gesture_start_y); 1222 #endif 1223 } else 1224 if (fingers == 0 && sc->prev_fingers != 0) { 1225 /* 1226 * Finger was just removed. 1227 * Check if the contact time and finger movement were 1228 * small enough to qualify as a gesture. 1229 * Ignore finger movement if multiple fingers were 1230 * detected (the pad may report coordinates for any 1231 * of the fingers). 1232 */ 1233 1234 #ifdef DIAGNOSTIC 1235 aprint_debug("Finger removed: gesture_len: %d (%d)\n", 1236 gesture_len, synaptics_gesture_length); 1237 aprint_debug("gesture_move_x: %d (%d) sp_x: %d\n", 1238 sc->gesture_move_x, synaptics_gesture_move, abs(sp->sp_x)); 1239 aprint_debug("gesture_move_y: %d (%d) sp_y: %d\n", 1240 sc->gesture_move_y, synaptics_gesture_move, abs(sp->sp_y)); 1241 #endif 1242 1243 if (gesture_len < synaptics_gesture_length && 1244 ((sc->gesture_move_x < synaptics_gesture_move && 1245 sc->gesture_move_y < synaptics_gesture_move))) { 1246 /* 1247 * Looking good so far. 1248 */ 1249 if (SYN_IS_DRAG(sc->gesture_type)) { 1250 /* 1251 * Promote this gesture to double-click. 1252 */ 1253 sc->gesture_type |= SYN_GESTURE_DOUBLE; 1254 sc->gesture_type &= ~SYN_GESTURE_SINGLE; 1255 } else { 1256 /* 1257 * Single tap gesture. Set the tap length timer 1258 * and flag a single-click. 1259 */ 1260 sc->gesture_tap_packet = sc->total_packets[0]; 1261 sc->gesture_type |= SYN_GESTURE_SINGLE; 1262 1263 /* 1264 * The gesture can be modified depending on 1265 * the number of fingers detected. 1266 * 1267 * 1: Normal left button emulation. 1268 * 2: Either middle button or right button 1269 * depending on the value of the two_fingers 1270 * sysctl variable. 1271 * 3: Right button. 1272 */ 1273 switch (sc->prev_fingers) { 1274 case 2: 1275 if (synaptics_two_fingers_emul == 1) 1276 gesture_buttons |= PMS_RBUTMASK; 1277 else 1278 if (synaptics_two_fingers_emul == 2) 1279 gesture_buttons |= PMS_MBUTMASK; 1280 break; 1281 case 3: 1282 gesture_buttons |= PMS_RBUTMASK; 1283 break; 1284 default: 1285 gesture_buttons |= PMS_LBUTMASK; 1286 break; 1287 } 1288 } 1289 } 1290 1291 /* 1292 * Always clear drag state when the finger is removed. 1293 */ 1294 sc->gesture_type &= ~SYN_GESTURE_DRAG; 1295 } 1296 1297 if (sc->gesture_type == 0) { 1298 /* 1299 * There is no gesture in progress. 1300 * Clear emulated button state. 1301 */ 1302 sc->gesture_buttons = 0; 1303 return; 1304 } 1305 1306 /* 1307 * A gesture is in progress. 1308 */ 1309 set_buttons = 0; 1310 1311 if (SYN_IS_SINGLE_TAP(sc->gesture_type)) { 1312 /* 1313 * Single-click. 1314 * Activate the relevant button(s) until the 1315 * gesture tap timer has expired. 1316 */ 1317 if (SYN_TIME(sc, sc->gesture_tap_packet, sp->sp_finger) < 1318 synaptics_gesture_length) 1319 set_buttons = 1; 1320 else 1321 sc->gesture_type &= ~SYN_GESTURE_SINGLE; 1322 } else 1323 if (SYN_IS_DOUBLE_TAP(sc->gesture_type) && sc->prev_fingers == 0) { 1324 /* 1325 * Double-click. 1326 * Activate the relevant button(s) once. 1327 */ 1328 set_buttons = 1; 1329 sc->gesture_type &= ~SYN_GESTURE_DOUBLE; 1330 } 1331 1332 if (set_buttons || SYN_IS_DRAG(sc->gesture_type)) { 1333 /* 1334 * Single-click and drag. 1335 * Maintain button state until the finger is removed. 1336 */ 1337 sp->sp_left |= gesture_buttons & PMS_LBUTMASK; 1338 sp->sp_right |= gesture_buttons & PMS_RBUTMASK; 1339 sp->sp_middle |= gesture_buttons & PMS_MBUTMASK; 1340 } 1341 1342 sc->gesture_buttons = gesture_buttons; 1343 } 1344 1345 static inline int 1346 synaptics_filter_policy(struct synaptics_softc *sc, int finger, int *history, 1347 int value) 1348 { 1349 int a, b, rv, count; 1350 1351 count = sc->total_packets[finger]; 1352 1353 /* 1354 * Once we've accumulated at least SYN_HIST_SIZE values, combine 1355 * each new value with the previous two and return the average. 1356 * 1357 * This is necessary when the touchpad is operating in 80 packets 1358 * per second mode, as it performs little internal filtering on 1359 * reported values. 1360 * 1361 * Using a rolling average helps to filter out jitter caused by 1362 * tiny finger movements. 1363 */ 1364 if (sc->movement_history[finger] >= SYN_HIST_SIZE) { 1365 a = (history[(count + 0) % SYN_HIST_SIZE] + 1366 history[(count + 1) % SYN_HIST_SIZE]) / 2; 1367 1368 b = (value + history[(count + 0) % SYN_HIST_SIZE]) / 2; 1369 1370 rv = b - a; 1371 1372 /* 1373 * Don't report the movement if it's below a certain 1374 * threshold. 1375 */ 1376 if (abs(rv) < synaptics_movement_threshold) 1377 rv = 0; 1378 } else 1379 rv = 0; 1380 1381 /* 1382 * Add the new value to the history buffer. 1383 */ 1384 history[(count + 1) % SYN_HIST_SIZE] = value; 1385 1386 return (rv); 1387 } 1388 1389 /* Edge detection */ 1390 #define SYN_EDGE_TOP 1 1391 #define SYN_EDGE_BOTTOM 2 1392 #define SYN_EDGE_LEFT 4 1393 #define SYN_EDGE_RIGHT 8 1394 1395 static inline int 1396 synaptics_check_edge(int x, int y) 1397 { 1398 int rv = 0; 1399 1400 if (x < synaptics_edge_left) 1401 rv |= SYN_EDGE_LEFT; 1402 else 1403 if (x > synaptics_edge_right) 1404 rv |= SYN_EDGE_RIGHT; 1405 1406 if (y < synaptics_edge_bottom) 1407 rv |= SYN_EDGE_BOTTOM; 1408 else 1409 if (y > synaptics_edge_top) 1410 rv |= SYN_EDGE_TOP; 1411 1412 return (rv); 1413 } 1414 1415 static inline int 1416 synaptics_edge_motion(struct synaptics_softc *sc, int delta, int dir) 1417 { 1418 1419 /* 1420 * When edge motion is enabled, synaptics_edge_motion_delta is 1421 * combined with the current delta, together with the direction 1422 * in which to simulate the motion. The result is added to 1423 * the delta derived from finger movement. This provides a smooth 1424 * transition from finger movement to edge motion. 1425 */ 1426 delta = synaptics_edge_motion_delta + (dir * delta); 1427 if (delta < 0) 1428 return (0); 1429 if (delta > synaptics_edge_motion_delta) 1430 return (synaptics_edge_motion_delta); 1431 return (delta); 1432 } 1433 1434 static inline int 1435 synaptics_scale(int delta, int scale, int *remp) 1436 { 1437 int rv; 1438 1439 /* 1440 * Scale the raw delta in Synaptics coordinates (0-6143) into 1441 * something more reasonable by dividing the raw delta by a 1442 * scale factor. Any remainder from the previous scale result 1443 * is added to the current delta before scaling. 1444 * This prevents loss of resolution for very small/slow 1445 * movements of the finger. 1446 */ 1447 delta += *remp; 1448 rv = delta / scale; 1449 *remp = delta % scale; 1450 1451 return (rv); 1452 } 1453 1454 static inline void 1455 synaptics_movement(struct synaptics_softc *sc, struct synaptics_packet *sp, 1456 int finger, int *dxp, int *dyp) 1457 { 1458 int dx, dy, edge; 1459 1460 /* 1461 * Compute the next values of dx and dy 1462 */ 1463 dx = synaptics_filter_policy(sc, finger, sc->history_x[finger], 1464 sp->sp_x); 1465 dy = synaptics_filter_policy(sc, finger, sc->history_y[finger], 1466 sp->sp_y); 1467 1468 /* 1469 * If we're dealing with a drag gesture, and the finger moves to 1470 * the edge of the touchpad, apply edge motion emulation if it 1471 * is enabled. 1472 */ 1473 if (synaptics_edge_motion_delta && SYN_IS_DRAG(sc->gesture_type)) { 1474 edge = synaptics_check_edge(sp->sp_x, sp->sp_y); 1475 1476 if (edge & SYN_EDGE_LEFT) 1477 dx -= synaptics_edge_motion(sc, dx, 1); 1478 if (edge & SYN_EDGE_RIGHT) 1479 dx += synaptics_edge_motion(sc, dx, -1); 1480 if (edge & SYN_EDGE_BOTTOM) 1481 dy -= synaptics_edge_motion(sc, dy, 1); 1482 if (edge & SYN_EDGE_TOP) 1483 dy += synaptics_edge_motion(sc, dy, -1); 1484 } 1485 1486 /* 1487 * Apply scaling to both deltas 1488 */ 1489 dx = synaptics_scale(dx, synaptics_scale_x, &sc->rem_x[finger]); 1490 dy = synaptics_scale(dy, synaptics_scale_y, &sc->rem_y[finger]); 1491 1492 /* 1493 * Clamp deltas to specified maximums. 1494 */ 1495 if (dx > synaptics_max_speed_x) 1496 dx = synaptics_max_speed_x; 1497 if (dy > synaptics_max_speed_y) 1498 dy = synaptics_max_speed_y; 1499 1500 *dxp = dx; 1501 *dyp = dy; 1502 1503 sc->movement_history[finger]++; 1504 } 1505 1506 static void 1507 pms_synaptics_process_packet(struct pms_softc *psc, struct synaptics_packet *sp) 1508 { 1509 struct synaptics_softc *sc = &psc->u.synaptics; 1510 int dx, dy, dz; 1511 int fingers, palm, buttons, changed; 1512 int s; 1513 1514 /* 1515 * Do Z-axis emulation using up/down buttons if required. 1516 * Note that the pad will send a one second burst of packets 1517 * when an up/down button is pressed and held. At the moment 1518 * we don't deal with auto-repeat, so convert the burst into 1519 * a one-shot. 1520 */ 1521 dz = 0; 1522 if (synaptics_up_down_emul == 2) { 1523 if (sc->up_down == 0) { 1524 if (sp->sp_up && sp->sp_down) { 1525 /* 1526 * Most up/down buttons will be actuated using 1527 * a rocker switch, so we should never see 1528 * them both simultaneously. But just in case, 1529 * treat this situation as a middle button 1530 * event. 1531 */ 1532 sp->sp_middle = 1; 1533 } else 1534 if (sp->sp_up) 1535 dz = -synaptics_up_down_motion_delta; 1536 else 1537 if (sp->sp_down) 1538 dz = synaptics_up_down_motion_delta; 1539 } 1540 1541 sc->up_down = sp->sp_up | sp->sp_down; 1542 sp->sp_up = sp->sp_down = 0; 1543 } 1544 1545 /* 1546 * Determine whether or not a finger is on the pad. 1547 * On some pads, this will return the number of fingers 1548 * detected. 1549 */ 1550 fingers = synaptics_finger_detect(sc, sp, &palm); 1551 1552 /* 1553 * Do gesture processing only if we didn't detect a palm and 1554 * it is not the seondary finger. 1555 */ 1556 if ((sp->sp_finger == 0) && (palm == 0)) 1557 synaptics_gesture_detect(sc, sp, fingers); 1558 else 1559 sc->gesture_type = sc->gesture_buttons = 0; 1560 1561 /* 1562 * Determine what buttons to report 1563 */ 1564 buttons = (sp->sp_left ? 0x1 : 0) | 1565 (sp->sp_middle ? 0x2 : 0) | 1566 (sp->sp_right ? 0x4 : 0) | 1567 (sp->sp_up ? 0x8 : 0) | 1568 (sp->sp_down ? 0x10 : 0); 1569 changed = buttons ^ (psc->buttons & 0x1f); 1570 psc->buttons ^= changed; 1571 1572 sc->prev_fingers = fingers; 1573 sc->total_packets[sp->sp_finger]++; 1574 1575 /* 1576 * Do movement processing IFF we have a single finger and no palm or 1577 * a secondary finger and no palm. 1578 */ 1579 if (palm == 0 && synaptics_movement_enable) { 1580 if (fingers == 1) { 1581 synaptics_movement(sc, sp, sp->sp_finger, &dx, &dy); 1582 } else { 1583 /* 1584 * No valid finger. Therefore no movement. 1585 */ 1586 sc->movement_history[sp->sp_finger] = 0; 1587 sc->rem_x[sp->sp_finger] = sc->rem_y[sp->sp_finger] = 0; 1588 dx = dy = 0; 1589 } 1590 } else { 1591 /* 1592 * No valid finger. Therefore no movement. 1593 */ 1594 sc->movement_history[0] = 0; 1595 sc->rem_x[0] = sc->rem_y[0] = 0; 1596 dx = dy = 0; 1597 } 1598 1599 /* 1600 * Pass the final results up to wsmouse_input() if necessary. 1601 */ 1602 if (dx || dy || dz || changed) { 1603 buttons = (psc->buttons & 0x1f) | ((psc->buttons >> 5) & 0x7); 1604 s = spltty(); 1605 wsmouse_input(psc->sc_wsmousedev, 1606 buttons, 1607 dx, dy, dz, 0, 1608 WSMOUSE_INPUT_DELTA); 1609 splx(s); 1610 } 1611 } 1612