atp.c revision 262417
1/*- 2 * Copyright (c) 2014 Rohit Grover 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Some tables, structures, definitions and constant values for the 29 * touchpad protocol has been copied from Linux's 30 * "drivers/input/mouse/bcm5974.c" which has the following copyright 31 * holders under GPLv2. All device specific code in this driver has 32 * been written from scratch. The decoding algorithm is based on 33 * output from FreeBSD's usbdump. 34 * 35 * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se) 36 * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com) 37 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) 38 * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) 39 * Copyright (C) 2005 Stelian Pop (stelian@popies.net) 40 * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) 41 * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) 42 * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) 43 * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) 44 */ 45 46/* 47 * Author's note: 'atp' supports two distinct families of Apple trackpad 48 * products: the older Fountain/Geyser and the latest Wellspring trackpads. 49 * The first version made its appearance with FreeBSD 8 and worked only with 50 * the Fountain/Geyser hardware. A fork of this driver for Wellspring was 51 * contributed by Huang Wen Hui. This driver unifies the Wellspring effort 52 * and also improves upon the original work. 53 * 54 * I'm grateful to Stephan Scheunig, Angela Naegele, and Nokia IT-support 55 * for helping me with access to hardware. Thanks also go to Nokia for 56 * giving me an opportunity to do this work. 57 */ 58 59#include <sys/cdefs.h> 60__FBSDID("$FreeBSD: head/sys/dev/usb/input/atp.c 262417 2014-02-23 23:36:32Z hselasky $"); 61 62#include <sys/stdint.h> 63#include <sys/stddef.h> 64#include <sys/param.h> 65#include <sys/types.h> 66#include <sys/systm.h> 67#include <sys/kernel.h> 68#include <sys/bus.h> 69#include <sys/module.h> 70#include <sys/lock.h> 71#include <sys/mutex.h> 72#include <sys/sysctl.h> 73#include <sys/malloc.h> 74#include <sys/conf.h> 75#include <sys/fcntl.h> 76#include <sys/file.h> 77#include <sys/selinfo.h> 78#include <sys/poll.h> 79 80#include <dev/usb/usb.h> 81#include <dev/usb/usbdi.h> 82#include <dev/usb/usbdi_util.h> 83#include <dev/usb/usbhid.h> 84 85#include "usbdevs.h" 86 87#define USB_DEBUG_VAR atp_debug 88#include <dev/usb/usb_debug.h> 89 90#include <sys/mouse.h> 91 92#define ATP_DRIVER_NAME "atp" 93 94/* 95 * Driver specific options: the following options may be set by 96 * `options' statements in the kernel configuration file. 97 */ 98 99/* The divisor used to translate sensor reported positions to mickeys. */ 100#ifndef ATP_SCALE_FACTOR 101#define ATP_SCALE_FACTOR 16 102#endif 103 104/* Threshold for small movement noise (in mickeys) */ 105#ifndef ATP_SMALL_MOVEMENT_THRESHOLD 106#define ATP_SMALL_MOVEMENT_THRESHOLD 30 107#endif 108 109/* Threshold of instantaneous deltas beyond which movement is considered fast.*/ 110#ifndef ATP_FAST_MOVEMENT_TRESHOLD 111#define ATP_FAST_MOVEMENT_TRESHOLD 150 112#endif 113 114/* 115 * This is the age in microseconds beyond which a touch is considered 116 * to be a slide; and therefore a tap event isn't registered. 117 */ 118#ifndef ATP_TOUCH_TIMEOUT 119#define ATP_TOUCH_TIMEOUT 125000 120#endif 121 122#ifndef ATP_IDLENESS_THRESHOLD 123#define ATP_IDLENESS_THRESHOLD 10 124#endif 125 126#ifndef FG_SENSOR_NOISE_THRESHOLD 127#define FG_SENSOR_NOISE_THRESHOLD 2 128#endif 129 130/* 131 * A double-tap followed by a single-finger slide is treated as a 132 * special gesture. The driver responds to this gesture by assuming a 133 * virtual button-press for the lifetime of the slide. The following 134 * threshold is the maximum time gap (in microseconds) between the two 135 * tap events preceding the slide for such a gesture. 136 */ 137#ifndef ATP_DOUBLE_TAP_N_DRAG_THRESHOLD 138#define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD 200000 139#endif 140 141/* 142 * The wait duration in ticks after losing a touch contact before 143 * zombied strokes are reaped and turned into button events. 144 */ 145#define ATP_ZOMBIE_STROKE_REAP_INTERVAL (hz / 20) /* 50 ms */ 146 147/* The multiplier used to translate sensor reported positions to mickeys. */ 148#define FG_SCALE_FACTOR 380 149 150/* 151 * The movement threshold for a stroke; this is the maximum difference 152 * in position which will be resolved as a continuation of a stroke 153 * component. 154 */ 155#define FG_MAX_DELTA_MICKEYS ((3 * (FG_SCALE_FACTOR)) >> 1) 156 157/* Distance-squared threshold for matching a finger with a known stroke */ 158#ifndef WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ 159#define WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ 1000000 160#endif 161 162/* Ignore pressure spans with cumulative press. below this value. */ 163#define FG_PSPAN_MIN_CUM_PRESSURE 10 164 165/* Maximum allowed width for pressure-spans.*/ 166#define FG_PSPAN_MAX_WIDTH 4 167 168/* end of driver specific options */ 169 170/* Tunables */ 171static SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW, 0, "USB ATP"); 172 173#ifdef USB_DEBUG 174enum atp_log_level { 175 ATP_LLEVEL_DISABLED = 0, 176 ATP_LLEVEL_ERROR, 177 ATP_LLEVEL_DEBUG, /* for troubleshooting */ 178 ATP_LLEVEL_INFO, /* for diagnostics */ 179}; 180static int atp_debug = ATP_LLEVEL_ERROR; /* the default is to only log errors */ 181SYSCTL_INT(_hw_usb_atp, OID_AUTO, debug, CTLFLAG_RW, 182 &atp_debug, ATP_LLEVEL_ERROR, "ATP debug level"); 183#endif /* USB_DEBUG */ 184 185static u_int atp_touch_timeout = ATP_TOUCH_TIMEOUT; 186SYSCTL_UINT(_hw_usb_atp, OID_AUTO, touch_timeout, CTLFLAG_RW, 187 &atp_touch_timeout, 125000, "age threshold in microseconds for a touch"); 188 189static u_int atp_double_tap_threshold = ATP_DOUBLE_TAP_N_DRAG_THRESHOLD; 190SYSCTL_UINT(_hw_usb_atp, OID_AUTO, double_tap_threshold, CTLFLAG_RW, 191 &atp_double_tap_threshold, ATP_DOUBLE_TAP_N_DRAG_THRESHOLD, 192 "maximum time in microseconds to allow association between a double-tap and " 193 "drag gesture"); 194 195static u_int atp_mickeys_scale_factor = ATP_SCALE_FACTOR; 196static int atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS); 197SYSCTL_PROC(_hw_usb_atp, OID_AUTO, scale_factor, CTLTYPE_UINT | CTLFLAG_RW, 198 &atp_mickeys_scale_factor, sizeof(atp_mickeys_scale_factor), 199 atp_sysctl_scale_factor_handler, "IU", "movement scale factor"); 200 201static u_int atp_small_movement_threshold = ATP_SMALL_MOVEMENT_THRESHOLD; 202SYSCTL_UINT(_hw_usb_atp, OID_AUTO, small_movement, CTLFLAG_RW, 203 &atp_small_movement_threshold, ATP_SMALL_MOVEMENT_THRESHOLD, 204 "the small movement black-hole for filtering noise"); 205 206static u_int atp_tap_minimum = 1; 207SYSCTL_UINT(_hw_usb_atp, OID_AUTO, tap_minimum, CTLFLAG_RW, 208 &atp_tap_minimum, 1, "Minimum number of taps before detection"); 209 210/* 211 * Strokes which accumulate at least this amount of absolute movement 212 * from the aggregate of their components are considered as 213 * slides. Unit: mickeys. 214 */ 215static u_int atp_slide_min_movement = 2 * ATP_SMALL_MOVEMENT_THRESHOLD; 216SYSCTL_UINT(_hw_usb_atp, OID_AUTO, slide_min_movement, CTLFLAG_RW, 217 &atp_slide_min_movement, 2 * ATP_SMALL_MOVEMENT_THRESHOLD, 218 "strokes with at least this amt. of movement are considered slides"); 219 220/* 221 * The minimum age of a stroke for it to be considered mature; this 222 * helps filter movements (noise) from immature strokes. Units: interrupts. 223 */ 224static u_int atp_stroke_maturity_threshold = 4; 225SYSCTL_UINT(_hw_usb_atp, OID_AUTO, stroke_maturity_threshold, CTLFLAG_RW, 226 &atp_stroke_maturity_threshold, 4, 227 "the minimum age of a stroke for it to be considered mature"); 228 229typedef enum atp_trackpad_family { 230 TRACKPAD_FAMILY_FOUNTAIN_GEYSER, 231 TRACKPAD_FAMILY_WELLSPRING, 232 TRACKPAD_FAMILY_MAX /* keep this at the tail end of the enumeration */ 233} trackpad_family_t; 234 235enum fountain_geyser_product { 236 FOUNTAIN, 237 GEYSER1, 238 GEYSER1_17inch, 239 GEYSER2, 240 GEYSER3, 241 GEYSER4, 242 FOUNTAIN_GEYSER_PRODUCT_MAX /* keep this at the end */ 243}; 244 245enum wellspring_product { 246 WELLSPRING1, 247 WELLSPRING2, 248 WELLSPRING3, 249 WELLSPRING4, 250 WELLSPRING4A, 251 WELLSPRING5, 252 WELLSPRING6A, 253 WELLSPRING6, 254 WELLSPRING5A, 255 WELLSPRING7, 256 WELLSPRING7A, 257 WELLSPRING8, 258 WELLSPRING_PRODUCT_MAX /* keep this at the end of the enumeration */ 259}; 260 261/* trackpad header types */ 262enum fountain_geyser_trackpad_type { 263 FG_TRACKPAD_TYPE_GEYSER1, 264 FG_TRACKPAD_TYPE_GEYSER2, 265 FG_TRACKPAD_TYPE_GEYSER3, 266 FG_TRACKPAD_TYPE_GEYSER4, 267}; 268enum wellspring_trackpad_type { 269 WSP_TRACKPAD_TYPE1, /* plain trackpad */ 270 WSP_TRACKPAD_TYPE2, /* button integrated in trackpad */ 271 WSP_TRACKPAD_TYPE3 /* additional header fields since June 2013 */ 272}; 273 274/* 275 * Trackpad family and product and family are encoded together in the 276 * driver_info value associated with a trackpad product. 277 */ 278#define N_PROD_BITS 8 /* Number of bits used to encode product */ 279#define ENCODE_DRIVER_INFO(FAMILY, PROD) \ 280 (((FAMILY) << N_PROD_BITS) | (PROD)) 281#define DECODE_FAMILY_FROM_DRIVER_INFO(INFO) ((INFO) >> N_PROD_BITS) 282#define DECODE_PRODUCT_FROM_DRIVER_INFO(INFO) \ 283 ((INFO) & ((1 << N_PROD_BITS) - 1)) 284 285#define FG_DRIVER_INFO(PRODUCT) \ 286 ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_FOUNTAIN_GEYSER, PRODUCT) 287#define WELLSPRING_DRIVER_INFO(PRODUCT) \ 288 ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_WELLSPRING, PRODUCT) 289 290/* 291 * The following structure captures the state of a pressure span along 292 * an axis. Each contact with the touchpad results in separate 293 * pressure spans along the two axes. 294 */ 295typedef struct fg_pspan { 296 u_int width; /* in units of sensors */ 297 u_int cum; /* cumulative compression (from all sensors) */ 298 u_int cog; /* center of gravity */ 299 u_int loc; /* location (scaled using the mickeys factor) */ 300 boolean_t matched; /* to track pspans as they match against strokes. */ 301} fg_pspan; 302 303#define FG_MAX_PSPANS_PER_AXIS 3 304#define FG_MAX_STROKES (2 * FG_MAX_PSPANS_PER_AXIS) 305 306#define WELLSPRING_INTERFACE_INDEX 1 307 308/* trackpad finger data offsets, le16-aligned */ 309#define WSP_TYPE1_FINGER_DATA_OFFSET (13 * 2) 310#define WSP_TYPE2_FINGER_DATA_OFFSET (15 * 2) 311#define WSP_TYPE3_FINGER_DATA_OFFSET (19 * 2) 312 313/* trackpad button data offsets */ 314#define WSP_TYPE2_BUTTON_DATA_OFFSET 15 315#define WSP_TYPE3_BUTTON_DATA_OFFSET 23 316 317/* list of device capability bits */ 318#define HAS_INTEGRATED_BUTTON 1 319 320/* trackpad finger structure - little endian */ 321struct wsp_finger_sensor_data { 322 int16_t origin; /* zero when switching track finger */ 323 int16_t abs_x; /* absolute x coordinate */ 324 int16_t abs_y; /* absolute y coordinate */ 325 int16_t rel_x; /* relative x coordinate */ 326 int16_t rel_y; /* relative y coordinate */ 327 int16_t tool_major; /* tool area, major axis */ 328 int16_t tool_minor; /* tool area, minor axis */ 329 int16_t orientation; /* 16384 when point, else 15 bit angle */ 330 int16_t touch_major; /* touch area, major axis */ 331 int16_t touch_minor; /* touch area, minor axis */ 332 int16_t unused[3]; /* zeros */ 333 int16_t multi; /* one finger: varies, more fingers: constant */ 334} __packed; 335 336typedef struct wsp_finger { 337 /* to track fingers as they match against strokes. */ 338 boolean_t matched; 339 340 /* location (scaled using the mickeys factor) */ 341 int x; 342 int y; 343} wsp_finger_t; 344 345#define WSP_MAX_FINGERS 16 346#define WSP_SIZEOF_FINGER_SENSOR_DATA sizeof(struct wsp_finger_sensor_data) 347#define WSP_SIZEOF_ALL_FINGER_DATA (WSP_MAX_FINGERS * \ 348 WSP_SIZEOF_FINGER_SENSOR_DATA) 349#define WSP_MAX_FINGER_ORIENTATION 16384 350 351#define ATP_SENSOR_DATA_BUF_MAX 1024 352#if (ATP_SENSOR_DATA_BUF_MAX < ((WSP_MAX_FINGERS * 14 * 2) + \ 353 WSP_TYPE3_FINGER_DATA_OFFSET)) 354/* note: 14 * 2 in the above is based on sizeof(struct wsp_finger_sensor_data)*/ 355#error "ATP_SENSOR_DATA_BUF_MAX is too small" 356#endif 357 358#define ATP_MAX_STROKES MAX(WSP_MAX_FINGERS, FG_MAX_STROKES) 359 360#define FG_MAX_XSENSORS 26 361#define FG_MAX_YSENSORS 16 362 363/* device-specific configuration */ 364struct fg_dev_params { 365 u_int data_len; /* for sensor data */ 366 u_int n_xsensors; 367 u_int n_ysensors; 368 enum fountain_geyser_trackpad_type prot; 369}; 370struct wsp_dev_params { 371 uint8_t caps; /* device capability bitmask */ 372 uint8_t tp_type; /* type of trackpad interface */ 373 uint8_t finger_data_offset; /* offset to trackpad finger data */ 374}; 375 376static const struct fg_dev_params fg_dev_params[FOUNTAIN_GEYSER_PRODUCT_MAX] = { 377 [FOUNTAIN] = { 378 .data_len = 81, 379 .n_xsensors = 16, 380 .n_ysensors = 16, 381 .prot = FG_TRACKPAD_TYPE_GEYSER1 382 }, 383 [GEYSER1] = { 384 .data_len = 81, 385 .n_xsensors = 16, 386 .n_ysensors = 16, 387 .prot = FG_TRACKPAD_TYPE_GEYSER1 388 }, 389 [GEYSER1_17inch] = { 390 .data_len = 81, 391 .n_xsensors = 26, 392 .n_ysensors = 16, 393 .prot = FG_TRACKPAD_TYPE_GEYSER1 394 }, 395 [GEYSER2] = { 396 .data_len = 64, 397 .n_xsensors = 15, 398 .n_ysensors = 9, 399 .prot = FG_TRACKPAD_TYPE_GEYSER2 400 }, 401 [GEYSER3] = { 402 .data_len = 64, 403 .n_xsensors = 20, 404 .n_ysensors = 10, 405 .prot = FG_TRACKPAD_TYPE_GEYSER3 406 }, 407 [GEYSER4] = { 408 .data_len = 64, 409 .n_xsensors = 20, 410 .n_ysensors = 10, 411 .prot = FG_TRACKPAD_TYPE_GEYSER4 412 } 413}; 414 415static const STRUCT_USB_HOST_ID fg_devs[] = { 416 /* PowerBooks Feb 2005, iBooks G4 */ 417 { USB_VPI(USB_VENDOR_APPLE, 0x020e, FG_DRIVER_INFO(FOUNTAIN)) }, 418 { USB_VPI(USB_VENDOR_APPLE, 0x020f, FG_DRIVER_INFO(FOUNTAIN)) }, 419 { USB_VPI(USB_VENDOR_APPLE, 0x0210, FG_DRIVER_INFO(FOUNTAIN)) }, 420 { USB_VPI(USB_VENDOR_APPLE, 0x030a, FG_DRIVER_INFO(FOUNTAIN)) }, 421 { USB_VPI(USB_VENDOR_APPLE, 0x030b, FG_DRIVER_INFO(GEYSER1)) }, 422 423 /* PowerBooks Oct 2005 */ 424 { USB_VPI(USB_VENDOR_APPLE, 0x0214, FG_DRIVER_INFO(GEYSER2)) }, 425 { USB_VPI(USB_VENDOR_APPLE, 0x0215, FG_DRIVER_INFO(GEYSER2)) }, 426 { USB_VPI(USB_VENDOR_APPLE, 0x0216, FG_DRIVER_INFO(GEYSER2)) }, 427 428 /* Core Duo MacBook & MacBook Pro */ 429 { USB_VPI(USB_VENDOR_APPLE, 0x0217, FG_DRIVER_INFO(GEYSER3)) }, 430 { USB_VPI(USB_VENDOR_APPLE, 0x0218, FG_DRIVER_INFO(GEYSER3)) }, 431 { USB_VPI(USB_VENDOR_APPLE, 0x0219, FG_DRIVER_INFO(GEYSER3)) }, 432 433 /* Core2 Duo MacBook & MacBook Pro */ 434 { USB_VPI(USB_VENDOR_APPLE, 0x021a, FG_DRIVER_INFO(GEYSER4)) }, 435 { USB_VPI(USB_VENDOR_APPLE, 0x021b, FG_DRIVER_INFO(GEYSER4)) }, 436 { USB_VPI(USB_VENDOR_APPLE, 0x021c, FG_DRIVER_INFO(GEYSER4)) }, 437 438 /* Core2 Duo MacBook3,1 */ 439 { USB_VPI(USB_VENDOR_APPLE, 0x0229, FG_DRIVER_INFO(GEYSER4)) }, 440 { USB_VPI(USB_VENDOR_APPLE, 0x022a, FG_DRIVER_INFO(GEYSER4)) }, 441 { USB_VPI(USB_VENDOR_APPLE, 0x022b, FG_DRIVER_INFO(GEYSER4)) }, 442 443 /* 17 inch PowerBook */ 444 { USB_VPI(USB_VENDOR_APPLE, 0x020d, FG_DRIVER_INFO(GEYSER1_17inch)) }, 445}; 446 447static const struct wsp_dev_params wsp_dev_params[WELLSPRING_PRODUCT_MAX] = { 448 [WELLSPRING1] = { 449 .caps = 0, 450 .tp_type = WSP_TRACKPAD_TYPE1, 451 .finger_data_offset = WSP_TYPE1_FINGER_DATA_OFFSET, 452 }, 453 [WELLSPRING2] = { 454 .caps = 0, 455 .tp_type = WSP_TRACKPAD_TYPE1, 456 .finger_data_offset = WSP_TYPE1_FINGER_DATA_OFFSET, 457 }, 458 [WELLSPRING3] = { 459 .caps = HAS_INTEGRATED_BUTTON, 460 .tp_type = WSP_TRACKPAD_TYPE2, 461 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 462 }, 463 [WELLSPRING4] = { 464 .caps = HAS_INTEGRATED_BUTTON, 465 .tp_type = WSP_TRACKPAD_TYPE2, 466 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 467 }, 468 [WELLSPRING4A] = { 469 .caps = HAS_INTEGRATED_BUTTON, 470 .tp_type = WSP_TRACKPAD_TYPE2, 471 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 472 }, 473 [WELLSPRING5] = { 474 .caps = HAS_INTEGRATED_BUTTON, 475 .tp_type = WSP_TRACKPAD_TYPE2, 476 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 477 }, 478 [WELLSPRING6] = { 479 .caps = HAS_INTEGRATED_BUTTON, 480 .tp_type = WSP_TRACKPAD_TYPE2, 481 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 482 }, 483 [WELLSPRING5A] = { 484 .caps = HAS_INTEGRATED_BUTTON, 485 .tp_type = WSP_TRACKPAD_TYPE2, 486 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 487 }, 488 [WELLSPRING6A] = { 489 .caps = HAS_INTEGRATED_BUTTON, 490 .tp_type = WSP_TRACKPAD_TYPE2, 491 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 492 }, 493 [WELLSPRING7] = { 494 .caps = HAS_INTEGRATED_BUTTON, 495 .tp_type = WSP_TRACKPAD_TYPE2, 496 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 497 }, 498 [WELLSPRING7A] = { 499 .caps = HAS_INTEGRATED_BUTTON, 500 .tp_type = WSP_TRACKPAD_TYPE2, 501 .finger_data_offset = WSP_TYPE2_FINGER_DATA_OFFSET, 502 }, 503 [WELLSPRING8] = { 504 .caps = HAS_INTEGRATED_BUTTON, 505 .tp_type = WSP_TRACKPAD_TYPE3, 506 .finger_data_offset = WSP_TYPE3_FINGER_DATA_OFFSET, 507 }, 508}; 509 510#define ATP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } 511 512static const STRUCT_USB_HOST_ID wsp_devs[] = { 513 /* MacbookAir1.1 */ 514 ATP_DEV(APPLE, WELLSPRING_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING1)), 515 ATP_DEV(APPLE, WELLSPRING_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING1)), 516 ATP_DEV(APPLE, WELLSPRING_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING1)), 517 518 /* MacbookProPenryn, aka wellspring2 */ 519 ATP_DEV(APPLE, WELLSPRING2_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING2)), 520 ATP_DEV(APPLE, WELLSPRING2_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING2)), 521 ATP_DEV(APPLE, WELLSPRING2_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING2)), 522 523 /* Macbook5,1 (unibody), aka wellspring3 */ 524 ATP_DEV(APPLE, WELLSPRING3_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING3)), 525 ATP_DEV(APPLE, WELLSPRING3_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING3)), 526 ATP_DEV(APPLE, WELLSPRING3_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING3)), 527 528 /* MacbookAir3,2 (unibody), aka wellspring4 */ 529 ATP_DEV(APPLE, WELLSPRING4_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING4)), 530 ATP_DEV(APPLE, WELLSPRING4_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING4)), 531 ATP_DEV(APPLE, WELLSPRING4_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING4)), 532 533 /* MacbookAir3,1 (unibody), aka wellspring4 */ 534 ATP_DEV(APPLE, WELLSPRING4A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING4A)), 535 ATP_DEV(APPLE, WELLSPRING4A_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING4A)), 536 ATP_DEV(APPLE, WELLSPRING4A_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING4A)), 537 538 /* Macbook8 (unibody, March 2011) */ 539 ATP_DEV(APPLE, WELLSPRING5_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING5)), 540 ATP_DEV(APPLE, WELLSPRING5_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING5)), 541 ATP_DEV(APPLE, WELLSPRING5_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING5)), 542 543 /* MacbookAir4,1 (unibody, July 2011) */ 544 ATP_DEV(APPLE, WELLSPRING6A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING6A)), 545 ATP_DEV(APPLE, WELLSPRING6A_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING6A)), 546 ATP_DEV(APPLE, WELLSPRING6A_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING6A)), 547 548 /* MacbookAir4,2 (unibody, July 2011) */ 549 ATP_DEV(APPLE, WELLSPRING6_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING6)), 550 ATP_DEV(APPLE, WELLSPRING6_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING6)), 551 ATP_DEV(APPLE, WELLSPRING6_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING6)), 552 553 /* Macbook8,2 (unibody) */ 554 ATP_DEV(APPLE, WELLSPRING5A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING5A)), 555 ATP_DEV(APPLE, WELLSPRING5A_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING5A)), 556 ATP_DEV(APPLE, WELLSPRING5A_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING5A)), 557 558 /* MacbookPro10,1 (unibody, June 2012) */ 559 /* MacbookPro11,? (unibody, June 2013) */ 560 ATP_DEV(APPLE, WELLSPRING7_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING7)), 561 ATP_DEV(APPLE, WELLSPRING7_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING7)), 562 ATP_DEV(APPLE, WELLSPRING7_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING7)), 563 564 /* MacbookPro10,2 (unibody, October 2012) */ 565 ATP_DEV(APPLE, WELLSPRING7A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING7A)), 566 ATP_DEV(APPLE, WELLSPRING7A_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING7A)), 567 ATP_DEV(APPLE, WELLSPRING7A_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING7A)), 568 569 /* MacbookAir6,2 (unibody, June 2013) */ 570 ATP_DEV(APPLE, WELLSPRING8_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING8)), 571 ATP_DEV(APPLE, WELLSPRING8_ISO, WELLSPRING_DRIVER_INFO(WELLSPRING8)), 572 ATP_DEV(APPLE, WELLSPRING8_JIS, WELLSPRING_DRIVER_INFO(WELLSPRING8)), 573}; 574 575typedef enum atp_stroke_type { 576 ATP_STROKE_TOUCH, 577 ATP_STROKE_SLIDE, 578} atp_stroke_type; 579 580typedef enum atp_axis { 581 X = 0, 582 Y = 1, 583 NUM_AXES 584} atp_axis; 585 586#define ATP_FIFO_BUF_SIZE 8 /* bytes */ 587#define ATP_FIFO_QUEUE_MAXLEN 50 /* units */ 588 589enum { 590 ATP_INTR_DT, 591 ATP_RESET, 592 ATP_N_TRANSFER, 593}; 594 595typedef struct fg_stroke_component { 596 /* Fields encapsulating the pressure-span. */ 597 u_int loc; /* location (scaled) */ 598 u_int cum_pressure; /* cumulative compression */ 599 u_int max_cum_pressure; /* max cumulative compression */ 600 boolean_t matched; /*to track components as they match against pspans.*/ 601 602 int delta_mickeys; /* change in location (un-smoothened movement)*/ 603} fg_stroke_component_t; 604 605/* 606 * The following structure captures a finger contact with the 607 * touchpad. A stroke comprises two p-span components and some state. 608 */ 609typedef struct atp_stroke { 610 TAILQ_ENTRY(atp_stroke) entry; 611 612 atp_stroke_type type; 613 uint32_t flags; /* the state of this stroke */ 614#define ATSF_ZOMBIE 0x1 615 boolean_t matched; /* to track match against fingers.*/ 616 617 struct timeval ctime; /* create time; for coincident siblings. */ 618 619 /* 620 * Unit: interrupts; we maintain this value in 621 * addition to 'ctime' in order to avoid the 622 * expensive call to microtime() at every 623 * interrupt. 624 */ 625 uint32_t age; 626 627 /* Location */ 628 int x; 629 int y; 630 631 /* Fields containing information about movement. */ 632 int instantaneous_dx; /* curr. change in X location (un-smoothened) */ 633 int instantaneous_dy; /* curr. change in Y location (un-smoothened) */ 634 int pending_dx; /* cum. of pending short movements */ 635 int pending_dy; /* cum. of pending short movements */ 636 int movement_dx; /* interpreted smoothened movement */ 637 int movement_dy; /* interpreted smoothened movement */ 638 int cum_movement_x; /* cum. horizontal movement */ 639 int cum_movement_y; /* cum. vertical movement */ 640 641 /* 642 * The following member is relevant only for fountain-geyser trackpads. 643 * For these, there is the need to track pressure-spans and cumulative 644 * pressures for stroke components. 645 */ 646 fg_stroke_component_t components[NUM_AXES]; 647} atp_stroke_t; 648 649struct atp_softc; /* forward declaration */ 650typedef void (*sensor_data_interpreter_t)(struct atp_softc *sc, u_int len); 651 652struct atp_softc { 653 device_t sc_dev; 654 struct usb_device *sc_usb_device; 655 struct mtx sc_mutex; /* for synchronization */ 656 struct usb_fifo_sc sc_fifo; 657 658#define MODE_LENGTH 8 659 char sc_mode_bytes[MODE_LENGTH]; /* device mode */ 660 661 trackpad_family_t sc_family; 662 const void *sc_params; /* device configuration */ 663 sensor_data_interpreter_t sensor_data_interpreter; 664 665 mousehw_t sc_hw; 666 mousemode_t sc_mode; 667 mousestatus_t sc_status; 668 669 u_int sc_state; 670#define ATP_ENABLED 0x01 671#define ATP_ZOMBIES_EXIST 0x02 672#define ATP_DOUBLE_TAP_DRAG 0x04 673#define ATP_VALID 0x08 674 675 struct usb_xfer *sc_xfer[ATP_N_TRANSFER]; 676 677 u_int sc_pollrate; 678 int sc_fflags; 679 680 atp_stroke_t sc_strokes_data[ATP_MAX_STROKES]; 681 TAILQ_HEAD(,atp_stroke) sc_stroke_free; 682 TAILQ_HEAD(,atp_stroke) sc_stroke_used; 683 u_int sc_n_strokes; 684 685 struct callout sc_callout; 686 687 /* 688 * button status. Set to non-zero if the mouse-button is physically 689 * pressed. This state variable is exposed through softc to allow 690 * reap_sibling_zombies to avoid registering taps while the trackpad 691 * button is pressed. 692 */ 693 uint8_t sc_ibtn; 694 695 /* 696 * Time when touch zombies were last reaped; useful for detecting 697 * double-touch-n-drag. 698 */ 699 struct timeval sc_touch_reap_time; 700 701 u_int sc_idlecount; 702 703 /* Regarding the data transferred from t-pad in USB INTR packets. */ 704 u_int sc_expected_sensor_data_len; 705 uint8_t sc_sensor_data[ATP_SENSOR_DATA_BUF_MAX] __aligned(4); 706 707 int sc_cur_x[FG_MAX_XSENSORS]; /* current sensor readings */ 708 int sc_cur_y[FG_MAX_YSENSORS]; 709 int sc_base_x[FG_MAX_XSENSORS]; /* base sensor readings */ 710 int sc_base_y[FG_MAX_YSENSORS]; 711 int sc_pressure_x[FG_MAX_XSENSORS]; /* computed pressures */ 712 int sc_pressure_y[FG_MAX_YSENSORS]; 713 fg_pspan sc_pspans_x[FG_MAX_PSPANS_PER_AXIS]; 714 fg_pspan sc_pspans_y[FG_MAX_PSPANS_PER_AXIS]; 715}; 716 717/* 718 * The last byte of the fountain-geyser sensor data contains status bits; the 719 * following values define the meanings of these bits. 720 * (only Geyser 3/4) 721 */ 722enum geyser34_status_bits { 723 FG_STATUS_BUTTON = (uint8_t)0x01, /* The button was pressed */ 724 FG_STATUS_BASE_UPDATE = (uint8_t)0x04, /* Data from an untouched pad.*/ 725}; 726 727typedef enum interface_mode { 728 RAW_SENSOR_MODE = (uint8_t)0x01, 729 HID_MODE = (uint8_t)0x08 730} interface_mode; 731 732 733/* 734 * function prototypes 735 */ 736static usb_fifo_cmd_t atp_start_read; 737static usb_fifo_cmd_t atp_stop_read; 738static usb_fifo_open_t atp_open; 739static usb_fifo_close_t atp_close; 740static usb_fifo_ioctl_t atp_ioctl; 741 742static struct usb_fifo_methods atp_fifo_methods = { 743 .f_open = &atp_open, 744 .f_close = &atp_close, 745 .f_ioctl = &atp_ioctl, 746 .f_start_read = &atp_start_read, 747 .f_stop_read = &atp_stop_read, 748 .basename[0] = ATP_DRIVER_NAME, 749}; 750 751/* device initialization and shutdown */ 752static usb_error_t atp_set_device_mode(struct atp_softc *, interface_mode); 753static void atp_reset_callback(struct usb_xfer *, usb_error_t); 754static int atp_enable(struct atp_softc *); 755static void atp_disable(struct atp_softc *); 756 757/* sensor interpretation */ 758static void fg_interpret_sensor_data(struct atp_softc *, u_int); 759static void fg_extract_sensor_data(const int8_t *, u_int, atp_axis, 760 int *, enum fountain_geyser_trackpad_type); 761static void fg_get_pressures(int *, const int *, const int *, int); 762static void fg_detect_pspans(int *, u_int, u_int, fg_pspan *, u_int *); 763static void wsp_interpret_sensor_data(struct atp_softc *, u_int); 764 765/* movement detection */ 766static boolean_t fg_match_stroke_component(fg_stroke_component_t *, 767 const fg_pspan *, atp_stroke_type); 768static void fg_match_strokes_against_pspans(struct atp_softc *, 769 atp_axis, fg_pspan *, u_int, u_int); 770static boolean_t wsp_match_strokes_against_fingers(struct atp_softc *, 771 wsp_finger_t *, u_int); 772static boolean_t fg_update_strokes(struct atp_softc *, fg_pspan *, u_int, 773 fg_pspan *, u_int); 774static boolean_t wsp_update_strokes(struct atp_softc *, 775 wsp_finger_t [WSP_MAX_FINGERS], u_int); 776static void fg_add_stroke(struct atp_softc *, const fg_pspan *, const fg_pspan *); 777static void fg_add_new_strokes(struct atp_softc *, fg_pspan *, 778 u_int, fg_pspan *, u_int); 779static void wsp_add_stroke(struct atp_softc *, const wsp_finger_t *); 780static void atp_advance_stroke_state(struct atp_softc *, 781 atp_stroke_t *, boolean_t *); 782static boolean_t atp_stroke_has_small_movement(const atp_stroke_t *); 783static void atp_update_pending_mickeys(atp_stroke_t *); 784static boolean_t atp_compute_stroke_movement(atp_stroke_t *); 785static void atp_terminate_stroke(struct atp_softc *, atp_stroke_t *); 786 787/* tap detection */ 788static boolean_t atp_is_horizontal_scroll(const atp_stroke_t *); 789static boolean_t atp_is_vertical_scroll(const atp_stroke_t *); 790static void atp_reap_sibling_zombies(void *); 791static void atp_convert_to_slide(struct atp_softc *, atp_stroke_t *); 792 793/* updating fifo */ 794static void atp_reset_buf(struct atp_softc *); 795static void atp_add_to_queue(struct atp_softc *, int, int, int, uint32_t); 796 797static const sensor_data_interpreter_t atp_sensor_data_interpreters[TRACKPAD_FAMILY_MAX] = { 798 [TRACKPAD_FAMILY_FOUNTAIN_GEYSER] = fg_interpret_sensor_data, 799 [TRACKPAD_FAMILY_WELLSPRING] = wsp_interpret_sensor_data, 800}; 801 802/* Device methods. */ 803static device_probe_t atp_probe; 804static device_attach_t atp_attach; 805static device_detach_t atp_detach; 806static usb_callback_t atp_intr; 807 808static const struct usb_config atp_xfer_config[ATP_N_TRANSFER] = { 809 [ATP_INTR_DT] = { 810 .type = UE_INTERRUPT, 811 .endpoint = UE_ADDR_ANY, 812 .direction = UE_DIR_IN, 813 .flags = { 814 .pipe_bof = 1, /* block pipe on failure */ 815 .short_xfer_ok = 1, 816 }, 817 .bufsize = ATP_SENSOR_DATA_BUF_MAX, 818 .callback = &atp_intr, 819 }, 820 [ATP_RESET] = { 821 .type = UE_CONTROL, 822 .endpoint = 0, /* Control pipe */ 823 .direction = UE_DIR_ANY, 824 .bufsize = sizeof(struct usb_device_request) + MODE_LENGTH, 825 .callback = &atp_reset_callback, 826 .interval = 0, /* no pre-delay */ 827 }, 828}; 829 830static atp_stroke_t * 831atp_alloc_stroke(struct atp_softc *sc) 832{ 833 atp_stroke_t *pstroke; 834 835 pstroke = TAILQ_FIRST(&sc->sc_stroke_free); 836 if (pstroke == NULL) 837 goto done; 838 839 TAILQ_REMOVE(&sc->sc_stroke_free, pstroke, entry); 840 memset(pstroke, 0, sizeof(*pstroke)); 841 TAILQ_INSERT_TAIL(&sc->sc_stroke_used, pstroke, entry); 842 843 sc->sc_n_strokes++; 844done: 845 return (pstroke); 846} 847 848static void 849atp_free_stroke(struct atp_softc *sc, atp_stroke_t *pstroke) 850{ 851 if (pstroke == NULL) 852 return; 853 854 sc->sc_n_strokes--; 855 856 TAILQ_REMOVE(&sc->sc_stroke_used, pstroke, entry); 857 TAILQ_INSERT_TAIL(&sc->sc_stroke_free, pstroke, entry); 858} 859 860static void 861atp_init_stroke_pool(struct atp_softc *sc) 862{ 863 u_int x; 864 865 TAILQ_INIT(&sc->sc_stroke_free); 866 TAILQ_INIT(&sc->sc_stroke_used); 867 868 sc->sc_n_strokes = 0; 869 870 memset(&sc->sc_strokes_data, 0, sizeof(sc->sc_strokes_data)); 871 872 for (x = 0; x != ATP_MAX_STROKES; x++) { 873 TAILQ_INSERT_TAIL(&sc->sc_stroke_free, &sc->sc_strokes_data[x], 874 entry); 875 } 876} 877 878static usb_error_t 879atp_set_device_mode(struct atp_softc *sc, interface_mode newMode) 880{ 881 uint8_t mode_value; 882 usb_error_t err; 883 884 if ((newMode != RAW_SENSOR_MODE) && (newMode != HID_MODE)) 885 return (USB_ERR_INVAL); 886 887 if ((newMode == RAW_SENSOR_MODE) && 888 (sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER)) 889 mode_value = (uint8_t)0x04; 890 else 891 mode_value = newMode; 892 893 err = usbd_req_get_report(sc->sc_usb_device, NULL /* mutex */, 894 sc->sc_mode_bytes, sizeof(sc->sc_mode_bytes), 0 /* interface idx */, 895 0x03 /* type */, 0x00 /* id */); 896 if (err != USB_ERR_NORMAL_COMPLETION) { 897 DPRINTF("Failed to read device mode (%d)\n", err); 898 return (err); 899 } 900 901 if (sc->sc_mode_bytes[0] == mode_value) 902 return (err); 903 904 /* 905 * XXX Need to wait at least 250ms for hardware to get 906 * ready. The device mode handling appears to be handled 907 * asynchronously and we should not issue these commands too 908 * quickly. 909 */ 910 pause("WHW", hz / 4); 911 912 sc->sc_mode_bytes[0] = mode_value; 913 return (usbd_req_set_report(sc->sc_usb_device, NULL /* mutex */, 914 sc->sc_mode_bytes, sizeof(sc->sc_mode_bytes), 0 /* interface idx */, 915 0x03 /* type */, 0x00 /* id */)); 916} 917 918static void 919atp_reset_callback(struct usb_xfer *xfer, usb_error_t error) 920{ 921 usb_device_request_t req; 922 struct usb_page_cache *pc; 923 struct atp_softc *sc = usbd_xfer_softc(xfer); 924 925 uint8_t mode_value; 926 if (sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER) 927 mode_value = 0x04; 928 else 929 mode_value = RAW_SENSOR_MODE; 930 931 switch (USB_GET_STATE(xfer)) { 932 case USB_ST_SETUP: 933 sc->sc_mode_bytes[0] = mode_value; 934 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 935 req.bRequest = UR_SET_REPORT; 936 USETW2(req.wValue, 937 (uint8_t)0x03 /* type */, (uint8_t)0x00 /* id */); 938 USETW(req.wIndex, 0); 939 USETW(req.wLength, MODE_LENGTH); 940 941 pc = usbd_xfer_get_frame(xfer, 0); 942 usbd_copy_in(pc, 0, &req, sizeof(req)); 943 pc = usbd_xfer_get_frame(xfer, 1); 944 usbd_copy_in(pc, 0, sc->sc_mode_bytes, MODE_LENGTH); 945 946 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 947 usbd_xfer_set_frame_len(xfer, 1, MODE_LENGTH); 948 usbd_xfer_set_frames(xfer, 2); 949 usbd_transfer_submit(xfer); 950 break; 951 952 case USB_ST_TRANSFERRED: 953 default: 954 break; 955 } 956} 957 958static int 959atp_enable(struct atp_softc *sc) 960{ 961 if (sc->sc_state & ATP_ENABLED) 962 return (0); 963 964 /* reset status */ 965 memset(&sc->sc_status, 0, sizeof(sc->sc_status)); 966 967 atp_init_stroke_pool(sc); 968 969 sc->sc_state |= ATP_ENABLED; 970 971 DPRINTFN(ATP_LLEVEL_INFO, "enabled atp\n"); 972 return (0); 973} 974 975static void 976atp_disable(struct atp_softc *sc) 977{ 978 sc->sc_state &= ~(ATP_ENABLED | ATP_VALID); 979 DPRINTFN(ATP_LLEVEL_INFO, "disabled atp\n"); 980} 981 982static void 983fg_interpret_sensor_data(struct atp_softc *sc, u_int data_len) 984{ 985 u_int n_xpspans = 0; 986 u_int n_ypspans = 0; 987 uint8_t status_bits; 988 989 const struct fg_dev_params *params = 990 (const struct fg_dev_params *)sc->sc_params; 991 992 fg_extract_sensor_data(sc->sc_sensor_data, params->n_xsensors, X, 993 sc->sc_cur_x, params->prot); 994 fg_extract_sensor_data(sc->sc_sensor_data, params->n_ysensors, Y, 995 sc->sc_cur_y, params->prot); 996 997 /* 998 * If this is the initial update (from an untouched 999 * pad), we should set the base values for the sensor 1000 * data; deltas with respect to these base values can 1001 * be used as pressure readings subsequently. 1002 */ 1003 status_bits = sc->sc_sensor_data[params->data_len - 1]; 1004 if (((params->prot == FG_TRACKPAD_TYPE_GEYSER3) || 1005 (params->prot == FG_TRACKPAD_TYPE_GEYSER4)) && 1006 ((sc->sc_state & ATP_VALID) == 0)) { 1007 if (status_bits & FG_STATUS_BASE_UPDATE) { 1008 memcpy(sc->sc_base_x, sc->sc_cur_x, 1009 params->n_xsensors * sizeof(*sc->sc_base_x)); 1010 memcpy(sc->sc_base_y, sc->sc_cur_y, 1011 params->n_ysensors * sizeof(*sc->sc_base_y)); 1012 sc->sc_state |= ATP_VALID; 1013 return; 1014 } 1015 } 1016 1017 /* Get pressure readings and detect p-spans for both axes. */ 1018 fg_get_pressures(sc->sc_pressure_x, sc->sc_cur_x, sc->sc_base_x, 1019 params->n_xsensors); 1020 fg_detect_pspans(sc->sc_pressure_x, params->n_xsensors, 1021 FG_MAX_PSPANS_PER_AXIS, sc->sc_pspans_x, &n_xpspans); 1022 fg_get_pressures(sc->sc_pressure_y, sc->sc_cur_y, sc->sc_base_y, 1023 params->n_ysensors); 1024 fg_detect_pspans(sc->sc_pressure_y, params->n_ysensors, 1025 FG_MAX_PSPANS_PER_AXIS, sc->sc_pspans_y, &n_ypspans); 1026 1027 /* Update strokes with new pspans to detect movements. */ 1028 if (fg_update_strokes(sc, sc->sc_pspans_x, n_xpspans, sc->sc_pspans_y, n_ypspans)) 1029 sc->sc_status.flags |= MOUSE_POSCHANGED; 1030 1031 sc->sc_ibtn = (status_bits & FG_STATUS_BUTTON) ? MOUSE_BUTTON1DOWN : 0; 1032 sc->sc_status.button = sc->sc_ibtn; 1033 1034 /* 1035 * The Fountain/Geyser device continues to trigger interrupts 1036 * at a fast rate even after touchpad activity has 1037 * stopped. Upon detecting that the device has remained idle 1038 * beyond a threshold, we reinitialize it to silence the 1039 * interrupts. 1040 */ 1041 if ((sc->sc_status.flags == 0) && (sc->sc_n_strokes == 0)) { 1042 sc->sc_idlecount++; 1043 if (sc->sc_idlecount >= ATP_IDLENESS_THRESHOLD) { 1044 /* 1045 * Use the last frame before we go idle for 1046 * calibration on pads which do not send 1047 * calibration frames. 1048 */ 1049 const struct fg_dev_params *params = 1050 (const struct fg_dev_params *)sc->sc_params; 1051 1052 DPRINTFN(ATP_LLEVEL_INFO, "idle\n"); 1053 1054 if (params->prot < FG_TRACKPAD_TYPE_GEYSER3) { 1055 memcpy(sc->sc_base_x, sc->sc_cur_x, 1056 params->n_xsensors * sizeof(*(sc->sc_base_x))); 1057 memcpy(sc->sc_base_y, sc->sc_cur_y, 1058 params->n_ysensors * sizeof(*(sc->sc_base_y))); 1059 } 1060 1061 sc->sc_idlecount = 0; 1062 usbd_transfer_start(sc->sc_xfer[ATP_RESET]); 1063 } 1064 } else { 1065 sc->sc_idlecount = 0; 1066 } 1067} 1068 1069/* 1070 * Interpret the data from the X and Y pressure sensors. This function 1071 * is called separately for the X and Y sensor arrays. The data in the 1072 * USB packet is laid out in the following manner: 1073 * 1074 * sensor_data: 1075 * --,--,Y1,Y2,--,Y3,Y4,--,Y5,...,Y10, ... X1,X2,--,X3,X4 1076 * indices: 0 1 2 3 4 5 6 7 8 ... 15 ... 20 21 22 23 24 1077 * 1078 * '--' (in the above) indicates that the value is unimportant. 1079 * 1080 * Information about the above layout was obtained from the 1081 * implementation of the AppleTouch driver in Linux. 1082 * 1083 * parameters: 1084 * sensor_data 1085 * raw sensor data from the USB packet. 1086 * num 1087 * The number of elements in the array 'arr'. 1088 * axis 1089 * Axis of data to fetch 1090 * arr 1091 * The array to be initialized with the readings. 1092 * prot 1093 * The protocol to use to interpret the data 1094 */ 1095static void 1096fg_extract_sensor_data(const int8_t *sensor_data, u_int num, atp_axis axis, 1097 int *arr, enum fountain_geyser_trackpad_type prot) 1098{ 1099 u_int i; 1100 u_int di; /* index into sensor data */ 1101 1102 switch (prot) { 1103 case FG_TRACKPAD_TYPE_GEYSER1: 1104 /* 1105 * For Geyser 1, the sensors are laid out in pairs 1106 * every 5 bytes. 1107 */ 1108 for (i = 0, di = (axis == Y) ? 1 : 2; i < 8; di += 5, i++) { 1109 arr[i] = sensor_data[di]; 1110 arr[i+8] = sensor_data[di+2]; 1111 if ((axis == X) && (num > 16)) 1112 arr[i+16] = sensor_data[di+40]; 1113 } 1114 1115 break; 1116 case FG_TRACKPAD_TYPE_GEYSER2: 1117 for (i = 0, di = (axis == Y) ? 1 : 19; i < num; /* empty */ ) { 1118 arr[i++] = sensor_data[di++]; 1119 arr[i++] = sensor_data[di++]; 1120 di++; 1121 } 1122 break; 1123 case FG_TRACKPAD_TYPE_GEYSER3: 1124 case FG_TRACKPAD_TYPE_GEYSER4: 1125 for (i = 0, di = (axis == Y) ? 2 : 20; i < num; /* empty */ ) { 1126 arr[i++] = sensor_data[di++]; 1127 arr[i++] = sensor_data[di++]; 1128 di++; 1129 } 1130 break; 1131 default: 1132 break; 1133 } 1134} 1135 1136static void 1137fg_get_pressures(int *p, const int *cur, const int *base, int n) 1138{ 1139 int i; 1140 1141 for (i = 0; i < n; i++) { 1142 p[i] = cur[i] - base[i]; 1143 if (p[i] > 127) 1144 p[i] -= 256; 1145 if (p[i] < -127) 1146 p[i] += 256; 1147 if (p[i] < 0) 1148 p[i] = 0; 1149 1150 /* 1151 * Shave off pressures below the noise-pressure 1152 * threshold; this will reduce the contribution from 1153 * lower pressure readings. 1154 */ 1155 if ((u_int)p[i] <= FG_SENSOR_NOISE_THRESHOLD) 1156 p[i] = 0; /* filter away noise */ 1157 else 1158 p[i] -= FG_SENSOR_NOISE_THRESHOLD; 1159 } 1160} 1161 1162static void 1163fg_detect_pspans(int *p, u_int num_sensors, 1164 u_int max_spans, /* max # of pspans permitted */ 1165 fg_pspan *spans, /* finger spans */ 1166 u_int *nspans_p) /* num spans detected */ 1167{ 1168 u_int i; 1169 int maxp; /* max pressure seen within a span */ 1170 u_int num_spans = 0; 1171 1172 enum fg_pspan_state { 1173 ATP_PSPAN_INACTIVE, 1174 ATP_PSPAN_INCREASING, 1175 ATP_PSPAN_DECREASING, 1176 } state; /* state of the pressure span */ 1177 1178 /* 1179 * The following is a simple state machine to track 1180 * the phase of the pressure span. 1181 */ 1182 memset(spans, 0, max_spans * sizeof(fg_pspan)); 1183 maxp = 0; 1184 state = ATP_PSPAN_INACTIVE; 1185 for (i = 0; i < num_sensors; i++) { 1186 if (num_spans >= max_spans) 1187 break; 1188 1189 if (p[i] == 0) { 1190 if (state == ATP_PSPAN_INACTIVE) { 1191 /* 1192 * There is no pressure information for this 1193 * sensor, and we aren't tracking a finger. 1194 */ 1195 continue; 1196 } else { 1197 state = ATP_PSPAN_INACTIVE; 1198 maxp = 0; 1199 num_spans++; 1200 } 1201 } else { 1202 switch (state) { 1203 case ATP_PSPAN_INACTIVE: 1204 state = ATP_PSPAN_INCREASING; 1205 maxp = p[i]; 1206 break; 1207 1208 case ATP_PSPAN_INCREASING: 1209 if (p[i] > maxp) 1210 maxp = p[i]; 1211 else if (p[i] <= (maxp >> 1)) 1212 state = ATP_PSPAN_DECREASING; 1213 break; 1214 1215 case ATP_PSPAN_DECREASING: 1216 if (p[i] > p[i - 1]) { 1217 /* 1218 * This is the beginning of 1219 * another span; change state 1220 * to give the appearance that 1221 * we're starting from an 1222 * inactive span, and then 1223 * re-process this reading in 1224 * the next iteration. 1225 */ 1226 num_spans++; 1227 state = ATP_PSPAN_INACTIVE; 1228 maxp = 0; 1229 i--; 1230 continue; 1231 } 1232 break; 1233 } 1234 1235 /* Update the finger span with this reading. */ 1236 spans[num_spans].width++; 1237 spans[num_spans].cum += p[i]; 1238 spans[num_spans].cog += p[i] * (i + 1); 1239 } 1240 } 1241 if (state != ATP_PSPAN_INACTIVE) 1242 num_spans++; /* close the last finger span */ 1243 1244 /* post-process the spans */ 1245 for (i = 0; i < num_spans; i++) { 1246 /* filter away unwanted pressure spans */ 1247 if ((spans[i].cum < FG_PSPAN_MIN_CUM_PRESSURE) || 1248 (spans[i].width > FG_PSPAN_MAX_WIDTH)) { 1249 if ((i + 1) < num_spans) { 1250 memcpy(&spans[i], &spans[i + 1], 1251 (num_spans - i - 1) * sizeof(fg_pspan)); 1252 i--; 1253 } 1254 num_spans--; 1255 continue; 1256 } 1257 1258 /* compute this span's representative location */ 1259 spans[i].loc = spans[i].cog * FG_SCALE_FACTOR / 1260 spans[i].cum; 1261 1262 spans[i].matched = false; /* not yet matched against a stroke */ 1263 } 1264 1265 *nspans_p = num_spans; 1266} 1267 1268static void 1269wsp_interpret_sensor_data(struct atp_softc *sc, u_int data_len) 1270{ 1271 const struct wsp_dev_params *params = sc->sc_params; 1272 wsp_finger_t fingers[WSP_MAX_FINGERS]; 1273 struct wsp_finger_sensor_data *source_fingerp; 1274 u_int n_source_fingers; 1275 u_int n_fingers; 1276 u_int i; 1277 1278 /* validate sensor data length */ 1279 if ((data_len < params->finger_data_offset) || 1280 ((data_len - params->finger_data_offset) % 1281 WSP_SIZEOF_FINGER_SENSOR_DATA) != 0) 1282 return; 1283 1284 /* compute number of source fingers */ 1285 n_source_fingers = (data_len - params->finger_data_offset) / 1286 WSP_SIZEOF_FINGER_SENSOR_DATA; 1287 1288 if (n_source_fingers > WSP_MAX_FINGERS) 1289 n_source_fingers = WSP_MAX_FINGERS; 1290 1291 /* iterate over the source data collecting useful fingers */ 1292 n_fingers = 0; 1293 source_fingerp = (struct wsp_finger_sensor_data *)(sc->sc_sensor_data + 1294 params->finger_data_offset); 1295 1296 for (i = 0; i < n_source_fingers; i++, source_fingerp++) { 1297 /* swap endianness, if any */ 1298 if (le16toh(0x1234) != 0x1234) { 1299 source_fingerp->origin = le16toh((uint16_t)source_fingerp->origin); 1300 source_fingerp->abs_x = le16toh((uint16_t)source_fingerp->abs_x); 1301 source_fingerp->abs_y = le16toh((uint16_t)source_fingerp->abs_y); 1302 source_fingerp->rel_x = le16toh((uint16_t)source_fingerp->rel_x); 1303 source_fingerp->rel_y = le16toh((uint16_t)source_fingerp->rel_y); 1304 source_fingerp->tool_major = le16toh((uint16_t)source_fingerp->tool_major); 1305 source_fingerp->tool_minor = le16toh((uint16_t)source_fingerp->tool_minor); 1306 source_fingerp->orientation = le16toh((uint16_t)source_fingerp->orientation); 1307 source_fingerp->touch_major = le16toh((uint16_t)source_fingerp->touch_major); 1308 source_fingerp->touch_minor = le16toh((uint16_t)source_fingerp->touch_minor); 1309 source_fingerp->multi = le16toh((uint16_t)source_fingerp->multi); 1310 } 1311 1312 /* check for minium threshold */ 1313 if (source_fingerp->touch_major == 0) 1314 continue; 1315 1316 fingers[n_fingers].matched = false; 1317 fingers[n_fingers].x = source_fingerp->abs_x; 1318 fingers[n_fingers].y = -source_fingerp->abs_y; 1319 1320 n_fingers++; 1321 } 1322 1323 if ((sc->sc_n_strokes == 0) && (n_fingers == 0)) 1324 return; 1325 1326 if (wsp_update_strokes(sc, fingers, n_fingers)) 1327 sc->sc_status.flags |= MOUSE_POSCHANGED; 1328 1329 switch(params->tp_type) { 1330 case WSP_TRACKPAD_TYPE2: 1331 sc->sc_ibtn = sc->sc_sensor_data[WSP_TYPE2_BUTTON_DATA_OFFSET]; 1332 break; 1333 case WSP_TRACKPAD_TYPE3: 1334 sc->sc_ibtn = sc->sc_sensor_data[WSP_TYPE3_BUTTON_DATA_OFFSET]; 1335 break; 1336 default: 1337 break; 1338 } 1339 sc->sc_status.button = sc->sc_ibtn ? MOUSE_BUTTON1DOWN : 0; 1340} 1341 1342/* 1343 * Match a pressure-span against a stroke-component. If there is a 1344 * match, update the component's state and return true. 1345 */ 1346static boolean_t 1347fg_match_stroke_component(fg_stroke_component_t *component, 1348 const fg_pspan *pspan, atp_stroke_type stroke_type) 1349{ 1350 int delta_mickeys; 1351 u_int min_pressure; 1352 1353 delta_mickeys = pspan->loc - component->loc; 1354 1355 if (abs(delta_mickeys) > (int)FG_MAX_DELTA_MICKEYS) 1356 return (false); /* the finger span is too far out; no match */ 1357 1358 component->loc = pspan->loc; 1359 1360 /* 1361 * A sudden and significant increase in a pspan's cumulative 1362 * pressure indicates the incidence of a new finger 1363 * contact. This usually revises the pspan's 1364 * centre-of-gravity, and hence the location of any/all 1365 * matching stroke component(s). But such a change should 1366 * *not* be interpreted as a movement. 1367 */ 1368 if (pspan->cum > ((3 * component->cum_pressure) >> 1)) 1369 delta_mickeys = 0; 1370 1371 component->cum_pressure = pspan->cum; 1372 if (pspan->cum > component->max_cum_pressure) 1373 component->max_cum_pressure = pspan->cum; 1374 1375 /* 1376 * Disregard the component's movement if its cumulative 1377 * pressure drops below a fraction of the maximum; this 1378 * fraction is determined based on the stroke's type. 1379 */ 1380 if (stroke_type == ATP_STROKE_TOUCH) 1381 min_pressure = (3 * component->max_cum_pressure) >> 2; 1382 else 1383 min_pressure = component->max_cum_pressure >> 2; 1384 if (component->cum_pressure < min_pressure) 1385 delta_mickeys = 0; 1386 1387 component->delta_mickeys = delta_mickeys; 1388 return (true); 1389} 1390 1391static void 1392fg_match_strokes_against_pspans(struct atp_softc *sc, atp_axis axis, 1393 fg_pspan *pspans, u_int n_pspans, u_int repeat_count) 1394{ 1395 atp_stroke_t *strokep; 1396 u_int repeat_index = 0; 1397 u_int i; 1398 1399 /* Determine the index of the multi-span. */ 1400 if (repeat_count) { 1401 for (i = 0; i < n_pspans; i++) { 1402 if (pspans[i].cum > pspans[repeat_index].cum) 1403 repeat_index = i; 1404 } 1405 } 1406 1407 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { 1408 if (strokep->components[axis].matched) 1409 continue; /* skip matched components */ 1410 1411 for (i = 0; i < n_pspans; i++) { 1412 if (pspans[i].matched) 1413 continue; /* skip matched pspans */ 1414 1415 if (fg_match_stroke_component( 1416 &strokep->components[axis], &pspans[i], 1417 strokep->type)) { 1418 1419 /* There is a match. */ 1420 strokep->components[axis].matched = true; 1421 1422 /* Take care to repeat at the multi-span. */ 1423 if ((repeat_count > 0) && (i == repeat_index)) 1424 repeat_count--; 1425 else 1426 pspans[i].matched = true; 1427 1428 break; /* skip to the next strokep */ 1429 } 1430 } /* loop over pspans */ 1431 } /* loop over strokes */ 1432} 1433 1434static boolean_t 1435wsp_match_strokes_against_fingers(struct atp_softc *sc, 1436 wsp_finger_t *fingers, u_int n_fingers) 1437{ 1438 boolean_t movement = false; 1439 atp_stroke_t *strokep; 1440 u_int i; 1441 1442 /* reset the matched status for all strokes */ 1443 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) 1444 strokep->matched = false; 1445 1446 for (i = 0; i != n_fingers; i++) { 1447 u_int least_distance_sq = WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ; 1448 atp_stroke_t *strokep_best = NULL; 1449 1450 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { 1451 int instantaneous_dx; 1452 int instantaneous_dy; 1453 u_int d_squared; 1454 1455 if (strokep->matched) 1456 continue; 1457 1458 instantaneous_dx = fingers[i].x - strokep->x; 1459 instantaneous_dy = fingers[i].y - strokep->y; 1460 1461 /* skip strokes which are far away */ 1462 d_squared = 1463 (instantaneous_dx * instantaneous_dx) + 1464 (instantaneous_dy * instantaneous_dy); 1465 1466 if (d_squared < least_distance_sq) { 1467 least_distance_sq = d_squared; 1468 strokep_best = strokep; 1469 } 1470 } 1471 1472 strokep = strokep_best; 1473 1474 if (strokep != NULL) { 1475 fingers[i].matched = true; 1476 1477 strokep->matched = true; 1478 strokep->instantaneous_dx = fingers[i].x - strokep->x; 1479 strokep->instantaneous_dy = fingers[i].y - strokep->y; 1480 strokep->x = fingers[i].x; 1481 strokep->y = fingers[i].y; 1482 1483 atp_advance_stroke_state(sc, strokep, &movement); 1484 } 1485 } 1486 return (movement); 1487} 1488 1489/* 1490 * Update strokes by matching against current pressure-spans. 1491 * Return true if any movement is detected. 1492 */ 1493static boolean_t 1494fg_update_strokes(struct atp_softc *sc, fg_pspan *pspans_x, 1495 u_int n_xpspans, fg_pspan *pspans_y, u_int n_ypspans) 1496{ 1497 atp_stroke_t *strokep; 1498 atp_stroke_t *strokep_next; 1499 boolean_t movement = false; 1500 u_int repeat_count = 0; 1501 u_int i; 1502 u_int j; 1503 1504 /* Reset X and Y components of all strokes as unmatched. */ 1505 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { 1506 strokep->components[X].matched = false; 1507 strokep->components[Y].matched = false; 1508 } 1509 1510 /* 1511 * Usually, the X and Y pspans come in pairs (the common case 1512 * being a single pair). It is possible, however, that 1513 * multiple contacts resolve to a single pspan along an 1514 * axis, as illustrated in the following: 1515 * 1516 * F = finger-contact 1517 * 1518 * pspan pspan 1519 * +-----------------------+ 1520 * | . . | 1521 * | . . | 1522 * | . . | 1523 * | . . | 1524 * pspan |.........F......F | 1525 * | | 1526 * | | 1527 * | | 1528 * +-----------------------+ 1529 * 1530 * 1531 * The above case can be detected by a difference in the 1532 * number of X and Y pspans. When this happens, X and Y pspans 1533 * aren't easy to pair or match against strokes. 1534 * 1535 * When X and Y pspans differ in number, the axis with the 1536 * smaller number of pspans is regarded as having a repeating 1537 * pspan (or a multi-pspan)--in the above illustration, the 1538 * Y-axis has a repeating pspan. Our approach is to try to 1539 * match the multi-pspan repeatedly against strokes. The 1540 * difference between the number of X and Y pspans gives us a 1541 * crude repeat_count for matching multi-pspans--i.e. the 1542 * multi-pspan along the Y axis (above) has a repeat_count of 1. 1543 */ 1544 repeat_count = abs(n_xpspans - n_ypspans); 1545 1546 fg_match_strokes_against_pspans(sc, X, pspans_x, n_xpspans, 1547 (((repeat_count != 0) && ((n_xpspans < n_ypspans))) ? 1548 repeat_count : 0)); 1549 fg_match_strokes_against_pspans(sc, Y, pspans_y, n_ypspans, 1550 (((repeat_count != 0) && (n_ypspans < n_xpspans)) ? 1551 repeat_count : 0)); 1552 1553 /* Update the state of strokes based on the above pspan matches. */ 1554 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) { 1555 1556 if (strokep->components[X].matched && 1557 strokep->components[Y].matched) { 1558 strokep->matched = true; 1559 strokep->instantaneous_dx = 1560 strokep->components[X].delta_mickeys; 1561 strokep->instantaneous_dy = 1562 strokep->components[Y].delta_mickeys; 1563 atp_advance_stroke_state(sc, strokep, &movement); 1564 } else { 1565 /* 1566 * At least one component of this stroke 1567 * didn't match against current pspans; 1568 * terminate it. 1569 */ 1570 atp_terminate_stroke(sc, strokep); 1571 } 1572 } 1573 1574 /* Add new strokes for pairs of unmatched pspans */ 1575 for (i = 0; i < n_xpspans; i++) { 1576 if (pspans_x[i].matched == false) break; 1577 } 1578 for (j = 0; j < n_ypspans; j++) { 1579 if (pspans_y[j].matched == false) break; 1580 } 1581 if ((i < n_xpspans) && (j < n_ypspans)) { 1582#ifdef USB_DEBUG 1583 if (atp_debug >= ATP_LLEVEL_INFO) { 1584 printf("unmatched pspans:"); 1585 for (; i < n_xpspans; i++) { 1586 if (pspans_x[i].matched) 1587 continue; 1588 printf(" X:[loc:%u,cum:%u]", 1589 pspans_x[i].loc, pspans_x[i].cum); 1590 } 1591 for (; j < n_ypspans; j++) { 1592 if (pspans_y[j].matched) 1593 continue; 1594 printf(" Y:[loc:%u,cum:%u]", 1595 pspans_y[j].loc, pspans_y[j].cum); 1596 } 1597 printf("\n"); 1598 } 1599#endif /* USB_DEBUG */ 1600 if ((n_xpspans == 1) && (n_ypspans == 1)) 1601 /* The common case of a single pair of new pspans. */ 1602 fg_add_stroke(sc, &pspans_x[0], &pspans_y[0]); 1603 else 1604 fg_add_new_strokes(sc, pspans_x, n_xpspans, 1605 pspans_y, n_ypspans); 1606 } 1607 1608#ifdef USB_DEBUG 1609 if (atp_debug >= ATP_LLEVEL_INFO) { 1610 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { 1611 printf(" %s%clc:%u,dm:%d,cum:%d,max:%d,%c" 1612 ",%clc:%u,dm:%d,cum:%d,max:%d,%c", 1613 (strokep->flags & ATSF_ZOMBIE) ? "zomb:" : "", 1614 (strokep->type == ATP_STROKE_TOUCH) ? '[' : '<', 1615 strokep->components[X].loc, 1616 strokep->components[X].delta_mickeys, 1617 strokep->components[X].cum_pressure, 1618 strokep->components[X].max_cum_pressure, 1619 (strokep->type == ATP_STROKE_TOUCH) ? ']' : '>', 1620 (strokep->type == ATP_STROKE_TOUCH) ? '[' : '<', 1621 strokep->components[Y].loc, 1622 strokep->components[Y].delta_mickeys, 1623 strokep->components[Y].cum_pressure, 1624 strokep->components[Y].max_cum_pressure, 1625 (strokep->type == ATP_STROKE_TOUCH) ? ']' : '>'); 1626 } 1627 if (TAILQ_FIRST(&sc->sc_stroke_used) != NULL) 1628 printf("\n"); 1629 } 1630#endif /* USB_DEBUG */ 1631 return (movement); 1632} 1633 1634/* 1635 * Update strokes by matching against current pressure-spans. 1636 * Return true if any movement is detected. 1637 */ 1638static boolean_t 1639wsp_update_strokes(struct atp_softc *sc, wsp_finger_t *fingers, u_int n_fingers) 1640{ 1641 boolean_t movement = false; 1642 atp_stroke_t *strokep_next; 1643 atp_stroke_t *strokep; 1644 u_int i; 1645 1646 if (sc->sc_n_strokes > 0) { 1647 movement = wsp_match_strokes_against_fingers( 1648 sc, fingers, n_fingers); 1649 1650 /* handle zombie strokes */ 1651 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) { 1652 if (strokep->matched) 1653 continue; 1654 atp_terminate_stroke(sc, strokep); 1655 } 1656 } 1657 1658 /* initialize unmatched fingers as strokes */ 1659 for (i = 0; i != n_fingers; i++) { 1660 if (fingers[i].matched) 1661 continue; 1662 1663 wsp_add_stroke(sc, fingers + i); 1664 } 1665 return (movement); 1666} 1667 1668/* Initialize a stroke using a pressure-span. */ 1669static void 1670fg_add_stroke(struct atp_softc *sc, const fg_pspan *pspan_x, 1671 const fg_pspan *pspan_y) 1672{ 1673 atp_stroke_t *strokep; 1674 1675 strokep = atp_alloc_stroke(sc); 1676 if (strokep == NULL) 1677 return; 1678 1679 /* 1680 * Strokes begin as potential touches. If a stroke survives 1681 * longer than a threshold, or if it records significant 1682 * cumulative movement, then it is considered a 'slide'. 1683 */ 1684 strokep->type = ATP_STROKE_TOUCH; 1685 strokep->matched = false; 1686 microtime(&strokep->ctime); 1687 strokep->age = 1; /* number of interrupts */ 1688 strokep->x = pspan_x->loc; 1689 strokep->y = pspan_y->loc; 1690 1691 strokep->components[X].loc = pspan_x->loc; 1692 strokep->components[X].cum_pressure = pspan_x->cum; 1693 strokep->components[X].max_cum_pressure = pspan_x->cum; 1694 strokep->components[X].matched = true; 1695 1696 strokep->components[Y].loc = pspan_y->loc; 1697 strokep->components[Y].cum_pressure = pspan_y->cum; 1698 strokep->components[Y].max_cum_pressure = pspan_y->cum; 1699 strokep->components[Y].matched = true; 1700 1701 if (sc->sc_n_strokes > 1) { 1702 /* Reset double-tap-n-drag if we have more than one strokes. */ 1703 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; 1704 } 1705 1706 DPRINTFN(ATP_LLEVEL_INFO, "[%u,%u], time: %u,%ld\n", 1707 strokep->components[X].loc, 1708 strokep->components[Y].loc, 1709 (u_int)strokep->ctime.tv_sec, 1710 (unsigned long int)strokep->ctime.tv_usec); 1711} 1712 1713static void 1714fg_add_new_strokes(struct atp_softc *sc, fg_pspan *pspans_x, 1715 u_int n_xpspans, fg_pspan *pspans_y, u_int n_ypspans) 1716{ 1717 fg_pspan spans[2][FG_MAX_PSPANS_PER_AXIS]; 1718 u_int nspans[2]; 1719 u_int i; 1720 u_int j; 1721 1722 /* Copy unmatched pspans into the local arrays. */ 1723 for (i = 0, nspans[X] = 0; i < n_xpspans; i++) { 1724 if (pspans_x[i].matched == false) { 1725 spans[X][nspans[X]] = pspans_x[i]; 1726 nspans[X]++; 1727 } 1728 } 1729 for (j = 0, nspans[Y] = 0; j < n_ypspans; j++) { 1730 if (pspans_y[j].matched == false) { 1731 spans[Y][nspans[Y]] = pspans_y[j]; 1732 nspans[Y]++; 1733 } 1734 } 1735 1736 if (nspans[X] == nspans[Y]) { 1737 /* Create new strokes from pairs of unmatched pspans */ 1738 for (i = 0, j = 0; (i < nspans[X]) && (j < nspans[Y]); i++, j++) 1739 fg_add_stroke(sc, &spans[X][i], &spans[Y][j]); 1740 } else { 1741 u_int cum = 0; 1742 atp_axis repeat_axis; /* axis with multi-pspans */ 1743 u_int repeat_count; /* repeat count for the multi-pspan*/ 1744 u_int repeat_index = 0; /* index of the multi-span */ 1745 1746 repeat_axis = (nspans[X] > nspans[Y]) ? Y : X; 1747 repeat_count = abs(nspans[X] - nspans[Y]); 1748 for (i = 0; i < nspans[repeat_axis]; i++) { 1749 if (spans[repeat_axis][i].cum > cum) { 1750 repeat_index = i; 1751 cum = spans[repeat_axis][i].cum; 1752 } 1753 } 1754 1755 /* Create new strokes from pairs of unmatched pspans */ 1756 i = 0, j = 0; 1757 for (; (i < nspans[X]) && (j < nspans[Y]); i++, j++) { 1758 fg_add_stroke(sc, &spans[X][i], &spans[Y][j]); 1759 1760 /* Take care to repeat at the multi-pspan. */ 1761 if (repeat_count > 0) { 1762 if ((repeat_axis == X) && 1763 (repeat_index == i)) { 1764 i--; /* counter loop increment */ 1765 repeat_count--; 1766 } else if ((repeat_axis == Y) && 1767 (repeat_index == j)) { 1768 j--; /* counter loop increment */ 1769 repeat_count--; 1770 } 1771 } 1772 } 1773 } 1774} 1775 1776/* Initialize a stroke from an unmatched finger. */ 1777static void 1778wsp_add_stroke(struct atp_softc *sc, const wsp_finger_t *fingerp) 1779{ 1780 atp_stroke_t *strokep; 1781 1782 strokep = atp_alloc_stroke(sc); 1783 if (strokep == NULL) 1784 return; 1785 1786 /* 1787 * Strokes begin as potential touches. If a stroke survives 1788 * longer than a threshold, or if it records significant 1789 * cumulative movement, then it is considered a 'slide'. 1790 */ 1791 strokep->type = ATP_STROKE_TOUCH; 1792 strokep->matched = true; 1793 microtime(&strokep->ctime); 1794 strokep->age = 1; /* number of interrupts */ 1795 strokep->x = fingerp->x; 1796 strokep->y = fingerp->y; 1797 1798 /* Reset double-tap-n-drag if we have more than one strokes. */ 1799 if (sc->sc_n_strokes > 1) 1800 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; 1801 1802 DPRINTFN(ATP_LLEVEL_INFO, "[%d,%d]\n", strokep->x, strokep->y); 1803} 1804 1805static void 1806atp_advance_stroke_state(struct atp_softc *sc, atp_stroke_t *strokep, 1807 boolean_t *movementp) 1808{ 1809 /* Revitalize stroke if it had previously been marked as a zombie. */ 1810 if (strokep->flags & ATSF_ZOMBIE) 1811 strokep->flags &= ~ATSF_ZOMBIE; 1812 1813 strokep->age++; 1814 if (strokep->age <= atp_stroke_maturity_threshold) { 1815 /* Avoid noise from immature strokes. */ 1816 strokep->instantaneous_dx = 0; 1817 strokep->instantaneous_dy = 0; 1818 } 1819 1820 if (atp_compute_stroke_movement(strokep)) 1821 *movementp = true; 1822 1823 if (strokep->type != ATP_STROKE_TOUCH) 1824 return; 1825 1826 /* Convert touch strokes to slides upon detecting movement or age. */ 1827 if ((abs(strokep->cum_movement_x) > atp_slide_min_movement) || 1828 (abs(strokep->cum_movement_y) > atp_slide_min_movement)) 1829 atp_convert_to_slide(sc, strokep); 1830 else { 1831 /* Compute the stroke's age. */ 1832 struct timeval tdiff; 1833 getmicrotime(&tdiff); 1834 if (timevalcmp(&tdiff, &strokep->ctime, >)) { 1835 timevalsub(&tdiff, &strokep->ctime); 1836 1837 if ((tdiff.tv_sec > (atp_touch_timeout / 1000000)) || 1838 ((tdiff.tv_sec == (atp_touch_timeout / 1000000)) && 1839 (tdiff.tv_usec >= (atp_touch_timeout % 1000000)))) 1840 atp_convert_to_slide(sc, strokep); 1841 } 1842 } 1843} 1844 1845static boolean_t 1846atp_stroke_has_small_movement(const atp_stroke_t *strokep) 1847{ 1848 return (((u_int)abs(strokep->instantaneous_dx) <= 1849 atp_small_movement_threshold) && 1850 ((u_int)abs(strokep->instantaneous_dy) <= 1851 atp_small_movement_threshold)); 1852} 1853 1854/* 1855 * Accumulate instantaneous changes into the stroke's 'pending' bucket; if 1856 * the aggregate exceeds the small_movement_threshold, then retain 1857 * instantaneous changes for later. 1858 */ 1859static void 1860atp_update_pending_mickeys(atp_stroke_t *strokep) 1861{ 1862 /* accumulate instantaneous movement */ 1863 strokep->pending_dx += strokep->instantaneous_dx; 1864 strokep->pending_dy += strokep->instantaneous_dy; 1865 1866#define UPDATE_INSTANTANEOUS_AND_PENDING(I, P) \ 1867 if (abs((P)) <= atp_small_movement_threshold) \ 1868 (I) = 0; /* clobber small movement */ \ 1869 else { \ 1870 if ((I) > 0) { \ 1871 /* \ 1872 * Round up instantaneous movement to the nearest \ 1873 * ceiling. This helps preserve small mickey \ 1874 * movements from being lost in following scaling \ 1875 * operation. \ 1876 */ \ 1877 (I) = (((I) + (atp_mickeys_scale_factor - 1)) / \ 1878 atp_mickeys_scale_factor) * \ 1879 atp_mickeys_scale_factor; \ 1880 \ 1881 /* \ 1882 * Deduct the rounded mickeys from pending mickeys. \ 1883 * Note: we multiply by 2 to offset the previous \ 1884 * accumulation of instantaneous movement into \ 1885 * pending. \ 1886 */ \ 1887 (P) -= ((I) << 1); \ 1888 \ 1889 /* truncate pending to 0 if it becomes negative. */ \ 1890 (P) = imax((P), 0); \ 1891 } else { \ 1892 /* \ 1893 * Round down instantaneous movement to the nearest \ 1894 * ceiling. This helps preserve small mickey \ 1895 * movements from being lost in following scaling \ 1896 * operation. \ 1897 */ \ 1898 (I) = (((I) - (atp_mickeys_scale_factor - 1)) / \ 1899 atp_mickeys_scale_factor) * \ 1900 atp_mickeys_scale_factor; \ 1901 \ 1902 /* \ 1903 * Deduct the rounded mickeys from pending mickeys. \ 1904 * Note: we multiply by 2 to offset the previous \ 1905 * accumulation of instantaneous movement into \ 1906 * pending. \ 1907 */ \ 1908 (P) -= ((I) << 1); \ 1909 \ 1910 /* truncate pending to 0 if it becomes positive. */ \ 1911 (P) = imin((P), 0); \ 1912 } \ 1913 } 1914 1915 UPDATE_INSTANTANEOUS_AND_PENDING(strokep->instantaneous_dx, 1916 strokep->pending_dx); 1917 UPDATE_INSTANTANEOUS_AND_PENDING(strokep->instantaneous_dy, 1918 strokep->pending_dy); 1919} 1920 1921/* 1922 * Compute a smoothened value for the stroke's movement from 1923 * instantaneous changes in the X and Y components. 1924 */ 1925static boolean_t 1926atp_compute_stroke_movement(atp_stroke_t *strokep) 1927{ 1928 /* 1929 * Short movements are added first to the 'pending' bucket, 1930 * and then acted upon only when their aggregate exceeds a 1931 * threshold. This has the effect of filtering away movement 1932 * noise. 1933 */ 1934 if (atp_stroke_has_small_movement(strokep)) 1935 atp_update_pending_mickeys(strokep); 1936 else { /* large movement */ 1937 /* clear away any pending mickeys if there are large movements*/ 1938 strokep->pending_dx = 0; 1939 strokep->pending_dy = 0; 1940 } 1941 1942 /* scale movement */ 1943 strokep->movement_dx = (strokep->instantaneous_dx) / 1944 (int)atp_mickeys_scale_factor; 1945 strokep->movement_dy = (strokep->instantaneous_dy) / 1946 (int)atp_mickeys_scale_factor; 1947 1948 if ((abs(strokep->instantaneous_dx) >= ATP_FAST_MOVEMENT_TRESHOLD) || 1949 (abs(strokep->instantaneous_dy) >= ATP_FAST_MOVEMENT_TRESHOLD)) { 1950 strokep->movement_dx <<= 1; 1951 strokep->movement_dy <<= 1; 1952 } 1953 1954 strokep->cum_movement_x += strokep->movement_dx; 1955 strokep->cum_movement_y += strokep->movement_dy; 1956 1957 return ((strokep->movement_dx != 0) || (strokep->movement_dy != 0)); 1958} 1959 1960/* 1961 * Terminate a stroke. Aside from immature strokes, a slide or touch is 1962 * retained as a zombies so as to reap all their termination siblings 1963 * together; this helps establish the number of fingers involved at the 1964 * end of a multi-touch gesture. 1965 */ 1966static void 1967atp_terminate_stroke(struct atp_softc *sc, atp_stroke_t *strokep) 1968{ 1969 if (strokep->flags & ATSF_ZOMBIE) 1970 return; 1971 1972 /* Drop immature strokes rightaway. */ 1973 if (strokep->age <= atp_stroke_maturity_threshold) { 1974 atp_free_stroke(sc, strokep); 1975 return; 1976 } 1977 1978 strokep->flags |= ATSF_ZOMBIE; 1979 sc->sc_state |= ATP_ZOMBIES_EXIST; 1980 1981 callout_reset(&sc->sc_callout, ATP_ZOMBIE_STROKE_REAP_INTERVAL, 1982 atp_reap_sibling_zombies, sc); 1983 1984 /* 1985 * Reset the double-click-n-drag at the termination of any 1986 * slide stroke. 1987 */ 1988 if (strokep->type == ATP_STROKE_SLIDE) 1989 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; 1990} 1991 1992static boolean_t 1993atp_is_horizontal_scroll(const atp_stroke_t *strokep) 1994{ 1995 if (abs(strokep->cum_movement_x) < atp_slide_min_movement) 1996 return (false); 1997 if (strokep->cum_movement_y == 0) 1998 return (true); 1999 return (abs(strokep->cum_movement_x / strokep->cum_movement_y) >= 4); 2000} 2001 2002static boolean_t 2003atp_is_vertical_scroll(const atp_stroke_t *strokep) 2004{ 2005 if (abs(strokep->cum_movement_y) < atp_slide_min_movement) 2006 return (false); 2007 if (strokep->cum_movement_x == 0) 2008 return (true); 2009 return (abs(strokep->cum_movement_y / strokep->cum_movement_x) >= 4); 2010} 2011 2012static void 2013atp_reap_sibling_zombies(void *arg) 2014{ 2015 struct atp_softc *sc = (struct atp_softc *)arg; 2016 u_int8_t n_touches_reaped = 0; 2017 u_int8_t n_slides_reaped = 0; 2018 u_int8_t n_horizontal_scrolls = 0; 2019 u_int8_t n_vertical_scrolls = 0; 2020 int horizontal_scroll = 0; 2021 int vertical_scroll = 0; 2022 atp_stroke_t *strokep; 2023 atp_stroke_t *strokep_next; 2024 2025 DPRINTFN(ATP_LLEVEL_INFO, "\n"); 2026 2027 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) { 2028 if ((strokep->flags & ATSF_ZOMBIE) == 0) 2029 continue; 2030 2031 if (strokep->type == ATP_STROKE_TOUCH) { 2032 n_touches_reaped++; 2033 } else { 2034 n_slides_reaped++; 2035 2036 if (atp_is_horizontal_scroll(strokep)) { 2037 n_horizontal_scrolls++; 2038 horizontal_scroll += strokep->cum_movement_x; 2039 } else if (atp_is_vertical_scroll(strokep)) { 2040 n_vertical_scrolls++; 2041 vertical_scroll += strokep->cum_movement_y; 2042 } 2043 } 2044 2045 atp_free_stroke(sc, strokep); 2046 } 2047 2048 DPRINTFN(ATP_LLEVEL_INFO, "reaped %u zombies\n", 2049 n_touches_reaped + n_slides_reaped); 2050 sc->sc_state &= ~ATP_ZOMBIES_EXIST; 2051 2052 /* No further processing necessary if physical button is depressed. */ 2053 if (sc->sc_ibtn != 0) 2054 return; 2055 2056 if ((n_touches_reaped == 0) && (n_slides_reaped == 0)) 2057 return; 2058 2059 /* Add a pair of virtual button events (button-down and button-up) if 2060 * the physical button isn't pressed. */ 2061 if (n_touches_reaped != 0) { 2062 if (n_touches_reaped < atp_tap_minimum) 2063 return; 2064 2065 switch (n_touches_reaped) { 2066 case 1: 2067 atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN); 2068 microtime(&sc->sc_touch_reap_time); /* remember this time */ 2069 break; 2070 case 2: 2071 atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON3DOWN); 2072 break; 2073 case 3: 2074 atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON2DOWN); 2075 break; 2076 default: 2077 /* we handle taps of only up to 3 fingers */ 2078 break; 2079 } 2080 atp_add_to_queue(sc, 0, 0, 0, 0); /* button release */ 2081 2082 } else if (n_slides_reaped == 2) { 2083 if (n_horizontal_scrolls == 2) { 2084 if (horizontal_scroll < 0) 2085 atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON4DOWN); 2086 else 2087 atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON5DOWN); 2088 atp_add_to_queue(sc, 0, 0, 0, 0); /* button release */ 2089 } 2090 } 2091} 2092 2093/* Switch a given touch stroke to being a slide. */ 2094static void 2095atp_convert_to_slide(struct atp_softc *sc, atp_stroke_t *strokep) 2096{ 2097 strokep->type = ATP_STROKE_SLIDE; 2098 2099 /* Are we at the beginning of a double-click-n-drag? */ 2100 if ((sc->sc_n_strokes == 1) && 2101 ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) && 2102 timevalcmp(&strokep->ctime, &sc->sc_touch_reap_time, >)) { 2103 struct timeval delta; 2104 struct timeval window = { 2105 atp_double_tap_threshold / 1000000, 2106 atp_double_tap_threshold % 1000000 2107 }; 2108 2109 delta = strokep->ctime; 2110 timevalsub(&delta, &sc->sc_touch_reap_time); 2111 if (timevalcmp(&delta, &window, <=)) 2112 sc->sc_state |= ATP_DOUBLE_TAP_DRAG; 2113 } 2114} 2115 2116static void 2117atp_reset_buf(struct atp_softc *sc) 2118{ 2119 /* reset read queue */ 2120 usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]); 2121} 2122 2123static void 2124atp_add_to_queue(struct atp_softc *sc, int dx, int dy, int dz, 2125 uint32_t buttons_in) 2126{ 2127 uint32_t buttons_out; 2128 uint8_t buf[8]; 2129 2130 dx = imin(dx, 254); dx = imax(dx, -256); 2131 dy = imin(dy, 254); dy = imax(dy, -256); 2132 dz = imin(dz, 126); dz = imax(dz, -128); 2133 2134 buttons_out = MOUSE_MSC_BUTTONS; 2135 if (buttons_in & MOUSE_BUTTON1DOWN) 2136 buttons_out &= ~MOUSE_MSC_BUTTON1UP; 2137 else if (buttons_in & MOUSE_BUTTON2DOWN) 2138 buttons_out &= ~MOUSE_MSC_BUTTON2UP; 2139 else if (buttons_in & MOUSE_BUTTON3DOWN) 2140 buttons_out &= ~MOUSE_MSC_BUTTON3UP; 2141 2142 DPRINTFN(ATP_LLEVEL_INFO, "dx=%d, dy=%d, buttons=%x\n", 2143 dx, dy, buttons_out); 2144 2145 /* Encode the mouse data in standard format; refer to mouse(4) */ 2146 buf[0] = sc->sc_mode.syncmask[1]; 2147 buf[0] |= buttons_out; 2148 buf[1] = dx >> 1; 2149 buf[2] = dy >> 1; 2150 buf[3] = dx - (dx >> 1); 2151 buf[4] = dy - (dy >> 1); 2152 /* Encode extra bytes for level 1 */ 2153 if (sc->sc_mode.level == 1) { 2154 buf[5] = dz >> 1; 2155 buf[6] = dz - (dz >> 1); 2156 buf[7] = (((~buttons_in) >> 3) & MOUSE_SYS_EXTBUTTONS); 2157 } 2158 2159 usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf, 2160 sc->sc_mode.packetsize, 1); 2161} 2162 2163static int 2164atp_probe(device_t self) 2165{ 2166 struct usb_attach_arg *uaa = device_get_ivars(self); 2167 2168 if (uaa->usb_mode != USB_MODE_HOST) 2169 return (ENXIO); 2170 2171 if (uaa->info.bInterfaceClass != UICLASS_HID) 2172 return (ENXIO); 2173 /* 2174 * Note: for some reason, the check 2175 * (uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) doesn't hold true 2176 * for wellspring trackpads, so we've removed it from the common path. 2177 */ 2178 2179 if ((usbd_lookup_id_by_uaa(fg_devs, sizeof(fg_devs), uaa)) == 0) 2180 return ((uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) ? 2181 0 : ENXIO); 2182 2183 if ((usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa)) == 0) 2184 if (uaa->info.bIfaceIndex == WELLSPRING_INTERFACE_INDEX) 2185 return (0); 2186 2187 return (ENXIO); 2188} 2189 2190static int 2191atp_attach(device_t dev) 2192{ 2193 struct atp_softc *sc = device_get_softc(dev); 2194 struct usb_attach_arg *uaa = device_get_ivars(dev); 2195 usb_error_t err; 2196 void *descriptor_ptr = NULL; 2197 uint16_t descriptor_len; 2198 unsigned long di; 2199 2200 DPRINTFN(ATP_LLEVEL_INFO, "sc=%p\n", sc); 2201 2202 sc->sc_dev = dev; 2203 sc->sc_usb_device = uaa->device; 2204 2205 /* Get HID descriptor */ 2206 if (usbd_req_get_hid_desc(uaa->device, NULL, &descriptor_ptr, 2207 &descriptor_len, M_TEMP, uaa->info.bIfaceIndex) != 2208 USB_ERR_NORMAL_COMPLETION) 2209 return (ENXIO); 2210 2211 /* Get HID report descriptor length */ 2212 sc->sc_expected_sensor_data_len = hid_report_size(descriptor_ptr, 2213 descriptor_len, hid_input, NULL); 2214 free(descriptor_ptr, M_TEMP); 2215 2216 if ((sc->sc_expected_sensor_data_len <= 0) || 2217 (sc->sc_expected_sensor_data_len > ATP_SENSOR_DATA_BUF_MAX)) { 2218 DPRINTF("atp_attach: datalength invalid or too large: %d\n", 2219 sc->sc_expected_sensor_data_len); 2220 return (ENXIO); 2221 } 2222 2223 /* 2224 * By default the touchpad behaves like an HID device, sending 2225 * packets with reportID = 2. Such reports contain only 2226 * limited information--they encode movement deltas and button 2227 * events,--but do not include data from the pressure 2228 * sensors. The device input mode can be switched from HID 2229 * reports to raw sensor data using vendor-specific USB 2230 * control commands. 2231 */ 2232 if ((err = atp_set_device_mode(sc, RAW_SENSOR_MODE)) != 0) { 2233 DPRINTF("failed to set mode to 'RAW_SENSOR' (%d)\n", err); 2234 return (ENXIO); 2235 } 2236 2237 mtx_init(&sc->sc_mutex, "atpmtx", NULL, MTX_DEF | MTX_RECURSE); 2238 2239 di = USB_GET_DRIVER_INFO(uaa); 2240 2241 sc->sc_family = DECODE_FAMILY_FROM_DRIVER_INFO(di); 2242 2243 switch(sc->sc_family) { 2244 case TRACKPAD_FAMILY_FOUNTAIN_GEYSER: 2245 sc->sc_params = 2246 &fg_dev_params[DECODE_PRODUCT_FROM_DRIVER_INFO(di)]; 2247 sc->sensor_data_interpreter = fg_interpret_sensor_data; 2248 break; 2249 case TRACKPAD_FAMILY_WELLSPRING: 2250 sc->sc_params = 2251 &wsp_dev_params[DECODE_PRODUCT_FROM_DRIVER_INFO(di)]; 2252 sc->sensor_data_interpreter = wsp_interpret_sensor_data; 2253 break; 2254 default: 2255 goto detach; 2256 } 2257 2258 err = usbd_transfer_setup(uaa->device, 2259 &uaa->info.bIfaceIndex, sc->sc_xfer, atp_xfer_config, 2260 ATP_N_TRANSFER, sc, &sc->sc_mutex); 2261 if (err) { 2262 DPRINTF("error=%s\n", usbd_errstr(err)); 2263 goto detach; 2264 } 2265 2266 if (usb_fifo_attach(sc->sc_usb_device, sc, &sc->sc_mutex, 2267 &atp_fifo_methods, &sc->sc_fifo, 2268 device_get_unit(dev), -1, uaa->info.bIfaceIndex, 2269 UID_ROOT, GID_OPERATOR, 0644)) { 2270 goto detach; 2271 } 2272 2273 device_set_usb_desc(dev); 2274 2275 sc->sc_hw.buttons = 3; 2276 sc->sc_hw.iftype = MOUSE_IF_USB; 2277 sc->sc_hw.type = MOUSE_PAD; 2278 sc->sc_hw.model = MOUSE_MODEL_GENERIC; 2279 sc->sc_hw.hwid = 0; 2280 sc->sc_mode.protocol = MOUSE_PROTO_MSC; 2281 sc->sc_mode.rate = -1; 2282 sc->sc_mode.resolution = MOUSE_RES_UNKNOWN; 2283 sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; 2284 sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; 2285 sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; 2286 sc->sc_mode.accelfactor = 0; 2287 sc->sc_mode.level = 0; 2288 2289 sc->sc_state = 0; 2290 sc->sc_ibtn = 0; 2291 2292 callout_init_mtx(&sc->sc_callout, &sc->sc_mutex, 0); 2293 2294 return (0); 2295 2296detach: 2297 atp_detach(dev); 2298 return (ENOMEM); 2299} 2300 2301static int 2302atp_detach(device_t dev) 2303{ 2304 struct atp_softc *sc; 2305 2306 sc = device_get_softc(dev); 2307 atp_set_device_mode(sc, HID_MODE); 2308 2309 mtx_lock(&sc->sc_mutex); 2310 callout_drain(&sc->sc_callout); 2311 if (sc->sc_state & ATP_ENABLED) 2312 atp_disable(sc); 2313 mtx_unlock(&sc->sc_mutex); 2314 2315 usb_fifo_detach(&sc->sc_fifo); 2316 2317 usbd_transfer_unsetup(sc->sc_xfer, ATP_N_TRANSFER); 2318 2319 mtx_destroy(&sc->sc_mutex); 2320 2321 return (0); 2322} 2323 2324static void 2325atp_intr(struct usb_xfer *xfer, usb_error_t error) 2326{ 2327 struct atp_softc *sc = usbd_xfer_softc(xfer); 2328 struct usb_page_cache *pc; 2329 int len; 2330 2331 usbd_xfer_status(xfer, &len, NULL, NULL, NULL); 2332 2333 switch (USB_GET_STATE(xfer)) { 2334 case USB_ST_TRANSFERRED: 2335 pc = usbd_xfer_get_frame(xfer, 0); 2336 usbd_copy_out(pc, 0, sc->sc_sensor_data, len); 2337 if (len < sc->sc_expected_sensor_data_len) { 2338 /* make sure we don't process old data */ 2339 memset(sc->sc_sensor_data + len, 0, 2340 sc->sc_expected_sensor_data_len - len); 2341 } 2342 2343 sc->sc_status.flags &= ~(MOUSE_STDBUTTONSCHANGED | 2344 MOUSE_POSCHANGED); 2345 sc->sc_status.obutton = sc->sc_status.button; 2346 2347 (sc->sensor_data_interpreter)(sc, len); 2348 2349 if (sc->sc_status.button != 0) { 2350 /* Reset DOUBLE_TAP_N_DRAG if the button is pressed. */ 2351 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; 2352 } else if (sc->sc_state & ATP_DOUBLE_TAP_DRAG) { 2353 /* Assume a button-press with DOUBLE_TAP_N_DRAG. */ 2354 sc->sc_status.button = MOUSE_BUTTON1DOWN; 2355 } 2356 2357 sc->sc_status.flags |= 2358 sc->sc_status.button ^ sc->sc_status.obutton; 2359 if (sc->sc_status.flags & MOUSE_STDBUTTONSCHANGED) { 2360 DPRINTFN(ATP_LLEVEL_INFO, "button %s\n", 2361 ((sc->sc_status.button & MOUSE_BUTTON1DOWN) ? 2362 "pressed" : "released")); 2363 } 2364 2365 if (sc->sc_status.flags & (MOUSE_POSCHANGED | 2366 MOUSE_STDBUTTONSCHANGED)) { 2367 2368 atp_stroke_t *strokep; 2369 u_int8_t n_movements = 0; 2370 int dx = 0; 2371 int dy = 0; 2372 2373 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { 2374 dx += strokep->movement_dx; 2375 dy += strokep->movement_dy; 2376 if (strokep->movement_dx || 2377 strokep->movement_dy) 2378 n_movements++; 2379 } 2380 2381 /* average movement if multiple strokes record motion.*/ 2382 if (n_movements > 1) { 2383 dx /= (int)n_movements; 2384 dy /= (int)n_movements; 2385 } 2386 2387 sc->sc_status.dx += dx; 2388 sc->sc_status.dy += dy; 2389 atp_add_to_queue(sc, dx, -dy, 0, sc->sc_status.button); 2390 } 2391 2392 case USB_ST_SETUP: 2393 tr_setup: 2394 /* check if we can put more data into the FIFO */ 2395 if (usb_fifo_put_bytes_max(sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { 2396 usbd_xfer_set_frame_len(xfer, 0, 2397 sc->sc_expected_sensor_data_len); 2398 usbd_transfer_submit(xfer); 2399 } 2400 break; 2401 2402 default: /* Error */ 2403 if (error != USB_ERR_CANCELLED) { 2404 /* try clear stall first */ 2405 usbd_xfer_set_stall(xfer); 2406 goto tr_setup; 2407 } 2408 break; 2409 } 2410} 2411 2412static void 2413atp_start_read(struct usb_fifo *fifo) 2414{ 2415 struct atp_softc *sc = usb_fifo_softc(fifo); 2416 int rate; 2417 2418 /* Check if we should override the default polling interval */ 2419 rate = sc->sc_pollrate; 2420 /* Range check rate */ 2421 if (rate > 1000) 2422 rate = 1000; 2423 /* Check for set rate */ 2424 if ((rate > 0) && (sc->sc_xfer[ATP_INTR_DT] != NULL)) { 2425 /* Stop current transfer, if any */ 2426 usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]); 2427 /* Set new interval */ 2428 usbd_xfer_set_interval(sc->sc_xfer[ATP_INTR_DT], 1000 / rate); 2429 /* Only set pollrate once */ 2430 sc->sc_pollrate = 0; 2431 } 2432 2433 usbd_transfer_start(sc->sc_xfer[ATP_INTR_DT]); 2434} 2435 2436static void 2437atp_stop_read(struct usb_fifo *fifo) 2438{ 2439 struct atp_softc *sc = usb_fifo_softc(fifo); 2440 usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]); 2441} 2442 2443static int 2444atp_open(struct usb_fifo *fifo, int fflags) 2445{ 2446 struct atp_softc *sc = usb_fifo_softc(fifo); 2447 2448 /* check for duplicate open, should not happen */ 2449 if (sc->sc_fflags & fflags) 2450 return (EBUSY); 2451 2452 /* check for first open */ 2453 if (sc->sc_fflags == 0) { 2454 int rc; 2455 if ((rc = atp_enable(sc)) != 0) 2456 return (rc); 2457 } 2458 2459 if (fflags & FREAD) { 2460 if (usb_fifo_alloc_buffer(fifo, 2461 ATP_FIFO_BUF_SIZE, ATP_FIFO_QUEUE_MAXLEN)) { 2462 return (ENOMEM); 2463 } 2464 } 2465 2466 sc->sc_fflags |= (fflags & (FREAD | FWRITE)); 2467 return (0); 2468} 2469 2470static void 2471atp_close(struct usb_fifo *fifo, int fflags) 2472{ 2473 struct atp_softc *sc = usb_fifo_softc(fifo); 2474 if (fflags & FREAD) 2475 usb_fifo_free_buffer(fifo); 2476 2477 sc->sc_fflags &= ~(fflags & (FREAD | FWRITE)); 2478 if (sc->sc_fflags == 0) { 2479 atp_disable(sc); 2480 } 2481} 2482 2483static int 2484atp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags) 2485{ 2486 struct atp_softc *sc = usb_fifo_softc(fifo); 2487 mousemode_t mode; 2488 int error = 0; 2489 2490 mtx_lock(&sc->sc_mutex); 2491 2492 switch(cmd) { 2493 case MOUSE_GETHWINFO: 2494 *(mousehw_t *)addr = sc->sc_hw; 2495 break; 2496 case MOUSE_GETMODE: 2497 *(mousemode_t *)addr = sc->sc_mode; 2498 break; 2499 case MOUSE_SETMODE: 2500 mode = *(mousemode_t *)addr; 2501 2502 if (mode.level == -1) 2503 /* Don't change the current setting */ 2504 ; 2505 else if ((mode.level < 0) || (mode.level > 1)) { 2506 error = EINVAL; 2507 break; 2508 } 2509 sc->sc_mode.level = mode.level; 2510 sc->sc_pollrate = mode.rate; 2511 sc->sc_hw.buttons = 3; 2512 2513 if (sc->sc_mode.level == 0) { 2514 sc->sc_mode.protocol = MOUSE_PROTO_MSC; 2515 sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; 2516 sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; 2517 sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; 2518 } else if (sc->sc_mode.level == 1) { 2519 sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE; 2520 sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE; 2521 sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK; 2522 sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC; 2523 } 2524 atp_reset_buf(sc); 2525 break; 2526 case MOUSE_GETLEVEL: 2527 *(int *)addr = sc->sc_mode.level; 2528 break; 2529 case MOUSE_SETLEVEL: 2530 if ((*(int *)addr < 0) || (*(int *)addr > 1)) { 2531 error = EINVAL; 2532 break; 2533 } 2534 sc->sc_mode.level = *(int *)addr; 2535 sc->sc_hw.buttons = 3; 2536 2537 if (sc->sc_mode.level == 0) { 2538 sc->sc_mode.protocol = MOUSE_PROTO_MSC; 2539 sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; 2540 sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; 2541 sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; 2542 } else if (sc->sc_mode.level == 1) { 2543 sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE; 2544 sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE; 2545 sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK; 2546 sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC; 2547 } 2548 atp_reset_buf(sc); 2549 break; 2550 case MOUSE_GETSTATUS: { 2551 mousestatus_t *status = (mousestatus_t *)addr; 2552 2553 *status = sc->sc_status; 2554 sc->sc_status.obutton = sc->sc_status.button; 2555 sc->sc_status.button = 0; 2556 sc->sc_status.dx = 0; 2557 sc->sc_status.dy = 0; 2558 sc->sc_status.dz = 0; 2559 2560 if (status->dx || status->dy || status->dz) 2561 status->flags |= MOUSE_POSCHANGED; 2562 if (status->button != status->obutton) 2563 status->flags |= MOUSE_BUTTONSCHANGED; 2564 break; 2565 } 2566 2567 default: 2568 error = ENOTTY; 2569 break; 2570 } 2571 2572 mtx_unlock(&sc->sc_mutex); 2573 return (error); 2574} 2575 2576static int 2577atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS) 2578{ 2579 int error; 2580 u_int tmp; 2581 2582 tmp = atp_mickeys_scale_factor; 2583 error = sysctl_handle_int(oidp, &tmp, 0, req); 2584 if (error != 0 || req->newptr == NULL) 2585 return (error); 2586 2587 if (tmp == atp_mickeys_scale_factor) 2588 return (0); /* no change */ 2589 if ((tmp == 0) || (tmp > (10 * ATP_SCALE_FACTOR))) 2590 return (EINVAL); 2591 2592 atp_mickeys_scale_factor = tmp; 2593 DPRINTFN(ATP_LLEVEL_INFO, "%s: resetting mickeys_scale_factor to %u\n", 2594 ATP_DRIVER_NAME, tmp); 2595 2596 return (0); 2597} 2598 2599static devclass_t atp_devclass; 2600 2601static device_method_t atp_methods[] = { 2602 DEVMETHOD(device_probe, atp_probe), 2603 DEVMETHOD(device_attach, atp_attach), 2604 DEVMETHOD(device_detach, atp_detach), 2605 2606 DEVMETHOD_END 2607}; 2608 2609static driver_t atp_driver = { 2610 .name = ATP_DRIVER_NAME, 2611 .methods = atp_methods, 2612 .size = sizeof(struct atp_softc) 2613}; 2614 2615DRIVER_MODULE(atp, uhub, atp_driver, atp_devclass, NULL, 0); 2616MODULE_DEPEND(atp, usb, 1, 1, 1); 2617MODULE_VERSION(atp, 1); 2618