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 2496 if (pb->inputbytes < sc->mode.packetsize) 2497 continue; 2498 2499 VLOG(4, (LOG_DEBUG, 2500 "psmintr: %02x %02x %02x %02x %02x %02x\n", 2501 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], 2502 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); 2503 2504 c = pb->ipacket[0]; 2505 2506 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) { 2507 sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]); 2508 sc->flags &= ~PSM_NEED_SYNCBITS; 2509 VLOG(2, (LOG_DEBUG, 2510 "psmintr: Sync bytes now %04x,%04x\n", 2511 sc->mode.syncmask[0], sc->mode.syncmask[0])); 2512 } else if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) { 2513 VLOG(3, (LOG_DEBUG, "psmintr: out of sync " 2514 "(%04x != %04x) %d cmds since last error.\n", 2515 c & sc->mode.syncmask[0], sc->mode.syncmask[1], 2516 sc->cmdcount - sc->lasterr)); 2517 sc->lasterr = sc->cmdcount; 2518 /* 2519 * The sync byte test is a weak measure of packet 2520 * validity. Conservatively discard any input yet 2521 * to be seen by userland when we detect a sync 2522 * error since there is a good chance some of 2523 * the queued packets have undetected errors. 2524 */ 2525 dropqueue(sc); 2526 if (sc->syncerrors == 0) 2527 sc->pkterrors++; 2528 ++sc->syncerrors; 2529 sc->lastinputerr = now; 2530 if (sc->syncerrors >= sc->mode.packetsize * 2 || 2531 sc->pkterrors >= pkterrthresh) { 2532 /* 2533 * If we've failed to find a single sync byte 2534 * in 2 packets worth of data, or we've seen 2535 * persistent packet errors during the 2536 * validation period, reinitialize the mouse 2537 * in hopes of returning it to the expected 2538 * mode. 2539 */ 2540 VLOG(3, (LOG_DEBUG, 2541 "psmintr: reset the mouse.\n")); 2542 reinitialize(sc, TRUE); 2543 } else if (sc->syncerrors == sc->mode.packetsize) { 2544 /* 2545 * Try a soft reset after searching for a sync 2546 * byte through a packet length of bytes. 2547 */ 2548 VLOG(3, (LOG_DEBUG, 2549 "psmintr: re-enable the mouse.\n")); 2550 pb->inputbytes = 0; 2551 disable_aux_dev(sc->kbdc); 2552 enable_aux_dev(sc->kbdc); 2553 } else { 2554 VLOG(3, (LOG_DEBUG, 2555 "psmintr: discard a byte (%d)\n", 2556 sc->syncerrors)); 2557 pb->inputbytes--; 2558 bcopy(&pb->ipacket[1], &pb->ipacket[0], 2559 pb->inputbytes); 2560 } 2561 continue; 2562 } 2563 2564 /* 2565 * We have what appears to be a valid packet. 2566 * Reset the error counters. 2567 */ 2568 sc->syncerrors = 0; 2569 2570 /* 2571 * Drop even good packets if they occur within a timeout 2572 * period of a sync error. This allows the detection of 2573 * a change in the mouse's packet mode without exposing 2574 * erratic mouse behavior to the user. Some KVMs forget 2575 * enhanced mouse modes during switch events. 2576 */ 2577 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs, 2578 &now)) { 2579 pb->inputbytes = 0; 2580 continue; 2581 } 2582 2583 /* 2584 * Now that we're out of the validation period, reset 2585 * the packet error count. 2586 */ 2587 sc->pkterrors = 0; 2588 2589 sc->cmdcount++; 2590 if (++sc->pqueue_end >= PSM_PACKETQUEUE) 2591 sc->pqueue_end = 0; 2592 /* 2593 * If we've filled the queue then call the softintr ourselves, 2594 * otherwise schedule the interrupt for later. 2595 */ 2596 if (!timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) || 2597 (sc->pqueue_end == sc->pqueue_start)) { 2598 if ((sc->state & PSM_SOFTARMED) != 0) { 2599 sc->state &= ~PSM_SOFTARMED; 2600 callout_stop(&sc->softcallout); 2601 } 2602 psmsoftintr(arg); 2603 } else if ((sc->state & PSM_SOFTARMED) == 0) { 2604 sc->state |= PSM_SOFTARMED; 2605 callout_reset(&sc->softcallout, psmhz < 1 ? 1 : (hz/psmhz), 2606 psmsoftintr, arg); 2607 } 2608 } 2609 } 2610 2611 static void 2612 proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 2613 int *x, int *y, int *z) 2614 { 2615 2616 /* 2617 * PS2++ protocl packet 2618 * 2619 * b7 b6 b5 b4 b3 b2 b1 b0 2620 * byte 1: * 1 p3 p2 1 * * * 2621 * byte 2: c1 c2 p1 p0 d1 d0 1 0 2622 * 2623 * p3-p0: packet type 2624 * c1, c2: c1 & c2 == 1, if p2 == 0 2625 * c1 & c2 == 0, if p2 == 1 2626 * 2627 * packet type: 0 (device type) 2628 * See comments in enable_mmanplus() below. 2629 * 2630 * packet type: 1 (wheel data) 2631 * 2632 * b7 b6 b5 b4 b3 b2 b1 b0 2633 * byte 3: h * B5 B4 s d2 d1 d0 2634 * 2635 * h: 1, if horizontal roller data 2636 * 0, if vertical roller data 2637 * B4, B5: button 4 and 5 2638 * s: sign bit 2639 * d2-d0: roller data 2640 * 2641 * packet type: 2 (reserved) 2642 */ 2643 if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) && 2644 (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) { 2645 /* 2646 * the extended data packet encodes button 2647 * and wheel events 2648 */ 2649 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) { 2650 case 1: 2651 /* wheel data packet */ 2652 *x = *y = 0; 2653 if (pb->ipacket[2] & 0x80) { 2654 /* XXX horizontal roller count - ignore it */ 2655 ; 2656 } else { 2657 /* vertical roller count */ 2658 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ? 2659 (pb->ipacket[2] & 0x0f) - 16 : 2660 (pb->ipacket[2] & 0x0f); 2661 } 2662 ms->button |= (pb->ipacket[2] & 2663 MOUSE_PS2PLUS_BUTTON4DOWN) ? 2664 MOUSE_BUTTON4DOWN : 0; 2665 ms->button |= (pb->ipacket[2] & 2666 MOUSE_PS2PLUS_BUTTON5DOWN) ? 2667 MOUSE_BUTTON5DOWN : 0; 2668 break; 2669 case 2: 2670 /* 2671 * this packet type is reserved by 2672 * Logitech... 2673 */ 2674 /* 2675 * IBM ScrollPoint Mouse uses this 2676 * packet type to encode both vertical 2677 * and horizontal scroll movement. 2678 */ 2679 *x = *y = 0; 2680 /* horizontal count */ 2681 if (pb->ipacket[2] & 0x0f) 2682 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ? 2683 -2 : 2; 2684 /* vertical count */ 2685 if (pb->ipacket[2] & 0xf0) 2686 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ? 2687 -1 : 1; 2688 break; 2689 case 0: 2690 /* device type packet - shouldn't happen 2691 * 2692 * XXX: if this shouldn't happen, shouldn't we at least 2693 * add a kprintf indiciating to the user something bad 2694 * happened or is it that prevalent that it'd spam? -htse 2695 * 2696 * */ 2697 /* FALLTHROUGH */ 2698 default: 2699 *x = *y = 0; 2700 ms->button = ms->obutton; 2701 VLOG(1, (LOG_DEBUG, "psmintr: unknown PS2++ packet " 2702 "type %d: 0x%02x 0x%02x 0x%02x\n", 2703 MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket), 2704 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2])); 2705 break; 2706 } 2707 } else { 2708 /* preserve button states */ 2709 ms->button |= ms->obutton & MOUSE_EXTBUTTONS; 2710 } 2711 } 2712 2713 static int 2714 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 2715 int *x, int *y, int *z) 2716 { 2717 static int touchpad_buttons; 2718 static int guest_buttons; 2719 static finger_t f[PSM_FINGERS]; 2720 int w, id, nfingers, ewcode, extended_buttons; 2721 2722 extended_buttons = 0; 2723 2724 /* TouchPad PS/2 absolute mode message format with capFourButtons: 2725 * 2726 * Bits: 7 6 5 4 3 2 1 0 (LSB) 2727 * ------------------------------------------------ 2728 * ipacket[0]: 1 0 W3 W2 0 W1 R L 2729 * ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8 2730 * ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 2731 * ipacket[3]: 1 1 Yc Xc 0 W0 D U 2732 * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 2733 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 2734 * 2735 * Legend: 2736 * L: left physical mouse button 2737 * R: right physical mouse button 2738 * D: down button 2739 * U: up button 2740 * W: "wrist" value 2741 * X: x position 2742 * Y: y position 2743 * Z: pressure 2744 * 2745 * 2746 * Without capFourButtons but with nExtendeButtons and/or capMiddle 2747 * 2748 * Bits: 7 6 5 4 3 2 1 0 (LSB) 2749 * ------------------------------------------------------ 2750 * ipacket[3]: 1 1 Yc Xc 0 W0 E^R M^L 2751 * ipacket[4]: X7 X6 X5 X4 X3|b7 X2|b5 X1|b3 X0|b1 2752 * ipacket[5]: Y7 Y6 Y5 Y4 Y3|b8 Y2|b6 Y1|b4 Y0|b2 2753 * 2754 * Legend: 2755 * M: Middle physical mouse button 2756 * E: Extended mouse buttons reported instead of low bits of X and Y 2757 * b1-b8: Extended mouse buttons 2758 * Only ((nExtendedButtons + 1) >> 1) bits are used in packet 2759 * 4 and 5, for reading X and Y value they should be zeroed. 2760 * 2761 * Absolute reportable limits: 0 - 6143. 2762 * Typical bezel limits: 1472 - 5472. 2763 * Typical edge marings: 1632 - 5312. 2764 * 2765 * w = 3 Passthrough Packet 2766 * 2767 * Byte 2,5,6 == Byte 1,2,3 of "Guest" 2768 */ 2769 2770 if (!synaptics_support) 2771 return (0); 2772 2773 /* Sanity check for out of sync packets. */ 2774 if ((pb->ipacket[0] & 0xc8) != 0x80 || 2775 (pb->ipacket[3] & 0xc8) != 0xc0) 2776 return (-1); 2777 2778 *x = *y = 0; 2779 ms->button = ms->obutton; 2780 2781 /* 2782 * Pressure value. 2783 * Interpretation: 2784 * z = 0 No finger contact 2785 * z = 10 Finger hovering near the pad 2786 * z = 30 Very light finger contact 2787 * z = 80 Normal finger contact 2788 * z = 110 Very heavy finger contact 2789 * z = 200 Finger lying flat on pad surface 2790 * z = 255 Maximum reportable Z 2791 */ 2792 *z = pb->ipacket[2]; 2793 2794 /* 2795 * Finger width value 2796 * Interpretation: 2797 * w = 0 Two finger on the pad (capMultiFinger needed) 2798 * w = 1 Three or more fingers (capMultiFinger needed) 2799 * w = 2 Pen (instead of finger) (capPen needed) 2800 * w = 3 Reserved (passthrough?) 2801 * w = 4-7 Finger of normal width (capPalmDetect needed) 2802 * w = 8-14 Very wide finger or palm (capPalmDetect needed) 2803 * w = 15 Maximum reportable width (capPalmDetect needed) 2804 */ 2805 /* XXX Is checking capExtended enough? */ 2806 if (sc->synhw.capExtended) { 2807 w = ((pb->ipacket[0] & 0x30) >> 2) | 2808 ((pb->ipacket[0] & 0x04) >> 1) | 2809 ((pb->ipacket[3] & 0x04) >> 2); 2810 } 2811 else { 2812 /* Assume a finger of regular width. */ 2813 w = 4; 2814 } 2815 2816 switch (w) { 2817 case 3: 2818 /* 2819 * Handle packets from the guest device. See: 2820 * Synaptics PS/2 TouchPad Interfacing Guide, Section 5.1 2821 */ 2822 if (sc->synhw.capPassthrough) { 2823 *x = ((pb->ipacket[1] & 0x10) ? 2824 pb->ipacket[4] - 256 : pb->ipacket[4]); 2825 *y = ((pb->ipacket[1] & 0x20) ? 2826 pb->ipacket[5] - 256 : pb->ipacket[5]); 2827 *z = 0; 2828 2829 guest_buttons = 0; 2830 if (pb->ipacket[1] & 0x01) 2831 guest_buttons |= MOUSE_BUTTON1DOWN; 2832 if (pb->ipacket[1] & 0x04) 2833 guest_buttons |= MOUSE_BUTTON2DOWN; 2834 if (pb->ipacket[1] & 0x02) 2835 guest_buttons |= MOUSE_BUTTON3DOWN; 2836 2837 ms->button = touchpad_buttons | guest_buttons | 2838 sc->extended_buttons; 2839 } 2840 goto SYNAPTICS_END; 2841 2842 case 2: 2843 /* Handle Extended W mode packets */ 2844 ewcode = (pb->ipacket[5] & 0xf0) >> 4; 2845 #if PSM_FINGERS > 1 2846 switch (ewcode) { 2847 case 1: 2848 /* Secondary finger */ 2849 if (sc->synhw.capAdvancedGestures) 2850 f[1] = (finger_t) { 2851 .x = (((pb->ipacket[4] & 0x0f) << 8) | 2852 pb->ipacket[1]) << 1, 2853 .y = (((pb->ipacket[4] & 0xf0) << 4) | 2854 pb->ipacket[2]) << 1, 2855 .p = ((pb->ipacket[3] & 0x30) | 2856 (pb->ipacket[5] & 0x0f)) << 1, 2857 .w = PSM_FINGER_DEFAULT_W, 2858 .flags = PSM_FINGER_FUZZY, 2859 }; 2860 else if (sc->synhw.capReportsV) 2861 f[1] = (finger_t) { 2862 .x = (((pb->ipacket[4] & 0x0f) << 8) | 2863 (pb->ipacket[1] & 0xfe)) << 1, 2864 .y = (((pb->ipacket[4] & 0xf0) << 4) | 2865 (pb->ipacket[2] & 0xfe)) << 1, 2866 .p = ((pb->ipacket[3] & 0x30) | 2867 (pb->ipacket[5] & 0x0e)) << 1, 2868 .w = (((pb->ipacket[5] & 0x01) << 2) | 2869 ((pb->ipacket[2] & 0x01) << 1) | 2870 (pb->ipacket[1] & 0x01)) + 8, 2871 .flags = PSM_FINGER_FUZZY, 2872 }; 2873 default: 2874 break; 2875 } 2876 #endif 2877 goto SYNAPTICS_END; 2878 2879 case 1: 2880 case 0: 2881 nfingers = w + 2; 2882 break; 2883 2884 default: 2885 nfingers = 1; 2886 } 2887 2888 if (sc->syninfo.touchpad_off) 2889 goto SYNAPTICS_END; 2890 2891 /* Button presses */ 2892 touchpad_buttons = 0; 2893 if (pb->ipacket[0] & 0x01) 2894 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2895 if (pb->ipacket[0] & 0x02) 2896 touchpad_buttons |= MOUSE_BUTTON3DOWN; 2897 2898 if (sc->synhw.capExtended && sc->synhw.capFourButtons) { 2899 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01) 2900 touchpad_buttons |= MOUSE_BUTTON4DOWN; 2901 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02) 2902 touchpad_buttons |= MOUSE_BUTTON5DOWN; 2903 } else if (sc->synhw.capExtended && sc->synhw.capMiddle && 2904 !sc->synhw.capClickPad) { 2905 /* Middle Button */ 2906 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01) 2907 touchpad_buttons |= MOUSE_BUTTON2DOWN; 2908 } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) { 2909 /* Extended Buttons */ 2910 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) { 2911 if (sc->syninfo.directional_scrolls) { 2912 if (pb->ipacket[4] & 0x01) 2913 extended_buttons |= MOUSE_BUTTON4DOWN; 2914 if (pb->ipacket[5] & 0x01) 2915 extended_buttons |= MOUSE_BUTTON5DOWN; 2916 if (pb->ipacket[4] & 0x02) 2917 extended_buttons |= MOUSE_BUTTON6DOWN; 2918 if (pb->ipacket[5] & 0x02) 2919 extended_buttons |= MOUSE_BUTTON7DOWN; 2920 } else { 2921 if (pb->ipacket[4] & 0x01) 2922 extended_buttons |= MOUSE_BUTTON1DOWN; 2923 if (pb->ipacket[5] & 0x01) 2924 extended_buttons |= MOUSE_BUTTON3DOWN; 2925 if (pb->ipacket[4] & 0x02) 2926 extended_buttons |= MOUSE_BUTTON2DOWN; 2927 sc->extended_buttons = extended_buttons; 2928 } 2929 2930 /* 2931 * Zero out bits used by extended buttons to avoid 2932 * misinterpretation of the data absolute position. 2933 * 2934 * The bits represented by 2935 * 2936 * (nExtendedButtons + 1) >> 1 2937 * 2938 * will be masked out in both bytes. 2939 * The mask for n bits is computed with the formula 2940 * 2941 * (1 << n) - 1 2942 */ 2943 int maskedbits = 0; 2944 int mask = 0; 2945 maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; 2946 mask = (1 << maskedbits) - 1; 2947 pb->ipacket[4] &= ~(mask); 2948 pb->ipacket[5] &= ~(mask); 2949 } else if (!sc->syninfo.directional_scrolls && 2950 !sc->gesture.in_vscroll) { 2951 /* 2952 * Keep reporting MOUSE DOWN until we get a new packet 2953 * indicating otherwise. 2954 */ 2955 extended_buttons |= sc->extended_buttons; 2956 } 2957 } 2958 /* Handle ClickPad */ 2959 if (sc->synhw.capClickPad && 2960 ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) 2961 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2962 2963 if (sc->synhw.capReportsV && nfingers > 1) 2964 f[0] = (finger_t) { 2965 .x = ((pb->ipacket[3] & 0x10) << 8) | 2966 ((pb->ipacket[1] & 0x0f) << 8) | 2967 (pb->ipacket[4] & 0xfd), 2968 .y = ((pb->ipacket[3] & 0x20) << 7) | 2969 ((pb->ipacket[1] & 0xf0) << 4) | 2970 (pb->ipacket[5] & 0xfd), 2971 .p = *z & 0xfe, 2972 .w = (((pb->ipacket[2] & 0x01) << 2) | 2973 (pb->ipacket[5] & 0x02) | 2974 ((pb->ipacket[4] & 0x02) >> 1)) + 8, 2975 .flags = PSM_FINGER_FUZZY, 2976 }; 2977 else 2978 f[0] = (finger_t) { 2979 .x = ((pb->ipacket[3] & 0x10) << 8) | 2980 ((pb->ipacket[1] & 0x0f) << 8) | 2981 pb->ipacket[4], 2982 .y = ((pb->ipacket[3] & 0x20) << 7) | 2983 ((pb->ipacket[1] & 0xf0) << 4) | 2984 pb->ipacket[5], 2985 .p = *z, 2986 .w = w, 2987 .flags = nfingers > 1 ? PSM_FINGER_FUZZY : 0, 2988 }; 2989 2990 /* Ignore hovering and unmeasurable touches */ 2991 if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2) 2992 nfingers = 0; 2993 2994 for (id = 0; id < PSM_FINGERS; id++) 2995 if (id >= nfingers) 2996 PSM_FINGER_RESET(f[id]); 2997 2998 ms->button = touchpad_buttons; 2999 3000 /* Palm detection doesn't terminate the current action. */ 3001 if (!psmpalmdetect(sc, &f[0], nfingers)) { 3002 psmgestures(sc, &f[0], nfingers, ms); 3003 for (id = 0; id < PSM_FINGERS; id++) 3004 psmsmoother(sc, &f[id], id, ms, x, y); 3005 } else { 3006 VLOG(2, (LOG_DEBUG, "synaptics: palm detected! (%d)\n", f[0].w)); 3007 } 3008 3009 ms->button |= extended_buttons | guest_buttons; 3010 3011 3012 3013 SYNAPTICS_END: 3014 /* 3015 * Use the extra buttons as a scrollwheel 3016 * 3017 * XXX X.Org uses the Z axis for vertical wheel only, 3018 * whereas moused(8) understands special values to differ 3019 * vertical and horizontal wheels. 3020 * 3021 * xf86-input-mouse needs therefore a small patch to 3022 * understand these special values. Without it, the 3023 * horizontal wheel acts as a vertical wheel in X.Org. 3024 * 3025 * That's why the horizontal wheel is disabled by 3026 * default for now. 3027 */ 3028 if (ms->button & MOUSE_BUTTON4DOWN) { 3029 *z = -1; 3030 } else if (ms->button & MOUSE_BUTTON5DOWN) { 3031 *z = 1; 3032 } else if (ms->button & MOUSE_BUTTON6DOWN) { 3033 *z = -2; 3034 } else if (ms->button & MOUSE_BUTTON7DOWN) { 3035 *z = 2; 3036 } else 3037 *z = 0; 3038 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN | 3039 MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN); 3040 3041 return (0); 3042 } 3043 3044 static int 3045 psmpalmdetect(struct psm_softc *sc, finger_t *f, int nfingers) 3046 { 3047 if (!( 3048 ((sc->synhw.capMultiFinger || 3049 sc->synhw.capAdvancedGestures) && nfingers > 1) || 3050 (sc->synhw.capPalmDetect && f->w <= sc->syninfo.max_width) || 3051 (!sc->synhw.capPalmDetect && f->p <= sc->syninfo.max_pressure) || 3052 (sc->synhw.capPen && f->flags & PSM_FINGER_IS_PEN))) { 3053 /* 3054 * We consider the packet irrelevant for the current 3055 * action when: 3056 * - the width isn't comprised in: 3057 * [1; max_width] 3058 * - the pressure isn't comprised in: 3059 * [min_pressure; max_pressure] 3060 * - pen aren't supported but PSM_FINGER_IS_PEN is set 3061 */ 3062 return (1); 3063 } 3064 return (0); 3065 } 3066 3067 static void 3068 psmgestures(struct psm_softc *sc, finger_t *fingers, int nfingers, 3069 mousestatus_t *ms) 3070 { 3071 smoother_t *smoother; 3072 gesture_t *gest; 3073 finger_t *f; 3074 int y_ok, center_button, center_x, right_button, right_x, i; 3075 3076 f = &fingers[0]; 3077 smoother = &sc->smoother[0]; 3078 gest = &sc->gesture; 3079 3080 /* Find first active finger. */ 3081 if (nfingers > 0) { 3082 for (i = 0; i < PSM_FINGERS; i++) { 3083 if (PSM_FINGER_IS_SET(fingers[i])) { 3084 f = &fingers[i]; 3085 smoother = &sc->smoother[i]; 3086 break; 3087 } 3088 } 3089 } 3090 3091 /* 3092 * Check pressure to detect a real wanted action on the 3093 * touchpad. 3094 */ 3095 if (f->p >= sc->syninfo.min_pressure) { 3096 int x0, y0; 3097 int dxp, dyp; 3098 int start_x, start_y; 3099 int queue_len; 3100 int margin_top, margin_right, margin_bottom, margin_left; 3101 int window_min, window_max; 3102 int vscroll_hor_area, vscroll_ver_area; 3103 int two_finger_scroll; 3104 int max_x, max_y; 3105 3106 /* silence gcc warnings for last VLOG call */ 3107 dxp = dyp = 0; 3108 3109 /* Read sysctl. */ 3110 /* XXX Verify values? */ 3111 margin_top = sc->syninfo.margin_top; 3112 margin_right = sc->syninfo.margin_right; 3113 margin_bottom = sc->syninfo.margin_bottom; 3114 margin_left = sc->syninfo.margin_left; 3115 window_min = sc->syninfo.window_min; 3116 window_max = sc->syninfo.window_max; 3117 vscroll_hor_area = sc->syninfo.vscroll_hor_area; 3118 vscroll_ver_area = sc->syninfo.vscroll_ver_area; 3119 two_finger_scroll = sc->syninfo.two_finger_scroll; 3120 max_x = sc->syninfo.max_x; 3121 max_y = sc->syninfo.max_y; 3122 3123 /* Read current absolute position. */ 3124 x0 = f->x; 3125 y0 = f->y; 3126 3127 /* 3128 * Limit the coordinates to the specified margins because 3129 * this area isn't very reliable. 3130 */ 3131 if (x0 <= margin_left) 3132 x0 = margin_left; 3133 else if (x0 >= max_x - margin_right) 3134 x0 = max_x - margin_right; 3135 if (y0 <= margin_bottom) 3136 y0 = margin_bottom; 3137 else if (y0 >= max_y - margin_top) 3138 y0 = max_y - margin_top; 3139 3140 VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", 3141 x0, y0, f->p, f->w)); 3142 3143 /* 3144 * If the action is just beginning, init the structure and 3145 * compute tap timeout. 3146 */ 3147 if (!(sc->flags & PSM_FLAGS_FINGERDOWN)) { 3148 VLOG(3, (LOG_DEBUG, "synaptics: ----\n")); 3149 3150 /* Initialize queue. */ 3151 gest->window_min = window_min; 3152 3153 /* Reset pressure peak. */ 3154 gest->zmax = 0; 3155 3156 /* Reset fingers count. */ 3157 gest->fingers_nb = 0; 3158 3159 /* Reset virtual scrolling state. */ 3160 gest->in_vscroll = 0; 3161 3162 /* Compute tap timeout. */ 3163 gest->taptimeout.tv_sec = tap_timeout / 1000000; 3164 gest->taptimeout.tv_usec = tap_timeout % 1000000; 3165 timevaladd(&gest->taptimeout, &sc->lastsoftintr); 3166 3167 sc->flags |= PSM_FLAGS_FINGERDOWN; 3168 3169 /* Smoother has not been reset yet */ 3170 queue_len = 1; 3171 start_x = x0; 3172 start_y = y0; 3173 } else { 3174 queue_len = smoother->queue_len + 1; 3175 start_x = smoother->start_x; 3176 start_y = smoother->start_y; 3177 } 3178 3179 /* Process ClickPad softbuttons */ 3180 if (sc->synhw.capClickPad && ms->button & MOUSE_BUTTON1DOWN) { 3181 y_ok = sc->syninfo.softbuttons_y >= 0 ? 3182 start_y < sc->syninfo.softbuttons_y : 3183 start_y > max_y - sc->syninfo.softbuttons_y; 3184 3185 center_button = MOUSE_BUTTON2DOWN; 3186 center_x = sc->syninfo.softbutton2_x; 3187 right_button = MOUSE_BUTTON3DOWN; 3188 right_x = sc->syninfo.softbutton3_x; 3189 3190 if (center_x > 0 && right_x > 0 && center_x > right_x) { 3191 center_button = MOUSE_BUTTON3DOWN; 3192 center_x = sc->syninfo.softbutton3_x; 3193 right_button = MOUSE_BUTTON2DOWN; 3194 right_x = sc->syninfo.softbutton2_x; 3195 } 3196 3197 if (right_x > 0 && start_x > right_x && y_ok) 3198 ms->button = (ms->button & 3199 ~MOUSE_BUTTON1DOWN) | right_button; 3200 else if (center_x > 0 && start_x > center_x && y_ok) 3201 ms->button = (ms->button & 3202 ~MOUSE_BUTTON1DOWN) | center_button; 3203 } 3204 3205 /* If in tap-hold, add the recorded button. */ 3206 if (gest->in_taphold) 3207 ms->button |= gest->tap_button; 3208 3209 /* 3210 * For tap, we keep the maximum number of fingers and the 3211 * pressure peak. Also with multiple fingers, we increase 3212 * the minimum window. 3213 */ 3214 if (nfingers > 1) 3215 gest->window_min = window_max; 3216 gest->fingers_nb = imax(nfingers, gest->fingers_nb); 3217 gest->zmax = imax(f->p, gest->zmax); 3218 3219 /* Do we have enough packets to consider this a gesture? */ 3220 if (queue_len < gest->window_min) 3221 return; 3222 3223 /* Is a scrolling action occurring? */ 3224 if (!gest->in_taphold && !ms->button && 3225 (!gest->in_vscroll || two_finger_scroll)) { 3226 /* 3227 * A scrolling action must not conflict with a tap 3228 * action. Here are the conditions to consider a 3229 * scrolling action: 3230 * - the action in a configurable area 3231 * - one of the following: 3232 * . the distance between the last packet and the 3233 * first should be above a configurable minimum 3234 * . tap timed out 3235 */ 3236 dxp = abs(x0 - start_x); 3237 dyp = abs(y0 - start_y); 3238 3239 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, >) || 3240 dxp >= sc->syninfo.vscroll_min_delta || 3241 dyp >= sc->syninfo.vscroll_min_delta) { 3242 /* 3243 * Handle two finger scrolling. 3244 * Note that we don't rely on fingers_nb 3245 * as that keeps the maximum number of fingers. 3246 */ 3247 if (two_finger_scroll) { 3248 if (nfingers == 2) { 3249 gest->in_vscroll += 3250 dyp ? 2 : 0; 3251 gest->in_vscroll += 3252 dxp ? 1 : 0; 3253 } 3254 } else { 3255 /* Check for horizontal scrolling. */ 3256 if ((vscroll_hor_area > 0 && 3257 start_y <= vscroll_hor_area) || 3258 (vscroll_hor_area < 0 && 3259 start_y >= 3260 max_y + vscroll_hor_area)) 3261 gest->in_vscroll += 2; 3262 3263 /* Check for vertical scrolling. */ 3264 if ((vscroll_ver_area > 0 && 3265 start_x <= vscroll_ver_area) || 3266 (vscroll_ver_area < 0 && 3267 start_x >= 3268 max_x + vscroll_ver_area)) 3269 gest->in_vscroll += 1; 3270 } 3271 3272 /* Avoid conflicts if area overlaps. */ 3273 if (gest->in_vscroll >= 3) 3274 gest->in_vscroll = 3275 (dxp > dyp) ? 2 : 1; 3276 } 3277 } 3278 /* 3279 * Reset two finger scrolling when the number of fingers 3280 * is different from two or any button is pressed. 3281 */ 3282 if (two_finger_scroll && gest->in_vscroll != 0 && 3283 (nfingers != 2 || ms->button)) 3284 gest->in_vscroll = 0; 3285 3286 VLOG(5, (LOG_DEBUG, 3287 "synaptics: virtual scrolling: %s " 3288 "(direction=%d, dxp=%d, dyp=%d, fingers=%d)\n", 3289 gest->in_vscroll ? "YES" : "NO", 3290 gest->in_vscroll, dxp, dyp, 3291 gest->fingers_nb)); 3292 3293 } else if (sc->flags & PSM_FLAGS_FINGERDOWN) { 3294 /* 3295 * An action is currently taking place but the pressure 3296 * dropped under the minimum, putting an end to it. 3297 */ 3298 int taphold_timeout, dx, dy, tap_max_delta; 3299 3300 dx = abs(smoother->queue[smoother->queue_cursor].x - 3301 smoother->start_x); 3302 dy = abs(smoother->queue[smoother->queue_cursor].y - 3303 smoother->start_y); 3304 3305 /* Max delta is disabled for multi-fingers tap. */ 3306 if (gest->fingers_nb > 1) 3307 tap_max_delta = imax(dx, dy); 3308 else 3309 tap_max_delta = sc->syninfo.tap_max_delta; 3310 3311 sc->flags &= ~PSM_FLAGS_FINGERDOWN; 3312 3313 /* Check for tap. */ 3314 VLOG(3, (LOG_DEBUG, 3315 "synaptics: zmax=%d, dx=%d, dy=%d, " 3316 "delta=%d, fingers=%d, queue=%d\n", 3317 gest->zmax, dx, dy, tap_max_delta, gest->fingers_nb, 3318 smoother->queue_len)); 3319 if (!gest->in_vscroll && gest->zmax >= tap_threshold && 3320 timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=) && 3321 dx <= tap_max_delta && dy <= tap_max_delta && 3322 smoother->queue_len >= sc->syninfo.tap_min_queue) { 3323 /* 3324 * We have a tap if: 3325 * - the maximum pressure went over tap_threshold 3326 * - the action ended before tap_timeout 3327 * 3328 * To handle tap-hold, we must delay any button push to 3329 * the next action. 3330 */ 3331 if (gest->in_taphold) { 3332 /* 3333 * This is the second and last tap of a 3334 * double tap action, not a tap-hold. 3335 */ 3336 gest->in_taphold = 0; 3337 3338 /* 3339 * For double-tap to work: 3340 * - no button press is emitted (to 3341 * simulate a button release) 3342 * - PSM_FLAGS_FINGERDOWN is set to 3343 * force the next packet to emit a 3344 * button press) 3345 */ 3346 VLOG(2, (LOG_DEBUG, 3347 "synaptics: button RELEASE: %d\n", 3348 gest->tap_button)); 3349 sc->flags |= PSM_FLAGS_FINGERDOWN; 3350 3351 /* Schedule button press on next interrupt */ 3352 sc->idletimeout.tv_sec = psmhz > 1 ? 3353 0 : 1; 3354 sc->idletimeout.tv_usec = psmhz > 1 ? 3355 1000000 / psmhz : 0; 3356 } else { 3357 /* 3358 * This is the first tap: we set the 3359 * tap-hold state and notify the button 3360 * down event. 3361 */ 3362 gest->in_taphold = 1; 3363 taphold_timeout = sc->syninfo.taphold_timeout; 3364 gest->taptimeout.tv_sec = taphold_timeout / 3365 1000000; 3366 gest->taptimeout.tv_usec = taphold_timeout % 3367 1000000; 3368 sc->idletimeout = gest->taptimeout; 3369 timevaladd(&gest->taptimeout, 3370 &sc->lastsoftintr); 3371 3372 switch (gest->fingers_nb) { 3373 case 3: 3374 gest->tap_button = 3375 MOUSE_BUTTON2DOWN; 3376 break; 3377 case 2: 3378 gest->tap_button = 3379 MOUSE_BUTTON3DOWN; 3380 break; 3381 default: 3382 gest->tap_button = 3383 MOUSE_BUTTON1DOWN; 3384 } 3385 VLOG(2, (LOG_DEBUG, 3386 "synaptics: button PRESS: %d\n", 3387 gest->tap_button)); 3388 ms->button |= gest->tap_button; 3389 } 3390 } else { 3391 /* 3392 * Not enough pressure or timeout: reset 3393 * tap-hold state. 3394 */ 3395 if (gest->in_taphold) { 3396 VLOG(2, (LOG_DEBUG, 3397 "synaptics: button RELEASE: %d\n", 3398 gest->tap_button)); 3399 gest->in_taphold = 0; 3400 } else { 3401 VLOG(2, (LOG_DEBUG, 3402 "synaptics: not a tap-hold\n")); 3403 } 3404 } 3405 } else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && gest->in_taphold) { 3406 /* 3407 * For a tap-hold to work, the button must remain down at 3408 * least until timeout (where the in_taphold flags will be 3409 * cleared) or during the next action. 3410 */ 3411 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=)) { 3412 ms->button |= gest->tap_button; 3413 } else { 3414 VLOG(2, (LOG_DEBUG, "synaptics: button RELEASE: %d\n", 3415 gest->tap_button)); 3416 gest->in_taphold = 0; 3417 } 3418 } 3419 3420 return; 3421 } 3422 3423 static void 3424 psmsmoother(struct psm_softc *sc, finger_t *f, int smoother_id, 3425 mousestatus_t *ms, int *x, int *y) 3426 { 3427 smoother_t *smoother = &sc->smoother[smoother_id]; 3428 gesture_t *gest = &(sc->gesture); 3429 3430 /* 3431 * Check pressure to detect a real wanted action on the 3432 * touchpad. 3433 */ 3434 if (f->p >= sc->syninfo.min_pressure) { 3435 int x0, y0; 3436 int cursor, peer, window; 3437 int dx, dy, dxp, dyp; 3438 int max_width, max_pressure; 3439 int margin_top, margin_right, margin_bottom, margin_left; 3440 int na_top, na_right, na_bottom, na_left; 3441 int window_min, window_max; 3442 int multiplicator; 3443 int weight_current, weight_previous, weight_len_squared; 3444 int div_min, div_max, div_len; 3445 int vscroll_hor_area, vscroll_ver_area; 3446 int two_finger_scroll; 3447 int max_x, max_y; 3448 int len, weight_prev_x, weight_prev_y; 3449 int div_max_x, div_max_y, div_x, div_y; 3450 int is_fuzzy; 3451 3452 /* Read sysctl. */ 3453 /* XXX Verify values? */ 3454 max_width = sc->syninfo.max_width; 3455 max_pressure = sc->syninfo.max_pressure; 3456 margin_top = sc->syninfo.margin_top; 3457 margin_right = sc->syninfo.margin_right; 3458 margin_bottom = sc->syninfo.margin_bottom; 3459 margin_left = sc->syninfo.margin_left; 3460 na_top = sc->syninfo.na_top; 3461 na_right = sc->syninfo.na_right; 3462 na_bottom = sc->syninfo.na_bottom; 3463 na_left = sc->syninfo.na_left; 3464 window_min = sc->syninfo.window_min; 3465 window_max = sc->syninfo.window_max; 3466 multiplicator = sc->syninfo.multiplicator; 3467 weight_current = sc->syninfo.weight_current; 3468 weight_previous = sc->syninfo.weight_previous; 3469 weight_len_squared = sc->syninfo.weight_len_squared; 3470 div_min = sc->syninfo.div_min; 3471 div_max = sc->syninfo.div_max; 3472 div_len = sc->syninfo.div_len; 3473 vscroll_hor_area = sc->syninfo.vscroll_hor_area; 3474 vscroll_ver_area = sc->syninfo.vscroll_ver_area; 3475 two_finger_scroll = sc->syninfo.two_finger_scroll; 3476 max_x = sc->syninfo.max_x; 3477 max_y = sc->syninfo.max_y; 3478 3479 is_fuzzy = (f->flags & PSM_FINGER_FUZZY) != 0; 3480 3481 /* Read current absolute position. */ 3482 x0 = f->x; 3483 y0 = f->y; 3484 3485 /* 3486 * Limit the coordinates to the specified margins because 3487 * this area isn't very reliable. 3488 */ 3489 if (x0 <= margin_left) 3490 x0 = margin_left; 3491 else if (x0 >= max_x - margin_right) 3492 x0 = max_x - margin_right; 3493 if (y0 <= margin_bottom) 3494 y0 = margin_bottom; 3495 else if (y0 >= max_y - margin_top) 3496 y0 = max_y - margin_top; 3497 3498 /* If the action is just beginning, init the structure. */ 3499 if (smoother->active == 0) { 3500 VLOG(3, (LOG_DEBUG, "smoother%d: ---\n", smoother_id)); 3501 3502 /* Store the first point of this action. */ 3503 smoother->start_x = x0; 3504 smoother->start_y = y0; 3505 dx = dy = 0; 3506 3507 /* Initialize queue. */ 3508 smoother->queue_cursor = SYNAPTICS_PACKETQUEUE; 3509 smoother->queue_len = 0; 3510 3511 /* Reset average. */ 3512 smoother->avg_dx = 0; 3513 smoother->avg_dy = 0; 3514 3515 /* Reset squelch. */ 3516 smoother->squelch_x = 0; 3517 smoother->squelch_y = 0; 3518 3519 /* Activate queue */ 3520 smoother->active = 1; 3521 } else { 3522 /* Calculate the current delta. */ 3523 cursor = smoother->queue_cursor; 3524 dx = x0 - smoother->queue[cursor].x; 3525 dy = y0 - smoother->queue[cursor].y; 3526 } 3527 3528 VLOG(3, (LOG_DEBUG, "smoother%d: ipacket: [%d, %d], %d, %d\n", 3529 smoother_id, x0, y0, f->p, f->w)); 3530 3531 /* Queue this new packet. */ 3532 cursor = SYNAPTICS_QUEUE_CURSOR(smoother->queue_cursor - 1); 3533 smoother->queue[cursor].x = x0; 3534 smoother->queue[cursor].y = y0; 3535 smoother->queue_cursor = cursor; 3536 if (smoother->queue_len < SYNAPTICS_PACKETQUEUE) 3537 smoother->queue_len++; 3538 VLOG(5, (LOG_DEBUG, 3539 "smoother%d: cursor[%d]: x=%d, y=%d, dx=%d, dy=%d\n", 3540 smoother_id, cursor, x0, y0, dx, dy)); 3541 3542 /* Do we have enough packets to consider this a movement? */ 3543 if (smoother->queue_len < gest->window_min) 3544 return; 3545 3546 weight_prev_x = weight_prev_y = weight_previous; 3547 div_max_x = div_max_y = div_max; 3548 3549 if (gest->in_vscroll) { 3550 /* Dividers are different with virtual scrolling. */ 3551 div_min = sc->syninfo.vscroll_div_min; 3552 div_max_x = div_max_y = sc->syninfo.vscroll_div_max; 3553 } else { 3554 /* 3555 * There's a lot of noise in coordinates when 3556 * the finger is on the touchpad's borders. When 3557 * using this area, we apply a special weight and 3558 * div. 3559 */ 3560 if (x0 <= na_left || x0 >= max_x - na_right) { 3561 weight_prev_x = sc->syninfo.weight_previous_na; 3562 div_max_x = sc->syninfo.div_max_na; 3563 } 3564 3565 if (y0 <= na_bottom || y0 >= max_y - na_top) { 3566 weight_prev_y = sc->syninfo.weight_previous_na; 3567 div_max_y = sc->syninfo.div_max_na; 3568 } 3569 } 3570 3571 /* 3572 * Calculate weights for the average operands and 3573 * the divisor. Both depend on the distance between 3574 * the current packet and a previous one (based on the 3575 * window width). 3576 */ 3577 window = imin(smoother->queue_len, window_max); 3578 peer = SYNAPTICS_QUEUE_CURSOR(cursor + window - 1); 3579 dxp = abs(x0 - smoother->queue[peer].x) + 1; 3580 dyp = abs(y0 - smoother->queue[peer].y) + 1; 3581 len = (dxp * dxp) + (dyp * dyp); 3582 weight_prev_x = imin(weight_prev_x, 3583 weight_len_squared * weight_prev_x / len); 3584 weight_prev_y = imin(weight_prev_y, 3585 weight_len_squared * weight_prev_y / len); 3586 3587 len = (dxp + dyp) / 2; 3588 div_x = div_len * div_max_x / len; 3589 div_x = imin(div_max_x, div_x); 3590 div_x = imax(div_min, div_x); 3591 div_y = div_len * div_max_y / len; 3592 div_y = imin(div_max_y, div_y); 3593 div_y = imax(div_min, div_y); 3594 3595 VLOG(3, (LOG_DEBUG, 3596 "smoother%d: peer=%d, len=%d, weight=%d/%d, div=%d/%d\n", 3597 smoother_id, peer, len, weight_prev_x, weight_prev_y, 3598 div_x, div_y)); 3599 3600 /* Compute averages. */ 3601 smoother->avg_dx = 3602 (weight_current * dx * multiplicator + 3603 weight_prev_x * smoother->avg_dx) / 3604 (weight_current + weight_prev_x); 3605 3606 smoother->avg_dy = 3607 (weight_current * dy * multiplicator + 3608 weight_prev_y * smoother->avg_dy) / 3609 (weight_current + weight_prev_y); 3610 3611 VLOG(5, (LOG_DEBUG, 3612 "smoother%d: avg_dx~=%d, avg_dy~=%d\n", smoother_id, 3613 smoother->avg_dx / multiplicator, 3614 smoother->avg_dy / multiplicator)); 3615 3616 /* Use these averages to calculate x & y. */ 3617 smoother->squelch_x += smoother->avg_dx; 3618 dxp = smoother->squelch_x / (div_x * multiplicator); 3619 smoother->squelch_x = smoother->squelch_x % 3620 (div_x * multiplicator); 3621 3622 smoother->squelch_y += smoother->avg_dy; 3623 dyp = smoother->squelch_y / (div_y * multiplicator); 3624 smoother->squelch_y = smoother->squelch_y % 3625 (div_y * multiplicator); 3626 3627 switch(gest->in_vscroll) { 3628 case 0: /* Pointer movement. */ 3629 /* On real<->fuzzy finger switch the x/y pos jumps */ 3630 if (is_fuzzy == smoother->is_fuzzy) { 3631 *x += dxp; 3632 *y += dyp; 3633 } 3634 3635 VLOG(3, (LOG_DEBUG, "smoother%d: [%d, %d] -> [%d, %d]\n", 3636 smoother_id, dx, dy, dxp, dyp)); 3637 break; 3638 case 1: /* Vertical scrolling. */ 3639 if (dyp != 0) 3640 ms->button |= (dyp > 0) ? 3641 MOUSE_BUTTON4DOWN : MOUSE_BUTTON5DOWN; 3642 break; 3643 case 2: /* Horizontal scrolling. */ 3644 if (dxp != 0) 3645 ms->button |= (dxp > 0) ? 3646 MOUSE_BUTTON7DOWN : MOUSE_BUTTON6DOWN; 3647 break; 3648 } 3649 3650 smoother->is_fuzzy = is_fuzzy; 3651 3652 } else { 3653 /* 3654 * Deactivate queue. Note: We can not just reset queue here 3655 * as these values are still used by gesture processor. 3656 * So postpone reset till next touch. 3657 */ 3658 smoother->active = 0; 3659 } 3660 } 3661 3662 static int 3663 proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 3664 int *x, int *y, int *z) 3665 { 3666 static int touchpad_button, trackpoint_button; 3667 finger_t fn, f[ELANTECH_MAX_FINGERS]; 3668 int pkt, id, scale, i, nfingers, mask; 3669 3670 if (!elantech_support) 3671 return (0); 3672 3673 /* Determine packet format and do a sanity check for out of sync packets. */ 3674 if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion)) 3675 pkt = ELANTECH_PKT_NOP; 3676 else if (ELANTECH_PKT_IS_TRACKPOINT(pb)) 3677 pkt = ELANTECH_PKT_TRACKPOINT; 3678 else 3679 switch (sc->elanhw.hwversion) { 3680 case 2: 3681 if (!ELANTECH_PKT_IS_V2(pb)) 3682 return (-1); 3683 3684 pkt = (pb->ipacket[0] & 0xc0) == 0x80 ? 3685 ELANTECH_PKT_V2_2FINGER : ELANTECH_PKT_V2_COMMON; 3686 break; 3687 case 3: 3688 if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) && 3689 !ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc)) 3690 return (-1); 3691 3692 pkt = ELANTECH_PKT_V3; 3693 break; 3694 case 4: 3695 if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc)) 3696 return (-1); 3697 3698 switch (pb->ipacket[3] & 0x03) { 3699 case 0x00: 3700 pkt = ELANTECH_PKT_V4_STATUS; 3701 break; 3702 case 0x01: 3703 pkt = ELANTECH_PKT_V4_HEAD; 3704 break; 3705 case 0x02: 3706 pkt = ELANTECH_PKT_V4_MOTION; 3707 break; 3708 default: 3709 return (-1); 3710 } 3711 break; 3712 default: 3713 return (-1); 3714 } 3715 3716 VLOG(5, (LOG_DEBUG, "elantech: ipacket format: %d\n", pkt)); 3717 3718 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) 3719 PSM_FINGER_RESET(f[id]); 3720 3721 *x = *y = *z = 0; 3722 ms->button = ms->obutton; 3723 3724 if (sc->syninfo.touchpad_off) 3725 return (0); 3726 3727 /* Common legend 3728 * L: Left mouse button pressed 3729 * R: Right mouse button pressed 3730 * N: number of fingers on touchpad 3731 * X: absolute x value (horizontal) 3732 * Y: absolute y value (vertical) 3733 * W; width of the finger touch 3734 * P: pressure 3735 */ 3736 switch (pkt) { 3737 case ELANTECH_PKT_V2_COMMON: /* HW V2. One/Three finger touch */ 3738 /* 7 6 5 4 3 2 1 0 (LSB) 3739 * ------------------------------------------- 3740 * ipacket[0]: N1 N0 W3 W2 . . R L 3741 * ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 3742 * ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 3743 * ipacket[3]: N4 VF W1 W0 . . . B2 3744 * ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 3745 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3746 * ------------------------------------------- 3747 * N4: set if more than 3 fingers (only in 3 fingers mode) 3748 * VF: a kind of flag? (only on EF123, 0 when finger 3749 * is over one of the buttons, 1 otherwise) 3750 * B2: (on EF113 only, 0 otherwise), one button pressed 3751 * P & W is not reported on EF113 touchpads 3752 */ 3753 nfingers = (pb->ipacket[0] & 0xc0) >> 6; 3754 if (nfingers == 3 && (pb->ipacket[3] & 0x80)) 3755 nfingers = 4; 3756 mask = (1 << nfingers) - 1; 3757 3758 fn = ELANTECH_FINGER_SET_XYP(pb); 3759 if (sc->elanhw.haspressure) { 3760 fn.w = ((pb->ipacket[0] & 0x30) >> 2) | 3761 ((pb->ipacket[3] & 0x30) >> 4); 3762 } else { 3763 fn.p = PSM_FINGER_DEFAULT_P; 3764 fn.w = PSM_FINGER_DEFAULT_W; 3765 } 3766 3767 /* 3768 * HW v2 dont report exact finger positions when 3 or more 3769 * fingers are on touchpad. Use reported value as fingers 3770 * position as it is required for tap detection 3771 */ 3772 if (nfingers > 2) 3773 fn.flags = PSM_FINGER_FUZZY; 3774 3775 for (id = 0; id < imin(nfingers, ELANTECH_MAX_FINGERS); id++) 3776 f[id] = fn; 3777 break; 3778 3779 case ELANTECH_PKT_V2_2FINGER: /*HW V2. Two finger touch */ 3780 /* 7 6 5 4 3 2 1 0 (LSB) 3781 * ------------------------------------------- 3782 * ipacket[0]: N1 N0 AY8 AX8 . . R L 3783 * ipacket[1]: AX7 AX6 AX5 AX4 AX3 AX2 AX1 AX0 3784 * ipacket[2]: AY7 AY6 AY5 AY4 AY3 AY2 AY1 AY0 3785 * ipacket[3]: . . BY8 BX8 . . . . 3786 * ipacket[4]: BX7 BX6 BX5 BX4 BX3 BX2 BX1 BX0 3787 * ipacket[5]: BY7 BY6 BY5 BY4 BY3 BY2 BY1 BY0 3788 * ------------------------------------------- 3789 * AX: lower-left finger absolute x value 3790 * AY: lower-left finger absolute y value 3791 * BX: upper-right finger absolute x value 3792 * BY: upper-right finger absolute y value 3793 */ 3794 nfingers = 2; 3795 mask = (1 << nfingers) - 1; 3796 3797 for (id = 0; id < imin(2, ELANTECH_MAX_FINGERS); id ++) 3798 f[id] = (finger_t) { 3799 .x = (((pb->ipacket[id * 3] & 0x10) << 4) | 3800 pb->ipacket[id * 3 + 1]) << 2, 3801 .y = (((pb->ipacket[id * 3] & 0x20) << 3) | 3802 pb->ipacket[id * 3 + 2]) << 2, 3803 .p = PSM_FINGER_DEFAULT_P, 3804 .w = PSM_FINGER_DEFAULT_W, 3805 /* HW ver.2 sends bounding box */ 3806 .flags = PSM_FINGER_FUZZY 3807 }; 3808 break; 3809 3810 case ELANTECH_PKT_V3: /* HW Version 3 */ 3811 /* 7 6 5 4 3 2 1 0 (LSB) 3812 * ------------------------------------------- 3813 * ipacket[0]: N1 N0 W3 W2 0 1 R L 3814 * ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 3815 * ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 3816 * ipacket[3]: 0 0 W1 W0 0 0 1 0 3817 * ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 3818 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3819 * ------------------------------------------- 3820 */ 3821 nfingers = (pb->ipacket[0] & 0xc0) >> 6; 3822 mask = (1 << nfingers) - 1; 3823 id = nfingers - 1; 3824 3825 fn = ELANTECH_FINGER_SET_XYP(pb); 3826 fn.w = ((pb->ipacket[0] & 0x30) >> 2) | 3827 ((pb->ipacket[3] & 0x30) >> 4); 3828 3829 /* 3830 * HW v3 dont report exact finger positions when 3 or more 3831 * fingers are on touchpad. Use reported value as fingers 3832 * position as it is required for tap detection 3833 */ 3834 if (nfingers > 1) 3835 fn.flags = PSM_FINGER_FUZZY; 3836 3837 for (id = 0; id < imin(nfingers, ELANTECH_MAX_FINGERS); id++) 3838 f[id] = fn; 3839 3840 if (nfingers == 2) { 3841 if (ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc)) { 3842 sc->elanaction.fingers[0] = fn; 3843 return (0); 3844 } else 3845 f[0] = sc->elanaction.fingers[0]; 3846 } 3847 break; 3848 3849 case ELANTECH_PKT_V4_STATUS: /* HW Version 4. Status packet */ 3850 /* 7 6 5 4 3 2 1 0 (LSB) 3851 * ------------------------------------------- 3852 * ipacket[0]: . . . . 0 1 R L 3853 * ipacket[1]: . . . F4 F3 F2 F1 F0 3854 * ipacket[2]: . . . . . . . . 3855 * ipacket[3]: . . . 1 0 0 0 0 3856 * ipacket[4]: PL . . . . . . . 3857 * ipacket[5]: . . . . . . . . 3858 * ------------------------------------------- 3859 * Fn: finger n is on touchpad 3860 * PL: palm 3861 * HV ver4 sends a status packet to indicate that the numbers 3862 * or identities of the fingers has been changed 3863 */ 3864 3865 mask = pb->ipacket[1] & 0x1f; 3866 nfingers = bitcount32(mask); 3867 3868 /* Skip "new finger is on touchpad" packets */ 3869 if ((sc->elanaction.mask & mask) == sc->elanaction.mask && 3870 (mask & ~sc->elanaction.mask)) { 3871 sc->elanaction.mask = mask; 3872 return (0); 3873 } 3874 3875 break; 3876 3877 case ELANTECH_PKT_V4_HEAD: /* HW Version 4. Head packet */ 3878 /* 7 6 5 4 3 2 1 0 (LSB) 3879 * ------------------------------------------- 3880 * ipacket[0]: W3 W2 W1 W0 0 1 R L 3881 * ipacket[1]: P7 P6 P5 P4 X11 X10 X9 X8 3882 * ipacket[2]: X7 X6 X5 X4 X3 X2 X1 X0 3883 * ipacket[3]: ID2 ID1 ID0 1 0 0 0 1 3884 * ipacket[4]: P3 P1 P2 P0 Y11 Y10 Y9 Y8 3885 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3886 * ------------------------------------------- 3887 * ID: finger id 3888 * HW ver 4 sends head packets in two cases: 3889 * 1. One finger touch and movement. 3890 * 2. Next after status packet to tell new finger positions. 3891 */ 3892 mask = sc->elanaction.mask; 3893 nfingers = bitcount32(mask); 3894 id = ((pb->ipacket[3] & 0xe0) >> 5) - 1; 3895 3896 if (id >= 0 && id < ELANTECH_MAX_FINGERS) { 3897 f[id] = ELANTECH_FINGER_SET_XYP(pb); 3898 f[id].w = (pb->ipacket[0] & 0xf0) >> 4; 3899 } 3900 break; 3901 3902 case ELANTECH_PKT_V4_MOTION: /* HW Version 4. Motion packet */ 3903 /* 7 6 5 4 3 2 1 0 (LSB) 3904 * ------------------------------------------- 3905 * ipacket[0]: ID2 ID1 ID0 OF 0 1 R L 3906 * ipacket[1]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 3907 * ipacket[2]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 3908 * ipacket[3]: ID2 ID1 ID0 1 0 0 1 0 3909 * ipacket[4]: DX7 DX6 DX5 DX4 DX3 DX2 DX1 DX0 3910 * ipacket[5]: DY7 DY6 DY5 DY4 DY3 DY2 DY1 DY0 3911 * ------------------------------------------- 3912 * OF: delta overflows (> 127 or < -128), in this case 3913 * firmware sends us (delta x / 5) and (delta y / 5) 3914 * ID: finger id 3915 * DX: delta x (two's complement) 3916 * XY: delta y (two's complement) 3917 * byte 0 ~ 2 for one finger 3918 * byte 3 ~ 5 for another finger 3919 */ 3920 mask = sc->elanaction.mask; 3921 nfingers = bitcount32(mask); 3922 3923 scale = (pb->ipacket[0] & 0x10) ? 5 : 1; 3924 for (i = 0; i <= 3; i += 3) { 3925 id = ((pb->ipacket[i] & 0xe0) >> 5) - 1; 3926 if (id < 0 || id >= ELANTECH_MAX_FINGERS) 3927 continue; 3928 3929 if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) { 3930 f[id] = sc->elanaction.fingers[id]; 3931 f[id].x += imax(-f[id].x, 3932 (signed char)pb->ipacket[i+1] * scale); 3933 f[id].y += imax(-f[id].y, 3934 (signed char)pb->ipacket[i+2] * scale); 3935 } else { 3936 VLOG(3, (LOG_DEBUG, "elantech: " 3937 "HW v4 motion packet skipped\n")); 3938 } 3939 } 3940 3941 break; 3942 3943 case ELANTECH_PKT_TRACKPOINT: 3944 /* 7 6 5 4 3 2 1 0 (LSB) 3945 * ------------------------------------------- 3946 * ipacket[0]: 0 0 SX SY 0 M R L 3947 * ipacket[1]: ~SX 0 0 0 0 0 0 0 3948 * ipacket[2]: ~SY 0 0 0 0 0 0 0 3949 * ipacket[3]: 0 0 ~SY ~SX 0 1 1 0 3950 * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 3951 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 3952 * ------------------------------------------- 3953 * X and Y are written in two's complement spread 3954 * over 9 bits with SX/SY the relative top bit and 3955 * X7..X0 and Y7..Y0 the lower bits. 3956 */ 3957 *x = (pb->ipacket[0] & 0x20) ? 3958 pb->ipacket[4] - 256 : pb->ipacket[4]; 3959 *y = (pb->ipacket[0] & 0x10) ? 3960 pb->ipacket[5] - 256 : pb->ipacket[5]; 3961 3962 trackpoint_button = 3963 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | 3964 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) | 3965 ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); 3966 3967 ms->button = touchpad_button | trackpoint_button; 3968 return (0); 3969 3970 case ELANTECH_PKT_NOP: 3971 return (0); 3972 3973 default: 3974 return (-1); 3975 } 3976 3977 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) 3978 if (PSM_FINGER_IS_SET(f[id])) 3979 VLOG(2, (LOG_DEBUG, "elantech: " 3980 "finger %d: down [%d, %d], %d, %d, %d\n", id + 1, 3981 f[id].x, f[id].y, f[id].p, f[id].w, f[id].flags)); 3982 3983 /* Touchpad button presses */ 3984 if (sc->elanhw.isclickpad) { 3985 touchpad_button = 3986 ((pb->ipacket[0] & 0x03) ? MOUSE_BUTTON1DOWN : 0); 3987 } else { 3988 touchpad_button = 3989 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | 3990 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); 3991 } 3992 3993 ms->button = touchpad_button | trackpoint_button; 3994 3995 /* Palm detection doesn't terminate the current action. */ 3996 if (!psmpalmdetect(sc, &f[0], nfingers)) { 3997 /* Send finger 1 position to gesture processor */ 3998 if (PSM_FINGER_IS_SET(f[0]) || PSM_FINGER_IS_SET(f[1]) || 3999 nfingers == 0) 4000 psmgestures(sc, &f[0], imin(nfingers, 3), ms); 4001 /* Send fingers positions to movement smoothers */ 4002 for (id = 0; id < PSM_FINGERS; id++) 4003 if (PSM_FINGER_IS_SET(f[id]) || !(mask & (1 << id))) 4004 psmsmoother(sc, &f[id], id, ms, x, y); 4005 } else { 4006 VLOG(2, (LOG_DEBUG, "elantech: palm detected! (%d)\n", 4007 f[0].w)); 4008 } 4009 4010 /* Store current finger positions in action context */ 4011 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) { 4012 if (PSM_FINGER_IS_SET(f[id])) 4013 sc->elanaction.fingers[id] = f[id]; 4014 if ((sc->elanaction.mask & (1 << id)) && !(mask & (1 << id))) 4015 PSM_FINGER_RESET(sc->elanaction.fingers[id]); 4016 } 4017 sc->elanaction.mask = mask; 4018 4019 /* Use the extra buttons as a scrollwheel */ 4020 if (ms->button & MOUSE_BUTTON4DOWN) 4021 *z = -1; 4022 else if (ms->button & MOUSE_BUTTON5DOWN) 4023 *z = 1; 4024 else if (ms->button & MOUSE_BUTTON6DOWN) 4025 *z = -2; 4026 else if (ms->button & MOUSE_BUTTON7DOWN) 4027 *z = 2; 4028 else 4029 *z = 0; 4030 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN | 4031 MOUSE_BUTTON6DOWN | MOUSE_BUTTON7DOWN); 4032 4033 return (0); 4034 } 4035 4036 static void 4037 proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 4038 int *x, int *y, int *z) 4039 { 4040 static int butmap_versapad[8] = { 4041 0, 4042 MOUSE_BUTTON3DOWN, 4043 0, 4044 MOUSE_BUTTON3DOWN, 4045 MOUSE_BUTTON1DOWN, 4046 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 4047 MOUSE_BUTTON1DOWN, 4048 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN 4049 }; 4050 int c, x0, y0; 4051 4052 /* VersaPad PS/2 absolute mode message format 4053 * 4054 * [packet1] 7 6 5 4 3 2 1 0(LSB) 4055 * ipacket[0]: 1 1 0 A 1 L T R 4056 * ipacket[1]: H7 H6 H5 H4 H3 H2 H1 H0 4057 * ipacket[2]: V7 V6 V5 V4 V3 V2 V1 V0 4058 * ipacket[3]: 1 1 1 A 1 L T R 4059 * ipacket[4]:V11 V10 V9 V8 H11 H10 H9 H8 4060 * ipacket[5]: 0 P6 P5 P4 P3 P2 P1 P0 4061 * 4062 * [note] 4063 * R: right physical mouse button (1=on) 4064 * T: touch pad virtual button (1=tapping) 4065 * L: left physical mouse button (1=on) 4066 * A: position data is valid (1=valid) 4067 * H: horizontal data (12bit signed integer. H11 is sign bit.) 4068 * V: vertical data (12bit signed integer. V11 is sign bit.) 4069 * P: pressure data 4070 * 4071 * Tapping is mapped to MOUSE_BUTTON4. 4072 */ 4073 c = pb->ipacket[0]; 4074 *x = *y = 0; 4075 ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS]; 4076 ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0; 4077 if (c & MOUSE_PS2VERSA_IN_USE) { 4078 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8); 4079 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4); 4080 if (x0 & 0x800) 4081 x0 -= 0x1000; 4082 if (y0 & 0x800) 4083 y0 -= 0x1000; 4084 if (sc->flags & PSM_FLAGS_FINGERDOWN) { 4085 *x = sc->xold - x0; 4086 *y = y0 - sc->yold; 4087 if (*x < 0) /* XXX */ 4088 ++*x; 4089 else if (*x) 4090 --*x; 4091 if (*y < 0) 4092 ++*y; 4093 else if (*y) 4094 --*y; 4095 } else 4096 sc->flags |= PSM_FLAGS_FINGERDOWN; 4097 sc->xold = x0; 4098 sc->yold = y0; 4099 } else 4100 sc->flags &= ~PSM_FLAGS_FINGERDOWN; 4101 } 4102 4103 static void 4104 psmsoftintridle(void *arg) 4105 { 4106 struct psm_softc *sc = arg; 4107 packetbuf_t *pb; 4108 4109 /* Invoke soft handler only when pqueue is empty. Otherwise it will be 4110 * invoked from psmintr soon with pqueue filled with real data */ 4111 if (sc->pqueue_start == sc->pqueue_end && 4112 sc->idlepacket.inputbytes > 0) { 4113 /* Grow circular queue backwards to avoid race with psmintr */ 4114 if (--sc->pqueue_start < 0) 4115 sc->pqueue_start = PSM_PACKETQUEUE - 1; 4116 4117 pb = &sc->pqueue[sc->pqueue_start]; 4118 memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t)); 4119 VLOG(4, (LOG_DEBUG, 4120 "psmsoftintridle: %02x %02x %02x %02x %02x %02x\n", 4121 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], 4122 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); 4123 4124 psmsoftintr(arg); 4125 } 4126 } 4127 4128 4129 static void 4130 psmsoftintr(void *arg) 4131 { 4132 /* 4133 * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN) 4134 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). 4135 */ 4136 static int butmap[8] = { 4137 0, 4138 MOUSE_BUTTON1DOWN, 4139 MOUSE_BUTTON3DOWN, 4140 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 4141 MOUSE_BUTTON2DOWN, 4142 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 4143 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 4144 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 4145 }; 4146 struct psm_softc *sc = arg; 4147 mousestatus_t ms; 4148 packetbuf_t *pb; 4149 int x, y, z, c, l; 4150 4151 getmicrouptime(&sc->lastsoftintr); 4152 4153 lockmgr(&sc->lock, LK_EXCLUSIVE); 4154 4155 do { 4156 pb = &sc->pqueue[sc->pqueue_start]; 4157 4158 c = pb->ipacket[0]; 4159 /* 4160 * A kludge for Kensington device! 4161 * The MSB of the horizontal count appears to be stored in 4162 * a strange place. 4163 */ 4164 if (sc->hw.model == MOUSE_MODEL_THINK) 4165 pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0; 4166 4167 /* ignore the overflow bits... */ 4168 x = (c & MOUSE_PS2_XNEG) ? 4169 pb->ipacket[1] - 256 : pb->ipacket[1]; 4170 y = (c & MOUSE_PS2_YNEG) ? 4171 pb->ipacket[2] - 256 : pb->ipacket[2]; 4172 z = 0; 4173 ms.obutton = sc->button; /* previous button state */ 4174 ms.button = butmap[c & MOUSE_PS2_BUTTONS]; 4175 /* `tapping' action */ 4176 if (sc->config & PSM_CONFIG_FORCETAP) 4177 ms.button |= ((c & MOUSE_PS2_TAP)) ? 4178 0 : MOUSE_BUTTON4DOWN; 4179 timevalclear(&sc->idletimeout); 4180 sc->idlepacket.inputbytes = 0; 4181 4182 switch (sc->hw.model) { 4183 4184 case MOUSE_MODEL_EXPLORER: 4185 /* 4186 * b7 b6 b5 b4 b3 b2 b1 b0 4187 * byte 1: oy ox sy sx 1 M R L 4188 * byte 2: x x x x x x x x 4189 * byte 3: y y y y y y y y 4190 * byte 4: * * S2 S1 s d2 d1 d0 4191 * 4192 * L, M, R, S1, S2: left, middle, right and side buttons 4193 * s: wheel data sign bit 4194 * d2-d0: wheel data 4195 */ 4196 z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ? 4197 (pb->ipacket[3] & 0x0f) - 16 : 4198 (pb->ipacket[3] & 0x0f); 4199 ms.button |= 4200 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ? 4201 MOUSE_BUTTON4DOWN : 0; 4202 ms.button |= 4203 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ? 4204 MOUSE_BUTTON5DOWN : 0; 4205 break; 4206 4207 case MOUSE_MODEL_INTELLI: 4208 case MOUSE_MODEL_NET: 4209 /* wheel data is in the fourth byte */ 4210 z = (char)pb->ipacket[3]; 4211 /* 4212 * XXX some mice may send 7 when there is no Z movement? */ 4213 if ((z >= 7) || (z <= -7)) 4214 z = 0; 4215 /* some compatible mice have additional buttons */ 4216 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN) ? 4217 MOUSE_BUTTON4DOWN : 0; 4218 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN) ? 4219 MOUSE_BUTTON5DOWN : 0; 4220 break; 4221 4222 case MOUSE_MODEL_MOUSEMANPLUS: 4223 proc_mmanplus(sc, pb, &ms, &x, &y, &z); 4224 break; 4225 4226 case MOUSE_MODEL_GLIDEPOINT: 4227 /* `tapping' action */ 4228 ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : 4229 MOUSE_BUTTON4DOWN; 4230 break; 4231 4232 case MOUSE_MODEL_NETSCROLL: 4233 /* 4234 * three addtional bytes encode buttons and 4235 * wheel events 4236 */ 4237 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ? 4238 MOUSE_BUTTON4DOWN : 0; 4239 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ? 4240 MOUSE_BUTTON5DOWN : 0; 4241 z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ? 4242 pb->ipacket[4] - 256 : pb->ipacket[4]; 4243 break; 4244 4245 case MOUSE_MODEL_THINK: 4246 /* the fourth button state in the first byte */ 4247 ms.button |= (c & MOUSE_PS2_TAP) ? 4248 MOUSE_BUTTON4DOWN : 0; 4249 break; 4250 4251 case MOUSE_MODEL_VERSAPAD: 4252 proc_versapad(sc, pb, &ms, &x, &y, &z); 4253 c = ((x < 0) ? MOUSE_PS2_XNEG : 0) | 4254 ((y < 0) ? MOUSE_PS2_YNEG : 0); 4255 break; 4256 4257 case MOUSE_MODEL_4D: 4258 /* 4259 * b7 b6 b5 b4 b3 b2 b1 b0 4260 * byte 1: s2 d2 s1 d1 1 M R L 4261 * byte 2: sx x x x x x x x 4262 * byte 3: sy y y y y y y y 4263 * 4264 * s1: wheel 1 direction 4265 * d1: wheel 1 data 4266 * s2: wheel 2 direction 4267 * d2: wheel 2 data 4268 */ 4269 x = (pb->ipacket[1] & 0x80) ? 4270 pb->ipacket[1] - 256 : pb->ipacket[1]; 4271 y = (pb->ipacket[2] & 0x80) ? 4272 pb->ipacket[2] - 256 : pb->ipacket[2]; 4273 switch (c & MOUSE_4D_WHEELBITS) { 4274 case 0x10: 4275 z = 1; 4276 break; 4277 case 0x30: 4278 z = -1; 4279 break; 4280 case 0x40: /* XXX 2nd wheel turning right */ 4281 z = 2; 4282 break; 4283 case 0xc0: /* XXX 2nd wheel turning left */ 4284 z = -2; 4285 break; 4286 } 4287 break; 4288 4289 case MOUSE_MODEL_4DPLUS: 4290 if ((x < 16 - 256) && (y < 16 - 256)) { 4291 /* 4292 * b7 b6 b5 b4 b3 b2 b1 b0 4293 * byte 1: 0 0 1 1 1 M R L 4294 * byte 2: 0 0 0 0 1 0 0 0 4295 * byte 3: 0 0 0 0 S s d1 d0 4296 * 4297 * L, M, R, S: left, middle, right, 4298 * and side buttons 4299 * s: wheel data sign bit 4300 * d1-d0: wheel data 4301 */ 4302 x = y = 0; 4303 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN) 4304 ms.button |= MOUSE_BUTTON4DOWN; 4305 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ? 4306 ((pb->ipacket[2] & 0x07) - 8) : 4307 (pb->ipacket[2] & 0x07) ; 4308 } else { 4309 /* preserve previous button states */ 4310 ms.button |= ms.obutton & MOUSE_EXTBUTTONS; 4311 } 4312 break; 4313 4314 case MOUSE_MODEL_SYNAPTICS: 4315 if (proc_synaptics(sc, pb, &ms, &x, &y, &z) != 0) 4316 goto next; 4317 break; 4318 4319 case MOUSE_MODEL_ELANTECH: 4320 if (proc_elantech(sc, pb, &ms, &x, &y, &z) != 0) 4321 goto next; 4322 break; 4323 4324 case MOUSE_MODEL_TRACKPOINT: 4325 case MOUSE_MODEL_GENERIC: 4326 default: 4327 break; 4328 } 4329 4330 /* scale values */ 4331 if (sc->mode.accelfactor >= 1) { 4332 if (x != 0) { 4333 x = x * x / sc->mode.accelfactor; 4334 if (x == 0) 4335 x = 1; 4336 if (c & MOUSE_PS2_XNEG) 4337 x = -x; 4338 } 4339 if (y != 0) { 4340 y = y * y / sc->mode.accelfactor; 4341 if (y == 0) 4342 y = 1; 4343 if (c & MOUSE_PS2_YNEG) 4344 y = -y; 4345 } 4346 } 4347 /* Store last packet for reinjection if it has not been set already */ 4348 if (timevalisset(&sc->idletimeout) && sc->idlepacket.inputbytes == 0) 4349 sc->idlepacket = *pb; 4350 4351 ms.dx = x; 4352 ms.dy = y; 4353 ms.dz = z; 4354 ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) | 4355 (ms.obutton ^ ms.button); 4356 4357 pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket); 4358 4359 sc->status.flags |= ms.flags; 4360 sc->status.dx += ms.dx; 4361 sc->status.dy += ms.dy; 4362 sc->status.dz += ms.dz; 4363 sc->status.button = ms.button; 4364 sc->button = ms.button; 4365 4366 sc->watchdog = FALSE; 4367 4368 /* queue data */ 4369 if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) { 4370 l = imin(pb->inputbytes, 4371 sizeof(sc->queue.buf) - sc->queue.tail); 4372 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l); 4373 if (pb->inputbytes > l) 4374 bcopy(&pb->ipacket[l], &sc->queue.buf[0], 4375 pb->inputbytes - l); 4376 sc->queue.tail = (sc->queue.tail + pb->inputbytes) % 4377 sizeof(sc->queue.buf); 4378 sc->queue.count += pb->inputbytes; 4379 } 4380 pb->inputbytes = 0; 4381 4382 next: 4383 if (++sc->pqueue_start >= PSM_PACKETQUEUE) 4384 sc->pqueue_start = 0; 4385 } while (sc->pqueue_start != sc->pqueue_end); 4386 4387 if (sc->state & PSM_ASLP) { 4388 sc->state &= ~PSM_ASLP; 4389 wakeup(sc); 4390 } 4391 4392 KNOTE(&sc->rkq.ki_note, 0); 4393 sc->state &= ~PSM_SOFTARMED; 4394 4395 /* schedule injection of predefined packet after idletimeout 4396 * if no data packets have been received from psmintr */ 4397 if (timevalisset(&sc->idletimeout)) { 4398 sc->state |= PSM_SOFTARMED; 4399 callout_reset(&sc->softcallout, tvtohz_high(&sc->idletimeout), 4400 psmsoftintridle, sc); 4401 VLOG(2, (LOG_DEBUG, "softintr: callout set: %d ticks\n", 4402 tvtohz_high(&sc->idletimeout))); 4403 } 4404 lockmgr(&sc->lock, LK_RELEASE); 4405 } 4406 4407 static struct filterops psmfiltops = 4408 { FILTEROP_ISFD, NULL, psmfilter_detach, psmfilter }; 4409 4410 static int 4411 psmkqfilter(struct dev_kqfilter_args *ap) 4412 { 4413 cdev_t dev = ap->a_head.a_dev; 4414 struct psm_softc *sc = dev->si_drv1; 4415 struct knote *kn = ap->a_kn; 4416 struct klist *klist; 4417 4418 ap->a_result = 0; 4419 4420 switch (kn->kn_filter) { 4421 case EVFILT_READ: 4422 kn->kn_fop = &psmfiltops; 4423 kn->kn_hook = (caddr_t)sc; 4424 break; 4425 default: 4426 ap->a_result = EOPNOTSUPP; 4427 return (0); 4428 } 4429 4430 klist = &sc->rkq.ki_note; 4431 knote_insert(klist, kn); 4432 4433 return (0); 4434 } 4435 4436 static void 4437 psmfilter_detach(struct knote *kn) 4438 { 4439 struct psm_softc *sc = (struct psm_softc *)kn->kn_hook; 4440 struct klist *klist; 4441 4442 klist = &sc->rkq.ki_note; 4443 knote_remove(klist, kn); 4444 } 4445 4446 static int 4447 psmfilter(struct knote *kn, long hint) 4448 { 4449 struct psm_softc *sc = (struct psm_softc *)kn->kn_hook; 4450 int ready = 0; 4451 4452 lockmgr(&sc->lock, LK_EXCLUSIVE); 4453 if (sc->queue.count > 0) 4454 ready = 1; 4455 lockmgr(&sc->lock, LK_RELEASE); 4456 4457 return (ready); 4458 } 4459 4460 4461 /* vendor/model specific routines */ 4462 4463 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status) 4464 { 4465 4466 if (set_mouse_resolution(kbdc, res) != res) 4467 return (FALSE); 4468 if (set_mouse_scaling(kbdc, scale) && 4469 set_mouse_scaling(kbdc, scale) && 4470 set_mouse_scaling(kbdc, scale) && 4471 (get_mouse_status(kbdc, status, 0, 3) >= 3)) 4472 return (TRUE); 4473 return (FALSE); 4474 } 4475 4476 static int 4477 mouse_ext_command(KBDC kbdc, int command) 4478 { 4479 4480 int c; 4481 4482 c = (command >> 6) & 0x03; 4483 if (set_mouse_resolution(kbdc, c) != c) 4484 return (FALSE); 4485 c = (command >> 4) & 0x03; 4486 if (set_mouse_resolution(kbdc, c) != c) 4487 return (FALSE); 4488 c = (command >> 2) & 0x03; 4489 if (set_mouse_resolution(kbdc, c) != c) 4490 return (FALSE); 4491 c = (command >> 0) & 0x03; 4492 if (set_mouse_resolution(kbdc, c) != c) 4493 return (FALSE); 4494 return (TRUE); 4495 } 4496 4497 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */ 4498 static int 4499 enable_groller(struct psm_softc *sc, enum probearg arg) 4500 { 4501 KBDC kbdc = sc->kbdc; 4502 int status[3]; 4503 4504 /* 4505 * The special sequence to enable the fourth button and the 4506 * roller. Immediately after this sequence check status bytes. 4507 * if the mouse is NetScroll, the second and the third bytes are 4508 * '3' and 'D'. 4509 */ 4510 4511 /* 4512 * If the mouse is an ordinary PS/2 mouse, the status bytes should 4513 * look like the following. 4514 * 4515 * byte 1 bit 7 always 0 4516 * bit 6 stream mode (0) 4517 * bit 5 disabled (0) 4518 * bit 4 1:1 scaling (0) 4519 * bit 3 always 0 4520 * bit 0-2 button status 4521 * byte 2 resolution (PSMD_RES_HIGH) 4522 * byte 3 report rate (?) 4523 */ 4524 4525 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 1, status)) 4526 return (FALSE); 4527 if ((status[1] != '3') || (status[2] != 'D')) 4528 return (FALSE); 4529 /* FIXME: SmartScroll Mouse has 5 buttons! XXX */ 4530 if (arg == PROBE) 4531 sc->hw.buttons = 4; 4532 return (TRUE); 4533 } 4534 4535 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */ 4536 static int 4537 enable_gmouse(struct psm_softc *sc, enum probearg arg) 4538 { 4539 KBDC kbdc = sc->kbdc; 4540 int status[3]; 4541 4542 /* 4543 * The special sequence to enable the middle, "rubber" button. 4544 * Immediately after this sequence check status bytes. 4545 * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse, 4546 * the second and the third bytes are '3' and 'U'. 4547 * NOTE: NetMouse reports that it has three buttons although it has 4548 * two buttons and a rubber button. NetMouse Pro and MIE Mouse 4549 * say they have three buttons too and they do have a button on the 4550 * side... 4551 */ 4552 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 1, status)) 4553 return (FALSE); 4554 if ((status[1] != '3') || (status[2] != 'U')) 4555 return (FALSE); 4556 return (TRUE); 4557 } 4558 4559 /* ALPS GlidePoint */ 4560 static int 4561 enable_aglide(struct psm_softc *sc, enum probearg arg) 4562 { 4563 KBDC kbdc = sc->kbdc; 4564 int status[3]; 4565 4566 /* 4567 * The special sequence to obtain ALPS GlidePoint specific 4568 * information. Immediately after this sequence, status bytes will 4569 * contain something interesting. 4570 * NOTE: ALPS produces several models of GlidePoint. Some of those 4571 * do not respond to this sequence, thus, cannot be detected this way. 4572 */ 4573 if (set_mouse_sampling_rate(kbdc, 100) != 100) 4574 return (FALSE); 4575 if (!mouse_id_proc1(kbdc, PSMD_RES_LOW, 2, status)) 4576 return (FALSE); 4577 if ((status[1] == PSMD_RES_LOW) || (status[2] == 100)) 4578 return (FALSE); 4579 return (TRUE); 4580 } 4581 4582 /* Kensington ThinkingMouse/Trackball */ 4583 static int 4584 enable_kmouse(struct psm_softc *sc, enum probearg arg) 4585 { 4586 static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; 4587 KBDC kbdc = sc->kbdc; 4588 int status[3]; 4589 int id1; 4590 int id2; 4591 int i; 4592 4593 id1 = get_aux_id(kbdc); 4594 if (set_mouse_sampling_rate(kbdc, 10) != 10) 4595 return (FALSE); 4596 /* 4597 * The device is now in the native mode? It returns a different 4598 * ID value... 4599 */ 4600 id2 = get_aux_id(kbdc); 4601 if ((id1 == id2) || (id2 != 2)) 4602 return (FALSE); 4603 4604 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) 4605 return (FALSE); 4606 #if PSM_DEBUG >= 2 4607 /* at this point, resolution is LOW, sampling rate is 10/sec */ 4608 if (get_mouse_status(kbdc, status, 0, 3) < 3) 4609 return (FALSE); 4610 #endif 4611 4612 /* 4613 * The special sequence to enable the third and fourth buttons. 4614 * Otherwise they behave like the first and second buttons. 4615 */ 4616 for (i = 0; i < nitems(rate); ++i) 4617 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4618 return (FALSE); 4619 4620 /* 4621 * At this point, the device is using default resolution and 4622 * sampling rate for the native mode. 4623 */ 4624 if (get_mouse_status(kbdc, status, 0, 3) < 3) 4625 return (FALSE); 4626 if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1])) 4627 return (FALSE); 4628 4629 /* the device appears be enabled by this sequence, diable it for now */ 4630 disable_aux_dev(kbdc); 4631 empty_aux_buffer(kbdc, 5); 4632 4633 return (TRUE); 4634 } 4635 4636 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */ 4637 static int 4638 enable_mmanplus(struct psm_softc *sc, enum probearg arg) 4639 { 4640 KBDC kbdc = sc->kbdc; 4641 int data[3]; 4642 4643 /* the special sequence to enable the fourth button and the roller. */ 4644 /* 4645 * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION 4646 * must be called exactly three times since the last RESET command 4647 * before this sequence. XXX 4648 */ 4649 if (!set_mouse_scaling(kbdc, 1)) 4650 return (FALSE); 4651 if (!mouse_ext_command(kbdc, 0x39) || !mouse_ext_command(kbdc, 0xdb)) 4652 return (FALSE); 4653 if (get_mouse_status(kbdc, data, 1, 3) < 3) 4654 return (FALSE); 4655 4656 /* 4657 * PS2++ protocol, packet type 0 4658 * 4659 * b7 b6 b5 b4 b3 b2 b1 b0 4660 * byte 1: * 1 p3 p2 1 * * * 4661 * byte 2: 1 1 p1 p0 m1 m0 1 0 4662 * byte 3: m7 m6 m5 m4 m3 m2 m1 m0 4663 * 4664 * p3-p0: packet type: 0 4665 * m7-m0: model ID: MouseMan+:0x50, 4666 * FirstMouse+:0x51, 4667 * ScrollPoint:0x58... 4668 */ 4669 /* check constant bits */ 4670 if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC) 4671 return (FALSE); 4672 if ((data[1] & 0xc3) != 0xc2) 4673 return (FALSE); 4674 /* check d3-d0 in byte 2 */ 4675 if (!MOUSE_PS2PLUS_CHECKBITS(data)) 4676 return (FALSE); 4677 /* check p3-p0 */ 4678 if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0) 4679 return (FALSE); 4680 4681 if (arg == PROBE) { 4682 sc->hw.hwid &= 0x00ff; 4683 sc->hw.hwid |= data[2] << 8; /* save model ID */ 4684 } 4685 4686 /* 4687 * MouseMan+ (or FirstMouse+) is now in its native mode, in which 4688 * the wheel and the fourth button events are encoded in the 4689 * special data packet. The mouse may be put in the IntelliMouse mode 4690 * if it is initialized by the IntelliMouse's method. 4691 */ 4692 return (TRUE); 4693 } 4694 4695 /* MS IntelliMouse Explorer */ 4696 static int 4697 enable_msexplorer(struct psm_softc *sc, enum probearg arg) 4698 { 4699 KBDC kbdc = sc->kbdc; 4700 static u_char rate0[] = { 200, 100, 80, }; 4701 static u_char rate1[] = { 200, 200, 80, }; 4702 int id; 4703 int i; 4704 4705 /* 4706 * This is needed for at least A4Tech X-7xx mice - they do not go 4707 * straight to Explorer mode, but need to be set to Intelli mode 4708 * first. 4709 */ 4710 enable_msintelli(sc, arg); 4711 4712 /* the special sequence to enable the extra buttons and the roller. */ 4713 for (i = 0; i < nitems(rate1); ++i) 4714 if (set_mouse_sampling_rate(kbdc, rate1[i]) != rate1[i]) 4715 return (FALSE); 4716 /* the device will give the genuine ID only after the above sequence */ 4717 id = get_aux_id(kbdc); 4718 if (id != PSM_EXPLORER_ID) 4719 return (FALSE); 4720 4721 if (arg == PROBE) { 4722 sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */ 4723 sc->hw.hwid = id; 4724 } 4725 4726 /* 4727 * XXX: this is a kludge to fool some KVM switch products 4728 * which think they are clever enough to know the 4-byte IntelliMouse 4729 * protocol, and assume any other protocols use 3-byte packets. 4730 * They don't convey 4-byte data packets from the IntelliMouse Explorer 4731 * correctly to the host computer because of this! 4732 * The following sequence is actually IntelliMouse's "wake up" 4733 * sequence; it will make the KVM think the mouse is IntelliMouse 4734 * when it is in fact IntelliMouse Explorer. 4735 */ 4736 for (i = 0; i < nitems(rate0); ++i) 4737 if (set_mouse_sampling_rate(kbdc, rate0[i]) != rate0[i]) 4738 break; 4739 get_aux_id(kbdc); 4740 4741 return (TRUE); 4742 } 4743 4744 /* 4745 * MS IntelliMouse 4746 * Logitech MouseMan+ and FirstMouse+ will also respond to this 4747 * probe routine and act like IntelliMouse. 4748 */ 4749 static int 4750 enable_msintelli(struct psm_softc *sc, enum probearg arg) 4751 { 4752 KBDC kbdc = sc->kbdc; 4753 static u_char rate[] = { 200, 100, 80, }; 4754 int id; 4755 int i; 4756 4757 /* the special sequence to enable the third button and the roller. */ 4758 for (i = 0; i < nitems(rate); ++i) 4759 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4760 return (FALSE); 4761 /* the device will give the genuine ID only after the above sequence */ 4762 id = get_aux_id(kbdc); 4763 if (id != PSM_INTELLI_ID) 4764 return (FALSE); 4765 4766 if (arg == PROBE) { 4767 sc->hw.buttons = 3; 4768 sc->hw.hwid = id; 4769 } 4770 4771 return (TRUE); 4772 } 4773 4774 /* 4775 * A4 Tech 4D Mouse 4776 * Newer wheel mice from A4 Tech may use the 4D+ protocol. 4777 */ 4778 static int 4779 enable_4dmouse(struct psm_softc *sc, enum probearg arg) 4780 { 4781 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; 4782 KBDC kbdc = sc->kbdc; 4783 int id; 4784 int i; 4785 4786 for (i = 0; i < nitems(rate); ++i) 4787 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4788 return (FALSE); 4789 id = get_aux_id(kbdc); 4790 /* 4791 * WinEasy 4D, 4 Way Scroll 4D: 6 4792 * Cable-Free 4D: 8 (4DPLUS) 4793 * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS) 4794 */ 4795 if (id != PSM_4DMOUSE_ID) 4796 return (FALSE); 4797 4798 if (arg == PROBE) { 4799 sc->hw.buttons = 3; /* XXX some 4D mice have 4? */ 4800 sc->hw.hwid = id; 4801 } 4802 4803 return (TRUE); 4804 } 4805 4806 /* 4807 * A4 Tech 4D+ Mouse 4808 * Newer wheel mice from A4 Tech seem to use this protocol. 4809 * Older models are recognized as either 4D Mouse or IntelliMouse. 4810 */ 4811 static int 4812 enable_4dplus(struct psm_softc *sc, enum probearg arg) 4813 { 4814 KBDC kbdc = sc->kbdc; 4815 int id; 4816 4817 /* 4818 * enable_4dmouse() already issued the following ID sequence... 4819 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; 4820 int i; 4821 4822 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) 4823 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4824 return (FALSE); 4825 */ 4826 4827 id = get_aux_id(kbdc); 4828 switch (id) { 4829 case PSM_4DPLUS_ID: 4830 break; 4831 case PSM_4DPLUS_RFSW35_ID: 4832 break; 4833 default: 4834 return (FALSE); 4835 } 4836 4837 if (arg == PROBE) { 4838 sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3; 4839 sc->hw.hwid = id; 4840 } 4841 4842 return (TRUE); 4843 } 4844 4845 /* Synaptics Touchpad */ 4846 static int 4847 synaptics_sysctl(SYSCTL_HANDLER_ARGS) 4848 { 4849 struct psm_softc *sc; 4850 int error, arg; 4851 4852 if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 || 4853 oidp->oid_arg2 > SYNAPTICS_SYSCTL_SOFTBUTTON3_X) 4854 return (EINVAL); 4855 4856 sc = oidp->oid_arg1; 4857 4858 /* Read the current value. */ 4859 arg = *(int *)((char *)sc + oidp->oid_arg2); 4860 error = sysctl_handle_int(oidp, &arg, 0, req); 4861 4862 /* Sanity check. */ 4863 if (error || !req->newptr) 4864 return (error); 4865 4866 /* 4867 * Check that the new value is in the concerned node's range 4868 * of values. 4869 */ 4870 switch (oidp->oid_arg2) { 4871 case SYNAPTICS_SYSCTL_MIN_PRESSURE: 4872 case SYNAPTICS_SYSCTL_MAX_PRESSURE: 4873 if (arg < 0 || arg > 255) 4874 return (EINVAL); 4875 break; 4876 case SYNAPTICS_SYSCTL_MAX_WIDTH: 4877 if (arg < 4 || arg > 15) 4878 return (EINVAL); 4879 break; 4880 case SYNAPTICS_SYSCTL_MARGIN_TOP: 4881 case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: 4882 case SYNAPTICS_SYSCTL_NA_TOP: 4883 case SYNAPTICS_SYSCTL_NA_BOTTOM: 4884 if (arg < 0 || arg > sc->synhw.maximumYCoord) 4885 return (EINVAL); 4886 break; 4887 case SYNAPTICS_SYSCTL_SOFTBUTTON2_X: 4888 case SYNAPTICS_SYSCTL_SOFTBUTTON3_X: 4889 /* Softbuttons is clickpad only feature */ 4890 if (!sc->synhw.capClickPad && arg != 0) 4891 return (EINVAL); 4892 /* FALLTHROUGH */ 4893 case SYNAPTICS_SYSCTL_MARGIN_RIGHT: 4894 case SYNAPTICS_SYSCTL_MARGIN_LEFT: 4895 case SYNAPTICS_SYSCTL_NA_RIGHT: 4896 case SYNAPTICS_SYSCTL_NA_LEFT: 4897 if (arg < 0 || arg > sc->synhw.maximumXCoord) 4898 return (EINVAL); 4899 break; 4900 case SYNAPTICS_SYSCTL_WINDOW_MIN: 4901 case SYNAPTICS_SYSCTL_WINDOW_MAX: 4902 case SYNAPTICS_SYSCTL_TAP_MIN_QUEUE: 4903 if (arg < 1 || arg > SYNAPTICS_PACKETQUEUE) 4904 return (EINVAL); 4905 break; 4906 case SYNAPTICS_SYSCTL_MULTIPLICATOR: 4907 case SYNAPTICS_SYSCTL_WEIGHT_CURRENT: 4908 case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS: 4909 case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA: 4910 case SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED: 4911 case SYNAPTICS_SYSCTL_DIV_MIN: 4912 case SYNAPTICS_SYSCTL_DIV_MAX: 4913 case SYNAPTICS_SYSCTL_DIV_MAX_NA: 4914 case SYNAPTICS_SYSCTL_DIV_LEN: 4915 case SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN: 4916 case SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX: 4917 if (arg < 1) 4918 return (EINVAL); 4919 break; 4920 case SYNAPTICS_SYSCTL_TAP_MAX_DELTA: 4921 case SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT: 4922 case SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA: 4923 if (arg < 0) 4924 return (EINVAL); 4925 break; 4926 case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: 4927 if (arg < -sc->synhw.maximumXCoord || 4928 arg > sc->synhw.maximumXCoord) 4929 return (EINVAL); 4930 break; 4931 case SYNAPTICS_SYSCTL_SOFTBUTTONS_Y: 4932 /* Softbuttons is clickpad only feature */ 4933 if (!sc->synhw.capClickPad && arg != 0) 4934 return (EINVAL); 4935 /* FALLTHROUGH */ 4936 case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: 4937 if (arg < -sc->synhw.maximumYCoord || 4938 arg > sc->synhw.maximumYCoord) 4939 return (EINVAL); 4940 break; 4941 case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: 4942 if (arg < 0 || arg > 1) 4943 return (EINVAL); 4944 break; 4945 default: 4946 return (EINVAL); 4947 } 4948 4949 /* Update. */ 4950 *(int *)((char *)sc + oidp->oid_arg2) = arg; 4951 4952 return (error); 4953 } 4954 4955 static void 4956 synaptics_sysctl_create_softbuttons_tree(struct psm_softc *sc) 4957 { 4958 /* 4959 * Set predefined sizes for softbuttons. 4960 * Values are taken to match HP Pavilion dv6 clickpad drawings 4961 * with thin middle softbutton placed on separator 4962 */ 4963 4964 /* hw.psm.synaptics.softbuttons_y */ 4965 sc->syninfo.softbuttons_y = 1700; 4966 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4967 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4968 "softbuttons_y", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4969 sc, SYNAPTICS_SYSCTL_SOFTBUTTONS_Y, 4970 synaptics_sysctl, "I", 4971 "Vertical size of softbuttons area"); 4972 4973 /* hw.psm.synaptics.softbutton2_x */ 4974 sc->syninfo.softbutton2_x = 3100; 4975 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4976 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4977 "softbutton2_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4978 sc, SYNAPTICS_SYSCTL_SOFTBUTTON2_X, 4979 synaptics_sysctl, "I", 4980 "Horisontal position of 2-nd softbutton left edge (0-disable)"); 4981 4982 /* hw.psm.synaptics.softbutton3_x */ 4983 sc->syninfo.softbutton3_x = 3900; 4984 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4985 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4986 "softbutton3_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4987 sc, SYNAPTICS_SYSCTL_SOFTBUTTON3_X, 4988 synaptics_sysctl, "I", 4989 "Horisontal position of 3-rd softbutton left edge (0-disable)"); 4990 } 4991 4992 static void 4993 synaptics_sysctl_create_tree(struct psm_softc *sc, const char *name, 4994 const char *descr) 4995 { 4996 4997 if (sc->syninfo.sysctl_tree != NULL) 4998 return; 4999 5000 /* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ 5001 sysctl_ctx_init(&sc->syninfo.sysctl_ctx); 5002 sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, 5003 SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, name, CTLFLAG_RD, 5004 0, descr); 5005 5006 /* hw.psm.synaptics.directional_scrolls. */ 5007 sc->syninfo.directional_scrolls = 0; 5008 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5009 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5010 "directional_scrolls", CTLFLAG_RW|CTLFLAG_ANYBODY, 5011 &sc->syninfo.directional_scrolls, 0, 5012 "Enable hardware scrolling pad (if non-zero) or register it as " 5013 "extended buttons (if 0)"); 5014 5015 /* hw.psm.synaptics.max_x. */ 5016 sc->syninfo.max_x = 6143; 5017 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5018 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5019 "max_x", CTLFLAG_RD|CTLFLAG_ANYBODY, 5020 &sc->syninfo.max_x, 0, 5021 "Horizontal reporting range"); 5022 5023 /* hw.psm.synaptics.max_y. */ 5024 sc->syninfo.max_y = 6143; 5025 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5026 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5027 "max_y", CTLFLAG_RD|CTLFLAG_ANYBODY, 5028 &sc->syninfo.max_y, 0, 5029 "Vertical reporting range"); 5030 5031 /* 5032 * Turn off two finger scroll if we have a 5033 * physical area reserved for scrolling or when 5034 * there's no multi finger support. 5035 */ 5036 if (sc->synhw.verticalScroll || (sc->synhw.capMultiFinger == 0 && 5037 sc->synhw.capAdvancedGestures == 0)) 5038 sc->syninfo.two_finger_scroll = 0; 5039 else 5040 sc->syninfo.two_finger_scroll = 1; 5041 /* hw.psm.synaptics.two_finger_scroll. */ 5042 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 5043 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5044 "two_finger_scroll", CTLFLAG_RW|CTLFLAG_ANYBODY, 5045 &sc->syninfo.two_finger_scroll, 0, 5046 "Enable two finger scrolling"); 5047 5048 /* hw.psm.synaptics.min_pressure. */ 5049 sc->syninfo.min_pressure = 16; 5050 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5051 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5052 "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5053 sc, SYNAPTICS_SYSCTL_MIN_PRESSURE, 5054 synaptics_sysctl, "I", 5055 "Minimum pressure required to start an action"); 5056 5057 /* hw.psm.synaptics.max_pressure. */ 5058 sc->syninfo.max_pressure = 220; 5059 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5060 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5061 "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5062 sc, SYNAPTICS_SYSCTL_MAX_PRESSURE, 5063 synaptics_sysctl, "I", 5064 "Maximum pressure to detect palm"); 5065 5066 /* hw.psm.synaptics.max_width. */ 5067 sc->syninfo.max_width = 10; 5068 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5069 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5070 "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5071 sc, SYNAPTICS_SYSCTL_MAX_WIDTH, 5072 synaptics_sysctl, "I", 5073 "Maximum finger width to detect palm"); 5074 5075 /* hw.psm.synaptics.top_margin. */ 5076 sc->syninfo.margin_top = 200; 5077 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5078 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5079 "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5080 sc, SYNAPTICS_SYSCTL_MARGIN_TOP, 5081 synaptics_sysctl, "I", 5082 "Top margin"); 5083 5084 /* hw.psm.synaptics.right_margin. */ 5085 sc->syninfo.margin_right = 200; 5086 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5087 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5088 "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5089 sc, SYNAPTICS_SYSCTL_MARGIN_RIGHT, 5090 synaptics_sysctl, "I", 5091 "Right margin"); 5092 5093 /* hw.psm.synaptics.bottom_margin. */ 5094 sc->syninfo.margin_bottom = 200; 5095 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5096 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5097 "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5098 sc, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, 5099 synaptics_sysctl, "I", 5100 "Bottom margin"); 5101 5102 /* hw.psm.synaptics.left_margin. */ 5103 sc->syninfo.margin_left = 200; 5104 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5105 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5106 "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5107 sc, SYNAPTICS_SYSCTL_MARGIN_LEFT, 5108 synaptics_sysctl, "I", 5109 "Left margin"); 5110 5111 /* hw.psm.synaptics.na_top. */ 5112 sc->syninfo.na_top = 1783; 5113 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5114 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5115 "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5116 sc, SYNAPTICS_SYSCTL_NA_TOP, 5117 synaptics_sysctl, "I", 5118 "Top noisy area, where weight_previous_na is used instead " 5119 "of weight_previous"); 5120 5121 /* hw.psm.synaptics.na_right. */ 5122 sc->syninfo.na_right = 563; 5123 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5124 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5125 "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5126 sc, SYNAPTICS_SYSCTL_NA_RIGHT, 5127 synaptics_sysctl, "I", 5128 "Right noisy area, where weight_previous_na is used instead " 5129 "of weight_previous"); 5130 5131 /* hw.psm.synaptics.na_bottom. */ 5132 sc->syninfo.na_bottom = 1408; 5133 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5134 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5135 "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5136 sc, SYNAPTICS_SYSCTL_NA_BOTTOM, 5137 synaptics_sysctl, "I", 5138 "Bottom noisy area, where weight_previous_na is used instead " 5139 "of weight_previous"); 5140 5141 /* hw.psm.synaptics.na_left. */ 5142 sc->syninfo.na_left = 1600; 5143 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5144 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5145 "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5146 sc, SYNAPTICS_SYSCTL_NA_LEFT, 5147 synaptics_sysctl, "I", 5148 "Left noisy area, where weight_previous_na is used instead " 5149 "of weight_previous"); 5150 5151 /* hw.psm.synaptics.window_min. */ 5152 sc->syninfo.window_min = 4; 5153 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5154 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5155 "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5156 sc, SYNAPTICS_SYSCTL_WINDOW_MIN, 5157 synaptics_sysctl, "I", 5158 "Minimum window size to start an action"); 5159 5160 /* hw.psm.synaptics.window_max. */ 5161 sc->syninfo.window_max = 10; 5162 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5163 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5164 "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5165 sc, SYNAPTICS_SYSCTL_WINDOW_MAX, 5166 synaptics_sysctl, "I", 5167 "Maximum window size"); 5168 5169 /* hw.psm.synaptics.multiplicator. */ 5170 sc->syninfo.multiplicator = 10000; 5171 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5172 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5173 "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5174 sc, SYNAPTICS_SYSCTL_MULTIPLICATOR, 5175 synaptics_sysctl, "I", 5176 "Multiplicator to increase precision in averages and divisions"); 5177 5178 /* hw.psm.synaptics.weight_current. */ 5179 sc->syninfo.weight_current = 3; 5180 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5181 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5182 "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5183 sc, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, 5184 synaptics_sysctl, "I", 5185 "Weight of the current movement in the new average"); 5186 5187 /* hw.psm.synaptics.weight_previous. */ 5188 sc->syninfo.weight_previous = 6; 5189 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5190 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5191 "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5192 sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, 5193 synaptics_sysctl, "I", 5194 "Weight of the previous average"); 5195 5196 /* hw.psm.synaptics.weight_previous_na. */ 5197 sc->syninfo.weight_previous_na = 20; 5198 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5199 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5200 "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5201 sc, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, 5202 synaptics_sysctl, "I", 5203 "Weight of the previous average (inside the noisy area)"); 5204 5205 /* hw.psm.synaptics.weight_len_squared. */ 5206 sc->syninfo.weight_len_squared = 2000; 5207 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5208 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5209 "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5210 sc, SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, 5211 synaptics_sysctl, "I", 5212 "Length (squared) of segments where weight_previous " 5213 "starts to decrease"); 5214 5215 /* hw.psm.synaptics.div_min. */ 5216 sc->syninfo.div_min = 9; 5217 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5218 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5219 "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5220 sc, SYNAPTICS_SYSCTL_DIV_MIN, 5221 synaptics_sysctl, "I", 5222 "Divisor for fast movements"); 5223 5224 /* hw.psm.synaptics.div_max. */ 5225 sc->syninfo.div_max = 17; 5226 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5227 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5228 "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5229 sc, SYNAPTICS_SYSCTL_DIV_MAX, 5230 synaptics_sysctl, "I", 5231 "Divisor for slow movements"); 5232 5233 /* hw.psm.synaptics.div_max_na. */ 5234 sc->syninfo.div_max_na = 30; 5235 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5236 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5237 "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5238 sc, SYNAPTICS_SYSCTL_DIV_MAX_NA, 5239 synaptics_sysctl, "I", 5240 "Divisor with slow movements (inside the noisy area)"); 5241 5242 /* hw.psm.synaptics.div_len. */ 5243 sc->syninfo.div_len = 100; 5244 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5245 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5246 "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5247 sc, SYNAPTICS_SYSCTL_DIV_LEN, 5248 synaptics_sysctl, "I", 5249 "Length of segments where div_max starts to decrease"); 5250 5251 /* hw.psm.synaptics.tap_max_delta. */ 5252 sc->syninfo.tap_max_delta = 80; 5253 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5254 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5255 "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5256 sc, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, 5257 synaptics_sysctl, "I", 5258 "Length of segments above which a tap is ignored"); 5259 5260 /* hw.psm.synaptics.tap_min_queue. */ 5261 sc->syninfo.tap_min_queue = 2; 5262 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5263 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5264 "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5265 sc, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, 5266 synaptics_sysctl, "I", 5267 "Number of packets required to consider a tap"); 5268 5269 /* hw.psm.synaptics.taphold_timeout. */ 5270 sc->gesture.in_taphold = 0; 5271 sc->syninfo.taphold_timeout = tap_timeout; 5272 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5273 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5274 "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5275 sc, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, 5276 synaptics_sysctl, "I", 5277 "Maximum elapsed time between two taps to consider a tap-hold " 5278 "action"); 5279 5280 /* hw.psm.synaptics.vscroll_hor_area. */ 5281 sc->syninfo.vscroll_hor_area = 0; /* 1300 */ 5282 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5283 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5284 "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5285 sc, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, 5286 synaptics_sysctl, "I", 5287 "Area reserved for horizontal virtual scrolling"); 5288 5289 /* hw.psm.synaptics.vscroll_ver_area. */ 5290 sc->syninfo.vscroll_ver_area = -400 - sc->syninfo.margin_right; 5291 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5292 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5293 "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5294 sc, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, 5295 synaptics_sysctl, "I", 5296 "Area reserved for vertical virtual scrolling"); 5297 5298 /* hw.psm.synaptics.vscroll_min_delta. */ 5299 sc->syninfo.vscroll_min_delta = 50; 5300 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5301 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5302 "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5303 sc, SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, 5304 synaptics_sysctl, "I", 5305 "Minimum movement to consider virtual scrolling"); 5306 5307 /* hw.psm.synaptics.vscroll_div_min. */ 5308 sc->syninfo.vscroll_div_min = 100; 5309 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5310 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5311 "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5312 sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, 5313 synaptics_sysctl, "I", 5314 "Divisor for fast scrolling"); 5315 5316 /* hw.psm.synaptics.vscroll_div_min. */ 5317 sc->syninfo.vscroll_div_max = 150; 5318 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5319 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5320 "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5321 sc, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, 5322 synaptics_sysctl, "I", 5323 "Divisor for slow scrolling"); 5324 5325 /* hw.psm.synaptics.touchpad_off. */ 5326 sc->syninfo.touchpad_off = 0; 5327 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 5328 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 5329 "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5330 sc, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, 5331 synaptics_sysctl, "I", 5332 "Turn off touchpad"); 5333 5334 sc->syninfo.softbuttons_y = 0; 5335 sc->syninfo.softbutton2_x = 0; 5336 sc->syninfo.softbutton3_x = 0; 5337 5338 /* skip softbuttons sysctl on not clickpads */ 5339 if (sc->synhw.capClickPad) 5340 synaptics_sysctl_create_softbuttons_tree(sc); 5341 } 5342 5343 5344 static int 5345 synaptics_preferred_mode(struct psm_softc *sc) { 5346 int mode_byte; 5347 5348 mode_byte = 0xc4; 5349 5350 /* request wmode where available */ 5351 if (sc->synhw.capExtended) 5352 mode_byte |= 1; 5353 5354 return mode_byte; 5355 } 5356 5357 static void 5358 synaptics_set_mode(struct psm_softc *sc, int mode_byte) { 5359 mouse_ext_command(sc->kbdc, mode_byte); 5360 5361 /* "Commit" the Set Mode Byte command sent above. */ 5362 set_mouse_sampling_rate(sc->kbdc, 20); 5363 5364 /* 5365 * Enable advanced gestures mode if supported and we are not entering 5366 * passthrough mode. 5367 */ 5368 if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) && 5369 !(mode_byte & (1 << 5))) { 5370 mouse_ext_command(sc->kbdc, 3); 5371 set_mouse_sampling_rate(sc->kbdc, 0xc8); 5372 } 5373 } 5374 5375 static int 5376 enable_synaptics(struct psm_softc *sc, enum probearg arg) 5377 { 5378 KBDC kbdc = sc->kbdc; 5379 synapticshw_t synhw; 5380 int status[3]; 5381 int buttons; 5382 5383 VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n")); 5384 5385 /* 5386 * Just to be on the safe side: this avoids troubles with 5387 * following mouse_ext_command() when the previous command 5388 * was PSMC_SET_RESOLUTION. Set Scaling has no effect on 5389 * Synaptics Touchpad behaviour. 5390 */ 5391 set_mouse_scaling(kbdc, 1); 5392 5393 /* Identify the Touchpad version. */ 5394 if (mouse_ext_command(kbdc, 0) == 0) 5395 return (FALSE); 5396 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5397 return (FALSE); 5398 if (status[1] != 0x47) 5399 return (FALSE); 5400 5401 bzero(&synhw, sizeof(synhw)); 5402 synhw.infoMinor = status[0]; 5403 synhw.infoMajor = status[2] & 0x0f; 5404 5405 if (verbose >= 2) 5406 kprintf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, 5407 synhw.infoMinor); 5408 5409 if (synhw.infoMajor < 4) { 5410 kprintf(" Unsupported (pre-v4) Touchpad detected\n"); 5411 return (FALSE); 5412 } 5413 5414 /* Get the Touchpad model information. */ 5415 if (mouse_ext_command(kbdc, 3) == 0) 5416 return (FALSE); 5417 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5418 return (FALSE); 5419 if ((status[1] & 0x01) != 0) { 5420 kprintf(" Failed to read model information\n"); 5421 return (FALSE); 5422 } 5423 5424 synhw.infoRot180 = (status[0] & 0x80) != 0; 5425 synhw.infoPortrait = (status[0] & 0x40) != 0; 5426 synhw.infoSensor = status[0] & 0x3f; 5427 synhw.infoHardware = (status[1] & 0xfe) >> 1; 5428 synhw.infoNewAbs = (status[2] & 0x80) != 0; 5429 synhw.capPen = (status[2] & 0x40) != 0; 5430 synhw.infoSimplC = (status[2] & 0x20) != 0; 5431 synhw.infoGeometry = status[2] & 0x0f; 5432 5433 if (verbose >= 2) { 5434 kprintf(" Model information:\n"); 5435 kprintf(" infoRot180: %d\n", synhw.infoRot180); 5436 kprintf(" infoPortrait: %d\n", synhw.infoPortrait); 5437 kprintf(" infoSensor: %d\n", synhw.infoSensor); 5438 kprintf(" infoHardware: %d\n", synhw.infoHardware); 5439 kprintf(" infoNewAbs: %d\n", synhw.infoNewAbs); 5440 kprintf(" capPen: %d\n", synhw.capPen); 5441 kprintf(" infoSimplC: %d\n", synhw.infoSimplC); 5442 kprintf(" infoGeometry: %d\n", synhw.infoGeometry); 5443 } 5444 5445 /* Read the extended capability bits. */ 5446 if (mouse_ext_command(kbdc, 2) == 0) 5447 return (FALSE); 5448 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5449 return (FALSE); 5450 if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { 5451 kprintf(" Failed to read extended capability bits\n"); 5452 return (FALSE); 5453 } 5454 5455 /* Set the different capabilities when they exist. */ 5456 buttons = 0; 5457 synhw.capExtended = (status[0] & 0x80) != 0; 5458 if (synhw.capExtended) { 5459 synhw.nExtendedQueries = (status[0] & 0x70) >> 4; 5460 synhw.capMiddle = (status[0] & 0x04) != 0; 5461 synhw.capPassthrough = (status[2] & 0x80) != 0; 5462 synhw.capLowPower = (status[2] & 0x40) != 0; 5463 synhw.capMultiFingerReport = 5464 (status[2] & 0x20) != 0; 5465 synhw.capSleep = (status[2] & 0x10) != 0; 5466 synhw.capFourButtons = (status[2] & 0x08) != 0; 5467 synhw.capBallistics = (status[2] & 0x04) != 0; 5468 synhw.capMultiFinger = (status[2] & 0x02) != 0; 5469 synhw.capPalmDetect = (status[2] & 0x01) != 0; 5470 5471 if (!set_mouse_scaling(kbdc, 1)) 5472 return (FALSE); 5473 if (mouse_ext_command(kbdc, 0x08) == 0) 5474 return (FALSE); 5475 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5476 return (FALSE); 5477 5478 synhw.infoXupmm = status[0]; 5479 synhw.infoYupmm = status[2]; 5480 5481 if (verbose >= 2) { 5482 kprintf(" Extended capabilities:\n"); 5483 kprintf(" capExtended: %d\n", synhw.capExtended); 5484 kprintf(" capMiddle: %d\n", synhw.capMiddle); 5485 kprintf(" nExtendedQueries: %d\n", 5486 synhw.nExtendedQueries); 5487 kprintf(" capPassthrough: %d\n", synhw.capPassthrough); 5488 kprintf(" capLowPower: %d\n", synhw.capLowPower); 5489 kprintf(" capMultiFingerReport: %d\n", 5490 synhw.capMultiFingerReport); 5491 kprintf(" capSleep: %d\n", synhw.capSleep); 5492 kprintf(" capFourButtons: %d\n", synhw.capFourButtons); 5493 kprintf(" capBallistics: %d\n", synhw.capBallistics); 5494 kprintf(" capMultiFinger: %d\n", synhw.capMultiFinger); 5495 kprintf(" capPalmDetect: %d\n", synhw.capPalmDetect); 5496 kprintf(" infoXupmm: %d\n", synhw.infoXupmm); 5497 kprintf(" infoYupmm: %d\n", synhw.infoYupmm); 5498 } 5499 5500 /* 5501 * If nExtendedQueries is 1 or greater, then the TouchPad 5502 * supports this number of extended queries. We can load 5503 * more information about buttons using query 0x09. 5504 */ 5505 if (synhw.nExtendedQueries >= 1) { 5506 if (!set_mouse_scaling(kbdc, 1)) 5507 return (FALSE); 5508 if (mouse_ext_command(kbdc, 0x09) == 0) 5509 return (FALSE); 5510 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5511 return (FALSE); 5512 synhw.verticalScroll = (status[0] & 0x01) != 0; 5513 synhw.horizontalScroll = (status[0] & 0x02) != 0; 5514 synhw.verticalWheel = (status[0] & 0x08) != 0; 5515 synhw.nExtendedButtons = (status[1] & 0xf0) >> 4; 5516 synhw.capEWmode = (status[0] & 0x04) != 0; 5517 if (verbose >= 2) { 5518 kprintf(" Extended model ID:\n"); 5519 kprintf(" verticalScroll: %d\n", 5520 synhw.verticalScroll); 5521 kprintf(" horizontalScroll: %d\n", 5522 synhw.horizontalScroll); 5523 kprintf(" verticalWheel: %d\n", 5524 synhw.verticalWheel); 5525 kprintf(" nExtendedButtons: %d\n", 5526 synhw.nExtendedButtons); 5527 kprintf(" capEWmode: %d\n", 5528 synhw.capEWmode); 5529 } 5530 /* 5531 * Add the number of extended buttons to the total 5532 * button support count, including the middle button 5533 * if capMiddle support bit is set. 5534 */ 5535 buttons = synhw.nExtendedButtons + synhw.capMiddle; 5536 } else 5537 /* 5538 * If the capFourButtons support bit is set, 5539 * add a fourth button to the total button count. 5540 */ 5541 buttons = synhw.capFourButtons ? 1 : 0; 5542 5543 /* Read the continued capabilities bits. */ 5544 if (synhw.nExtendedQueries >= 4) { 5545 if (!set_mouse_scaling(kbdc, 1)) 5546 return (FALSE); 5547 if (mouse_ext_command(kbdc, 0x0c) == 0) 5548 return (FALSE); 5549 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5550 return (FALSE); 5551 5552 synhw.capClickPad = (status[1] & 0x01) << 1; 5553 synhw.capClickPad |= (status[0] & 0x10) != 0; 5554 synhw.capDeluxeLEDs = (status[1] & 0x02) != 0; 5555 synhw.noAbsoluteFilter = (status[1] & 0x04) != 0; 5556 synhw.capReportsV = (status[1] & 0x08) != 0; 5557 synhw.capUniformClickPad = (status[1] & 0x10) != 0; 5558 synhw.capReportsMin = (status[1] & 0x20) != 0; 5559 synhw.capInterTouch = (status[1] & 0x40) != 0; 5560 synhw.capReportsMax = (status[0] & 0x02) != 0; 5561 synhw.capClearPad = (status[0] & 0x04) != 0; 5562 synhw.capAdvancedGestures = (status[0] & 0x08) != 0; 5563 synhw.capCoveredPad = (status[0] & 0x80) != 0; 5564 5565 if (synhw.capReportsMax) { 5566 if (!set_mouse_scaling(kbdc, 1)) 5567 return (FALSE); 5568 if (mouse_ext_command(kbdc, 0x0d) == 0) 5569 return (FALSE); 5570 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5571 return (FALSE); 5572 5573 synhw.maximumXCoord = (status[0] << 5) | 5574 ((status[1] & 0x0f) << 1); 5575 synhw.maximumYCoord = (status[2] << 5) | 5576 ((status[1] & 0xf0) >> 3); 5577 } else { 5578 /* 5579 * Typical bezel limits. Taken from 'Synaptics 5580 * PS/2 * TouchPad Interfacing Guide' p.3.2.3. 5581 */ 5582 synhw.maximumXCoord = 5472; 5583 synhw.maximumYCoord = 4448; 5584 } 5585 5586 if (synhw.capReportsMin) { 5587 if (!set_mouse_scaling(kbdc, 1)) 5588 return (FALSE); 5589 if (mouse_ext_command(kbdc, 0x0f) == 0) 5590 return (FALSE); 5591 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5592 return (FALSE); 5593 5594 synhw.minimumXCoord = (status[0] << 5) | 5595 ((status[1] & 0x0f) << 1); 5596 synhw.minimumYCoord = (status[2] << 5) | 5597 ((status[1] & 0xf0) >> 3); 5598 } else { 5599 /* 5600 * Typical bezel limits. Taken from 'Synaptics 5601 * PS/2 * TouchPad Interfacing Guide' p.3.2.3. 5602 */ 5603 synhw.minimumXCoord = 1472; 5604 synhw.minimumYCoord = 1408; 5605 } 5606 5607 if (verbose >= 2) { 5608 kprintf(" Continued capabilities:\n"); 5609 kprintf(" capClickPad: %d\n", 5610 synhw.capClickPad); 5611 kprintf(" capDeluxeLEDs: %d\n", 5612 synhw.capDeluxeLEDs); 5613 kprintf(" noAbsoluteFilter: %d\n", 5614 synhw.noAbsoluteFilter); 5615 kprintf(" capReportsV: %d\n", 5616 synhw.capReportsV); 5617 kprintf(" capUniformClickPad: %d\n", 5618 synhw.capUniformClickPad); 5619 kprintf(" capReportsMin: %d\n", 5620 synhw.capReportsMin); 5621 kprintf(" capInterTouch: %d\n", 5622 synhw.capInterTouch); 5623 kprintf(" capReportsMax: %d\n", 5624 synhw.capReportsMax); 5625 kprintf(" capClearPad: %d\n", 5626 synhw.capClearPad); 5627 kprintf(" capAdvancedGestures: %d\n", 5628 synhw.capAdvancedGestures); 5629 kprintf(" capCoveredPad: %d\n", 5630 synhw.capCoveredPad); 5631 if (synhw.capReportsMax) { 5632 kprintf(" maximumXCoord: %d\n", 5633 synhw.maximumXCoord); 5634 kprintf(" maximumYCoord: %d\n", 5635 synhw.maximumYCoord); 5636 } 5637 if (synhw.capReportsMin) { 5638 kprintf(" minimumXCoord: %d\n", 5639 synhw.minimumXCoord); 5640 kprintf(" minimumYCoord: %d\n", 5641 synhw.minimumYCoord); 5642 } 5643 } 5644 buttons += synhw.capClickPad; 5645 } 5646 } 5647 5648 if (verbose >= 2) { 5649 if (synhw.capExtended) 5650 kprintf(" Additional Buttons: %d\n", buttons); 5651 else 5652 kprintf(" No extended capabilities\n"); 5653 } 5654 5655 /* 5656 * Add the default number of 3 buttons to the total 5657 * count of supported buttons reported above. 5658 */ 5659 buttons += 3; 5660 5661 /* 5662 * Read the mode byte. 5663 * 5664 * XXX: Note the Synaptics documentation also defines the first 5665 * byte of the response to this query to be a constant 0x3b, this 5666 * does not appear to be true for Touchpads with guest devices. 5667 */ 5668 if (mouse_ext_command(kbdc, 1) == 0) 5669 return (FALSE); 5670 if (get_mouse_status(kbdc, status, 0, 3) != 3) 5671 return (FALSE); 5672 if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { 5673 kprintf(" Failed to read mode byte\n"); 5674 return (FALSE); 5675 } 5676 5677 if (arg == PROBE) 5678 sc->synhw = synhw; 5679 if (!synaptics_support) 5680 return (FALSE); 5681 5682 synaptics_set_mode(sc, synaptics_preferred_mode(sc)); 5683 5684 if (trackpoint_support && synhw.capPassthrough) { 5685 enable_trackpoint(sc, arg); 5686 } 5687 5688 VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); 5689 5690 if (arg == PROBE) { 5691 /* Create sysctl tree. */ 5692 synaptics_sysctl_create_tree(sc, "synaptics", 5693 "Synaptics TouchPad"); 5694 sc->hw.buttons = buttons; 5695 } 5696 return (TRUE); 5697 } 5698 5699 static void 5700 synaptics_passthrough_on(struct psm_softc *sc) 5701 { 5702 VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode.\n")); 5703 synaptics_set_mode(sc, synaptics_preferred_mode(sc) | (1 << 5)); 5704 } 5705 5706 static void 5707 synaptics_passthrough_off(struct psm_softc *sc) 5708 { 5709 VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n")); 5710 set_mouse_scaling(sc->kbdc, 2); 5711 set_mouse_scaling(sc->kbdc, 1); 5712 synaptics_set_mode(sc, synaptics_preferred_mode(sc)); 5713 } 5714 5715 /* IBM/Lenovo TrackPoint */ 5716 static int 5717 trackpoint_command(struct psm_softc *sc, int cmd, int loc, int val) 5718 { 5719 const int seq[] = { 0xe2, cmd, loc, val }; 5720 int i; 5721 5722 if (sc->synhw.capPassthrough) 5723 synaptics_passthrough_on(sc); 5724 5725 for (i = 0; i < nitems(seq); i++) { 5726 if (sc->synhw.capPassthrough && 5727 (seq[i] == 0xff || seq[i] == 0xe7)) 5728 if (send_aux_command(sc->kbdc, 0xe7) != PSM_ACK) { 5729 synaptics_passthrough_off(sc); 5730 return (EIO); 5731 } 5732 if (send_aux_command(sc->kbdc, seq[i]) != PSM_ACK) { 5733 if (sc->synhw.capPassthrough) 5734 synaptics_passthrough_off(sc); 5735 return (EIO); 5736 } 5737 } 5738 5739 if (sc->synhw.capPassthrough) 5740 synaptics_passthrough_off(sc); 5741 5742 return (0); 5743 } 5744 5745 #define PSM_TPINFO(x) offsetof(struct psm_softc, tpinfo.x) 5746 #define TPMASK 0 5747 #define TPLOC 1 5748 #define TPINFO 2 5749 5750 static int 5751 trackpoint_sysctl(SYSCTL_HANDLER_ARGS) 5752 { 5753 static const int data[][3] = { 5754 { 0x00, 0x4a, PSM_TPINFO(sensitivity) }, 5755 { 0x00, 0x4d, PSM_TPINFO(inertia) }, 5756 { 0x00, 0x60, PSM_TPINFO(uplateau) }, 5757 { 0x00, 0x57, PSM_TPINFO(reach) }, 5758 { 0x00, 0x58, PSM_TPINFO(draghys) }, 5759 { 0x00, 0x59, PSM_TPINFO(mindrag) }, 5760 { 0x00, 0x5a, PSM_TPINFO(upthresh) }, 5761 { 0x00, 0x5c, PSM_TPINFO(threshold) }, 5762 { 0x00, 0x5d, PSM_TPINFO(jenks) }, 5763 { 0x00, 0x5e, PSM_TPINFO(ztime) }, 5764 { 0x01, 0x2c, PSM_TPINFO(pts) }, 5765 { 0x08, 0x2d, PSM_TPINFO(skipback) } 5766 }; 5767 struct psm_softc *sc; 5768 int error, newval, *oldvalp; 5769 const int *tp; 5770 5771 if (arg1 == NULL || arg2 < 0 || arg2 >= nitems(data)) 5772 return (EINVAL); 5773 sc = arg1; 5774 tp = data[arg2]; 5775 oldvalp = (int *)((intptr_t)sc + tp[TPINFO]); 5776 newval = *oldvalp; 5777 error = sysctl_handle_int(oidp, &newval, 0, req); 5778 if (error != 0) 5779 return (error); 5780 if (newval == *oldvalp) 5781 return (0); 5782 if (newval < 0 || newval > (tp[TPMASK] == 0 ? 255 : 1)) 5783 return (EINVAL); 5784 error = trackpoint_command(sc, tp[TPMASK] == 0 ? 0x81 : 0x47, 5785 tp[TPLOC], tp[TPMASK] == 0 ? newval : tp[TPMASK]); 5786 if (error != 0) 5787 return (error); 5788 *oldvalp = newval; 5789 5790 return (0); 5791 } 5792 5793 static void 5794 trackpoint_sysctl_create_tree(struct psm_softc *sc) 5795 { 5796 5797 if (sc->tpinfo.sysctl_tree != NULL) 5798 return; 5799 5800 /* Attach extra trackpoint sysctl nodes under hw.psm.trackpoint */ 5801 sysctl_ctx_init(&sc->tpinfo.sysctl_ctx); 5802 sc->tpinfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->tpinfo.sysctl_ctx, 5803 SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "trackpoint", CTLFLAG_RD, 5804 0, "IBM/Lenovo TrackPoint"); 5805 5806 /* hw.psm.trackpoint.sensitivity */ 5807 sc->tpinfo.sensitivity = 0x80; 5808 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5809 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5810 "sensitivity", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5811 sc, TRACKPOINT_SYSCTL_SENSITIVITY, 5812 trackpoint_sysctl, "I", 5813 "Sensitivity"); 5814 5815 /* hw.psm.trackpoint.negative_inertia */ 5816 sc->tpinfo.inertia = 0x06; 5817 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5818 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5819 "negative_inertia", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5820 sc, TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, 5821 trackpoint_sysctl, "I", 5822 "Negative inertia factor"); 5823 5824 /* hw.psm.trackpoint.upper_plateau */ 5825 sc->tpinfo.uplateau = 0x61; 5826 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5827 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5828 "upper_plateau", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5829 sc, TRACKPOINT_SYSCTL_UPPER_PLATEAU, 5830 trackpoint_sysctl, "I", 5831 "Transfer function upper plateau speed"); 5832 5833 /* hw.psm.trackpoint.backup_range */ 5834 sc->tpinfo.reach = 0x0a; 5835 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5836 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5837 "backup_range", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5838 sc, TRACKPOINT_SYSCTL_BACKUP_RANGE, 5839 trackpoint_sysctl, "I", 5840 "Backup range"); 5841 5842 /* hw.psm.trackpoint.drag_hysteresis */ 5843 sc->tpinfo.draghys = 0xff; 5844 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5845 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5846 "drag_hysteresis", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5847 sc, TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, 5848 trackpoint_sysctl, "I", 5849 "Drag hysteresis"); 5850 5851 /* hw.psm.trackpoint.minimum_drag */ 5852 sc->tpinfo.mindrag = 0x14; 5853 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5854 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5855 "minimum_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5856 sc, TRACKPOINT_SYSCTL_MINIMUM_DRAG, 5857 trackpoint_sysctl, "I", 5858 "Minimum drag"); 5859 5860 /* hw.psm.trackpoint.up_threshold */ 5861 sc->tpinfo.upthresh = 0xff; 5862 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5863 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5864 "up_threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5865 sc, TRACKPOINT_SYSCTL_UP_THRESHOLD, 5866 trackpoint_sysctl, "I", 5867 "Up threshold for release"); 5868 5869 /* hw.psm.trackpoint.threshold */ 5870 sc->tpinfo.threshold = 0x08; 5871 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5872 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5873 "threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5874 sc, TRACKPOINT_SYSCTL_THRESHOLD, 5875 trackpoint_sysctl, "I", 5876 "Threshold"); 5877 5878 /* hw.psm.trackpoint.jenks_curvature */ 5879 sc->tpinfo.jenks = 0x87; 5880 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5881 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5882 "jenks_curvature", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5883 sc, TRACKPOINT_SYSCTL_JENKS_CURVATURE, 5884 trackpoint_sysctl, "I", 5885 "Jenks curvature"); 5886 5887 /* hw.psm.trackpoint.z_time */ 5888 sc->tpinfo.ztime = 0x26; 5889 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5890 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5891 "z_time", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5892 sc, TRACKPOINT_SYSCTL_Z_TIME, 5893 trackpoint_sysctl, "I", 5894 "Z time constant"); 5895 5896 /* hw.psm.trackpoint.press_to_select */ 5897 sc->tpinfo.pts = 0x00; 5898 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5899 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5900 "press_to_select", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5901 sc, TRACKPOINT_SYSCTL_PRESS_TO_SELECT, 5902 trackpoint_sysctl, "I", 5903 "Press to Select"); 5904 5905 /* hw.psm.trackpoint.skip_backups */ 5906 sc->tpinfo.skipback = 0x00; 5907 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 5908 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 5909 "skip_backups", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 5910 sc, TRACKPOINT_SYSCTL_SKIP_BACKUPS, 5911 trackpoint_sysctl, "I", 5912 "Skip backups from drags"); 5913 } 5914 5915 static void 5916 set_trackpoint_parameters(struct psm_softc *sc) 5917 { 5918 trackpoint_command(sc, 0x81, 0x4a, sc->tpinfo.sensitivity); 5919 trackpoint_command(sc, 0x81, 0x60, sc->tpinfo.uplateau); 5920 trackpoint_command(sc, 0x81, 0x4d, sc->tpinfo.inertia); 5921 trackpoint_command(sc, 0x81, 0x57, sc->tpinfo.reach); 5922 trackpoint_command(sc, 0x81, 0x58, sc->tpinfo.draghys); 5923 trackpoint_command(sc, 0x81, 0x59, sc->tpinfo.mindrag); 5924 trackpoint_command(sc, 0x81, 0x5a, sc->tpinfo.upthresh); 5925 trackpoint_command(sc, 0x81, 0x5c, sc->tpinfo.threshold); 5926 trackpoint_command(sc, 0x81, 0x5d, sc->tpinfo.jenks); 5927 trackpoint_command(sc, 0x81, 0x5e, sc->tpinfo.ztime); 5928 if (sc->tpinfo.pts == 0x01) 5929 trackpoint_command(sc, 0x47, 0x2c, 0x01); 5930 if (sc->tpinfo.skipback == 0x01) 5931 trackpoint_command(sc, 0x47, 0x2d, 0x08); 5932 } 5933 5934 static int 5935 enable_trackpoint(struct psm_softc *sc, enum probearg arg) 5936 { 5937 KBDC kbdc = sc->kbdc; 5938 int id; 5939 5940 /* 5941 * If called from enable_synaptics(), make sure that passthrough 5942 * mode is enabled so we can reach the trackpoint. 5943 * However, passthrough mode must be disabled before setting the 5944 * trackpoint parameters, as rackpoint_command() enables and disables 5945 * passthrough mode on its own. 5946 */ 5947 if (sc->synhw.capPassthrough) 5948 synaptics_passthrough_on(sc); 5949 5950 if (send_aux_command(kbdc, 0xe1) != PSM_ACK || 5951 read_aux_data(kbdc) != 0x01) 5952 goto no_trackpoint; 5953 id = read_aux_data(kbdc); 5954 if (id < 0x01) 5955 goto no_trackpoint; 5956 if (arg == PROBE) 5957 sc->tphw = id; 5958 if (!trackpoint_support) 5959 goto no_trackpoint; 5960 5961 if (sc->synhw.capPassthrough) 5962 synaptics_passthrough_off(sc); 5963 5964 if (arg == PROBE) { 5965 trackpoint_sysctl_create_tree(sc); 5966 /* 5967 * Don't overwrite hwid and buttons when we are 5968 * a guest device. 5969 */ 5970 if (!sc->synhw.capPassthrough) { 5971 sc->hw.hwid = id; 5972 sc->hw.buttons = 3; 5973 } 5974 } 5975 5976 set_trackpoint_parameters(sc); 5977 5978 return (TRUE); 5979 5980 no_trackpoint: 5981 if (sc->synhw.capPassthrough) 5982 synaptics_passthrough_off(sc); 5983 5984 return (FALSE); 5985 } 5986 5987 /* Interlink electronics VersaPad */ 5988 static int 5989 enable_versapad(struct psm_softc *sc, enum probearg arg) 5990 { 5991 KBDC kbdc = sc->kbdc; 5992 int data[3]; 5993 5994 set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */ 5995 set_mouse_sampling_rate(kbdc, 100); /* set rate 100 */ 5996 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5997 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5998 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5999 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6000 if (get_mouse_status(kbdc, data, 0, 3) < 3) /* get status */ 6001 return (FALSE); 6002 if (data[2] != 0xa || data[1] != 0 ) /* rate == 0xa && res. == 0 */ 6003 return (FALSE); 6004 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 6005 6006 return (TRUE); /* PS/2 absolute mode */ 6007 } 6008 6009 /* Elantech Touchpad */ 6010 static int 6011 elantech_read_1(KBDC kbdc, int hwversion, int reg, int *val) 6012 { 6013 int res, readcmd, retidx; 6014 int resp[3]; 6015 6016 readcmd = hwversion == 2 ? ELANTECH_REG_READ : ELANTECH_REG_RDWR; 6017 retidx = hwversion == 4 ? 1 : 0; 6018 6019 res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6020 res |= send_aux_command(kbdc, readcmd) != PSM_ACK; 6021 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6022 res |= send_aux_command(kbdc, reg) != PSM_ACK; 6023 res |= get_mouse_status(kbdc, resp, 0, 3) != 3; 6024 6025 if (res == 0) 6026 *val = resp[retidx]; 6027 6028 return (res); 6029 } 6030 6031 static int 6032 elantech_write_1(KBDC kbdc, int hwversion, int reg, int val) 6033 { 6034 int res, writecmd; 6035 6036 writecmd = hwversion == 2 ? ELANTECH_REG_WRITE : ELANTECH_REG_RDWR; 6037 6038 res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6039 res |= send_aux_command(kbdc, writecmd) != PSM_ACK; 6040 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6041 res |= send_aux_command(kbdc, reg) != PSM_ACK; 6042 if (hwversion == 4) { 6043 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6044 res |= send_aux_command(kbdc, writecmd) != PSM_ACK; 6045 } 6046 res |= send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6047 res |= send_aux_command(kbdc, val) != PSM_ACK; 6048 res |= set_mouse_scaling(kbdc, 1) == 0; 6049 6050 return (res); 6051 } 6052 6053 static int 6054 elantech_cmd(KBDC kbdc, int hwversion, int cmd, int *resp) 6055 { 6056 int res; 6057 6058 if (hwversion == 2) { 6059 res = set_mouse_scaling(kbdc, 1) == 0; 6060 res |= mouse_ext_command(kbdc, cmd) == 0; 6061 } else { 6062 res = send_aux_command(kbdc, ELANTECH_CUSTOM_CMD) != PSM_ACK; 6063 res |= send_aux_command(kbdc, cmd) != PSM_ACK; 6064 } 6065 res |= get_mouse_status(kbdc, resp, 0, 3) != 3; 6066 6067 return (res); 6068 } 6069 6070 static int 6071 elantech_init(KBDC kbdc, elantechhw_t *elanhw) 6072 { 6073 int i, val, res, hwversion, reg10; 6074 6075 /* set absolute mode */ 6076 hwversion = elanhw->hwversion; 6077 reg10 = -1; 6078 switch (hwversion) { 6079 case 2: 6080 reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4; 6081 res = elantech_write_1(kbdc, hwversion, 0x10, reg10); 6082 if (res) 6083 break; 6084 res = elantech_write_1(kbdc, hwversion, 0x11, 0x8A); 6085 break; 6086 case 3: 6087 reg10 = 0x0b; 6088 res = elantech_write_1(kbdc, hwversion, 0x10, reg10); 6089 break; 6090 case 4: 6091 res = elantech_write_1(kbdc, hwversion, 0x07, 0x01); 6092 break; 6093 default: 6094 res = 1; 6095 } 6096 6097 /* Read back reg 0x10 to ensure hardware is ready. */ 6098 if (res == 0 && reg10 >= 0) { 6099 for (i = 0; i < 5; i++) { 6100 if (elantech_read_1(kbdc, hwversion, 0x10, &val) == 0) 6101 break; 6102 DELAY(2000); 6103 } 6104 if (i == 5) 6105 res = 1; 6106 } 6107 6108 if (res) 6109 kprintf("couldn't set absolute mode\n"); 6110 6111 return (res); 6112 } 6113 6114 static void 6115 elantech_init_synaptics(struct psm_softc *sc) 6116 { 6117 6118 /* Set capabilites required by movement smother */ 6119 sc->synhw.infoMajor = sc->elanhw.hwversion; 6120 sc->synhw.infoMinor = sc->elanhw.fwversion; 6121 sc->synhw.infoXupmm = sc->elanhw.dpmmx; 6122 sc->synhw.infoYupmm = sc->elanhw.dpmmy; 6123 sc->synhw.verticalScroll = 0; 6124 sc->synhw.nExtendedQueries = 4; 6125 sc->synhw.capExtended = 1; 6126 sc->synhw.capPassthrough = sc->elanhw.hastrackpoint; 6127 sc->synhw.capClickPad = sc->elanhw.isclickpad; 6128 sc->synhw.capMultiFinger = 1; 6129 sc->synhw.capAdvancedGestures = 1; 6130 sc->synhw.capPalmDetect = 1; 6131 sc->synhw.capPen = 0; 6132 sc->synhw.capReportsMax = 1; 6133 sc->synhw.maximumXCoord = sc->elanhw.sizex; 6134 sc->synhw.maximumYCoord = sc->elanhw.sizey; 6135 sc->synhw.capReportsMin = 1; 6136 sc->synhw.minimumXCoord = 0; 6137 sc->synhw.minimumYCoord = 0; 6138 6139 if (sc->syninfo.sysctl_tree == NULL) { 6140 synaptics_sysctl_create_tree(sc, "elantech", 6141 "Elantech Touchpad"); 6142 6143 /* 6144 * Adjust synaptic smoother tunables 6145 * 1. Disable finger detection pressure threshold. Unlike 6146 * synaptics we assume the finger is acting when packet with 6147 * its X&Y arrives not when pressure exceedes some threshold 6148 * 2. Disable unrelated features like margins and noisy areas 6149 * 3. Disable virtual scroll areas as 2nd finger is preferable 6150 * 4. For clickpads set bottom quarter as 42% - 16% - 42% sized 6151 * softbuttons 6152 * 5. Scale down divisors and movement lengths by a factor of 3 6153 * where 3 is Synaptics to Elantech (~2200/800) dpi ratio 6154 */ 6155 6156 /* Set reporting range to be equal touchpad size */ 6157 sc->syninfo.max_x = sc->elanhw.sizex; 6158 sc->syninfo.max_y = sc->elanhw.sizey; 6159 6160 /* Disable finger detection pressure threshold */ 6161 sc->syninfo.min_pressure = 1; 6162 6163 /* Use full area of touchpad */ 6164 sc->syninfo.margin_top = 0; 6165 sc->syninfo.margin_right = 0; 6166 sc->syninfo.margin_bottom = 0; 6167 sc->syninfo.margin_left = 0; 6168 6169 /* Disable noisy area */ 6170 sc->syninfo.na_top = 0; 6171 sc->syninfo.na_right = 0; 6172 sc->syninfo.na_bottom = 0; 6173 sc->syninfo.na_left = 0; 6174 6175 /* Tune divisors and movement lengths */ 6176 sc->syninfo.weight_len_squared = 200; 6177 sc->syninfo.div_min = 3; 6178 sc->syninfo.div_max = 6; 6179 sc->syninfo.div_max_na = 10; 6180 sc->syninfo.div_len = 30; 6181 sc->syninfo.tap_max_delta = 25; 6182 6183 /* Disable virtual scrolling areas and tune its divisors */ 6184 sc->syninfo.vscroll_hor_area = 0; 6185 sc->syninfo.vscroll_ver_area = 0; 6186 sc->syninfo.vscroll_min_delta = 15; 6187 sc->syninfo.vscroll_div_min = 30; 6188 sc->syninfo.vscroll_div_max = 50; 6189 6190 /* Set bottom quarter as 42% - 16% - 42% sized softbuttons */ 6191 if (sc->elanhw.isclickpad) { 6192 sc->syninfo.softbuttons_y = sc->elanhw.sizey / 4; 6193 sc->syninfo.softbutton2_x = sc->elanhw.sizex * 11 / 25; 6194 sc->syninfo.softbutton3_x = sc->elanhw.sizex * 14 / 25; 6195 } 6196 } 6197 6198 return; 6199 } 6200 6201 static int 6202 enable_elantech(struct psm_softc *sc, enum probearg arg) 6203 { 6204 static const int ic2hw[] = 6205 /*IC: 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 6206 { 0, 0, 2, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0 }; 6207 elantechhw_t elanhw; 6208 int icversion, hwversion, dptracex, dptracey, id, resp[3], dpix, dpiy; 6209 KBDC kbdc = sc->kbdc; 6210 6211 VLOG(3, (LOG_DEBUG, "elantech: BEGIN init\n")); 6212 6213 set_mouse_scaling(kbdc, 1); 6214 set_mouse_scaling(kbdc, 1); 6215 set_mouse_scaling(kbdc, 1); 6216 if (get_mouse_status(kbdc, resp, 0, 3) != 3) 6217 return (FALSE); 6218 6219 if (!ELANTECH_MAGIC(resp)) 6220 return (FALSE); 6221 6222 /* Identify the Touchpad version. */ 6223 if (elantech_cmd(kbdc, 2, ELANTECH_FW_VERSION, resp)) 6224 return (FALSE); 6225 6226 bzero(&elanhw, sizeof(elanhw)); 6227 6228 elanhw.fwversion = (resp[0] << 16) | (resp[1] << 8) | resp[2]; 6229 icversion = resp[0] & 0x0f; 6230 hwversion = ic2hw[icversion]; 6231 6232 if (verbose >= 2) 6233 kprintf("Elantech touchpad hardware v.%d firmware v.0x%06x\n", 6234 hwversion, elanhw.fwversion); 6235 6236 if (ELANTECH_HW_IS_V1(elanhw.fwversion)) { 6237 kprintf (" Unsupported touchpad hardware (v1)\n"); 6238 return (FALSE); 6239 } 6240 if (hwversion == 0) { 6241 kprintf (" Unknown touchpad hardware (firmware v.0x%06x)\n", 6242 elanhw.fwversion); 6243 return (FALSE); 6244 } 6245 6246 /* Get the Touchpad model information. */ 6247 elanhw.hwversion = hwversion; 6248 elanhw.issemimt = hwversion == 2; 6249 elanhw.isclickpad = (resp[1] & 0x10) != 0; 6250 elanhw.hascrc = (resp[1] & 0x40) != 0; 6251 elanhw.haspressure = elanhw.fwversion >= 0x020800; 6252 6253 /* Read the capability bits. */ 6254 if (elantech_cmd(kbdc, hwversion, ELANTECH_CAPABILITIES, resp) != 0) { 6255 kprintf(" Failed to read capability bits\n"); 6256 return (FALSE); 6257 } 6258 6259 elanhw.ntracesx = resp[1] - 1; 6260 elanhw.ntracesy = resp[2] - 1; 6261 elanhw.hastrackpoint = (resp[0] & 0x80) != 0; 6262 6263 /* Get the touchpad resolution */ 6264 switch (hwversion) { 6265 case 4: 6266 if (elantech_cmd(kbdc, hwversion, ELANTECH_RESOLUTION, resp) 6267 == 0) { 6268 dpix = (resp[1] & 0x0f) * 10 + 790; 6269 dpiy = ((resp[1] & 0xf0) >> 4) * 10 + 790; 6270 elanhw.dpmmx = (dpix * 10 + 5) / 254; 6271 elanhw.dpmmy = (dpiy * 10 + 5) / 254; 6272 break; 6273 } 6274 /* FALLTHROUGH */ 6275 case 2: 6276 case 3: 6277 elanhw.dpmmx = elanhw.dpmmy = 32; /* 800 dpi */ 6278 break; 6279 } 6280 6281 if (!elantech_support) 6282 return (FALSE); 6283 6284 if (elantech_init(kbdc, &elanhw)) { 6285 kprintf("couldn't initialize elantech touchpad\n"); 6286 return (FALSE); 6287 } 6288 6289 /* 6290 * Get the touchpad reporting range. 6291 * On HW v.3 touchpads it should be done after switching hardware 6292 * to real resolution mode (by setting bit 3 of reg10) 6293 */ 6294 if (elantech_cmd(kbdc, hwversion, ELANTECH_FW_ID, resp) != 0) { 6295 kprintf(" Failed to read touchpad size\n"); 6296 elanhw.sizex = 10000; /* Arbitrary high values to */ 6297 elanhw.sizey = 10000; /* prevent clipping in smoother */ 6298 } else if (hwversion == 2) { 6299 dptracex = dptracey = 64; 6300 if ((elanhw.fwversion >> 16) == 0x14 && (resp[1] & 0x10) && 6301 !elantech_cmd(kbdc, hwversion, ELANTECH_SAMPLE, resp)) { 6302 dptracex = resp[1] / 2; 6303 dptracey = resp[2] / 2; 6304 } 6305 elanhw.sizex = (elanhw.ntracesx - 1) * dptracex; 6306 elanhw.sizey = (elanhw.ntracesy - 1) * dptracey; 6307 } else { 6308 elanhw.sizex = (resp[0] & 0x0f) << 8 | resp[1]; 6309 elanhw.sizey = (resp[0] & 0xf0) << 4 | resp[2]; 6310 } 6311 6312 if (verbose >= 2) { 6313 kprintf(" Model information:\n"); 6314 kprintf(" MaxX: %d\n", elanhw.sizex); 6315 kprintf(" MaxY: %d\n", elanhw.sizey); 6316 kprintf(" DpmmX: %d\n", elanhw.dpmmx); 6317 kprintf(" DpmmY: %d\n", elanhw.dpmmy); 6318 kprintf(" TracesX: %d\n", elanhw.ntracesx); 6319 kprintf(" TracesY: %d\n", elanhw.ntracesy); 6320 kprintf(" SemiMT: %d\n", elanhw.issemimt); 6321 kprintf(" Clickpad: %d\n", elanhw.isclickpad); 6322 kprintf(" Trackpoint: %d\n", elanhw.hastrackpoint); 6323 kprintf(" CRC: %d\n", elanhw.hascrc); 6324 kprintf(" Pressure: %d\n", elanhw.haspressure); 6325 } 6326 6327 VLOG(3, (LOG_DEBUG, "elantech: END init\n")); 6328 6329 if (arg == PROBE) { 6330 sc->elanhw = elanhw; 6331 sc->hw.buttons = 3; 6332 6333 /* Initialize synaptics movement smoother */ 6334 elantech_init_synaptics(sc); 6335 6336 for (id = 0; id < ELANTECH_MAX_FINGERS; id++) 6337 PSM_FINGER_RESET(sc->elanaction.fingers[id]); 6338 } 6339 return (TRUE); 6340 } 6341 6342 /* 6343 * Return true if 'now' is earlier than (start + (secs.usecs)). 6344 * Now may be NULL and the function will fetch the current time from 6345 * getmicrouptime(), or a cached 'now' can be passed in. 6346 * All values should be numbers derived from getmicrouptime(). 6347 */ 6348 static int 6349 timeelapsed(const struct timeval *start, int secs, int usecs, 6350 const struct timeval *now) { 6351 struct timeval snow, tv; 6352 6353 /* if there is no 'now' passed in, the get it as a convenience. */ 6354 if (now == NULL) { 6355 getmicrouptime(&snow); 6356 now = &snow; 6357 } 6358 6359 tv.tv_sec = secs; 6360 tv.tv_usec = usecs; 6361 timevaladd(&tv, start); 6362 return (timevalcmp(&tv, now, <)); 6363 } 6364 6365 static int 6366 psmresume(device_t dev) 6367 { 6368 6369 struct psm_softc *sc = device_get_softc(dev); 6370 int unit = device_get_unit(dev); 6371 int err; 6372 6373 VLOG(2, (LOG_NOTICE, "psm%d: system resume hook called.\n", unit)); 6374 6375 if ((sc->config & 6376 (PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND)) == 0) 6377 return (0); 6378 6379 err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND); 6380 6381 if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) { 6382 /* 6383 * Release the blocked process; it must be notified that 6384 * the device cannot be accessed anymore. 6385 */ 6386 sc->state &= ~PSM_ASLP; 6387 wakeup(sc); 6388 } 6389 6390 VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit)); 6391 6392 return (err); 6393 } 6394 6395 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, NULL, NULL); 6396 6397 #ifdef DEV_ISA 6398 #if 0 6399 /* 6400 * This sucks up assignments from PNPBIOS and ACPI. 6401 */ 6402 6403 /* 6404 * When the PS/2 mouse device is reported by ACPI or PnP BIOS, it may 6405 * appear BEFORE the AT keyboard controller. As the PS/2 mouse device 6406 * can be probed and attached only after the AT keyboard controller is 6407 * attached, we shall quietly reserve the IRQ resource for later use. 6408 * If the PS/2 mouse device is reported to us AFTER the keyboard controller, 6409 * copy the IRQ resource to the PS/2 mouse device instance hanging 6410 * under the keyboard controller, then probe and attach it. 6411 */ 6412 6413 static devclass_t psmcpnp_devclass; 6414 6415 static device_probe_t psmcpnp_probe; 6416 static device_attach_t psmcpnp_attach; 6417 6418 static device_method_t psmcpnp_methods[] = { 6419 DEVMETHOD(device_probe, psmcpnp_probe), 6420 DEVMETHOD(device_attach, psmcpnp_attach), 6421 6422 { 0, 0 } 6423 }; 6424 6425 static driver_t psmcpnp_driver = { 6426 PSMCPNP_DRIVER_NAME, 6427 psmcpnp_methods, 6428 1, /* no softc */ 6429 }; 6430 6431 static struct isa_pnp_id psmcpnp_ids[] = { 6432 { 0x030fd041, "PS/2 mouse port" }, /* PNP0F03 */ 6433 { 0x0e0fd041, "PS/2 mouse port" }, /* PNP0F0E */ 6434 { 0x120fd041, "PS/2 mouse port" }, /* PNP0F12 */ 6435 { 0x130fd041, "PS/2 mouse port" }, /* PNP0F13 */ 6436 { 0x1303d041, "PS/2 port" }, /* PNP0313, XXX */ 6437 { 0x02002e4f, "Dell PS/2 mouse port" }, /* Lat. X200, Dell */ 6438 { 0x0002a906, "ALPS Glide Point" }, /* ALPS Glide Point */ 6439 { 0x80374d24, "IBM PS/2 mouse port" }, /* IBM3780, ThinkPad */ 6440 { 0x81374d24, "IBM PS/2 mouse port" }, /* IBM3781, ThinkPad */ 6441 { 0x0190d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9001, Vaio */ 6442 { 0x0290d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9002, Vaio */ 6443 { 0x0390d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9003, Vaio */ 6444 { 0x0490d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9004, Vaio */ 6445 { 0 } 6446 }; 6447 6448 static int 6449 create_a_copy(device_t atkbdc, device_t me) 6450 { 6451 6452 device_t psm; 6453 u_long irq; 6454 6455 /* find the PS/2 mouse device instance under the keyboard controller */ 6456 psm = device_find_child(atkbdc, PSM_DRIVER_NAME, 6457 device_get_unit(atkbdc)); 6458 if (psm == NULL) 6459 return (ENXIO); 6460 if (device_get_state(psm) != DS_NOTPRESENT) 6461 return (0); 6462 6463 /* move our resource to the found device */ 6464 irq = bus_get_resource_start(me, SYS_RES_IRQ, 0); 6465 bus_delete_resource(me, SYS_RES_IRQ, 0); 6466 bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1, 6467 machintr_legacy_intr_cpuid(irq)); 6468 6469 /* ...then probe and attach it */ 6470 return (device_probe_and_attach(psm)); 6471 } 6472 6473 static int 6474 psmcpnp_probe(device_t dev) 6475 { 6476 struct resource *res; 6477 u_long irq; 6478 int rid; 6479 6480 if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids)) 6481 return (ENXIO); 6482 6483 /* 6484 * The PnP BIOS and ACPI are supposed to assign an IRQ (12) 6485 * to the PS/2 mouse device node. But, some buggy PnP BIOS 6486 * declares the PS/2 mouse device node without an IRQ resource! 6487 * If this happens, we shall refer to device hints. 6488 * If we still don't find it there, use a hardcoded value... XXX 6489 */ 6490 rid = 0; 6491 irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid); 6492 if (irq <= 0) { 6493 if (resource_long_value(PSM_DRIVER_NAME, 6494 device_get_unit(dev),"irq", &irq) != 0) 6495 irq = 12; /* XXX */ 6496 device_printf(dev, "irq resource info is missing; " 6497 "assuming irq %ld\n", irq); 6498 bus_set_resource(dev, SYS_RES_IRQ, rid, irq, 1, 6499 machintr_legacy_intr_cpuid(irq)); 6500 } 6501 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE); 6502 bus_release_resource(dev, SYS_RES_IRQ, rid, res); 6503 6504 /* keep quiet */ 6505 if (!bootverbose) 6506 device_quiet(dev); 6507 6508 return ((res == NULL) ? ENXIO : 0); 6509 } 6510 6511 static int 6512 psmcpnp_attach(device_t dev) 6513 { 6514 device_t atkbdc; 6515 6516 /* find the keyboard controller, which may be on acpi* or isa* bus */ 6517 atkbdc = devclass_get_device(devclass_find(ATKBDC_DRIVER_NAME), 6518 device_get_unit(dev)); 6519 if ((atkbdc != NULL) && (device_get_state(atkbdc) == DS_ATTACHED)) { 6520 create_a_copy(atkbdc, dev); 6521 } else { 6522 /* 6523 * If we don't have the AT keyboard controller yet, 6524 * just reserve the IRQ for later use... 6525 * (See psmidentify() above.) 6526 */ 6527 rid = 0; 6528 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE); 6529 } 6530 6531 return (0); 6532 } 6533 6534 DRIVER_MODULE(psmcpnp, isa, psmcpnp_driver, psmcpnp_devclass, NULL, NULL); 6535 DRIVER_MODULE(psmcpnp, acpi, psmcpnp_driver, psmcpnp_devclass, NULL, NULL); 6536 6537 #endif 6538 #endif /* DEV_ISA */ 6539