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 61 #include <sys/cdefs.h> 62 __FBSDID("$FreeBSD$"); 63 64 #include "opt_isa.h" 65 #include "opt_psm.h" 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/kernel.h> 70 #include <sys/module.h> 71 #include <sys/bus.h> 72 #include <sys/conf.h> 73 #include <sys/filio.h> 74 #include <sys/poll.h> 75 #include <sys/sigio.h> 76 #include <sys/signalvar.h> 77 #include <sys/syslog.h> 78 #include <machine/bus.h> 79 #include <sys/rman.h> 80 #include <sys/selinfo.h> 81 #include <sys/sysctl.h> 82 #include <sys/time.h> 83 #include <sys/uio.h> 84 85 #include <sys/limits.h> 86 #include <sys/mouse.h> 87 #include <machine/resource.h> 88 89 #ifdef DEV_ISA 90 #include <isa/isavar.h> 91 #endif 92 93 #include <dev/atkbdc/atkbdcreg.h> 94 #include <dev/atkbdc/psm.h> 95 96 /* 97 * Driver specific options: the following options may be set by 98 * `options' statements in the kernel configuration file. 99 */ 100 101 /* debugging */ 102 #ifndef PSM_DEBUG 103 #define PSM_DEBUG 0 /* 104 * logging: 0: none, 1: brief, 2: verbose 105 * 3: sync errors, 4: all packets 106 */ 107 #endif 108 #define VLOG(level, args) do { \ 109 if (verbose >= level) \ 110 log args; \ 111 } while (0) 112 113 #ifndef PSM_INPUT_TIMEOUT 114 #define PSM_INPUT_TIMEOUT 2000000 /* 2 sec */ 115 #endif 116 117 #ifndef PSM_TAP_TIMEOUT 118 #define PSM_TAP_TIMEOUT 125000 119 #endif 120 121 #ifndef PSM_TAP_THRESHOLD 122 #define PSM_TAP_THRESHOLD 25 123 #endif 124 125 /* end of driver specific options */ 126 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_NATIVE 2 137 #define PSM_LEVEL_MIN PSM_LEVEL_BASE 138 #define PSM_LEVEL_MAX PSM_LEVEL_NATIVE 139 140 /* Logitech PS2++ protocol */ 141 #define MOUSE_PS2PLUS_CHECKBITS(b) \ 142 ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f)) 143 #define MOUSE_PS2PLUS_PACKET_TYPE(b) \ 144 (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4)) 145 146 /* ring buffer */ 147 typedef struct ringbuf { 148 int count; /* # of valid elements in the buffer */ 149 int head; /* head pointer */ 150 int tail; /* tail poiner */ 151 u_char buf[PSM_BUFSIZE]; 152 } ringbuf_t; 153 154 /* data buffer */ 155 typedef struct packetbuf { 156 u_char ipacket[16]; /* interim input buffer */ 157 int inputbytes; /* # of bytes in the input buffer */ 158 } packetbuf_t; 159 160 #ifndef PSM_PACKETQUEUE 161 #define PSM_PACKETQUEUE 128 162 #endif 163 164 enum { 165 SYNAPTICS_SYSCTL_MIN_PRESSURE, 166 SYNAPTICS_SYSCTL_MAX_PRESSURE, 167 SYNAPTICS_SYSCTL_MAX_WIDTH, 168 SYNAPTICS_SYSCTL_MARGIN_TOP, 169 SYNAPTICS_SYSCTL_MARGIN_RIGHT, 170 SYNAPTICS_SYSCTL_MARGIN_BOTTOM, 171 SYNAPTICS_SYSCTL_MARGIN_LEFT, 172 SYNAPTICS_SYSCTL_NA_TOP, 173 SYNAPTICS_SYSCTL_NA_RIGHT, 174 SYNAPTICS_SYSCTL_NA_BOTTOM, 175 SYNAPTICS_SYSCTL_NA_LEFT, 176 SYNAPTICS_SYSCTL_WINDOW_MIN, 177 SYNAPTICS_SYSCTL_WINDOW_MAX, 178 SYNAPTICS_SYSCTL_MULTIPLICATOR, 179 SYNAPTICS_SYSCTL_WEIGHT_CURRENT, 180 SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, 181 SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, 182 SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, 183 SYNAPTICS_SYSCTL_DIV_MIN, 184 SYNAPTICS_SYSCTL_DIV_MAX, 185 SYNAPTICS_SYSCTL_DIV_MAX_NA, 186 SYNAPTICS_SYSCTL_DIV_LEN, 187 SYNAPTICS_SYSCTL_TAP_MAX_DELTA, 188 SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, 189 SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, 190 SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, 191 SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, 192 SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, 193 SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, 194 SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, 195 SYNAPTICS_SYSCTL_TOUCHPAD_OFF 196 }; 197 198 typedef struct synapticsinfo { 199 struct sysctl_ctx_list sysctl_ctx; 200 struct sysctl_oid *sysctl_tree; 201 int directional_scrolls; 202 int two_finger_scroll; 203 int min_pressure; 204 int max_pressure; 205 int max_width; 206 int margin_top; 207 int margin_right; 208 int margin_bottom; 209 int margin_left; 210 int na_top; 211 int na_right; 212 int na_bottom; 213 int na_left; 214 int window_min; 215 int window_max; 216 int multiplicator; 217 int weight_current; 218 int weight_previous; 219 int weight_previous_na; 220 int weight_len_squared; 221 int div_min; 222 int div_max; 223 int div_max_na; 224 int div_len; 225 int tap_max_delta; 226 int tap_min_queue; 227 int taphold_timeout; 228 int vscroll_ver_area; 229 int vscroll_hor_area; 230 int vscroll_min_delta; 231 int vscroll_div_min; 232 int vscroll_div_max; 233 int touchpad_off; 234 } synapticsinfo_t; 235 236 typedef struct synapticspacket { 237 int x; 238 int y; 239 } synapticspacket_t; 240 241 #define SYNAPTICS_PACKETQUEUE 10 242 #define SYNAPTICS_QUEUE_CURSOR(x) \ 243 (x + SYNAPTICS_PACKETQUEUE) % SYNAPTICS_PACKETQUEUE 244 245 #define SYNAPTICS_VERSION_GE(synhw, major, minor) \ 246 ((synhw).infoMajor > (major) || \ 247 ((synhw).infoMajor == (major) && (synhw).infoMinor >= (minor))) 248 249 typedef struct synapticsaction { 250 synapticspacket_t queue[SYNAPTICS_PACKETQUEUE]; 251 int queue_len; 252 int queue_cursor; 253 int window_min; 254 int start_x; 255 int start_y; 256 int avg_dx; 257 int avg_dy; 258 int squelch_x; 259 int squelch_y; 260 int fingers_nb; 261 int tap_button; 262 int in_taphold; 263 int in_vscroll; 264 } synapticsaction_t; 265 266 enum { 267 TRACKPOINT_SYSCTL_SENSITIVITY, 268 TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, 269 TRACKPOINT_SYSCTL_UPPER_PLATEAU, 270 TRACKPOINT_SYSCTL_BACKUP_RANGE, 271 TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, 272 TRACKPOINT_SYSCTL_MINIMUM_DRAG, 273 TRACKPOINT_SYSCTL_UP_THRESHOLD, 274 TRACKPOINT_SYSCTL_THRESHOLD, 275 TRACKPOINT_SYSCTL_JENKS_CURVATURE, 276 TRACKPOINT_SYSCTL_Z_TIME, 277 TRACKPOINT_SYSCTL_PRESS_TO_SELECT, 278 TRACKPOINT_SYSCTL_SKIP_BACKUPS 279 }; 280 281 typedef struct trackpointinfo { 282 struct sysctl_ctx_list sysctl_ctx; 283 struct sysctl_oid *sysctl_tree; 284 int sensitivity; 285 int inertia; 286 int uplateau; 287 int reach; 288 int draghys; 289 int mindrag; 290 int upthresh; 291 int threshold; 292 int jenks; 293 int ztime; 294 int pts; 295 int skipback; 296 } trackpointinfo_t; 297 298 /* driver control block */ 299 struct psm_softc { /* Driver status information */ 300 int unit; 301 struct selinfo rsel; /* Process selecting for Input */ 302 u_char state; /* Mouse driver state */ 303 int config; /* driver configuration flags */ 304 int flags; /* other flags */ 305 KBDC kbdc; /* handle to access kbd controller */ 306 struct resource *intr; /* IRQ resource */ 307 void *ih; /* interrupt handle */ 308 mousehw_t hw; /* hardware information */ 309 synapticshw_t synhw; /* Synaptics hardware information */ 310 synapticsinfo_t syninfo; /* Synaptics configuration */ 311 synapticsaction_t synaction; /* Synaptics action context */ 312 int tphw; /* TrackPoint hardware information */ 313 trackpointinfo_t tpinfo; /* TrackPoint configuration */ 314 mousemode_t mode; /* operation mode */ 315 mousemode_t dflt_mode; /* default operation mode */ 316 mousestatus_t status; /* accumulated mouse movement */ 317 ringbuf_t queue; /* mouse status queue */ 318 packetbuf_t pqueue[PSM_PACKETQUEUE]; /* mouse data queue */ 319 int pqueue_start; /* start of data in queue */ 320 int pqueue_end; /* end of data in queue */ 321 int button; /* the latest button state */ 322 int xold; /* previous absolute X position */ 323 int yold; /* previous absolute Y position */ 324 int xaverage; /* average X position */ 325 int yaverage; /* average Y position */ 326 int squelch; /* level to filter movement at low speed */ 327 int zmax; /* maximum pressure value for touchpads */ 328 int syncerrors; /* # of bytes discarded to synchronize */ 329 int pkterrors; /* # of packets failed during quaranteen. */ 330 struct timeval inputtimeout; 331 struct timeval lastsoftintr; /* time of last soft interrupt */ 332 struct timeval lastinputerr; /* time last sync error happened */ 333 struct timeval taptimeout; /* tap timeout for touchpads */ 334 int watchdog; /* watchdog timer flag */ 335 struct callout callout; /* watchdog timer call out */ 336 struct callout softcallout; /* buffer timer call out */ 337 struct cdev *dev; 338 struct cdev *bdev; 339 int lasterr; 340 int cmdcount; 341 struct sigio *async; /* Processes waiting for SIGIO */ 342 int extended_buttons; 343 }; 344 static devclass_t psm_devclass; 345 346 /* driver state flags (state) */ 347 #define PSM_VALID 0x80 348 #define PSM_OPEN 1 /* Device is open */ 349 #define PSM_ASLP 2 /* Waiting for mouse data */ 350 #define PSM_SOFTARMED 4 /* Software interrupt armed */ 351 #define PSM_NEED_SYNCBITS 8 /* Set syncbits using next data pkt */ 352 353 /* driver configuration flags (config) */ 354 #define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ 355 #define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */ 356 #define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */ 357 #define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */ 358 #define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */ 359 #define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */ 360 #define PSM_CONFIG_IGNPORTERROR 0x1000 /* ignore error in aux port test */ 361 #define PSM_CONFIG_HOOKRESUME 0x2000 /* hook the system resume event */ 362 #define PSM_CONFIG_INITAFTERSUSPEND 0x4000 /* init the device at the resume event */ 363 364 #define PSM_CONFIG_FLAGS \ 365 (PSM_CONFIG_RESOLUTION | \ 366 PSM_CONFIG_ACCEL | \ 367 PSM_CONFIG_NOCHECKSYNC | \ 368 PSM_CONFIG_NOIDPROBE | \ 369 PSM_CONFIG_NORESET | \ 370 PSM_CONFIG_FORCETAP | \ 371 PSM_CONFIG_IGNPORTERROR | \ 372 PSM_CONFIG_HOOKRESUME | \ 373 PSM_CONFIG_INITAFTERSUSPEND) 374 375 /* other flags (flags) */ 376 #define PSM_FLAGS_FINGERDOWN 0x0001 /* VersaPad finger down */ 377 378 #define kbdcp(p) ((atkbdc_softc_t *)(p)) 379 #define ALWAYS_RESTORE_CONTROLLER(kbdc) !(kbdcp(kbdc)->quirks \ 380 & KBDC_QUIRK_KEEP_ACTIVATED) 381 382 /* Tunables */ 383 static int tap_enabled = -1; 384 TUNABLE_INT("hw.psm.tap_enabled", &tap_enabled); 385 386 static int synaptics_support = 0; 387 TUNABLE_INT("hw.psm.synaptics_support", &synaptics_support); 388 389 static int trackpoint_support = 0; 390 TUNABLE_INT("hw.psm.trackpoint_support", &trackpoint_support); 391 392 static int verbose = PSM_DEBUG; 393 TUNABLE_INT("debug.psm.loglevel", &verbose); 394 395 /* for backward compatibility */ 396 #define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t) 397 #define OLD_MOUSE_GETMODE _IOR('M', 2, old_mousemode_t) 398 #define OLD_MOUSE_SETMODE _IOW('M', 3, old_mousemode_t) 399 400 typedef struct old_mousehw { 401 int buttons; 402 int iftype; 403 int type; 404 int hwid; 405 } old_mousehw_t; 406 407 typedef struct old_mousemode { 408 int protocol; 409 int rate; 410 int resolution; 411 int accelfactor; 412 } old_mousemode_t; 413 414 /* packet formatting function */ 415 typedef int packetfunc_t(struct psm_softc *, u_char *, int *, int, 416 mousestatus_t *); 417 418 /* function prototypes */ 419 static void psmidentify(driver_t *, device_t); 420 static int psmprobe(device_t); 421 static int psmattach(device_t); 422 static int psmdetach(device_t); 423 static int psmresume(device_t); 424 425 static d_open_t psmopen; 426 static d_close_t psmclose; 427 static d_read_t psmread; 428 static d_write_t psmwrite; 429 static d_ioctl_t psmioctl; 430 static d_poll_t psmpoll; 431 432 static int enable_aux_dev(KBDC); 433 static int disable_aux_dev(KBDC); 434 static int get_mouse_status(KBDC, int *, int, int); 435 static int get_aux_id(KBDC); 436 static int set_mouse_sampling_rate(KBDC, int); 437 static int set_mouse_scaling(KBDC, int); 438 static int set_mouse_resolution(KBDC, int); 439 static int set_mouse_mode(KBDC); 440 static int get_mouse_buttons(KBDC); 441 static int is_a_mouse(int); 442 static void recover_from_error(KBDC); 443 static int restore_controller(KBDC, int); 444 static int doinitialize(struct psm_softc *, mousemode_t *); 445 static int doopen(struct psm_softc *, int); 446 static int reinitialize(struct psm_softc *, int); 447 static char *model_name(int); 448 static void psmsoftintr(void *); 449 static void psmintr(void *); 450 static void psmtimeout(void *); 451 static int timeelapsed(const struct timeval *, int, int, 452 const struct timeval *); 453 static void dropqueue(struct psm_softc *); 454 static void flushpackets(struct psm_softc *); 455 static void proc_mmanplus(struct psm_softc *, packetbuf_t *, 456 mousestatus_t *, int *, int *, int *); 457 static int proc_synaptics(struct psm_softc *, packetbuf_t *, 458 mousestatus_t *, int *, int *, int *); 459 static void proc_versapad(struct psm_softc *, packetbuf_t *, 460 mousestatus_t *, int *, int *, int *); 461 static int tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *, 462 u_char *); 463 464 /* vendor specific features */ 465 typedef int probefunc_t(KBDC, struct psm_softc *); 466 467 static int mouse_id_proc1(KBDC, int, int, int *); 468 static int mouse_ext_command(KBDC, int); 469 470 static probefunc_t enable_groller; 471 static probefunc_t enable_gmouse; 472 static probefunc_t enable_aglide; 473 static probefunc_t enable_kmouse; 474 static probefunc_t enable_msexplorer; 475 static probefunc_t enable_msintelli; 476 static probefunc_t enable_4dmouse; 477 static probefunc_t enable_4dplus; 478 static probefunc_t enable_mmanplus; 479 static probefunc_t enable_synaptics; 480 static probefunc_t enable_trackpoint; 481 static probefunc_t enable_versapad; 482 483 static void set_trackpoint_parameters(struct psm_softc *sc); 484 static void synaptics_passthrough_on(struct psm_softc *sc); 485 static void synaptics_passthrough_off(struct psm_softc *sc); 486 487 static struct { 488 int model; 489 u_char syncmask; 490 int packetsize; 491 probefunc_t *probefunc; 492 } vendortype[] = { 493 /* 494 * WARNING: the order of probe is very important. Don't mess it 495 * unless you know what you are doing. 496 */ 497 { MOUSE_MODEL_NET, /* Genius NetMouse */ 498 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_gmouse }, 499 { MOUSE_MODEL_NETSCROLL, /* Genius NetScroll */ 500 0xc8, 6, enable_groller }, 501 { MOUSE_MODEL_MOUSEMANPLUS, /* Logitech MouseMan+ */ 502 0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus }, 503 { MOUSE_MODEL_EXPLORER, /* Microsoft IntelliMouse Explorer */ 504 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msexplorer }, 505 { MOUSE_MODEL_4D, /* A4 Tech 4D Mouse */ 506 0x08, MOUSE_4D_PACKETSIZE, enable_4dmouse }, 507 { MOUSE_MODEL_4DPLUS, /* A4 Tech 4D+ Mouse */ 508 0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus }, 509 { MOUSE_MODEL_SYNAPTICS, /* Synaptics Touchpad */ 510 0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics }, 511 { MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ 512 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli }, 513 { MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ 514 0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide }, 515 { MOUSE_MODEL_THINK, /* Kensington ThinkingMouse */ 516 0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse }, 517 { MOUSE_MODEL_VERSAPAD, /* Interlink electronics VersaPad */ 518 0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad }, 519 { MOUSE_MODEL_TRACKPOINT, /* IBM/Lenovo TrackPoint */ 520 0xc0, MOUSE_PS2_PACKETSIZE, enable_trackpoint }, 521 { MOUSE_MODEL_GENERIC, 522 0xc0, MOUSE_PS2_PACKETSIZE, NULL }, 523 }; 524 #define GENERIC_MOUSE_ENTRY \ 525 ((sizeof(vendortype) / sizeof(*vendortype)) - 1) 526 527 /* device driver declarateion */ 528 static device_method_t psm_methods[] = { 529 /* Device interface */ 530 DEVMETHOD(device_identify, psmidentify), 531 DEVMETHOD(device_probe, psmprobe), 532 DEVMETHOD(device_attach, psmattach), 533 DEVMETHOD(device_detach, psmdetach), 534 DEVMETHOD(device_resume, psmresume), 535 536 { 0, 0 } 537 }; 538 539 static driver_t psm_driver = { 540 PSM_DRIVER_NAME, 541 psm_methods, 542 sizeof(struct psm_softc), 543 }; 544 545 static struct cdevsw psm_cdevsw = { 546 .d_version = D_VERSION, 547 .d_flags = D_NEEDGIANT, 548 .d_open = psmopen, 549 .d_close = psmclose, 550 .d_read = psmread, 551 .d_write = psmwrite, 552 .d_ioctl = psmioctl, 553 .d_poll = psmpoll, 554 .d_name = PSM_DRIVER_NAME, 555 }; 556 557 /* device I/O routines */ 558 static int 559 enable_aux_dev(KBDC kbdc) 560 { 561 int res; 562 563 res = send_aux_command(kbdc, PSMC_ENABLE_DEV); 564 VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res)); 565 566 return (res == PSM_ACK); 567 } 568 569 static int 570 disable_aux_dev(KBDC kbdc) 571 { 572 int res; 573 574 res = send_aux_command(kbdc, PSMC_DISABLE_DEV); 575 VLOG(2, (LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res)); 576 577 return (res == PSM_ACK); 578 } 579 580 static int 581 get_mouse_status(KBDC kbdc, int *status, int flag, int len) 582 { 583 int cmd; 584 int res; 585 int i; 586 587 switch (flag) { 588 case 0: 589 default: 590 cmd = PSMC_SEND_DEV_STATUS; 591 break; 592 case 1: 593 cmd = PSMC_SEND_DEV_DATA; 594 break; 595 } 596 empty_aux_buffer(kbdc, 5); 597 res = send_aux_command(kbdc, cmd); 598 VLOG(2, (LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n", 599 (flag == 1) ? "DATA" : "STATUS", res)); 600 if (res != PSM_ACK) 601 return (0); 602 603 for (i = 0; i < len; ++i) { 604 status[i] = read_aux_data(kbdc); 605 if (status[i] < 0) 606 break; 607 } 608 609 VLOG(1, (LOG_DEBUG, "psm: %s %02x %02x %02x\n", 610 (flag == 1) ? "data" : "status", status[0], status[1], status[2])); 611 612 return (i); 613 } 614 615 static int 616 get_aux_id(KBDC kbdc) 617 { 618 int res; 619 int id; 620 621 empty_aux_buffer(kbdc, 5); 622 res = send_aux_command(kbdc, PSMC_SEND_DEV_ID); 623 VLOG(2, (LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res)); 624 if (res != PSM_ACK) 625 return (-1); 626 627 /* 10ms delay */ 628 DELAY(10000); 629 630 id = read_aux_data(kbdc); 631 VLOG(2, (LOG_DEBUG, "psm: device ID: %04x\n", id)); 632 633 return (id); 634 } 635 636 static int 637 set_mouse_sampling_rate(KBDC kbdc, int rate) 638 { 639 int res; 640 641 res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate); 642 VLOG(2, (LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res)); 643 644 return ((res == PSM_ACK) ? rate : -1); 645 } 646 647 static int 648 set_mouse_scaling(KBDC kbdc, int scale) 649 { 650 int res; 651 652 switch (scale) { 653 case 1: 654 default: 655 scale = PSMC_SET_SCALING11; 656 break; 657 case 2: 658 scale = PSMC_SET_SCALING21; 659 break; 660 } 661 res = send_aux_command(kbdc, scale); 662 VLOG(2, (LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n", 663 (scale == PSMC_SET_SCALING21) ? "21" : "11", res)); 664 665 return (res == PSM_ACK); 666 } 667 668 /* `val' must be 0 through PSMD_MAX_RESOLUTION */ 669 static int 670 set_mouse_resolution(KBDC kbdc, int val) 671 { 672 int res; 673 674 res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val); 675 VLOG(2, (LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res)); 676 677 return ((res == PSM_ACK) ? val : -1); 678 } 679 680 /* 681 * NOTE: once `set_mouse_mode()' is called, the mouse device must be 682 * re-enabled by calling `enable_aux_dev()' 683 */ 684 static int 685 set_mouse_mode(KBDC kbdc) 686 { 687 int res; 688 689 res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE); 690 VLOG(2, (LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res)); 691 692 return (res == PSM_ACK); 693 } 694 695 static int 696 get_mouse_buttons(KBDC kbdc) 697 { 698 int c = 2; /* assume two buttons by default */ 699 int status[3]; 700 701 /* 702 * NOTE: a special sequence to obtain Logitech Mouse specific 703 * information: set resolution to 25 ppi, set scaling to 1:1, set 704 * scaling to 1:1, set scaling to 1:1. Then the second byte of the 705 * mouse status bytes is the number of available buttons. 706 * Some manufactures also support this sequence. 707 */ 708 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) 709 return (c); 710 if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) && 711 set_mouse_scaling(kbdc, 1) && 712 get_mouse_status(kbdc, status, 0, 3) >= 3 && status[1] != 0) 713 return (status[1]); 714 return (c); 715 } 716 717 /* misc subroutines */ 718 /* 719 * Someday, I will get the complete list of valid pointing devices and 720 * their IDs... XXX 721 */ 722 static int 723 is_a_mouse(int id) 724 { 725 #if 0 726 static int valid_ids[] = { 727 PSM_MOUSE_ID, /* mouse */ 728 PSM_BALLPOINT_ID, /* ballpoint device */ 729 PSM_INTELLI_ID, /* Intellimouse */ 730 PSM_EXPLORER_ID, /* Intellimouse Explorer */ 731 -1 /* end of table */ 732 }; 733 int i; 734 735 for (i = 0; valid_ids[i] >= 0; ++i) 736 if (valid_ids[i] == id) 737 return (TRUE); 738 return (FALSE); 739 #else 740 return (TRUE); 741 #endif 742 } 743 744 static char * 745 model_name(int model) 746 { 747 static struct { 748 int model_code; 749 char *model_name; 750 } models[] = { 751 { MOUSE_MODEL_NETSCROLL, "NetScroll" }, 752 { MOUSE_MODEL_NET, "NetMouse/NetScroll Optical" }, 753 { MOUSE_MODEL_GLIDEPOINT, "GlidePoint" }, 754 { MOUSE_MODEL_THINK, "ThinkingMouse" }, 755 { MOUSE_MODEL_INTELLI, "IntelliMouse" }, 756 { MOUSE_MODEL_MOUSEMANPLUS, "MouseMan+" }, 757 { MOUSE_MODEL_VERSAPAD, "VersaPad" }, 758 { MOUSE_MODEL_EXPLORER, "IntelliMouse Explorer" }, 759 { MOUSE_MODEL_4D, "4D Mouse" }, 760 { MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, 761 { MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, 762 { MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, 763 { MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, 764 { MOUSE_MODEL_UNKNOWN, "Unknown" }, 765 }; 766 int i; 767 768 for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) 769 if (models[i].model_code == model) 770 break; 771 return (models[i].model_name); 772 } 773 774 static void 775 recover_from_error(KBDC kbdc) 776 { 777 /* discard anything left in the output buffer */ 778 empty_both_buffers(kbdc, 10); 779 780 #if 0 781 /* 782 * NOTE: KBDC_RESET_KBD may not restore the communication between the 783 * keyboard and the controller. 784 */ 785 reset_kbd(kbdc); 786 #else 787 /* 788 * NOTE: somehow diagnostic and keyboard port test commands bring the 789 * keyboard back. 790 */ 791 if (!test_controller(kbdc)) 792 log(LOG_ERR, "psm: keyboard controller failed.\n"); 793 /* if there isn't a keyboard in the system, the following error is OK */ 794 if (test_kbd_port(kbdc) != 0) 795 VLOG(1, (LOG_ERR, "psm: keyboard port failed.\n")); 796 #endif 797 } 798 799 static int 800 restore_controller(KBDC kbdc, int command_byte) 801 { 802 empty_both_buffers(kbdc, 10); 803 804 if (!set_controller_command_byte(kbdc, 0xff, command_byte)) { 805 log(LOG_ERR, "psm: failed to restore the keyboard controller " 806 "command byte.\n"); 807 empty_both_buffers(kbdc, 10); 808 return (FALSE); 809 } else { 810 empty_both_buffers(kbdc, 10); 811 return (TRUE); 812 } 813 } 814 815 /* 816 * Re-initialize the aux port and device. The aux port must be enabled 817 * and its interrupt must be disabled before calling this routine. 818 * The aux device will be disabled before returning. 819 * The keyboard controller must be locked via `kbdc_lock()' before 820 * calling this routine. 821 */ 822 static int 823 doinitialize(struct psm_softc *sc, mousemode_t *mode) 824 { 825 KBDC kbdc = sc->kbdc; 826 int stat[3]; 827 int i; 828 829 switch((i = test_aux_port(kbdc))) { 830 case 1: /* ignore these errors */ 831 case 2: 832 case 3: 833 case PSM_ACK: 834 if (verbose) 835 log(LOG_DEBUG, 836 "psm%d: strange result for test aux port (%d).\n", 837 sc->unit, i); 838 /* FALLTHROUGH */ 839 case 0: /* no error */ 840 break; 841 case -1: /* time out */ 842 default: /* error */ 843 recover_from_error(kbdc); 844 if (sc->config & PSM_CONFIG_IGNPORTERROR) 845 break; 846 log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n", 847 sc->unit, i); 848 return (FALSE); 849 } 850 851 if (sc->config & PSM_CONFIG_NORESET) { 852 /* 853 * Don't try to reset the pointing device. It may possibly 854 * be left in the unknown state, though... 855 */ 856 } else { 857 /* 858 * NOTE: some controllers appears to hang the `keyboard' when 859 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. 860 */ 861 if (!reset_aux_dev(kbdc)) { 862 recover_from_error(kbdc); 863 log(LOG_ERR, "psm%d: failed to reset the aux device.\n", 864 sc->unit); 865 return (FALSE); 866 } 867 } 868 869 /* 870 * both the aux port and the aux device is functioning, see 871 * if the device can be enabled. 872 */ 873 if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) { 874 log(LOG_ERR, "psm%d: failed to enable the aux device.\n", 875 sc->unit); 876 return (FALSE); 877 } 878 empty_both_buffers(kbdc, 10); /* remove stray data if any */ 879 880 /* Re-enable the mouse. */ 881 for (i = 0; vendortype[i].probefunc != NULL; ++i) 882 if (vendortype[i].model == sc->hw.model) 883 (*vendortype[i].probefunc)(sc->kbdc, NULL); 884 885 /* set mouse parameters */ 886 if (mode != (mousemode_t *)NULL) { 887 if (mode->rate > 0) 888 mode->rate = set_mouse_sampling_rate(kbdc, mode->rate); 889 if (mode->resolution >= 0) 890 mode->resolution = 891 set_mouse_resolution(kbdc, mode->resolution); 892 set_mouse_scaling(kbdc, 1); 893 set_mouse_mode(kbdc); 894 895 /* 896 * Trackpoint settings are lost on resume. 897 * Restore them here. 898 */ 899 if (sc->tphw > 0) 900 set_trackpoint_parameters(sc); 901 } 902 903 /* Record sync on the next data packet we see. */ 904 sc->flags |= PSM_NEED_SYNCBITS; 905 906 /* just check the status of the mouse */ 907 if (get_mouse_status(kbdc, stat, 0, 3) < 3) 908 log(LOG_DEBUG, "psm%d: failed to get status (doinitialize).\n", 909 sc->unit); 910 911 return (TRUE); 912 } 913 914 static int 915 doopen(struct psm_softc *sc, int command_byte) 916 { 917 int stat[3]; 918 919 /* 920 * FIXME: Synaptics TouchPad seems to go back to Relative Mode with 921 * no obvious reason. Thus we check the current mode and restore the 922 * Absolute Mode if it was cleared. 923 * 924 * The previous hack at the end of psmprobe() wasn't efficient when 925 * moused(8) was restarted. 926 * 927 * A Reset (FF) or Set Defaults (F6) command would clear the 928 * Absolute Mode bit. But a verbose boot or debug.psm.loglevel=5 929 * doesn't show any evidence of such a command. 930 */ 931 if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) { 932 mouse_ext_command(sc->kbdc, 1); 933 get_mouse_status(sc->kbdc, stat, 0, 3); 934 if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) || 935 stat[1] == 0x47) && 936 stat[2] == 0x40) { 937 /* Set the mode byte -- request wmode where 938 * available */ 939 if (sc->synhw.capExtended) 940 mouse_ext_command(sc->kbdc, 0xc1); 941 else 942 mouse_ext_command(sc->kbdc, 0xc0); 943 set_mouse_sampling_rate(sc->kbdc, 20); 944 VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode " 945 "hopefully restored\n", 946 sc->unit)); 947 } 948 } 949 950 /* 951 * A user may want to disable tap and drag gestures on a Synaptics 952 * TouchPad when it operates in Relative Mode. 953 */ 954 if (sc->hw.model == MOUSE_MODEL_GENERIC) { 955 if (tap_enabled > 0) { 956 /* 957 * Enable tap & drag gestures. We use a Mode Byte 958 * and clear the DisGest bit (see §2.5 of Synaptics 959 * TouchPad Interfacing Guide). 960 */ 961 VLOG(2, (LOG_DEBUG, 962 "psm%d: enable tap and drag gestures\n", 963 sc->unit)); 964 mouse_ext_command(sc->kbdc, 0x00); 965 set_mouse_sampling_rate(sc->kbdc, 20); 966 } else if (tap_enabled == 0) { 967 /* 968 * Disable tap & drag gestures. We use a Mode Byte 969 * and set the DisGest bit (see §2.5 of Synaptics 970 * TouchPad Interfacing Guide). 971 */ 972 VLOG(2, (LOG_DEBUG, 973 "psm%d: disable tap and drag gestures\n", 974 sc->unit)); 975 mouse_ext_command(sc->kbdc, 0x04); 976 set_mouse_sampling_rate(sc->kbdc, 20); 977 } 978 } 979 980 /* enable the mouse device */ 981 if (!enable_aux_dev(sc->kbdc)) { 982 /* MOUSE ERROR: failed to enable the mouse because: 983 * 1) the mouse is faulty, 984 * 2) the mouse has been removed(!?) 985 * In the latter case, the keyboard may have hung, and need 986 * recovery procedure... 987 */ 988 recover_from_error(sc->kbdc); 989 #if 0 990 /* FIXME: we could reset the mouse here and try to enable 991 * it again. But it will take long time and it's not a good 992 * idea to disable the keyboard that long... 993 */ 994 if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) { 995 recover_from_error(sc->kbdc); 996 #else 997 { 998 #endif 999 restore_controller(sc->kbdc, command_byte); 1000 /* mark this device is no longer available */ 1001 sc->state &= ~PSM_VALID; 1002 log(LOG_ERR, 1003 "psm%d: failed to enable the device (doopen).\n", 1004 sc->unit); 1005 return (EIO); 1006 } 1007 } 1008 1009 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 1010 log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", 1011 sc->unit); 1012 1013 /* enable the aux port and interrupt */ 1014 if (!set_controller_command_byte(sc->kbdc, 1015 kbdc_get_device_mask(sc->kbdc), 1016 (command_byte & KBD_KBD_CONTROL_BITS) | 1017 KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) { 1018 /* CONTROLLER ERROR */ 1019 disable_aux_dev(sc->kbdc); 1020 restore_controller(sc->kbdc, command_byte); 1021 log(LOG_ERR, 1022 "psm%d: failed to enable the aux interrupt (doopen).\n", 1023 sc->unit); 1024 return (EIO); 1025 } 1026 1027 /* start the watchdog timer */ 1028 sc->watchdog = FALSE; 1029 callout_reset(&sc->callout, hz * 2, psmtimeout, sc); 1030 1031 return (0); 1032 } 1033 1034 static int 1035 reinitialize(struct psm_softc *sc, int doinit) 1036 { 1037 int err; 1038 int c; 1039 int s; 1040 1041 /* don't let anybody mess with the aux device */ 1042 if (!kbdc_lock(sc->kbdc, TRUE)) 1043 return (EIO); 1044 s = spltty(); 1045 1046 /* block our watchdog timer */ 1047 sc->watchdog = FALSE; 1048 callout_stop(&sc->callout); 1049 1050 /* save the current controller command byte */ 1051 empty_both_buffers(sc->kbdc, 10); 1052 c = get_controller_command_byte(sc->kbdc); 1053 VLOG(2, (LOG_DEBUG, 1054 "psm%d: current command byte: %04x (reinitialize).\n", 1055 sc->unit, c)); 1056 1057 /* enable the aux port but disable the aux interrupt and the keyboard */ 1058 if ((c == -1) || !set_controller_command_byte(sc->kbdc, 1059 kbdc_get_device_mask(sc->kbdc), 1060 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | 1061 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1062 /* CONTROLLER ERROR */ 1063 splx(s); 1064 kbdc_lock(sc->kbdc, FALSE); 1065 log(LOG_ERR, 1066 "psm%d: unable to set the command byte (reinitialize).\n", 1067 sc->unit); 1068 return (EIO); 1069 } 1070 1071 /* flush any data */ 1072 if (sc->state & PSM_VALID) { 1073 /* this may fail; but never mind... */ 1074 disable_aux_dev(sc->kbdc); 1075 empty_aux_buffer(sc->kbdc, 10); 1076 } 1077 flushpackets(sc); 1078 sc->syncerrors = 0; 1079 sc->pkterrors = 0; 1080 memset(&sc->lastinputerr, 0, sizeof(sc->lastinputerr)); 1081 1082 /* try to detect the aux device; are you still there? */ 1083 err = 0; 1084 if (doinit) { 1085 if (doinitialize(sc, &sc->mode)) { 1086 /* yes */ 1087 sc->state |= PSM_VALID; 1088 } else { 1089 /* the device has gone! */ 1090 restore_controller(sc->kbdc, c); 1091 sc->state &= ~PSM_VALID; 1092 log(LOG_ERR, 1093 "psm%d: the aux device has gone! (reinitialize).\n", 1094 sc->unit); 1095 err = ENXIO; 1096 } 1097 } 1098 splx(s); 1099 1100 /* restore the driver state */ 1101 if ((sc->state & PSM_OPEN) && (err == 0)) { 1102 /* enable the aux device and the port again */ 1103 err = doopen(sc, c); 1104 if (err != 0) 1105 log(LOG_ERR, "psm%d: failed to enable the device " 1106 "(reinitialize).\n", sc->unit); 1107 } else { 1108 /* restore the keyboard port and disable the aux port */ 1109 if (!set_controller_command_byte(sc->kbdc, 1110 kbdc_get_device_mask(sc->kbdc), 1111 (c & KBD_KBD_CONTROL_BITS) | 1112 KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1113 /* CONTROLLER ERROR */ 1114 log(LOG_ERR, "psm%d: failed to disable the aux port " 1115 "(reinitialize).\n", sc->unit); 1116 err = EIO; 1117 } 1118 } 1119 1120 kbdc_lock(sc->kbdc, FALSE); 1121 return (err); 1122 } 1123 1124 /* psm driver entry points */ 1125 1126 static void 1127 psmidentify(driver_t *driver, device_t parent) 1128 { 1129 device_t psmc; 1130 device_t psm; 1131 u_long irq; 1132 int unit; 1133 1134 unit = device_get_unit(parent); 1135 1136 /* always add at least one child */ 1137 psm = BUS_ADD_CHILD(parent, KBDC_RID_AUX, driver->name, unit); 1138 if (psm == NULL) 1139 return; 1140 1141 irq = bus_get_resource_start(psm, SYS_RES_IRQ, KBDC_RID_AUX); 1142 if (irq > 0) 1143 return; 1144 1145 /* 1146 * If the PS/2 mouse device has already been reported by ACPI or 1147 * PnP BIOS, obtain the IRQ resource from it. 1148 * (See psmcpnp_attach() below.) 1149 */ 1150 psmc = device_find_child(device_get_parent(parent), 1151 PSMCPNP_DRIVER_NAME, unit); 1152 if (psmc == NULL) 1153 return; 1154 irq = bus_get_resource_start(psmc, SYS_RES_IRQ, 0); 1155 if (irq <= 0) 1156 return; 1157 bus_delete_resource(psmc, SYS_RES_IRQ, 0); 1158 bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1); 1159 } 1160 1161 #define endprobe(v) do { \ 1162 if (bootverbose) \ 1163 --verbose; \ 1164 kbdc_set_device_mask(sc->kbdc, mask); \ 1165 kbdc_lock(sc->kbdc, FALSE); \ 1166 return (v); \ 1167 } while (0) 1168 1169 static int 1170 psmprobe(device_t dev) 1171 { 1172 int unit = device_get_unit(dev); 1173 struct psm_softc *sc = device_get_softc(dev); 1174 int stat[3]; 1175 int command_byte; 1176 int mask; 1177 int rid; 1178 int i; 1179 1180 #if 0 1181 kbdc_debug(TRUE); 1182 #endif 1183 1184 /* see if IRQ is available */ 1185 rid = KBDC_RID_AUX; 1186 sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 1187 if (sc->intr == NULL) { 1188 if (bootverbose) 1189 device_printf(dev, "unable to allocate IRQ\n"); 1190 return (ENXIO); 1191 } 1192 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); 1193 1194 sc->unit = unit; 1195 sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev))); 1196 sc->config = device_get_flags(dev) & PSM_CONFIG_FLAGS; 1197 /* XXX: for backward compatibility */ 1198 #if defined(PSM_HOOKRESUME) || defined(PSM_HOOKAPM) 1199 sc->config |= 1200 #ifdef PSM_RESETAFTERSUSPEND 1201 PSM_CONFIG_INITAFTERSUSPEND; 1202 #else 1203 PSM_CONFIG_HOOKRESUME; 1204 #endif 1205 #endif /* PSM_HOOKRESUME | PSM_HOOKAPM */ 1206 sc->flags = 0; 1207 if (bootverbose) 1208 ++verbose; 1209 1210 device_set_desc(dev, "PS/2 Mouse"); 1211 1212 if (!kbdc_lock(sc->kbdc, TRUE)) { 1213 printf("psm%d: unable to lock the controller.\n", unit); 1214 if (bootverbose) 1215 --verbose; 1216 return (ENXIO); 1217 } 1218 1219 /* 1220 * NOTE: two bits in the command byte controls the operation of the 1221 * aux port (mouse port): the aux port disable bit (bit 5) and the aux 1222 * port interrupt (IRQ 12) enable bit (bit 2). 1223 */ 1224 1225 /* discard anything left after the keyboard initialization */ 1226 empty_both_buffers(sc->kbdc, 10); 1227 1228 /* save the current command byte; it will be used later */ 1229 mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS; 1230 command_byte = get_controller_command_byte(sc->kbdc); 1231 if (verbose) 1232 printf("psm%d: current command byte:%04x\n", unit, 1233 command_byte); 1234 if (command_byte == -1) { 1235 /* CONTROLLER ERROR */ 1236 printf("psm%d: unable to get the current command byte value.\n", 1237 unit); 1238 endprobe(ENXIO); 1239 } 1240 1241 /* 1242 * disable the keyboard port while probing the aux port, which must be 1243 * enabled during this routine 1244 */ 1245 if (!set_controller_command_byte(sc->kbdc, 1246 KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS, 1247 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | 1248 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1249 /* 1250 * this is CONTROLLER ERROR; I don't know how to recover 1251 * from this error... 1252 */ 1253 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc)) 1254 restore_controller(sc->kbdc, command_byte); 1255 printf("psm%d: unable to set the command byte.\n", unit); 1256 endprobe(ENXIO); 1257 } 1258 write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT); 1259 1260 /* 1261 * NOTE: `test_aux_port()' is designed to return with zero if the aux 1262 * port exists and is functioning. However, some controllers appears 1263 * to respond with zero even when the aux port doesn't exist. (It may 1264 * be that this is only the case when the controller DOES have the aux 1265 * port but the port is not wired on the motherboard.) The keyboard 1266 * controllers without the port, such as the original AT, are 1267 * supposed to return with an error code or simply time out. In any 1268 * case, we have to continue probing the port even when the controller 1269 * passes this test. 1270 * 1271 * XXX: some controllers erroneously return the error code 1, 2 or 3 1272 * when it has a perfectly functional aux port. We have to ignore 1273 * this error code. Even if the controller HAS error with the aux 1274 * port, it will be detected later... 1275 * XXX: another incompatible controller returns PSM_ACK (0xfa)... 1276 */ 1277 switch ((i = test_aux_port(sc->kbdc))) { 1278 case 1: /* ignore these errors */ 1279 case 2: 1280 case 3: 1281 case PSM_ACK: 1282 if (verbose) 1283 printf("psm%d: strange result for test aux port " 1284 "(%d).\n", unit, i); 1285 /* FALLTHROUGH */ 1286 case 0: /* no error */ 1287 break; 1288 case -1: /* time out */ 1289 default: /* error */ 1290 recover_from_error(sc->kbdc); 1291 if (sc->config & PSM_CONFIG_IGNPORTERROR) 1292 break; 1293 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc)) 1294 restore_controller(sc->kbdc, command_byte); 1295 if (verbose) 1296 printf("psm%d: the aux port is not functioning (%d).\n", 1297 unit, i); 1298 endprobe(ENXIO); 1299 } 1300 1301 if (sc->config & PSM_CONFIG_NORESET) { 1302 /* 1303 * Don't try to reset the pointing device. It may possibly be 1304 * left in an unknown state, though... 1305 */ 1306 } else { 1307 /* 1308 * NOTE: some controllers appears to hang the `keyboard' when 1309 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. 1310 * 1311 * Attempt to reset the controller twice -- this helps 1312 * pierce through some KVM switches. The second reset 1313 * is non-fatal. 1314 */ 1315 if (!reset_aux_dev(sc->kbdc)) { 1316 recover_from_error(sc->kbdc); 1317 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc)) 1318 restore_controller(sc->kbdc, command_byte); 1319 if (verbose) 1320 printf("psm%d: failed to reset the aux " 1321 "device.\n", unit); 1322 endprobe(ENXIO); 1323 } else if (!reset_aux_dev(sc->kbdc)) { 1324 recover_from_error(sc->kbdc); 1325 if (verbose >= 2) 1326 printf("psm%d: failed to reset the aux device " 1327 "(2).\n", unit); 1328 } 1329 } 1330 1331 /* 1332 * both the aux port and the aux device are functioning, see if the 1333 * device can be enabled. NOTE: when enabled, the device will start 1334 * sending data; we shall immediately disable the device once we know 1335 * the device can be enabled. 1336 */ 1337 if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) { 1338 /* MOUSE ERROR */ 1339 recover_from_error(sc->kbdc); 1340 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc)) 1341 restore_controller(sc->kbdc, command_byte); 1342 if (verbose) 1343 printf("psm%d: failed to enable the aux device.\n", 1344 unit); 1345 endprobe(ENXIO); 1346 } 1347 1348 /* save the default values after reset */ 1349 if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) { 1350 sc->dflt_mode.rate = sc->mode.rate = stat[2]; 1351 sc->dflt_mode.resolution = sc->mode.resolution = stat[1]; 1352 } else { 1353 sc->dflt_mode.rate = sc->mode.rate = -1; 1354 sc->dflt_mode.resolution = sc->mode.resolution = -1; 1355 } 1356 1357 /* hardware information */ 1358 sc->hw.iftype = MOUSE_IF_PS2; 1359 1360 /* verify the device is a mouse */ 1361 sc->hw.hwid = get_aux_id(sc->kbdc); 1362 if (!is_a_mouse(sc->hw.hwid)) { 1363 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc)) 1364 restore_controller(sc->kbdc, command_byte); 1365 if (verbose) 1366 printf("psm%d: unknown device type (%d).\n", unit, 1367 sc->hw.hwid); 1368 endprobe(ENXIO); 1369 } 1370 switch (sc->hw.hwid) { 1371 case PSM_BALLPOINT_ID: 1372 sc->hw.type = MOUSE_TRACKBALL; 1373 break; 1374 case PSM_MOUSE_ID: 1375 case PSM_INTELLI_ID: 1376 case PSM_EXPLORER_ID: 1377 case PSM_4DMOUSE_ID: 1378 case PSM_4DPLUS_ID: 1379 sc->hw.type = MOUSE_MOUSE; 1380 break; 1381 default: 1382 sc->hw.type = MOUSE_UNKNOWN; 1383 break; 1384 } 1385 1386 if (sc->config & PSM_CONFIG_NOIDPROBE) { 1387 sc->hw.buttons = 2; 1388 i = GENERIC_MOUSE_ENTRY; 1389 } else { 1390 /* # of buttons */ 1391 sc->hw.buttons = get_mouse_buttons(sc->kbdc); 1392 1393 /* other parameters */ 1394 for (i = 0; vendortype[i].probefunc != NULL; ++i) 1395 if ((*vendortype[i].probefunc)(sc->kbdc, sc)) { 1396 if (verbose >= 2) 1397 printf("psm%d: found %s\n", unit, 1398 model_name(vendortype[i].model)); 1399 break; 1400 } 1401 } 1402 1403 sc->hw.model = vendortype[i].model; 1404 1405 sc->dflt_mode.level = PSM_LEVEL_BASE; 1406 sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE; 1407 sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4; 1408 if (sc->config & PSM_CONFIG_NOCHECKSYNC) 1409 sc->dflt_mode.syncmask[0] = 0; 1410 else 1411 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask; 1412 if (sc->config & PSM_CONFIG_FORCETAP) 1413 sc->dflt_mode.syncmask[0] &= ~MOUSE_PS2_TAP; 1414 sc->dflt_mode.syncmask[1] = 0; /* syncbits */ 1415 sc->mode = sc->dflt_mode; 1416 sc->mode.packetsize = vendortype[i].packetsize; 1417 1418 /* set mouse parameters */ 1419 #if 0 1420 /* 1421 * A version of Logitech FirstMouse+ won't report wheel movement, 1422 * if SET_DEFAULTS is sent... Don't use this command. 1423 * This fix was found by Takashi Nishida. 1424 */ 1425 i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS); 1426 if (verbose >= 2) 1427 printf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i); 1428 #endif 1429 if (sc->config & PSM_CONFIG_RESOLUTION) 1430 sc->mode.resolution = 1431 set_mouse_resolution(sc->kbdc, 1432 (sc->config & PSM_CONFIG_RESOLUTION) - 1); 1433 else if (sc->mode.resolution >= 0) 1434 sc->mode.resolution = 1435 set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution); 1436 if (sc->mode.rate > 0) 1437 sc->mode.rate = 1438 set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate); 1439 set_mouse_scaling(sc->kbdc, 1); 1440 1441 /* Record sync on the next data packet we see. */ 1442 sc->flags |= PSM_NEED_SYNCBITS; 1443 1444 /* just check the status of the mouse */ 1445 /* 1446 * NOTE: XXX there are some arcane controller/mouse combinations out 1447 * there, which hung the controller unless there is data transmission 1448 * after ACK from the mouse. 1449 */ 1450 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 1451 printf("psm%d: failed to get status.\n", unit); 1452 else { 1453 /* 1454 * When in its native mode, some mice operate with different 1455 * default parameters than in the PS/2 compatible mode. 1456 */ 1457 sc->dflt_mode.rate = sc->mode.rate = stat[2]; 1458 sc->dflt_mode.resolution = sc->mode.resolution = stat[1]; 1459 } 1460 1461 /* disable the aux port for now... */ 1462 if (!set_controller_command_byte(sc->kbdc, 1463 KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS, 1464 (command_byte & KBD_KBD_CONTROL_BITS) | 1465 KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1466 /* 1467 * this is CONTROLLER ERROR; I don't know the proper way to 1468 * recover from this error... 1469 */ 1470 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc)) 1471 restore_controller(sc->kbdc, command_byte); 1472 printf("psm%d: unable to set the command byte.\n", unit); 1473 endprobe(ENXIO); 1474 } 1475 1476 /* done */ 1477 kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS); 1478 kbdc_lock(sc->kbdc, FALSE); 1479 return (0); 1480 } 1481 1482 static int 1483 psmattach(device_t dev) 1484 { 1485 int unit = device_get_unit(dev); 1486 struct psm_softc *sc = device_get_softc(dev); 1487 int error; 1488 int rid; 1489 1490 /* Setup initial state */ 1491 sc->state = PSM_VALID; 1492 callout_init(&sc->callout, 0); 1493 callout_init(&sc->softcallout, 0); 1494 1495 /* Setup our interrupt handler */ 1496 rid = KBDC_RID_AUX; 1497 sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 1498 if (sc->intr == NULL) 1499 return (ENXIO); 1500 error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, psmintr, sc, 1501 &sc->ih); 1502 if (error) { 1503 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); 1504 return (error); 1505 } 1506 1507 /* Done */ 1508 sc->dev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "psm%d", unit); 1509 sc->dev->si_drv1 = sc; 1510 sc->bdev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "bpsm%d", unit); 1511 sc->bdev->si_drv1 = sc; 1512 1513 /* Some touchpad devices need full reinitialization after suspend. */ 1514 switch (sc->hw.model) { 1515 case MOUSE_MODEL_SYNAPTICS: 1516 case MOUSE_MODEL_GLIDEPOINT: 1517 case MOUSE_MODEL_VERSAPAD: 1518 sc->config |= PSM_CONFIG_INITAFTERSUSPEND; 1519 break; 1520 default: 1521 if (sc->synhw.infoMajor >= 4 || sc->tphw > 0) 1522 sc->config |= PSM_CONFIG_INITAFTERSUSPEND; 1523 break; 1524 } 1525 1526 if (!verbose) 1527 printf("psm%d: model %s, device ID %d\n", 1528 unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff); 1529 else { 1530 printf("psm%d: model %s, device ID %d-%02x, %d buttons\n", 1531 unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff, 1532 sc->hw.hwid >> 8, sc->hw.buttons); 1533 printf("psm%d: config:%08x, flags:%08x, packet size:%d\n", 1534 unit, sc->config, sc->flags, sc->mode.packetsize); 1535 printf("psm%d: syncmask:%02x, syncbits:%02x\n", 1536 unit, sc->mode.syncmask[0], sc->mode.syncmask[1]); 1537 } 1538 1539 if (bootverbose) 1540 --verbose; 1541 1542 return (0); 1543 } 1544 1545 static int 1546 psmdetach(device_t dev) 1547 { 1548 struct psm_softc *sc; 1549 int rid; 1550 1551 sc = device_get_softc(dev); 1552 if (sc->state & PSM_OPEN) 1553 return (EBUSY); 1554 1555 rid = KBDC_RID_AUX; 1556 bus_teardown_intr(dev, sc->intr, sc->ih); 1557 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); 1558 1559 destroy_dev(sc->dev); 1560 destroy_dev(sc->bdev); 1561 1562 callout_drain(&sc->callout); 1563 callout_drain(&sc->softcallout); 1564 1565 return (0); 1566 } 1567 1568 static int 1569 psmopen(struct cdev *dev, int flag, int fmt, struct thread *td) 1570 { 1571 struct psm_softc *sc; 1572 int command_byte; 1573 int err; 1574 int s; 1575 1576 /* Get device data */ 1577 sc = dev->si_drv1; 1578 if ((sc == NULL) || (sc->state & PSM_VALID) == 0) { 1579 /* the device is no longer valid/functioning */ 1580 return (ENXIO); 1581 } 1582 1583 /* Disallow multiple opens */ 1584 if (sc->state & PSM_OPEN) 1585 return (EBUSY); 1586 1587 device_busy(devclass_get_device(psm_devclass, sc->unit)); 1588 1589 /* Initialize state */ 1590 sc->mode.level = sc->dflt_mode.level; 1591 sc->mode.protocol = sc->dflt_mode.protocol; 1592 sc->watchdog = FALSE; 1593 sc->async = NULL; 1594 1595 /* flush the event queue */ 1596 sc->queue.count = 0; 1597 sc->queue.head = 0; 1598 sc->queue.tail = 0; 1599 sc->status.flags = 0; 1600 sc->status.button = 0; 1601 sc->status.obutton = 0; 1602 sc->status.dx = 0; 1603 sc->status.dy = 0; 1604 sc->status.dz = 0; 1605 sc->button = 0; 1606 sc->pqueue_start = 0; 1607 sc->pqueue_end = 0; 1608 1609 /* empty input buffer */ 1610 flushpackets(sc); 1611 sc->syncerrors = 0; 1612 sc->pkterrors = 0; 1613 1614 /* don't let timeout routines in the keyboard driver to poll the kbdc */ 1615 if (!kbdc_lock(sc->kbdc, TRUE)) 1616 return (EIO); 1617 1618 /* save the current controller command byte */ 1619 s = spltty(); 1620 command_byte = get_controller_command_byte(sc->kbdc); 1621 1622 /* enable the aux port and temporalily disable the keyboard */ 1623 if (command_byte == -1 || !set_controller_command_byte(sc->kbdc, 1624 kbdc_get_device_mask(sc->kbdc), 1625 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | 1626 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1627 /* CONTROLLER ERROR; do you know how to get out of this? */ 1628 kbdc_lock(sc->kbdc, FALSE); 1629 splx(s); 1630 log(LOG_ERR, 1631 "psm%d: unable to set the command byte (psmopen).\n", 1632 sc->unit); 1633 return (EIO); 1634 } 1635 /* 1636 * Now that the keyboard controller is told not to generate 1637 * the keyboard and mouse interrupts, call `splx()' to allow 1638 * the other tty interrupts. The clock interrupt may also occur, 1639 * but timeout routines will be blocked by the poll flag set 1640 * via `kbdc_lock()' 1641 */ 1642 splx(s); 1643 1644 /* enable the mouse device */ 1645 err = doopen(sc, command_byte); 1646 1647 /* done */ 1648 if (err == 0) 1649 sc->state |= PSM_OPEN; 1650 kbdc_lock(sc->kbdc, FALSE); 1651 return (err); 1652 } 1653 1654 static int 1655 psmclose(struct cdev *dev, int flag, int fmt, struct thread *td) 1656 { 1657 struct psm_softc *sc = dev->si_drv1; 1658 int stat[3]; 1659 int command_byte; 1660 int s; 1661 1662 /* don't let timeout routines in the keyboard driver to poll the kbdc */ 1663 if (!kbdc_lock(sc->kbdc, TRUE)) 1664 return (EIO); 1665 1666 /* save the current controller command byte */ 1667 s = spltty(); 1668 command_byte = get_controller_command_byte(sc->kbdc); 1669 if (command_byte == -1) { 1670 kbdc_lock(sc->kbdc, FALSE); 1671 splx(s); 1672 return (EIO); 1673 } 1674 1675 /* disable the aux interrupt and temporalily disable the keyboard */ 1676 if (!set_controller_command_byte(sc->kbdc, 1677 kbdc_get_device_mask(sc->kbdc), 1678 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | 1679 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1680 log(LOG_ERR, 1681 "psm%d: failed to disable the aux int (psmclose).\n", 1682 sc->unit); 1683 /* CONTROLLER ERROR; 1684 * NOTE: we shall force our way through. Because the only 1685 * ill effect we shall see is that we may not be able 1686 * to read ACK from the mouse, and it doesn't matter much 1687 * so long as the mouse will accept the DISABLE command. 1688 */ 1689 } 1690 splx(s); 1691 1692 /* stop the watchdog timer */ 1693 callout_stop(&sc->callout); 1694 1695 /* remove anything left in the output buffer */ 1696 empty_aux_buffer(sc->kbdc, 10); 1697 1698 /* disable the aux device, port and interrupt */ 1699 if (sc->state & PSM_VALID) { 1700 if (!disable_aux_dev(sc->kbdc)) { 1701 /* MOUSE ERROR; 1702 * NOTE: we don't return (error) and continue, 1703 * pretending we have successfully disabled the device. 1704 * It's OK because the interrupt routine will discard 1705 * any data from the mouse hereafter. 1706 */ 1707 log(LOG_ERR, 1708 "psm%d: failed to disable the device (psmclose).\n", 1709 sc->unit); 1710 } 1711 1712 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 1713 log(LOG_DEBUG, 1714 "psm%d: failed to get status (psmclose).\n", 1715 sc->unit); 1716 } 1717 1718 if (!set_controller_command_byte(sc->kbdc, 1719 kbdc_get_device_mask(sc->kbdc), 1720 (command_byte & KBD_KBD_CONTROL_BITS) | 1721 KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1722 /* 1723 * CONTROLLER ERROR; 1724 * we shall ignore this error; see the above comment. 1725 */ 1726 log(LOG_ERR, 1727 "psm%d: failed to disable the aux port (psmclose).\n", 1728 sc->unit); 1729 } 1730 1731 /* remove anything left in the output buffer */ 1732 empty_aux_buffer(sc->kbdc, 10); 1733 1734 /* clean up and sigio requests */ 1735 if (sc->async != NULL) { 1736 funsetown(&sc->async); 1737 sc->async = NULL; 1738 } 1739 1740 /* close is almost always successful */ 1741 sc->state &= ~PSM_OPEN; 1742 kbdc_lock(sc->kbdc, FALSE); 1743 device_unbusy(devclass_get_device(psm_devclass, sc->unit)); 1744 return (0); 1745 } 1746 1747 static int 1748 tame_mouse(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *status, 1749 u_char *buf) 1750 { 1751 static u_char butmapps2[8] = { 1752 0, 1753 MOUSE_PS2_BUTTON1DOWN, 1754 MOUSE_PS2_BUTTON2DOWN, 1755 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN, 1756 MOUSE_PS2_BUTTON3DOWN, 1757 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN, 1758 MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN, 1759 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | 1760 MOUSE_PS2_BUTTON3DOWN, 1761 }; 1762 static u_char butmapmsc[8] = { 1763 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | 1764 MOUSE_MSC_BUTTON3UP, 1765 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, 1766 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, 1767 MOUSE_MSC_BUTTON3UP, 1768 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, 1769 MOUSE_MSC_BUTTON2UP, 1770 MOUSE_MSC_BUTTON1UP, 1771 0, 1772 }; 1773 int mapped; 1774 int i; 1775 1776 if (sc->mode.level == PSM_LEVEL_BASE) { 1777 mapped = status->button & ~MOUSE_BUTTON4DOWN; 1778 if (status->button & MOUSE_BUTTON4DOWN) 1779 mapped |= MOUSE_BUTTON1DOWN; 1780 status->button = mapped; 1781 buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS]; 1782 i = imax(imin(status->dx, 255), -256); 1783 if (i < 0) 1784 buf[0] |= MOUSE_PS2_XNEG; 1785 buf[1] = i; 1786 i = imax(imin(status->dy, 255), -256); 1787 if (i < 0) 1788 buf[0] |= MOUSE_PS2_YNEG; 1789 buf[2] = i; 1790 return (MOUSE_PS2_PACKETSIZE); 1791 } else if (sc->mode.level == PSM_LEVEL_STANDARD) { 1792 buf[0] = MOUSE_MSC_SYNC | 1793 butmapmsc[status->button & MOUSE_STDBUTTONS]; 1794 i = imax(imin(status->dx, 255), -256); 1795 buf[1] = i >> 1; 1796 buf[3] = i - buf[1]; 1797 i = imax(imin(status->dy, 255), -256); 1798 buf[2] = i >> 1; 1799 buf[4] = i - buf[2]; 1800 i = imax(imin(status->dz, 127), -128); 1801 buf[5] = (i >> 1) & 0x7f; 1802 buf[6] = (i - (i >> 1)) & 0x7f; 1803 buf[7] = (~status->button >> 3) & 0x7f; 1804 return (MOUSE_SYS_PACKETSIZE); 1805 } 1806 return (pb->inputbytes); 1807 } 1808 1809 static int 1810 psmread(struct cdev *dev, struct uio *uio, int flag) 1811 { 1812 struct psm_softc *sc = dev->si_drv1; 1813 u_char buf[PSM_SMALLBUFSIZE]; 1814 int error = 0; 1815 int s; 1816 int l; 1817 1818 if ((sc->state & PSM_VALID) == 0) 1819 return (EIO); 1820 1821 /* block until mouse activity occured */ 1822 s = spltty(); 1823 while (sc->queue.count <= 0) { 1824 if (dev != sc->bdev) { 1825 splx(s); 1826 return (EWOULDBLOCK); 1827 } 1828 sc->state |= PSM_ASLP; 1829 error = tsleep(sc, PZERO | PCATCH, "psmrea", 0); 1830 sc->state &= ~PSM_ASLP; 1831 if (error) { 1832 splx(s); 1833 return (error); 1834 } else if ((sc->state & PSM_VALID) == 0) { 1835 /* the device disappeared! */ 1836 splx(s); 1837 return (EIO); 1838 } 1839 } 1840 splx(s); 1841 1842 /* copy data to the user land */ 1843 while ((sc->queue.count > 0) && (uio->uio_resid > 0)) { 1844 s = spltty(); 1845 l = imin(sc->queue.count, uio->uio_resid); 1846 if (l > sizeof(buf)) 1847 l = sizeof(buf); 1848 if (l > sizeof(sc->queue.buf) - sc->queue.head) { 1849 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], 1850 sizeof(sc->queue.buf) - sc->queue.head); 1851 bcopy(&sc->queue.buf[0], 1852 &buf[sizeof(sc->queue.buf) - sc->queue.head], 1853 l - (sizeof(sc->queue.buf) - sc->queue.head)); 1854 } else 1855 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l); 1856 sc->queue.count -= l; 1857 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf); 1858 splx(s); 1859 error = uiomove(buf, l, uio); 1860 if (error) 1861 break; 1862 } 1863 1864 return (error); 1865 } 1866 1867 static int 1868 block_mouse_data(struct psm_softc *sc, int *c) 1869 { 1870 int s; 1871 1872 if (!kbdc_lock(sc->kbdc, TRUE)) 1873 return (EIO); 1874 1875 s = spltty(); 1876 *c = get_controller_command_byte(sc->kbdc); 1877 if ((*c == -1) || !set_controller_command_byte(sc->kbdc, 1878 kbdc_get_device_mask(sc->kbdc), 1879 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | 1880 KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { 1881 /* this is CONTROLLER ERROR */ 1882 splx(s); 1883 kbdc_lock(sc->kbdc, FALSE); 1884 return (EIO); 1885 } 1886 1887 /* 1888 * The device may be in the middle of status data transmission. 1889 * The transmission will be interrupted, thus, incomplete status 1890 * data must be discarded. Although the aux interrupt is disabled 1891 * at the keyboard controller level, at most one aux interrupt 1892 * may have already been pending and a data byte is in the 1893 * output buffer; throw it away. Note that the second argument 1894 * to `empty_aux_buffer()' is zero, so that the call will just 1895 * flush the internal queue. 1896 * `psmintr()' will be invoked after `splx()' if an interrupt is 1897 * pending; it will see no data and returns immediately. 1898 */ 1899 empty_aux_buffer(sc->kbdc, 0); /* flush the queue */ 1900 read_aux_data_no_wait(sc->kbdc); /* throw away data if any */ 1901 flushpackets(sc); 1902 splx(s); 1903 1904 return (0); 1905 } 1906 1907 static void 1908 dropqueue(struct psm_softc *sc) 1909 { 1910 1911 sc->queue.count = 0; 1912 sc->queue.head = 0; 1913 sc->queue.tail = 0; 1914 if ((sc->state & PSM_SOFTARMED) != 0) { 1915 sc->state &= ~PSM_SOFTARMED; 1916 callout_stop(&sc->softcallout); 1917 } 1918 sc->pqueue_start = sc->pqueue_end; 1919 } 1920 1921 static void 1922 flushpackets(struct psm_softc *sc) 1923 { 1924 1925 dropqueue(sc); 1926 bzero(&sc->pqueue, sizeof(sc->pqueue)); 1927 } 1928 1929 static int 1930 unblock_mouse_data(struct psm_softc *sc, int c) 1931 { 1932 int error = 0; 1933 1934 /* 1935 * We may have seen a part of status data during `set_mouse_XXX()'. 1936 * they have been queued; flush it. 1937 */ 1938 empty_aux_buffer(sc->kbdc, 0); 1939 1940 /* restore ports and interrupt */ 1941 if (!set_controller_command_byte(sc->kbdc, 1942 kbdc_get_device_mask(sc->kbdc), 1943 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { 1944 /* 1945 * CONTROLLER ERROR; this is serious, we may have 1946 * been left with the inaccessible keyboard and 1947 * the disabled mouse interrupt. 1948 */ 1949 error = EIO; 1950 } 1951 1952 kbdc_lock(sc->kbdc, FALSE); 1953 return (error); 1954 } 1955 1956 static int 1957 psmwrite(struct cdev *dev, struct uio *uio, int flag) 1958 { 1959 struct psm_softc *sc = dev->si_drv1; 1960 u_char buf[PSM_SMALLBUFSIZE]; 1961 int error = 0, i, l; 1962 1963 if ((sc->state & PSM_VALID) == 0) 1964 return (EIO); 1965 1966 if (sc->mode.level < PSM_LEVEL_NATIVE) 1967 return (ENODEV); 1968 1969 /* copy data from the user land */ 1970 while (uio->uio_resid > 0) { 1971 l = imin(PSM_SMALLBUFSIZE, uio->uio_resid); 1972 error = uiomove(buf, l, uio); 1973 if (error) 1974 break; 1975 for (i = 0; i < l; i++) { 1976 VLOG(4, (LOG_DEBUG, "psm: cmd 0x%x\n", buf[i])); 1977 if (!write_aux_command(sc->kbdc, buf[i])) { 1978 VLOG(2, (LOG_DEBUG, 1979 "psm: cmd 0x%x failed.\n", buf[i])); 1980 return (reinitialize(sc, FALSE)); 1981 } 1982 } 1983 } 1984 1985 return (error); 1986 } 1987 1988 static int 1989 psmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, 1990 struct thread *td) 1991 { 1992 struct psm_softc *sc = dev->si_drv1; 1993 mousemode_t mode; 1994 mousestatus_t status; 1995 #if (defined(MOUSE_GETVARS)) 1996 mousevar_t *var; 1997 #endif 1998 mousedata_t *data; 1999 int stat[3]; 2000 int command_byte; 2001 int error = 0; 2002 int s; 2003 2004 /* Perform IOCTL command */ 2005 switch (cmd) { 2006 2007 case OLD_MOUSE_GETHWINFO: 2008 s = spltty(); 2009 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons; 2010 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype; 2011 ((old_mousehw_t *)addr)->type = sc->hw.type; 2012 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff; 2013 splx(s); 2014 break; 2015 2016 case MOUSE_GETHWINFO: 2017 s = spltty(); 2018 *(mousehw_t *)addr = sc->hw; 2019 if (sc->mode.level == PSM_LEVEL_BASE) 2020 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; 2021 splx(s); 2022 break; 2023 2024 case MOUSE_SYN_GETHWINFO: 2025 s = spltty(); 2026 if (sc->synhw.infoMajor >= 4) 2027 *(synapticshw_t *)addr = sc->synhw; 2028 else 2029 error = EINVAL; 2030 splx(s); 2031 break; 2032 2033 case OLD_MOUSE_GETMODE: 2034 s = spltty(); 2035 switch (sc->mode.level) { 2036 case PSM_LEVEL_BASE: 2037 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; 2038 break; 2039 case PSM_LEVEL_STANDARD: 2040 ((old_mousemode_t *)addr)->protocol = 2041 MOUSE_PROTO_SYSMOUSE; 2042 break; 2043 case PSM_LEVEL_NATIVE: 2044 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; 2045 break; 2046 } 2047 ((old_mousemode_t *)addr)->rate = sc->mode.rate; 2048 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution; 2049 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor; 2050 splx(s); 2051 break; 2052 2053 case MOUSE_GETMODE: 2054 s = spltty(); 2055 *(mousemode_t *)addr = sc->mode; 2056 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) { 2057 ((mousemode_t *)addr)->syncmask[0] = 0; 2058 ((mousemode_t *)addr)->syncmask[1] = 0; 2059 } 2060 ((mousemode_t *)addr)->resolution = 2061 MOUSE_RES_LOW - sc->mode.resolution; 2062 switch (sc->mode.level) { 2063 case PSM_LEVEL_BASE: 2064 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; 2065 ((mousemode_t *)addr)->packetsize = 2066 MOUSE_PS2_PACKETSIZE; 2067 break; 2068 case PSM_LEVEL_STANDARD: 2069 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; 2070 ((mousemode_t *)addr)->packetsize = 2071 MOUSE_SYS_PACKETSIZE; 2072 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; 2073 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; 2074 break; 2075 case PSM_LEVEL_NATIVE: 2076 /* FIXME: this isn't quite correct... XXX */ 2077 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; 2078 break; 2079 } 2080 splx(s); 2081 break; 2082 2083 case OLD_MOUSE_SETMODE: 2084 case MOUSE_SETMODE: 2085 if (cmd == OLD_MOUSE_SETMODE) { 2086 mode.rate = ((old_mousemode_t *)addr)->rate; 2087 /* 2088 * resolution old I/F new I/F 2089 * default 0 0 2090 * low 1 -2 2091 * medium low 2 -3 2092 * medium high 3 -4 2093 * high 4 -5 2094 */ 2095 if (((old_mousemode_t *)addr)->resolution > 0) 2096 mode.resolution = 2097 -((old_mousemode_t *)addr)->resolution - 1; 2098 else 2099 mode.resolution = 0; 2100 mode.accelfactor = 2101 ((old_mousemode_t *)addr)->accelfactor; 2102 mode.level = -1; 2103 } else 2104 mode = *(mousemode_t *)addr; 2105 2106 /* adjust and validate parameters. */ 2107 if (mode.rate > UCHAR_MAX) 2108 return (EINVAL); 2109 if (mode.rate == 0) 2110 mode.rate = sc->dflt_mode.rate; 2111 else if (mode.rate == -1) 2112 /* don't change the current setting */ 2113 ; 2114 else if (mode.rate < 0) 2115 return (EINVAL); 2116 if (mode.resolution >= UCHAR_MAX) 2117 return (EINVAL); 2118 if (mode.resolution >= 200) 2119 mode.resolution = MOUSE_RES_HIGH; 2120 else if (mode.resolution >= 100) 2121 mode.resolution = MOUSE_RES_MEDIUMHIGH; 2122 else if (mode.resolution >= 50) 2123 mode.resolution = MOUSE_RES_MEDIUMLOW; 2124 else if (mode.resolution > 0) 2125 mode.resolution = MOUSE_RES_LOW; 2126 if (mode.resolution == MOUSE_RES_DEFAULT) 2127 mode.resolution = sc->dflt_mode.resolution; 2128 else if (mode.resolution == -1) 2129 /* don't change the current setting */ 2130 ; 2131 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */ 2132 mode.resolution = MOUSE_RES_LOW - mode.resolution; 2133 if (mode.level == -1) 2134 /* don't change the current setting */ 2135 mode.level = sc->mode.level; 2136 else if ((mode.level < PSM_LEVEL_MIN) || 2137 (mode.level > PSM_LEVEL_MAX)) 2138 return (EINVAL); 2139 if (mode.accelfactor == -1) 2140 /* don't change the current setting */ 2141 mode.accelfactor = sc->mode.accelfactor; 2142 else if (mode.accelfactor < 0) 2143 return (EINVAL); 2144 2145 /* don't allow anybody to poll the keyboard controller */ 2146 error = block_mouse_data(sc, &command_byte); 2147 if (error) 2148 return (error); 2149 2150 /* set mouse parameters */ 2151 if (mode.rate > 0) 2152 mode.rate = set_mouse_sampling_rate(sc->kbdc, 2153 mode.rate); 2154 if (mode.resolution >= 0) 2155 mode.resolution = 2156 set_mouse_resolution(sc->kbdc, mode.resolution); 2157 set_mouse_scaling(sc->kbdc, 1); 2158 get_mouse_status(sc->kbdc, stat, 0, 3); 2159 2160 s = spltty(); 2161 sc->mode.rate = mode.rate; 2162 sc->mode.resolution = mode.resolution; 2163 sc->mode.accelfactor = mode.accelfactor; 2164 sc->mode.level = mode.level; 2165 splx(s); 2166 2167 unblock_mouse_data(sc, command_byte); 2168 break; 2169 2170 case MOUSE_GETLEVEL: 2171 *(int *)addr = sc->mode.level; 2172 break; 2173 2174 case MOUSE_SETLEVEL: 2175 if ((*(int *)addr < PSM_LEVEL_MIN) || 2176 (*(int *)addr > PSM_LEVEL_MAX)) 2177 return (EINVAL); 2178 sc->mode.level = *(int *)addr; 2179 break; 2180 2181 case MOUSE_GETSTATUS: 2182 s = spltty(); 2183 status = sc->status; 2184 sc->status.flags = 0; 2185 sc->status.obutton = sc->status.button; 2186 sc->status.button = 0; 2187 sc->status.dx = 0; 2188 sc->status.dy = 0; 2189 sc->status.dz = 0; 2190 splx(s); 2191 *(mousestatus_t *)addr = status; 2192 break; 2193 2194 #if (defined(MOUSE_GETVARS)) 2195 case MOUSE_GETVARS: 2196 var = (mousevar_t *)addr; 2197 bzero(var, sizeof(*var)); 2198 s = spltty(); 2199 var->var[0] = MOUSE_VARS_PS2_SIG; 2200 var->var[1] = sc->config; 2201 var->var[2] = sc->flags; 2202 splx(s); 2203 break; 2204 2205 case MOUSE_SETVARS: 2206 return (ENODEV); 2207 #endif /* MOUSE_GETVARS */ 2208 2209 case MOUSE_READSTATE: 2210 case MOUSE_READDATA: 2211 data = (mousedata_t *)addr; 2212 if (data->len > sizeof(data->buf)/sizeof(data->buf[0])) 2213 return (EINVAL); 2214 2215 error = block_mouse_data(sc, &command_byte); 2216 if (error) 2217 return (error); 2218 if ((data->len = get_mouse_status(sc->kbdc, data->buf, 2219 (cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0) 2220 error = EIO; 2221 unblock_mouse_data(sc, command_byte); 2222 break; 2223 2224 #if (defined(MOUSE_SETRESOLUTION)) 2225 case MOUSE_SETRESOLUTION: 2226 mode.resolution = *(int *)addr; 2227 if (mode.resolution >= UCHAR_MAX) 2228 return (EINVAL); 2229 else if (mode.resolution >= 200) 2230 mode.resolution = MOUSE_RES_HIGH; 2231 else if (mode.resolution >= 100) 2232 mode.resolution = MOUSE_RES_MEDIUMHIGH; 2233 else if (mode.resolution >= 50) 2234 mode.resolution = MOUSE_RES_MEDIUMLOW; 2235 else if (mode.resolution > 0) 2236 mode.resolution = MOUSE_RES_LOW; 2237 if (mode.resolution == MOUSE_RES_DEFAULT) 2238 mode.resolution = sc->dflt_mode.resolution; 2239 else if (mode.resolution == -1) 2240 mode.resolution = sc->mode.resolution; 2241 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */ 2242 mode.resolution = MOUSE_RES_LOW - mode.resolution; 2243 2244 error = block_mouse_data(sc, &command_byte); 2245 if (error) 2246 return (error); 2247 sc->mode.resolution = 2248 set_mouse_resolution(sc->kbdc, mode.resolution); 2249 if (sc->mode.resolution != mode.resolution) 2250 error = EIO; 2251 unblock_mouse_data(sc, command_byte); 2252 break; 2253 #endif /* MOUSE_SETRESOLUTION */ 2254 2255 #if (defined(MOUSE_SETRATE)) 2256 case MOUSE_SETRATE: 2257 mode.rate = *(int *)addr; 2258 if (mode.rate > UCHAR_MAX) 2259 return (EINVAL); 2260 if (mode.rate == 0) 2261 mode.rate = sc->dflt_mode.rate; 2262 else if (mode.rate < 0) 2263 mode.rate = sc->mode.rate; 2264 2265 error = block_mouse_data(sc, &command_byte); 2266 if (error) 2267 return (error); 2268 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate); 2269 if (sc->mode.rate != mode.rate) 2270 error = EIO; 2271 unblock_mouse_data(sc, command_byte); 2272 break; 2273 #endif /* MOUSE_SETRATE */ 2274 2275 #if (defined(MOUSE_SETSCALING)) 2276 case MOUSE_SETSCALING: 2277 if ((*(int *)addr <= 0) || (*(int *)addr > 2)) 2278 return (EINVAL); 2279 2280 error = block_mouse_data(sc, &command_byte); 2281 if (error) 2282 return (error); 2283 if (!set_mouse_scaling(sc->kbdc, *(int *)addr)) 2284 error = EIO; 2285 unblock_mouse_data(sc, command_byte); 2286 break; 2287 #endif /* MOUSE_SETSCALING */ 2288 2289 #if (defined(MOUSE_GETHWID)) 2290 case MOUSE_GETHWID: 2291 error = block_mouse_data(sc, &command_byte); 2292 if (error) 2293 return (error); 2294 sc->hw.hwid &= ~0x00ff; 2295 sc->hw.hwid |= get_aux_id(sc->kbdc); 2296 *(int *)addr = sc->hw.hwid & 0x00ff; 2297 unblock_mouse_data(sc, command_byte); 2298 break; 2299 #endif /* MOUSE_GETHWID */ 2300 2301 case FIONBIO: 2302 case FIOASYNC: 2303 break; 2304 case FIOSETOWN: 2305 error = fsetown(*(int *)addr, &sc->async); 2306 break; 2307 case FIOGETOWN: 2308 *(int *) addr = fgetown(&sc->async); 2309 break; 2310 default: 2311 return (ENOTTY); 2312 } 2313 2314 return (error); 2315 } 2316 2317 static void 2318 psmtimeout(void *arg) 2319 { 2320 struct psm_softc *sc; 2321 int s; 2322 2323 sc = (struct psm_softc *)arg; 2324 s = spltty(); 2325 if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) { 2326 VLOG(4, (LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit)); 2327 psmintr(sc); 2328 kbdc_lock(sc->kbdc, FALSE); 2329 } 2330 sc->watchdog = TRUE; 2331 splx(s); 2332 callout_reset(&sc->callout, hz, psmtimeout, sc); 2333 } 2334 2335 /* Add all sysctls under the debug.psm and hw.psm nodes */ 2336 static SYSCTL_NODE(_debug, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse"); 2337 static SYSCTL_NODE(_hw, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse"); 2338 2339 SYSCTL_INT(_debug_psm, OID_AUTO, loglevel, CTLFLAG_RW, &verbose, 0, 2340 "Verbosity level"); 2341 2342 static int psmhz = 20; 2343 SYSCTL_INT(_debug_psm, OID_AUTO, hz, CTLFLAG_RW, &psmhz, 0, 2344 "Frequency of the softcallout (in hz)"); 2345 static int psmerrsecs = 2; 2346 SYSCTL_INT(_debug_psm, OID_AUTO, errsecs, CTLFLAG_RW, &psmerrsecs, 0, 2347 "Number of seconds during which packets will dropped after a sync error"); 2348 static int psmerrusecs = 0; 2349 SYSCTL_INT(_debug_psm, OID_AUTO, errusecs, CTLFLAG_RW, &psmerrusecs, 0, 2350 "Microseconds to add to psmerrsecs"); 2351 static int psmsecs = 0; 2352 SYSCTL_INT(_debug_psm, OID_AUTO, secs, CTLFLAG_RW, &psmsecs, 0, 2353 "Max number of seconds between soft interrupts"); 2354 static int psmusecs = 500000; 2355 SYSCTL_INT(_debug_psm, OID_AUTO, usecs, CTLFLAG_RW, &psmusecs, 0, 2356 "Microseconds to add to psmsecs"); 2357 static int pkterrthresh = 2; 2358 SYSCTL_INT(_debug_psm, OID_AUTO, pkterrthresh, CTLFLAG_RW, &pkterrthresh, 0, 2359 "Number of error packets allowed before reinitializing the mouse"); 2360 2361 SYSCTL_INT(_hw_psm, OID_AUTO, tap_enabled, CTLFLAG_RW, &tap_enabled, 0, 2362 "Enable tap and drag gestures"); 2363 static int tap_threshold = PSM_TAP_THRESHOLD; 2364 SYSCTL_INT(_hw_psm, OID_AUTO, tap_threshold, CTLFLAG_RW, &tap_threshold, 0, 2365 "Button tap threshold"); 2366 static int tap_timeout = PSM_TAP_TIMEOUT; 2367 SYSCTL_INT(_hw_psm, OID_AUTO, tap_timeout, CTLFLAG_RW, &tap_timeout, 0, 2368 "Tap timeout for touchpads"); 2369 2370 static void 2371 psmintr(void *arg) 2372 { 2373 struct psm_softc *sc = arg; 2374 struct timeval now; 2375 int c; 2376 packetbuf_t *pb; 2377 2378 2379 /* read until there is nothing to read */ 2380 while((c = read_aux_data_no_wait(sc->kbdc)) != -1) { 2381 pb = &sc->pqueue[sc->pqueue_end]; 2382 2383 /* discard the byte if the device is not open */ 2384 if ((sc->state & PSM_OPEN) == 0) 2385 continue; 2386 2387 getmicrouptime(&now); 2388 if ((pb->inputbytes > 0) && 2389 timevalcmp(&now, &sc->inputtimeout, >)) { 2390 VLOG(3, (LOG_DEBUG, "psmintr: delay too long; " 2391 "resetting byte count\n")); 2392 pb->inputbytes = 0; 2393 sc->syncerrors = 0; 2394 sc->pkterrors = 0; 2395 } 2396 sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000; 2397 sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000; 2398 timevaladd(&sc->inputtimeout, &now); 2399 2400 pb->ipacket[pb->inputbytes++] = c; 2401 2402 if (sc->mode.level == PSM_LEVEL_NATIVE) { 2403 VLOG(4, (LOG_DEBUG, "psmintr: %02x\n", pb->ipacket[0])); 2404 sc->syncerrors = 0; 2405 sc->pkterrors = 0; 2406 goto next; 2407 } else { 2408 if (pb->inputbytes < sc->mode.packetsize) 2409 continue; 2410 2411 VLOG(4, (LOG_DEBUG, 2412 "psmintr: %02x %02x %02x %02x %02x %02x\n", 2413 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], 2414 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); 2415 } 2416 2417 c = pb->ipacket[0]; 2418 2419 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) { 2420 sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]); 2421 sc->flags &= ~PSM_NEED_SYNCBITS; 2422 VLOG(2, (LOG_DEBUG, 2423 "psmintr: Sync bytes now %04x,%04x\n", 2424 sc->mode.syncmask[0], sc->mode.syncmask[0])); 2425 } else if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) { 2426 VLOG(3, (LOG_DEBUG, "psmintr: out of sync " 2427 "(%04x != %04x) %d cmds since last error.\n", 2428 c & sc->mode.syncmask[0], sc->mode.syncmask[1], 2429 sc->cmdcount - sc->lasterr)); 2430 sc->lasterr = sc->cmdcount; 2431 /* 2432 * The sync byte test is a weak measure of packet 2433 * validity. Conservatively discard any input yet 2434 * to be seen by userland when we detect a sync 2435 * error since there is a good chance some of 2436 * the queued packets have undetected errors. 2437 */ 2438 dropqueue(sc); 2439 if (sc->syncerrors == 0) 2440 sc->pkterrors++; 2441 ++sc->syncerrors; 2442 sc->lastinputerr = now; 2443 if (sc->syncerrors >= sc->mode.packetsize * 2 || 2444 sc->pkterrors >= pkterrthresh) { 2445 /* 2446 * If we've failed to find a single sync byte 2447 * in 2 packets worth of data, or we've seen 2448 * persistent packet errors during the 2449 * validation period, reinitialize the mouse 2450 * in hopes of returning it to the expected 2451 * mode. 2452 */ 2453 VLOG(3, (LOG_DEBUG, 2454 "psmintr: reset the mouse.\n")); 2455 reinitialize(sc, TRUE); 2456 } else if (sc->syncerrors == sc->mode.packetsize) { 2457 /* 2458 * Try a soft reset after searching for a sync 2459 * byte through a packet length of bytes. 2460 */ 2461 VLOG(3, (LOG_DEBUG, 2462 "psmintr: re-enable the mouse.\n")); 2463 pb->inputbytes = 0; 2464 disable_aux_dev(sc->kbdc); 2465 enable_aux_dev(sc->kbdc); 2466 } else { 2467 VLOG(3, (LOG_DEBUG, 2468 "psmintr: discard a byte (%d)\n", 2469 sc->syncerrors)); 2470 pb->inputbytes--; 2471 bcopy(&pb->ipacket[1], &pb->ipacket[0], 2472 pb->inputbytes); 2473 } 2474 continue; 2475 } 2476 2477 /* 2478 * We have what appears to be a valid packet. 2479 * Reset the error counters. 2480 */ 2481 sc->syncerrors = 0; 2482 2483 /* 2484 * Drop even good packets if they occur within a timeout 2485 * period of a sync error. This allows the detection of 2486 * a change in the mouse's packet mode without exposing 2487 * erratic mouse behavior to the user. Some KVMs forget 2488 * enhanced mouse modes during switch events. 2489 */ 2490 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs, 2491 &now)) { 2492 pb->inputbytes = 0; 2493 continue; 2494 } 2495 2496 /* 2497 * Now that we're out of the validation period, reset 2498 * the packet error count. 2499 */ 2500 sc->pkterrors = 0; 2501 2502 sc->cmdcount++; 2503 next: 2504 if (++sc->pqueue_end >= PSM_PACKETQUEUE) 2505 sc->pqueue_end = 0; 2506 /* 2507 * If we've filled the queue then call the softintr ourselves, 2508 * otherwise schedule the interrupt for later. 2509 */ 2510 if (!timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) || 2511 (sc->pqueue_end == sc->pqueue_start)) { 2512 if ((sc->state & PSM_SOFTARMED) != 0) { 2513 sc->state &= ~PSM_SOFTARMED; 2514 callout_stop(&sc->softcallout); 2515 } 2516 psmsoftintr(arg); 2517 } else if ((sc->state & PSM_SOFTARMED) == 0) { 2518 sc->state |= PSM_SOFTARMED; 2519 callout_reset(&sc->softcallout, 2520 psmhz < 1 ? 1 : (hz/psmhz), psmsoftintr, arg); 2521 } 2522 } 2523 } 2524 2525 static void 2526 proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 2527 int *x, int *y, int *z) 2528 { 2529 2530 /* 2531 * PS2++ protocol packet 2532 * 2533 * b7 b6 b5 b4 b3 b2 b1 b0 2534 * byte 1: * 1 p3 p2 1 * * * 2535 * byte 2: c1 c2 p1 p0 d1 d0 1 0 2536 * 2537 * p3-p0: packet type 2538 * c1, c2: c1 & c2 == 1, if p2 == 0 2539 * c1 & c2 == 0, if p2 == 1 2540 * 2541 * packet type: 0 (device type) 2542 * See comments in enable_mmanplus() below. 2543 * 2544 * packet type: 1 (wheel data) 2545 * 2546 * b7 b6 b5 b4 b3 b2 b1 b0 2547 * byte 3: h * B5 B4 s d2 d1 d0 2548 * 2549 * h: 1, if horizontal roller data 2550 * 0, if vertical roller data 2551 * B4, B5: button 4 and 5 2552 * s: sign bit 2553 * d2-d0: roller data 2554 * 2555 * packet type: 2 (reserved) 2556 */ 2557 if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) && 2558 (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) { 2559 /* 2560 * the extended data packet encodes button 2561 * and wheel events 2562 */ 2563 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) { 2564 case 1: 2565 /* wheel data packet */ 2566 *x = *y = 0; 2567 if (pb->ipacket[2] & 0x80) { 2568 /* XXX horizontal roller count - ignore it */ 2569 ; 2570 } else { 2571 /* vertical roller count */ 2572 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ? 2573 (pb->ipacket[2] & 0x0f) - 16 : 2574 (pb->ipacket[2] & 0x0f); 2575 } 2576 ms->button |= (pb->ipacket[2] & 2577 MOUSE_PS2PLUS_BUTTON4DOWN) ? 2578 MOUSE_BUTTON4DOWN : 0; 2579 ms->button |= (pb->ipacket[2] & 2580 MOUSE_PS2PLUS_BUTTON5DOWN) ? 2581 MOUSE_BUTTON5DOWN : 0; 2582 break; 2583 case 2: 2584 /* 2585 * this packet type is reserved by 2586 * Logitech... 2587 */ 2588 /* 2589 * IBM ScrollPoint Mouse uses this 2590 * packet type to encode both vertical 2591 * and horizontal scroll movement. 2592 */ 2593 *x = *y = 0; 2594 /* horizontal count */ 2595 if (pb->ipacket[2] & 0x0f) 2596 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ? 2597 -2 : 2; 2598 /* vertical count */ 2599 if (pb->ipacket[2] & 0xf0) 2600 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ? 2601 -1 : 1; 2602 break; 2603 case 0: 2604 /* device type packet - shouldn't happen */ 2605 /* FALLTHROUGH */ 2606 default: 2607 *x = *y = 0; 2608 ms->button = ms->obutton; 2609 VLOG(1, (LOG_DEBUG, "psmintr: unknown PS2++ packet " 2610 "type %d: 0x%02x 0x%02x 0x%02x\n", 2611 MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket), 2612 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2])); 2613 break; 2614 } 2615 } else { 2616 /* preserve button states */ 2617 ms->button |= ms->obutton & MOUSE_EXTBUTTONS; 2618 } 2619 } 2620 2621 static int 2622 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 2623 int *x, int *y, int *z) 2624 { 2625 static int touchpad_buttons; 2626 static int guest_buttons; 2627 int w, x0, y0; 2628 2629 /* TouchPad PS/2 absolute mode message format with capFourButtons: 2630 * 2631 * Bits: 7 6 5 4 3 2 1 0 (LSB) 2632 * ------------------------------------------------ 2633 * ipacket[0]: 1 0 W3 W2 0 W1 R L 2634 * ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8 2635 * ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 2636 * ipacket[3]: 1 1 Yc Xc 0 W0 D^R U^L 2637 * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 2638 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 2639 * 2640 * Legend: 2641 * L: left physical mouse button 2642 * R: right physical mouse button 2643 * D: down button 2644 * U: up button 2645 * W: "wrist" value 2646 * X: x position 2647 * Y: y position 2648 * Z: pressure 2649 * 2650 * Without capFourButtons but with nExtendeButtons and/or capMiddle 2651 * 2652 * Bits: 7 6 5 4 3 2 1 0 (LSB) 2653 * ------------------------------------------------------ 2654 * ipacket[3]: 1 1 Yc Xc 0 W0 E^R M^L 2655 * ipacket[4]: X7 X6 X5 X4 X3|b7 X2|b5 X1|b3 X0|b1 2656 * ipacket[5]: Y7 Y6 Y5 Y4 Y3|b8 Y2|b6 Y1|b4 Y0|b2 2657 * 2658 * Legend: 2659 * M: Middle physical mouse button 2660 * E: Extended mouse buttons reported instead of low bits of X and Y 2661 * b1-b8: Extended mouse buttons 2662 * Only ((nExtendedButtons + 1) >> 1) bits are used in packet 2663 * 4 and 5, for reading X and Y value they should be zeroed. 2664 * 2665 * Absolute reportable limits: 0 - 6143. 2666 * Typical bezel limits: 1472 - 5472. 2667 * Typical edge marings: 1632 - 5312. 2668 * 2669 * w = 3 Passthrough Packet 2670 * 2671 * Byte 2,5,6 == Byte 1,2,3 of "Guest" 2672 */ 2673 2674 if (!synaptics_support) 2675 return (0); 2676 2677 /* Sanity check for out of sync packets. */ 2678 if ((pb->ipacket[0] & 0xc8) != 0x80 || 2679 (pb->ipacket[3] & 0xc8) != 0xc0) 2680 return (-1); 2681 2682 *x = *y = 0; 2683 2684 /* 2685 * Pressure value. 2686 * Interpretation: 2687 * z = 0 No finger contact 2688 * z = 10 Finger hovering near the pad 2689 * z = 30 Very light finger contact 2690 * z = 80 Normal finger contact 2691 * z = 110 Very heavy finger contact 2692 * z = 200 Finger lying flat on pad surface 2693 * z = 255 Maximum reportable Z 2694 */ 2695 *z = pb->ipacket[2]; 2696 2697 /* 2698 * Finger width value 2699 * Interpretation: 2700 * w = 0 Two finger on the pad (capMultiFinger needed) 2701 * w = 1 Three or more fingers (capMultiFinger needed) 2702 * w = 2 Pen (instead of finger) (capPen needed) 2703 * w = 3 Reserved (passthrough?) 2704 * w = 4-7 Finger of normal width (capPalmDetect needed) 2705 * w = 8-14 Very wide finger or palm (capPalmDetect needed) 2706 * w = 15 Maximum reportable width (capPalmDetect needed) 2707 */ 2708 /* XXX Is checking capExtended enough? */ 2709 if (sc->synhw.capExtended) 2710 w = ((pb->ipacket[0] & 0x30) >> 2) | 2711 ((pb->ipacket[0] & 0x04) >> 1) | 2712 ((pb->ipacket[3] & 0x04) >> 2); 2713 else { 2714 /* Assume a finger of regular width. */ 2715 w = 4; 2716 } 2717 2718 /* 2719 * Handle packets from the guest device. See: 2720 * Synaptics PS/2 TouchPad Interfacing Guide, Section 5.1 2721 */ 2722 if (w == 3 && sc->synhw.capPassthrough) { 2723 *x = ((pb->ipacket[1] & 0x10) ? 2724 pb->ipacket[4] - 256 : pb->ipacket[4]); 2725 *y = ((pb->ipacket[1] & 0x20) ? 2726 pb->ipacket[5] - 256 : pb->ipacket[5]); 2727 *z = 0; 2728 2729 guest_buttons = 0; 2730 if (pb->ipacket[1] & 0x01) 2731 guest_buttons |= MOUSE_BUTTON1DOWN; 2732 if (pb->ipacket[1] & 0x04) 2733 guest_buttons |= MOUSE_BUTTON2DOWN; 2734 if (pb->ipacket[1] & 0x02) 2735 guest_buttons |= MOUSE_BUTTON3DOWN; 2736 2737 ms->button = touchpad_buttons | guest_buttons; 2738 goto SYNAPTICS_END; 2739 } 2740 2741 if (sc->syninfo.touchpad_off) { 2742 *x = *y = *z = 0; 2743 ms->button = ms->obutton; 2744 goto SYNAPTICS_END; 2745 } 2746 2747 /* Button presses */ 2748 touchpad_buttons = 0; 2749 if (pb->ipacket[0] & 0x01) 2750 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2751 if (pb->ipacket[0] & 0x02) 2752 touchpad_buttons |= MOUSE_BUTTON3DOWN; 2753 2754 if (sc->synhw.capExtended && sc->synhw.capFourButtons) { 2755 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01) 2756 touchpad_buttons |= MOUSE_BUTTON4DOWN; 2757 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02) 2758 touchpad_buttons |= MOUSE_BUTTON5DOWN; 2759 } else if (sc->synhw.capExtended && sc->synhw.capMiddle) { 2760 /* Middle Button */ 2761 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01) 2762 touchpad_buttons |= MOUSE_BUTTON2DOWN; 2763 } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) { 2764 /* Extended Buttons */ 2765 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) { 2766 if (sc->syninfo.directional_scrolls) { 2767 if (pb->ipacket[4] & 0x01) 2768 touchpad_buttons |= MOUSE_BUTTON4DOWN; 2769 if (pb->ipacket[5] & 0x01) 2770 touchpad_buttons |= MOUSE_BUTTON5DOWN; 2771 if (pb->ipacket[4] & 0x02) 2772 touchpad_buttons |= MOUSE_BUTTON6DOWN; 2773 if (pb->ipacket[5] & 0x02) 2774 touchpad_buttons |= MOUSE_BUTTON7DOWN; 2775 } else { 2776 if (pb->ipacket[4] & 0x01) 2777 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2778 if (pb->ipacket[5] & 0x01) 2779 touchpad_buttons |= MOUSE_BUTTON3DOWN; 2780 if (pb->ipacket[4] & 0x02) 2781 touchpad_buttons |= MOUSE_BUTTON2DOWN; 2782 sc->extended_buttons = touchpad_buttons; 2783 } 2784 2785 /* 2786 * Zero out bits used by extended buttons to avoid 2787 * misinterpretation of the data absolute position. 2788 * 2789 * The bits represented by 2790 * 2791 * (nExtendedButtons + 1) >> 1 2792 * 2793 * will be masked out in both bytes. 2794 * The mask for n bits is computed with the formula 2795 * 2796 * (1 << n) - 1 2797 */ 2798 int maskedbits = 0; 2799 int mask = 0; 2800 maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; 2801 mask = (1 << maskedbits) - 1; 2802 pb->ipacket[4] &= ~(mask); 2803 pb->ipacket[5] &= ~(mask); 2804 } else if (!sc->syninfo.directional_scrolls && 2805 !sc->synaction.in_vscroll) { 2806 /* 2807 * Keep reporting MOUSE DOWN until we get a new packet 2808 * indicating otherwise. 2809 */ 2810 touchpad_buttons |= sc->extended_buttons; 2811 } 2812 } 2813 /* Handle ClickPad. */ 2814 if (sc->synhw.capClickPad && 2815 ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)) 2816 touchpad_buttons |= MOUSE_BUTTON1DOWN; 2817 2818 ms->button = touchpad_buttons | guest_buttons; 2819 2820 /* 2821 * Check pressure to detect a real wanted action on the 2822 * touchpad. 2823 */ 2824 if (*z >= sc->syninfo.min_pressure) { 2825 synapticsaction_t *synaction; 2826 int cursor, peer, window; 2827 int dx, dy, dxp, dyp; 2828 int max_width, max_pressure; 2829 int margin_top, margin_right, margin_bottom, margin_left; 2830 int na_top, na_right, na_bottom, na_left; 2831 int window_min, window_max; 2832 int multiplicator; 2833 int weight_current, weight_previous, weight_len_squared; 2834 int div_min, div_max, div_len; 2835 int vscroll_hor_area, vscroll_ver_area; 2836 int two_finger_scroll; 2837 int len, weight_prev_x, weight_prev_y; 2838 int div_max_x, div_max_y, div_x, div_y; 2839 2840 /* Read sysctl. */ 2841 /* XXX Verify values? */ 2842 max_width = sc->syninfo.max_width; 2843 max_pressure = sc->syninfo.max_pressure; 2844 margin_top = sc->syninfo.margin_top; 2845 margin_right = sc->syninfo.margin_right; 2846 margin_bottom = sc->syninfo.margin_bottom; 2847 margin_left = sc->syninfo.margin_left; 2848 na_top = sc->syninfo.na_top; 2849 na_right = sc->syninfo.na_right; 2850 na_bottom = sc->syninfo.na_bottom; 2851 na_left = sc->syninfo.na_left; 2852 window_min = sc->syninfo.window_min; 2853 window_max = sc->syninfo.window_max; 2854 multiplicator = sc->syninfo.multiplicator; 2855 weight_current = sc->syninfo.weight_current; 2856 weight_previous = sc->syninfo.weight_previous; 2857 weight_len_squared = sc->syninfo.weight_len_squared; 2858 div_min = sc->syninfo.div_min; 2859 div_max = sc->syninfo.div_max; 2860 div_len = sc->syninfo.div_len; 2861 vscroll_hor_area = sc->syninfo.vscroll_hor_area; 2862 vscroll_ver_area = sc->syninfo.vscroll_ver_area; 2863 two_finger_scroll = sc->syninfo.two_finger_scroll; 2864 2865 /* Palm detection. */ 2866 if (!( 2867 (sc->synhw.capMultiFinger && (w == 0 || w == 1)) || 2868 (sc->synhw.capPalmDetect && w >= 4 && w <= max_width) || 2869 (!sc->synhw.capPalmDetect && *z <= max_pressure) || 2870 (sc->synhw.capPen && w == 2))) { 2871 /* 2872 * We consider the packet irrelevant for the current 2873 * action when: 2874 * - the width isn't comprised in: 2875 * [4; max_width] 2876 * - the pressure isn't comprised in: 2877 * [min_pressure; max_pressure] 2878 * - pen aren't supported but w is 2 2879 * 2880 * Note that this doesn't terminate the current action. 2881 */ 2882 VLOG(2, (LOG_DEBUG, 2883 "synaptics: palm detected! (%d)\n", w)); 2884 goto SYNAPTICS_END; 2885 } 2886 2887 /* Read current absolute position. */ 2888 x0 = ((pb->ipacket[3] & 0x10) << 8) | 2889 ((pb->ipacket[1] & 0x0f) << 8) | 2890 pb->ipacket[4]; 2891 y0 = ((pb->ipacket[3] & 0x20) << 7) | 2892 ((pb->ipacket[1] & 0xf0) << 4) | 2893 pb->ipacket[5]; 2894 2895 synaction = &(sc->synaction); 2896 2897 /* 2898 * If the action is just beginning, init the structure and 2899 * compute tap timeout. 2900 */ 2901 if (!(sc->flags & PSM_FLAGS_FINGERDOWN)) { 2902 VLOG(3, (LOG_DEBUG, "synaptics: ----\n")); 2903 2904 /* Store the first point of this action. */ 2905 synaction->start_x = x0; 2906 synaction->start_y = y0; 2907 dx = dy = 0; 2908 2909 /* Initialize queue. */ 2910 synaction->queue_cursor = SYNAPTICS_PACKETQUEUE; 2911 synaction->queue_len = 0; 2912 synaction->window_min = window_min; 2913 2914 /* Reset average. */ 2915 synaction->avg_dx = 0; 2916 synaction->avg_dy = 0; 2917 2918 /* Reset squelch. */ 2919 synaction->squelch_x = 0; 2920 synaction->squelch_y = 0; 2921 2922 /* Reset pressure peak. */ 2923 sc->zmax = 0; 2924 2925 /* Reset fingers count. */ 2926 synaction->fingers_nb = 0; 2927 2928 /* Reset virtual scrolling state. */ 2929 synaction->in_vscroll = 0; 2930 2931 /* Compute tap timeout. */ 2932 sc->taptimeout.tv_sec = tap_timeout / 1000000; 2933 sc->taptimeout.tv_usec = tap_timeout % 1000000; 2934 timevaladd(&sc->taptimeout, &sc->lastsoftintr); 2935 2936 sc->flags |= PSM_FLAGS_FINGERDOWN; 2937 } else { 2938 /* Calculate the current delta. */ 2939 cursor = synaction->queue_cursor; 2940 dx = x0 - synaction->queue[cursor].x; 2941 dy = y0 - synaction->queue[cursor].y; 2942 } 2943 2944 /* If in tap-hold, add the recorded button. */ 2945 if (synaction->in_taphold) 2946 ms->button |= synaction->tap_button; 2947 2948 /* 2949 * From now on, we can use the SYNAPTICS_END label to skip 2950 * the current packet. 2951 */ 2952 2953 /* 2954 * Limit the coordinates to the specified margins because 2955 * this area isn't very reliable. 2956 */ 2957 if (x0 <= margin_left) 2958 x0 = margin_left; 2959 else if (x0 >= 6143 - margin_right) 2960 x0 = 6143 - margin_right; 2961 if (y0 <= margin_bottom) 2962 y0 = margin_bottom; 2963 else if (y0 >= 6143 - margin_top) 2964 y0 = 6143 - margin_top; 2965 2966 VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n", 2967 x0, y0, *z, w)); 2968 2969 /* Queue this new packet. */ 2970 cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1); 2971 synaction->queue[cursor].x = x0; 2972 synaction->queue[cursor].y = y0; 2973 synaction->queue_cursor = cursor; 2974 if (synaction->queue_len < SYNAPTICS_PACKETQUEUE) 2975 synaction->queue_len++; 2976 VLOG(5, (LOG_DEBUG, 2977 "synaptics: cursor[%d]: x=%d, y=%d, dx=%d, dy=%d\n", 2978 cursor, x0, y0, dx, dy)); 2979 2980 /* 2981 * For tap, we keep the maximum number of fingers and the 2982 * pressure peak. Also with multiple fingers, we increase 2983 * the minimum window. 2984 */ 2985 switch (w) { 2986 case 1: /* Three or more fingers. */ 2987 synaction->fingers_nb = imax(3, synaction->fingers_nb); 2988 synaction->window_min = window_max; 2989 break; 2990 case 0: /* Two fingers. */ 2991 synaction->fingers_nb = imax(2, synaction->fingers_nb); 2992 synaction->window_min = window_max; 2993 break; 2994 default: /* One finger or undetectable. */ 2995 synaction->fingers_nb = imax(1, synaction->fingers_nb); 2996 } 2997 sc->zmax = imax(*z, sc->zmax); 2998 2999 /* Do we have enough packets to consider this a movement? */ 3000 if (synaction->queue_len < synaction->window_min) 3001 goto SYNAPTICS_END; 3002 3003 /* Is a scrolling action occuring? */ 3004 if (!synaction->in_taphold && !synaction->in_vscroll) { 3005 /* 3006 * A scrolling action must not conflict with a tap 3007 * action. Here are the conditions to consider a 3008 * scrolling action: 3009 * - the action in a configurable area 3010 * - one of the following: 3011 * . the distance between the last packet and the 3012 * first should be above a configurable minimum 3013 * . tap timed out 3014 */ 3015 dxp = abs(synaction->queue[synaction->queue_cursor].x - 3016 synaction->start_x); 3017 dyp = abs(synaction->queue[synaction->queue_cursor].y - 3018 synaction->start_y); 3019 3020 if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, >) || 3021 dxp >= sc->syninfo.vscroll_min_delta || 3022 dyp >= sc->syninfo.vscroll_min_delta) { 3023 /* 3024 * Handle two finger scrolling. 3025 * Note that we don't rely on fingers_nb 3026 * as that keeps the maximum number of fingers. 3027 */ 3028 if (two_finger_scroll) { 3029 if (w == 0) { 3030 synaction->in_vscroll += 3031 dyp ? 2 : 0; 3032 synaction->in_vscroll += 3033 dxp ? 1 : 0; 3034 } 3035 } else { 3036 /* Check for horizontal scrolling. */ 3037 if ((vscroll_hor_area > 0 && 3038 synaction->start_y <= 3039 vscroll_hor_area) || 3040 (vscroll_hor_area < 0 && 3041 synaction->start_y >= 3042 6143 + vscroll_hor_area)) 3043 synaction->in_vscroll += 2; 3044 3045 /* Check for vertical scrolling. */ 3046 if ((vscroll_ver_area > 0 && 3047 synaction->start_x <= 3048 vscroll_ver_area) || 3049 (vscroll_ver_area < 0 && 3050 synaction->start_x >= 3051 6143 + vscroll_ver_area)) 3052 synaction->in_vscroll += 1; 3053 } 3054 3055 /* Avoid conflicts if area overlaps. */ 3056 if (synaction->in_vscroll >= 3) 3057 synaction->in_vscroll = 3058 (dxp > dyp) ? 2 : 1; 3059 } 3060 } 3061 /* 3062 * Reset two finger scrolling when the number of fingers 3063 * is different from two. 3064 */ 3065 if (two_finger_scroll && w != 0) 3066 synaction->in_vscroll = 0; 3067 3068 VLOG(5, (LOG_DEBUG, 3069 "synaptics: virtual scrolling: %s " 3070 "(direction=%d, dxp=%d, dyp=%d, fingers=%d)\n", 3071 synaction->in_vscroll ? "YES" : "NO", 3072 synaction->in_vscroll, dxp, dyp, 3073 synaction->fingers_nb)); 3074 3075 weight_prev_x = weight_prev_y = weight_previous; 3076 div_max_x = div_max_y = div_max; 3077 3078 if (synaction->in_vscroll) { 3079 /* Dividers are different with virtual scrolling. */ 3080 div_min = sc->syninfo.vscroll_div_min; 3081 div_max_x = div_max_y = sc->syninfo.vscroll_div_max; 3082 } else { 3083 /* 3084 * There's a lot of noise in coordinates when 3085 * the finger is on the touchpad's borders. When 3086 * using this area, we apply a special weight and 3087 * div. 3088 */ 3089 if (x0 <= na_left || x0 >= 6143 - na_right) { 3090 weight_prev_x = sc->syninfo.weight_previous_na; 3091 div_max_x = sc->syninfo.div_max_na; 3092 } 3093 3094 if (y0 <= na_bottom || y0 >= 6143 - na_top) { 3095 weight_prev_y = sc->syninfo.weight_previous_na; 3096 div_max_y = sc->syninfo.div_max_na; 3097 } 3098 } 3099 3100 /* 3101 * Calculate weights for the average operands and 3102 * the divisor. Both depend on the distance between 3103 * the current packet and a previous one (based on the 3104 * window width). 3105 */ 3106 window = imin(synaction->queue_len, window_max); 3107 peer = SYNAPTICS_QUEUE_CURSOR(cursor + window - 1); 3108 dxp = abs(x0 - synaction->queue[peer].x) + 1; 3109 dyp = abs(y0 - synaction->queue[peer].y) + 1; 3110 len = (dxp * dxp) + (dyp * dyp); 3111 weight_prev_x = imin(weight_prev_x, 3112 weight_len_squared * weight_prev_x / len); 3113 weight_prev_y = imin(weight_prev_y, 3114 weight_len_squared * weight_prev_y / len); 3115 3116 len = (dxp + dyp) / 2; 3117 div_x = div_len * div_max_x / len; 3118 div_x = imin(div_max_x, div_x); 3119 div_x = imax(div_min, div_x); 3120 div_y = div_len * div_max_y / len; 3121 div_y = imin(div_max_y, div_y); 3122 div_y = imax(div_min, div_y); 3123 3124 VLOG(3, (LOG_DEBUG, 3125 "synaptics: peer=%d, len=%d, weight=%d/%d, div=%d/%d\n", 3126 peer, len, weight_prev_x, weight_prev_y, div_x, div_y)); 3127 3128 /* Compute averages. */ 3129 synaction->avg_dx = 3130 (weight_current * dx * multiplicator + 3131 weight_prev_x * synaction->avg_dx) / 3132 (weight_current + weight_prev_x); 3133 3134 synaction->avg_dy = 3135 (weight_current * dy * multiplicator + 3136 weight_prev_y * synaction->avg_dy) / 3137 (weight_current + weight_prev_y); 3138 3139 VLOG(5, (LOG_DEBUG, 3140 "synaptics: avg_dx~=%d, avg_dy~=%d\n", 3141 synaction->avg_dx / multiplicator, 3142 synaction->avg_dy / multiplicator)); 3143 3144 /* Use these averages to calculate x & y. */ 3145 synaction->squelch_x += synaction->avg_dx; 3146 *x = synaction->squelch_x / (div_x * multiplicator); 3147 synaction->squelch_x = synaction->squelch_x % 3148 (div_x * multiplicator); 3149 3150 synaction->squelch_y += synaction->avg_dy; 3151 *y = synaction->squelch_y / (div_y * multiplicator); 3152 synaction->squelch_y = synaction->squelch_y % 3153 (div_y * multiplicator); 3154 3155 if (synaction->in_vscroll) { 3156 switch(synaction->in_vscroll) { 3157 case 1: /* Vertical scrolling. */ 3158 if (*y != 0) 3159 ms->button |= (*y > 0) ? 3160 MOUSE_BUTTON4DOWN : 3161 MOUSE_BUTTON5DOWN; 3162 break; 3163 case 2: /* Horizontal scrolling. */ 3164 if (*x != 0) 3165 ms->button |= (*x > 0) ? 3166 MOUSE_BUTTON7DOWN : 3167 MOUSE_BUTTON6DOWN; 3168 break; 3169 } 3170 3171 /* The pointer is not moved. */ 3172 *x = *y = 0; 3173 } else { 3174 VLOG(3, (LOG_DEBUG, "synaptics: [%d, %d] -> [%d, %d]\n", 3175 dx, dy, *x, *y)); 3176 } 3177 } else if (sc->flags & PSM_FLAGS_FINGERDOWN) { 3178 /* 3179 * An action is currently taking place but the pressure 3180 * dropped under the minimum, putting an end to it. 3181 */ 3182 synapticsaction_t *synaction; 3183 int taphold_timeout, dx, dy, tap_max_delta; 3184 3185 synaction = &(sc->synaction); 3186 dx = abs(synaction->queue[synaction->queue_cursor].x - 3187 synaction->start_x); 3188 dy = abs(synaction->queue[synaction->queue_cursor].y - 3189 synaction->start_y); 3190 3191 /* Max delta is disabled for multi-fingers tap. */ 3192 if (synaction->fingers_nb > 1) 3193 tap_max_delta = imax(dx, dy); 3194 else 3195 tap_max_delta = sc->syninfo.tap_max_delta; 3196 3197 sc->flags &= ~PSM_FLAGS_FINGERDOWN; 3198 3199 /* Check for tap. */ 3200 VLOG(3, (LOG_DEBUG, 3201 "synaptics: zmax=%d, dx=%d, dy=%d, " 3202 "delta=%d, fingers=%d, queue=%d\n", 3203 sc->zmax, dx, dy, tap_max_delta, synaction->fingers_nb, 3204 synaction->queue_len)); 3205 if (!synaction->in_vscroll && sc->zmax >= tap_threshold && 3206 timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=) && 3207 dx <= tap_max_delta && dy <= tap_max_delta && 3208 synaction->queue_len >= sc->syninfo.tap_min_queue) { 3209 /* 3210 * We have a tap if: 3211 * - the maximum pressure went over tap_threshold 3212 * - the action ended before tap_timeout 3213 * 3214 * To handle tap-hold, we must delay any button push to 3215 * the next action. 3216 */ 3217 if (synaction->in_taphold) { 3218 /* 3219 * This is the second and last tap of a 3220 * double tap action, not a tap-hold. 3221 */ 3222 synaction->in_taphold = 0; 3223 3224 /* 3225 * For double-tap to work: 3226 * - no button press is emitted (to 3227 * simulate a button release) 3228 * - PSM_FLAGS_FINGERDOWN is set to 3229 * force the next packet to emit a 3230 * button press) 3231 */ 3232 VLOG(2, (LOG_DEBUG, 3233 "synaptics: button RELEASE: %d\n", 3234 synaction->tap_button)); 3235 sc->flags |= PSM_FLAGS_FINGERDOWN; 3236 } else { 3237 /* 3238 * This is the first tap: we set the 3239 * tap-hold state and notify the button 3240 * down event. 3241 */ 3242 synaction->in_taphold = 1; 3243 taphold_timeout = sc->syninfo.taphold_timeout; 3244 sc->taptimeout.tv_sec = taphold_timeout / 3245 1000000; 3246 sc->taptimeout.tv_usec = taphold_timeout % 3247 1000000; 3248 timevaladd(&sc->taptimeout, &sc->lastsoftintr); 3249 3250 switch (synaction->fingers_nb) { 3251 case 3: 3252 synaction->tap_button = 3253 MOUSE_BUTTON2DOWN; 3254 break; 3255 case 2: 3256 synaction->tap_button = 3257 MOUSE_BUTTON3DOWN; 3258 break; 3259 default: 3260 synaction->tap_button = 3261 MOUSE_BUTTON1DOWN; 3262 } 3263 VLOG(2, (LOG_DEBUG, 3264 "synaptics: button PRESS: %d\n", 3265 synaction->tap_button)); 3266 ms->button |= synaction->tap_button; 3267 } 3268 } else { 3269 /* 3270 * Not enough pressure or timeout: reset 3271 * tap-hold state. 3272 */ 3273 if (synaction->in_taphold) { 3274 VLOG(2, (LOG_DEBUG, 3275 "synaptics: button RELEASE: %d\n", 3276 synaction->tap_button)); 3277 synaction->in_taphold = 0; 3278 } else { 3279 VLOG(2, (LOG_DEBUG, 3280 "synaptics: not a tap-hold\n")); 3281 } 3282 } 3283 } else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && 3284 sc->synaction.in_taphold) { 3285 /* 3286 * For a tap-hold to work, the button must remain down at 3287 * least until timeout (where the in_taphold flags will be 3288 * cleared) or during the next action. 3289 */ 3290 if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) { 3291 ms->button |= sc->synaction.tap_button; 3292 } else { 3293 VLOG(2, (LOG_DEBUG, 3294 "synaptics: button RELEASE: %d\n", 3295 sc->synaction.tap_button)); 3296 sc->synaction.in_taphold = 0; 3297 } 3298 } 3299 3300 SYNAPTICS_END: 3301 /* 3302 * Use the extra buttons as a scrollwheel 3303 * 3304 * XXX X.Org uses the Z axis for vertical wheel only, 3305 * whereas moused(8) understands special values to differ 3306 * vertical and horizontal wheels. 3307 * 3308 * xf86-input-mouse needs therefore a small patch to 3309 * understand these special values. Without it, the 3310 * horizontal wheel acts as a vertical wheel in X.Org. 3311 * 3312 * That's why the horizontal wheel is disabled by 3313 * default for now. 3314 */ 3315 3316 if (ms->button & MOUSE_BUTTON4DOWN) { 3317 *z = -1; 3318 ms->button &= ~MOUSE_BUTTON4DOWN; 3319 } else if (ms->button & MOUSE_BUTTON5DOWN) { 3320 *z = 1; 3321 ms->button &= ~MOUSE_BUTTON5DOWN; 3322 } else if (ms->button & MOUSE_BUTTON6DOWN) { 3323 *z = -2; 3324 ms->button &= ~MOUSE_BUTTON6DOWN; 3325 } else if (ms->button & MOUSE_BUTTON7DOWN) { 3326 *z = 2; 3327 ms->button &= ~MOUSE_BUTTON7DOWN; 3328 } else 3329 *z = 0; 3330 3331 return (0); 3332 } 3333 3334 static void 3335 proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, 3336 int *x, int *y, int *z) 3337 { 3338 static int butmap_versapad[8] = { 3339 0, 3340 MOUSE_BUTTON3DOWN, 3341 0, 3342 MOUSE_BUTTON3DOWN, 3343 MOUSE_BUTTON1DOWN, 3344 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 3345 MOUSE_BUTTON1DOWN, 3346 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN 3347 }; 3348 int c, x0, y0; 3349 3350 /* VersaPad PS/2 absolute mode message format 3351 * 3352 * [packet1] 7 6 5 4 3 2 1 0(LSB) 3353 * ipacket[0]: 1 1 0 A 1 L T R 3354 * ipacket[1]: H7 H6 H5 H4 H3 H2 H1 H0 3355 * ipacket[2]: V7 V6 V5 V4 V3 V2 V1 V0 3356 * ipacket[3]: 1 1 1 A 1 L T R 3357 * ipacket[4]:V11 V10 V9 V8 H11 H10 H9 H8 3358 * ipacket[5]: 0 P6 P5 P4 P3 P2 P1 P0 3359 * 3360 * [note] 3361 * R: right physical mouse button (1=on) 3362 * T: touch pad virtual button (1=tapping) 3363 * L: left physical mouse button (1=on) 3364 * A: position data is valid (1=valid) 3365 * H: horizontal data (12bit signed integer. H11 is sign bit.) 3366 * V: vertical data (12bit signed integer. V11 is sign bit.) 3367 * P: pressure data 3368 * 3369 * Tapping is mapped to MOUSE_BUTTON4. 3370 */ 3371 c = pb->ipacket[0]; 3372 *x = *y = 0; 3373 ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS]; 3374 ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0; 3375 if (c & MOUSE_PS2VERSA_IN_USE) { 3376 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8); 3377 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4); 3378 if (x0 & 0x800) 3379 x0 -= 0x1000; 3380 if (y0 & 0x800) 3381 y0 -= 0x1000; 3382 if (sc->flags & PSM_FLAGS_FINGERDOWN) { 3383 *x = sc->xold - x0; 3384 *y = y0 - sc->yold; 3385 if (*x < 0) /* XXX */ 3386 ++*x; 3387 else if (*x) 3388 --*x; 3389 if (*y < 0) 3390 ++*y; 3391 else if (*y) 3392 --*y; 3393 } else 3394 sc->flags |= PSM_FLAGS_FINGERDOWN; 3395 sc->xold = x0; 3396 sc->yold = y0; 3397 } else 3398 sc->flags &= ~PSM_FLAGS_FINGERDOWN; 3399 } 3400 3401 static void 3402 psmsoftintr(void *arg) 3403 { 3404 /* 3405 * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN) 3406 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). 3407 */ 3408 static int butmap[8] = { 3409 0, 3410 MOUSE_BUTTON1DOWN, 3411 MOUSE_BUTTON3DOWN, 3412 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 3413 MOUSE_BUTTON2DOWN, 3414 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 3415 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 3416 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 3417 }; 3418 struct psm_softc *sc = arg; 3419 mousestatus_t ms; 3420 packetbuf_t *pb; 3421 int x, y, z, c, l, s; 3422 3423 getmicrouptime(&sc->lastsoftintr); 3424 3425 s = spltty(); 3426 3427 do { 3428 pb = &sc->pqueue[sc->pqueue_start]; 3429 3430 if (sc->mode.level == PSM_LEVEL_NATIVE) 3431 goto next_native; 3432 3433 c = pb->ipacket[0]; 3434 /* 3435 * A kludge for Kensington device! 3436 * The MSB of the horizontal count appears to be stored in 3437 * a strange place. 3438 */ 3439 if (sc->hw.model == MOUSE_MODEL_THINK) 3440 pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0; 3441 3442 /* ignore the overflow bits... */ 3443 x = (c & MOUSE_PS2_XNEG) ? 3444 pb->ipacket[1] - 256 : pb->ipacket[1]; 3445 y = (c & MOUSE_PS2_YNEG) ? 3446 pb->ipacket[2] - 256 : pb->ipacket[2]; 3447 z = 0; 3448 ms.obutton = sc->button; /* previous button state */ 3449 ms.button = butmap[c & MOUSE_PS2_BUTTONS]; 3450 /* `tapping' action */ 3451 if (sc->config & PSM_CONFIG_FORCETAP) 3452 ms.button |= ((c & MOUSE_PS2_TAP)) ? 3453 0 : MOUSE_BUTTON4DOWN; 3454 3455 switch (sc->hw.model) { 3456 3457 case MOUSE_MODEL_EXPLORER: 3458 /* 3459 * b7 b6 b5 b4 b3 b2 b1 b0 3460 * byte 1: oy ox sy sx 1 M R L 3461 * byte 2: x x x x x x x x 3462 * byte 3: y y y y y y y y 3463 * byte 4: * * S2 S1 s d2 d1 d0 3464 * 3465 * L, M, R, S1, S2: left, middle, right and side buttons 3466 * s: wheel data sign bit 3467 * d2-d0: wheel data 3468 */ 3469 z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ? 3470 (pb->ipacket[3] & 0x0f) - 16 : 3471 (pb->ipacket[3] & 0x0f); 3472 ms.button |= 3473 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ? 3474 MOUSE_BUTTON4DOWN : 0; 3475 ms.button |= 3476 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ? 3477 MOUSE_BUTTON5DOWN : 0; 3478 break; 3479 3480 case MOUSE_MODEL_INTELLI: 3481 case MOUSE_MODEL_NET: 3482 /* wheel data is in the fourth byte */ 3483 z = (char)pb->ipacket[3]; 3484 /* 3485 * XXX some mice may send 7 when there is no Z movement? */ 3486 if ((z >= 7) || (z <= -7)) 3487 z = 0; 3488 /* some compatible mice have additional buttons */ 3489 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN) ? 3490 MOUSE_BUTTON4DOWN : 0; 3491 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN) ? 3492 MOUSE_BUTTON5DOWN : 0; 3493 break; 3494 3495 case MOUSE_MODEL_MOUSEMANPLUS: 3496 proc_mmanplus(sc, pb, &ms, &x, &y, &z); 3497 break; 3498 3499 case MOUSE_MODEL_GLIDEPOINT: 3500 /* `tapping' action */ 3501 ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : 3502 MOUSE_BUTTON4DOWN; 3503 break; 3504 3505 case MOUSE_MODEL_NETSCROLL: 3506 /* 3507 * three addtional bytes encode buttons and 3508 * wheel events 3509 */ 3510 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ? 3511 MOUSE_BUTTON4DOWN : 0; 3512 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ? 3513 MOUSE_BUTTON5DOWN : 0; 3514 z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ? 3515 pb->ipacket[4] - 256 : pb->ipacket[4]; 3516 break; 3517 3518 case MOUSE_MODEL_THINK: 3519 /* the fourth button state in the first byte */ 3520 ms.button |= (c & MOUSE_PS2_TAP) ? 3521 MOUSE_BUTTON4DOWN : 0; 3522 break; 3523 3524 case MOUSE_MODEL_VERSAPAD: 3525 proc_versapad(sc, pb, &ms, &x, &y, &z); 3526 c = ((x < 0) ? MOUSE_PS2_XNEG : 0) | 3527 ((y < 0) ? MOUSE_PS2_YNEG : 0); 3528 break; 3529 3530 case MOUSE_MODEL_4D: 3531 /* 3532 * b7 b6 b5 b4 b3 b2 b1 b0 3533 * byte 1: s2 d2 s1 d1 1 M R L 3534 * byte 2: sx x x x x x x x 3535 * byte 3: sy y y y y y y y 3536 * 3537 * s1: wheel 1 direction 3538 * d1: wheel 1 data 3539 * s2: wheel 2 direction 3540 * d2: wheel 2 data 3541 */ 3542 x = (pb->ipacket[1] & 0x80) ? 3543 pb->ipacket[1] - 256 : pb->ipacket[1]; 3544 y = (pb->ipacket[2] & 0x80) ? 3545 pb->ipacket[2] - 256 : pb->ipacket[2]; 3546 switch (c & MOUSE_4D_WHEELBITS) { 3547 case 0x10: 3548 z = 1; 3549 break; 3550 case 0x30: 3551 z = -1; 3552 break; 3553 case 0x40: /* XXX 2nd wheel turning right */ 3554 z = 2; 3555 break; 3556 case 0xc0: /* XXX 2nd wheel turning left */ 3557 z = -2; 3558 break; 3559 } 3560 break; 3561 3562 case MOUSE_MODEL_4DPLUS: 3563 if ((x < 16 - 256) && (y < 16 - 256)) { 3564 /* 3565 * b7 b6 b5 b4 b3 b2 b1 b0 3566 * byte 1: 0 0 1 1 1 M R L 3567 * byte 2: 0 0 0 0 1 0 0 0 3568 * byte 3: 0 0 0 0 S s d1 d0 3569 * 3570 * L, M, R, S: left, middle, right, 3571 * and side buttons 3572 * s: wheel data sign bit 3573 * d1-d0: wheel data 3574 */ 3575 x = y = 0; 3576 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN) 3577 ms.button |= MOUSE_BUTTON4DOWN; 3578 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ? 3579 ((pb->ipacket[2] & 0x07) - 8) : 3580 (pb->ipacket[2] & 0x07) ; 3581 } else { 3582 /* preserve previous button states */ 3583 ms.button |= ms.obutton & MOUSE_EXTBUTTONS; 3584 } 3585 break; 3586 3587 case MOUSE_MODEL_SYNAPTICS: 3588 if (proc_synaptics(sc, pb, &ms, &x, &y, &z) != 0) 3589 goto next; 3590 break; 3591 3592 case MOUSE_MODEL_TRACKPOINT: 3593 case MOUSE_MODEL_GENERIC: 3594 default: 3595 break; 3596 } 3597 3598 /* scale values */ 3599 if (sc->mode.accelfactor >= 1) { 3600 if (x != 0) { 3601 x = x * x / sc->mode.accelfactor; 3602 if (x == 0) 3603 x = 1; 3604 if (c & MOUSE_PS2_XNEG) 3605 x = -x; 3606 } 3607 if (y != 0) { 3608 y = y * y / sc->mode.accelfactor; 3609 if (y == 0) 3610 y = 1; 3611 if (c & MOUSE_PS2_YNEG) 3612 y = -y; 3613 } 3614 } 3615 3616 ms.dx = x; 3617 ms.dy = y; 3618 ms.dz = z; 3619 ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) | 3620 (ms.obutton ^ ms.button); 3621 3622 pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket); 3623 3624 sc->status.flags |= ms.flags; 3625 sc->status.dx += ms.dx; 3626 sc->status.dy += ms.dy; 3627 sc->status.dz += ms.dz; 3628 sc->status.button = ms.button; 3629 sc->button = ms.button; 3630 3631 next_native: 3632 sc->watchdog = FALSE; 3633 3634 /* queue data */ 3635 if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) { 3636 l = imin(pb->inputbytes, 3637 sizeof(sc->queue.buf) - sc->queue.tail); 3638 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l); 3639 if (pb->inputbytes > l) 3640 bcopy(&pb->ipacket[l], &sc->queue.buf[0], 3641 pb->inputbytes - l); 3642 sc->queue.tail = (sc->queue.tail + pb->inputbytes) % 3643 sizeof(sc->queue.buf); 3644 sc->queue.count += pb->inputbytes; 3645 } 3646 pb->inputbytes = 0; 3647 3648 next: 3649 if (++sc->pqueue_start >= PSM_PACKETQUEUE) 3650 sc->pqueue_start = 0; 3651 } while (sc->pqueue_start != sc->pqueue_end); 3652 3653 if (sc->state & PSM_ASLP) { 3654 sc->state &= ~PSM_ASLP; 3655 wakeup(sc); 3656 } 3657 selwakeuppri(&sc->rsel, PZERO); 3658 if (sc->async != NULL) { 3659 pgsigio(&sc->async, SIGIO, 0); 3660 } 3661 sc->state &= ~PSM_SOFTARMED; 3662 splx(s); 3663 } 3664 3665 static int 3666 psmpoll(struct cdev *dev, int events, struct thread *td) 3667 { 3668 struct psm_softc *sc = dev->si_drv1; 3669 int s; 3670 int revents = 0; 3671 3672 /* Return true if a mouse event available */ 3673 s = spltty(); 3674 if (events & (POLLIN | POLLRDNORM)) { 3675 if (sc->queue.count > 0) 3676 revents |= events & (POLLIN | POLLRDNORM); 3677 else 3678 selrecord(td, &sc->rsel); 3679 } 3680 splx(s); 3681 3682 return (revents); 3683 } 3684 3685 /* vendor/model specific routines */ 3686 3687 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status) 3688 { 3689 if (set_mouse_resolution(kbdc, res) != res) 3690 return (FALSE); 3691 if (set_mouse_scaling(kbdc, scale) && 3692 set_mouse_scaling(kbdc, scale) && 3693 set_mouse_scaling(kbdc, scale) && 3694 (get_mouse_status(kbdc, status, 0, 3) >= 3)) 3695 return (TRUE); 3696 return (FALSE); 3697 } 3698 3699 static int 3700 mouse_ext_command(KBDC kbdc, int command) 3701 { 3702 int c; 3703 3704 c = (command >> 6) & 0x03; 3705 if (set_mouse_resolution(kbdc, c) != c) 3706 return (FALSE); 3707 c = (command >> 4) & 0x03; 3708 if (set_mouse_resolution(kbdc, c) != c) 3709 return (FALSE); 3710 c = (command >> 2) & 0x03; 3711 if (set_mouse_resolution(kbdc, c) != c) 3712 return (FALSE); 3713 c = (command >> 0) & 0x03; 3714 if (set_mouse_resolution(kbdc, c) != c) 3715 return (FALSE); 3716 return (TRUE); 3717 } 3718 3719 #ifdef notyet 3720 /* Logitech MouseMan Cordless II */ 3721 static int 3722 enable_lcordless(KDBC kbdc, struct psm_softc *sc) 3723 { 3724 int status[3]; 3725 int ch; 3726 3727 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 2, status)) 3728 return (FALSE); 3729 if (status[1] == PSMD_RES_HIGH) 3730 return (FALSE); 3731 ch = (status[0] & 0x07) - 1; /* channel # */ 3732 if ((ch <= 0) || (ch > 4)) 3733 return (FALSE); 3734 /* 3735 * status[1]: always one? 3736 * status[2]: battery status? (0-100) 3737 */ 3738 return (TRUE); 3739 } 3740 #endif /* notyet */ 3741 3742 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */ 3743 static int 3744 enable_groller(KBDC kbdc, struct psm_softc *sc) 3745 { 3746 int status[3]; 3747 3748 /* 3749 * The special sequence to enable the fourth button and the 3750 * roller. Immediately after this sequence check status bytes. 3751 * if the mouse is NetScroll, the second and the third bytes are 3752 * '3' and 'D'. 3753 */ 3754 3755 /* 3756 * If the mouse is an ordinary PS/2 mouse, the status bytes should 3757 * look like the following. 3758 * 3759 * byte 1 bit 7 always 0 3760 * bit 6 stream mode (0) 3761 * bit 5 disabled (0) 3762 * bit 4 1:1 scaling (0) 3763 * bit 3 always 0 3764 * bit 0-2 button status 3765 * byte 2 resolution (PSMD_RES_HIGH) 3766 * byte 3 report rate (?) 3767 */ 3768 3769 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 1, status)) 3770 return (FALSE); 3771 if ((status[1] != '3') || (status[2] != 'D')) 3772 return (FALSE); 3773 /* FIXME: SmartScroll Mouse has 5 buttons! XXX */ 3774 if (sc != NULL) 3775 sc->hw.buttons = 4; 3776 return (TRUE); 3777 } 3778 3779 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */ 3780 static int 3781 enable_gmouse(KBDC kbdc, struct psm_softc *sc) 3782 { 3783 int status[3]; 3784 3785 /* 3786 * The special sequence to enable the middle, "rubber" button. 3787 * Immediately after this sequence check status bytes. 3788 * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse, 3789 * the second and the third bytes are '3' and 'U'. 3790 * NOTE: NetMouse reports that it has three buttons although it has 3791 * two buttons and a rubber button. NetMouse Pro and MIE Mouse 3792 * say they have three buttons too and they do have a button on the 3793 * side... 3794 */ 3795 if (!mouse_id_proc1(kbdc, PSMD_RES_HIGH, 1, status)) 3796 return (FALSE); 3797 if ((status[1] != '3') || (status[2] != 'U')) 3798 return (FALSE); 3799 return (TRUE); 3800 } 3801 3802 /* ALPS GlidePoint */ 3803 static int 3804 enable_aglide(KBDC kbdc, struct psm_softc *sc) 3805 { 3806 int status[3]; 3807 3808 /* 3809 * The special sequence to obtain ALPS GlidePoint specific 3810 * information. Immediately after this sequence, status bytes will 3811 * contain something interesting. 3812 * NOTE: ALPS produces several models of GlidePoint. Some of those 3813 * do not respond to this sequence, thus, cannot be detected this way. 3814 */ 3815 if (set_mouse_sampling_rate(kbdc, 100) != 100) 3816 return (FALSE); 3817 if (!mouse_id_proc1(kbdc, PSMD_RES_LOW, 2, status)) 3818 return (FALSE); 3819 if ((status[1] == PSMD_RES_LOW) || (status[2] == 100)) 3820 return (FALSE); 3821 return (TRUE); 3822 } 3823 3824 /* Kensington ThinkingMouse/Trackball */ 3825 static int 3826 enable_kmouse(KBDC kbdc, struct psm_softc *sc) 3827 { 3828 static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; 3829 int status[3]; 3830 int id1; 3831 int id2; 3832 int i; 3833 3834 id1 = get_aux_id(kbdc); 3835 if (set_mouse_sampling_rate(kbdc, 10) != 10) 3836 return (FALSE); 3837 /* 3838 * The device is now in the native mode? It returns a different 3839 * ID value... 3840 */ 3841 id2 = get_aux_id(kbdc); 3842 if ((id1 == id2) || (id2 != 2)) 3843 return (FALSE); 3844 3845 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) 3846 return (FALSE); 3847 #if PSM_DEBUG >= 2 3848 /* at this point, resolution is LOW, sampling rate is 10/sec */ 3849 if (get_mouse_status(kbdc, status, 0, 3) < 3) 3850 return (FALSE); 3851 #endif 3852 3853 /* 3854 * The special sequence to enable the third and fourth buttons. 3855 * Otherwise they behave like the first and second buttons. 3856 */ 3857 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) 3858 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 3859 return (FALSE); 3860 3861 /* 3862 * At this point, the device is using default resolution and 3863 * sampling rate for the native mode. 3864 */ 3865 if (get_mouse_status(kbdc, status, 0, 3) < 3) 3866 return (FALSE); 3867 if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1])) 3868 return (FALSE); 3869 3870 /* the device appears be enabled by this sequence, diable it for now */ 3871 disable_aux_dev(kbdc); 3872 empty_aux_buffer(kbdc, 5); 3873 3874 return (TRUE); 3875 } 3876 3877 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */ 3878 static int 3879 enable_mmanplus(KBDC kbdc, struct psm_softc *sc) 3880 { 3881 int data[3]; 3882 3883 /* the special sequence to enable the fourth button and the roller. */ 3884 /* 3885 * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION 3886 * must be called exactly three times since the last RESET command 3887 * before this sequence. XXX 3888 */ 3889 if (!set_mouse_scaling(kbdc, 1)) 3890 return (FALSE); 3891 if (!mouse_ext_command(kbdc, 0x39) || !mouse_ext_command(kbdc, 0xdb)) 3892 return (FALSE); 3893 if (get_mouse_status(kbdc, data, 1, 3) < 3) 3894 return (FALSE); 3895 3896 /* 3897 * PS2++ protocol, packet type 0 3898 * 3899 * b7 b6 b5 b4 b3 b2 b1 b0 3900 * byte 1: * 1 p3 p2 1 * * * 3901 * byte 2: 1 1 p1 p0 m1 m0 1 0 3902 * byte 3: m7 m6 m5 m4 m3 m2 m1 m0 3903 * 3904 * p3-p0: packet type: 0 3905 * m7-m0: model ID: MouseMan+:0x50, 3906 * FirstMouse+:0x51, 3907 * ScrollPoint:0x58... 3908 */ 3909 /* check constant bits */ 3910 if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC) 3911 return (FALSE); 3912 if ((data[1] & 0xc3) != 0xc2) 3913 return (FALSE); 3914 /* check d3-d0 in byte 2 */ 3915 if (!MOUSE_PS2PLUS_CHECKBITS(data)) 3916 return (FALSE); 3917 /* check p3-p0 */ 3918 if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0) 3919 return (FALSE); 3920 3921 if (sc != NULL) { 3922 sc->hw.hwid &= 0x00ff; 3923 sc->hw.hwid |= data[2] << 8; /* save model ID */ 3924 } 3925 3926 /* 3927 * MouseMan+ (or FirstMouse+) is now in its native mode, in which 3928 * the wheel and the fourth button events are encoded in the 3929 * special data packet. The mouse may be put in the IntelliMouse mode 3930 * if it is initialized by the IntelliMouse's method. 3931 */ 3932 return (TRUE); 3933 } 3934 3935 /* MS IntelliMouse Explorer */ 3936 static int 3937 enable_msexplorer(KBDC kbdc, struct psm_softc *sc) 3938 { 3939 static u_char rate0[] = { 200, 100, 80, }; 3940 static u_char rate1[] = { 200, 200, 80, }; 3941 int id; 3942 int i; 3943 3944 /* 3945 * This is needed for at least A4Tech X-7xx mice - they do not go 3946 * straight to Explorer mode, but need to be set to Intelli mode 3947 * first. 3948 */ 3949 enable_msintelli(kbdc, sc); 3950 3951 /* the special sequence to enable the extra buttons and the roller. */ 3952 for (i = 0; i < sizeof(rate1)/sizeof(rate1[0]); ++i) 3953 if (set_mouse_sampling_rate(kbdc, rate1[i]) != rate1[i]) 3954 return (FALSE); 3955 /* the device will give the genuine ID only after the above sequence */ 3956 id = get_aux_id(kbdc); 3957 if (id != PSM_EXPLORER_ID) 3958 return (FALSE); 3959 3960 if (sc != NULL) { 3961 sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */ 3962 sc->hw.hwid = id; 3963 } 3964 3965 /* 3966 * XXX: this is a kludge to fool some KVM switch products 3967 * which think they are clever enough to know the 4-byte IntelliMouse 3968 * protocol, and assume any other protocols use 3-byte packets. 3969 * They don't convey 4-byte data packets from the IntelliMouse Explorer 3970 * correctly to the host computer because of this! 3971 * The following sequence is actually IntelliMouse's "wake up" 3972 * sequence; it will make the KVM think the mouse is IntelliMouse 3973 * when it is in fact IntelliMouse Explorer. 3974 */ 3975 for (i = 0; i < sizeof(rate0)/sizeof(rate0[0]); ++i) 3976 if (set_mouse_sampling_rate(kbdc, rate0[i]) != rate0[i]) 3977 break; 3978 get_aux_id(kbdc); 3979 3980 return (TRUE); 3981 } 3982 3983 /* MS IntelliMouse */ 3984 static int 3985 enable_msintelli(KBDC kbdc, struct psm_softc *sc) 3986 { 3987 /* 3988 * Logitech MouseMan+ and FirstMouse+ will also respond to this 3989 * probe routine and act like IntelliMouse. 3990 */ 3991 3992 static u_char rate[] = { 200, 100, 80, }; 3993 int id; 3994 int i; 3995 3996 /* the special sequence to enable the third button and the roller. */ 3997 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) 3998 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 3999 return (FALSE); 4000 /* the device will give the genuine ID only after the above sequence */ 4001 id = get_aux_id(kbdc); 4002 if (id != PSM_INTELLI_ID) 4003 return (FALSE); 4004 4005 if (sc != NULL) { 4006 sc->hw.buttons = 3; 4007 sc->hw.hwid = id; 4008 } 4009 4010 return (TRUE); 4011 } 4012 4013 /* A4 Tech 4D Mouse */ 4014 static int 4015 enable_4dmouse(KBDC kbdc, struct psm_softc *sc) 4016 { 4017 /* 4018 * Newer wheel mice from A4 Tech may use the 4D+ protocol. 4019 */ 4020 4021 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; 4022 int id; 4023 int i; 4024 4025 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) 4026 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4027 return (FALSE); 4028 id = get_aux_id(kbdc); 4029 /* 4030 * WinEasy 4D, 4 Way Scroll 4D: 6 4031 * Cable-Free 4D: 8 (4DPLUS) 4032 * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS) 4033 */ 4034 if (id != PSM_4DMOUSE_ID) 4035 return (FALSE); 4036 4037 if (sc != NULL) { 4038 sc->hw.buttons = 3; /* XXX some 4D mice have 4? */ 4039 sc->hw.hwid = id; 4040 } 4041 4042 return (TRUE); 4043 } 4044 4045 /* A4 Tech 4D+ Mouse */ 4046 static int 4047 enable_4dplus(KBDC kbdc, struct psm_softc *sc) 4048 { 4049 /* 4050 * Newer wheel mice from A4 Tech seem to use this protocol. 4051 * Older models are recognized as either 4D Mouse or IntelliMouse. 4052 */ 4053 int id; 4054 4055 /* 4056 * enable_4dmouse() already issued the following ID sequence... 4057 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; 4058 int i; 4059 4060 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) 4061 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) 4062 return (FALSE); 4063 */ 4064 4065 id = get_aux_id(kbdc); 4066 switch (id) { 4067 case PSM_4DPLUS_ID: 4068 break; 4069 case PSM_4DPLUS_RFSW35_ID: 4070 break; 4071 default: 4072 return (FALSE); 4073 } 4074 4075 if (sc != NULL) { 4076 sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3; 4077 sc->hw.hwid = id; 4078 } 4079 4080 return (TRUE); 4081 } 4082 4083 /* Synaptics Touchpad */ 4084 static int 4085 synaptics_sysctl(SYSCTL_HANDLER_ARGS) 4086 { 4087 int error, arg; 4088 4089 /* Read the current value. */ 4090 arg = *(int *)oidp->oid_arg1; 4091 error = sysctl_handle_int(oidp, &arg, 0, req); 4092 4093 /* Sanity check. */ 4094 if (error || !req->newptr) 4095 return (error); 4096 4097 /* 4098 * Check that the new value is in the concerned node's range 4099 * of values. 4100 */ 4101 switch (oidp->oid_arg2) { 4102 case SYNAPTICS_SYSCTL_MIN_PRESSURE: 4103 case SYNAPTICS_SYSCTL_MAX_PRESSURE: 4104 if (arg < 0 || arg > 255) 4105 return (EINVAL); 4106 break; 4107 case SYNAPTICS_SYSCTL_MAX_WIDTH: 4108 if (arg < 4 || arg > 15) 4109 return (EINVAL); 4110 break; 4111 case SYNAPTICS_SYSCTL_MARGIN_TOP: 4112 case SYNAPTICS_SYSCTL_MARGIN_RIGHT: 4113 case SYNAPTICS_SYSCTL_MARGIN_BOTTOM: 4114 case SYNAPTICS_SYSCTL_MARGIN_LEFT: 4115 case SYNAPTICS_SYSCTL_NA_TOP: 4116 case SYNAPTICS_SYSCTL_NA_RIGHT: 4117 case SYNAPTICS_SYSCTL_NA_BOTTOM: 4118 case SYNAPTICS_SYSCTL_NA_LEFT: 4119 if (arg < 0 || arg > 6143) 4120 return (EINVAL); 4121 break; 4122 case SYNAPTICS_SYSCTL_WINDOW_MIN: 4123 case SYNAPTICS_SYSCTL_WINDOW_MAX: 4124 case SYNAPTICS_SYSCTL_TAP_MIN_QUEUE: 4125 if (arg < 1 || arg > SYNAPTICS_PACKETQUEUE) 4126 return (EINVAL); 4127 break; 4128 case SYNAPTICS_SYSCTL_MULTIPLICATOR: 4129 case SYNAPTICS_SYSCTL_WEIGHT_CURRENT: 4130 case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS: 4131 case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA: 4132 case SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED: 4133 case SYNAPTICS_SYSCTL_DIV_MIN: 4134 case SYNAPTICS_SYSCTL_DIV_MAX: 4135 case SYNAPTICS_SYSCTL_DIV_MAX_NA: 4136 case SYNAPTICS_SYSCTL_DIV_LEN: 4137 case SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN: 4138 case SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX: 4139 if (arg < 1) 4140 return (EINVAL); 4141 break; 4142 case SYNAPTICS_SYSCTL_TAP_MAX_DELTA: 4143 case SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT: 4144 case SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA: 4145 if (arg < 0) 4146 return (EINVAL); 4147 break; 4148 case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA: 4149 case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA: 4150 if (arg < -6143 || arg > 6143) 4151 return (EINVAL); 4152 break; 4153 case SYNAPTICS_SYSCTL_TOUCHPAD_OFF: 4154 if (arg < 0 || arg > 1) 4155 return (EINVAL); 4156 break; 4157 default: 4158 return (EINVAL); 4159 } 4160 4161 /* Update. */ 4162 *(int *)oidp->oid_arg1 = arg; 4163 4164 return (error); 4165 } 4166 4167 static void 4168 synaptics_sysctl_create_tree(struct psm_softc *sc) 4169 { 4170 4171 if (sc->syninfo.sysctl_tree != NULL) 4172 return; 4173 4174 /* Attach extra synaptics sysctl nodes under hw.psm.synaptics */ 4175 sysctl_ctx_init(&sc->syninfo.sysctl_ctx); 4176 sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx, 4177 SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "synaptics", CTLFLAG_RD, 4178 0, "Synaptics TouchPad"); 4179 4180 /* hw.psm.synaptics.directional_scrolls. */ 4181 sc->syninfo.directional_scrolls = 0; 4182 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 4183 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4184 "directional_scrolls", CTLFLAG_RW|CTLFLAG_ANYBODY, 4185 &sc->syninfo.directional_scrolls, 0, 4186 "Enable hardware scrolling pad (if non-zero) or register it as " 4187 "extended buttons (if 0)"); 4188 4189 /* 4190 * Turn off two finger scroll if we have a 4191 * physical area reserved for scrolling or when 4192 * there's no multi finger support. 4193 */ 4194 if (sc->synhw.verticalScroll || sc->synhw.capMultiFinger == 0) 4195 sc->syninfo.two_finger_scroll = 0; 4196 else 4197 sc->syninfo.two_finger_scroll = 1; 4198 /* hw.psm.synaptics.two_finger_scroll. */ 4199 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx, 4200 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4201 "two_finger_scroll", CTLFLAG_RW|CTLFLAG_ANYBODY, 4202 &sc->syninfo.two_finger_scroll, 0, 4203 "Enable two finger scrolling"); 4204 4205 /* hw.psm.synaptics.min_pressure. */ 4206 sc->syninfo.min_pressure = 16; 4207 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4208 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4209 "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4210 &sc->syninfo.min_pressure, SYNAPTICS_SYSCTL_MIN_PRESSURE, 4211 synaptics_sysctl, "I", 4212 "Minimum pressure required to start an action"); 4213 4214 /* hw.psm.synaptics.max_pressure. */ 4215 sc->syninfo.max_pressure = 220; 4216 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4217 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4218 "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4219 &sc->syninfo.max_pressure, SYNAPTICS_SYSCTL_MAX_PRESSURE, 4220 synaptics_sysctl, "I", 4221 "Maximum pressure to detect palm"); 4222 4223 /* hw.psm.synaptics.max_width. */ 4224 sc->syninfo.max_width = 10; 4225 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4226 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4227 "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4228 &sc->syninfo.max_width, SYNAPTICS_SYSCTL_MAX_WIDTH, 4229 synaptics_sysctl, "I", 4230 "Maximum finger width to detect palm"); 4231 4232 /* hw.psm.synaptics.top_margin. */ 4233 sc->syninfo.margin_top = 200; 4234 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4235 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4236 "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4237 &sc->syninfo.margin_top, SYNAPTICS_SYSCTL_MARGIN_TOP, 4238 synaptics_sysctl, "I", 4239 "Top margin"); 4240 4241 /* hw.psm.synaptics.right_margin. */ 4242 sc->syninfo.margin_right = 200; 4243 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4244 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4245 "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4246 &sc->syninfo.margin_right, SYNAPTICS_SYSCTL_MARGIN_RIGHT, 4247 synaptics_sysctl, "I", 4248 "Right margin"); 4249 4250 /* hw.psm.synaptics.bottom_margin. */ 4251 sc->syninfo.margin_bottom = 200; 4252 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4253 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4254 "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4255 &sc->syninfo.margin_bottom, SYNAPTICS_SYSCTL_MARGIN_BOTTOM, 4256 synaptics_sysctl, "I", 4257 "Bottom margin"); 4258 4259 /* hw.psm.synaptics.left_margin. */ 4260 sc->syninfo.margin_left = 200; 4261 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4262 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4263 "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4264 &sc->syninfo.margin_left, SYNAPTICS_SYSCTL_MARGIN_LEFT, 4265 synaptics_sysctl, "I", 4266 "Left margin"); 4267 4268 /* hw.psm.synaptics.na_top. */ 4269 sc->syninfo.na_top = 1783; 4270 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4271 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4272 "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4273 &sc->syninfo.na_top, SYNAPTICS_SYSCTL_NA_TOP, 4274 synaptics_sysctl, "I", 4275 "Top noisy area, where weight_previous_na is used instead " 4276 "of weight_previous"); 4277 4278 /* hw.psm.synaptics.na_right. */ 4279 sc->syninfo.na_right = 563; 4280 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4281 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4282 "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4283 &sc->syninfo.na_right, SYNAPTICS_SYSCTL_NA_RIGHT, 4284 synaptics_sysctl, "I", 4285 "Right noisy area, where weight_previous_na is used instead " 4286 "of weight_previous"); 4287 4288 /* hw.psm.synaptics.na_bottom. */ 4289 sc->syninfo.na_bottom = 1408; 4290 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4291 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4292 "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4293 &sc->syninfo.na_bottom, SYNAPTICS_SYSCTL_NA_BOTTOM, 4294 synaptics_sysctl, "I", 4295 "Bottom noisy area, where weight_previous_na is used instead " 4296 "of weight_previous"); 4297 4298 /* hw.psm.synaptics.na_left. */ 4299 sc->syninfo.na_left = 1600; 4300 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4301 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4302 "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4303 &sc->syninfo.na_left, SYNAPTICS_SYSCTL_NA_LEFT, 4304 synaptics_sysctl, "I", 4305 "Left noisy area, where weight_previous_na is used instead " 4306 "of weight_previous"); 4307 4308 /* hw.psm.synaptics.window_min. */ 4309 sc->syninfo.window_min = 4; 4310 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4311 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4312 "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4313 &sc->syninfo.window_min, SYNAPTICS_SYSCTL_WINDOW_MIN, 4314 synaptics_sysctl, "I", 4315 "Minimum window size to start an action"); 4316 4317 /* hw.psm.synaptics.window_max. */ 4318 sc->syninfo.window_max = 10; 4319 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4320 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4321 "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4322 &sc->syninfo.window_max, SYNAPTICS_SYSCTL_WINDOW_MAX, 4323 synaptics_sysctl, "I", 4324 "Maximum window size"); 4325 4326 /* hw.psm.synaptics.multiplicator. */ 4327 sc->syninfo.multiplicator = 10000; 4328 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4329 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4330 "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4331 &sc->syninfo.multiplicator, SYNAPTICS_SYSCTL_MULTIPLICATOR, 4332 synaptics_sysctl, "I", 4333 "Multiplicator to increase precision in averages and divisions"); 4334 4335 /* hw.psm.synaptics.weight_current. */ 4336 sc->syninfo.weight_current = 3; 4337 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4338 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4339 "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4340 &sc->syninfo.weight_current, SYNAPTICS_SYSCTL_WEIGHT_CURRENT, 4341 synaptics_sysctl, "I", 4342 "Weight of the current movement in the new average"); 4343 4344 /* hw.psm.synaptics.weight_previous. */ 4345 sc->syninfo.weight_previous = 6; 4346 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4347 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4348 "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4349 &sc->syninfo.weight_previous, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS, 4350 synaptics_sysctl, "I", 4351 "Weight of the previous average"); 4352 4353 /* hw.psm.synaptics.weight_previous_na. */ 4354 sc->syninfo.weight_previous_na = 20; 4355 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4356 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4357 "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4358 &sc->syninfo.weight_previous_na, 4359 SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA, 4360 synaptics_sysctl, "I", 4361 "Weight of the previous average (inside the noisy area)"); 4362 4363 /* hw.psm.synaptics.weight_len_squared. */ 4364 sc->syninfo.weight_len_squared = 2000; 4365 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4366 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4367 "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4368 &sc->syninfo.weight_len_squared, 4369 SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED, 4370 synaptics_sysctl, "I", 4371 "Length (squared) of segments where weight_previous " 4372 "starts to decrease"); 4373 4374 /* hw.psm.synaptics.div_min. */ 4375 sc->syninfo.div_min = 9; 4376 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4377 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4378 "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4379 &sc->syninfo.div_min, SYNAPTICS_SYSCTL_DIV_MIN, 4380 synaptics_sysctl, "I", 4381 "Divisor for fast movements"); 4382 4383 /* hw.psm.synaptics.div_max. */ 4384 sc->syninfo.div_max = 17; 4385 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4386 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4387 "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4388 &sc->syninfo.div_max, SYNAPTICS_SYSCTL_DIV_MAX, 4389 synaptics_sysctl, "I", 4390 "Divisor for slow movements"); 4391 4392 /* hw.psm.synaptics.div_max_na. */ 4393 sc->syninfo.div_max_na = 30; 4394 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4395 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4396 "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4397 &sc->syninfo.div_max_na, SYNAPTICS_SYSCTL_DIV_MAX_NA, 4398 synaptics_sysctl, "I", 4399 "Divisor with slow movements (inside the noisy area)"); 4400 4401 /* hw.psm.synaptics.div_len. */ 4402 sc->syninfo.div_len = 100; 4403 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4404 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4405 "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4406 &sc->syninfo.div_len, SYNAPTICS_SYSCTL_DIV_LEN, 4407 synaptics_sysctl, "I", 4408 "Length of segments where div_max starts to decrease"); 4409 4410 /* hw.psm.synaptics.tap_max_delta. */ 4411 sc->syninfo.tap_max_delta = 80; 4412 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4413 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4414 "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4415 &sc->syninfo.tap_max_delta, SYNAPTICS_SYSCTL_TAP_MAX_DELTA, 4416 synaptics_sysctl, "I", 4417 "Length of segments above which a tap is ignored"); 4418 4419 /* hw.psm.synaptics.tap_min_queue. */ 4420 sc->syninfo.tap_min_queue = 2; 4421 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4422 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4423 "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4424 &sc->syninfo.tap_min_queue, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE, 4425 synaptics_sysctl, "I", 4426 "Number of packets required to consider a tap"); 4427 4428 /* hw.psm.synaptics.taphold_timeout. */ 4429 sc->synaction.in_taphold = 0; 4430 sc->syninfo.taphold_timeout = tap_timeout; 4431 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4432 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4433 "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4434 &sc->syninfo.taphold_timeout, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT, 4435 synaptics_sysctl, "I", 4436 "Maximum elapsed time between two taps to consider a tap-hold " 4437 "action"); 4438 4439 /* hw.psm.synaptics.vscroll_hor_area. */ 4440 sc->syninfo.vscroll_hor_area = 0; /* 1300 */ 4441 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4442 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4443 "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4444 &sc->syninfo.vscroll_hor_area, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA, 4445 synaptics_sysctl, "I", 4446 "Area reserved for horizontal virtual scrolling"); 4447 4448 /* hw.psm.synaptics.vscroll_ver_area. */ 4449 sc->syninfo.vscroll_ver_area = -600; 4450 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4451 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4452 "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4453 &sc->syninfo.vscroll_ver_area, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA, 4454 synaptics_sysctl, "I", 4455 "Area reserved for vertical virtual scrolling"); 4456 4457 /* hw.psm.synaptics.vscroll_min_delta. */ 4458 sc->syninfo.vscroll_min_delta = 50; 4459 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4460 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4461 "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4462 &sc->syninfo.vscroll_min_delta, 4463 SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA, 4464 synaptics_sysctl, "I", 4465 "Minimum movement to consider virtual scrolling"); 4466 4467 /* hw.psm.synaptics.vscroll_div_min. */ 4468 sc->syninfo.vscroll_div_min = 100; 4469 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4470 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4471 "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4472 &sc->syninfo.vscroll_div_min, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN, 4473 synaptics_sysctl, "I", 4474 "Divisor for fast scrolling"); 4475 4476 /* hw.psm.synaptics.vscroll_div_min. */ 4477 sc->syninfo.vscroll_div_max = 150; 4478 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4479 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4480 "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4481 &sc->syninfo.vscroll_div_max, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX, 4482 synaptics_sysctl, "I", 4483 "Divisor for slow scrolling"); 4484 4485 /* hw.psm.synaptics.touchpad_off. */ 4486 sc->syninfo.touchpad_off = 0; 4487 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx, 4488 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO, 4489 "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4490 &sc->syninfo.touchpad_off, SYNAPTICS_SYSCTL_TOUCHPAD_OFF, 4491 synaptics_sysctl, "I", 4492 "Turn off touchpad"); 4493 } 4494 4495 static int 4496 enable_synaptics(KBDC kbdc, struct psm_softc *sc) 4497 { 4498 synapticshw_t synhw; 4499 int status[3]; 4500 int buttons; 4501 4502 VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n")); 4503 4504 /* 4505 * Just to be on the safe side: this avoids troubles with 4506 * following mouse_ext_command() when the previous command 4507 * was PSMC_SET_RESOLUTION. Set Scaling has no effect on 4508 * Synaptics Touchpad behaviour. 4509 */ 4510 set_mouse_scaling(kbdc, 1); 4511 4512 /* Identify the Touchpad version. */ 4513 if (mouse_ext_command(kbdc, 0) == 0) 4514 return (FALSE); 4515 if (get_mouse_status(kbdc, status, 0, 3) != 3) 4516 return (FALSE); 4517 if (status[1] != 0x47) 4518 return (FALSE); 4519 4520 bzero(&synhw, sizeof(synhw)); 4521 synhw.infoMinor = status[0]; 4522 synhw.infoMajor = status[2] & 0x0f; 4523 4524 if (verbose >= 2) 4525 printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, 4526 synhw.infoMinor); 4527 4528 if (synhw.infoMajor < 4) { 4529 printf(" Unsupported (pre-v4) Touchpad detected\n"); 4530 return (FALSE); 4531 } 4532 4533 /* Get the Touchpad model information. */ 4534 if (mouse_ext_command(kbdc, 3) == 0) 4535 return (FALSE); 4536 if (get_mouse_status(kbdc, status, 0, 3) != 3) 4537 return (FALSE); 4538 if ((status[1] & 0x01) != 0) { 4539 printf(" Failed to read model information\n"); 4540 return (FALSE); 4541 } 4542 4543 synhw.infoRot180 = (status[0] & 0x80) != 0; 4544 synhw.infoPortrait = (status[0] & 0x40) != 0; 4545 synhw.infoSensor = status[0] & 0x3f; 4546 synhw.infoHardware = (status[1] & 0xfe) >> 1; 4547 synhw.infoNewAbs = (status[2] & 0x80) != 0; 4548 synhw.capPen = (status[2] & 0x40) != 0; 4549 synhw.infoSimplC = (status[2] & 0x20) != 0; 4550 synhw.infoGeometry = status[2] & 0x0f; 4551 4552 if (verbose >= 2) { 4553 printf(" Model information:\n"); 4554 printf(" infoRot180: %d\n", synhw.infoRot180); 4555 printf(" infoPortrait: %d\n", synhw.infoPortrait); 4556 printf(" infoSensor: %d\n", synhw.infoSensor); 4557 printf(" infoHardware: %d\n", synhw.infoHardware); 4558 printf(" infoNewAbs: %d\n", synhw.infoNewAbs); 4559 printf(" capPen: %d\n", synhw.capPen); 4560 printf(" infoSimplC: %d\n", synhw.infoSimplC); 4561 printf(" infoGeometry: %d\n", synhw.infoGeometry); 4562 } 4563 4564 /* Read the extended capability bits. */ 4565 if (mouse_ext_command(kbdc, 2) == 0) 4566 return (FALSE); 4567 if (get_mouse_status(kbdc, status, 0, 3) != 3) 4568 return (FALSE); 4569 if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { 4570 printf(" Failed to read extended capability bits\n"); 4571 return (FALSE); 4572 } 4573 4574 /* Set the different capabilities when they exist. */ 4575 buttons = 0; 4576 synhw.capExtended = (status[0] & 0x80) != 0; 4577 if (synhw.capExtended) { 4578 synhw.nExtendedQueries = (status[0] & 0x70) != 0; 4579 synhw.capMiddle = (status[0] & 0x04) != 0; 4580 synhw.capPassthrough = (status[2] & 0x80) != 0; 4581 synhw.capLowPower = (status[2] & 0x40) != 0; 4582 synhw.capMultiFingerReport = 4583 (status[2] & 0x20) != 0; 4584 synhw.capSleep = (status[2] & 0x10) != 0; 4585 synhw.capFourButtons = (status[2] & 0x08) != 0; 4586 synhw.capBallistics = (status[2] & 0x04) != 0; 4587 synhw.capMultiFinger = (status[2] & 0x02) != 0; 4588 synhw.capPalmDetect = (status[2] & 0x01) != 0; 4589 4590 if (verbose >= 2) { 4591 printf(" Extended capabilities:\n"); 4592 printf(" capExtended: %d\n", synhw.capExtended); 4593 printf(" capMiddle: %d\n", synhw.capMiddle); 4594 printf(" nExtendedQueries: %d\n", 4595 synhw.nExtendedQueries); 4596 printf(" capPassthrough: %d\n", synhw.capPassthrough); 4597 printf(" capLowPower: %d\n", synhw.capLowPower); 4598 printf(" capMultiFingerReport: %d\n", 4599 synhw.capMultiFingerReport); 4600 printf(" capSleep: %d\n", synhw.capSleep); 4601 printf(" capFourButtons: %d\n", synhw.capFourButtons); 4602 printf(" capBallistics: %d\n", synhw.capBallistics); 4603 printf(" capMultiFinger: %d\n", synhw.capMultiFinger); 4604 printf(" capPalmDetect: %d\n", synhw.capPalmDetect); 4605 } 4606 4607 /* 4608 * If nExtendedQueries is 1 or greater, then the TouchPad 4609 * supports this number of extended queries. We can load 4610 * more information about buttons using query 0x09. 4611 */ 4612 if (synhw.capExtended && synhw.nExtendedQueries) { 4613 if (mouse_ext_command(kbdc, 0x09) == 0) 4614 return (FALSE); 4615 if (get_mouse_status(kbdc, status, 0, 3) != 3) 4616 return (FALSE); 4617 synhw.verticalScroll = (status[0] & 0x01) != 0; 4618 synhw.horizontalScroll = (status[0] & 0x02) != 0; 4619 synhw.verticalWheel = (status[0] & 0x08) != 0; 4620 synhw.nExtendedButtons = (status[1] & 0xf0) >> 4; 4621 if (verbose >= 2) { 4622 printf(" Extended model ID:\n"); 4623 printf(" verticalScroll: %d\n", 4624 synhw.verticalScroll); 4625 printf(" horizontalScroll: %d\n", 4626 synhw.horizontalScroll); 4627 printf(" verticalWheel: %d\n", 4628 synhw.verticalWheel); 4629 printf(" nExtendedButtons: %d\n", 4630 synhw.nExtendedButtons); 4631 } 4632 /* 4633 * Add the number of extended buttons to the total 4634 * button support count, including the middle button 4635 * if capMiddle support bit is set. 4636 */ 4637 buttons = synhw.nExtendedButtons + synhw.capMiddle; 4638 } else 4639 /* 4640 * If the capFourButtons support bit is set, 4641 * add a fourth button to the total button count. 4642 */ 4643 buttons = synhw.capFourButtons ? 1 : 0; 4644 } 4645 if (verbose >= 2) { 4646 if (synhw.capExtended) 4647 printf(" Additional Buttons: %d\n", buttons); 4648 else 4649 printf(" No extended capabilities\n"); 4650 } 4651 4652 /* Read the continued capabilities bits. */ 4653 if (mouse_ext_command(kbdc, 0xc) != 0 && 4654 get_mouse_status(kbdc, status, 0, 3) == 3) { 4655 synhw.capClickPad = (status[1] & 0x01) << 1; 4656 synhw.capClickPad |= (status[0] & 0x10) != 0; 4657 synhw.capDeluxeLEDs = (status[1] & 0x02) != 0; 4658 synhw.noAbsoluteFilter = (status[1] & 0x04) != 0; 4659 synhw.capReportsV = (status[1] & 0x08) != 0; 4660 synhw.capUniformClickPad = (status[1] & 0x10) != 0; 4661 synhw.capReportsMin = (status[1] & 0x20) != 0; 4662 synhw.capInterTouch = (status[1] & 0x40) != 0; 4663 synhw.capReportsMax = (status[2] & 0x02) != 0; 4664 synhw.capClearPad = (status[2] & 0x04) != 0; 4665 synhw.capAdvancedGestures = (status[2] & 0x08) != 0; 4666 synhw.capCoveredPad = (status[2] & 0x80) != 0; 4667 4668 if (verbose >= 2) { 4669 printf(" Continued capabilities:\n"); 4670 printf(" capClickPad: %d\n", synhw.capClickPad); 4671 printf(" capDeluxeLEDs: %d\n", synhw.capDeluxeLEDs); 4672 printf(" noAbsoluteFilter: %d\n", 4673 synhw.noAbsoluteFilter); 4674 printf(" capReportsV: %d\n", synhw.capReportsV); 4675 printf(" capUniformClickPad: %d\n", 4676 synhw.capUniformClickPad); 4677 printf(" capReportsMin: %d\n", synhw.capReportsMin); 4678 printf(" capInterTouch: %d\n", synhw.capInterTouch); 4679 printf(" capReportsMax: %d\n", synhw.capReportsMax); 4680 printf(" capClearPad: %d\n", synhw.capClearPad); 4681 printf(" capAdvancedGestures: %d\n", 4682 synhw.capAdvancedGestures); 4683 printf(" capCoveredPad: %d\n", synhw.capCoveredPad); 4684 } 4685 buttons += synhw.capClickPad; 4686 } 4687 4688 /* 4689 * Add the default number of 3 buttons to the total 4690 * count of supported buttons reported above. 4691 */ 4692 buttons += 3; 4693 4694 /* 4695 * Read the mode byte. 4696 * 4697 * XXX: Note the Synaptics documentation also defines the first 4698 * byte of the response to this query to be a constant 0x3b, this 4699 * does not appear to be true for Touchpads with guest devices. 4700 */ 4701 if (mouse_ext_command(kbdc, 1) == 0) 4702 return (FALSE); 4703 if (get_mouse_status(kbdc, status, 0, 3) != 3) 4704 return (FALSE); 4705 if (!SYNAPTICS_VERSION_GE(synhw, 7, 5) && status[1] != 0x47) { 4706 printf(" Failed to read mode byte\n"); 4707 return (FALSE); 4708 } 4709 4710 if (sc != NULL) 4711 sc->synhw = synhw; 4712 if (!synaptics_support) 4713 return (FALSE); 4714 4715 /* Set the mode byte; request wmode where available. */ 4716 mouse_ext_command(kbdc, synhw.capExtended ? 0xc1 : 0xc0); 4717 4718 /* "Commit" the Set Mode Byte command sent above. */ 4719 set_mouse_sampling_rate(kbdc, 20); 4720 4721 VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); 4722 4723 if (sc != NULL) { 4724 if (trackpoint_support && synhw.capPassthrough) { 4725 synaptics_passthrough_on(sc); 4726 enable_trackpoint(kbdc, sc); 4727 synaptics_passthrough_off(sc); 4728 } 4729 /* Create sysctl tree. */ 4730 synaptics_sysctl_create_tree(sc); 4731 sc->hw.buttons = buttons; 4732 } 4733 4734 return (TRUE); 4735 } 4736 4737 static void 4738 synaptics_passthrough_on(struct psm_softc *sc) 4739 { 4740 int mode_byte; 4741 4742 mode_byte = 0xc1 | (1 << 5); 4743 VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode. %d\n", 4744 mode_byte)); 4745 mouse_ext_command(sc->kbdc, mode_byte); 4746 4747 /* "Commit" the Set Mode Byte command sent above. */ 4748 set_mouse_sampling_rate(sc->kbdc, 20); 4749 } 4750 4751 static void 4752 synaptics_passthrough_off(struct psm_softc *sc) 4753 { 4754 int mode_byte; 4755 4756 mode_byte = 0xc1; 4757 VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n")); 4758 set_mouse_scaling(sc->kbdc, 2); 4759 set_mouse_scaling(sc->kbdc, 1); 4760 mouse_ext_command(sc->kbdc, mode_byte); 4761 4762 /* "Commit" the Set Mode Byte command sent above. */ 4763 set_mouse_sampling_rate(sc->kbdc, 20); 4764 } 4765 4766 /* IBM/Lenovo TrackPoint */ 4767 static int 4768 trackpoint_command(struct psm_softc *sc, int cmd, int loc, int val) 4769 { 4770 const int seq[] = { 0xe2, cmd, loc, val }; 4771 int i; 4772 4773 if (sc->synhw.capPassthrough) 4774 synaptics_passthrough_on(sc); 4775 4776 for (i = 0; i < nitems(seq); i++) { 4777 if (sc->synhw.capPassthrough && 4778 (seq[i] == 0xff || seq[i] == 0xe7)) 4779 if (send_aux_command(sc->kbdc, 0xe7) != PSM_ACK) { 4780 synaptics_passthrough_off(sc); 4781 return (EIO); 4782 } 4783 if (send_aux_command(sc->kbdc, seq[i]) != PSM_ACK) { 4784 if (sc->synhw.capPassthrough) 4785 synaptics_passthrough_off(sc); 4786 return (EIO); 4787 } 4788 } 4789 4790 if (sc->synhw.capPassthrough) 4791 synaptics_passthrough_off(sc); 4792 4793 return (0); 4794 } 4795 4796 #define PSM_TPINFO(x) offsetof(struct psm_softc, tpinfo.x) 4797 #define TPMASK 0 4798 #define TPLOC 1 4799 #define TPINFO 2 4800 4801 static int 4802 trackpoint_sysctl(SYSCTL_HANDLER_ARGS) 4803 { 4804 static const int data[][3] = { 4805 { 0x00, 0x4a, PSM_TPINFO(sensitivity) }, 4806 { 0x00, 0x4d, PSM_TPINFO(inertia) }, 4807 { 0x00, 0x60, PSM_TPINFO(uplateau) }, 4808 { 0x00, 0x57, PSM_TPINFO(reach) }, 4809 { 0x00, 0x58, PSM_TPINFO(draghys) }, 4810 { 0x00, 0x59, PSM_TPINFO(mindrag) }, 4811 { 0x00, 0x5a, PSM_TPINFO(upthresh) }, 4812 { 0x00, 0x5c, PSM_TPINFO(threshold) }, 4813 { 0x00, 0x5d, PSM_TPINFO(jenks) }, 4814 { 0x00, 0x5e, PSM_TPINFO(ztime) }, 4815 { 0x01, 0x2c, PSM_TPINFO(pts) }, 4816 { 0x08, 0x2d, PSM_TPINFO(skipback) } 4817 }; 4818 struct psm_softc *sc; 4819 int error, newval, *oldvalp; 4820 const int *tp; 4821 4822 if (arg1 == NULL || arg2 < 0 || arg2 >= nitems(data)) 4823 return (EINVAL); 4824 sc = arg1; 4825 tp = data[arg2]; 4826 oldvalp = (int *)((intptr_t)sc + tp[TPINFO]); 4827 newval = *oldvalp; 4828 error = sysctl_handle_int(oidp, &newval, 0, req); 4829 if (error != 0) 4830 return (error); 4831 if (newval == *oldvalp) 4832 return (0); 4833 if (newval < 0 || newval > (tp[TPMASK] == 0 ? 255 : 1)) 4834 return (EINVAL); 4835 error = trackpoint_command(sc, tp[TPMASK] == 0 ? 0x81 : 0x47, 4836 tp[TPLOC], tp[TPMASK] == 0 ? newval : tp[TPMASK]); 4837 if (error != 0) 4838 return (error); 4839 *oldvalp = newval; 4840 4841 return (0); 4842 } 4843 4844 static void 4845 trackpoint_sysctl_create_tree(struct psm_softc *sc) 4846 { 4847 4848 if (sc->tpinfo.sysctl_tree != NULL) 4849 return; 4850 4851 /* Attach extra trackpoint sysctl nodes under hw.psm.trackpoint */ 4852 sysctl_ctx_init(&sc->tpinfo.sysctl_ctx); 4853 sc->tpinfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->tpinfo.sysctl_ctx, 4854 SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "trackpoint", CTLFLAG_RD, 4855 0, "IBM/Lenovo TrackPoint"); 4856 4857 /* hw.psm.trackpoint.sensitivity */ 4858 sc->tpinfo.sensitivity = 0x80; 4859 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4860 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4861 "sensitivity", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4862 sc, TRACKPOINT_SYSCTL_SENSITIVITY, 4863 trackpoint_sysctl, "I", 4864 "Sensitivity"); 4865 4866 /* hw.psm.trackpoint.negative_inertia */ 4867 sc->tpinfo.inertia = 0x06; 4868 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4869 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4870 "negative_inertia", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4871 sc, TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, 4872 trackpoint_sysctl, "I", 4873 "Negative inertia factor"); 4874 4875 /* hw.psm.trackpoint.upper_plateau */ 4876 sc->tpinfo.uplateau = 0x61; 4877 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4878 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4879 "upper_plateau", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4880 sc, TRACKPOINT_SYSCTL_UPPER_PLATEAU, 4881 trackpoint_sysctl, "I", 4882 "Transfer function upper plateau speed"); 4883 4884 /* hw.psm.trackpoint.backup_range */ 4885 sc->tpinfo.reach = 0x0a; 4886 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4887 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4888 "backup_range", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4889 sc, TRACKPOINT_SYSCTL_BACKUP_RANGE, 4890 trackpoint_sysctl, "I", 4891 "Backup range"); 4892 4893 /* hw.psm.trackpoint.drag_hysteresis */ 4894 sc->tpinfo.draghys = 0xff; 4895 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4896 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4897 "drag_hysteresis", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4898 sc, TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, 4899 trackpoint_sysctl, "I", 4900 "Drag hysteresis"); 4901 4902 /* hw.psm.trackpoint.minimum_drag */ 4903 sc->tpinfo.mindrag = 0x14; 4904 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4905 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4906 "minimum_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4907 sc, TRACKPOINT_SYSCTL_MINIMUM_DRAG, 4908 trackpoint_sysctl, "I", 4909 "Minimum drag"); 4910 4911 /* hw.psm.trackpoint.up_threshold */ 4912 sc->tpinfo.upthresh = 0xff; 4913 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4914 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4915 "up_threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4916 sc, TRACKPOINT_SYSCTL_UP_THRESHOLD, 4917 trackpoint_sysctl, "I", 4918 "Up threshold for release"); 4919 4920 /* hw.psm.trackpoint.threshold */ 4921 sc->tpinfo.threshold = 0x08; 4922 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4923 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4924 "threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4925 sc, TRACKPOINT_SYSCTL_THRESHOLD, 4926 trackpoint_sysctl, "I", 4927 "Threshold"); 4928 4929 /* hw.psm.trackpoint.jenks_curvature */ 4930 sc->tpinfo.jenks = 0x87; 4931 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4932 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4933 "jenks_curvature", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4934 sc, TRACKPOINT_SYSCTL_JENKS_CURVATURE, 4935 trackpoint_sysctl, "I", 4936 "Jenks curvature"); 4937 4938 /* hw.psm.trackpoint.z_time */ 4939 sc->tpinfo.ztime = 0x26; 4940 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4941 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4942 "z_time", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4943 sc, TRACKPOINT_SYSCTL_Z_TIME, 4944 trackpoint_sysctl, "I", 4945 "Z time constant"); 4946 4947 /* hw.psm.trackpoint.press_to_select */ 4948 sc->tpinfo.pts = 0x00; 4949 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4950 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4951 "press_to_select", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4952 sc, TRACKPOINT_SYSCTL_PRESS_TO_SELECT, 4953 trackpoint_sysctl, "I", 4954 "Press to Select"); 4955 4956 /* hw.psm.trackpoint.skip_backups */ 4957 sc->tpinfo.skipback = 0x00; 4958 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, 4959 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, 4960 "skip_backups", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 4961 sc, TRACKPOINT_SYSCTL_SKIP_BACKUPS, 4962 trackpoint_sysctl, "I", 4963 "Skip backups from drags"); 4964 } 4965 4966 static void 4967 set_trackpoint_parameters(struct psm_softc *sc) 4968 { 4969 trackpoint_command(sc, 0x81, 0x4a, sc->tpinfo.sensitivity); 4970 trackpoint_command(sc, 0x81, 0x60, sc->tpinfo.uplateau); 4971 trackpoint_command(sc, 0x81, 0x4d, sc->tpinfo.inertia); 4972 trackpoint_command(sc, 0x81, 0x57, sc->tpinfo.reach); 4973 trackpoint_command(sc, 0x81, 0x58, sc->tpinfo.draghys); 4974 trackpoint_command(sc, 0x81, 0x59, sc->tpinfo.mindrag); 4975 trackpoint_command(sc, 0x81, 0x5a, sc->tpinfo.upthresh); 4976 trackpoint_command(sc, 0x81, 0x5c, sc->tpinfo.threshold); 4977 trackpoint_command(sc, 0x81, 0x5d, sc->tpinfo.jenks); 4978 trackpoint_command(sc, 0x81, 0x5e, sc->tpinfo.ztime); 4979 if (sc->tpinfo.pts == 0x01) 4980 trackpoint_command(sc, 0x47, 0x2c, 0x01); 4981 if (sc->tpinfo.skipback == 0x01) 4982 trackpoint_command(sc, 0x47, 0x2d, 0x08); 4983 } 4984 4985 static int 4986 enable_trackpoint(KBDC kbdc, struct psm_softc *sc) 4987 { 4988 int id; 4989 4990 if (send_aux_command(kbdc, 0xe1) != PSM_ACK || 4991 read_aux_data(kbdc) != 0x01) 4992 return (FALSE); 4993 id = read_aux_data(kbdc); 4994 if (id < 0x01) 4995 return (FALSE); 4996 if (sc != NULL) 4997 sc->tphw = id; 4998 if (!trackpoint_support) 4999 return (FALSE); 5000 5001 if (sc != NULL) { 5002 /* Create sysctl tree. */ 5003 trackpoint_sysctl_create_tree(sc); 5004 5005 /* 5006 * Don't overwrite hwid and buttons when we are 5007 * a guest device. 5008 */ 5009 if (!sc->synhw.capPassthrough) { 5010 sc->hw.hwid = id; 5011 sc->hw.buttons = 3; 5012 } 5013 } 5014 5015 return (TRUE); 5016 } 5017 5018 /* Interlink electronics VersaPad */ 5019 static int 5020 enable_versapad(KBDC kbdc, struct psm_softc *sc) 5021 { 5022 int data[3]; 5023 5024 set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */ 5025 set_mouse_sampling_rate(kbdc, 100); /* set rate 100 */ 5026 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5027 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5028 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5029 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5030 if (get_mouse_status(kbdc, data, 0, 3) < 3) /* get status */ 5031 return (FALSE); 5032 if (data[2] != 0xa || data[1] != 0 ) /* rate == 0xa && res. == 0 */ 5033 return (FALSE); 5034 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */ 5035 5036 return (TRUE); /* PS/2 absolute mode */ 5037 } 5038 5039 /* 5040 * Return true if 'now' is earlier than (start + (secs.usecs)). 5041 * Now may be NULL and the function will fetch the current time from 5042 * getmicrouptime(), or a cached 'now' can be passed in. 5043 * All values should be numbers derived from getmicrouptime(). 5044 */ 5045 static int 5046 timeelapsed(start, secs, usecs, now) 5047 const struct timeval *start, *now; 5048 int secs, usecs; 5049 { 5050 struct timeval snow, tv; 5051 5052 /* if there is no 'now' passed in, the get it as a convience. */ 5053 if (now == NULL) { 5054 getmicrouptime(&snow); 5055 now = &snow; 5056 } 5057 5058 tv.tv_sec = secs; 5059 tv.tv_usec = usecs; 5060 timevaladd(&tv, start); 5061 return (timevalcmp(&tv, now, <)); 5062 } 5063 5064 static int 5065 psmresume(device_t dev) 5066 { 5067 struct psm_softc *sc = device_get_softc(dev); 5068 int unit = device_get_unit(dev); 5069 int err; 5070 5071 VLOG(2, (LOG_NOTICE, "psm%d: system resume hook called.\n", unit)); 5072 5073 if ((sc->config & 5074 (PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND)) == 0) 5075 return (0); 5076 5077 err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND); 5078 5079 if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) { 5080 /* 5081 * Release the blocked process; it must be notified that 5082 * the device cannot be accessed anymore. 5083 */ 5084 sc->state &= ~PSM_ASLP; 5085 wakeup(sc); 5086 } 5087 5088 VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit)); 5089 5090 return (err); 5091 } 5092 5093 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0); 5094 5095 #ifdef DEV_ISA 5096 5097 /* 5098 * This sucks up assignments from PNPBIOS and ACPI. 5099 */ 5100 5101 /* 5102 * When the PS/2 mouse device is reported by ACPI or PnP BIOS, it may 5103 * appear BEFORE the AT keyboard controller. As the PS/2 mouse device 5104 * can be probed and attached only after the AT keyboard controller is 5105 * attached, we shall quietly reserve the IRQ resource for later use. 5106 * If the PS/2 mouse device is reported to us AFTER the keyboard controller, 5107 * copy the IRQ resource to the PS/2 mouse device instance hanging 5108 * under the keyboard controller, then probe and attach it. 5109 */ 5110 5111 static devclass_t psmcpnp_devclass; 5112 5113 static device_probe_t psmcpnp_probe; 5114 static device_attach_t psmcpnp_attach; 5115 5116 static device_method_t psmcpnp_methods[] = { 5117 DEVMETHOD(device_probe, psmcpnp_probe), 5118 DEVMETHOD(device_attach, psmcpnp_attach), 5119 5120 { 0, 0 } 5121 }; 5122 5123 static driver_t psmcpnp_driver = { 5124 PSMCPNP_DRIVER_NAME, 5125 psmcpnp_methods, 5126 1, /* no softc */ 5127 }; 5128 5129 static struct isa_pnp_id psmcpnp_ids[] = { 5130 { 0x030fd041, "PS/2 mouse port" }, /* PNP0F03 */ 5131 { 0x0e0fd041, "PS/2 mouse port" }, /* PNP0F0E */ 5132 { 0x120fd041, "PS/2 mouse port" }, /* PNP0F12 */ 5133 { 0x130fd041, "PS/2 mouse port" }, /* PNP0F13 */ 5134 { 0x1303d041, "PS/2 port" }, /* PNP0313, XXX */ 5135 { 0x02002e4f, "Dell PS/2 mouse port" }, /* Lat. X200, Dell */ 5136 { 0x0002a906, "ALPS Glide Point" }, /* ALPS Glide Point */ 5137 { 0x80374d24, "IBM PS/2 mouse port" }, /* IBM3780, ThinkPad */ 5138 { 0x81374d24, "IBM PS/2 mouse port" }, /* IBM3781, ThinkPad */ 5139 { 0x0190d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9001, Vaio */ 5140 { 0x0290d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9002, Vaio */ 5141 { 0x0390d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9003, Vaio */ 5142 { 0x0490d94d, "SONY VAIO PS/2 mouse port"}, /* SNY9004, Vaio */ 5143 { 0 } 5144 }; 5145 5146 static int 5147 create_a_copy(device_t atkbdc, device_t me) 5148 { 5149 device_t psm; 5150 u_long irq; 5151 5152 /* find the PS/2 mouse device instance under the keyboard controller */ 5153 psm = device_find_child(atkbdc, PSM_DRIVER_NAME, 5154 device_get_unit(atkbdc)); 5155 if (psm == NULL) 5156 return (ENXIO); 5157 if (device_get_state(psm) != DS_NOTPRESENT) 5158 return (0); 5159 5160 /* move our resource to the found device */ 5161 irq = bus_get_resource_start(me, SYS_RES_IRQ, 0); 5162 bus_delete_resource(me, SYS_RES_IRQ, 0); 5163 bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1); 5164 5165 /* ...then probe and attach it */ 5166 return (device_probe_and_attach(psm)); 5167 } 5168 5169 static int 5170 psmcpnp_probe(device_t dev) 5171 { 5172 struct resource *res; 5173 u_long irq; 5174 int rid; 5175 5176 if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids)) 5177 return (ENXIO); 5178 5179 /* 5180 * The PnP BIOS and ACPI are supposed to assign an IRQ (12) 5181 * to the PS/2 mouse device node. But, some buggy PnP BIOS 5182 * declares the PS/2 mouse device node without an IRQ resource! 5183 * If this happens, we shall refer to device hints. 5184 * If we still don't find it there, use a hardcoded value... XXX 5185 */ 5186 rid = 0; 5187 irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid); 5188 if (irq <= 0) { 5189 if (resource_long_value(PSM_DRIVER_NAME, 5190 device_get_unit(dev),"irq", &irq) != 0) 5191 irq = 12; /* XXX */ 5192 device_printf(dev, "irq resource info is missing; " 5193 "assuming irq %ld\n", irq); 5194 bus_set_resource(dev, SYS_RES_IRQ, rid, irq, 1); 5195 } 5196 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0); 5197 bus_release_resource(dev, SYS_RES_IRQ, rid, res); 5198 5199 /* keep quiet */ 5200 if (!bootverbose) 5201 device_quiet(dev); 5202 5203 return ((res == NULL) ? ENXIO : 0); 5204 } 5205 5206 static int 5207 psmcpnp_attach(device_t dev) 5208 { 5209 device_t atkbdc; 5210 5211 /* find the keyboard controller, which may be on acpi* or isa* bus */ 5212 atkbdc = devclass_get_device(devclass_find(ATKBDC_DRIVER_NAME), 5213 device_get_unit(dev)); 5214 if ((atkbdc != NULL) && (device_get_state(atkbdc) == DS_ATTACHED)) 5215 create_a_copy(atkbdc, dev); 5216 5217 return (0); 5218 } 5219 5220 DRIVER_MODULE(psmcpnp, isa, psmcpnp_driver, psmcpnp_devclass, 0, 0); 5221 DRIVER_MODULE(psmcpnp, acpi, psmcpnp_driver, psmcpnp_devclass, 0, 0); 5222 5223 #endif /* DEV_ISA */ 5224