1 /*- 2 * Copyright (c) 1992, 1993 Erik Forsberg. 3 * Copyright (c) 1996, 1997 Kazutaka YOKOTA. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED 13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 15 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 */ 23 /* 24 * Ported to 386bsd Oct 17, 1992 25 * Sandi Donno, Computer Science, University of Cape Town, South Africa 26 * Please send bug reports to sandi@cs.uct.ac.za 27 * 28 * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca - 29 * although I was only partially successful in getting the alpha release 30 * of his "driver for the Logitech and ATI Inport Bus mice for use with 31 * 386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless 32 * found his code to be an invaluable reference when porting this driver 33 * to 386bsd. 34 * 35 * Further modifications for latest 386BSD+patchkit and port to NetBSD, 36 * Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993 37 * 38 * Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by 39 * Andrew Herbert - 12 June 1993 40 * 41 * Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu> 42 * - 13 June 1993 43 * 44 * Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp> 45 * - 24 October 1993 46 * 47 * Hardware access routines and probe logic rewritten by 48 * Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp> 49 * - 3, 14, 22 October 1996. 50 * - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'... 51 * - 14, 30 November 1996. Uses `kbdio.c'. 52 * - 13 December 1996. Uses queuing version of `kbdio.c'. 53 * - January/February 1997. Tweaked probe logic for 54 * HiNote UltraII/Latitude/Armada laptops. 55 * - 30 July 1997. Added APM support. 56 * - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX). 57 * Improved sync check logic. 58 * Vendor specific support routines. 59 * 60 * $FreeBSD: src/sys/dev/atkbdc/psm.c,v 1.107 2010/09/09 07:52:15 ed Exp $ 61 * $FreeBSD: stable/11/sys/dev/atkbdc/psm.c 307576 2016-10-18 20:17:57Z gonzo $ 62 */ 63 64 #include "opt_psm.h" 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #include <sys/kernel.h> 69 #include <sys/module.h> 70 #include <sys/bus.h> 71 #include <sys/conf.h> 72 #include <sys/device.h> 73 #include <sys/event.h> 74 #include <sys/syslog.h> 75 #include <sys/malloc.h> 76 #include <sys/rman.h> 77 #include <sys/sysctl.h> 78 #include <sys/thread2.h> 79 #include <sys/time.h> 80 #include <sys/uio.h> 81 #include <sys/machintr.h> 82 #include <sys/vnode.h> 83 84 #include <machine/clock.h> 85 #include <machine/limits.h> 86 #include <sys/mouse.h> 87 88 #include <bus/isa/isavar.h> 89 #include <dev/misc/kbd/atkbdcreg.h> 90 91 #include <sys/signalvar.h> 92 #include <sys/filio.h> 93 94 95 /* 96 * Driver specific options: the following options may be set by 97 * `options' statements in the kernel configuration file. 98 */ 99 100 /* debugging */ 101 #ifndef PSM_DEBUG 102 #define PSM_DEBUG 0 /* 103 * logging: 0: none, 1: brief, 2: verbose 104 * 3: sync errors, 4: all packets 105 */ 106 #endif 107 #define VLOG(level, args) do { \ 108 if (verbose >= level) \ 109 log args; \ 110 } while (0) 111 112 #ifndef PSM_INPUT_TIMEOUT 113 #define PSM_INPUT_TIMEOUT 2000000 /* 2 sec */ 114 #endif 115 116 #ifndef PSM_TAP_TIMEOUT 117 #define PSM_TAP_TIMEOUT 125000 118 #endif 119 120 #ifndef PSM_TAP_THRESHOLD 121 #define PSM_TAP_THRESHOLD 25 122 #endif 123 124 /* end of driver specific options */ 125 126 #define PSM_DRIVER_NAME "psm" 127 #define PSMCPNP_DRIVER_NAME "psmcpnp" 128 129 /* input queue */ 130 #define PSM_BUFSIZE 960 131 #define PSM_SMALLBUFSIZE 240 132 133 /* operation levels */ 134 #define PSM_LEVEL_BASE 0 135 #define PSM_LEVEL_STANDARD 1 136 #define PSM_LEVEL_MIN PSM_LEVEL_BASE 137 #define PSM_LEVEL_MAX PSM_LEVEL_STANDARD 138 139 /* Logitech PS2++ protocol */ 140 #define MOUSE_PS2PLUS_CHECKBITS(b) \ 141 ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f)) 142 #define MOUSE_PS2PLUS_PACKET_TYPE(b) \ 143 (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4)) 144 145 /* ring buffer */ 146 typedef struct ringbuf { 147 int count; /* # of valid elements in the buffer */ 148 int head; /* head pointer */ 149 int tail; /* tail poiner */ 150 u_char buf[PSM_BUFSIZE]; 151 } ringbuf_t; 152 153 /* data buffer */ 154 typedef struct packetbuf { 155 u_char ipacket[16]; /* interim input buffer */ 156 int inputbytes; /* # of bytes in the input buffer */ 157 } packetbuf_t; 158 159 #ifndef PSM_PACKETQUEUE 160 #define PSM_PACKETQUEUE 128 161 #endif 162 163 164 typedef struct synapticsinfo { 165 struct sysctl_oid *sysctl_tree; 166 struct sysctl_ctx_list sysctl_ctx; 167 int directional_scrolls; 168 int two_finger_scroll; 169 int min_pressure; 170 int max_pressure; 171 int max_width; 172 int margin_top; 173 int margin_right; 174 int margin_bottom; 175 int margin_left; 176 int na_top; 177 int na_right; 178 int na_bottom; 179 int na_left; 180 int window_min; 181 int window_max; 182 int multiplicator; 183 int weight_current; 184 int weight_previous; 185 int weight_previous_na; 186 int weight_len_squared; 187 int div_min; 188 int div_max; 189 int div_max_na; 190 int div_len; 191 int tap_max_delta; 192 int tap_min_queue; 193 int taphold_timeout; 194 int vscroll_ver_area; 195 int vscroll_hor_area; 196 int vscroll_min_delta; 197 int vscroll_div_min; 198 int vscroll_div_max; 199 int touchpad_off; 200 int softbuttons_y; 201 int softbutton2_x; 202 int softbutton3_x; 203 int max_x; 204 int max_y; 205 } synapticsinfo_t; 206 207 typedef struct synapticspacket { 208 int x; 209 int y; 210 } synapticspacket_t; 211 212 #define SYNAPTICS_PACKETQUEUE 10 213 #define SYNAPTICS_QUEUE_CURSOR(x) \ 214 (x + SYNAPTICS_PACKETQUEUE) % SYNAPTICS_PACKETQUEUE 215 216 #define SYNAPTICS_VERSION_GE(synhw, major, minor) \ 217 ((synhw).infoMajor > (major) || \ 218 ((synhw).infoMajor == (major) && (synhw).infoMinor >= (minor))) 219 220 221 222 typedef struct smoother { 223 synapticspacket_t queue[SYNAPTICS_PACKETQUEUE]; 224 int queue_len; 225 int queue_cursor; 226 int start_x; 227 int start_y; 228 int avg_dx; 229 int avg_dy; 230 int squelch_x; 231 int squelch_y; 232 int is_fuzzy; 233 int active; 234 } smoother_t; 235 236 typedef struct gesture { 237 int window_min; 238 int fingers_nb; 239 int tap_button; 240 int in_taphold; 241 int in_vscroll; 242 int zmax; /* maximum pressure value */ 243 struct timeval taptimeout; /* tap timeout for touchpads */ 244 } gesture_t; 245 246 enum { 247 TRACKPOINT_SYSCTL_SENSITIVITY, 248 TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, 249 TRACKPOINT_SYSCTL_UPPER_PLATEAU, 250 TRACKPOINT_SYSCTL_BACKUP_RANGE, 251 TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, 252 TRACKPOINT_SYSCTL_MINIMUM_DRAG, 253 TRACKPOINT_SYSCTL_UP_THRESHOLD, 254 TRACKPOINT_SYSCTL_THRESHOLD, 255 TRACKPOINT_SYSCTL_JENKS_CURVATURE, 256 TRACKPOINT_SYSCTL_Z_TIME, 257 TRACKPOINT_SYSCTL_PRESS_TO_SELECT, 258 TRACKPOINT_SYSCTL_SKIP_BACKUPS 259 }; 260 261 typedef struct trackpointinfo { 262 struct sysctl_ctx_list sysctl_ctx; 263 struct sysctl_oid *sysctl_tree; 264 int sensitivity; 265 int inertia; 266 int uplateau; 267 int reach; 268 int draghys; 269 int mindrag; 270 int upthresh; 271 int threshold; 272 int jenks; 273 int ztime; 274 int pts; 275 int skipback; 276 } trackpointinfo_t; 277 278 typedef struct finger { 279 int x; 280 int y; 281 int p; 282 int w; 283 int flags; 284 } finger_t; 285 #define PSM_FINGERS 2 /* # of processed fingers */ 286 #define PSM_FINGER_IS_PEN (1<<0) 287 #define PSM_FINGER_FUZZY (1<<1) 288 #define PSM_FINGER_DEFAULT_P tap_threshold 289 #define PSM_FINGER_DEFAULT_W 1 290 #define PSM_FINGER_IS_SET(f) ((f).x != -1 && (f).y != -1 && (f).p != 0) 291 #define PSM_FINGER_RESET(f) do { \ 292 (f) = (finger_t) { .x = -1, .y = -1, .p = 0, .w = 0, .flags = 0 }; \ 293 } while (0) 294 295 typedef struct elantechhw { 296 int hwversion; 297 int fwversion; 298 int sizex; 299 int sizey; 300 int dpmmx; 301 int dpmmy; 302 int ntracesx; 303 int ntracesy; 304 int issemimt; 305 int isclickpad; 306 int hascrc; 307 int hastrackpoint; 308 int haspressure; 309 } elantechhw_t; 310 311 /* minimum versions supported by this driver */ 312 #define ELANTECH_HW_IS_V1(fwver) ((fwver) < 0x020030 || (fwver) == 0x020600) 313 314 #define ELANTECH_MAGIC(magic) \ 315 ((magic)[0] == 0x3c && (magic)[1] == 0x03 && \ 316 ((magic)[2] == 0xc8 || (magic)[2] == 0x00)) 317 318 #define ELANTECH_FW_ID 0x00 319 #define ELANTECH_FW_VERSION 0x01 320 #define ELANTECH_CAPABILITIES 0x02 321 #define ELANTECH_SAMPLE 0x03 322 #define ELANTECH_RESOLUTION 0x04 323 #define ELANTECH_REG_READ 0x10 324 #define ELANTECH_REG_WRITE 0x11 325 #define ELANTECH_REG_RDWR 0x00 326 #define ELANTECH_CUSTOM_CMD 0xf8 327 328 #define ELANTECH_MAX_FINGERS PSM_FINGERS 329 330 #define ELANTECH_FINGER_SET_XYP(pb) (finger_t) { \ 331 .x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \ 332 .y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \ 333 .p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \ 334 .w = PSM_FINGER_DEFAULT_W, \ 335 .flags = 0 \ 336 } 337 338 enum { 339 ELANTECH_PKT_NOP, 340 ELANTECH_PKT_TRACKPOINT, 341 ELANTECH_PKT_V2_COMMON, 342 ELANTECH_PKT_V2_2FINGER, 343 ELANTECH_PKT_V3, 344 ELANTECH_PKT_V4_STATUS, 345 ELANTECH_PKT_V4_HEAD, 346 ELANTECH_PKT_V4_MOTION 347 }; 348 349 #define ELANTECH_PKT_IS_TRACKPOINT(pb) (((pb)->ipacket[3] & 0x0f) == 0x06) 350 #define ELANTECH_PKT_IS_DEBOUNCE(pb, hwversion) ((hwversion) == 4 ? 0 : \ 351 (pb)->ipacket[0] == ((hwversion) == 2 ? 0x84 : 0xc4) && \ 352 (pb)->ipacket[1] == 0xff && (pb)->ipacket[2] == 0xff && \ 353 (pb)->ipacket[3] == 0x02 && (pb)->ipacket[4] == 0xff && \ 354 (pb)->ipacket[5] == 0xff) 355 #define ELANTECH_PKT_IS_V2(pb) \ 356 (((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x0f) == 0x02) 357 #define ELANTECH_PKT_IS_V3_HEAD(pb, hascrc) ((hascrc) ? \ 358 ((pb)->ipacket[3] & 0x09) == 0x08 : \ 359 ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0xcf) == 0x02) 360 #define ELANTECH_PKT_IS_V3_TAIL(pb, hascrc) ((hascrc) ? \ 361 ((pb)->ipacket[3] & 0x09) == 0x09 : \ 362 ((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c) 363 #define ELANTECH_PKT_IS_V4(pb, hascrc) ((hascrc) ? \ 364 ((pb)->ipacket[3] & 0x08) == 0x00 : \ 365 ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10) 366 367 typedef struct elantechaction { 368 finger_t fingers[ELANTECH_MAX_FINGERS]; 369 int mask; 370 } elantechaction_t; 371 372 /* driver control block */ 373 struct psm_softc { /* Driver status information */ 374 int unit; 375 struct kqinfo rkq; /* Processes with registered kevents */ 376 struct lock lock; /* Control lock */ 377 u_char state; /* Mouse driver state */ 378 int config; /* driver configuration flags */ 379 int flags; /* other flags */ 380 KBDC kbdc; /* handle to access kbd controller */ 381 struct resource *intr; /* IRQ resource */ 382 void *ih; /* interrupt handle */ 383 mousehw_t hw; /* hardware information */ 384 synapticshw_t synhw; /* Synaptics hardware information */ 385 synapticsinfo_t syninfo; /* Synaptics configuration */ 386 smoother_t smoother[PSM_FINGERS]; /* Motion smoothing */ 387 gesture_t gesture; /* Gesture context */ 388 elantechhw_t elanhw; /* Elantech hardware information */ 389 elantechaction_t elanaction; /* Elantech action context */ 390 int tphw; /* TrackPoint hardware information */ 391 trackpointinfo_t tpinfo; /* TrackPoint configuration */ 392 mousemode_t mode; /* operation mode */ 393 mousemode_t dflt_mode; /* default operation mode */ 394 mousestatus_t status; /* accumulated mouse movement */ 395 ringbuf_t queue; /* mouse status queue */ 396 packetbuf_t pqueue[PSM_PACKETQUEUE]; /* mouse data queue */ 397 int pqueue_start; /* start of data in queue */ 398 int pqueue_end; /* end of data in queue */ 399 int button; /* the latest button state */ 400 int xold; /* previous absolute X position */ 401 int yold; /* previous absolute Y position */ 402 int xaverage; /* average X position */ 403 int yaverage; /* average Y position */ 404 int squelch; /* level to filter movement at low speed */ 405 int syncerrors; /* # of bytes discarded to synchronize */ 406 int pkterrors; /* # of packets failed during quaranteen. */ 407 struct timeval inputtimeout; 408 struct timeval lastsoftintr; /* time of last soft interrupt */ 409 struct timeval lastinputerr; /* time last sync error happened */ 410 struct timeval idletimeout; 411 packetbuf_t idlepacket; /* packet to send after idle timeout */ 412 int watchdog; /* watchdog timer flag */ 413 struct callout callout; /* watchdog timer call out */ 414 struct callout softcallout; /* buffer timer call out */ 415 struct cdev *dev; 416 int lasterr; 417 int cmdcount; 418 int extended_buttons; 419 }; 420 static devclass_t psm_devclass; 421 422 #define SYN_OFFSET(field) offsetof(struct psm_softc, syninfo.field) 423 enum { 424 SYNAPTICS_SYSCTL_MIN_PRESSURE = SYN_OFFSET(min_pressure), 425 SYNAPTICS_SYSCTL_MAX_PRESSURE = SYN_OFFSET(max_pressure), 426 SYNAPTICS_SYSCTL_MAX_WIDTH = SYN_OFFSET(max_width), 427 SYNAPTICS_SYSCTL_MARGIN_TOP = SYN_OFFSET(margin_top), 428 SYNAPTICS_SYSCTL_MARGIN_RIGHT = SYN_OFFSET(margin_right), 429 SYNAPTICS_SYSCTL_MARGIN_BOTTOM = SYN_OFFSET(margin_bottom), 430 SYNAPTICS_SYSCTL_MARGIN_LEFT = SYN_OFFSET(margin_left), 431 SYNAPTICS_SYSCTL_NA_TOP = SYN_OFFSET(na_top), 432 SYNAPTICS_SYSCTL_NA_RIGHT = SYN_OFFSET(na_right), 433 SYNAPTICS_SYSCTL_NA_BOTTOM = SYN_OFFSET(na_bottom), 434 SYNAPTICS_SYSCTL_NA_LEFT = SYN_OFFSET(na_left), 435 SYNAPTICS_SYSCTL_WINDOW_MIN = SYN_OFFSET(window_min), 436 SYNAPTICS_SYSCTL_WINDOW_MAX = SYN_OFFSET(window_max), 437 SYNAPTICS_SYSCTL_MULTIPLICATOR = SYN_OFFSET(multiplicator), 438 SYNAPTICS_SYSCTL_WEIGHT_CURRENT = SYN_OFFSET(weight_current), 439 SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS = SYN_OFFSET(weight_previous), 440 SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA = SYN_OFFSET(weight_previous_na), 441 SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED = SYN_OFFSET(weight_len_squared), 442 SYNAPTICS_SYSCTL_DIV_MIN = SYN_OFFSET(div_min), 443 SYNAPTICS_SYSCTL_DIV_MAX = SYN_OFFSET(div_max), 444 SYNAPTICS_SYSCTL_DIV_MAX_NA = SYN_OFFSET(div_max_na), 445 SYNAPTICS_SYSCTL_DIV_LEN = SYN_OFFSET(div_len), 446 SYNAPTICS_SYSCTL_TAP_MAX_DELTA = SYN_OFFSET(tap_max_delta), 447 SYNAPTICS_SYSCTL_TAP_MIN_QUEUE = SYN_OFFSET(tap_min_queue), 448 SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT = SYN_OFFSET(taphold_timeout), 449 SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA = SYN_OFFSET(vscroll_hor_area), 450 SYNAPTICS_SYSCTL_VSCROLL_VER_AREA = SYN_OFFSET(vscroll_ver_area), 451 SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA = SYN_OFFSET(vscroll_min_delta), 452 SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN = SYN_OFFSET(vscroll_div_min), 453 SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX = SYN_OFFSET(vscroll_div_max), 454 SYNAPTICS_SYSCTL_TOUCHPAD_OFF = SYN_OFFSET(touchpad_off), 455 SYNAPTICS_SYSCTL_SOFTBUTTONS_Y = SYN_OFFSET(softbuttons_y), 456 SYNAPTICS_SYSCTL_SOFTBUTTON2_X = SYN_OFFSET(softbutton2_x), 457 SYNAPTICS_SYSCTL_SOFTBUTTON3_X = SYN_OFFSET(softbutton3_x), 458 }; 459 460 /* driver state flags (state) */ 461 #define PSM_VALID 0x80 462 #define PSM_OPEN 1 /* Device is open */ 463 #define PSM_ASLP 2 /* Waiting for mouse data */ 464 #define PSM_SOFTARMED 4 /* Software interrupt armed */ 465 #define PSM_NEED_SYNCBITS 8 /* Set syncbits using next data pkt */ 466 467 /* driver configuration flags (config) */ 468 #define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ 469 #define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */ 470 #define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */ 471 #define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */ 472 #define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */ 473 #define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */ 474 #define PSM_CONFIG_IGNPORTERROR 0x1000 /* ignore error in aux port test */ 475 #define PSM_CONFIG_HOOKRESUME 0x2000 /* hook the system resume event */ 476 #define PSM_CONFIG_INITAFTERSUSPEND 0x4000 /* init the device at the resume event */ 477 478 #define PSM_CONFIG_FLAGS \ 479 (PSM_CONFIG_RESOLUTION | \ 480 PSM_CONFIG_ACCEL | \ 481 PSM_CONFIG_NOCHECKSYNC | \ 482 PSM_CONFIG_NOIDPROBE | \ 483 PSM_CONFIG_NORESET | \ 484 PSM_CONFIG_FORCETAP | \ 485 PSM_CONFIG_IGNPORTERROR | \ 486 PSM_CONFIG_HOOKRESUME | \ 487 PSM_CONFIG_INITAFTERSUSPEND) 488 489 /* other flags (flags) */ 490 #define PSM_FLAGS_FINGERDOWN 0x0001 /* VersaPad finger down */ 491 492 #define kbdcp(p) ((atkbdc_softc_t *)(p)) 493 494 /* Tunables */ 495 static int tap_enabled = -1; 496 TUNABLE_INT("hw.psm.tap_enabled", &tap_enabled); 497 498 static int synaptics_support = 0; 499 TUNABLE_INT("hw.psm.synaptics_support", &synaptics_support); 500 501 static int verbose = PSM_DEBUG; 502 TUNABLE_INT("debug.psm.loglevel", &verbose); 503 504 static int trackpoint_support = 0; 505 TUNABLE_INT("hw.psm.trackpoint_support",&trackpoint_support); 506 507 static int elantech_support = 0; 508 TUNABLE_INT("hw.psm.elantech_support",&elantech_support); 509 510 511 /* for backward compatibility */ 512 #define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t) 513 #define OLD_MOUSE_GETMODE _IOR('M', 2, old_mousemode_t) 514 #define OLD_MOUSE_SETMODE _IOW('M', 3, old_mousemode_t) 515 516 typedef struct old_mousehw { 517 int buttons; 518 int iftype; 519 int type; 520 int hwid; 521 } old_mousehw_t; 522 523 typedef struct old_mousemode { 524 int protocol; 525 int rate; 526 int resolution; 527 int accelfactor; 528 } old_mousemode_t; 529 /* packet formatting function */ 530 typedef int packetfunc_t(struct psm_softc *, u_char *, int *, int, 531 mousestatus_t *); 532 533 /* function prototypes */ 534 static void psmidentify(driver_t *, device_t); 535 static int psmprobe(device_t); 536 static int psmattach(device_t); 537 static int psmdetach(device_t); 538 static int psmresume(device_t); 539 540 static d_open_t psmopen; 541 static d_close_t psmclose; 542 static d_read_t psmread; 543 static d_ioctl_t psmioctl; 544 static d_kqfilter_t psmkqfilter; 545 546 static int enable_aux_dev(KBDC); 547 static int disable_aux_dev(KBDC); 548 static int get_mouse_status(KBDC, int *, int, int); 549 static int get_aux_id(KBDC); 550 static int set_mouse_sampling_rate(KBDC, int); 551 static int set_mouse_scaling(KBDC, int); 552 static int set_mouse_resolution(KBDC, int); 553 static int set_mouse_mode(KBDC); 554 static int get_mouse_buttons(KBDC); 555 static void recover_from_error(KBDC); 556 static int restore_controller(KBDC, int); 557 static int doinitialize(struct psm_softc *, mousemode_t *); 558 static int doopen(struct psm_softc *, int); 559 static int reinitialize(struct psm_softc *, int); 560 static char *model_name(int); 561 static void psmsoftintr(void *); 562 static void psmsoftintridle(void *); 563 static void psmintr(void *); 564 static void psmtimeout(void *); 565 static void psmfilter_detach(struct knote *); 566 static int psmfilter(struct knote *, long); 567 static int timeelapsed(const struct timeval *, int, int, 568 const struct timeval *); 569 static void dropqueue(struct psm_softc *); 570 static void flushpackets(struct psm_softc *); 571 static void proc_mmanplus(struct psm_softc *, packetbuf_t *, 572 mousestatus_t *, int *, int *, int *); 573 static int proc_synaptics(struct psm_softc *, packetbuf_t *, 574 mousestatus_t *, int *, int *, int *); 575 static void proc_versapad(struct psm_softc *, packetbuf_t *, 576 mousestatus_t *, int *, int *, int *); 577 static int proc_elantech(struct psm_softc *, packetbuf_t *, 578 mousestatus_t *, int *, int *, int *); 579 static int psmpalmdetect(struct psm_softc *, finger_t *, int); 580 static void psmgestures(struct psm_softc *, finger_t *, int, 581 mousestatus_t *); 582 static void psmsmoother(struct psm_softc *, finger_t *, int, 583 mousestatus_t *, int *, int *); 584 static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, 585 u_char *); 586 587 /* vendor specific features */ 588 enum probearg { PROBE, REINIT }; 589 typedef int probefunc_t(struct psm_softc *, enum probearg); 590 591 static int mouse_id_proc1(KBDC, int, int, int *); 592 static int mouse_ext_command(KBDC, int); 593 594 static int enable_groller(struct psm_softc *sc, enum probearg arg); 595 static int enable_gmouse(struct psm_softc *sc, enum probearg arg); 596 static int enable_aglide(struct psm_softc *sc, enum probearg arg); 597 static int enable_kmouse(struct psm_softc *sc, enum probearg arg); 598 static int enable_msexplorer(struct psm_softc *sc, enum probearg arg); 599 static int enable_msintelli(struct psm_softc *sc, enum probearg arg); 600 static int enable_4dmouse(struct psm_softc *sc, enum probearg arg); 601 static int enable_4dplus(struct psm_softc *sc, enum probearg arg); 602 static int enable_mmanplus(struct psm_softc *sc, enum probearg arg); 603 static int enable_synaptics(struct psm_softc *sc, enum probearg arg); 604 static int enable_trackpoint(struct psm_softc *sc, enum probearg arg); 605 static int enable_versapad(struct psm_softc *sc, enum probearg arg); 606 static int enable_elantech(struct psm_softc *sc, enum probearg arg); 607 608 static void set_trackpoint_parameters(struct psm_softc *sc); 609 static void synaptics_passthrough_on(struct psm_softc *sc); 610 static void synaptics_passthrough_off(struct psm_softc *sc); 611 static int synaptics_preferred_mode(struct psm_softc *sc); 612 static void synaptics_set_mode(struct psm_softc *sc, int mode_byte); 613 614 615 616 static struct { 617 int model; 618 u_char syncmask; 619 int packetsize; 620 probefunc_t *probefunc; 621 } vendortype[] = { 622 /* 623 * WARNING: the order of probe is very important. Don't mess it 624 * unless you know what you are doing. 625 */ 626 { MOUSE_MODEL_NET, /* Genius NetMouse */ 627 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_gmouse }, 628 { MOUSE_MODEL_NETSCROLL, /* Genius NetScroll */ 629 0xc8, 6, enable_groller }, 630 { MOUSE_MODEL_MOUSEMANPLUS, /* Logitech MouseMan+ */ 631 0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus }, 632 { MOUSE_MODEL_EXPLORER, /* Microsoft IntelliMouse Explorer */ 633 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msexplorer }, 634 { MOUSE_MODEL_4D, /* A4 Tech 4D Mouse */ 635 0x08, MOUSE_4D_PACKETSIZE, enable_4dmouse }, 636 { MOUSE_MODEL_4DPLUS, /* A4 Tech 4D+ Mouse */ 637 0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus }, 638 { MOUSE_MODEL_SYNAPTICS, /* Synaptics Touchpad */ 639 0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics }, 640 { MOUSE_MODEL_ELANTECH, /* Elantech Touchpad */ 641 0x04, MOUSE_ELANTECH_PACKETSIZE, enable_elantech }, 642 { MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ 643 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli }, 644 { MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ 645 0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide }, 646 { MOUSE_MODEL_THINK, /* Kensington ThinkingMouse */ 647 0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse }, 648 { MOUSE_MODEL_VERSAPAD, /* Interlink electronics VersaPad */ 649 0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad }, 650 { MOUSE_MODEL_TRACKPOINT, /* IBM/Lenovo TrackPoint */ 651 0xc0, MOUSE_PS2_PACKETSIZE, enable_trackpoint }, 652 { MOUSE_MODEL_GENERIC, 653 0xc0, MOUSE_PS2_PACKETSIZE, NULL }, 654 }; 655 #define GENERIC_MOUSE_ENTRY (NELEM(vendortype) - 1) 656 657 /* device driver declaration */ 658 static device_method_t psm_methods[] = { 659 /* Device interface */ 660 DEVMETHOD(device_identify, psmidentify), 661 DEVMETHOD(device_probe, psmprobe), 662 DEVMETHOD(device_attach, psmattach), 663 DEVMETHOD(device_detach, psmdetach), 664 DEVMETHOD(device_resume, psmresume), 665 666 DEVMETHOD_END 667 }; 668 669 static driver_t psm_driver = { 670 PSM_DRIVER_NAME, 671 psm_methods, 672 sizeof(struct psm_softc) 673 }; 674 675 static struct dev_ops psm_ops = { 676 { PSM_DRIVER_NAME, 0, 0 }, 677 .d_open = psmopen, 678 .d_close = psmclose, 679 .d_read = psmread, 680 .d_ioctl = psmioctl, 681 .d_kqfilter = psmkqfilter 682 }; 683 684 685 /* device I/O routines */ 686 static int 687 enable_aux_dev(KBDC kbdc) 688 { 689 690 int res; 691 692 res = send_aux_command(kbdc, PSMC_ENABLE_DEV); 693 VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res)); 694 695 return (res == PSM_ACK); 696 } 697 698 static int 699 disable_aux_dev(KBDC kbdc) 700 { 701 702 int res; 703 704 res = send_aux_command(kbdc, PSMC_DISABLE_DEV); 705 VLOG(2, (LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res)); 706 707 return (res == PSM_ACK); 708 } 709 710 static int 711 get_mouse_status(KBDC kbdc, int *status, int flag, int len) 712 { 713 714 int cmd; 715 int res; 716 int i; 717 718 switch (flag) { 719 case 0: 720 default: 721 cmd = PSMC_SEND_DEV_STATUS; 722 break; 723 case 1: 724 cmd = PSMC_SEND_DEV_DATA; 725 break; 726 } 727 empty_aux_buffer(kbdc, 5); 728 res = send_aux_command(kbdc, cmd); 729 VLOG(2, (LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n", 730 (flag == 1) ? "DATA" : "STATUS", res)); 731 if (res != PSM_ACK) 732 return (0); 733 734 for (i = 0; i < len; ++i) { 735 status[i] = read_aux_data(kbdc); 736 if (status[i] < 0) 737 break; 738 } 739 740 VLOG(1, (LOG_DEBUG, "psm: %s %02x %02x %02x\n", 741 (flag == 1) ? "data" : "status", status[0], status[1], status[2])); 742 743 return (i); 744 } 745 746 static int 747 get_aux_id(KBDC kbdc) 748 { 749 int id; 750 int res; 751 752 empty_aux_buffer(kbdc, 5); 753 res = send_aux_command(kbdc, PSMC_SEND_DEV_ID); 754 VLOG(2, (LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res)); 755 if (res != PSM_ACK) 756 return (-1); 757 758 /* 10ms delay */ 759 DRIVERSLEEP(10000); 760 761 id = read_aux_data(kbdc); 762 VLOG(2, (LOG_DEBUG, "psm: device ID: %04x\n", id)); 763 764 return (id); 765 } 766 767 static int 768 set_mouse_sampling_rate(KBDC kbdc, int rate) 769 { 770 771 int res; 772 773 res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate); 774 VLOG(2, (LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res)); 775 776 return ((res == PSM_ACK) ? rate : -1); 777 } 778 779 static int 780 set_mouse_scaling(KBDC kbdc, int scale) 781 { 782 783 int res; 784 785 switch (scale) { 786 case 1: 787 default: 788 scale = PSMC_SET_SCALING11; 789 break; 790 case 2: 791 scale = PSMC_SET_SCALING21; 792 break; 793 } 794 res = send_aux_command(kbdc, scale); 795 VLOG(2, (LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n", 796 (scale == PSMC_SET_SCALING21) ? "21" : "11", res)); 797 798 return (res == PSM_ACK); 799 } 800 801 /* `val' must be 0 through PSMD_MAX_RESOLUTION */ 802 static int 803 set_mouse_resolution(KBDC kbdc, int val) 804 { 805 806 int res; 807 808 res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val); 809 VLOG(2, (LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res)); 810 811 return ((res == PSM_ACK) ? val : -1); 812 } 813 814 /* 815 * NOTE: once `set_mouse_mode()' is called, the mouse device must be 816 * re-enabled by calling `enable_aux_dev()' 817 */ 818 static int 819 set_mouse_mode(KBDC kbdc) 820 { 821 822 int res; 823 824 res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE); 825 VLOG(2, (LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res)); 826 827 return (res == PSM_ACK); 828 } 829 830 static int 831 get_mouse_buttons(KBDC kbdc) 832 { 833 834 int c = 2; /* assume two buttons by default */ 835 int status[3]; 836 837 /* 838 * NOTE: a special sequence to obtain Logitech Mouse specific 839 * information: set resolution to 25 ppi, set scaling to 1:1, set 840 * scaling to 1:1, set scaling to 1:1. Then the second byte of the 841 * mouse status bytes is the number of available buttons. 842 * Some manufactures also support this sequence. 843 */ 844 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) 845 return (c); 846 if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) && 847 set_mouse_scaling(kbdc, 1) && 848 get_mouse_status(kbdc, status, 0, 3) >= 3 && status[1] != 0) 849 return (status[1]); 850 return (c); 851 } 852 853 /* misc subroutines */ 854 static char * 855 model_name(int model) 856 { 857 858 static struct { 859 int model_code; 860 char *model_name; 861 } models[] = { 862 { MOUSE_MODEL_NETSCROLL, "NetScroll" }, 863 { MOUSE_MODEL_NET, "NetMouse/NetScroll Optical" }, 864 { MOUSE_MODEL_GLIDEPOINT, "GlidePoint" }, 865 { MOUSE_MODEL_THINK, "ThinkingMouse" }, 866 { MOUSE_MODEL_INTELLI, "IntelliMouse" }, 867 { MOUSE_MODEL_MOUSEMANPLUS, "MouseMan+" }, 868 { MOUSE_MODEL_VERSAPAD, "VersaPad" }, 869 { MOUSE_MODEL_EXPLORER, "IntelliMouse Explorer" }, 870 { MOUSE_MODEL_4D, "4D Mouse" }, 871 { MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, 872 { MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, 873 { MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, 874 { MOUSE_MODEL_ELANTECH, "Elantech Touchpad" }, 875 { MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, 876 { MOUSE_MODEL_UNKNOWN, "Unknown" }, 877 }; 878 int i; 879 880 for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) 881 if (models[i].model_code == model) 882 break; 883 return (models[i].model_name); 884 } 885 886 static void 887 recover_from_error(KBDC kbdc) 888 { 889 890 /* discard anything left in the output buffer */ 891 empty_both_buffers(kbdc, 10); 892 893 #if 0 894 /* 895 * NOTE: KBDC_RESET_KBD may not restore the communication between the 896 * keyboard and the controller. 897 */ 898 reset_kbd(kbdc); 899 #else 900 /* 901 * NOTE: somehow diagnostic and keyboard port test commands bring the 902 * keyboard back. 903 */ 904 if (!test_controller(kbdc)) 905 log(LOG_ERR, "psm: keyboard controller failed.\n"); 906 /* if there isn't a keyboard in the system, the following error is OK */ 907 if (test_kbd_port(kbdc) != 0) 908 VLOG(1, (LOG_ERR, "psm: keyboard port failed.\n")); 909 #endif 910 } 911 912 static int 913 restore_controller(KBDC kbdc, int command_byte) 914 { 915 916 empty_both_buffers(kbdc, 10); 917 918 if (!set_controller_command_byte(kbdc, 0xff, command_byte)) { 919 log(LOG_ERR, "psm: failed to restore the keyboard controller " 920 "command byte.\n"); 921 empty_both_buffers(kbdc, 10); 922 return (FALSE); 923 } else { 924 empty_both_buffers(kbdc, 10); 925 return (TRUE); 926 } 927 } 928 929 /* 930 * Re-initialize the aux port and device. The aux port must be enabled 931 * and its interrupt must be disabled before calling this routine. 932 * The aux device will be disabled before returning. 933 * The keyboard controller must be locked via `kbdc_lock()' before 934 * calling this routine. 935 */ 936 static int 937 doinitialize(struct psm_softc *sc, mousemode_t *mode) 938 { 939 940 KBDC kbdc = sc->kbdc; 941 int stat[3]; 942 int i; 943 944 switch((i = test_aux_port(kbdc))) { 945 case 1: /* ignore these errors */ 946 case 2: 947 case 3: 948 case PSM_ACK: 949 if (verbose) 950 log(LOG_DEBUG, 951 "psm%d: strange result for test aux port (%d).\n", 952 sc->unit, i); 953 /* FALLTHROUGH */ 954 case 0: /* no error */ 955 break; 956 case -1: /* time out */ 957 default: /* error */ 958 recover_from_error(kbdc); 959 if (sc->config & PSM_CONFIG_IGNPORTERROR) 960 break; 961 log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n", 962 sc->unit, i); 963 return (FALSE); 964 } 965 966 if (sc->config & PSM_CONFIG_NORESET) { 967 /* 968 * Don't try to reset the pointing device. It may possibly 969 * be left in the unknown state, though... 970 */ 971 } else { 972 /* 973 * NOTE: some controllers appears to hang the `keyboard' when 974 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. 975 */ 976 if (!reset_aux_dev(kbdc)) { 977 recover_from_error(kbdc); 978 log(LOG_ERR, "psm%d: failed to reset the aux device.\n", 979 sc->unit); 980 return (FALSE); 981 } 982 } 983 984 /* 985 * both the aux port and the aux device is functioning, see 986 * if the device can be enabled. 987 */ 988 if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) { 989 log(LOG_ERR, "psm%d: failed to enable the aux device.\n", 990 sc->unit); 991 return (FALSE); 992 } 993 empty_both_buffers(kbdc, 10); /* remove stray data if any */ 994 995 /* Re-enable the mouse. */ 996 for (i = 0; vendortype[i].probefunc != NULL; ++i) 997 if (vendortype[i].model == sc->hw.model) 998 (*vendortype[i].probefunc)(sc, REINIT); 999 1000 /* set mouse parameters */ 1001 if (mode != (mousemode_t *)NULL) { 1002 if (mode->rate > 0) 1003 mode->rate = set_mouse_sampling_rate(kbdc, mode->rate); 1004 if (mode->resolution >= 0) 1005 mode->resolution = 1006 set_mouse_resolution(kbdc, mode->resolution); 1007 set_mouse_scaling(kbdc, 1); 1008 set_mouse_mode(kbdc); 1009 } 1010 1011 /* Record sync on the next data packet we see. */ 1012 sc->flags |= PSM_NEED_SYNCBITS; 1013 1014 /* just check the status of the mouse */ 1015 if (get_mouse_status(kbdc, stat, 0, 3) < 3) 1016 log(LOG_DEBUG, "psm%d: failed to get status (doinitialize).\n", 1017 sc->unit); 1018 1019 return (TRUE); 1020 } 1021 1022 static int 1023 doopen(struct psm_softc *sc, int command_byte) 1024 { 1025 1026 int stat[3]; 1027 1028 /* 1029 * FIXME: Synaptics TouchPad seems to go back to Relative Mode with 1030 * no obvious reason. Thus we check the current mode and restore the 1031 * Absolute Mode if it was cleared. 1032 * 1033 * The previous hack at the end of psmprobe() wasn't efficient when 1034 * moused(8) was restarted. 1035 * 1036 * A Reset (FF) or Set Defaults (F6) command would clear the 1037 * Absolute Mode bit. But a verbose boot or debug.psm.loglevel=5 1038 * doesn't show any evidence of such a command. 1039 */ 1040 if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) { 1041 mouse_ext_command(sc->kbdc, 1); 1042 get_mouse_status(sc->kbdc, stat, 0, 3); 1043 if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) || 1044 stat[1] == 0x47) && 1045 stat[2] == 0x40) { 1046 synaptics_set_mode(sc, synaptics_preferred_mode(sc)); 1047 VLOG(5, (LOG_DEBUG, "psm%d: Synaptics Absolute Mode " 1048 "hopefully restored\n", 1049 sc->unit)); 1050 } 1051 1052 } 1053 1054 /* 1055 * A user may want to disable tap and drag gestures on a Synaptics 1056 * TouchPad when it operates in Relative Mode. 1057 */ 1058 if (sc->hw.model == MOUSE_MODEL_GENERIC) { 1059 if (tap_enabled > 0) { 1060 /* 1061 * Enable tap & drag gestures. We use a Mode Byte 1062 * and clear the DisGest bit (see §2.5 of Synaptics 1063 * TouchPad Interfacing Guide). 1064 */ 1065 VLOG(2, (LOG_DEBUG, 1066 "psm%d: enable tap and drag gestures\n", 1067 sc->unit)); 1068 mouse_ext_command(sc->kbdc, 0x00); 1069 set_mouse_sampling_rate(sc->kbdc, 20); 1070 } else if (tap_enabled == 0) { 1071 /* 1072 * Disable tap & drag gestures. We use a Mode Byte 1073 * and set the DisGest bit (see §2.5 of Synaptics 1074 * TouchPad Interfacing Guide). 1075 */ 1076 VLOG(2, (LOG_DEBUG, 1077 "psm%d: disable tap and drag gestures\n", 1078 sc->unit)); 1079 mouse_ext_command(sc->kbdc, 0x04); 1080 set_mouse_sampling_rate(sc->kbdc, 20); 1081 } 1082 } 1083 1084 /* enable the mouse device */ 1085 if (!enable_aux_dev(sc->kbdc)) { 1086 /* MOUSE ERROR: failed to enable the mouse because: 1087 * 1) the mouse is faulty, 1088 * 2) the mouse has been removed(!?) 1089 * In the latter case, the keyboard may have hung, and need 1090 * recovery procedure... 1091 */ 1092 recover_from_error(sc->kbdc); 1093 #if 0 1094 /* FIXME: we could reset the mouse here and try to enable 1095 * it again. But it will take long time and it's not a good 1096 * idea to disable the keyboard that long... 1097 */ 1098 if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) { 1099 recover_from_error(sc->kbdc); 1100 #else 1101 { 1102 #endif 1103 restore_controller(sc->kbdc, command_byte); 1104 /* mark this device is no longer available */ 1105 sc->state &= ~PSM_VALID; 1106 log(LOG_ERR, 1107 "psm%d: failed to enable the device (doopen).\n", 1108 sc->unit); 1109 return (EIO); 1110 } 1111 } 1112 1113 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 1114 log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", 1115 sc->unit); 1116 1117 /* enable the aux port and interrupt */ 1118 if (!set_controller_command_byte(sc->kbdc, 1119 KBD_AUX_CONTROL_BITS, 1120 KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) { 1121 /* CONTROLLER ERROR */ 1122 disable_aux_dev(sc->kbdc); 1123 restore_controller(sc->kbdc, command_byte); 1124 log(LOG_ERR, 1125 "psm%d: failed to enable the aux interrupt (doopen).\n", 1126 sc->unit); 1127 return (EIO); 1128 } 1129 1130 /* start the watchdog timer */ 1131 sc->watchdog = FALSE; 1132 callout_reset(&sc->callout, hz * 2, psmtimeout, (void *)(uintptr_t)sc); 1133 1134 return (0); 1135 } 1136 1137 static int 1138 reinitialize(struct psm_softc *sc, int doinit) 1139 { 1140 1141 int err; 1142 int c; 1143 1144 /* don't let anybody mess with the aux device */ 1145 if (!kbdc_lock(sc->kbdc, TRUE)) 1146 return (EIO); 1147 1148 lockmgr(&sc->lock, LK_EXCLUSIVE); 1149 1150 /* block our watchdog timer */ 1151 sc->watchdog = FALSE; 1152 callout_stop(&sc->callout); 1153 1154 /* save the current controller command byte */ 1155 empty_both_buffers(sc->kbdc, 10); 1156 c = get_controller_command_byte(sc->kbdc); 1157 VLOG(2, (LOG_DEBUG, 1158 "psm%d: current command byte: %04x (reinitialize).\n", 1159 sc->unit, c)); 1160 1161 /* enable the aux port but disable the aux interrupt and the keyboard */ 1162 if ((c == -1) || 1163 !set_controller_command_byte(sc->kbdc, 1164 KBD_AUX_CONTROL_BITS, 1165 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1166 /* CONTROLLER ERROR */ 1167 lockmgr(&sc->lock, LK_RELEASE); 1168 kbdc_lock(sc->kbdc, FALSE); 1169 log(LOG_ERR, 1170 "psm%d: unable to set the command byte (reinitialize).\n", 1171 sc->unit); 1172 return (EIO); 1173 } 1174 1175 /* flush any data */ 1176 if (sc->state & PSM_VALID) { 1177 /* this may fail; but never mind... */ 1178 disable_aux_dev(sc->kbdc); 1179 empty_aux_buffer(sc->kbdc, 10); 1180 } 1181 flushpackets(sc); 1182 sc->syncerrors = 0; 1183 sc->pkterrors = 0; 1184 memset(&sc->lastinputerr, 0, sizeof(sc->lastinputerr)); 1185 1186 /* try to detect the aux device; are you still there? */ 1187 err = 0; 1188 if (doinit) { 1189 if (doinitialize(sc, &sc->mode)) { 1190 /* yes */ 1191 sc->state |= PSM_VALID; 1192 } else { 1193 /* the device has gone! */ 1194 restore_controller(sc->kbdc, c); 1195 sc->state &= ~PSM_VALID; 1196 log(LOG_ERR, 1197 "psm%d: the aux device has gone! (reinitialize).\n", 1198 sc->unit); 1199 err = ENXIO; 1200 } 1201 } 1202 lockmgr(&sc->lock, LK_RELEASE); 1203 1204 /* restore the driver state */ 1205 if ((sc->state & PSM_OPEN) && (err == 0)) { 1206 /* enable the aux device and the port again */ 1207 err = doopen(sc, c); 1208 if (err != 0) 1209 log(LOG_ERR, "psm%d: failed to enable the device " 1210 "(reinitialize).\n", sc->unit); 1211 } else { 1212 /* restore the keyboard port and disable the aux port */ 1213 if (!set_controller_command_byte(sc->kbdc, 1214 KBD_AUX_CONTROL_BITS, 1215 KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1216 /* CONTROLLER ERROR */ 1217 log(LOG_ERR, "psm%d: failed to disable the aux port " 1218 "(reinitialize).\n", sc->unit); 1219 err = EIO; 1220 } 1221 } 1222 1223 kbdc_lock(sc->kbdc, FALSE); 1224 return (err); 1225 } 1226 1227 /* psm driver entry points */ 1228 1229 static void 1230 psmidentify(driver_t *driver, device_t parent) 1231 { 1232 1233 device_t psmc; 1234 device_t psm; 1235 u_long irq; 1236 int unit; 1237 1238 unit = device_get_unit(parent); 1239 1240 /* always add at least one child */ 1241 psm = BUS_ADD_CHILD(parent, parent, KBDC_RID_AUX, driver->name, unit); 1242 if (psm == NULL) { 1243 1244 return; 1245 } 1246 1247 irq = bus_get_resource_start(psm, SYS_RES_IRQ, KBDC_RID_AUX); 1248 if (irq > 0) { 1249 1250 return; 1251 } 1252 1253 /* 1254 * If the PS/2 mouse device has already been reported by ACPI or 1255 * PnP BIOS, obtain the IRQ resource from it. 1256 * (See psmcpnp_attach() below.) 1257 */ 1258 psmc = device_find_child(device_get_parent(parent), 1259 PSMCPNP_DRIVER_NAME, unit); 1260 if (psmc == NULL) 1261 return; 1262 1263 irq = bus_get_resource_start(psmc, SYS_RES_IRQ, 0); 1264 if (irq <= 0) { 1265 1266 return; 1267 } 1268 1269 bus_delete_resource(psmc, SYS_RES_IRQ, 0); 1270 bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1, 1271 machintr_legacy_intr_cpuid(irq)); 1272 } 1273 1274 #define endprobe(v) do { \ 1275 if (bootverbose) \ 1276 --verbose; \ 1277 set_controller_command_byte(sc->kbdc, \ 1278 KBD_AUX_CONTROL_BITS, KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT); \ 1279 kbdc_lock(sc->kbdc, FALSE); \ 1280 return (v); \ 1281 } while (0) 1282 1283 static int 1284 psmprobe(device_t dev) 1285 { 1286 1287 int unit = device_get_unit(dev); 1288 struct psm_softc *sc = device_get_softc(dev); 1289 int stat[3]; 1290 int command_byte; 1291 /* int rid; */ 1292 int i; 1293 uintptr_t irq; 1294 uintptr_t flags; 1295 1296 #if 0 1297 kbdc_debug(TRUE); 1298 #endif 1299 1300 BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq); 1301 BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_FLAGS, &flags); 1302 1303 sc->unit = unit; 1304 sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev))); 1305 sc->config = flags & PSM_CONFIG_FLAGS; 1306 /* XXX: for backward compatibility */ 1307 #if defined(PSM_HOOKRESUME) 1308 sc->config |= 1309 #ifdef PSM_RESETAFTERSUSPEND 1310 PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND; 1311 #else 1312 PSM_CONFIG_HOOKRESUME; 1313 #endif 1314 #endif /* PSM_HOOKRESUME */ 1315 sc->flags = 0; 1316 if (bootverbose) 1317 ++verbose; 1318 1319 device_set_desc(dev, "PS/2 Mouse"); 1320 1321 if (!kbdc_lock(sc->kbdc, TRUE)) { 1322 kprintf("psm%d: unable to lock the controller.\n", unit); 1323 if (bootverbose) 1324 --verbose; 1325 return (ENXIO); 1326 } 1327 1328 1329 /* 1330 * NOTE: two bits in the command byte controls the operation of the 1331 * aux port (mouse port): the aux port disable bit (bit 5) and the aux 1332 * port interrupt (IRQ 12) enable bit (bit 2). 1333 */ 1334 1335 /* discard anything left after the keyboard initialization */ 1336 empty_both_buffers(sc->kbdc, 10); 1337 1338 /* save the current command byte; it will be used later */ 1339 command_byte = get_controller_command_byte(sc->kbdc); 1340 if (verbose) 1341 kprintf("psm%d: current command byte:%04x\n", unit, 1342 command_byte); 1343 if (command_byte == -1) { 1344 /* CONTROLLER ERROR */ 1345 kprintf("psm%d: unable to get the current " 1346 "command byte value.\n", 1347 unit); 1348 endprobe(ENXIO); 1349 } 1350 1351 /* XXX: this note is of the previous code, kept intact in case any 1352 * breakage occurs. Since both comments contradict each other. 1353 * Previous condition used was: 1354 * 1355 * if (!set_controller_command_byte(sc->kbdc, 1356 * KBD_AUX_CONTROL_BITS, 1357 * KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) 1358 * 1359 * .. <slightly different code> 1360 * NOTE: We cannot mess with the keyboard port, do NOT disable it 1361 * while we are probing the aux port during this routine. 1362 * Disabling the keyboard port will break some things 1363 * (Acer c720)... probably related to BIOS emulation of the 1364 * i8042. 1365 */ 1366 /* 1367 * disable the keyboard port while probing the aux port, which must be 1368 * enabled during this routine 1369 */ 1370 if (!set_controller_command_byte(sc->kbdc, 1371 KBD_AUX_CONTROL_BITS, 1372 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1373 /* 1374 * this is CONTROLLER ERROR; I don't know how to recover 1375 * from this error... 1376 */ 1377 kprintf("psm%d: unable to set the command byte.\n", unit); 1378 endprobe(ENXIO); 1379 } 1380 1381 /* 1382 * NOTE: Linux doesn't send discrete aux port enablement commands, 1383 * it is unclear whether this is needed or helps or hinders 1384 * bios emulators. 1385 */ 1386 write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT); 1387 1388 /* 1389 * NOTE: `test_aux_port()' is designed to return with zero if the aux 1390 * port exists and is functioning. However, some controllers appears 1391 * to respond with zero even when the aux port doesn't exist. (It may 1392 * be that this is only the case when the controller DOES have the aux 1393 * port but the port is not wired on the motherboard.) The keyboard 1394 * controllers without the port, such as the original AT, are 1395 * supporsed to return with an error code or simply time out. In any 1396 * case, we have to continue probing the port even when the controller 1397 * passes this test. 1398 * 1399 * XXX: some controllers erroneously return the error code 1, 2 or 3 1400 * when it has the perfectly functional aux port. We have to ignore 1401 * this error code. Even if the controller HAS error with the aux 1402 * port, it will be detected later... 1403 * XXX: another incompatible controller returns PSM_ACK (0xfa)... 1404 */ 1405 1406 switch ((i = test_aux_port(sc->kbdc))) { 1407 case 1: /* ignore these errors */ 1408 case 2: 1409 case 3: 1410 case PSM_ACK: 1411 if (verbose) 1412 kprintf("psm%d: strange result for test aux port " 1413 "(%d).\n", unit, i); 1414 /* FALLTHROUGH */ 1415 case 0: /* no error */ 1416 break; 1417 case -1: /* time out */ 1418 default: /* error */ 1419 recover_from_error(sc->kbdc); 1420 if (sc->config & PSM_CONFIG_IGNPORTERROR) 1421 break; 1422 1423 if (verbose) 1424 kprintf("psm%d: the aux port is not " 1425 "functioning (%d).\n", 1426 unit, i); 1427 endprobe(ENXIO); 1428 } 1429 1430 if (sc->config & PSM_CONFIG_NORESET) { 1431 /* 1432 * Don't try to reset the pointing device. It may possibly be 1433 * left in the unknown state, though... 1434 */ 1435 } else { 1436 /* 1437 * NOTE: some controllers appears to hang the `keyboard' when 1438 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. 1439 * 1440 * Attempt to reset the controller twice -- this helps 1441 * pierce through some KVM switches. The second reset 1442 * is non-fatal. 1443 */ 1444 if (!reset_aux_dev(sc->kbdc)) { 1445 recover_from_error(sc->kbdc); 1446 if (verbose) 1447 kprintf("psm%d: failed to reset the aux " 1448 "device.\n", unit); 1449 endprobe(ENXIO); 1450 } else if (!reset_aux_dev(sc->kbdc)) { 1451 recover_from_error(sc->kbdc); 1452 if (verbose >= 2) 1453 kprintf("psm%d: failed to reset the aux device " 1454 "(2).\n", unit); 1455 } 1456 } 1457 1458 /* 1459 * both the aux port and the aux device are functioning, see if the 1460 * device can be enabled. NOTE: when enabled, the device will start 1461 * sending data; we shall immediately disable the device once we know 1462 * the device can be enabled. 1463 */ 1464 if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) { 1465 /* MOUSE ERROR */ 1466 recover_from_error(sc->kbdc); 1467 if (verbose) 1468 kprintf("psm%d: failed to enable the aux device.\n", 1469 unit); 1470 endprobe(ENXIO); 1471 } 1472 1473 /* save the default values after reset */ 1474 if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) { 1475 sc->dflt_mode.rate = sc->mode.rate = stat[2]; 1476 sc->dflt_mode.resolution = sc->mode.resolution = stat[1]; 1477 } else { 1478 sc->dflt_mode.rate = sc->mode.rate = -1; 1479 sc->dflt_mode.resolution = sc->mode.resolution = -1; 1480 } 1481 1482 /* hardware information */ 1483 sc->hw.iftype = MOUSE_IF_PS2; 1484 1485 #if 0 1486 /* verify the device is a mouse */ 1487 sc->hw.hwid = get_aux_id(sc->kbdc); 1488 /* XXX Check against a list of PS2 device types. */ 1489 #endif 1490 1491 switch (sc->hw.hwid) { 1492 case PSM_BALLPOINT_ID: 1493 sc->hw.type = MOUSE_TRACKBALL; 1494 break; 1495 case PSM_MOUSE_ID: 1496 case PSM_INTELLI_ID: 1497 case PSM_EXPLORER_ID: 1498 case PSM_4DMOUSE_ID: 1499 case PSM_4DPLUS_ID: 1500 sc->hw.type = MOUSE_MOUSE; 1501 break; 1502 default: 1503 sc->hw.type = MOUSE_UNKNOWN; 1504 break; 1505 } 1506 1507 if (sc->config & PSM_CONFIG_NOIDPROBE) { 1508 sc->hw.buttons = 2; 1509 i = GENERIC_MOUSE_ENTRY; 1510 } else { 1511 /* # of buttons */ 1512 sc->hw.buttons = get_mouse_buttons(sc->kbdc); 1513 1514 /* other parameters */ 1515 for (i = 0; vendortype[i].probefunc != NULL; ++i) 1516 if ((*vendortype[i].probefunc)(sc, PROBE)) { 1517 if (verbose >= 2) 1518 kprintf("psm%d: found %s\n", unit, 1519 model_name(vendortype[i].model)); 1520 break; 1521 } 1522 } 1523 1524 sc->hw.model = vendortype[i].model; 1525 1526 sc->dflt_mode.level = PSM_LEVEL_BASE; 1527 sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE; 1528 sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4; 1529 if (sc->config & PSM_CONFIG_NOCHECKSYNC) 1530 sc->dflt_mode.syncmask[0] = 0; 1531 else 1532 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask; 1533 if (sc->config & PSM_CONFIG_FORCETAP) 1534 sc->dflt_mode.syncmask[0] &= ~MOUSE_PS2_TAP; 1535 sc->dflt_mode.syncmask[1] = 0; /* syncbits */ 1536 sc->mode = sc->dflt_mode; 1537 sc->mode.packetsize = vendortype[i].packetsize; 1538 1539 /* set mouse parameters */ 1540 #if 0 1541 /* 1542 * A version of Logitech FirstMouse+ won't report wheel movement, 1543 * if SET_DEFAULTS is sent... Don't use this command. 1544 * This f}}}ix was found by Takashi Nishida. 1545 */ 1546 i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS); 1547 if (verbose >= 2) 1548 kprintf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i); 1549 #endif 1550 if (sc->config & PSM_CONFIG_RESOLUTION) 1551 sc->mode.resolution = 1552 set_mouse_resolution(sc->kbdc, 1553 (sc->config & PSM_CONFIG_RESOLUTION) - 1); 1554 else if (sc->mode.resolution >= 0) 1555 sc->mode.resolution = 1556 set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution); 1557 if (sc->mode.rate > 0) 1558 sc->mode.rate = 1559 set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate); 1560 set_mouse_scaling(sc->kbdc, 1); 1561 1562 /* Record sync on the next data packet we see. */ 1563 sc->flags |= PSM_NEED_SYNCBITS; 1564 1565 /* just check the status of the mouse */ 1566 /* 1567 * NOTE: XXX there are some arcane controller/mouse combinations out 1568 * there, which hung the controller unless there is data transmission 1569 * after ACK from the mouse. 1570 */ 1571 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 1572 kprintf("psm%d: failed to get status.\n", unit); 1573 else { 1574 /* 1575 * When in its native mode, some mice operate with different 1576 * default parameters than in the PS/2 compatible mode. 1577 */ 1578 sc->dflt_mode.rate = sc->mode.rate = stat[2]; 1579 sc->dflt_mode.resolution = sc->mode.resolution = stat[1]; 1580 } 1581 1582 /* disable the aux port for now... */ 1583 if (!set_controller_command_byte(sc->kbdc, 1584 KBD_AUX_CONTROL_BITS, 1585 KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1586 /* 1587 * this is CONTROLLER ERROR; I don't know the proper way to 1588 * recover from this error... 1589 */ 1590 kprintf("psm%d: unable to set the command byte.\n", unit); 1591 endprobe(ENXIO); 1592 } 1593 1594 /* done */ 1595 kbdc_lock(sc->kbdc, FALSE); 1596 return (0); 1597 } 1598 1599 static int 1600 psmattach(device_t dev) 1601 { 1602 1603 int unit = device_get_unit(dev); 1604 struct psm_softc *sc = device_get_softc(dev); 1605 int error; 1606 int rid; 1607 uintptr_t irq; 1608 1609 /* Setup initial state */ 1610 sc->state = PSM_VALID; 1611 callout_init_lk(&sc->callout, &sc->lock); 1612 callout_init_lk(&sc->softcallout, &sc->lock); 1613 lockinit(&sc->lock, "psmlk", 0, LK_CANRECURSE); 1614 1615 /* Setup our interrupt handler */ 1616 rid = KBDC_RID_AUX; 1617 BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq); 1618 sc->intr = bus_alloc_legacy_irq_resource(dev, &rid, irq, RF_ACTIVE); 1619 if (sc->intr == NULL) { 1620 return (ENXIO); 1621 } 1622 1623 error = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intr, 1624 INTR_NOPOLL, psmintr, sc, &sc->ih, NULL, NULL); 1625 if (error) { 1626 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); 1627 return (error); 1628 } 1629 1630 /* Done */ 1631 sc->dev = make_dev(&psm_ops, unit, 0, 0, 0666, "psm%d", unit); 1632 sc->dev->si_drv1 = sc; 1633 1634 /* Some touchpad devices need full reinitialization after suspend. */ 1635 switch (sc->hw.model) { 1636 case MOUSE_MODEL_SYNAPTICS: 1637 case MOUSE_MODEL_GLIDEPOINT: 1638 case MOUSE_MODEL_VERSAPAD: 1639 case MOUSE_MODEL_ELANTECH: 1640 sc->config |= PSM_CONFIG_INITAFTERSUSPEND; 1641 break; 1642 default: 1643 if (sc->synhw.infoMajor >= 4 || sc->tphw > 0) 1644 sc->config |= PSM_CONFIG_INITAFTERSUSPEND; 1645 break; 1646 } 1647 1648 /* Elantech trackpad`s sync bit differs from touchpad`s one */ 1649 if (sc->hw.model == MOUSE_MODEL_ELANTECH && 1650 (sc->elanhw.hascrc || sc->elanhw.hastrackpoint)) 1651 sc->config |= PSM_CONFIG_NOCHECKSYNC; 1652 1653 1654 if (!verbose) 1655 kprintf("psm%d: model %s, device ID %d\n", 1656 unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff); 1657 else { 1658 kprintf("psm%d: model %s, device ID %d-%02x, %d buttons\n", 1659 unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff, 1660 sc->hw.hwid >> 8, sc->hw.buttons); 1661 kprintf("psm%d: config:%08x, flags:%08x, packet size:%d\n", 1662 unit, sc->config, sc->flags, sc->mode.packetsize); 1663 kprintf("psm%d: syncmask:%02x, syncbits:%02x\n", 1664 unit, sc->mode.syncmask[0], sc->mode.syncmask[1]); 1665 } 1666 1667 if (bootverbose) 1668 --verbose; 1669 1670 return (0); 1671 } 1672 1673 static int 1674 psmdetach(device_t dev) 1675 { 1676 1677 struct psm_softc *sc; 1678 int rid; 1679 1680 sc = device_get_softc(dev); 1681 if (sc->state & PSM_OPEN) 1682 return (EBUSY); 1683 1684 rid = KBDC_RID_AUX; 1685 bus_teardown_intr(dev, sc->intr, sc->ih); 1686 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); 1687 1688 destroy_dev(sc->dev); 1689 1690 /* XXX: callout_drain in original freebsd11 code */ 1691 callout_terminate(&sc->callout); 1692 callout_terminate(&sc->softcallout); 1693 1694 return (0); 1695 } 1696 1697 static int 1698 psmopen(struct dev_open_args *ap) 1699 { 1700 1701 cdev_t dev = ap->a_head.a_dev; 1702 struct psm_softc *sc; 1703 int command_byte; 1704 int err; 1705 1706 /* Get device data */ 1707 sc = dev->si_drv1; 1708 if ((sc == NULL) || (sc->state & PSM_VALID) == 0) { 1709 /* the device is no longer valid/functioning */ 1710 return (ENXIO); 1711 } 1712 1713 /* Disallow multiple opens */ 1714 if (sc->state & PSM_OPEN) 1715 return (EBUSY); 1716 1717 device_busy(devclass_get_device(psm_devclass, sc->unit)); 1718 1719 /* Initialize state */ 1720 sc->mode.level = sc->dflt_mode.level; 1721 sc->mode.protocol = sc->dflt_mode.protocol; 1722 sc->watchdog = FALSE; 1723 1724 /* flush the event queue */ 1725 sc->queue.count = 0; 1726 sc->queue.head = 0; 1727 sc->queue.tail = 0; 1728 sc->status.flags = 0; 1729 sc->status.button = 0; 1730 sc->status.obutton = 0; 1731 sc->status.dx = 0; 1732 sc->status.dy = 0; 1733 sc->status.dz = 0; 1734 sc->button = 0; 1735 sc->pqueue_start = 0; 1736 sc->pqueue_end = 0; 1737 1738 /* empty input buffer */ 1739 flushpackets(sc); 1740 sc->syncerrors = 0; 1741 sc->pkterrors = 0; 1742 1743 /* don't let timeout routines in the keyboard driver to poll the kbdc */ 1744 if (!kbdc_lock(sc->kbdc, TRUE)) 1745 return (EIO); 1746 1747 /* save the current controller command byte */ 1748 lockmgr(&sc->lock, LK_EXCLUSIVE); 1749 command_byte = get_controller_command_byte(sc->kbdc); 1750 1751 /* enable the aux port and temporalily disable the keyboard */ 1752 if (command_byte == -1 || 1753 !set_controller_command_byte(sc->kbdc, 1754 KBD_AUX_CONTROL_BITS, 1755 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1756 /* CONTROLLER ERROR; do you know how to get out of this? */ 1757 kbdc_lock(sc->kbdc, FALSE); 1758 lockmgr(&sc->lock, LK_RELEASE); 1759 log(LOG_ERR, 1760 "psm%d: unable to set the command byte (psmopen).\n", 1761 sc->unit); 1762 return (EIO); 1763 } 1764 /* 1765 * Now that the keyboard controller is told not to generate 1766 * the keyboard and mouse interrupts, allow 1767 * the other tty interrupts. The clock interrupt may also occur, 1768 * but timeout routines will be blocked by the poll flag set 1769 * via `kbdc_lock()' 1770 */ 1771 lockmgr(&sc->lock, LK_RELEASE); 1772 1773 /* enable the mouse device */ 1774 err = doopen(sc, command_byte); 1775 1776 /* done */ 1777 if (err == 0) 1778 sc->state |= PSM_OPEN; 1779 kbdc_lock(sc->kbdc, FALSE); 1780 return (err); 1781 } 1782 1783 static int 1784 psmclose(struct dev_close_args *ap) 1785 { 1786 1787 cdev_t dev = ap->a_head.a_dev; 1788 struct psm_softc *sc = dev->si_drv1; 1789 int stat[3]; 1790 int command_byte; 1791 1792 /* don't let timeout routines in the keyboard driver to poll the kbdc */ 1793 if (!kbdc_lock(sc->kbdc, TRUE)) 1794 return (EIO); 1795 1796 /* save the current controller command byte */ 1797 lockmgr(&sc->lock, LK_EXCLUSIVE); 1798 command_byte = get_controller_command_byte(sc->kbdc); 1799 if (command_byte == -1) { 1800 kbdc_lock(sc->kbdc, FALSE); 1801 lockmgr(&sc->lock, LK_RELEASE); 1802 return (EIO); 1803 } 1804 1805 /* disable the aux interrupt and temporalily disable the keyboard */ 1806 if (!set_controller_command_byte(sc->kbdc, 1807 KBD_AUX_CONTROL_BITS, 1808 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1809 log(LOG_ERR, 1810 "psm%d: failed to disable the aux int (psmclose).\n", 1811 sc->unit); 1812 /* CONTROLLER ERROR; 1813 * NOTE: we shall force our way through. Because the only 1814 * ill effect we shall see is that we may not be able 1815 * to read ACK from the mouse, and it doesn't matter much 1816 * so long as the mouse will accept the DISABLE command. 1817 */ 1818 } 1819 lockmgr(&sc->lock, LK_RELEASE); 1820 1821 /* stop the watchdog timer */ 1822 callout_stop(&sc->callout); 1823 1824 /* remove anything left in the output buffer */ 1825 empty_aux_buffer(sc->kbdc, 10); 1826 1827 /* disable the aux device, port and interrupt */ 1828 if (sc->state & PSM_VALID) { 1829 if (!disable_aux_dev(sc->kbdc)) { 1830 /* MOUSE ERROR; 1831 * NOTE: we don't return (error) and continue, 1832 * pretending we have successfully disabled the device. 1833 * It's OK because the interrupt routine will discard 1834 * any data from the mouse hereafter. 1835 */ 1836 log(LOG_ERR, 1837 "psm%d: failed to disable the device (psmclose).\n", 1838 sc->unit); 1839 } 1840 1841 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 1842 log(LOG_DEBUG, 1843 "psm%d: failed to get status (psmclose).\n", 1844 sc->unit); 1845 } 1846 1847 if (!set_controller_command_byte(sc->kbdc, 1848 KBD_AUX_CONTROL_BITS, 1849 KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1850 /* 1851 * CONTROLLER ERROR; 1852 * we shall ignore this error; see the above comment. 1853 */ 1854 log(LOG_ERR, 1855 "psm%d: failed to disable the aux port (psmclose).\n", 1856 sc->unit); 1857 } 1858 1859 /* remove anything left in the output buffer */ 1860 empty_aux_buffer(sc->kbdc, 10); 1861 1862 /* close is almost always successful */ 1863 sc->state &= ~PSM_OPEN; 1864 kbdc_lock(sc->kbdc, FALSE); 1865 device_unbusy(devclass_get_device(psm_devclass, sc->unit)); 1866 return (0); 1867 } 1868 1869 static int 1870 tame_mouse(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *status, 1871 u_char *buf) 1872 { 1873 1874 static u_char butmapps2[8] = { 1875 0, 1876 MOUSE_PS2_BUTTON1DOWN, 1877 MOUSE_PS2_BUTTON2DOWN, 1878 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN, 1879 MOUSE_PS2_BUTTON3DOWN, 1880 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN, 1881 MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN, 1882 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | 1883 MOUSE_PS2_BUTTON3DOWN, 1884 }; 1885 static u_char butmapmsc[8] = { 1886 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | 1887 MOUSE_MSC_BUTTON3UP, 1888 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1889 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 1890 MOUSE_MSC_BUTTON3UP, 1891 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 1892 MOUSE_MSC_BUTTON2UP, 1893 MOUSE_MSC_BUTTON1UP, 1894 0, 1895 }; 1896 int mapped; 1897 int i; 1898 1899 if (sc->mode.level == PSM_LEVEL_BASE) { 1900 mapped = status->button & ~MOUSE_BUTTON4DOWN; 1901 if (status->button & MOUSE_BUTTON4DOWN) 1902 mapped |= MOUSE_BUTTON1DOWN; 1903 status->button = mapped; 1904 buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS]; 1905 i = imax(imin(status->dx, 255), -256); 1906 if (i < 0) 1907 buf[0] |= MOUSE_PS2_XNEG; 1908 buf[1] = i; 1909 i = imax(imin(status->dy, 255), -256); 1910 if (i < 0) 1911 buf[0] |= MOUSE_PS2_YNEG; 1912 buf[2] = i; 1913 return (MOUSE_PS2_PACKETSIZE); 1914 } else if (sc->mode.level == PSM_LEVEL_STANDARD) { 1915 buf[0] = MOUSE_MSC_SYNC | 1916 butmapmsc[status->button & MOUSE_STDBUTTONS]; 1917 i = imax(imin(status->dx, 255), -256); 1918 buf[1] = i >> 1; 1919 buf[3] = i - buf[1]; 1920 i = imax(imin(status->dy, 255), -256); 1921 buf[2] = i >> 1; 1922 buf[4] = i - buf[2]; 1923 i = imax(imin(status->dz, 127), -128); 1924 buf[5] = (i >> 1) & 0x7f; 1925 buf[6] = (i - (i >> 1)) & 0x7f; 1926 buf[7] = (~status->button >> 3) & 0x7f; 1927 return (MOUSE_SYS_PACKETSIZE); 1928 } 1929 return (pb->inputbytes); 1930 } 1931 1932 static int 1933 psmread(struct dev_read_args *ap) 1934 { 1935 1936 cdev_t dev = ap->a_head.a_dev; 1937 struct uio *uio = ap->a_uio; 1938 struct psm_softc *sc = dev->si_drv1; 1939 u_char buf[PSM_SMALLBUFSIZE]; 1940 int error = 0; 1941 int l; 1942 1943 if ((sc->state & PSM_VALID) == 0) 1944 return (EIO); 1945 1946 /* block until mouse activity occurred */ 1947 lockmgr(&sc->lock, LK_EXCLUSIVE); 1948 while (sc->queue.count <= 0) { 1949 if (ap->a_ioflag & IO_NDELAY) { 1950 lockmgr(&sc->lock, LK_RELEASE); 1951 return (EWOULDBLOCK); 1952 } 1953 sc->state |= PSM_ASLP; 1954 error = lksleep(sc, &sc->lock, PCATCH, "psmrea", 0); 1955 sc->state &= ~PSM_ASLP; 1956 if (error) { 1957 lockmgr(&sc->lock, LK_RELEASE); 1958 return (error); 1959 } else if ((sc->state & PSM_VALID) == 0) { 1960 /* the device disappeared! */ 1961 lockmgr(&sc->lock, LK_RELEASE); 1962 return (EIO); 1963 } 1964 } 1965 lockmgr(&sc->lock, LK_RELEASE); 1966 1967 /* copy data to the user land */ 1968 while ((sc->queue.count > 0) && (uio->uio_resid > 0)) { 1969 lockmgr(&sc->lock, LK_EXCLUSIVE); 1970 l = imin(sc->queue.count, uio->uio_resid); 1971 if (l > sizeof(buf)) 1972 l = sizeof(buf); 1973 if (l > sizeof(sc->queue.buf) - sc->queue.head) { 1974 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], 1975 sizeof(sc->queue.buf) - sc->queue.head); 1976 bcopy(&sc->queue.buf[0], 1977 &buf[sizeof(sc->queue.buf) - sc->queue.head], 1978 l - (sizeof(sc->queue.buf) - sc->queue.head)); 1979 } else 1980 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l); 1981 sc->queue.count -= l; 1982 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf); 1983 lockmgr(&sc->lock, LK_RELEASE); 1984 error = uiomove(buf, l, uio); 1985 if (error) 1986 break; 1987 } 1988 1989 return (error); 1990 } 1991 1992 static int 1993 block_mouse_data(struct psm_softc *sc, int *c) 1994 { 1995 1996 if (!kbdc_lock(sc->kbdc, TRUE)) 1997 return (EIO); 1998 1999 lockmgr(&sc->lock, LK_EXCLUSIVE); 2000 *c = get_controller_command_byte(sc->kbdc); 2001 if ((*c == -1) || 2002 !set_controller_command_byte(sc->kbdc, 2003 KBD_AUX_CONTROL_BITS, 2004 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 2005 /* this is CONTROLLER ERROR */ 2006 lockmgr(&sc->lock, LK_RELEASE); 2007 kbdc_lock(sc->kbdc, FALSE); 2008 return (EIO); 2009 } 2010 2011 /* 2012 * The device may be in the middle of status data transmission. 2013 * The transmission will be interrupted, thus, incomplete status 2014 * data must be discarded. Although the aux interrupt is disabled 2015 * at the keyboard controller level, at most one aux interrupt 2016 * may have already been pending and a data byte is in the 2017 * output buffer; throw it away. Note that the second argument 2018 * to `empty_aux_buffer()' is zero, so that the call will just 2019 * flush the internal queue. 2020 * `psmintr()' will be invoked after the lock is released if an 2021 * interrupt is pending; it will see no data and returns immediately. 2022 */ 2023 empty_aux_buffer(sc->kbdc, 0); /* flush the queue */ 2024 read_aux_data_no_wait(sc->kbdc); /* throw away data if any */ 2025 flushpackets(sc); 2026 lockmgr(&sc->lock, LK_RELEASE); 2027 2028 return (0); 2029 } 2030 2031 static void 2032 dropqueue(struct psm_softc *sc) 2033 { 2034 2035 sc->queue.count = 0; 2036 sc->queue.head = 0; 2037 sc->queue.tail = 0; 2038 if ((sc->state & PSM_SOFTARMED) != 0) { 2039 sc->state &= ~PSM_SOFTARMED; 2040 callout_stop(&sc->softcallout); 2041 } 2042 sc->pqueue_start = sc->pqueue_end; 2043 } 2044 2045 static void 2046 flushpackets(struct psm_softc *sc) 2047 { 2048 2049 dropqueue(sc); 2050 bzero(&sc->pqueue, sizeof(sc->pqueue)); 2051 } 2052 2053 static int 2054 unblock_mouse_data(struct psm_softc *sc, int c) 2055 { 2056 2057 int error = 0; 2058 2059 /* 2060 * We may have seen a part of status data during `set_mouse_XXX()'. 2061 * they have been queued; flush it. 2062 */ 2063 empty_aux_buffer(sc->kbdc, 0); 2064 2065 /* restore ports and interrupt */ 2066 if (!set_controller_command_byte(sc->kbdc, 2067 KBD_AUX_CONTROL_BITS, c & KBD_AUX_CONTROL_BITS)) { 2068 /* 2069 * CONTROLLER ERROR; this is serious, we may have 2070 * been left with the inaccessible keyboard and 2071 * the disabled mouse interrupt. 2072 */ 2073 error = EIO; 2074 } 2075 2076 kbdc_lock(sc->kbdc, FALSE); 2077 return (error); 2078 } 2079 2080 2081 static int 2082 psmioctl(struct dev_ioctl_args *ap) 2083 { 2084 cdev_t dev = ap->a_head.a_dev; 2085 caddr_t addr= ap->a_data; 2086 struct psm_softc *sc = dev->si_drv1; 2087 mousemode_t mode; 2088 mousestatus_t status; 2089 #if (defined(MOUSE_GETVARS)) 2090 mousevar_t *var; 2091 #endif 2092 mousedata_t *data; 2093 int stat[3]; 2094 int command_byte; 2095 int error = 0; 2096 2097 /* Perform IOCTL command */ 2098 switch (ap->a_cmd) { 2099 2100 case OLD_MOUSE_GETHWINFO: 2101 lockmgr(&sc->lock, LK_EXCLUSIVE); 2102 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons; 2103 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype; 2104 ((old_mousehw_t *)addr)->type = sc->hw.type; 2105 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff; 2106 lockmgr(&sc->lock, LK_RELEASE); 2107 break; 2108 2109 case MOUSE_GETHWINFO: 2110 lockmgr(&sc->lock, LK_EXCLUSIVE); 2111 *(mousehw_t *)addr = sc->hw; 2112 if (sc->mode.level == PSM_LEVEL_BASE) 2113 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; 2114 lockmgr(&sc->lock, LK_RELEASE); 2115 break; 2116 2117 case MOUSE_SYN_GETHWINFO: 2118 lockmgr(&sc->lock, LK_EXCLUSIVE); 2119 if (sc->synhw.infoMajor >= 4) 2120 *(synapticshw_t *)addr = sc->synhw; 2121 else 2122 error = EINVAL; 2123 lockmgr(&sc->lock, LK_RELEASE); 2124 break; 2125 2126 case OLD_MOUSE_GETMODE: 2127 lockmgr(&sc->lock, LK_EXCLUSIVE); 2128 switch (sc->mode.level) { 2129 case PSM_LEVEL_BASE: 2130 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; 2131 break; 2132 case PSM_LEVEL_STANDARD: 2133 ((old_mousemode_t *)addr)->protocol = 2134 MOUSE_PROTO_SYSMOUSE; 2135 break; 2136 } 2137 ((old_mousemode_t *)addr)->rate = sc->mode.rate; 2138 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution; 2139 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor; 2140 lockmgr(&sc->lock, LK_RELEASE); 2141 break; 2142 2143 case MOUSE_GETMODE: 2144 lockmgr(&sc->lock, LK_EXCLUSIVE); 2145 *(mousemode_t *)addr = sc->mode; 2146 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) { 2147 ((mousemode_t *)addr)->syncmask[0] = 0; 2148 ((mousemode_t *)addr)->syncmask[1] = 0; 2149 } 2150 ((mousemode_t *)addr)->resolution = 2151 MOUSE_RES_LOW - sc->mode.resolution; 2152 switch (sc->mode.level) { 2153 case PSM_LEVEL_BASE: 2154 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; 2155 ((mousemode_t *)addr)->packetsize = 2156 MOUSE_PS2_PACKETSIZE; 2157 break; 2158 case PSM_LEVEL_STANDARD: 2159 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; 2160 ((mousemode_t *)addr)->packetsize = 2161 MOUSE_SYS_PACKETSIZE; 2162 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; 2163 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; 2164 break; 2165 } 2166 lockmgr(&sc->lock, LK_RELEASE); 2167 break; 2168 2169 case OLD_MOUSE_SETMODE: 2170 case MOUSE_SETMODE: 2171 if (ap->a_cmd == OLD_MOUSE_SETMODE) { 2172 mode.rate = ((old_mousemode_t *)addr)->rate; 2173 /* 2174 * resolution old I/F new I/F 2175 * default 0 0 2176 * low 1 -2 2177 * medium low 2 -3 2178 * medium high 3 -4 2179 * high 4 -5 2180 */ 2181 if (((old_mousemode_t *)addr)->resolution > 0) 2182 mode.resolution = 2183 -((old_mousemode_t *)addr)->resolution - 1; 2184 else 2185 mode.resolution = 0; 2186 mode.accelfactor = 2187 ((old_mousemode_t *)addr)->accelfactor; 2188 mode.level = -1; 2189 } else 2190 mode = *(mousemode_t *)addr; 2191 2192 /* adjust and validate parameters. */ 2193 if (mode.rate > UCHAR_MAX) 2194 return (EINVAL); 2195 if (mode.rate == 0) 2196 mode.rate = sc->dflt_mode.rate; 2197 else if (mode.rate == -1) 2198 /* don't change the current setting */ 2199 ; 2200 else if (mode.rate < 0) 2201 return (EINVAL); 2202 if (mode.resolution >= UCHAR_MAX) 2203 return (EINVAL); 2204 if (mode.resolution >= 200) 2205 mode.resolution = MOUSE_RES_HIGH; 2206 else if (mode.resolution >= 100) 2207 mode.resolution = MOUSE_RES_MEDIUMHIGH; 2208 else if (mode.resolution >= 50) 2209 mode.resolution = MOUSE_RES_MEDIUMLOW; 2210 else if (mode.resolution > 0) 2211 mode.resolution = MOUSE_RES_LOW; 2212 if (mode.resolution == MOUSE_RES_DEFAULT) 2213 mode.resolution = sc->dflt_mode.resolution; 2214 else if (mode.resolution == -1) 2215 /* don't change the current setting */ 2216 ; 2217 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */ 2218 mode.resolution = MOUSE_RES_LOW - mode.resolution; 2219 if (mode.level == -1) 2220 /* don't change the current setting */ 2221 mode.level = sc->mode.level; 2222 else if ((mode.level < PSM_LEVEL_MIN) || 2223 (mode.level > PSM_LEVEL_MAX)) 2224 return (EINVAL); 2225 if (mode.accelfactor == -1) 2226 /* don't change the current setting */ 2227 mode.accelfactor = sc->mode.accelfactor; 2228 else if (mode.accelfactor < 0) 2229 return (EINVAL); 2230 2231 /* don't allow anybody to poll the keyboard controller */ 2232 error = block_mouse_data(sc, &command_byte); 2233 if (error) 2234 return (error); 2235 2236 /* set mouse parameters */ 2237 if (mode.rate > 0) 2238 mode.rate = set_mouse_sampling_rate(sc->kbdc, 2239 mode.rate); 2240 if (mode.resolution >= 0) 2241 mode.resolution = 2242 set_mouse_resolution(sc->kbdc, mode.resolution); 2243 set_mouse_scaling(sc->kbdc, 1); 2244 get_mouse_status(sc->kbdc, stat, 0, 3); 2245 2246 lockmgr(&sc->lock, LK_EXCLUSIVE); 2247 sc->mode.rate = mode.rate; 2248 sc->mode.resolution = mode.resolution; 2249 sc->mode.accelfactor = mode.accelfactor; 2250 sc->mode.level = mode.level; 2251 lockmgr(&sc->lock, LK_RELEASE); 2252 2253 unblock_mouse_data(sc, command_byte); 2254 break; 2255 2256 case MOUSE_GETLEVEL: 2257 *(int *)addr = sc->mode.level; 2258 break; 2259 2260 case MOUSE_SETLEVEL: 2261 if ((*(int *)addr < PSM_LEVEL_MIN) || 2262 (*(int *)addr > PSM_LEVEL_MAX)) 2263 return (EINVAL); 2264 sc->mode.level = *(int *)addr; 2265 break; 2266 2267 case MOUSE_GETSTATUS: 2268 lockmgr(&sc->lock, LK_EXCLUSIVE); 2269 status = sc->status; 2270 sc->status.flags = 0; 2271 sc->status.obutton = sc->status.button; 2272 sc->status.button = 0; 2273 sc->status.dx = 0; 2274 sc->status.dy = 0; 2275 sc->status.dz = 0; 2276 lockmgr(&sc->lock, LK_RELEASE); 2277 *(mousestatus_t *)addr = status; 2278 break; 2279 2280 #if (defined(MOUSE_GETVARS)) 2281 case MOUSE_GETVARS: 2282 var = (mousevar_t *)addr; 2283 bzero(var, sizeof(*var)); 2284 lockmgr(&sc->lock, LK_EXCLUSIVE); 2285 var->var[0] = MOUSE_VARS_PS2_SIG; 2286 var->var[1] = sc->config; 2287 var->var[2] = sc->flags; 2288 lockmgr(&sc->lock, LK_RELEASE); 2289 break; 2290 2291 case MOUSE_SETVARS: 2292 return (ENODEV); 2293 #endif /* MOUSE_GETVARS */ 2294 2295 case MOUSE_READSTATE: 2296 case MOUSE_READDATA: 2297 data = (mousedata_t *)addr; 2298 if (data->len > sizeof(data->buf)/sizeof(data->buf[0])) 2299 return (EINVAL); 2300 2301 error = block_mouse_data(sc, &command_byte); 2302 if (error) 2303 return (error); 2304 if ((data->len = get_mouse_status(sc->kbdc, data->buf, 2305 (ap->a_cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0) 2306 error = EIO; 2307 unblock_mouse_data(sc, command_byte); 2308 break; 2309 2310 #if (defined(MOUSE_SETRESOLUTION)) 2311 case MOUSE_SETRESOLUTION: 2312 mode.resolution = *(int *)addr; 2313 if (mode.resolution >= UCHAR_MAX) 2314 return (EINVAL); 2315 else if (mode.resolution >= 200) 2316 mode.resolution = MOUSE_RES_HIGH; 2317 else if (mode.resolution >= 100) 2318 mode.resolution = MOUSE_RES_MEDIUMHIGH; 2319 else if (mode.resolution >= 50) 2320 mode.resolution = MOUSE_RES_MEDIUMLOW; 2321 else if (mode.resolution > 0) 2322 mode.resolution = MOUSE_RES_LOW; 2323 if (mode.resolution == MOUSE_RES_DEFAULT) 2324 mode.resolution = sc->dflt_mode.resolution; 2325 else if (mode.resolution == -1) 2326 mode.resolution = sc->mode.resolution; 2327 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */ 2328 mode.resolution = MOUSE_RES_LOW - mode.resolution; 2329 2330 error = block_mouse_data(sc, &command_byte); 2331 if (error) 2332 return (error); 2333 sc->mode.resolution = 2334 set_mouse_resolution(sc->kbdc, mode.resolution); 2335 if (sc->mode.resolution != mode.resolution) 2336 error = EIO; 2337 unblock_mouse_data(sc, command_byte); 2338 break; 2339 #endif /* MOUSE_SETRESOLUTION */ 2340 2341 #if (defined(MOUSE_SETRATE)) 2342 case MOUSE_SETRATE: 2343 mode.rate = *(int *)addr; 2344 if (mode.rate > UCHAR_MAX) 2345 return (EINVAL); 2346 if (mode.rate == 0) 2347 mode.rate = sc->dflt_mode.rate; 2348 else if (mode.rate < 0) 2349 mode.rate = sc->mode.rate; 2350 2351 error = block_mouse_data(sc, &command_byte); 2352 if (error) 2353 return (error); 2354 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate); 2355 if (sc->mode.rate != mode.rate) 2356 error = EIO; 2357 unblock_mouse_data(sc, command_byte); 2358 break; 2359 #endif /* MOUSE_SETRATE */ 2360 2361 #if (defined(MOUSE_SETSCALING)) 2362 case MOUSE_SETSCALING: 2363 if ((*(int *)addr <= 0) || (*(int *)addr > 2)) 2364 return (EINVAL); 2365 2366 error = block_mouse_data(sc, &command_byte); 2367 if (error) 2368 return (error); 2369 if (!set_mouse_scaling(sc->kbdc, *(int *)addr)) 2370 error = EIO; 2371 unblock_mouse_data(sc, command_byte); 2372 break; 2373 #endif /* MOUSE_SETSCALING */ 2374 2375 #if (defined(MOUSE_GETHWID)) 2376 case MOUSE_GETHWID: 2377 error = block_mouse_data(sc, &command_byte); 2378 if (error) 2379 return (error); 2380 sc->hw.hwid &= ~0x00ff; 2381 sc->hw.hwid |= get_aux_id(sc->kbdc); 2382 *(int *)addr = sc->hw.hwid & 0x00ff; 2383 unblock_mouse_data(sc, command_byte); 2384 break; 2385 #endif /* MOUSE_GETHWID */ 2386 2387 case FIONBIO: 2388 case FIOASYNC: 2389 break; 2390 case FIOSETOWN: 2391 break; 2392 case FIOGETOWN: 2393 break; 2394 default: 2395 return (ENOTTY); 2396 } 2397 2398 return (error); 2399 } 2400 2401 static void 2402 psmtimeout(void *arg) 2403 { 2404 2405 struct psm_softc *sc; 2406 2407 sc = (struct psm_softc *)arg; 2408 lockmgr(&sc->lock, LK_EXCLUSIVE); 2409 if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) { 2410 VLOG(4, (LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit)); 2411 psmintr(sc); 2412 kbdc_lock(sc->kbdc, FALSE); 2413 } 2414 sc->watchdog = TRUE; 2415 lockmgr(&sc->lock, LK_RELEASE); 2416 callout_reset(&sc->callout, hz, psmtimeout, (void *)(uintptr_t)sc); 2417 } 2418 2419 /* Add all sysctls under the debug.psm and hw.psm nodes */ 2420 SYSCTL_NODE(_debug, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse"); 2421 SYSCTL_NODE(_hw, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse"); 2422 2423 SYSCTL_INT(_debug_psm, OID_AUTO, loglevel, CTLFLAG_RW, &verbose, 0, 2424 "Verbosity level"); 2425 2426 static int psmhz = 20; 2427 SYSCTL_INT(_debug_psm, OID_AUTO, hz, CTLFLAG_RW, &psmhz, 0, 2428 "Frequency of the softcallout (in hz)"); 2429 static int psmerrsecs = 2; 2430 SYSCTL_INT(_debug_psm, OID_AUTO, errsecs, CTLFLAG_RW, &psmerrsecs, 0, 2431 "Number of seconds during which packets will dropped after a sync error"); 2432 static int psmerrusecs = 0; 2433 SYSCTL_INT(_debug_psm, OID_AUTO, errusecs, CTLFLAG_RW, &psmerrusecs, 0, 2434 "Microseconds to add to psmerrsecs"); 2435 static int psmsecs = 0; 2436 SYSCTL_INT(_debug_psm, OID_AUTO, secs, CTLFLAG_RW, &psmsecs, 0, 2437 "Max number of seconds between soft interrupts"); 2438 static int psmusecs = 500000; 2439 SYSCTL_INT(_debug_psm, OID_AUTO, usecs, CTLFLAG_RW, &psmusecs, 0, 2440 "Microseconds to add to psmsecs"); 2441 static int pkterrthresh = 2; 2442 SYSCTL_INT(_debug_psm, OID_AUTO, pkterrthresh, CTLFLAG_RW, &pkterrthresh, 0, 2443 "Number of error packets allowed before reinitializing the mouse"); 2444 2445 SYSCTL_INT(_hw_psm, OID_AUTO, tap_enabled, CTLFLAG_RW, &tap_enabled, 0, 2446 "Enable tap and drag gestures"); 2447 static int tap_threshold = PSM_TAP_THRESHOLD; 2448 SYSCTL_INT(_hw_psm, OID_AUTO, tap_threshold, CTLFLAG_RW, &tap_threshold, 0, 2449 "Button tap threshold"); 2450 static int tap_timeout = PSM_TAP_TIMEOUT; 2451 SYSCTL_INT(_hw_psm, OID_AUTO, tap_timeout, CTLFLAG_RW, &tap_timeout, 0, 2452 "Tap timeout for touchpads"); 2453 2454 /* Tunables; defined near top of file */ 2455 SYSCTL_INT(_hw_psm, OID_AUTO, synaptics_support, CTLFLAG_RD, 2456 &synaptics_support, 0, "Enable support for Synaptics touchpads"); 2457 2458 SYSCTL_INT(_hw_psm, OID_AUTO, trackpoint_support, CTLFLAG_RD, 2459 &trackpoint_support, 0, "Enable support for IBM/Lenovo TrackPoint"); 2460 2461 SYSCTL_INT(_hw_psm, OID_AUTO, elantech_support, CTLFLAG_RD, 2462 &elantech_support, 0, "Enable support for Elantech touchpads"); 2463 2464 static void 2465 psmintr(void *arg) 2466 { 2467 struct psm_softc *sc = arg; 2468 struct timeval now; 2469 int c; 2470 packetbuf_t *pb; 2471 2472 2473 /* read until there is nothing to read */ 2474 while((c = read_aux_data_no_wait(sc->kbdc)) != -1) { 2475 pb = &sc->pqueue[sc->pqueue_end]; 2476 2477 /* discard the byte if the device is not open */ 2478 if ((sc->state & PSM_OPEN) == 0) 2479 continue; 2480 2481 getmicrouptime(&now); 2482 if ((pb->inputbytes > 0) && 2483 timevalcmp(&now, &sc->inputtimeout, >)) { 2484 VLOG(3, (LOG_DEBUG, "psmintr: delay too long; " 2485 "resetting byte count\n")); 2486 pb->inputbytes = 0; 2487 sc->syncerrors = 0; 2488 sc->pkterrors = 0; 2489 } 2490 sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000; 2491 sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000; 2492 timevaladd(&sc->inputtimeout, &now); 2493 2494 pb->ipacket[pb->inputbytes++] = c; 2495 KKASSERT(pb->inputbytes <= sizeof(pb->ipacket)); 2496 2497 if (pb->inputbytes < sc->mode.packetsize) 2498 continue; 2499 2500 VLOG(4, (LOG_DEBUG, 2501 "psmintr: %02x %02x %02x %02x %02x %02x\n", 2502 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], 2503 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); 2504 2505 c = pb->ipacket[0]; 2506 2507 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) { 2508 sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]); 2509 sc->flags &= ~PSM_NEED_SYNCBITS; 2510 VLOG(2, (LOG_DEBUG, 2511 "psmintr: Sync bytes now %04x,%04x\n", 2512 sc->mode.syncmask[0], sc->mode.syncmask[0])); 2513 } else if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) { 2514 VLOG(3, (LOG_DEBUG, "psmintr: out of sync " 2515 "(%04x != %04x) %d cmds since last error.\n", 2516 c & sc->mode.syncmask[0], sc->mode.syncmask[1], 2517 sc->cmdcount - sc->lasterr)); 2518 sc->lasterr = sc->cmdcount; 2519 /* 2520 * The sync byte test is a weak measure of packet 2521 * validity. 2522 */ 2523 if (sc->syncerrors == 0) 2524 sc->pkterrors++; 2525 ++sc->syncerrors; 2526 if (sc->syncerrors >= sc->mode.packetsize * 2 || 2527 sc->pkterrors >= pkterrthresh) { 2528 /* 2529 * If we've failed to find a single sync byte 2530 * in 2 packets worth of data, or we've seen 2531 * persistent packet errors during the 2532 * validation period, reinitialize the mouse 2533 * in hopes of returning it to the expected 2534 * mode. 2535 * 2536 * reset inputbytes in case reinitialize() 2537 * fails to prevent it from incrementing 2538 * forever. 2539 */ 2540 VLOG(3, (LOG_DEBUG, 2541 "psmintr: reset the mouse.\n")); 2542 sc->lastinputerr = now; 2543 dropqueue(sc); 2544 pb->inputbytes = 0; 2545 reinitialize(sc, TRUE); 2546 } else if (sc->syncerrors == sc->mode.packetsize) { 2547 /* 2548 * Try a soft reset after searching for a sync 2549 * byte through a packet length of bytes. 2550 */ 2551 VLOG(3, (LOG_DEBUG, 2552 "psmintr: re-enable the mouse.\n")); 2553 sc->lastinputerr = now; 2554 dropqueue(sc); 2555 pb->inputbytes = 0; 2556 disable_aux_dev(sc->kbdc); 2557 enable_aux_dev(sc->kbdc); 2558 } else { 2559 VLOG(3, (LOG_DEBUG, 2560 "psmintr: discard a byte (%d)\n", 2561 sc->syncerrors)); 2562 pb->inputbytes--; 2563 bcopy(&pb->ipacket[1], &pb->ipacket[0], 2564 pb->inputbytes); 2565 } 2566 continue; 2567 } 2568 2569 /* 2570 * We have what appears to be a valid packet. 2571 * Reset the error counters. 2572 */ 2573 sc->syncerrors = 0; 2574 2575 /* 2576 * Drop even good packets if they occur within a timeout 2577 * period of a sync error. This allows the detection of 2578 * a change in the mouse's packet mode without exposing 2579 * erratic mouse behavior to the user. Some KVMs forget 2580 * enhanced mouse modes during switch events. 2581 */ 2582 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs, 2583 &now)) { 2584 pb->inputbytes = 0; 2585 continue; 2586 } 2587 2588 /* 2589 * Now that we're out of the validation period, reset 2590 * the packet error count. 2591 */ 2592 sc->pkterrors = 0; 2593 2594 sc->cmdcount++; 2595 if (++sc->pqueue_end >= PSM_PACKETQUEUE) 2596 sc->pqueue_end = 0; 2597 /* 2598 * If we've filled the queue then call the softintr ourselves, 2599 * otherwise schedule the interrupt for later. 2600 */ 2601 if (!timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) || 2602 (sc->pqueue_end == sc->pqueue_start)) { 2603 if ((sc->state & PSM_SOFTARMED) != 0) { 2604 sc->state &= ~PSM_SOFTARMED; 2605 callout_stop(&sc->softcallout); 2606 } 2607 psmsoftintr(arg); 2608 } else if ((sc->state & PSM_SOFTARMED) == 0) { 2609 sc->state |= PSM_SOFTARMED; 2610 callout_reset(&sc->softcallout, psmhz < 1 ? 1 : (hz/psmhz), 2611 psmsoftintr, arg); 2612 } 2613 } 2614 } 2615 2616 static void 2617 proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 2618 int *x, int *y, int *z) 2619 { 2620 2621 /* 2622 * PS2++ protocl packet 2623 * 2624 * b7 b6 b5 b4 b3 b2 b1 b0 2625 * byte 1: * 1 p3 p2 1 * * * 2626 * byte 2: c1 c2 p1 p0 d1 d0 1 0 2627 * 2628 * p3-p0: packet type 2629 * c1, c2: c1 & c2 == 1, if p2 == 0 2630 * c1 & c2 == 0, if p2 == 1 2631 * 2632 * packet type: 0 (device type) 2633 * See comments in enable_mmanplus() below. 2634 * 2635 * packet type: 1 (wheel data) 2636 * 2637 * b7 b6 b5 b4 b3 b2 b1 b0 2638 * byte 3: h * B5 B4 s d2 d1 d0 2639 * 2640 * h: 1, if horizontal roller data 2641 * 0, if vertical roller data 2642 * B4, B5: button 4 and 5 2643 * s: sign bit 2644 * d2-d0: roller data 2645 * 2646 * packet type: 2 (reserved) 2647 */ 2648 if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) && 2649 (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) { 2650 /* 2651 * the extended data packet encodes button 2652 * and wheel events 2653 */ 2654 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) { 2655 case 1: 2656 /* wheel data packet */ 2657 *x = *y = 0; 2658 if (pb->ipacket[2] & 0x80) { 2659 /* XXX horizontal roller count - ignore it */ 2660 ; 2661 } else { 2662 /* vertical roller count */ 2663 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ? 2664 (pb->ipacket[2] & 0x0f) - 16 : 2665 (pb->ipacket[2] & 0x0f); 2666 } 2667 ms->button |= (pb->ipacket[2] & 2668 MOUSE_PS2PLUS_BUTTON4DOWN) ? 2669 MOUSE_BUTTON4DOWN : 0; 2670 ms->button |= (pb->ipacket[2] & 2671 MOUSE_PS2PLUS_BUTTON5DOWN) ? 2672 MOUSE_BUTTON5DOWN : 0; 2673 break; 2674 case 2: 2675 /* 2676 * this packet type is reserved by 2677 * Logitech... 2678 */ 2679 /* 2680 * IBM ScrollPoint Mouse uses this 2681 * packet type to encode both vertical 2682 * and horizontal scroll movement. 2683 */ 2684 *x = *y = 0; 2685 /* horizontal count */ 2686 if (pb->ipacket[2] & 0x0f) 2687 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ? 2688 -2 : 2; 2689 /* vertical count */ 2690 if (pb->ipacket[2] & 0xf0) 2691 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ? 2692 -1 : 1; 2693 break; 2694 case 0: 2695 /* device type packet - shouldn't happen 2696 * 2697 * XXX: if this shouldn't happen, shouldn't we at least 2698 * add a kprintf indiciating to the user something bad 2699 * happened or is it that prevalent that it'd spam? -htse 2700 * 2701 * */ 2702 /* FALLTHROUGH */ 2703 default: 2704 *x = *y = 0; 2705 ms->button = ms->obutton; 2706 VLOG(1, (LOG_DEBUG, "psmintr: unknown PS2++ packet " 2707 "type %d: 0x%02x 0x%02x 0x%02x\n", 2708 MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket), 2709 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2])); 2710 break; 2711 } 2712 } else { 2713 /* preserve button states */ 2714 ms->button |= ms->obutton & MOUSE_EXTBUTTONS; 2715 } 2716 } 2717 2718 static int 2719 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 2720 int *x, int *y, int *z) 2721 { 2722 static int touchpad_buttons; 2723 static int guest_buttons; 2724 static finger_t f[PSM_FINGERS]; 2725 int w, id, nfingers, ewcode, extended_buttons; 2726 2727 extended_buttons = 0; 2728 2729 /* TouchPad PS/2 absolute mode message format with capFourButtons: 2730 * 2731 * Bits: 7 6 5 4 3 2 1 0 (LSB) 2732 * ------------------------------------------------ 2733 * ipacket[0]: 1 0 W3 W2 0 W1 R L 2734 * ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8 2735 * ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 2736 * ipacket[3]: 1 1 Yc Xc 0 W0 D U 2737 * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 2738 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 2739 * 2740 * Legend: 2741 * L: left physical mouse button 2742 * R: right physical mouse button 2743 * D: down button 2744 * U: up button 2745 * W: "wrist" value 2746 * X: x position 2747 * Y: y position 2748 * Z: pressure 2749 * 2750 * 2751 * Without capFourButtons but with nExtendeButtons and/or capMiddle 2752 * 2753 * Bits: 7 6 5 4 3 2 1 0 (LSB) 2754 * ------------------------------------------------------ 2755 * ipacket[3]: 1 1 Yc Xc 0 W0 E^R M^L 2756 * ipacket[4]: X7 X6 X5 X4 X3|b7 X2|b5 X1|b3 X0|b1 2757 * ipacket[5]: Y7 Y6 Y5 Y4 Y3|b8 Y2|b6 Y1|b4 Y0|b2 2758 * 2759 * Legend: 2760 * M: Middle physical mouse button 2761 * E: Extended mouse buttons reported instead of low bits of X and Y 2762 * b1-b8: Extended mouse buttons 2763 * Only ((nExtendedButtons + 1) >> 1) bits are used in packet 2764 * 4 and 5, for reading X and Y value they should be zeroed. 2765 * 2766 * Absolute reportable limits: 0 - 6143. 2767 * Typical bezel limits: 1472 - 5472. 2768 * Typical edge marings: 1632 - 5312. 2769 * 2770 * w = 3 Passthrough Packet 2771 * 2772 * Byte 2,5,6 == Byte 1,2,3 of "Guest" 2773 */ 2774 2775 if (!synaptics_support) 2776 return (0); 2777 2778 /* Sanity check for out of sync packets. */ 2779 if ((pb->ipacket[0] & 0xc8) != 0x80 || 2780 (pb->ipacket[3] & 0xc8) != 0xc0) 2781 return (-1); 2782 2783 *x = *y = 0; 2784 ms->button = ms->obutton; 2785 2786 /* 2787 * Pressure value. 2788 * Interpretation: 2789 * z = 0 No finger contact 2790 * z = 10 Finger hovering near the pad 2791 * z = 30 Very light finger contact 2792 * z = 80 Normal finger contact 2793 * z = 110 Very heavy finger contact 2794 * z = 200 Finger lying flat on pad surface 2795 * z = 255 Maximum reportable Z 2796 */ 2797 *z = pb->ipacket[2]; 2798 2799 /* 2800 * Finger width value 2801 * Interpretation: 2802 * w = 0 Two finger on the pad (capMultiFinger needed) 2803 * w = 1 Three or more fingers (capMultiFinger needed) 2804 * w = 2 Pen (instead of finger) (capPen needed) 2805 * w = 3 Reserved (passthrough?) 2806 * w = 4-7 Finger of normal width (capPalmDetect needed) 2807 * w = 8-14 Very wide finger or palm (capPalmDetect needed) 2808 * w = 15 Maximum reportable width (capPalmDetect needed) 2809 */ 2810 /* XXX Is checking capExtended enough? */ 2811 if (sc->synhw.capExtended) { 2812 w = ((pb->ipacket[0] & 0x30) >> 2) | 2813 ((pb->ipacket[0] & 0x04) >> 1) | 2814 ((pb->ipacket[3] & 0x04) >> 2); 2815 } 2816 else { 2817 /* Assume a finger of regular width. */ 2818 w = 4; 2819 } 2820 2821 switch (w) { 2822 case 3: 2823 /* 2824 * Handle packets from the guest device. See: 2825 * Synaptics PS/2 TouchPad Interfacing Guide, Section 5.1 2826 */ 2827 if (sc->synhw.capPassthrough) { 2828 *x = ((pb->ipacket[1] & 0x10) ? 2829 pb->ipacket[4] - 256 : pb->ipacket[4]); 2830 *y = ((pb->ipacket[1] & 0x20) ? 2831 pb->ipacket[5] - 256 : pb->ipacket[5]); 2832 *z = 0; 2833 2834 guest_buttons = 0; 2835 if (pb->ipacket[1] & 0x01) 2836 guest_buttons |= MOUSE_BUTTON1DOWN; 2837 if (pb->ipacket[1] & 0x04) 2838 guest_buttons |= MOUSE_BUTTON2DOWN; 2839 if (pb->ipacket[1] & 0x02) 2840 guest_buttons |= MOUSE_BUTTON3DOWN; 2841 2842 ms->button = touchpad_buttons | guest_buttons | 2843 sc->extended_buttons; 2844 } 2845 goto SYNAPTICS_END; 2846 2847 case 2: 2848 /* Handle Extended W mode packets */ 2849 ewcode = (pb->ipacket[5] & 0xf0) >> 4; 2850 #if PSM_FINGERS > 1 2851 switch (ewcode) { 2852 case 1: 2853 /* Secondary finger */ 2854 if (sc->synhw.capAdvancedGestures) 2855 f[1] = (finger_t) { 2856 .x = (((pb->ipacket[4] & 0x0f) << 8) | 2857 pb->ipacket[1]) << 1, 2858 .y = (((pb->ipacket[4] & 0xf0) << 4) | 2859 pb->ipacket[2]) << 1, 2860 .p = ((pb->ipacket[3] & 0x30) | 2861 (pb->ipacket[5] & 0x0f)) << 1, 2862 .w = PSM_FINGER_DEFAULT_W, 2863 .flags = PSM_FINGER_FUZZY, 2864 }; 2865 else if (sc->synhw.capReportsV) 2866 f[1] = (finger_t) { 2867 .x = (((pb->ipacket[4] & 0x0f) << 8) | 2868 (pb->ipacket[1] & 0xfe)) << 1, 2869 .y = (((pb->ipacket[4] & 0xf0) << 4) | 2870 (pb->ipacket[2] & 0xfe)) << 1, 2871 .p = ((pb->ipacket[3] & 0x30) | 2872 (pb->ipacket[5] & 0x0e)) << 1, 2873 .w = (((pb->ipacket[5] & 0x01) << 2) | 2874 ((pb->ipacket[2] & 0x01) << 1) | 2875 (pb->ipacket[1] & 0x01)) + 8, 2876 .flags = PSM_FINGER_FUZZY, 2877 }; 2878 default: 2879 break; 2880 } 2881 #endif 2882 goto SYNAPTICS_END; 2883 2884 case 1: 2885 case 0: 2886 nfingers = w + 2; 2887 break; 2888 2889 default: 2890 nfingers = 1; 2891 } 2892 2893 if (sc->syninfo.touchpad_off) 2894 goto SYNAPTICS_END; 2895 2896 /* Button presses */ 2897 touchpad_buttons = 0; 2898 if (pb->ipacket[0] & 0x01) 2899 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2900 if (pb->ipacket[0] & 0x02) 2901 touchpad_buttons |= MOUSE_BUTTON3DOWN; 2902 2903 if (sc->synhw.capExtended && sc->synhw.capFourButtons) { 2904 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01) 2905 touchpad_buttons |= MOUSE_BUTTON4DOWN; 2906 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02) 2907 touchpad_buttons |= MOUSE_BUTTON5DOWN; 2908 } else if (sc->synhw.capExtended && sc->synhw.capMiddle && 2909 !sc->synhw.capClickPad) { 2910 /* Middle Button */ 2911 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01) 2912 touchpad_buttons |= MOUSE_BUTTON2DOWN; 2913 } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) { 2914 /* Extended Buttons */ 2915 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) { 2916 if (sc->syninfo.directional_scrolls) { 2917 if (pb->ipacket[4] & 0x01) 2918 extended_buttons |= MOUSE_BUTTON4DOWN; 2919 if (pb->ipacket[5] & 0x01) 2920 extended_buttons |= MOUSE_BUTTON5DOWN; 2921 if (pb->ipacket[4] & 0x02) 2922 extended_buttons |= MOUSE_BUTTON6DOWN; 2923 if (pb->ipacket[5] & 0x02) 2924 extended_buttons |= MOUSE_BUTTON7DOWN; 2925 } else { 2926 if (pb->ipacket[4] & 0x01) 2927 extended_buttons |= MOUSE_BUTTON1DOWN; 2928 if (pb->ipacket[5] & 0x01) 2929 extended_buttons |= MOUSE_BUTTON3DOWN; 2930 if (pb->ipacket[4] & 0x02) 2931 extended_buttons |= MOUSE_BUTTON2DOWN; 2932 sc->extended_buttons = extended_buttons; 2933 } 2934 2935 /* 2936 * Zero out bits used by extended buttons to avoid 2937 * misinterpretation of the data absolute position. 2938 * 2939 * The bits represented by 2940 * 2941 * (nExtendedButtons + 1) >> 1 2942 * 2943 * will be masked out in both bytes. 2944 * The mask for n bits is computed with the formula 2945 * 2946 * (1 << n) - 1 2947 */ 2948 int maskedbits = 0; 2949 int mask = 0; 2950 maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; 2951 mask = (1 << maskedbits) - 1; 2952 pb->ipacket[4] &= ~(mask); 2953 pb->ipacket[5] &= ~(mask); 2954 } else if (!sc->syninfo.directional_scrolls && 2955 !sc->gesture.in_vscroll) { 2956 /* 2957 * Keep reporting MOUSE DOWN until we get a new packet 2958 * indicating otherwise. 2959 */ 2960 extended_buttons |= sc->extended_buttons; 2961 } 2962 } 2963 /* Handle ClickPad */ 2964 if (sc->synhw.capClickPad && 2965 ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) 2966 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2967 2968 if (sc->synhw.capReportsV && nfingers > 1) 2969 f[0] = (finger_t) { 2970 .x = ((pb->ipacket[3] & 0x10) << 8) | 2971 ((pb->ipacket[1] & 0x0f) << 8) | 2972 (pb->ipacket[4] & 0xfd), 2973 .y = ((pb->ipacket[3] & 0x20) << 7) | 2974 ((pb->ipacket[1] & 0xf0) << 4) | 2975 (pb->ipacket[5] & 0xfd), 2976 .p = *z & 0xfe, 2977 .w = (((pb->ipacket[2] & 0x01) << 2) | 2978 (pb->ipacket[5] & 0x02) | 2979 ((pb->ipacket[4] & 0x02) >> 1)) + 8, 2980 .flags = PSM_FINGER_FUZZY, 2981 }; 2982 else 2983 f[0] = (finger_t) { 2984 .x = ((pb->ipacket[3] & 0x10) << 8) | 2985 ((pb->ipacket[1] & 0x0f) << 8) | 2986 pb->ipacket[4], 2987 .y = ((pb->ipacket[3] & 0x20) << 7) | 2988 ((pb->ipacket[1] & 0xf0) << 4) | 2989 pb->ipacket[5], 2990 .p = *z, 2991 .w = w, 2992 .flags = nfingers > 1 ? PSM_FINGER_FUZZY : 0, 2993 }; 2994 2995 /* Ignore hovering and unmeasurable touches */ 2996 if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) 2997 nfingers = 0; 2998 2999 for (id = 0; id < PSM_FINGERS; id++) 3000 if (id >= nfingers) 3001 PSM_FINGER_RESET(f[id]); 3002 3003 ms->button = touchpad_buttons; 3004 3005 /* Palm detection doesn't terminate the current action. */ 3006 if (!psmpalmdetect(sc, &f[0], nfingers)) { 3007 psmgestures(sc, &f[0], nfingers, ms); 3008 for (id = 0; id < PSM_FINGERS; id++) 3009 psmsmoother(sc, &f[id], id, ms, x, y); 3010 } else { 3011 VLOG(2, (LOG_DEBUG, "synaptics: palm detected! (%d)\n", f[0].w)); 3012 } 3013 3014 ms->button |= extended_buttons | guest_buttons; 3015 3016 3017 3018 SYNAPTICS_END: 3019 /* 3020 * Use the extra buttons as a scrollwheel 3021 * 3022 * XXX X.Org uses the Z axis for vertical wheel only, 3023 * whereas moused(8) understands special values to differ 3024 * vertical and horizontal wheels. 3025 * 3026 * xf86-input-mouse needs therefore a small patch to 3027 * understand these special values. Without it, the 3028 * horizontal wheel acts as a vertical wheel in X.Org. 3029 * 3030 * That's why the horizontal wheel is disabled by 3031 * default for now. 3032 */ 3033 if (ms->button & MOUSE_BUTTON4DOWN) { 3034 *z = -1; 3035 } else if (ms->button & MOUSE_BUTTON5DOWN) { 3036 *z = 1; 3037 } else if (ms->button & MOUSE_BUTTON6DOWN) { 3038 *z = -2; 3039 } else if (ms->button & MOUSE_BUTTON7DOWN) { 3040 *z = 2; 3041 } else 3042 *z = 0; 3043 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN | 3044 MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN); 3045 3046 return (0); 3047 } 3048 3049 static int 3050 psmpalmdetect(struct psm_softc *sc, finger_t *f, int nfingers) 3051 { 3052 if (!( 3053 ((sc->synhw.capMultiFinger || 3054 sc->synhw.capAdvancedGestures) && nfingers > 1) || 3055 (sc->synhw.capPalmDetect && f->w <= sc->syninfo.max_width) || 3056 (!sc->synhw.capPalmDetect && f->p <= sc->syninfo.max_pressure) || 3057 (sc->synhw.capPen && f->flags & PSM_FINGER_IS_PEN))) { 3058 /* 3059 * We consider the packet irrelevant for the current 3060 * action when: 3061 * - the width isn't comprised in: 3062 * [1; max_width] 3063 * - the pressure isn't comprised in: 3064 * [min_pressure; max_pressure] 3065 * - pen aren't supported but PSM_FINGER_IS_PEN is set 3066 */ 3067 return (1); 3068 } 3069 return (0); 3070 } 3071 3072 static void 3073 psmgestures(struct psm_softc *sc, finger_t *fingers, int nfingers, 3074 mousestatus_t *ms) 3075 { 3076 smoother_t *smoother; 3077 gesture_t *gest; 3078 finger_t *f; 3079 int y_ok, center_button, center_x, right_button, right_x, i; 3080 3081 f = &fingers[0]; 3082 smoother = &sc->smoother[0]; 3083 gest = &sc->gesture; 3084 3085 /* Find first active finger. */ 3086 if (nfingers > 0) { 3087 for (i = 0; i < PSM_FINGERS; i++) { 3088 if (PSM_FINGER_IS_SET(fingers[i])) { 3089 f = &fingers[i]; 3090 smoother = &sc->smoother[i]; 3091 break; 3092 } 3093 } 3094 } 3095 3096 /* 3097 * Check pressure to detect a real wanted action on the 3098 * touchpad. 3099 */ 3100 if (f->p >= sc->syninfo.min_pressure) { 3101 int x0, y0; 3102 int dxp, dyp; 3103 int start_x, start_y; 3104 int queue_len; 3105 int margin_top, margin_right, margin_bottom, margin_left; 3106 int window_min, window_max; 3107 int vscroll_hor_area, vscroll_ver_area; 3108 int two_finger_scroll; 3109 int max_x, max_y; 3110 3111 /* silence gcc warnings for last VLOG call */ 3112 dxp = dyp = 0; 3113 3114 /* Read sysctl. */ 3115 /* XXX Verify values? */ 3116 margin_top = sc->syninfo.margin_top; 3117 margin_right = sc->syninfo.margin_right; 3118 margin_bottom = sc->syninfo.margin_bottom; 3119 margin_left = sc->syninfo.margin_left; 3120 window_min = sc->syninfo.window_min; 3121 window_max = sc->syninfo.window_max; 3122 vscroll_hor_area = sc->syninfo.vscroll_hor_area; 3123 vscroll_ver_area = sc->syninfo.vscroll_ver_area; 3124 two_finger_scroll = sc->syninfo.two_finger_scroll; 3125 max_x = sc->syninfo.max_x; 3126 max_y = sc->syninfo.max_y; 3127 3128 /* Read current absolute position. */ 3129 x0 = f->x; 3130 y0 = f->y; 3131 3132 /* 3133 * Limit the coordinates to the specified margins because 3134 * this area isn't very reliable. 3135 */ 3136 if (x0 <= margin_left) 3137 x0 = margin_left; 3138 else if (x0 >= max_x - margin_right) 3139 x0 = max_x - margin_right; 3140 if (y0 <= margin_bottom) 3141 y0 = margin_bottom; 3142 else if (y0 >= max_y - margin_top) 3143 y0 = max_y - margin_top; 3144 3145 VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", 3146 x0, y0, f->p, f->w)); 3147 3148 /* 3149 * If the action is just beginning, init the structure and 3150 * compute tap timeout. 3151 */ 3152 if (!(sc->flags & PSM_FLAGS_FINGERDOWN)) { 3153 VLOG(3, (LOG_DEBUG, "synaptics: ----\n")); 3154 3155 /* Initialize queue. */ 3156 gest->window_min = window_min; 3157 3158 /* Reset pressure peak. */ 3159 gest->zmax = 0; 3160 3161 /* Reset fingers count. */ 3162 gest->fingers_nb = 0; 3163 3164 /* Reset virtual scrolling state. */ 3165 gest->in_vscroll = 0; 3166 3167 /* Compute tap timeout. */ 3168 gest->taptimeout.tv_sec = tap_timeout / 1000000; 3169 gest->taptimeout.tv_usec = tap_timeout % 1000000; 3170 timevaladd(&gest->taptimeout, &sc->lastsoftintr); 3171 3172 sc->flags |= PSM_FLAGS_FINGERDOWN; 3173 3174 /* Smoother has not been reset yet */ 3175 queue_len = 1; 3176 start_x = x0; 3177 start_y = y0; 3178 } else { 3179 queue_len = smoother->queue_len + 1; 3180 start_x = smoother->start_x; 3181 start_y = smoother->start_y; 3182 } 3183 3184 /* Process ClickPad softbuttons */ 3185 if (sc->synhw.capClickPad && ms->button & MOUSE_BUTTON1DOWN) { 3186 y_ok = sc->syninfo.softbuttons_y >= 0 ? 3187 start_y < sc->syninfo.softbuttons_y : 3188 start_y > max_y - sc->syninfo.softbuttons_y; 3189 3190 center_button = MOUSE_BUTTON2DOWN; 3191 center_x = sc->syninfo.softbutton2_x; 3192 right_button = MOUSE_BUTTON3DOWN; 3193 right_x = sc->syninfo.softbutton3_x; 3194 3195 if (center_x > 0 && right_x > 0 && center_x > right_x) { 3196 center_button = MOUSE_BUTTON3DOWN; 3197 center_x = sc->syninfo.softbutton3_x; 3198 right_button = MOUSE_BUTTON2DOWN; 3199 right_x = sc->syninfo.softbutton2_x; 3200 } 3201 3202 if (right_x > 0 && start_x > right_x && y_ok) 3203 ms->button = (ms->button & 3204 ~MOUSE_BUTTON1DOWN) | right_button; 3205 else if (center_x > 0 && start_x > center_x && y_ok) 3206 ms->button = (ms->button & 3207 ~MOUSE_BUTTON1DOWN) | center_button; 3208 } 3209 3210 /* If in tap-hold, add the recorded button. */ 3211 if (gest->in_taphold) 3212 ms->button |= gest->tap_button; 3213 3214 /* 3215 * For tap, we keep the maximum number of fingers and the 3216 * pressure peak. Also with multiple fingers, we increase 3217 * the minimum window. 3218 */ 3219 if (nfingers > 1) 3220 gest->window_min = window_max; 3221 gest->fingers_nb = imax(nfingers, gest->fingers_nb); 3222 gest->zmax = imax(f->p, gest->zmax); 3223 3224 /* Do we have enough packets to consider this a gesture? */ 3225 if (queue_len < gest->window_min) 3226 return; 3227 3228 /* Is a scrolling action occurring? */ 3229 if (!gest->in_taphold && !ms->button && 3230 (!gest->in_vscroll || two_finger_scroll)) { 3231 /* 3232 * A scrolling action must not conflict with a tap 3233 * action. Here are the conditions to consider a 3234 * scrolling action: 3235 * - the action in a configurable area 3236 * - one of the following: 3237 * . the distance between the last packet and the 3238 * first should be above a configurable minimum 3239 * . tap timed out 3240 */ 3241 dxp = abs(x0 - start_x); 3242 dyp = abs(y0 - start_y); 3243 3244 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, >) || 3245 dxp >= sc->syninfo.vscroll_min_delta || 3246 dyp >= sc->syninfo.vscroll_min_delta) { 3247 /* 3248 * Handle two finger scrolling. 3249 * Note that we don't rely on fingers_nb 3250 * as that keeps the maximum number of fingers. 3251 */ 3252 if (two_finger_scroll) { 3253 if (nfingers == 2) { 3254 gest->in_vscroll += 3255 dyp ? 2 : 0; 3256 gest->in_vscroll += 3257 dxp ? 1 : 0; 3258 } 3259 } else { 3260 /* Check for horizontal scrolling. */ 3261 if ((vscroll_hor_area > 0 && 3262 start_y <= vscroll_hor_area) || 3263 (vscroll_hor_area < 0 && 3264 start_y >= 3265 max_y + vscroll_hor_area)) 3266 gest->in_vscroll += 2; 3267 3268 /* Check for vertical scrolling. */ 3269 if ((vscroll_ver_area > 0 && 3270 start_x <= vscroll_ver_area) || 3271 (vscroll_ver_area < 0 && 3272 start_x >= 3273 max_x + vscroll_ver_area)) 3274 gest->in_vscroll += 1; 3275 } 3276 3277 /* Avoid conflicts if area overlaps. */ 3278 if (gest->in_vscroll >= 3) 3279 gest->in_vscroll = 3280 (dxp > dyp) ? 2 : 1; 3281 } 3282 } 3283 /* 3284 * Reset two finger scrolling when the number of fingers 3285 * is different from two or any button is pressed. 3286 */ 3287 if (two_finger_scroll && gest->in_vscroll != 0 && 3288 (nfingers != 2 || ms->button)) 3289 gest->in_vscroll = 0; 3290 3291 VLOG(5, (LOG_DEBUG, 3292 "synaptics: virtual scrolling: %s " 3293 "(direction=%d, dxp=%d, dyp=%d, fingers=%d)\n", 3294 gest->in_vscroll ? "YES" : "NO", 3295 gest->in_vscroll, dxp, dyp, 3296 gest->fingers_nb)); 3297 3298 } else if (sc->flags & PSM_FLAGS_FINGERDOWN) { 3299 /* 3300 * An action is currently taking place but the pressure 3301 * dropped under the minimum, putting an end to it. 3302 */ 3303 int taphold_timeout, dx, dy, tap_max_delta; 3304 3305 dx = abs(smoother->queue[smoother->queue_cursor].x - 3306 smoother->start_x); 3307 dy = abs(smoother->queue[smoother->queue_cursor].y - 3308 smoother->start_y); 3309 3310 /* Max delta is disabled for multi-fingers tap. */ 3311 if (gest->fingers_nb > 1) 3312 tap_max_delta = imax(dx, dy); 3313 else 3314 tap_max_delta = sc->syninfo.tap_max_delta; 3315 3316 sc->flags &= ~PSM_FLAGS_FINGERDOWN; 3317 3318 /* Check for tap. */ 3319 VLOG(3, (LOG_DEBUG, 3320 "synaptics: zmax=%d, dx=%d, dy=%d, " 3321 "delta=%d, fingers=%d, queue=%d\n", 3322 gest->zmax, dx, dy, tap_max_delta, gest->fingers_nb, 3323 smoother->queue_len)); 3324 if (!gest->in_vscroll && gest->zmax >= tap_threshold && 3325 timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=) && 3326 dx <= tap_max_delta && dy <= tap_max_delta && 3327 smoother->queue_len >= sc->syninfo.tap_min_queue) { 3328 /* 3329 * We have a tap if: 3330 * - the maximum pressure went over tap_threshold 3331 * - the action ended before tap_timeout 3332 * 3333 * To handle tap-hold, we must delay any button push to 3334 * the next action. 3335 */ 3336 if (gest->in_taphold) { 3337 /* 3338 * This is the second and last tap of a 3339 * double tap action, not a tap-hold. 3340 */ 3341 gest->in_taphold = 0; 3342 3343 /* 3344 * For double-tap to work: 3345 * - no button press is emitted (to 3346 * simulate a button release) 3347 * - PSM_FLAGS_FINGERDOWN is set to 3348 * force the next packet to emit a 3349 * button press) 3350 */ 3351 VLOG(2, (LOG_DEBUG, 3352 "synaptics: button RELEASE: %d\n", 3353 gest->tap_button)); 3354 sc->flags |= PSM_FLAGS_FINGERDOWN; 3355 3356 /* Schedule button press on next interrupt */ 3357 sc->idletimeout.tv_sec = psmhz > 1 ? 3358 0 : 1; 3359 sc->idletimeout.tv_usec = psmhz > 1 ? 3360 1000000 / psmhz : 0; 3361 } else { 3362 /* 3363 * This is the first tap: we set the 3364 * tap-hold state and notify the button 3365 * down event. 3366 */ 3367 gest->in_taphold = 1; 3368 taphold_timeout = sc->syninfo.taphold_timeout; 3369 gest->taptimeout.tv_sec = taphold_timeout / 3370 1000000; 3371 gest->taptimeout.tv_usec = taphold_timeout % 3372 1000000; 3373 sc->idletimeout = gest->taptimeout; 3374 timevaladd(&gest->taptimeout, 3375 &sc->lastsoftintr); 3376 3377 switch (gest->fingers_nb) { 3378 case 3: 3379 gest->tap_button = 3380 MOUSE_BUTTON2DOWN; 3381 break; 3382 case 2: 3383 gest->tap_button = 3384 MOUSE_BUTTON3DOWN; 3385 break; 3386 default: 3387 gest->tap_button = 3388 MOUSE_BUTTON1DOWN; 3389 } 3390 VLOG(2, (LOG_DEBUG, 3391 "synaptics: button PRESS: %d\n", 3392 gest->tap_button)); 3393 ms->button |= gest->tap_button; 3394 } 3395 } else { 3396 /* 3397 * Not enough pressure or timeout: reset 3398 * tap-hold state. 3399 */ 3400 if (gest->in_taphold) { 3401 VLOG(2, (LOG_DEBUG, 3402 "synaptics: button RELEASE: %d\n", 3403 gest->tap_button)); 3404 gest->in_taphold = 0; 3405 } else { 3406 VLOG(2, (LOG_DEBUG, 3407 "synaptics: not a tap-hold\n")); 3408 } 3409 } 3410 } else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && gest->in_taphold) { 3411 /* 3412 * For a tap-hold to work, the button must remain down at 3413 * least until timeout (where the in_taphold flags will be 3414 * cleared) or during the next action. 3415 */ 3416 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=)) { 3417 ms->button |= gest->tap_button; 3418 } else { 3419 VLOG(2, (LOG_DEBUG, "synaptics: button RELEASE: %d\n", 3420 gest->tap_button)); 3421 gest->in_taphold = 0; 3422 } 3423 } 3424 3425 return; 3426 } 3427 3428 static void 3429 psmsmoother(struct psm_softc *sc, finger_t *f, int smoother_id, 3430 mousestatus_t *ms, int *x, int *y) 3431 { 3432 smoother_t *smoother = &sc->smoother[smoother_id]; 3433 gesture_t *gest = &(sc->gesture); 3434 3435 /* 3436 * Check pressure to detect a real wanted action on the 3437 * touchpad. 3438 */ 3439 if (f->p >= sc->syninfo.min_pressure) { 3440 int x0, y0; 3441 int cursor, peer, window; 3442 int dx, dy, dxp, dyp; 3443 int max_width, max_pressure; 3444 int margin_top, margin_right, margin_bottom, margin_left; 3445 int na_top, na_right, na_bottom, na_left; 3446 int window_min, window_max; 3447 int multiplicator; 3448 int weight_current, weight_previous, weight_len_squared; 3449 int div_min, div_max, div_len; 3450 int vscroll_hor_area, vscroll_ver_area; 3451 int two_finger_scroll; 3452 int max_x, max_y; 3453 int len, weight_prev_x, weight_prev_y; 3454 int div_max_x, div_max_y, div_x, div_y; 3455 int is_fuzzy; 3456 3457 /* Read sysctl. */ 3458 /* XXX Verify values? */ 3459 max_width = sc->syninfo.max_width; 3460 max_pressure = sc->syninfo.max_pressure; 3461 margin_top = sc->syninfo.margin_top; 3462 margin_right = sc->syninfo.margin_right; 3463 margin_bottom = sc->syninfo.margin_bottom; 3464 margin_left = sc->syninfo.margin_left; 3465 na_top = sc->syninfo.na_top; 3466 na_right = sc->syninfo.na_right; 3467 na_bottom = sc->syninfo.na_bottom; 3468 na_left = sc->syninfo.na_left; 3469 window_min = sc->syninfo.window_min; 3470 window_max = sc->syninfo.window_max; 3471 multiplicator = sc->syninfo.multiplicator; 3472 weight_current = sc->syninfo.weight_current; 3473 weight_previous = sc->syninfo.weight_previous; 3474 weight_len_squared = sc->syninfo.weight_len_squared; 3475 div_min = sc->syninfo.div_min; 3476 div_max = sc->syninfo.div_max; 3477 div_len = sc->syninfo.div_len; 3478 vscroll_hor_area = sc->syninfo.vscroll_hor_area; 3479 vscroll_ver_area = sc->syninfo.vscroll_ver_area; 3480 two_finger_scroll = sc->syninfo.two_finger_scroll; 3481 max_x = sc->syninfo.max_x; 3482 max_y = sc->syninfo.max_y; 3483 3484 is_fuzzy = (f->flags & PSM_FINGER_FUZZY) != 0; 3485 3486 /* Read current absolute position. */ 3487 x0 = f->x; 3488 y0 = f->y; 3489 3490 /* 3491 * Limit the coordinates to the specified margins because 3492 * this area isn't very reliable. 3493 */ 3494 if (x0 <= margin_left) 3495 x0 = margin_left; 3496 else if (x0 >= max_x - margin_right) 3497 x0 = max_x - margin_right; 3498 if (y0 <= margin_bottom) 3499 y0 = margin_bottom; 3500 else if (y0 >= max_y - margin_top) 3501 y0 = max_y - margin_top; 3502 3503 /* If the action is just beginning, init the structure. */ 3504 if (smoother->active == 0) { 3505 VLOG(3, (LOG_DEBUG, "smoother%d: ---\n", smoother_id)); 3506 3507 /* Store the first point of this action. */ 3508 smoother->start_x = x0; 3509 smoother->start_y = y0; 3510 dx = dy = 0; 3511 3512 /* Initialize queue. */ 3513 smoother->queue_cursor = SYNAPTICS_PACKETQUEUE; 3514 smoother->queue_len = 0; 3515 3516 /* Reset average. */ 3517 smoother->avg_dx = 0; 3518 smoother->avg_dy = 0; 3519 3520 /* Reset squelch. */ 3521 smoother->squelch_x = 0; 3522 smoother->squelch_y = 0; 3523 3524 /* Activate queue */ 3525 smoother->active = 1; 3526 } else { 3527 /* Calculate the current delta. */ 3528 cursor = smoother->queue_cursor; 3529 dx = x0 - smoother->queue[cursor].x; 3530 dy = y0 - smoother->queue[cursor].y; 3531 } 3532 3533 VLOG(3, (LOG_DEBUG, "smoother%d: ipacket: [%d, %d], %d, %d\n", 3534 smoother_id, x0, y0, f->p, f->w)); 3535 3536 /* Queue this new packet. */ 3537 cursor = SYNAPTICS_QUEUE_CURSOR(smoother->queue_cursor - 1); 3538 smoother->queue[cursor].x = x0; 3539 smoother->queue[cursor].y = y0; 3540 smoother->queue_cursor = cursor; 3541 if (smoother->queue_len < SYNAPTICS_PACKETQUEUE) 3542 smoother->queue_len++; 3543 VLOG(5, (LOG_DEBUG, 3544 "smoother%d: cursor[%d]: x=%d, y=%d, dx=%d, dy=%d\n", 3545 smoother_id, cursor, x0, y0, dx, dy)); 3546 3547 /* Do we have enough packets to consider this a movement? */ 3548 if (smoother->queue_len < gest->window_min) 3549 return; 3550 3551 weight_prev_x = weight_prev_y = weight_previous; 3552 div_max_x = div_max_y = div_max; 3553 3554 if (gest->in_vscroll) { 3555 /* Dividers are different with virtual scrolling. */ 3556 div_min = sc->syninfo.vscroll_div_min; 3557 div_max_x = div_max_y = sc->syninfo.vscroll_div_max; 3558 } else { 3559 /* 3560 * There's a lot of noise in coordinates when 3561 * the finger is on the touchpad's borders. When 3562 * using this area, we apply a special weight and 3563 * div. 3564 */ 3565 if (x0 <= na_left || x0 >= max_x - na_right) { 3566 weight_prev_x = sc->syninfo.weight_previous_na; 3567 div_max_x = sc->syninfo.div_max_na; 3568 } 3569 3570 if (y0 <= na_bottom || y0 >= max_y - na_top) { 3571 weight_prev_y = sc->syninfo.weight_previous_na; 3572 div_max_y = sc->syninfo.div_max_na; 3573 } 3574 } 3575 3576 /* 3577 * Calculate weights for the average operands and 3578 * the divisor. Both depend on the distance between 3579 * the current packet and a previous one (based on the 3580 * window width). 3581 */ 3582 window = imin(smoother->queue_len, window_max); 3583 peer = SYNAPTICS_QUEUE_CURSOR(cursor + window - 1); 3584 dxp = abs(x0 - smoother->queue[peer].x) + 1; 3585 dyp = abs(y0 - smoother->queue[peer].y) + 1; 3586 len = (dxp * dxp) + (dyp * dyp); 3587 weight_prev_x = imin(weight_prev_x, 3588 weight_len_squared * weight_prev_x / len); 3589 weight_prev_y = imin(weight_prev_y, 3590 weight_len_squared * weight_prev_y / len); 3591 3592 len = (dxp + dyp) / 2; 3593 div_x = div_len * div_max_x / len; 3594 div_x = imin(div_max_x, div_x); 3595 div_x = imax(div_min, div_x); 3596 div_y = div_len * div_max_y / len; 3597 div_y = imin(div_max_y, div_y); 3598 div_y = imax(div_min, div_y); 3599 3600 VLOG(3, (LOG_DEBUG, 3601 "smoother%d: peer=%d, len=%d, weight=%d/%d, div=%d/%d\n", 3602 smoother_id, peer, len, weight_prev_x, weight_prev_y, 3603 div_x, div_y)); 3604 3605 /* Compute averages. */ 3606 smoother->avg_dx = 3607 (weight_current * dx * multiplicator + 3608 weight_prev_x * smoother->avg_dx) / 3609 (weight_current + weight_prev_x); 3610 3611 smoother->avg_dy = 3612 (weight_current * dy * multiplicator + 3613 weight_prev_y * smoother->avg_dy) / 3614 (weight_current + weight_prev_y); 3615 3616 VLOG(5, (LOG_DEBUG, 3617 "smoother%d: avg_dx~=%d, avg_dy~=%d\n", smoother_id, 3618 smoother->avg_dx / multiplicator, 3619 smoother->avg_dy / multiplicator)); 3620 3621 /* Use these averages to calculate x & y. */ 3622 smoother->squelch_x += smoother->avg_dx; 3623 dxp = smoother->squelch_x / (div_x * multiplicator); 3624 smoother->squelch_x = smoother->squelch_x % 3625 (div_x * multiplicator); 3626 3627 smoother->squelch_y += smoother->avg_dy; 3628 dyp = smoother->squelch_y / (div_y * multiplicator); 3629 smoother->squelch_y = smoother->squelch_y % 3630 (div_y * multiplicator); 3631 3632 switch(gest->in_vscroll) { 3633 case 0: /* Pointer movement. */ 3634 /* On real<->fuzzy finger switch the x/y pos jumps */ 3635 if (is_fuzzy == smoother->is_fuzzy) { 3636 *x += dxp; 3637 *y += dyp; 3638 } 3639 3640 VLOG(3, (LOG_DEBUG, "smoother%d: [%d, %d] -> [%d, %d]\n", 3641 smoother_id, dx, dy, dxp, dyp)); 3642 break; 3643 case 1: /* Vertical scrolling. */ 3644 if (dyp != 0) 3645 ms->button |= (dyp > 0) ? 3646 MOUSE_BUTTON4DOWN : MOUSE_BUTTON5DOWN; 3647 break; 3648 case 2: /* Horizontal scrolling. */ 3649 if (dxp != 0) 3650 ms->button |= (dxp > 0) ? 3651 MOUSE_BUTTON7DOWN : MOUSE_BUTTON6DOWN; 3652 break; 3653 } 3654 3655 smoother->is_fuzzy = is_fuzzy; 3656 3657 } else { 3658 /* 3659 * Deactivate queue. Note: We can not just reset queue here 3660 * as these values are still used by gesture processor. 3661 * So postpone reset till next touch. 3662 */ 3663 smoother->active = 0; 3664 } 3665 } 3666 3667 static int 3668 proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 3669 int *x, int *y, int *z) 3670 { 3671 static int touchpad_button, trackpoint_button; 3672 finger_t fn, f[ELANTECH_MAX_FINGERS]; 3673 int pkt, id, scale, i, nfingers, mask; 3674 3675 if (!elantech_support) 3676 return (0); 3677 3678 /* Determine packet format and do a sanity check for out of sync packets. */ 3679 if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion)) 3680 pkt = ELANTECH_PKT_NOP; 3681 else if (ELANTECH_PKT_IS_TRACKPOINT(pb)) 3682 pkt = ELANTECH_PKT_TRACKPOINT; 3683 else 3684 switch (sc->elanhw.hwversion) { 3685 case 2: 3686 if (!ELANTECH_PKT_IS_V2(pb)) 3687 return (-1); 3688 3689 pkt = (pb->ipacket[0] & 0xc0) == 0x80 ? 3690 ELANTECH_PKT_V2_2FINGER : ELANTECH_PKT_V2_COMMON; 3691 break; 3692 case 3: 3693 if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) && 3694 !ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc)) 3695 return (-1); 3696 3697 pkt = ELANTECH_PKT_V3; 3698 break; 3699 case 4: 3700 if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc)) 3701 return (-1); 3702 3703 switch (pb->ipacket[3] & 0x03) { 3704 case 0x00: 3705 pkt = ELANTECH_PKT_V4_STATUS; 3706 break; 3707 case 0x01: 3708 pkt = ELANTECH_PKT_V4_HEAD; 3709 break; 3710 case 0x02: 3711 pkt = ELANTECH_PKT_V4_MOTION; 3712 break; 3713 default: 3714 return (-1); 3715 } 3716 break; 3717 default: 3718 return (-1); 3719 } 3720 3721 VLOG(5, (LOG_DEBUG, "elantech: ipacket format: %d\n", pkt)); 3722 3723 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) 3724 PSM_FINGER_RESET(f[id]); 3725 3726 *x = *y = *z = 0; 3727 ms->button = ms->obutton; 3728 3729 if (sc->syninfo.touchpad_off) 3730 return (0); 3731 3732 /* Common legend 3733 * L: Left mouse button pressed 3734 * R: Right mouse button pressed 3735 * N: number of fingers on touchpad 3736 * X: absolute x value (horizontal) 3737 * Y: absolute y value (vertical) 3738 * W; width of the finger touch 3739 * P: pressure 3740 */ 3741 switch (pkt) { 3742 case ELANTECH_PKT_V2_COMMON: /* HW V2. One/Three finger touch */ 3743 /* 7 6 5 4 3 2 1 0 (LSB) 3744 * ------------------------------------------- 3745 * ipacket[0]: N1 N0 W3 W2 . . R L 3746 * ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 3747 * ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 3748 * ipacket[3]: N4 VF W1 W0 . . . B2 3749 * ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 3750 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3751 * ------------------------------------------- 3752 * N4: set if more than 3 fingers (only in 3 fingers mode) 3753 * VF: a kind of flag? (only on EF123, 0 when finger 3754 * is over one of the buttons, 1 otherwise) 3755 * B2: (on EF113 only, 0 otherwise), one button pressed 3756 * P & W is not reported on EF113 touchpads 3757 */ 3758 nfingers = (pb->ipacket[0] & 0xc0) >> 6; 3759 if (nfingers == 3 && (pb->ipacket[3] & 0x80)) 3760 nfingers = 4; 3761 mask = (1 << nfingers) - 1; 3762 3763 fn = ELANTECH_FINGER_SET_XYP(pb); 3764 if (sc->elanhw.haspressure) { 3765 fn.w = ((pb->ipacket[0] & 0x30) >> 2) | 3766 ((pb->ipacket[3] & 0x30) >> 4); 3767 } else { 3768 fn.p = PSM_FINGER_DEFAULT_P; 3769 fn.w = PSM_FINGER_DEFAULT_W; 3770 } 3771 3772 /* 3773 * HW v2 dont report exact finger positions when 3 or more 3774 * fingers are on touchpad. Use reported value as fingers 3775 * position as it is required for tap detection 3776 */ 3777 if (nfingers > 2) 3778 fn.flags = PSM_FINGER_FUZZY; 3779 3780 for (id = 0; id < imin(nfingers, ELANTECH_MAX_FINGERS); id++) 3781 f[id] = fn; 3782 break; 3783 3784 case ELANTECH_PKT_V2_2FINGER: /*HW V2. Two finger touch */ 3785 /* 7 6 5 4 3 2 1 0 (LSB) 3786 * ------------------------------------------- 3787 * ipacket[0]: N1 N0 AY8 AX8 . . R L 3788 * ipacket[1]: AX7 AX6 AX5 AX4 AX3 AX2 AX1 AX0 3789 * ipacket[2]: AY7 AY6 AY5 AY4 AY3 AY2 AY1 AY0 3790 * ipacket[3]: . . BY8 BX8 . . . . 3791 * ipacket[4]: BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0 3792 * ipacket[5]: BY7 BY6 BY5 BY4 BY3 BY2 BY1 BY0 3793 * ------------------------------------------- 3794 * AX: lower-left finger absolute x value 3795 * AY: lower-left finger absolute y value 3796 * BX: upper-right finger absolute x value 3797 * BY: upper-right finger absolute y value 3798 */ 3799 nfingers = 2; 3800 mask = (1 << nfingers) - 1; 3801 3802 for (id = 0; id < imin(2, ELANTECH_MAX_FINGERS); id ++) 3803 f[id] = (finger_t) { 3804 .x = (((pb->ipacket[id * 3] & 0x10) << 4) | 3805 pb->ipacket[id * 3 + 1]) << 2, 3806 .y = (((pb->ipacket[id * 3] & 0x20) << 3) | 3807 pb->ipacket[id * 3 + 2]) << 2, 3808 .p = PSM_FINGER_DEFAULT_P, 3809 .w = PSM_FINGER_DEFAULT_W, 3810 /* HW ver.2 sends bounding box */ 3811 .flags = PSM_FINGER_FUZZY 3812 }; 3813 break; 3814 3815 case ELANTECH_PKT_V3: /* HW Version 3 */ 3816 /* 7 6 5 4 3 2 1 0 (LSB) 3817 * ------------------------------------------- 3818 * ipacket[0]: N1 N0 W3 W2 0 1 R L 3819 * ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 3820 * ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 3821 * ipacket[3]: 0 0 W1 W0 0 0 1 0 3822 * ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 3823 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3824 * ------------------------------------------- 3825 */ 3826 nfingers = (pb->ipacket[0] & 0xc0) >> 6; 3827 mask = (1 << nfingers) - 1; 3828 id = nfingers - 1; 3829 3830 fn = ELANTECH_FINGER_SET_XYP(pb); 3831 fn.w = ((pb->ipacket[0] & 0x30) >> 2) | 3832 ((pb->ipacket[3] & 0x30) >> 4); 3833 3834 /* 3835 * HW v3 dont report exact finger positions when 3 or more 3836 * fingers are on touchpad. Use reported value as fingers 3837 * position as it is required for tap detection 3838 */ 3839 if (nfingers > 1) 3840 fn.flags = PSM_FINGER_FUZZY; 3841 3842 for (id = 0; id < imin(nfingers, ELANTECH_MAX_FINGERS); id++) 3843 f[id] = fn; 3844 3845 if (nfingers == 2) { 3846 if (ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc)) { 3847 sc->elanaction.fingers[0] = fn; 3848 return (0); 3849 } else 3850 f[0] = sc->elanaction.fingers[0]; 3851 } 3852 break; 3853 3854 case ELANTECH_PKT_V4_STATUS: /* HW Version 4. Status packet */ 3855 /* 7 6 5 4 3 2 1 0 (LSB) 3856 * ------------------------------------------- 3857 * ipacket[0]: . . . . 0 1 R L 3858 * ipacket[1]: . . . F4 F3 F2 F1 F0 3859 * ipacket[2]: . . . . . . . . 3860 * ipacket[3]: . . . 1 0 0 0 0 3861 * ipacket[4]: PL . . . . . . . 3862 * ipacket[5]: . . . . . . . . 3863 * ------------------------------------------- 3864 * Fn: finger n is on touchpad 3865 * PL: palm 3866 * HV ver4 sends a status packet to indicate that the numbers 3867 * or identities of the fingers has been changed 3868 */ 3869 3870 mask = pb->ipacket[1] & 0x1f; 3871 nfingers = bitcount32(mask); 3872 3873 /* Skip "new finger is on touchpad" packets */ 3874 if ((sc->elanaction.mask & mask) == sc->elanaction.mask && 3875 (mask & ~sc->elanaction.mask)) { 3876 sc->elanaction.mask = mask; 3877 return (0); 3878 } 3879 3880 break; 3881 3882 case ELANTECH_PKT_V4_HEAD: /* HW Version 4. Head packet */ 3883 /* 7 6 5 4 3 2 1 0 (LSB) 3884 * ------------------------------------------- 3885 * ipacket[0]: W3 W2 W1 W0 0 1 R L 3886 * ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 3887 * ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 3888 * ipacket[3]: ID2 ID1 ID0 1 0 0 0 1 3889 * ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 3890 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3891 * ------------------------------------------- 3892 * ID: finger id 3893 * HW ver 4 sends head packets in two cases: 3894 * 1. One finger touch and movement. 3895 * 2. Next after status packet to tell new finger positions. 3896 */ 3897 mask = sc->elanaction.mask; 3898 nfingers = bitcount32(mask); 3899 id = ((pb->ipacket[3] & 0xe0) >> 5) - 1; 3900 3901 if (id >= 0 && id < ELANTECH_MAX_FINGERS) { 3902 f[id] = ELANTECH_FINGER_SET_XYP(pb); 3903 f[id].w = (pb->ipacket[0] & 0xf0) >> 4; 3904 } 3905 break; 3906 3907 case ELANTECH_PKT_V4_MOTION: /* HW Version 4. Motion packet */ 3908 /* 7 6 5 4 3 2 1 0 (LSB) 3909 * ------------------------------------------- 3910 * ipacket[0]: ID2 ID1 ID0 OF 0 1 R L 3911 * ipacket[1]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 3912 * ipacket[2]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 3913 * ipacket[3]: ID2 ID1 ID0 1 0 0 1 0 3914 * ipacket[4]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 3915 * ipacket[5]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 3916 * ------------------------------------------- 3917 * OF: delta overflows (> 127 or < -128), in this case 3918 * firmware sends us (delta x / 5) and (delta y / 5) 3919 * ID: finger id 3920 * DX: delta x (two's complement) 3921 * XY: delta y (two's complement) 3922 * byte 0 ~ 2 for one finger 3923 * byte 3 ~ 5 for another finger 3924 */ 3925 mask = sc->elanaction.mask; 3926 nfingers = bitcount32(mask); 3927 3928 scale = (pb->ipacket[0] & 0x10) ? 5 : 1; 3929 for (i = 0; i <= 3; i += 3) { 3930 id = ((pb->ipacket[i] & 0xe0) >> 5) - 1; 3931 if (id < 0 || id >= ELANTECH_MAX_FINGERS) 3932 continue; 3933 3934 if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) { 3935 f[id] = sc->elanaction.fingers[id]; 3936 f[id].x += imax(-f[id].x, 3937 (signed char)pb->ipacket[i+1] * scale); 3938 f[id].y += imax(-f[id].y, 3939 (signed char)pb->ipacket[i+2] * scale); 3940 } else { 3941 VLOG(3, (LOG_DEBUG, "elantech: " 3942 "HW v4 motion packet skipped\n")); 3943 } 3944 } 3945 3946 break; 3947 3948 case ELANTECH_PKT_TRACKPOINT: 3949 /* 7 6 5 4 3 2 1 0 (LSB) 3950 * ------------------------------------------- 3951 * ipacket[0]: 0 0 SX SY 0 M R L 3952 * ipacket[1]: ~SX 0 0 0 0 0 0 0 3953 * ipacket[2]: ~SY 0 0 0 0 0 0 0 3954 * ipacket[3]: 0 0 ~SY ~SX 0 1 1 0 3955 * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 3956 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3957 * ------------------------------------------- 3958 * X and Y are written in two's complement spread 3959 * over 9 bits with SX/SY the relative top bit and 3960 * X7..X0 and Y7..Y0 the lower bits. 3961 */ 3962 *x = (pb->ipacket[0] & 0x20) ? 3963 pb->ipacket[4] - 256 : pb->ipacket[4]; 3964 *y = (pb->ipacket[0] & 0x10) ? 3965 pb->ipacket[5] - 256 : pb->ipacket[5]; 3966 3967 trackpoint_button = 3968 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | 3969 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | 3970 ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); 3971 3972 ms->button = touchpad_button | trackpoint_button; 3973 return (0); 3974 3975 case ELANTECH_PKT_NOP: 3976 return (0); 3977 3978 default: 3979 return (-1); 3980 } 3981 3982 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) 3983 if (PSM_FINGER_IS_SET(f[id])) 3984 VLOG(2, (LOG_DEBUG, "elantech: " 3985 "finger %d: down [%d, %d], %d, %d, %d\n", id + 1, 3986 f[id].x, f[id].y, f[id].p, f[id].w, f[id].flags)); 3987 3988 /* Touchpad button presses */ 3989 if (sc->elanhw.isclickpad) { 3990 touchpad_button = 3991 ((pb->ipacket[0] & 0x03) ? MOUSE_BUTTON1DOWN : 0); 3992 } else { 3993 touchpad_button = 3994 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | 3995 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); 3996 } 3997 3998 ms->button = touchpad_button | trackpoint_button; 3999 4000 /* Palm detection doesn't terminate the current action. */ 4001 if (!psmpalmdetect(sc, &f[0], nfingers)) { 4002 /* Send finger 1 position to gesture processor */ 4003 if (PSM_FINGER_IS_SET(f[0]) || PSM_FINGER_IS_SET(f[1]) || 4004 nfingers == 0) 4005 psmgestures(sc, &f[0], imin(nfingers, 3), ms); 4006 /* Send fingers positions to movement smoothers */ 4007 for (id = 0; id < PSM_FINGERS; id++) 4008 if (PSM_FINGER_IS_SET(f[id]) || !(mask & (1 << id))) 4009 psmsmoother(sc, &f[id], id, ms, x, y); 4010 } else { 4011 VLOG(2, (LOG_DEBUG, "elantech: palm detected! (%d)\n", 4012 f[0].w)); 4013 } 4014 4015 /* Store current finger positions in action context */ 4016 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) { 4017 if (PSM_FINGER_IS_SET(f[id])) 4018 sc->elanaction.fingers[id] = f[id]; 4019 if ((sc->elanaction.mask & (1 << id)) && !(mask & (1 << id))) 4020 PSM_FINGER_RESET(sc->elanaction.fingers[id]); 4021 } 4022 sc->elanaction.mask = mask; 4023 4024 /* Use the extra buttons as a scrollwheel */ 4025 if (ms->button & MOUSE_BUTTON4DOWN) 4026 *z = -1; 4027 else if (ms->button & MOUSE_BUTTON5DOWN) 4028 *z = 1; 4029 else if (ms->button & MOUSE_BUTTON6DOWN) 4030 *z = -2; 4031 else if (ms->button & MOUSE_BUTTON7DOWN) 4032 *z = 2; 4033 else 4034 *z = 0; 4035 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN | 4036 MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN); 4037 4038 return (0); 4039 } 4040 4041 static void 4042 proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 4043 int *x, int *y, int *z) 4044 { 4045 static int butmap_versapad[8] = { 4046 0, 4047 MOUSE_BUTTON3DOWN, 4048 0, 4049 MOUSE_BUTTON3DOWN, 4050 MOUSE_BUTTON1DOWN, 4051 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 4052 MOUSE_BUTTON1DOWN, 4053 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN 4054 }; 4055 int c, x0, y0; 4056 4057 /* VersaPad PS/2 absolute mode message format 4058 * 4059 * [packet1] 7 6 5 4 3 2 1 0(LSB) 4060 * ipacket[0]: 1 1 0 A 1 L T R 4061 * ipacket[1]: H7 H6 H5 H4 H3 H2 H1 H0 4062 * ipacket[2]: V7 V6 V5 V4 V3 V2 V1 V0 4063 * ipacket[3]: 1 1 1 A 1 L T R 4064 * ipacket[4]:V11 V10 V9 V8 H11 H10 H9 H8 4065 * ipacket[5]: 0 P6 P5 P4 P3 P2 P1 P0 4066 * 4067 * [note] 4068 * R: right physical mouse button (1=on) 4069 * T: touch pad virtual button (1=tapping) 4070 * L: left physical mouse button (1=on) 4071 * A: position data is valid (1=valid) 4072 * H: horizontal data (12bit signed integer. H11 is sign bit.) 4073 * V: vertical data (12bit signed integer. V11 is sign bit.) 4074 * P: pressure data 4075 * 4076 * Tapping is mapped to MOUSE_BUTTON4. 4077 */ 4078 c = pb->ipacket[0]; 4079 *x = *y = 0; 4080 ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS]; 4081 ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0; 4082 if (c & MOUSE_PS2VERSA_IN_USE) { 4083 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8); 4084 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4); 4085 if (x0 & 0x800) 4086 x0 -= 0x1000; 4087 if (y0 & 0x800) 4088 y0 -= 0x1000; 4089 if (sc->flags & PSM_FLAGS_FINGERDOWN) { 4090 *x = sc->xold - x0; 4091 *y = y0 - sc->yold; 4092 if (*x < 0) /* XXX */ 4093 ++*x; 4094 else if (*x) 4095 --*x; 4096 if (*y < 0) 4097 ++*y; 4098 else if (*y) 4099 --*y; 4100 } else 4101 sc->flags |= PSM_FLAGS_FINGERDOWN; 4102 sc->xold = x0; 4103 sc->yold = y0; 4104 } else 4105 sc->flags &= ~PSM_FLAGS_FINGERDOWN; 4106 } 4107 4108 static void 4109 psmsoftintridle(void *arg) 4110 { 4111 struct psm_softc *sc = arg; 4112 packetbuf_t *pb; 4113 4114 /* Invoke soft handler only when pqueue is empty. Otherwise it will be 4115 * invoked from psmintr soon with pqueue filled with real data */ 4116 if (sc->pqueue_start == sc->pqueue_end && 4117 sc->idlepacket.inputbytes > 0) { 4118 /* Grow circular queue backwards to avoid race with psmintr */ 4119 if (--sc->pqueue_start < 0) 4120 sc->pqueue_start = PSM_PACKETQUEUE - 1; 4121 4122 pb = &sc->pqueue[sc->pqueue_start]; 4123 memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t)); 4124 VLOG(4, (LOG_DEBUG, 4125 "psmsoftintridle: %02x %02x %02x %02x %02x %02x\n", 4126 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], 4127 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); 4128 4129 psmsoftintr(arg); 4130 } 4131 } 4132 4133 4134 static void 4135 psmsoftintr(void *arg) 4136 { 4137 /* 4138 * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN) 4139 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). 4140 */ 4141 static int butmap[8] = { 4142 0, 4143 MOUSE_BUTTON1DOWN, 4144 MOUSE_BUTTON3DOWN, 4145 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 4146 MOUSE_BUTTON2DOWN, 4147 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 4148 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 4149 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 4150 }; 4151 struct psm_softc *sc = arg; 4152 mousestatus_t ms; 4153 packetbuf_t *pb; 4154 int x, y, z, c, l; 4155 4156 getmicrouptime(&sc->lastsoftintr); 4157 4158 lockmgr(&sc->lock, LK_EXCLUSIVE); 4159 4160 do { 4161 pb = &sc->pqueue[sc->pqueue_start]; 4162 4163 c = pb->ipacket[0]; 4164 /* 4165 * A kludge for Kensington device! 4166 * The MSB of the horizontal count appears to be stored in 4167 * a strange place. 4168 */ 4169 if (sc->hw.model == MOUSE_MODEL_THINK) 4170 pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0; 4171 4172 /* ignore the overflow bits... */ 4173 x = (c & MOUSE_PS2_XNEG) ? 4174 pb->ipacket[1] - 256 : pb->ipacket[1]; 4175 y = (c & MOUSE_PS2_YNEG) ? 4176 pb->ipacket[2] - 256 : pb->ipacket[2]; 4177 z = 0; 4178 ms.obutton = sc->button; /* previous button state */ 4179 ms.button = butmap[c & MOUSE_PS2_BUTTONS]; 4180 /* `tapping' action */ 4181 if (sc->config & PSM_CONFIG_FORCETAP) 4182 ms.button |= ((c & MOUSE_PS2_TAP)) ? 4183 0 : MOUSE_BUTTON4DOWN; 4184 timevalclear(&sc->idletimeout); 4185 sc->idlepacket.inputbytes = 0; 4186 4187 switch (sc->hw.model) { 4188 4189 case MOUSE_MODEL_EXPLORER: 4190 /* 4191 * b7 b6 b5 b4 b3 b2 b1 b0 4192 * byte 1: oy ox sy sx 1 M R L 4193 * byte 2: x x x x x x x x 4194 * byte 3: y y y y y y y y 4195 * byte 4: * * S2 S1 s d2 d1 d0 4196 * 4197 * L, M, R, S1, S2: left, middle, right and side buttons 4198 * s: wheel data sign bit 4199 * d2-d0: wheel data 4200 */ 4201 z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ? 4202 (pb->ipacket[3] & 0x0f) - 16 : 4203 (pb->ipacket[3] & 0x0f); 4204 ms.button |= 4205 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ? 4206 MOUSE_BUTTON4DOWN : 0; 4207 ms.button |= 4208 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ? 4209 MOUSE_BUTTON5DOWN : 0; 4210 break; 4211 4212 case MOUSE_MODEL_INTELLI: 4213 case MOUSE_MODEL_NET: 4214 /* wheel data is in the fourth byte */ 4215 z = (char)pb->ipacket[3]; 4216 /* 4217 * XXX some mice may send 7 when there is no Z movement? */ 4218 if ((z >= 7) || (z <= -7)) 4219 z = 0; 4220 /* some compatible mice have additional buttons */ 4221 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN) ? 4222 MOUSE_BUTTON4DOWN : 0; 4223 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN) ? 4224 MOUSE_BUTTON5DOWN : 0; 4225 break; 4226 4227 case MOUSE_MODEL_MOUSEMANPLUS: 4228 proc_mmanplus(sc, pb, &ms, &x, &y, &z); 4229 break; 4230 4231 case MOUSE_MODEL_GLIDEPOINT: 4232 /* `tapping' action */ 4233 ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : 4234 MOUSE_BUTTON4DOWN; 4235 break; 4236 4237 case MOUSE_MODEL_NETSCROLL: 4238 /* 4239 * three addtional bytes encode buttons and 4240 * wheel events 4241 */ 4242 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ? 4243 MOUSE_BUTTON4DOWN : 0; 4244 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ? 4245 MOUSE_BUTTON5DOWN : 0; 4246 z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ? 4247 pb->ipacket[4] - 256 : pb->ipacket[4]; 4248 break; 4249 4250 case MOUSE_MODEL_THINK: 4251 /* the fourth button state in the first byte */ 4252 ms.button |= (c & MOUSE_PS2_TAP) ? 4253 MOUSE_BUTTON4DOWN : 0; 4254 break; 4255 4256 case MOUSE_MODEL_VERSAPAD: 4257 proc_versapad(sc, pb, &ms, &x, &y, &z); 4258 c = ((x < 0) ? MOUSE_PS2_XNEG : 0) | 4259 ((y < 0) ? MOUSE_PS2_YNEG : 0); 4260 break; 4261 4262 case MOUSE_MODEL_4D: 4263 /* 4264 * b7 b6 b5 b4 b3 b2 b1 b0 4265 * byte 1: s2 d2 s1 d1 1 M R L 4266 * byte 2: sx x x x x x x x 4267 * byte 3: sy y y y y y y y 4268 * 4269 * s1: wheel 1 direction 4270 * d1: wheel 1 data 4271 * s2: wheel 2 direction 4272 * d2: wheel 2 data 4273 */ 4274 x = (pb->ipacket[1] & 0x80) ? 4275 pb->ipacket[1] - 256 : pb->ipacket[1]; 4276 y = (pb->ipacket[2] & 0x80) ? 4277 pb->ipacket[2] - 256 : pb->ipacket[2]; 4278 switch (c & MOUSE_4D_WHEELBITS) { 4279 case 0x10: 4280 z = 1; 4281 break; 4282 case 0x30: 4283 z = -1; 4284 break; 4285 case 0x40: /* XXX 2nd wheel turning right */ 4286 z = 2; 4287 break; 4288 case 0xc0: /* XXX 2nd wheel turning left */ 4289 z = -2; 4290 break; 4291 } 4292 break; 4293 4294 case MOUSE_MODEL_4DPLUS: 4295 if ((x < 16 - 256) && (y < 16 - 256)) { 4296 /* 4297 * b7 b6 b5 b4 b3 b2 b1 b0 4298 * byte 1: 0 0 1 1 1 M R L 4299 * byte 2: 0 0 0 0 1 0 0 0 4300 * byte 3: 0 0 0 0 S s d1 d0 4301 * 4302 * L, M, R, S: left, middle, right, 4303 * and side buttons 4304 * s: wheel data sign bit 4305 * d1-d0: wheel data 4306 */ 4307 x = y = 0; 4308 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN) 4309 ms.button |= MOUSE_BUTTON4DOWN; 4310 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ? 4311 ((pb->ipacket[2] & 0x07) - 8) : 4312 (pb->ipacket[2] & 0x07) ; 4313 } else { 4314 /* preserve previous button states */ 4315 ms.button |= ms.obutton & MOUSE_EXTBUTTONS; 4316 } 4317 break; 4318 4319 case MOUSE_MODEL_SYNAPTICS: 4320 if (proc_synaptics(sc, pb, &ms, &x, &y, &z) != 0) 4321 goto next; 4322 break; 4323 4324 case MOUSE_MODEL_ELANTECH: 4325 if (proc_elantech(sc, pb, &ms, &x, &y, &z) != 0) 4326 goto next; 4327 break; 4328 4329 case MOUSE_MODEL_TRACKPOINT: 4330 case MOUSE_MODEL_GENERIC: 4331 default: 4332 break; 4333 } 4334 4335 /* scale values */ 4336 if (sc->mode.accelfactor >= 1) { 4337 if (x != 0) { 4338 x = x * x / sc->mode.accelfactor; 4339 if (x == 0) 4340 x = 1; 4341 if (c & MOUSE_PS2_XNEG) 4342 x = -x; 4343 } 4344 if (y != 0) { 4345 y = y * y / sc->mode.accelfactor; 4346 if (y == 0) 4347 y = 1; 4348 if (c & MOUSE_PS2_YNEG) 4349 y = -y; 4350 } 4351 } 4352 /* 4353 * Store last packet for reinjection if it has not been 4354 * set already 4355 */ 4356 if (timevalisset(&sc->idletimeout) && 4357 sc->idlepacket.inputbytes == 0) 4358 sc->idlepacket = *pb; 4359 4360 ms.dx = x; 4361 ms.dy = y; 4362 ms.dz = z; 4363 ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) | 4364 (ms.obutton ^ ms.button); 4365 4366 pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket); 4367 4368 sc->status.flags |= ms.flags; 4369 sc->status.dx += ms.dx; 4370 sc->status.dy += ms.dy; 4371 sc->status.dz += ms.dz; 4372 sc->status.button = ms.button; 4373 sc->button = ms.button; 4374 4375 sc->watchdog = FALSE; 4376 4377 /* queue data */ 4378 if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) { 4379 l = imin(pb->inputbytes, 4380 sizeof(sc->queue.buf) - sc->queue.tail); 4381 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l); 4382 if (pb->inputbytes > l) 4383 bcopy(&pb->ipacket[l], &sc->queue.buf[0], 4384 pb->inputbytes - l); 4385 sc->queue.tail = (sc->queue.tail + pb->inputbytes) % 4386 sizeof(sc->queue.buf); 4387 sc->queue.count += pb->inputbytes; 4388 } 4389 next: 4390 pb->inputbytes = 0; 4391 if (++sc->pqueue_start >= PSM_PACKETQUEUE) 4392 sc->pqueue_start = 0; 4393 } while (sc->pqueue_start != sc->pqueue_end); 4394 4395 if (sc->state & PSM_ASLP) { 4396 sc->state &= ~PSM_ASLP; 4397 wakeup(sc); 4398 } 4399 4400 KNOTE(&sc->rkq.ki_note, 0); 4401 sc->state &= ~PSM_SOFTARMED; 4402 4403 /* schedule injection of predefined packet after idletimeout 4404 * if no data packets have been received from psmintr */ 4405 if (timevalisset(&sc->idletimeout)) { 4406 sc->state |= PSM_SOFTARMED; 4407 callout_reset(&sc->softcallout, tvtohz_high(&sc->idletimeout), 4408 psmsoftintridle, sc); 4409 VLOG(2, (LOG_DEBUG, "softintr: callout set: %d ticks\n", 4410 tvtohz_high(&sc->idletimeout))); 4411 } 4412 lockmgr(&sc->lock, LK_RELEASE); 4413 } 4414 4415 static struct filterops psmfiltops = 4416 { FILTEROP_ISFD, NULL, psmfilter_detach, psmfilter }; 4417 4418 static int 4419 psmkqfilter(struct dev_kqfilter_args *ap) 4420 { 4421 cdev_t dev = ap->a_head.a_dev; 4422 struct psm_softc *sc = dev->si_drv1; 4423 struct knote *kn = ap->a_kn; 4424 struct klist *klist; 4425 4426 ap->a_result = 0; 4427 4428 switch (kn->kn_filter) { 4429 case EVFILT_READ: 4430 kn->kn_fop = &psmfiltops; 4431 kn->kn_hook = (caddr_t)sc; 4432 break; 4433 default: 4434 ap->a_result = EOPNOTSUPP; 4435 return (0); 4436 } 4437 4438 klist = &sc->rkq.ki_note; 4439 knote_insert(klist, kn); 4440 4441 return (0); 4442 } 4443 4444 static void 4445 psmfilter_detach(struct knote *kn) 4446 { 4447 struct psm_softc *sc = (struct psm_softc *)kn->kn_hook; 4448 struct klist *klist; 4449 4450 klist = &sc->rkq.ki_note; 4451 knote_remove(klist, kn); 4452 } 4453 4454 static int 4455 psmfilter(struct knote *kn, long hint) 4456 { 4457 struct psm_softc *sc = (struct psm_softc *)kn->kn_hook; 4458 int ready = 0; 4459 4460 lockmgr(&sc->lock, LK_EXCLUSIVE); 4461 if (sc->queue.count > 0) 4462 ready = 1; 4463 lockmgr(&sc->lock, LK_RELEASE); 4464 4465 return (ready); 4466 } 4467 4468 4469 /* vendor/model specific routines */ 4470 4471 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status) 4472 { 4473 4474 if (set_mouse_resolution(kbdc, res) != res) 4475 return (FALSE); 4476 if (set_mouse_scaling(kbdc, scale) && 4477 set_mouse_scaling(kbdc, scale) && 4478 set_mouse_scaling(kbdc, scale) && 4479 (get_mouse_status(kbdc, status, 0, 3) >= 3)) 4480 return (TRUE); 4481 return (FALSE); 4482 } 4483 4484 static int 4485 mouse_ext_command(KBDC kbdc, int command) 4486 { 4487 4488 int c; 4489 4490 c = (command >> 6) & 0x03; 4491 if (set_mouse_resolution(kbdc, c) != c) 4492 return (FALSE); 4493 c = (command >> 4) & 0x03; 4494 if (set_mouse_resolution(kbdc, c) != c) 4495 return (FALSE); 4496 c = (command >> 2) & 0x03; 4497 if (set_mouse_resolution(kbdc, c) != c) 4498 return (FALSE); 4499 c = (command >> 0) & 0x03; 4500 if (set_mouse_resolution(kbdc, c) != c) 4501 return (FALSE); 4502 return (TRUE); 4503 } 4504 4505 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */ 4506 static int 4507 enable_groller(struct psm_softc *sc, enum probearg arg) 4508 { 4509 KBDC kbdc = sc->kbdc; 4510 int status[3]; 4511 4512 /* 4513 * The special sequence to enable the fourth button and the 4514 * roller. Immediately after this sequence check status bytes. 4515 * if the mouse is NetScroll, the second and the third bytes are 4516 * '3' and 'D'. 4517 */ 4518 4519 /* 4520 * If the mouse is an ordinary PS/2 mouse, the status bytes should 4521 * look like the following. 4522 * 4523 * byte 1 bit 7 always 0 4524 * bit 6 stream mode (0) 4525 * bit 5 disabled (0) 4526 * bit 4 1:1 scaling (0) 4527 * bit 3 always 0 4528 * bit 0-2 button status 4529 * byte 2 resolution (PSMD_RES_HIGH) 4530 * byte 3 report rate (?) 4531 */ 4532 4533 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 1, status)) 4534 return (FALSE); 4535 if ((status[1] != '3') || (status[2] != 'D')) 4536 return (FALSE); 4537 /* FIXME: SmartScroll Mouse has 5 buttons! XXX */ 4538 if (arg == PROBE) 4539 sc->hw.buttons = 4; 4540 return (TRUE); 4541 } 4542 4543 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */ 4544 static int 4545 enable_gmouse(struct psm_softc *sc, enum probearg arg) 4546 { 4547 KBDC kbdc = sc->kbdc; 4548 int status[3]; 4549 4550 /* 4551 * The special sequence to enable the middle, "rubber" button. 4552 * Immediately after this sequence check status bytes. 4553 * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse, 4554 * the second and the third bytes are '3' and 'U'. 4555 * NOTE: NetMouse reports that it has three buttons although it has 4556 * two buttons and a rubber button. NetMouse Pro and MIE Mouse 4557 * say they have three buttons too and they do have a button on the 4558 * side... 4559 */ 4560 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 1, status)) 4561 return (FALSE); 4562 if ((status[1] != '3') || (status[2] != 'U')) 4563 return (FALSE); 4564 return (TRUE); 4565 } 4566 4567 /* ALPS GlidePoint */ 4568 static int 4569 enable_aglide(struct psm_softc *sc, enum probearg arg) 4570 { 4571 KBDC kbdc = sc->kbdc; 4572 int status[3]; 4573 4574 /* 4575 * The special sequence to obtain ALPS GlidePoint specific 4576 * information. Immediately after this sequence, status bytes will 4577 * contain something interesting. 4578 * NOTE: ALPS produces several models of GlidePoint. Some of those 4579 * do not respond to this sequence, thus, cannot be detected this way. 4580 */ 4581 if (set_mouse_sampling_rate(kbdc, 100) != 100) 4582 return (FALSE); 4583 if (!mouse_id_proc1(kbdc, PSMD_RES_LOW, 2, status)) 4584 return (FALSE); 4585 if ((status[1] == PSMD_RES_LOW) || (status[2] == 100)) 4586 return (FALSE); 4587 return (TRUE); 4588 } 4589 4590 /* Kensington ThinkingMouse/Trackball */ 4591 static int 4592 enable_kmouse(struct psm_softc *sc, enum probearg arg) 4593 { 4594 static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; 4595 KBDC kbdc = sc->kbdc; 4596 int status[3]; 4597 int id1; 4598 int id2; 4599 int i; 4600 4601 id1 = get_aux_id(kbdc); 4602 if (set_mouse_sampling_rate(kbdc, 10) != 10) 4603 return (FALSE); 4604 /* 4605 * The device is now in the native mode? It returns a different 4606 * ID value... 4607 */ 4608 id2 = get_aux_id(kbdc); 4609 if ((id1 == id2) || (id2 != 2)) 4610 return (FALSE); 4611 4612 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) 4613 return (FALSE); 4614 #if PSM_DEBUG >= 2 4615 /* at this point, resolution is LOW, sampling rate is 10/sec */ 4616 if (get_mouse_status(kbdc, status, 0, 3) < 3) 4617 return (FALSE); 4618 #endif 4619 4620 /* 4621 * The special sequence to enable the third and fourth buttons. 4622 * Otherwise they behave like the first and second buttons. 4623 */ 4624 for (i = 0; i < nitems(rate); ++i) 4625 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4626 return (FALSE); 4627 4628 /* 4629 * At this point, the device is using default resolution and 4630 * sampling rate for the native mode. 4631 */ 4632 if (get_mouse_status(kbdc, status, 0, 3) < 3) 4633 return (FALSE); 4634 if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1])) 4635 return (FALSE); 4636 4637 /* the device appears be enabled by this sequence, diable it for now */ 4638 disable_aux_dev(kbdc); 4639 empty_aux_buffer(kbdc, 5); 4640 4641 return (TRUE); 4642 } 4643 4644 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */ 4645 static int 4646 enable_mmanplus(struct psm_softc *sc, enum probearg arg) 4647 { 4648 KBDC kbdc = sc->kbdc; 4649 int data[3]; 4650 4651 /* the special sequence to enable the fourth button and the roller. */ 4652 /* 4653 * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION 4654 * must be called exactly three times since the last RESET command 4655 * before this sequence. XXX 4656 */ 4657 if (!set_mouse_scaling(kbdc, 1)) 4658 return (FALSE); 4659 if (!mouse_ext_command(kbdc, 0x39) || !mouse_ext_command(kbdc, 0xdb)) 4660 return (FALSE); 4661 if (get_mouse_status(kbdc, data, 1, 3) < 3) 4662 return (FALSE); 4663 4664 /* 4665 * PS2++ protocol, packet type 0 4666 * 4667 * b7 b6 b5 b4 b3 b2 b1 b0 4668 * byte 1: * 1 p3 p2 1 * * * 4669 * byte 2: 1 1 p1 p0 m1 m0 1 0 4670 * byte 3: m7 m6 m5 m4 m3 m2 m1 m0 4671 * 4672 * p3-p0: packet type: 0 4673 * m7-m0: model ID: MouseMan+:0x50, 4674 * FirstMouse+:0x51, 4675 * ScrollPoint:0x58... 4676 */ 4677 /* check constant bits */ 4678 if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC) 4679 return (FALSE); 4680 if ((data[1] & 0xc3) != 0xc2) 4681 return (FALSE); 4682 /* check d3-d0 in byte 2 */ 4683 if (!MOUSE_PS2PLUS_CHECKBITS(data)) 4684 return (FALSE); 4685 /* check p3-p0 */ 4686 if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0) 4687 return (FALSE); 4688 4689 if (arg == PROBE) { 4690 sc->hw.hwid &= 0x00ff; 4691 sc->hw.hwid |= data[2] << 8; /* save model ID */ 4692 } 4693 4694 /* 4695 * MouseMan+ (or FirstMouse+) is now in its native mode, in which 4696 * the wheel and the fourth button events are encoded in the 4697 * special data packet. The mouse may be put in the IntelliMouse mode 4698 * if it is initialized by the IntelliMouse's method. 4699 */ 4700 return (TRUE); 4701 } 4702 4703 /* MS IntelliMouse Explorer */ 4704 static int 4705 enable_msexplorer(struct psm_softc *sc, enum probearg arg) 4706 { 4707 KBDC kbdc = sc->kbdc; 4708 static u_char rate0[] = { 200, 100, 80, }; 4709 static u_char rate1[] = { 200, 200, 80, }; 4710 int id; 4711 int i; 4712 4713 /* 4714 * This is needed for at least A4Tech X-7xx mice - they do not go 4715 * straight to Explorer mode, but need to be set to Intelli mode 4716 * first. 4717 */ 4718 enable_msintelli(sc, arg); 4719 4720 /* the special sequence to enable the extra buttons and the roller. */ 4721 for (i = 0; i < nitems(rate1); ++i) 4722 if (set_mouse_sampling_rate(kbdc, rate1[i]) != rate1[i]) 4723 return (FALSE); 4724 /* the device will give the genuine ID only after the above sequence */ 4725 id = get_aux_id(kbdc); 4726 if (id != PSM_EXPLORER_ID) 4727 return (FALSE); 4728 4729 if (arg == PROBE) { 4730 sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */ 4731 sc->hw.hwid = id; 4732 } 4733 4734 /* 4735 * XXX: this is a kludge to fool some KVM switch products 4736 * which think they are clever enough to know the 4-byte IntelliMouse 4737 * protocol, and assume any other protocols use 3-byte packets. 4738 * They don't convey 4-byte data packets from the IntelliMouse Explorer 4739 * correctly to the host computer because of this! 4740 * The following sequence is actually IntelliMouse's "wake up" 4741 * sequence; it will make the KVM think the mouse is IntelliMouse 4742 * when it is in fact IntelliMouse Explorer. 4743 */ 4744 for (i = 0; i < nitems(rate0); ++i) 4745 if (set_mouse_sampling_rate(kbdc, rate0[i]) != rate0[i]) 4746 break; 4747 get_aux_id(kbdc); 4748 4749 return (TRUE); 4750 } 4751 4752 /* 4753 * MS IntelliMouse 4754 * Logitech MouseMan+ and FirstMouse+ will also respond to this 4755 * probe routine and act like IntelliMouse. 4756 */ 4757 static int 4758 enable_msintelli(struct psm_softc *sc, enum probearg arg) 4759 { 4760 KBDC kbdc = sc->kbdc; 4761 static u_char rate[] = { 200, 100, 80, }; 4762 int id; 4763 int i; 4764 4765 /* the special sequence to enable the third button and the roller. */ 4766 for (i = 0; i < nitems(rate); ++i) 4767 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4768 return (FALSE); 4769 /* the device will give the genuine ID only after the above sequence */ 4770 id = get_aux_id(kbdc); 4771 if (id != PSM_INTELLI_ID) 4772 return (FALSE); 4773 4774 if (arg == PROBE) { 4775 sc->hw.buttons = 3; 4776 sc->hw.hwid = id; 4777 } 4778 4779 return (TRUE); 4780 } 4781 4782 /* 4783 * A4 Tech 4D Mouse 4784 * Newer wheel mice from A4 Tech may use the 4D+ protocol. 4785 */ 4786 static int 4787 enable_4dmouse(struct psm_softc *sc, enum probearg arg) 4788 { 4789 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; 4790 KBDC kbdc = sc->kbdc; 4791 int id; 4792 int i; 4793 4794 for (i = 0; i < nitems(rate); ++i) 4795 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4796 return (FALSE); 4797 id = get_aux_id(kbdc); 4798 /* 4799 * WinEasy 4D, 4 Way Scroll 4D: 6 4800 * Cable-Free 4D: 8 (4DPLUS) 4801 * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS) 4802 */ 4803 if (id != PSM_4DMOUSE_ID) 4804 return (FALSE); 4805 4806 if (arg == PROBE) { 4807 sc->hw.buttons = 3; /* XXX some 4D mice have 4? */ 4808 sc->hw.hwid = id; 4809 } 4810 4811 return (TRUE); 4812 } 4813 4814 /* 4815 * A4 Tech 4D+ Mouse 4816 * Newer wheel mice from A4 Tech seem to use this protocol. 4817 * Older models are recognized as either 4D Mouse or IntelliMouse. 4818 */ 4819 static int 4820 enable_4dplus(struct psm_softc *sc, enum probearg arg) 4821 { 4822 KBDC kbdc = sc->kbdc; 4823 int id; 4824 4825 /* 4826 * enable_4dmouse() already issued the following ID sequence... 4827 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; 4828 int i; 4829 4830 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) 4831 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4832 return (FALSE); 4833 */ 4834 4835 id = get_aux_id(kbdc); 4836 switch (id) { 4837 case PSM_4DPLUS_ID: 4838 break; 4839 case PSM_4DPLUS_RFSW35_ID: 4840 break; 4841 default: 4842 return (FALSE); 4843 } 4844 4845 if (arg == PROBE) { 4846 sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3; 4847 sc->hw.hwid = id; 4848 } 4849 4850 return (TRUE); 4851 } 4852 4853 /* Synaptics Touchpad */ 4854 static int 4855 synaptics_sysctl(SYSCTL_HANDLER_ARGS) 4856 { 4857 struct psm_softc *sc; 4858 int error, arg; 4859 4860 if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || 4861 oidp->oid_arg2 > SYNAPTICS_SYSCTL_SOFTBUTTON3_X) 4862 return (EINVAL); 4863 4864 sc = oidp->oid_arg1; 4865 4866 /* Read the current value. */ 4867 arg = *(int *)((char *)sc + oidp->oid_arg2); 4868 error = sysctl_handle_int(oidp, &arg, 0, req); 4869 4870 /* Sanity check. */ 4871 if (error || !req->newptr) 4872 return (error); 4873 4874 /* 4875 * Check that the new value is in the concerned node's range 4876 * of values. 4877 */ 4878 switch (oidp->oid_arg2) { 4879 case SYNAPTICS_SYSCTL_MIN_PRESSURE: 4880 case SYNAPTICS_SYSCTL_MAX_PRESSURE: 4881 if (arg < 0 || arg > 255) 4882 return (EINVAL); 4883 break; 4884 case SYNAPTICS_SYSCTL_MAX_WIDTH: 4885 if (arg < 4 || arg > 15) 4886 return (EINVAL); 4887 break; 4888 case SYNAPTICS_SYSCTL_MARGIN_TOP: 4889 case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: 4890 case SYNAPTICS_SYSCTL_NA_TOP: 4891 case SYNAPTICS_SYSCTL_NA_BOTTOM: 4892 if (arg < 0 || arg > sc->synhw.maximumYCoord) 4893 return (EINVAL); 4894 break; 4895 case SYNAPTICS_SYSCTL_SOFTBUTTON2_X: 4896 case SYNAPTICS_SYSCTL_SOFTBUTTON3_X: 4897 /* Softbuttons is clickpad only feature */ 4898 if (!sc->synhw.capClickPad && arg != 0) 4899 return (EINVAL); 4900 /* FALLTHROUGH */ 4901 case SYNAPTICS_SYSCTL_MARGIN_RIGHT: 4902 case SYNAPTICS_SYSCTL_MARGIN_LEFT: 4903 case SYNAPTICS_SYSCTL_NA_RIGHT: 4904 case SYNAPTICS_SYSCTL_NA_LEFT: 4905 if (arg < 0 || arg > sc->synhw.maximumXCoord) 4906 return (EINVAL); 4907 break; 4908 case SYNAPTICS_SYSCTL_WINDOW_MIN: 4909 case SYNAPTICS_SYSCTL_WINDOW_MAX: 4910 case SYNAPTICS_SYSCTL_TAP_MIN_QUEUE: 4911 if (arg < 1 || arg > SYNAPTICS_PACKETQUEUE) 4912 return (EINVAL); 4913 break; 4914 case SYNAPTICS_SYSCTL_MULTIPLICATOR: 4915 case SYNAPTICS_SYSCTL_WEIGHT_CURRENT: 4916 case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS: 4917 case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA: 4918 case SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED: 4919 case SYNAPTICS_SYSCTL_DIV_MIN: 4920 case SYNAPTICS_SYSCTL_DIV_MAX: 4921 case SYNAPTICS_SYSCTL_DIV_MAX_NA: 4922 case SYNAPTICS_SYSCTL_DIV_LEN: 4923 case SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN: 4924 case SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX: 4925 if (arg < 1) 4926 return (EINVAL); 4927 break; 4928 case SYNAPTICS_SYSCTL_TAP_MAX_DELTA: 4929 case SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT: 4930 case SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA: 4931 if (arg < 0) 4932 return (EINVAL); 4933 break; 4934 case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: 4935 if (arg < -sc->synhw.maximumXCoord || 4936 arg > sc->synhw.maximumXCoord) 4937 return (EINVAL); 4938 break; 4939 case SYNAPTICS_SYSCTL_SOFTBUTTONS_Y: 4940 /* Softbuttons is clickpad only feature */ 4941 if (!sc->synhw.capClickPad && arg != 0) 4942 return (EINVAL); 4943 /* FALLTHROUGH */ 4944 case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: 4945 if (arg < -sc->synhw.maximumYCoord || 4946 arg > sc->synhw.maximumYCoord) 4947 return (EINVAL); 4948 break; 4949 case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: 4950 if (arg < 0 || arg > 1) 4951 return (EINVAL); 4952 break; 4953 default: 4954 return (EINVAL); 4955 } 4956 4957 /* Update. */ 4958 *(int *)((char *)sc + oidp->oid_arg2) = arg; 4959 4960 return (error); 4961 } 4962 4963 static void 4964 synaptics_sysctl_create_softbuttons_tree(struct psm_softc *sc) 4965 { 4966 /* 4967 * Set predefined sizes for softbuttons. 4968 * Values are taken to match HP Pavilion dv6 clickpad drawings 4969 * with thin middle softbutton placed on separator 4970 */ 4971 4972 /* hw.psm.synaptics.softbuttons_y */ 4973 sc->syninfo.softbuttons_y = 1700; 4974 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4975 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4976 "softbuttons_y", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4977 sc, SYNAPTICS_SYSCTL_SOFTBUTTONS_Y, 4978 synaptics_sysctl, "I", 4979 "Vertical size of softbuttons area"); 4980 4981 /* hw.psm.synaptics.softbutton2_x */ 4982 sc->syninfo.softbutton2_x = 3100; 4983 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4984 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4985 "softbutton2_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4986 sc, SYNAPTICS_SYSCTL_SOFTBUTTON2_X, 4987 synaptics_sysctl, "I", 4988 "Horisontal position of 2-nd softbutton left edge (0-disable)"); 4989 4990 /* hw.psm.synaptics.softbutton3_x */ 4991 sc->syninfo.softbutton3_x = 3900; 4992 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4993 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4994 "softbutton3_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4995 sc, SYNAPTICS_SYSCTL_SOFTBUTTON3_X, 4996 synaptics_sysctl, "I", 4997 "Horisontal position of 3-rd softbutton left edge (0-disable)"); 4998 } 4999 5000 static void 5001 synaptics_sysctl_create_tree(struct psm_softc *sc, const char *name, 5002 const char *descr) 5003 { 5004 5005 if (sc->syninfo.sysctl_tree != NULL) 5006 return; 5007 5008 /* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ 5009 sysctl_ctx_init(&sc->syninfo.sysctl_ctx); 5010 sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, 5011 SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, name, CTLFLAG_RD, 5012 0, descr); 5013 5014 /* hw.psm.synaptics.directional_scrolls. */ 5015 sc->syninfo.directional_scrolls = 0; 5016 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5017 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5018 "directional_scrolls", CTLFLAG_RW|CTLFLAG_ANYBODY, 5019 &sc->syninfo.directional_scrolls, 0, 5020 "Enable hardware scrolling pad (if non-zero) or register it as " 5021 "extended buttons (if 0)"); 5022 5023 /* hw.psm.synaptics.max_x. */ 5024 sc->syninfo.max_x = 6143; 5025 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5026 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5027 "max_x", CTLFLAG_RD|CTLFLAG_ANYBODY, 5028 &sc->syninfo.max_x, 0, 5029 "Horizontal reporting range"); 5030 5031 /* hw.psm.synaptics.max_y. */ 5032 sc->syninfo.max_y = 6143; 5033 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5034 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5035 "max_y", CTLFLAG_RD|CTLFLAG_ANYBODY, 5036 &sc->syninfo.max_y, 0, 5037 "Vertical reporting range"); 5038 5039 /* 5040 * Turn off two finger scroll if we have a 5041 * physical area reserved for scrolling or when 5042 * there's no multi finger support. 5043 */ 5044 if (sc->synhw.verticalScroll || (sc->synhw.capMultiFinger == 0 && 5045 sc->synhw.capAdvancedGestures == 0)) 5046 sc->syninfo.two_finger_scroll = 0; 5047 else 5048 sc->syninfo.two_finger_scroll = 1; 5049 /* hw.psm.synaptics.two_finger_scroll. */ 5050 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5051 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5052 "two_finger_scroll", CTLFLAG_RW|CTLFLAG_ANYBODY, 5053 &sc->syninfo.two_finger_scroll, 0, 5054 "Enable two finger scrolling"); 5055 5056 /* hw.psm.synaptics.min_pressure. */ 5057 sc->syninfo.min_pressure = 16; 5058 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5059 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5060 "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5061 sc, SYNAPTICS_SYSCTL_MIN_PRESSURE, 5062 synaptics_sysctl, "I", 5063 "Minimum pressure required to start an action"); 5064 5065 /* hw.psm.synaptics.max_pressure. */ 5066 sc->syninfo.max_pressure = 220; 5067 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5068 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5069 "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5070 sc, SYNAPTICS_SYSCTL_MAX_PRESSURE, 5071 synaptics_sysctl, "I", 5072 "Maximum pressure to detect palm"); 5073 5074 /* hw.psm.synaptics.max_width. */ 5075 sc->syninfo.max_width = 10; 5076 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5077 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5078 "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5079 sc, SYNAPTICS_SYSCTL_MAX_WIDTH, 5080 synaptics_sysctl, "I", 5081 "Maximum finger width to detect palm"); 5082 5083 /* hw.psm.synaptics.top_margin. */ 5084 sc->syninfo.margin_top = 200; 5085 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5086 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5087 "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5088 sc, SYNAPTICS_SYSCTL_MARGIN_TOP, 5089 synaptics_sysctl, "I", 5090 "Top margin"); 5091 5092 /* hw.psm.synaptics.right_margin. */ 5093 sc->syninfo.margin_right = 200; 5094 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5095 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5096 "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5097 sc, SYNAPTICS_SYSCTL_MARGIN_RIGHT, 5098 synaptics_sysctl, "I", 5099 "Right margin"); 5100 5101 /* hw.psm.synaptics.bottom_margin. */ 5102 sc->syninfo.margin_bottom = 200; 5103 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5104 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5105 "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5106 sc, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, 5107 synaptics_sysctl, "I", 5108 "Bottom margin"); 5109 5110 /* hw.psm.synaptics.left_margin. */ 5111 sc->syninfo.margin_left = 200; 5112 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5113 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5114 "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5115 sc, SYNAPTICS_SYSCTL_MARGIN_LEFT, 5116 synaptics_sysctl, "I", 5117 "Left margin"); 5118 5119 /* hw.psm.synaptics.na_top. */ 5120 sc->syninfo.na_top = 1783; 5121 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5122 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5123 "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5124 sc, SYNAPTICS_SYSCTL_NA_TOP, 5125 synaptics_sysctl, "I", 5126 "Top noisy area, where weight_previous_na is used instead " 5127 "of weight_previous"); 5128 5129 /* hw.psm.synaptics.na_right. */ 5130 sc->syninfo.na_right = 563; 5131 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5132 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5133 "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5134 sc, SYNAPTICS_SYSCTL_NA_RIGHT, 5135 synaptics_sysctl, "I", 5136 "Right noisy area, where weight_previous_na is used instead " 5137 "of weight_previous"); 5138 5139 /* hw.psm.synaptics.na_bottom. */ 5140 sc->syninfo.na_bottom = 1408; 5141 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5142 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5143 "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5144 sc, SYNAPTICS_SYSCTL_NA_BOTTOM, 5145 synaptics_sysctl, "I", 5146 "Bottom noisy area, where weight_previous_na is used instead " 5147 "of weight_previous"); 5148 5149 /* hw.psm.synaptics.na_left. */ 5150 sc->syninfo.na_left = 1600; 5151 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5152 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5153 "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5154 sc, SYNAPTICS_SYSCTL_NA_LEFT, 5155 synaptics_sysctl, "I", 5156 "Left noisy area, where weight_previous_na is used instead " 5157 "of weight_previous"); 5158 5159 /* hw.psm.synaptics.window_min. */ 5160 sc->syninfo.window_min = 4; 5161 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5162 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5163 "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5164 sc, SYNAPTICS_SYSCTL_WINDOW_MIN, 5165 synaptics_sysctl, "I", 5166 "Minimum window size to start an action"); 5167 5168 /* hw.psm.synaptics.window_max. */ 5169 sc->syninfo.window_max = 10; 5170 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5171 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5172 "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5173 sc, SYNAPTICS_SYSCTL_WINDOW_MAX, 5174 synaptics_sysctl, "I", 5175 "Maximum window size"); 5176 5177 /* hw.psm.synaptics.multiplicator. */ 5178 sc->syninfo.multiplicator = 10000; 5179 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5180 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5181 "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5182 sc, SYNAPTICS_SYSCTL_MULTIPLICATOR, 5183 synaptics_sysctl, "I", 5184 "Multiplicator to increase precision in averages and divisions"); 5185 5186 /* hw.psm.synaptics.weight_current. */ 5187 sc->syninfo.weight_current = 3; 5188 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5189 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5190 "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5191 sc, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, 5192 synaptics_sysctl, "I", 5193 "Weight of the current movement in the new average"); 5194 5195 /* hw.psm.synaptics.weight_previous. */ 5196 sc->syninfo.weight_previous = 6; 5197 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5198 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5199 "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5200 sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, 5201 synaptics_sysctl, "I", 5202 "Weight of the previous average"); 5203 5204 /* hw.psm.synaptics.weight_previous_na. */ 5205 sc->syninfo.weight_previous_na = 20; 5206 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5207 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5208 "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5209 sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, 5210 synaptics_sysctl, "I", 5211 "Weight of the previous average (inside the noisy area)"); 5212 5213 /* hw.psm.synaptics.weight_len_squared. */ 5214 sc->syninfo.weight_len_squared = 2000; 5215 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5216 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5217 "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5218 sc, SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, 5219 synaptics_sysctl, "I", 5220 "Length (squared) of segments where weight_previous " 5221 "starts to decrease"); 5222 5223 /* hw.psm.synaptics.div_min. */ 5224 sc->syninfo.div_min = 9; 5225 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5226 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5227 "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5228 sc, SYNAPTICS_SYSCTL_DIV_MIN, 5229 synaptics_sysctl, "I", 5230 "Divisor for fast movements"); 5231 5232 /* hw.psm.synaptics.div_max. */ 5233 sc->syninfo.div_max = 17; 5234 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5235 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5236 "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5237 sc, SYNAPTICS_SYSCTL_DIV_MAX, 5238 synaptics_sysctl, "I", 5239 "Divisor for slow movements"); 5240 5241 /* hw.psm.synaptics.div_max_na. */ 5242 sc->syninfo.div_max_na = 30; 5243 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5244 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5245 "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5246 sc, SYNAPTICS_SYSCTL_DIV_MAX_NA, 5247 synaptics_sysctl, "I", 5248 "Divisor with slow movements (inside the noisy area)"); 5249 5250 /* hw.psm.synaptics.div_len. */ 5251 sc->syninfo.div_len = 100; 5252 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5253 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5254 "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5255 sc, SYNAPTICS_SYSCTL_DIV_LEN, 5256 synaptics_sysctl, "I", 5257 "Length of segments where div_max starts to decrease"); 5258 5259 /* hw.psm.synaptics.tap_max_delta. */ 5260 sc->syninfo.tap_max_delta = 80; 5261 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5262 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5263 "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5264 sc, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, 5265 synaptics_sysctl, "I", 5266 "Length of segments above which a tap is ignored"); 5267 5268 /* hw.psm.synaptics.tap_min_queue. */ 5269 sc->syninfo.tap_min_queue = 2; 5270 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5271 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5272 "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5273 sc, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, 5274 synaptics_sysctl, "I", 5275 "Number of packets required to consider a tap"); 5276 5277 /* hw.psm.synaptics.taphold_timeout. */ 5278 sc->gesture.in_taphold = 0; 5279 sc->syninfo.taphold_timeout = tap_timeout; 5280 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5281 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5282 "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5283 sc, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, 5284 synaptics_sysctl, "I", 5285 "Maximum elapsed time between two taps to consider a tap-hold " 5286 "action"); 5287 5288 /* hw.psm.synaptics.vscroll_hor_area. */ 5289 sc->syninfo.vscroll_hor_area = 0; /* 1300 */ 5290 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5291 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5292 "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5293 sc, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, 5294 synaptics_sysctl, "I", 5295 "Area reserved for horizontal virtual scrolling"); 5296 5297 /* hw.psm.synaptics.vscroll_ver_area. */ 5298 sc->syninfo.vscroll_ver_area = -400 - sc->syninfo.margin_right; 5299 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5300 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5301 "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5302 sc, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, 5303 synaptics_sysctl, "I", 5304 "Area reserved for vertical virtual scrolling"); 5305 5306 /* hw.psm.synaptics.vscroll_min_delta. */ 5307 sc->syninfo.vscroll_min_delta = 50; 5308 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5309 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5310 "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5311 sc, SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, 5312 synaptics_sysctl, "I", 5313 "Minimum movement to consider virtual scrolling"); 5314 5315 /* hw.psm.synaptics.vscroll_div_min. */ 5316 sc->syninfo.vscroll_div_min = 100; 5317 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5318 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5319 "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5320 sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, 5321 synaptics_sysctl, "I", 5322 "Divisor for fast scrolling"); 5323 5324 /* hw.psm.synaptics.vscroll_div_min. */ 5325 sc->syninfo.vscroll_div_max = 150; 5326 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5327 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5328 "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5329 sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, 5330 synaptics_sysctl, "I", 5331 "Divisor for slow scrolling"); 5332 5333 /* hw.psm.synaptics.touchpad_off. */ 5334 sc->syninfo.touchpad_off = 0; 5335 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5336 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5337 "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5338 sc, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, 5339 synaptics_sysctl, "I", 5340 "Turn off touchpad"); 5341 5342 sc->syninfo.softbuttons_y = 0; 5343 sc->syninfo.softbutton2_x = 0; 5344 sc->syninfo.softbutton3_x = 0; 5345 5346 /* skip softbuttons sysctl on not clickpads */ 5347 if (sc->synhw.capClickPad) 5348 synaptics_sysctl_create_softbuttons_tree(sc); 5349 } 5350 5351 5352 static int 5353 synaptics_preferred_mode(struct psm_softc *sc) { 5354 int mode_byte; 5355 5356 mode_byte = 0xc4; 5357 5358 /* request wmode where available */ 5359 if (sc->synhw.capExtended) 5360 mode_byte |= 1; 5361 5362 return mode_byte; 5363 } 5364 5365 static void 5366 synaptics_set_mode(struct psm_softc *sc, int mode_byte) { 5367 mouse_ext_command(sc->kbdc, mode_byte); 5368 5369 /* "Commit" the Set Mode Byte command sent above. */ 5370 set_mouse_sampling_rate(sc->kbdc, 20); 5371 5372 /* 5373 * Enable advanced gestures mode if supported and we are not entering 5374 * passthrough mode. 5375 */ 5376 if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) && 5377 !(mode_byte & (1 << 5))) { 5378 mouse_ext_command(sc->kbdc, 3); 5379 set_mouse_sampling_rate(sc->kbdc, 0xc8); 5380 } 5381 } 5382 5383 static int 5384 enable_synaptics(struct psm_softc *sc, enum probearg arg) 5385 { 5386 KBDC kbdc = sc->kbdc; 5387 synapticshw_t synhw; 5388 int status[3]; 5389 int buttons; 5390 5391 VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n")); 5392 5393 /* 5394 * Just to be on the safe side: this avoids troubles with 5395 * following mouse_ext_command() when the previous command 5396 * was PSMC_SET_RESOLUTION. Set Scaling has no effect on 5397 * Synaptics Touchpad behaviour. 5398 */ 5399 set_mouse_scaling(kbdc, 1); 5400 5401 /* Identify the Touchpad version. */ 5402 if (mouse_ext_command(kbdc, 0) == 0) 5403 return (FALSE); 5404 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5405 return (FALSE); 5406 if (status[1] != 0x47) 5407 return (FALSE); 5408 5409 bzero(&synhw, sizeof(synhw)); 5410 synhw.infoMinor = status[0]; 5411 synhw.infoMajor = status[2] & 0x0f; 5412 5413 if (verbose >= 2) 5414 kprintf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, 5415 synhw.infoMinor); 5416 5417 if (synhw.infoMajor < 4) { 5418 kprintf(" Unsupported (pre-v4) Touchpad detected\n"); 5419 return (FALSE); 5420 } 5421 5422 /* Get the Touchpad model information. */ 5423 if (mouse_ext_command(kbdc, 3) == 0) 5424 return (FALSE); 5425 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5426 return (FALSE); 5427 if ((status[1] & 0x01) != 0) { 5428 kprintf(" Failed to read model information\n"); 5429 return (FALSE); 5430 } 5431 5432 synhw.infoRot180 = (status[0] & 0x80) != 0; 5433 synhw.infoPortrait = (status[0] & 0x40) != 0; 5434 synhw.infoSensor = status[0] & 0x3f; 5435 synhw.infoHardware = (status[1] & 0xfe) >> 1; 5436 synhw.infoNewAbs = (status[2] & 0x80) != 0; 5437 synhw.capPen = (status[2] & 0x40) != 0; 5438 synhw.infoSimplC = (status[2] & 0x20) != 0; 5439 synhw.infoGeometry = status[2] & 0x0f; 5440 5441 if (verbose >= 2) { 5442 kprintf(" Model information:\n"); 5443 kprintf(" infoRot180: %d\n", synhw.infoRot180); 5444 kprintf(" infoPortrait: %d\n", synhw.infoPortrait); 5445 kprintf(" infoSensor: %d\n", synhw.infoSensor); 5446 kprintf(" infoHardware: %d\n", synhw.infoHardware); 5447 kprintf(" infoNewAbs: %d\n", synhw.infoNewAbs); 5448 kprintf(" capPen: %d\n", synhw.capPen); 5449 kprintf(" infoSimplC: %d\n", synhw.infoSimplC); 5450 kprintf(" infoGeometry: %d\n", synhw.infoGeometry); 5451 } 5452 5453 /* Read the extended capability bits. */ 5454 if (mouse_ext_command(kbdc, 2) == 0) 5455 return (FALSE); 5456 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5457 return (FALSE); 5458 if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { 5459 kprintf(" Failed to read extended capability bits\n"); 5460 return (FALSE); 5461 } 5462 5463 /* Set the different capabilities when they exist. */ 5464 buttons = 0; 5465 synhw.capExtended = (status[0] & 0x80) != 0; 5466 if (synhw.capExtended) { 5467 synhw.nExtendedQueries = (status[0] & 0x70) >> 4; 5468 synhw.capMiddle = (status[0] & 0x04) != 0; 5469 synhw.capPassthrough = (status[2] & 0x80) != 0; 5470 synhw.capLowPower = (status[2] & 0x40) != 0; 5471 synhw.capMultiFingerReport = 5472 (status[2] & 0x20) != 0; 5473 synhw.capSleep = (status[2] & 0x10) != 0; 5474 synhw.capFourButtons = (status[2] & 0x08) != 0; 5475 synhw.capBallistics = (status[2] & 0x04) != 0; 5476 synhw.capMultiFinger = (status[2] & 0x02) != 0; 5477 synhw.capPalmDetect = (status[2] & 0x01) != 0; 5478 5479 if (!set_mouse_scaling(kbdc, 1)) 5480 return (FALSE); 5481 if (mouse_ext_command(kbdc, 0x08) == 0) 5482 return (FALSE); 5483 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5484 return (FALSE); 5485 5486 synhw.infoXupmm = status[0]; 5487 synhw.infoYupmm = status[2]; 5488 5489 if (verbose >= 2) { 5490 kprintf(" Extended capabilities:\n"); 5491 kprintf(" capExtended: %d\n", synhw.capExtended); 5492 kprintf(" capMiddle: %d\n", synhw.capMiddle); 5493 kprintf(" nExtendedQueries: %d\n", 5494 synhw.nExtendedQueries); 5495 kprintf(" capPassthrough: %d\n", synhw.capPassthrough); 5496 kprintf(" capLowPower: %d\n", synhw.capLowPower); 5497 kprintf(" capMultiFingerReport: %d\n", 5498 synhw.capMultiFingerReport); 5499 kprintf(" capSleep: %d\n", synhw.capSleep); 5500 kprintf(" capFourButtons: %d\n", synhw.capFourButtons); 5501 kprintf(" capBallistics: %d\n", synhw.capBallistics); 5502 kprintf(" capMultiFinger: %d\n", synhw.capMultiFinger); 5503 kprintf(" capPalmDetect: %d\n", synhw.capPalmDetect); 5504 kprintf(" infoXupmm: %d\n", synhw.infoXupmm); 5505 kprintf(" infoYupmm: %d\n", synhw.infoYupmm); 5506 } 5507 5508 /* 5509 * If nExtendedQueries is 1 or greater, then the TouchPad 5510 * supports this number of extended queries. We can load 5511 * more information about buttons using query 0x09. 5512 */ 5513 if (synhw.nExtendedQueries >= 1) { 5514 if (!set_mouse_scaling(kbdc, 1)) 5515 return (FALSE); 5516 if (mouse_ext_command(kbdc, 0x09) == 0) 5517 return (FALSE); 5518 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5519 return (FALSE); 5520 synhw.verticalScroll = (status[0] & 0x01) != 0; 5521 synhw.horizontalScroll = (status[0] & 0x02) != 0; 5522 synhw.verticalWheel = (status[0] & 0x08) != 0; 5523 synhw.nExtendedButtons = (status[1] & 0xf0) >> 4; 5524 synhw.capEWmode = (status[0] & 0x04) != 0; 5525 if (verbose >= 2) { 5526 kprintf(" Extended model ID:\n"); 5527 kprintf(" verticalScroll: %d\n", 5528 synhw.verticalScroll); 5529 kprintf(" horizontalScroll: %d\n", 5530 synhw.horizontalScroll); 5531 kprintf(" verticalWheel: %d\n", 5532 synhw.verticalWheel); 5533 kprintf(" nExtendedButtons: %d\n", 5534 synhw.nExtendedButtons); 5535 kprintf(" capEWmode: %d\n", 5536 synhw.capEWmode); 5537 } 5538 /* 5539 * Add the number of extended buttons to the total 5540 * button support count, including the middle button 5541 * if capMiddle support bit is set. 5542 */ 5543 buttons = synhw.nExtendedButtons + synhw.capMiddle; 5544 } else 5545 /* 5546 * If the capFourButtons support bit is set, 5547 * add a fourth button to the total button count. 5548 */ 5549 buttons = synhw.capFourButtons ? 1 : 0; 5550 5551 /* Read the continued capabilities bits. */ 5552 if (synhw.nExtendedQueries >= 4) { 5553 if (!set_mouse_scaling(kbdc, 1)) 5554 return (FALSE); 5555 if (mouse_ext_command(kbdc, 0x0c) == 0) 5556 return (FALSE); 5557 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5558 return (FALSE); 5559 5560 synhw.capClickPad = (status[1] & 0x01) << 1; 5561 synhw.capClickPad |= (status[0] & 0x10) != 0; 5562 synhw.capDeluxeLEDs = (status[1] & 0x02) != 0; 5563 synhw.noAbsoluteFilter = (status[1] & 0x04) != 0; 5564 synhw.capReportsV = (status[1] & 0x08) != 0; 5565 synhw.capUniformClickPad = (status[1] & 0x10) != 0; 5566 synhw.capReportsMin = (status[1] & 0x20) != 0; 5567 synhw.capInterTouch = (status[1] & 0x40) != 0; 5568 synhw.capReportsMax = (status[0] & 0x02) != 0; 5569 synhw.capClearPad = (status[0] & 0x04) != 0; 5570 synhw.capAdvancedGestures = (status[0] & 0x08) != 0; 5571 synhw.capCoveredPad = (status[0] & 0x80) != 0; 5572 5573 if (synhw.capReportsMax) { 5574 if (!set_mouse_scaling(kbdc, 1)) 5575 return (FALSE); 5576 if (mouse_ext_command(kbdc, 0x0d) == 0) 5577 return (FALSE); 5578 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5579 return (FALSE); 5580 5581 synhw.maximumXCoord = (status[0] << 5) | 5582 ((status[1] & 0x0f) << 1); 5583 synhw.maximumYCoord = (status[2] << 5) | 5584 ((status[1] & 0xf0) >> 3); 5585 } else { 5586 /* 5587 * Typical bezel limits. Taken from 'Synaptics 5588 * PS/2 * TouchPad Interfacing Guide' p.3.2.3. 5589 */ 5590 synhw.maximumXCoord = 5472; 5591 synhw.maximumYCoord = 4448; 5592 } 5593 5594 if (synhw.capReportsMin) { 5595 if (!set_mouse_scaling(kbdc, 1)) 5596 return (FALSE); 5597 if (mouse_ext_command(kbdc, 0x0f) == 0) 5598 return (FALSE); 5599 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5600 return (FALSE); 5601 5602 synhw.minimumXCoord = (status[0] << 5) | 5603 ((status[1] & 0x0f) << 1); 5604 synhw.minimumYCoord = (status[2] << 5) | 5605 ((status[1] & 0xf0) >> 3); 5606 } else { 5607 /* 5608 * Typical bezel limits. Taken from 'Synaptics 5609 * PS/2 * TouchPad Interfacing Guide' p.3.2.3. 5610 */ 5611 synhw.minimumXCoord = 1472; 5612 synhw.minimumYCoord = 1408; 5613 } 5614 5615 if (verbose >= 2) { 5616 kprintf(" Continued capabilities:\n"); 5617 kprintf(" capClickPad: %d\n", 5618 synhw.capClickPad); 5619 kprintf(" capDeluxeLEDs: %d\n", 5620 synhw.capDeluxeLEDs); 5621 kprintf(" noAbsoluteFilter: %d\n", 5622 synhw.noAbsoluteFilter); 5623 kprintf(" capReportsV: %d\n", 5624 synhw.capReportsV); 5625 kprintf(" capUniformClickPad: %d\n", 5626 synhw.capUniformClickPad); 5627 kprintf(" capReportsMin: %d\n", 5628 synhw.capReportsMin); 5629 kprintf(" capInterTouch: %d\n", 5630 synhw.capInterTouch); 5631 kprintf(" capReportsMax: %d\n", 5632 synhw.capReportsMax); 5633 kprintf(" capClearPad: %d\n", 5634 synhw.capClearPad); 5635 kprintf(" capAdvancedGestures: %d\n", 5636 synhw.capAdvancedGestures); 5637 kprintf(" capCoveredPad: %d\n", 5638 synhw.capCoveredPad); 5639 if (synhw.capReportsMax) { 5640 kprintf(" maximumXCoord: %d\n", 5641 synhw.maximumXCoord); 5642 kprintf(" maximumYCoord: %d\n", 5643 synhw.maximumYCoord); 5644 } 5645 if (synhw.capReportsMin) { 5646 kprintf(" minimumXCoord: %d\n", 5647 synhw.minimumXCoord); 5648 kprintf(" minimumYCoord: %d\n", 5649 synhw.minimumYCoord); 5650 } 5651 } 5652 buttons += synhw.capClickPad; 5653 } 5654 } 5655 5656 if (verbose >= 2) { 5657 if (synhw.capExtended) 5658 kprintf(" Additional Buttons: %d\n", buttons); 5659 else 5660 kprintf(" No extended capabilities\n"); 5661 } 5662 5663 /* 5664 * Add the default number of 3 buttons to the total 5665 * count of supported buttons reported above. 5666 */ 5667 buttons += 3; 5668 5669 /* 5670 * Read the mode byte. 5671 * 5672 * XXX: Note the Synaptics documentation also defines the first 5673 * byte of the response to this query to be a constant 0x3b, this 5674 * does not appear to be true for Touchpads with guest devices. 5675 */ 5676 if (mouse_ext_command(kbdc, 1) == 0) 5677 return (FALSE); 5678 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5679 return (FALSE); 5680 if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { 5681 kprintf(" Failed to read mode byte\n"); 5682 return (FALSE); 5683 } 5684 5685 if (arg == PROBE) 5686 sc->synhw = synhw; 5687 if (!synaptics_support) 5688 return (FALSE); 5689 5690 synaptics_set_mode(sc, synaptics_preferred_mode(sc)); 5691 5692 if (trackpoint_support && synhw.capPassthrough) { 5693 enable_trackpoint(sc, arg); 5694 } 5695 5696 VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); 5697 5698 if (arg == PROBE) { 5699 /* Create sysctl tree. */ 5700 synaptics_sysctl_create_tree(sc, "synaptics", 5701 "Synaptics TouchPad"); 5702 sc->hw.buttons = buttons; 5703 } 5704 return (TRUE); 5705 } 5706 5707 static void 5708 synaptics_passthrough_on(struct psm_softc *sc) 5709 { 5710 VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode.\n")); 5711 synaptics_set_mode(sc, synaptics_preferred_mode(sc) | (1 << 5)); 5712 } 5713 5714 static void 5715 synaptics_passthrough_off(struct psm_softc *sc) 5716 { 5717 VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n")); 5718 set_mouse_scaling(sc->kbdc, 2); 5719 set_mouse_scaling(sc->kbdc, 1); 5720 synaptics_set_mode(sc, synaptics_preferred_mode(sc)); 5721 } 5722 5723 /* IBM/Lenovo TrackPoint */ 5724 static int 5725 trackpoint_command(struct psm_softc *sc, int cmd, int loc, int val) 5726 { 5727 const int seq[] = { 0xe2, cmd, loc, val }; 5728 int i; 5729 5730 if (sc->synhw.capPassthrough) 5731 synaptics_passthrough_on(sc); 5732 5733 for (i = 0; i < nitems(seq); i++) { 5734 if (sc->synhw.capPassthrough && 5735 (seq[i] == 0xff || seq[i] == 0xe7)) 5736 if (send_aux_command(sc->kbdc, 0xe7) != PSM_ACK) { 5737 synaptics_passthrough_off(sc); 5738 return (EIO); 5739 } 5740 if (send_aux_command(sc->kbdc, seq[i]) != PSM_ACK) { 5741 if (sc->synhw.capPassthrough) 5742 synaptics_passthrough_off(sc); 5743 return (EIO); 5744 } 5745 } 5746 5747 if (sc->synhw.capPassthrough) 5748 synaptics_passthrough_off(sc); 5749 5750 return (0); 5751 } 5752 5753 #define PSM_TPINFO(x) offsetof(struct psm_softc, tpinfo.x) 5754 #define TPMASK 0 5755 #define TPLOC 1 5756 #define TPINFO 2 5757 5758 static int 5759 trackpoint_sysctl(SYSCTL_HANDLER_ARGS) 5760 { 5761 static const int data[][3] = { 5762 { 0x00, 0x4a, PSM_TPINFO(sensitivity) }, 5763 { 0x00, 0x4d, PSM_TPINFO(inertia) }, 5764 { 0x00, 0x60, PSM_TPINFO(uplateau) }, 5765 { 0x00, 0x57, PSM_TPINFO(reach) }, 5766 { 0x00, 0x58, PSM_TPINFO(draghys) }, 5767 { 0x00, 0x59, PSM_TPINFO(mindrag) }, 5768 { 0x00, 0x5a, PSM_TPINFO(upthresh) }, 5769 { 0x00, 0x5c, PSM_TPINFO(threshold) }, 5770 { 0x00, 0x5d, PSM_TPINFO(jenks) }, 5771 { 0x00, 0x5e, PSM_TPINFO(ztime) }, 5772 { 0x01, 0x2c, PSM_TPINFO(pts) }, 5773 { 0x08, 0x2d, PSM_TPINFO(skipback) } 5774 }; 5775 struct psm_softc *sc; 5776 int error, newval, *oldvalp; 5777 const int *tp; 5778 5779 if (arg1 == NULL || arg2 < 0 || arg2 >= nitems(data)) 5780 return (EINVAL); 5781 sc = arg1; 5782 tp = data[arg2]; 5783 oldvalp = (int *)((intptr_t)sc + tp[TPINFO]); 5784 newval = *oldvalp; 5785 error = sysctl_handle_int(oidp, &newval, 0, req); 5786 if (error != 0) 5787 return (error); 5788 if (newval == *oldvalp) 5789 return (0); 5790 if (newval < 0 || newval > (tp[TPMASK] == 0 ? 255 : 1)) 5791 return (EINVAL); 5792 error = trackpoint_command(sc, tp[TPMASK] == 0 ? 0x81 : 0x47, 5793 tp[TPLOC], tp[TPMASK] == 0 ? newval : tp[TPMASK]); 5794 if (error != 0) 5795 return (error); 5796 *oldvalp = newval; 5797 5798 return (0); 5799 } 5800 5801 static void 5802 trackpoint_sysctl_create_tree(struct psm_softc *sc) 5803 { 5804 5805 if (sc->tpinfo.sysctl_tree != NULL) 5806 return; 5807 5808 /* Attach extra trackpoint sysctl nodes under hw.psm.trackpoint */ 5809 sysctl_ctx_init(&sc->tpinfo.sysctl_ctx); 5810 sc->tpinfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->tpinfo.sysctl_ctx, 5811 SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "trackpoint", CTLFLAG_RD, 5812 0, "IBM/Lenovo TrackPoint"); 5813 5814 /* hw.psm.trackpoint.sensitivity */ 5815 sc->tpinfo.sensitivity = 0x80; 5816 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5817 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5818 "sensitivity", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5819 sc, TRACKPOINT_SYSCTL_SENSITIVITY, 5820 trackpoint_sysctl, "I", 5821 "Sensitivity"); 5822 5823 /* hw.psm.trackpoint.negative_inertia */ 5824 sc->tpinfo.inertia = 0x06; 5825 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5826 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5827 "negative_inertia", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5828 sc, TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, 5829 trackpoint_sysctl, "I", 5830 "Negative inertia factor"); 5831 5832 /* hw.psm.trackpoint.upper_plateau */ 5833 sc->tpinfo.uplateau = 0x61; 5834 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5835 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5836 "upper_plateau", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5837 sc, TRACKPOINT_SYSCTL_UPPER_PLATEAU, 5838 trackpoint_sysctl, "I", 5839 "Transfer function upper plateau speed"); 5840 5841 /* hw.psm.trackpoint.backup_range */ 5842 sc->tpinfo.reach = 0x0a; 5843 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5844 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5845 "backup_range", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5846 sc, TRACKPOINT_SYSCTL_BACKUP_RANGE, 5847 trackpoint_sysctl, "I", 5848 "Backup range"); 5849 5850 /* hw.psm.trackpoint.drag_hysteresis */ 5851 sc->tpinfo.draghys = 0xff; 5852 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5853 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5854 "drag_hysteresis", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5855 sc, TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, 5856 trackpoint_sysctl, "I", 5857 "Drag hysteresis"); 5858 5859 /* hw.psm.trackpoint.minimum_drag */ 5860 sc->tpinfo.mindrag = 0x14; 5861 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5862 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5863 "minimum_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5864 sc, TRACKPOINT_SYSCTL_MINIMUM_DRAG, 5865 trackpoint_sysctl, "I", 5866 "Minimum drag"); 5867 5868 /* hw.psm.trackpoint.up_threshold */ 5869 sc->tpinfo.upthresh = 0xff; 5870 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5871 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5872 "up_threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5873 sc, TRACKPOINT_SYSCTL_UP_THRESHOLD, 5874 trackpoint_sysctl, "I", 5875 "Up threshold for release"); 5876 5877 /* hw.psm.trackpoint.threshold */ 5878 sc->tpinfo.threshold = 0x08; 5879 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5880 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5881 "threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5882 sc, TRACKPOINT_SYSCTL_THRESHOLD, 5883 trackpoint_sysctl, "I", 5884 "Threshold"); 5885 5886 /* hw.psm.trackpoint.jenks_curvature */ 5887 sc->tpinfo.jenks = 0x87; 5888 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5889 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5890 "jenks_curvature", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5891 sc, TRACKPOINT_SYSCTL_JENKS_CURVATURE, 5892 trackpoint_sysctl, "I", 5893 "Jenks curvature"); 5894 5895 /* hw.psm.trackpoint.z_time */ 5896 sc->tpinfo.ztime = 0x26; 5897 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5898 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5899 "z_time", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5900 sc, TRACKPOINT_SYSCTL_Z_TIME, 5901 trackpoint_sysctl, "I", 5902 "Z time constant"); 5903 5904 /* hw.psm.trackpoint.press_to_select */ 5905 sc->tpinfo.pts = 0x00; 5906 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5907 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5908 "press_to_select", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5909 sc, TRACKPOINT_SYSCTL_PRESS_TO_SELECT, 5910 trackpoint_sysctl, "I", 5911 "Press to Select"); 5912 5913 /* hw.psm.trackpoint.skip_backups */ 5914 sc->tpinfo.skipback = 0x00; 5915 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5916 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5917 "skip_backups", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5918 sc, TRACKPOINT_SYSCTL_SKIP_BACKUPS, 5919 trackpoint_sysctl, "I", 5920 "Skip backups from drags"); 5921 } 5922 5923 static void 5924 set_trackpoint_parameters(struct psm_softc *sc) 5925 { 5926 trackpoint_command(sc, 0x81, 0x4a, sc->tpinfo.sensitivity); 5927 trackpoint_command(sc, 0x81, 0x60, sc->tpinfo.uplateau); 5928 trackpoint_command(sc, 0x81, 0x4d, sc->tpinfo.inertia); 5929 trackpoint_command(sc, 0x81, 0x57, sc->tpinfo.reach); 5930 trackpoint_command(sc, 0x81, 0x58, sc->tpinfo.draghys); 5931 trackpoint_command(sc, 0x81, 0x59, sc->tpinfo.mindrag); 5932 trackpoint_command(sc, 0x81, 0x5a, sc->tpinfo.upthresh); 5933 trackpoint_command(sc, 0x81, 0x5c, sc->tpinfo.threshold); 5934 trackpoint_command(sc, 0x81, 0x5d, sc->tpinfo.jenks); 5935 trackpoint_command(sc, 0x81, 0x5e, sc->tpinfo.ztime); 5936 if (sc->tpinfo.pts == 0x01) 5937 trackpoint_command(sc, 0x47, 0x2c, 0x01); 5938 if (sc->tpinfo.skipback == 0x01) 5939 trackpoint_command(sc, 0x47, 0x2d, 0x08); 5940 } 5941 5942 static int 5943 enable_trackpoint(struct psm_softc *sc, enum probearg arg) 5944 { 5945 KBDC kbdc = sc->kbdc; 5946 int id; 5947 5948 /* 5949 * If called from enable_synaptics(), make sure that passthrough 5950 * mode is enabled so we can reach the trackpoint. 5951 * However, passthrough mode must be disabled before setting the 5952 * trackpoint parameters, as rackpoint_command() enables and disables 5953 * passthrough mode on its own. 5954 */ 5955 if (sc->synhw.capPassthrough) 5956 synaptics_passthrough_on(sc); 5957 5958 if (send_aux_command(kbdc, 0xe1) != PSM_ACK || 5959 read_aux_data(kbdc) != 0x01) 5960 goto no_trackpoint; 5961 id = read_aux_data(kbdc); 5962 if (id < 0x01) 5963 goto no_trackpoint; 5964 if (arg == PROBE) 5965 sc->tphw = id; 5966 if (!trackpoint_support) 5967 goto no_trackpoint; 5968 5969 if (sc->synhw.capPassthrough) 5970 synaptics_passthrough_off(sc); 5971 5972 if (arg == PROBE) { 5973 trackpoint_sysctl_create_tree(sc); 5974 /* 5975 * Don't overwrite hwid and buttons when we are 5976 * a guest device. 5977 */ 5978 if (!sc->synhw.capPassthrough) { 5979 sc->hw.hwid = id; 5980 sc->hw.buttons = 3; 5981 } 5982 } 5983 5984 set_trackpoint_parameters(sc); 5985 5986 return (TRUE); 5987 5988 no_trackpoint: 5989 if (sc->synhw.capPassthrough) 5990 synaptics_passthrough_off(sc); 5991 5992 return (FALSE); 5993 } 5994 5995 /* Interlink electronics VersaPad */ 5996 static int 5997 enable_versapad(struct psm_softc *sc, enum probearg arg) 5998 { 5999 KBDC kbdc = sc->kbdc; 6000 int data[3]; 6001 6002 set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */ 6003 set_mouse_sampling_rate(kbdc, 100); /* set rate 100 */ 6004 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6005 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6006 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6007 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6008 if (get_mouse_status(kbdc, data, 0, 3) < 3) /* get status */ 6009 return (FALSE); 6010 if (data[2] != 0xa || data[1] != 0 ) /* rate == 0xa && res. == 0 */ 6011 return (FALSE); 6012 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6013 6014 return (TRUE); /* PS/2 absolute mode */ 6015 } 6016 6017 /* Elantech Touchpad */ 6018 static int 6019 elantech_read_1(KBDC kbdc, int hwversion, int reg, int *val) 6020 { 6021 int res, readcmd, retidx; 6022 int resp[3]; 6023 6024 readcmd = hwversion == 2 ? ELANTECH_REG_READ : ELANTECH_REG_RDWR; 6025 retidx = hwversion == 4 ? 1 : 0; 6026 6027 res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6028 res |= send_aux_command(kbdc, readcmd) != PSM_ACK; 6029 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6030 res |= send_aux_command(kbdc, reg) != PSM_ACK; 6031 res |= get_mouse_status(kbdc, resp, 0, 3) != 3; 6032 6033 if (res == 0) 6034 *val = resp[retidx]; 6035 6036 return (res); 6037 } 6038 6039 static int 6040 elantech_write_1(KBDC kbdc, int hwversion, int reg, int val) 6041 { 6042 int res, writecmd; 6043 6044 writecmd = hwversion == 2 ? ELANTECH_REG_WRITE : ELANTECH_REG_RDWR; 6045 6046 res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6047 res |= send_aux_command(kbdc, writecmd) != PSM_ACK; 6048 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6049 res |= send_aux_command(kbdc, reg) != PSM_ACK; 6050 if (hwversion == 4) { 6051 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6052 res |= send_aux_command(kbdc, writecmd) != PSM_ACK; 6053 } 6054 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6055 res |= send_aux_command(kbdc, val) != PSM_ACK; 6056 res |= set_mouse_scaling(kbdc, 1) == 0; 6057 6058 return (res); 6059 } 6060 6061 static int 6062 elantech_cmd(KBDC kbdc, int hwversion, int cmd, int *resp) 6063 { 6064 int res; 6065 6066 if (hwversion == 2) { 6067 res = set_mouse_scaling(kbdc, 1) == 0; 6068 res |= mouse_ext_command(kbdc, cmd) == 0; 6069 } else { 6070 res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6071 res |= send_aux_command(kbdc, cmd) != PSM_ACK; 6072 } 6073 res |= get_mouse_status(kbdc, resp, 0, 3) != 3; 6074 6075 return (res); 6076 } 6077 6078 static int 6079 elantech_init(KBDC kbdc, elantechhw_t *elanhw) 6080 { 6081 int i, val, res, hwversion, reg10; 6082 6083 /* set absolute mode */ 6084 hwversion = elanhw->hwversion; 6085 reg10 = -1; 6086 switch (hwversion) { 6087 case 2: 6088 reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4; 6089 res = elantech_write_1(kbdc, hwversion, 0x10, reg10); 6090 if (res) 6091 break; 6092 res = elantech_write_1(kbdc, hwversion, 0x11, 0x8A); 6093 break; 6094 case 3: 6095 reg10 = 0x0b; 6096 res = elantech_write_1(kbdc, hwversion, 0x10, reg10); 6097 break; 6098 case 4: 6099 res = elantech_write_1(kbdc, hwversion, 0x07, 0x01); 6100 break; 6101 default: 6102 res = 1; 6103 } 6104 6105 /* Read back reg 0x10 to ensure hardware is ready. */ 6106 if (res == 0 && reg10 >= 0) { 6107 for (i = 0; i < 5; i++) { 6108 if (elantech_read_1(kbdc, hwversion, 0x10, &val) == 0) 6109 break; 6110 DELAY(2000); 6111 } 6112 if (i == 5) 6113 res = 1; 6114 } 6115 6116 if (res) 6117 kprintf("couldn't set absolute mode\n"); 6118 6119 return (res); 6120 } 6121 6122 static void 6123 elantech_init_synaptics(struct psm_softc *sc) 6124 { 6125 6126 /* Set capabilites required by movement smother */ 6127 sc->synhw.infoMajor = sc->elanhw.hwversion; 6128 sc->synhw.infoMinor = sc->elanhw.fwversion; 6129 sc->synhw.infoXupmm = sc->elanhw.dpmmx; 6130 sc->synhw.infoYupmm = sc->elanhw.dpmmy; 6131 sc->synhw.verticalScroll = 0; 6132 sc->synhw.nExtendedQueries = 4; 6133 sc->synhw.capExtended = 1; 6134 sc->synhw.capPassthrough = sc->elanhw.hastrackpoint; 6135 sc->synhw.capClickPad = sc->elanhw.isclickpad; 6136 sc->synhw.capMultiFinger = 1; 6137 sc->synhw.capAdvancedGestures = 1; 6138 sc->synhw.capPalmDetect = 1; 6139 sc->synhw.capPen = 0; 6140 sc->synhw.capReportsMax = 1; 6141 sc->synhw.maximumXCoord = sc->elanhw.sizex; 6142 sc->synhw.maximumYCoord = sc->elanhw.sizey; 6143 sc->synhw.capReportsMin = 1; 6144 sc->synhw.minimumXCoord = 0; 6145 sc->synhw.minimumYCoord = 0; 6146 6147 if (sc->syninfo.sysctl_tree == NULL) { 6148 synaptics_sysctl_create_tree(sc, "elantech", 6149 "Elantech Touchpad"); 6150 6151 /* 6152 * Adjust synaptic smoother tunables 6153 * 1. Disable finger detection pressure threshold. Unlike 6154 * synaptics we assume the finger is acting when packet with 6155 * its X&Y arrives not when pressure exceedes some threshold 6156 * 2. Disable unrelated features like margins and noisy areas 6157 * 3. Disable virtual scroll areas as 2nd finger is preferable 6158 * 4. For clickpads set bottom quarter as 42% - 16% - 42% sized 6159 * softbuttons 6160 * 5. Scale down divisors and movement lengths by a factor of 3 6161 * where 3 is Synaptics to Elantech (~2200/800) dpi ratio 6162 */ 6163 6164 /* Set reporting range to be equal touchpad size */ 6165 sc->syninfo.max_x = sc->elanhw.sizex; 6166 sc->syninfo.max_y = sc->elanhw.sizey; 6167 6168 /* Disable finger detection pressure threshold */ 6169 sc->syninfo.min_pressure = 1; 6170 6171 /* Use full area of touchpad */ 6172 sc->syninfo.margin_top = 0; 6173 sc->syninfo.margin_right = 0; 6174 sc->syninfo.margin_bottom = 0; 6175 sc->syninfo.margin_left = 0; 6176 6177 /* Disable noisy area */ 6178 sc->syninfo.na_top = 0; 6179 sc->syninfo.na_right = 0; 6180 sc->syninfo.na_bottom = 0; 6181 sc->syninfo.na_left = 0; 6182 6183 /* Tune divisors and movement lengths */ 6184 sc->syninfo.weight_len_squared = 200; 6185 sc->syninfo.div_min = 3; 6186 sc->syninfo.div_max = 6; 6187 sc->syninfo.div_max_na = 10; 6188 sc->syninfo.div_len = 30; 6189 sc->syninfo.tap_max_delta = 25; 6190 6191 /* Disable virtual scrolling areas and tune its divisors */ 6192 sc->syninfo.vscroll_hor_area = 0; 6193 sc->syninfo.vscroll_ver_area = 0; 6194 sc->syninfo.vscroll_min_delta = 15; 6195 sc->syninfo.vscroll_div_min = 30; 6196 sc->syninfo.vscroll_div_max = 50; 6197 6198 /* Set bottom quarter as 42% - 16% - 42% sized softbuttons */ 6199 if (sc->elanhw.isclickpad) { 6200 sc->syninfo.softbuttons_y = sc->elanhw.sizey / 4; 6201 sc->syninfo.softbutton2_x = sc->elanhw.sizex * 11 / 25; 6202 sc->syninfo.softbutton3_x = sc->elanhw.sizex * 14 / 25; 6203 } 6204 } 6205 6206 return; 6207 } 6208 6209 static int 6210 enable_elantech(struct psm_softc *sc, enum probearg arg) 6211 { 6212 static const int ic2hw[] = 6213 /*IC: 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 6214 { 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; 6215 elantechhw_t elanhw; 6216 int icversion, hwversion, dptracex, dptracey, id, resp[3], dpix, dpiy; 6217 KBDC kbdc = sc->kbdc; 6218 6219 VLOG(3, (LOG_DEBUG, "elantech: BEGIN init\n")); 6220 6221 set_mouse_scaling(kbdc, 1); 6222 set_mouse_scaling(kbdc, 1); 6223 set_mouse_scaling(kbdc, 1); 6224 if (get_mouse_status(kbdc, resp, 0, 3) != 3) 6225 return (FALSE); 6226 6227 if (!ELANTECH_MAGIC(resp)) 6228 return (FALSE); 6229 6230 /* Identify the Touchpad version. */ 6231 if (elantech_cmd(kbdc, 2, ELANTECH_FW_VERSION, resp)) 6232 return (FALSE); 6233 6234 bzero(&elanhw, sizeof(elanhw)); 6235 6236 elanhw.fwversion = (resp[0] << 16) | (resp[1] << 8) | resp[2]; 6237 icversion = resp[0] & 0x0f; 6238 hwversion = ic2hw[icversion]; 6239 6240 if (verbose >= 2) 6241 kprintf("Elantech touchpad hardware v.%d firmware v.0x%06x\n", 6242 hwversion, elanhw.fwversion); 6243 6244 if (ELANTECH_HW_IS_V1(elanhw.fwversion)) { 6245 kprintf (" Unsupported touchpad hardware (v1)\n"); 6246 return (FALSE); 6247 } 6248 if (hwversion == 0) { 6249 kprintf (" Unknown touchpad hardware (firmware v.0x%06x)\n", 6250 elanhw.fwversion); 6251 return (FALSE); 6252 } 6253 6254 /* Get the Touchpad model information. */ 6255 elanhw.hwversion = hwversion; 6256 elanhw.issemimt = hwversion == 2; 6257 elanhw.isclickpad = (resp[1] & 0x10) != 0; 6258 elanhw.hascrc = (resp[1] & 0x40) != 0; 6259 elanhw.haspressure = elanhw.fwversion >= 0x020800; 6260 6261 /* Read the capability bits. */ 6262 if (elantech_cmd(kbdc, hwversion, ELANTECH_CAPABILITIES, resp) != 0) { 6263 kprintf(" Failed to read capability bits\n"); 6264 return (FALSE); 6265 } 6266 6267 elanhw.ntracesx = resp[1] - 1; 6268 elanhw.ntracesy = resp[2] - 1; 6269 elanhw.hastrackpoint = (resp[0] & 0x80) != 0; 6270 6271 /* Get the touchpad resolution */ 6272 switch (hwversion) { 6273 case 4: 6274 if (elantech_cmd(kbdc, hwversion, ELANTECH_RESOLUTION, resp) 6275 == 0) { 6276 dpix = (resp[1] & 0x0f) * 10 + 790; 6277 dpiy = ((resp[1] & 0xf0) >> 4) * 10 + 790; 6278 elanhw.dpmmx = (dpix * 10 + 5) / 254; 6279 elanhw.dpmmy = (dpiy * 10 + 5) / 254; 6280 break; 6281 } 6282 /* FALLTHROUGH */ 6283 case 2: 6284 case 3: 6285 elanhw.dpmmx = elanhw.dpmmy = 32; /* 800 dpi */ 6286 break; 6287 } 6288 6289 if (!elantech_support) 6290 return (FALSE); 6291 6292 if (elantech_init(kbdc, &elanhw)) { 6293 kprintf("couldn't initialize elantech touchpad\n"); 6294 return (FALSE); 6295 } 6296 6297 /* 6298 * Get the touchpad reporting range. 6299 * On HW v.3 touchpads it should be done after switching hardware 6300 * to real resolution mode (by setting bit 3 of reg10) 6301 */ 6302 if (elantech_cmd(kbdc, hwversion, ELANTECH_FW_ID, resp) != 0) { 6303 kprintf(" Failed to read touchpad size\n"); 6304 elanhw.sizex = 10000; /* Arbitrary high values to */ 6305 elanhw.sizey = 10000; /* prevent clipping in smoother */ 6306 } else if (hwversion == 2) { 6307 dptracex = dptracey = 64; 6308 if ((elanhw.fwversion >> 16) == 0x14 && (resp[1] & 0x10) && 6309 !elantech_cmd(kbdc, hwversion, ELANTECH_SAMPLE, resp)) { 6310 dptracex = resp[1] / 2; 6311 dptracey = resp[2] / 2; 6312 } 6313 elanhw.sizex = (elanhw.ntracesx - 1) * dptracex; 6314 elanhw.sizey = (elanhw.ntracesy - 1) * dptracey; 6315 } else { 6316 elanhw.sizex = (resp[0] & 0x0f) << 8 | resp[1]; 6317 elanhw.sizey = (resp[0] & 0xf0) << 4 | resp[2]; 6318 } 6319 6320 if (verbose >= 2) { 6321 kprintf(" Model information:\n"); 6322 kprintf(" MaxX: %d\n", elanhw.sizex); 6323 kprintf(" MaxY: %d\n", elanhw.sizey); 6324 kprintf(" DpmmX: %d\n", elanhw.dpmmx); 6325 kprintf(" DpmmY: %d\n", elanhw.dpmmy); 6326 kprintf(" TracesX: %d\n", elanhw.ntracesx); 6327 kprintf(" TracesY: %d\n", elanhw.ntracesy); 6328 kprintf(" SemiMT: %d\n", elanhw.issemimt); 6329 kprintf(" Clickpad: %d\n", elanhw.isclickpad); 6330 kprintf(" Trackpoint: %d\n", elanhw.hastrackpoint); 6331 kprintf(" CRC: %d\n", elanhw.hascrc); 6332 kprintf(" Pressure: %d\n", elanhw.haspressure); 6333 } 6334 6335 VLOG(3, (LOG_DEBUG, "elantech: END init\n")); 6336 6337 if (arg == PROBE) { 6338 sc->elanhw = elanhw; 6339 sc->hw.buttons = 3; 6340 6341 /* Initialize synaptics movement smoother */ 6342 elantech_init_synaptics(sc); 6343 6344 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) 6345 PSM_FINGER_RESET(sc->elanaction.fingers[id]); 6346 } 6347 return (TRUE); 6348 } 6349 6350 /* 6351 * Return true if 'now' is earlier than (start + (secs.usecs)). 6352 * Now may be NULL and the function will fetch the current time from 6353 * getmicrouptime(), or a cached 'now' can be passed in. 6354 * All values should be numbers derived from getmicrouptime(). 6355 */ 6356 static int 6357 timeelapsed(const struct timeval *start, int secs, int usecs, 6358 const struct timeval *now) { 6359 struct timeval snow, tv; 6360 6361 /* if there is no 'now' passed in, the get it as a convenience. */ 6362 if (now == NULL) { 6363 getmicrouptime(&snow); 6364 now = &snow; 6365 } 6366 6367 tv.tv_sec = secs; 6368 tv.tv_usec = usecs; 6369 timevaladd(&tv, start); 6370 return (timevalcmp(&tv, now, <)); 6371 } 6372 6373 static int 6374 psmresume(device_t dev) 6375 { 6376 6377 struct psm_softc *sc = device_get_softc(dev); 6378 int unit = device_get_unit(dev); 6379 int err; 6380 6381 VLOG(2, (LOG_NOTICE, "psm%d: system resume hook called.\n", unit)); 6382 6383 if ((sc->config & 6384 (PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND)) == 0) 6385 return (0); 6386 6387 err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND); 6388 6389 if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) { 6390 /* 6391 * Release the blocked process; it must be notified that 6392 * the device cannot be accessed anymore. 6393 */ 6394 sc->state &= ~PSM_ASLP; 6395 wakeup(sc); 6396 } 6397 6398 VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit)); 6399 6400 return (err); 6401 } 6402 6403 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, NULL, NULL); 6404 6405 #ifdef DEV_ISA 6406 #if 0 6407 /* 6408 * This sucks up assignments from PNPBIOS and ACPI. 6409 */ 6410 6411 /* 6412 * When the PS/2 mouse device is reported by ACPI or PnP BIOS, it may 6413 * appear BEFORE the AT keyboard controller. As the PS/2 mouse device 6414 * can be probed and attached only after the AT keyboard controller is 6415 * attached, we shall quietly reserve the IRQ resource for later use. 6416 * If the PS/2 mouse device is reported to us AFTER the keyboard controller, 6417 * copy the IRQ resource to the PS/2 mouse device instance hanging 6418 * under the keyboard controller, then probe and attach it. 6419 */ 6420 6421 static devclass_t psmcpnp_devclass; 6422 6423 static device_probe_t psmcpnp_probe; 6424 static device_attach_t psmcpnp_attach; 6425 6426 static device_method_t psmcpnp_methods[] = { 6427 DEVMETHOD(device_probe, psmcpnp_probe), 6428 DEVMETHOD(device_attach, psmcpnp_attach), 6429 6430 { 0, 0 } 6431 }; 6432 6433 static driver_t psmcpnp_driver = { 6434 PSMCPNP_DRIVER_NAME, 6435 psmcpnp_methods, 6436 1, /* no softc */ 6437 }; 6438 6439 static struct isa_pnp_id psmcpnp_ids[] = { 6440 { 0x030fd041, "PS/2 mouse port" }, /* PNP0F03 */ 6441 { 0x0e0fd041, "PS/2 mouse port" }, /* PNP0F0E */ 6442 { 0x120fd041, "PS/2 mouse port" }, /* PNP0F12 */ 6443 { 0x130fd041, "PS/2 mouse port" }, /* PNP0F13 */ 6444 { 0x1303d041, "PS/2 port" }, /* PNP0313, XXX */ 6445 { 0x02002e4f, "Dell PS/2 mouse port" }, /* Lat. X200, Dell */ 6446 { 0x0002a906, "ALPS Glide Point" }, /* ALPS Glide Point */ 6447 { 0x80374d24, "IBM PS/2 mouse port" }, /* IBM3780, ThinkPad */ 6448 { 0x81374d24, "IBM PS/2 mouse port" }, /* IBM3781, ThinkPad */ 6449 { 0x0190d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9001, Vaio */ 6450 { 0x0290d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9002, Vaio */ 6451 { 0x0390d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9003, Vaio */ 6452 { 0x0490d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9004, Vaio */ 6453 { 0 } 6454 }; 6455 6456 static int 6457 create_a_copy(device_t atkbdc, device_t me) 6458 { 6459 6460 device_t psm; 6461 u_long irq; 6462 6463 /* find the PS/2 mouse device instance under the keyboard controller */ 6464 psm = device_find_child(atkbdc, PSM_DRIVER_NAME, 6465 device_get_unit(atkbdc)); 6466 if (psm == NULL) 6467 return (ENXIO); 6468 if (device_get_state(psm) != DS_NOTPRESENT) 6469 return (0); 6470 6471 /* move our resource to the found device */ 6472 irq = bus_get_resource_start(me, SYS_RES_IRQ, 0); 6473 bus_delete_resource(me, SYS_RES_IRQ, 0); 6474 bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1, 6475 machintr_legacy_intr_cpuid(irq)); 6476 6477 /* ...then probe and attach it */ 6478 return (device_probe_and_attach(psm)); 6479 } 6480 6481 static int 6482 psmcpnp_probe(device_t dev) 6483 { 6484 struct resource *res; 6485 u_long irq; 6486 int rid; 6487 6488 if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids)) 6489 return (ENXIO); 6490 6491 /* 6492 * The PnP BIOS and ACPI are supposed to assign an IRQ (12) 6493 * to the PS/2 mouse device node. But, some buggy PnP BIOS 6494 * declares the PS/2 mouse device node without an IRQ resource! 6495 * If this happens, we shall refer to device hints. 6496 * If we still don't find it there, use a hardcoded value... XXX 6497 */ 6498 rid = 0; 6499 irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid); 6500 if (irq <= 0) { 6501 if (resource_long_value(PSM_DRIVER_NAME, 6502 device_get_unit(dev),"irq", &irq) != 0) 6503 irq = 12; /* XXX */ 6504 device_printf(dev, "irq resource info is missing; " 6505 "assuming irq %ld\n", irq); 6506 bus_set_resource(dev, SYS_RES_IRQ, rid, irq, 1, 6507 machintr_legacy_intr_cpuid(irq)); 6508 } 6509 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE); 6510 bus_release_resource(dev, SYS_RES_IRQ, rid, res); 6511 6512 /* keep quiet */ 6513 if (!bootverbose) 6514 device_quiet(dev); 6515 6516 return ((res == NULL) ? ENXIO : 0); 6517 } 6518 6519 static int 6520 psmcpnp_attach(device_t dev) 6521 { 6522 device_t atkbdc; 6523 6524 /* find the keyboard controller, which may be on acpi* or isa* bus */ 6525 atkbdc = devclass_get_device(devclass_find(ATKBDC_DRIVER_NAME), 6526 device_get_unit(dev)); 6527 if ((atkbdc != NULL) && (device_get_state(atkbdc) == DS_ATTACHED)) { 6528 create_a_copy(atkbdc, dev); 6529 } else { 6530 /* 6531 * If we don't have the AT keyboard controller yet, 6532 * just reserve the IRQ for later use... 6533 * (See psmidentify() above.) 6534 */ 6535 rid = 0; 6536 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE); 6537 } 6538 6539 return (0); 6540 } 6541 6542 DRIVER_MODULE(psmcpnp, isa, psmcpnp_driver, psmcpnp_devclass, NULL, NULL); 6543 DRIVER_MODULE(psmcpnp, acpi, psmcpnp_driver, psmcpnp_devclass, NULL, NULL); 6544 6545 #endif 6546 #endif /* DEV_ISA */ 6547