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