mouse.c revision 4d6d3f96
1/* 2 * 3 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 4 * Copyright 1993 by David Dawes <dawes@xfree86.org> 5 * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich 6 * Copyright 1994-2002 by The XFree86 Project, Inc. 7 * Copyright 2002 by Paul Elliott 8 * 9 * Permission to use, copy, modify, distribute, and sell this software and its 10 * documentation for any purpose is hereby granted without fee, provided that 11 * the above copyright notice appear in all copies and that both that 12 * copyright notice and this permission notice appear in supporting 13 * documentation, and that the names of copyright holders not be 14 * used in advertising or publicity pertaining to distribution of the 15 * software without specific, written prior permission. The copyright holders 16 * make no representations about the suitability of this 17 * software for any purpose. It is provided "as is" without express or 18 * implied warranty. 19 * 20 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 21 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 22 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 24 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 25 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27 * 28 */ 29/* Patch for PS/2 Intellimouse - Tim Goodwin 1997-11-06. */ 30 31/* 32 * [JCH-96/01/21] Added fourth button support for PROT_GLIDEPOINT mouse 33 * protocol. 34 */ 35 36/* 37 * [TVO-97/03/05] Added microsoft IntelliMouse support 38 */ 39 40/* 41 * [PME-02/08/11] Added support for drag lock buttons 42 * for use with 4 button trackballs for convenience 43 * and to help limited dexterity persons 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50#include <xorg-server.h> 51#include <math.h> 52#include <string.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <X11/X.h> 56 57#include "xf86.h" 58 59#include <X11/extensions/XI.h> 60#include "extnsionst.h" 61#include "extinit.h" 62 63#include "xf86Xinput.h" 64#include "xf86_OSproc.h" 65#include "exevents.h" 66#include <X11/Xatom.h> 67#include "xserver-properties.h" 68#include "xf86-mouse-properties.h" 69 70#ifdef __NetBSD__ 71#include <time.h> 72#include <dev/wscons/wsconsio.h> 73#include <sys/ioctl.h> 74#endif 75 76#include "compiler.h" 77 78#include "xisb.h" 79#include "mouse.h" 80#include "mousePriv.h" 81#include "mipointer.h" 82 83/* Xorg >= 1.10 provides an asprintf() implementation even if libc doesn't */ 84#include "xorgVersion.h" 85#if defined(HAVE_ASPRINTF) || \ 86 (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)) 87# define USE_ASPRINTF 88#endif 89 90enum { 91 /* number of bits in mapped nibble */ 92 NIB_BITS=4, 93 /* size of map of nibbles to bitmask */ 94 NIB_SIZE= (1 << NIB_BITS), 95 /* mask for map */ 96 NIB_MASK= (NIB_SIZE -1), 97 /* number of maps to map all the buttons */ 98 NIB_COUNT = ((MSE_MAXBUTTONS+NIB_BITS-1)/NIB_BITS) 99}; 100 101/*data to be used in implementing trackball drag locks.*/ 102typedef struct _DragLockRec { 103 104 /* Fields used to implement trackball drag locks. */ 105 /* mask for those buttons that are ordinary drag lock buttons */ 106 int lockButtonsM; 107 108 /* mask for the master drag lock button if any */ 109 int masterLockM; 110 111 /* button state up/down from last time adjusted for drag locks */ 112 int lockLastButtons; 113 114 /* 115 * true if master lock state i.e. master drag lock 116 * button has just been pressed 117 */ 118 int masterTS; 119 120 /* simulate these buttons being down although they are not */ 121 int simulatedDown; 122 123 /* 124 * data to map bits for drag lock buttons to corresponding 125 * bits for the target buttons 126 */ 127 int nib_table[NIB_COUNT][NIB_SIZE]; 128 129} DragLockRec, *DragLockPtr; 130 131 132#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 23 133#define HAVE_THREADED_INPUT 1 134#endif 135 136#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 24 137#define BLOCK_HANDLER_ARGS void *data, void *waitTime 138#define WAKEUP_HANDLER_ARGS void *data, int i 139#else 140#define BLOCK_HANDLER_ARGS pointer data, struct timeval **waitTime, pointer LastSelectMask 141#define WAKEUP_HANDLER_ARGS void *data, int i, pointer LastSelectMask 142#endif 143 144#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 145static InputInfoPtr MousePreInit(InputDriverPtr drv, IDevPtr dev, int flags); 146#else 147static int MousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 148#endif 149 150static int MouseProc(DeviceIntPtr device, int what); 151static void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl); 152static void MousePostEvent(InputInfoPtr pInfo, int buttons, 153 int dx, int dy, int dz, int dw); 154static void MouseReadInput(InputInfoPtr pInfo); 155static void MouseBlockHandler(BLOCK_HANDLER_ARGS); 156static void MouseWakeupHandler(WAKEUP_HANDLER_ARGS); 157static void FlushButtons(MouseDevPtr pMse); 158 159static Bool SetupMouse(InputInfoPtr pInfo); 160static Bool initMouseHW(InputInfoPtr pInfo); 161#ifdef SUPPORT_MOUSE_RESET 162static Bool mouseReset(InputInfoPtr pInfo, unsigned char val); 163static void ps2WakeupHandler(pointer data, int i, pointer LastSelectMask); 164static void ps2BlockHandler(pointer data, struct timeval **waitTime, 165 pointer LastSelectMask); 166#endif 167static void Emulate3ButtonsSetEnabled(InputInfoPtr pInfo, Bool enable); 168 169/* mouse autoprobe stuff */ 170static const char *autoOSProtocol(InputInfoPtr pInfo, int *protoPara); 171static void autoProbeMouse(InputInfoPtr pInfo, Bool inSync, Bool lostSync); 172static void checkForErraticMovements(InputInfoPtr pInfo, int dx, int dy); 173static Bool collectData(MouseDevPtr pMse, unsigned char u); 174static void SetMouseProto(MouseDevPtr pMse, MouseProtocolID protocolID); 175static Bool autoGood(MouseDevPtr pMse); 176 177#undef MOUSE 178_X_EXPORT InputDriverRec MOUSE = { 179 .driverVersion = 1, 180 .driverName = "mouse", 181 .Identify = NULL, 182 .PreInit = MousePreInit, 183 .UnInit = NULL, 184 .module = NULL, 185#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 186 .default_options = NULL, 187#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 21 188 .capabilities = 0 189#endif 190#endif 191}; 192 193#define RETRY_COUNT 4 194 195/* Properties that can be set at runtime via xinput */ 196static Atom prop_mbemu = 0; /* Middle button emulation on/off property */ 197static Atom prop_mbtimeout = 0; /* Middle button timeout property */ 198 199/* 200 * Microsoft (all serial models), Logitech MouseMan, First Mouse, etc, 201 * ALPS GlidePoint, Thinking Mouse. 202 */ 203static const char *msDefaults[] = { 204 "BaudRate", "1200", 205 "DataBits", "7", 206 "StopBits", "1", 207 "Parity", "None", 208 "FlowControl", "None", 209 "VTime", "0", 210 "VMin", "1", 211 NULL 212}; 213/* MouseSystems */ 214static const char *mlDefaults[] = { 215 "BaudRate", "1200", 216 "DataBits", "8", 217 "StopBits", "2", 218 "Parity", "None", 219 "FlowControl", "None", 220 "VTime", "0", 221 "VMin", "1", 222 NULL 223}; 224/* MMSeries */ 225static const char *mmDefaults[] = { 226 "BaudRate", "1200", 227 "DataBits", "8", 228 "StopBits", "1", 229 "Parity", "Odd", 230 "FlowControl", "None", 231 "VTime", "0", 232 "VMin", "1", 233 NULL 234}; 235/* Hitachi Tablet */ 236static const char *mmhitDefaults[] = { 237 "BaudRate", "1200", 238 "DataBits", "8", 239 "StopBits", "1", 240 "Parity", "None", 241 "FlowControl", "None", 242 "VTime", "0", 243 "VMin", "1", 244 NULL 245}; 246/* AceCad Tablet */ 247static const char *acecadDefaults[] = { 248 "BaudRate", "9600", 249 "DataBits", "8", 250 "StopBits", "1", 251 "Parity", "Odd", 252 "FlowControl", "None", 253 "VTime", "0", 254 "VMin", "1", 255 NULL 256}; 257 258static MouseProtocolRec mouseProtocols[] = { 259 260 /* Serial protocols */ 261 { "Microsoft", MSE_SERIAL, msDefaults, PROT_MS }, 262 { "MouseSystems", MSE_SERIAL, mlDefaults, PROT_MSC }, 263 { "MMSeries", MSE_SERIAL, mmDefaults, PROT_MM }, 264 { "Logitech", MSE_SERIAL, mlDefaults, PROT_LOGI }, 265 { "MouseMan", MSE_SERIAL, msDefaults, PROT_LOGIMAN }, 266 { "MMHitTab", MSE_SERIAL, mmhitDefaults, PROT_MMHIT }, 267 { "GlidePoint", MSE_SERIAL, msDefaults, PROT_GLIDE }, 268 { "IntelliMouse", MSE_SERIAL, msDefaults, PROT_IMSERIAL }, 269 { "ThinkingMouse", MSE_SERIAL, msDefaults, PROT_THINKING }, 270 { "AceCad", MSE_SERIAL, acecadDefaults, PROT_ACECAD }, 271 { "ValuMouseScroll", MSE_SERIAL, msDefaults, PROT_VALUMOUSESCROLL }, 272 273 /* Standard PS/2 */ 274 { "PS/2", MSE_PS2, NULL, PROT_PS2 }, 275 { "GenericPS/2", MSE_PS2, NULL, PROT_GENPS2 }, 276 277 /* Extended PS/2 */ 278 { "ImPS/2", MSE_XPS2, NULL, PROT_IMPS2 }, 279 { "ExplorerPS/2", MSE_XPS2, NULL, PROT_EXPPS2 }, 280 { "ThinkingMousePS/2", MSE_XPS2, NULL, PROT_THINKPS2 }, 281 { "MouseManPlusPS/2", MSE_XPS2, NULL, PROT_MMPS2 }, 282 { "GlidePointPS/2", MSE_XPS2, NULL, PROT_GLIDEPS2 }, 283 { "NetMousePS/2", MSE_XPS2, NULL, PROT_NETPS2 }, 284 { "NetScrollPS/2", MSE_XPS2, NULL, PROT_NETSCPS2 }, 285 286 /* Bus Mouse */ 287 { "BusMouse", MSE_BUS, NULL, PROT_BM }, 288 289 /* Auto-detect (PnP) */ 290 { "Auto", MSE_AUTO, NULL, PROT_AUTO }, 291 292 /* Misc (usually OS-specific) */ 293 { "SysMouse", MSE_MISC, mlDefaults, PROT_SYSMOUSE }, 294 { "WSMouse", MSE_MISC, NULL, PROT_WSMOUSE }, 295 { "VUID", MSE_MISC, NULL, PROT_VUID }, 296 297 /* end of list */ 298 { NULL, MSE_NONE, NULL, PROT_UNKNOWN } 299}; 300 301/* Process options common to all mouse types. */ 302static void 303MouseCommonOptions(InputInfoPtr pInfo) 304{ 305 MouseDevPtr pMse; 306 MessageType buttons_from = X_CONFIG; 307 char *s; 308 int origButtons; 309 int i; 310 311 pMse = pInfo->private; 312 313 pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0); 314 if (!pMse->buttons) { 315 pMse->buttons = MSE_DFLTBUTTONS; 316 buttons_from = X_DEFAULT; 317 } 318 origButtons = pMse->buttons; 319 320 pMse->emulate3Buttons = xf86SetBoolOption(pInfo->options, 321 "Emulate3Buttons", FALSE); 322 if (!xf86FindOptionValue(pInfo->options,"Emulate3Buttons")) { 323 pMse->emulate3ButtonsSoft = TRUE; 324 pMse->emulate3Buttons = TRUE; 325 } 326 327 pMse->emulate3Timeout = xf86SetIntOption(pInfo->options, 328 "Emulate3Timeout", 50); 329 if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) { 330 MessageType from = X_CONFIG; 331 if (pMse->emulate3ButtonsSoft) 332 from = X_DEFAULT; 333 xf86Msg(from, "%s: Emulate3Buttons, Emulate3Timeout: %d\n", 334 pInfo->name, pMse->emulate3Timeout); 335 } 336 337 pMse->chordMiddle = xf86SetBoolOption(pInfo->options, "ChordMiddle", FALSE); 338 pMse->flipXY = xf86SetBoolOption(pInfo->options, "FlipXY", FALSE); 339 if (xf86SetBoolOption(pInfo->options, "InvX", FALSE)) { 340 pMse->invX = -1; 341 } else 342 pMse->invX = 1; 343 if (xf86SetBoolOption(pInfo->options, "InvY", FALSE)) { 344 pMse->invY = -1; 345 } else 346 pMse->invY = 1; 347 pMse->angleOffset = xf86SetIntOption(pInfo->options, "AngleOffset", 0); 348 349 350 if (pMse->pDragLock) 351 free(pMse->pDragLock); 352 pMse->pDragLock = NULL; 353 354 s = xf86SetStrOption(pInfo->options, "DragLockButtons", NULL); 355 356 if (s) { 357 int lock; /* lock button */ 358 int target; /* target button */ 359 int lockM,targetM; /* bitmasks for drag lock, target */ 360 int j; /* indexes */ 361 char *s1; /* parse input string */ 362 DragLockPtr pLock; 363 364 pLock = pMse->pDragLock = calloc(1, sizeof(DragLockRec)); 365 /* init code */ 366 367 /* initial string to be taken apart */ 368 s1 = s; 369 370 /* keep getting numbers which are buttons */ 371 while ((s1 != NULL) && (lock = strtol(s1, &s1, 10)) != 0) { 372 373 /* check sanity for a button */ 374 if ((lock < 0) || (lock > MSE_MAXBUTTONS)) { 375 xf86Msg(X_WARNING, "DragLock: Invalid button number = %d\n", 376 lock); 377 break; 378 }; 379 /* turn into a button mask */ 380 lockM = 1 << (lock - 1); 381 382 /* try to get drag lock button */ 383 if ((s1 == NULL) || ((target=strtol(s1, &s1, 10)) == 0)) { 384 /*if no target, must be a master drag lock button */ 385 /* save master drag lock mask */ 386 pLock->masterLockM = lockM; 387 xf86Msg(X_CONFIG, 388 "DragLock button %d is master drag lock", 389 lock); 390 } else { 391 /* have target button number*/ 392 /* check target button number for sanity */ 393 if ((target < 0) || (target > MSE_MAXBUTTONS)) { 394 xf86Msg(X_WARNING, 395 "DragLock: Invalid button number for target=%d\n", 396 target); 397 break; 398 } 399 400 /* target button mask */ 401 targetM = 1 << (target - 1); 402 403 xf86Msg(X_CONFIG, 404 "DragLock: button %d is drag lock for button %d\n", 405 lock,target); 406 lock--; 407 408 /* initialize table that maps drag lock mask to target mask */ 409 pLock->nib_table[lock / NIB_BITS][1 << (lock % NIB_BITS)] = 410 targetM; 411 412 /* add new drag lock to mask of drag locks */ 413 pLock->lockButtonsM |= lockM; 414 } 415 416 } 417 418 /* 419 * fill out rest of map that maps sets of drag lock buttons 420 * to sets of target buttons, in the form of masks 421 */ 422 423 /* for each nibble */ 424 for (i = 0; i < NIB_COUNT; i++) { 425 /* for each possible set of bits for that nibble */ 426 for (j = 0; j < NIB_SIZE; j++) { 427 int ff, fM, otherbits; 428 429 /* get first bit set in j*/ 430 ff = ffs(j) - 1; 431 /* if 0 bits set nothing to do */ 432 if (ff >= 0) { 433 /* form mask for fist bit set */ 434 fM = 1 << ff; 435 /* mask off first bit set to get remaining bits set*/ 436 otherbits = j & ~fM; 437 /* 438 * if otherbits =0 then only 1 bit set 439 * so j=fM 440 * nib_table[i][fM] already calculated if fM has 441 * only 1 bit set. 442 * nib_table[i][j] has already been filled in 443 * by previous loop. otherwise 444 * otherbits < j so nibtable[i][otherbits] 445 * has already been calculated. 446 */ 447 if (otherbits) 448 pLock->nib_table[i][j] = 449 pLock->nib_table[i][fM] | 450 pLock->nib_table[i][otherbits]; 451 452 } 453 } 454 } 455 free(s); 456 } 457 458 s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5"); 459 if (s) { 460 int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 461 char *msg = NULL; 462 463 pMse->negativeZ = pMse->positiveZ = MSE_NOAXISMAP; 464 pMse->negativeW = pMse->positiveW = MSE_NOAXISMAP; 465 if (!xf86NameCmp(s, "x")) { 466 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX; 467 msg = xstrdup("X axis"); 468 } else if (!xf86NameCmp(s, "y")) { 469 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY; 470 msg = xstrdup("Y axis"); 471 } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 && 472 b1 > 0 && b1 <= MSE_MAXBUTTONS && 473 b2 > 0 && b2 <= MSE_MAXBUTTONS) { 474 pMse->negativeZ = 1 << (b1-1); 475 pMse->positiveZ = 1 << (b2-1); 476 if (b3 > 0 && b3 <= MSE_MAXBUTTONS && 477 b4 > 0 && b4 <= MSE_MAXBUTTONS) { 478 pMse->negativeW = 1 << (b3-1); 479 pMse->positiveW = 1 << (b4-1); 480#ifdef USE_ASPRINTF 481 if (asprintf(&msg, "buttons %d, %d, %d and %d", 482 b1, b2, b3, b4) == -1) 483 msg = NULL; 484#else 485 msg = Xprintf("buttons %d, %d, %d and %d", b1, b2, b3, b4); 486#endif 487 } 488 else { 489#ifdef USE_ASPRINTF 490 if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 491 msg = NULL; 492#else 493 msg = Xprintf("buttons %d and %d", b1, b2); 494#endif 495 } 496 if (b1 > pMse->buttons) pMse->buttons = b1; 497 if (b2 > pMse->buttons) pMse->buttons = b2; 498 if (b3 > pMse->buttons) pMse->buttons = b3; 499 if (b4 > pMse->buttons) pMse->buttons = b4; 500 } 501 if (msg) { 502 xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg); 503 free(msg); 504 } else { 505 xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n", 506 pInfo->name, s); 507 } 508 free(s); 509 } 510 if (xf86SetBoolOption(pInfo->options, "EmulateWheel", FALSE)) { 511 Bool yFromConfig = FALSE; 512 int wheelButton; 513 514 pMse->emulateWheel = TRUE; 515 wheelButton = xf86SetIntOption(pInfo->options, 516 "EmulateWheelButton", 4); 517 if (wheelButton < 0 || wheelButton > MSE_MAXBUTTONS) { 518 xf86Msg(X_WARNING, "%s: Invalid EmulateWheelButton value: %d\n", 519 pInfo->name, wheelButton); 520 wheelButton = 4; 521 } 522 pMse->wheelButton = wheelButton; 523 524 pMse->wheelInertia = xf86SetIntOption(pInfo->options, 525 "EmulateWheelInertia", 10); 526 if (pMse->wheelInertia <= 0) { 527 xf86Msg(X_WARNING, "%s: Invalid EmulateWheelInertia value: %d\n", 528 pInfo->name, pMse->wheelInertia); 529 pMse->wheelInertia = 10; 530 } 531 pMse->wheelButtonTimeout = xf86SetIntOption(pInfo->options, 532 "EmulateWheelTimeout", 200); 533 if (pMse->wheelButtonTimeout <= 0) { 534 xf86Msg(X_WARNING, "%s: Invalid EmulateWheelTimeout value: %d\n", 535 pInfo->name, pMse->wheelButtonTimeout); 536 pMse->wheelButtonTimeout = 200; 537 } 538 539 pMse->negativeX = MSE_NOAXISMAP; 540 pMse->positiveX = MSE_NOAXISMAP; 541 s = xf86SetStrOption(pInfo->options, "XAxisMapping", NULL); 542 if (s) { 543 int b1 = 0, b2 = 0; 544 char *msg = NULL; 545 546 if ((sscanf(s, "%d %d", &b1, &b2) == 2) && 547 b1 > 0 && b1 <= MSE_MAXBUTTONS && 548 b2 > 0 && b2 <= MSE_MAXBUTTONS) { 549#ifdef USE_ASPRINTF 550 if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 551 msg = NULL; 552#else 553 msg = Xprintf("buttons %d and %d", b1, b2); 554#endif 555 pMse->negativeX = b1; 556 pMse->positiveX = b2; 557 if (b1 > pMse->buttons) pMse->buttons = b1; 558 if (b2 > pMse->buttons) pMse->buttons = b2; 559 } else { 560 xf86Msg(X_WARNING, "%s: Invalid XAxisMapping value: \"%s\"\n", 561 pInfo->name, s); 562 } 563 if (msg) { 564 xf86Msg(X_CONFIG, "%s: XAxisMapping: %s\n", pInfo->name, msg); 565 free(msg); 566 } 567 free(s); 568 } 569 s = xf86SetStrOption(pInfo->options, "YAxisMapping", NULL); 570 if (s) { 571 int b1 = 0, b2 = 0; 572 char *msg = NULL; 573 574 if ((sscanf(s, "%d %d", &b1, &b2) == 2) && 575 b1 > 0 && b1 <= MSE_MAXBUTTONS && 576 b2 > 0 && b2 <= MSE_MAXBUTTONS) { 577#ifdef USE_ASPRINTF 578 if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 579 msg = NULL; 580#else 581 msg = Xprintf("buttons %d and %d", b1, b2); 582#endif 583 pMse->negativeY = b1; 584 pMse->positiveY = b2; 585 if (b1 > pMse->buttons) pMse->buttons = b1; 586 if (b2 > pMse->buttons) pMse->buttons = b2; 587 yFromConfig = TRUE; 588 } else { 589 xf86Msg(X_WARNING, "%s: Invalid YAxisMapping value: \"%s\"\n", 590 pInfo->name, s); 591 } 592 if (msg) { 593 xf86Msg(X_CONFIG, "%s: YAxisMapping: %s\n", pInfo->name, msg); 594 free(msg); 595 } 596 free(s); 597 } 598 if (!yFromConfig) { 599 pMse->negativeY = 4; 600 pMse->positiveY = 5; 601 if (pMse->negativeY > pMse->buttons) 602 pMse->buttons = pMse->negativeY; 603 if (pMse->positiveY > pMse->buttons) 604 pMse->buttons = pMse->positiveY; 605 xf86Msg(X_DEFAULT, "%s: YAxisMapping: buttons %d and %d\n", 606 pInfo->name, pMse->negativeY, pMse->positiveY); 607 } 608 xf86Msg(X_CONFIG, "%s: EmulateWheel, EmulateWheelButton: %d, " 609 "EmulateWheelInertia: %d, " 610 "EmulateWheelTimeout: %d\n", 611 pInfo->name, wheelButton, pMse->wheelInertia, 612 pMse->wheelButtonTimeout); 613 } 614 s = xf86SetStrOption(pInfo->options, "ButtonMapping", NULL); 615 if (s) { 616 int b, n = 0; 617 char *s1 = s; 618 /* keep getting numbers which are buttons */ 619 while (s1 && n < MSE_MAXBUTTONS && (b = strtol(s1, &s1, 10)) != 0) { 620 /* check sanity for a button */ 621 if (b < 0 || b > MSE_MAXBUTTONS) { 622 xf86Msg(X_WARNING, 623 "ButtonMapping: Invalid button number = %d\n", b); 624 break; 625 }; 626 pMse->buttonMap[n++] = 1 << (b-1); 627 if (b > pMse->buttons) pMse->buttons = b; 628 } 629 free(s); 630 } 631 /* get maximum of mapped buttons */ 632 for (i = pMse->buttons-1; i >= 0; i--) { 633 int f = ffs (pMse->buttonMap[i]); 634 if (f > pMse->buttons) 635 pMse->buttons = f; 636 } 637 if (origButtons != pMse->buttons) 638 buttons_from = X_CONFIG; 639 xf86Msg(buttons_from, "%s: Buttons: %d\n", pInfo->name, pMse->buttons); 640 641 pMse->doubleClickSourceButtonMask = 0; 642 pMse->doubleClickTargetButtonMask = 0; 643 pMse->doubleClickTargetButton = 0; 644 s = xf86SetStrOption(pInfo->options, "DoubleClickButtons", NULL); 645 if (s) { 646 int b1 = 0, b2 = 0; 647 char *msg = NULL; 648 649 if ((sscanf(s, "%d %d", &b1, &b2) == 2) && 650 (b1 > 0) && (b1 <= MSE_MAXBUTTONS) && 651 (b2 > 0) && (b2 <= MSE_MAXBUTTONS)) { 652#ifdef USE_ASPRINTF 653 if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 654 msg = NULL; 655#else 656 msg = Xprintf("buttons %d and %d", b1, b2); 657#endif 658 pMse->doubleClickTargetButton = b1; 659 pMse->doubleClickTargetButtonMask = 1 << (b1 - 1); 660 pMse->doubleClickSourceButtonMask = 1 << (b2 - 1); 661 if (b1 > pMse->buttons) pMse->buttons = b1; 662 if (b2 > pMse->buttons) pMse->buttons = b2; 663 } else { 664 xf86Msg(X_WARNING, "%s: Invalid DoubleClickButtons value: \"%s\"\n", 665 pInfo->name, s); 666 } 667 if (msg) { 668 xf86Msg(X_CONFIG, "%s: DoubleClickButtons: %s\n", pInfo->name, msg); 669 free(msg); 670 } 671 free(s); 672 } 673} 674/* 675 * map bits corresponding to lock buttons. 676 * for each bit for a lock button, 677 * turn on bit corresponding to button button that the lock 678 * button services. 679 */ 680 681static int 682lock2targetMap(DragLockPtr pLock, int lockMask) 683{ 684 int result,i; 685 result = 0; 686 687 /* 688 * for each nibble group of bits, use 689 * map for that group to get corresponding 690 * bits, turn them on. 691 * if 4 or less buttons only first map will 692 * need to be used. 693 */ 694 for (i = 0; (i < NIB_COUNT) && lockMask; i++) { 695 result |= pLock->nib_table[i][lockMask& NIB_MASK]; 696 697 lockMask &= ~NIB_MASK; 698 lockMask >>= NIB_BITS; 699 } 700 return result; 701} 702 703static void 704MouseHWOptions(InputInfoPtr pInfo) 705{ 706 MouseDevPtr pMse = pInfo->private; 707 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 708 709 if (mPriv == NULL) 710 return; 711 712 if ((mPriv->soft 713 = xf86SetBoolOption(pInfo->options, "AutoSoft", FALSE))) { 714 xf86Msg(X_CONFIG, "Don't initialize mouse when auto-probing\n"); 715 } 716 pMse->sampleRate = xf86SetIntOption(pInfo->options, "SampleRate", 0); 717 pMse->resolution = xf86SetIntOption(pInfo->options, "Resolution", 0); 718 mPriv->sensitivity = xf86SetRealOption(pInfo->options, "Sensitivity", 1.0); 719} 720 721static void 722MouseSerialOptions(InputInfoPtr pInfo) 723{ 724 MouseDevPtr pMse = pInfo->private; 725 726 pMse->baudRate = xf86SetIntOption(pInfo->options, "BaudRate", 0); 727} 728 729static MouseProtocolID 730ProtocolNameToID(const char *name) 731{ 732 int i; 733 734 for (i = 0; mouseProtocols[i].name; i++) 735 if (xf86NameCmp(name, mouseProtocols[i].name) == 0) 736 return mouseProtocols[i].id; 737 return PROT_UNKNOWN; 738} 739 740static const char * 741ProtocolIDToName(MouseProtocolID id) 742{ 743 int i; 744 745 switch (id) { 746 case PROT_UNKNOWN: 747 return "Unknown"; 748 break; 749 case PROT_UNSUP: 750 return "Unsupported"; 751 break; 752 default: 753 for (i = 0; mouseProtocols[i].name; i++) 754 if (id == mouseProtocols[i].id) 755 return mouseProtocols[i].name; 756 return "Invalid"; 757 } 758} 759 760static int 761ProtocolIDToClass(MouseProtocolID id) 762{ 763 int i; 764 765 switch (id) { 766 case PROT_UNKNOWN: 767 case PROT_UNSUP: 768 return MSE_NONE; 769 break; 770 default: 771 for (i = 0; mouseProtocols[i].name; i++) 772 if (id == mouseProtocols[i].id) 773 return mouseProtocols[i].class; 774 return MSE_NONE; 775 } 776} 777 778static MouseProtocolPtr 779GetProtocol(MouseProtocolID id) { 780 int i; 781 782 switch (id) { 783 case PROT_UNKNOWN: 784 case PROT_UNSUP: 785 return NULL; 786 break; 787 default: 788 for (i = 0; mouseProtocols[i].name; i++) 789 if (id == mouseProtocols[i].id) { 790 return &mouseProtocols[i]; 791 } 792 return NULL; 793 } 794} 795 796static OSMouseInfoPtr osInfo = NULL; 797 798static Bool 799InitProtocols(void) 800{ 801 int classes; 802 int i; 803 804 if (osInfo) 805 return TRUE; 806 807 osInfo = OSMouseInit(0); 808 if (!osInfo) 809 return FALSE; 810 if (!osInfo->SupportedInterfaces) 811 return FALSE; 812 813 classes = osInfo->SupportedInterfaces(); 814 if (!classes) 815 return FALSE; 816 817 /* Mark unsupported interface classes. */ 818 for (i = 0; mouseProtocols[i].name; i++) 819 if (!(mouseProtocols[i].class & classes)) 820 mouseProtocols[i].id = PROT_UNSUP; 821 822 for (i = 0; mouseProtocols[i].name; i++) 823 if (mouseProtocols[i].class & MSE_MISC) 824 if (!osInfo->CheckProtocol || 825 !osInfo->CheckProtocol(mouseProtocols[i].name)) 826 mouseProtocols[i].id = PROT_UNSUP; 827 828 /* NetBSD uses PROT_BM for "PS/2". */ 829#if defined(__NetBSD__) 830 for (i = 0; mouseProtocols[i].name; i++) 831 if (mouseProtocols[i].id == PROT_PS2) 832 mouseProtocols[i].id = PROT_BM; 833#endif 834 835 return TRUE; 836} 837 838static const char* 839MouseFindDevice(InputInfoPtr pInfo, const char* protocol) 840{ 841 const char *device; 842 843 if (!osInfo->FindDevice) 844 return NULL; 845 846 xf86Msg(X_WARNING, "%s: No Device specified, looking for one...\n", pInfo->name); 847 device = osInfo->FindDevice(pInfo, protocol, 0); 848 if (!device) 849 xf86Msg(X_ERROR, "%s: Cannot find which device to use.\n", pInfo->name); 850 else 851 xf86Msg(X_PROBED, "%s: Device: \"%s\"\n", pInfo->name, device); 852 853 return device; 854} 855 856static const char* 857MousePickProtocol(InputInfoPtr pInfo, const char* device, 858 const char *protocol, MouseProtocolID *protocolID_out) 859{ 860 MouseProtocolID protocolID = *protocolID_out; 861 862 protocolID = ProtocolNameToID(protocol); 863 864 if (protocolID == PROT_AUTO) 865 { 866 const char *osProt; 867 if (osInfo->SetupAuto && (osProt = osInfo->SetupAuto(pInfo,NULL))) { 868 protocolID = ProtocolNameToID(osProt); 869 protocol = osProt; 870 } 871 } 872 873 switch (protocolID) { 874 case PROT_WSMOUSE: 875 case PROT_VUID: 876 if (osInfo->PreInit) 877 osInfo->PreInit(pInfo, protocol, 0); 878 break; 879 case PROT_UNKNOWN: 880 /* Check for a builtin OS-specific protocol, 881 * and call its PreInit. */ 882 if (osInfo->CheckProtocol 883 && osInfo->CheckProtocol(protocol)) { 884 if (!device) 885 MouseFindDevice(pInfo, protocol); 886 if (osInfo->PreInit) { 887 osInfo->PreInit(pInfo, protocol, 0); 888 } 889 break; 890 } 891 xf86Msg(X_ERROR, "%s: Unknown protocol \"%s\"\n", 892 pInfo->name, protocol); 893 break; 894 case PROT_UNSUP: 895 xf86Msg(X_ERROR, 896 "%s: Protocol \"%s\" is not supported on this " 897 "platform\n", pInfo->name, protocol); 898 break; 899 default: 900 break; 901 } 902 903 *protocolID_out = protocolID; 904 905 return protocol; 906} 907 908#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 909static int NewMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, 910 int flags); 911 912static InputInfoPtr 913MousePreInit(InputDriverPtr drv, IDevPtr dev, int flags) 914{ 915 InputInfoPtr pInfo; 916 917 if (!(pInfo = xf86AllocateInput(drv, 0))) 918 return NULL; 919 920 pInfo->name = dev->identifier; 921 pInfo->flags = XI86_SEND_DRAG_EVENTS; 922 pInfo->conf_idev = dev; 923 pInfo->close_proc = NULL; 924 pInfo->private_flags = 0; 925 pInfo->always_core_feedback = NULL; 926 927 COLLECT_INPUT_OPTIONS(pInfo, NULL); 928 929 if (NewMousePreInit(drv, pInfo, flags) == Success) 930 { 931 /* Check if SendDragEvents has been disabled. */ 932 if (!xf86SetBoolOption(dev->commonOptions, "SendDragEvents", TRUE)) 933 pInfo->flags &= ~XI86_SEND_DRAG_EVENTS; 934 935 pInfo->flags |= XI86_CONFIGURED; 936 937 return pInfo; 938 } 939 940 xf86DeleteInput(pInfo, 0); 941 942 return NULL; 943} 944 945static int 946NewMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 947#else 948static int 949MousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 950#endif 951{ 952 MouseDevPtr pMse; 953 mousePrivPtr mPriv; 954 MessageType protocolFrom = X_DEFAULT; 955 const char *protocol; 956 const char *device; 957 MouseProtocolID protocolID; 958 MouseProtocolPtr pProto; 959 int i; 960 int rc = Success; 961 962 if (!InitProtocols()) 963 return BadAlloc; 964 965 /* Initialise the InputInfoRec. */ 966 pInfo->type_name = XI_MOUSE; 967 pInfo->device_control = MouseProc; 968 pInfo->read_input = MouseReadInput; 969 pInfo->control_proc = NULL; 970 pInfo->switch_mode = NULL; 971 pInfo->fd = -1; 972 pInfo->dev = NULL; 973 974 /* Allocate the MouseDevRec and initialise it. */ 975 if (!(pMse = calloc(sizeof(MouseDevRec), 1))) 976 { 977 rc = BadAlloc; 978 goto out; 979 } 980 981 pInfo->private = pMse; 982 pMse->Ctrl = MouseCtrl; 983 pMse->PostEvent = MousePostEvent; 984 pMse->CommonOptions = MouseCommonOptions; 985 986 /* Find the protocol type. */ 987 protocol = xf86SetStrOption(pInfo->options, "Protocol", NULL); 988 if (protocol) { 989 protocolFrom = X_CONFIG; 990 } else if (osInfo->DefaultProtocol) { 991 protocol = osInfo->DefaultProtocol(); 992 protocolFrom = X_DEFAULT; 993 } 994 if (!protocol) { 995 xf86Msg(X_ERROR, "%s: No Protocol specified\n", pInfo->name); 996 rc = BadValue; 997 goto out; 998 } 999 1000 device = xf86SetStrOption(pInfo->options, "Device", NULL); 1001 1002 /* Default Mapping: 1 2 3 8 9 10 11 ... */ 1003 for (i = 0; i < MSE_MAXBUTTONS; i++) 1004 pMse->buttonMap[i] = 1 << (i > 2 && i < MSE_MAXBUTTONS-4 ? i+4 : i); 1005 1006 protocol = MousePickProtocol(pInfo, device, protocol, &protocolID); 1007 1008 if (!device) 1009 MouseFindDevice(pInfo, protocol); 1010 1011 xf86Msg(protocolFrom, "%s: Protocol: \"%s\"\n", pInfo->name, protocol); 1012 if (protocolID == PROT_UNKNOWN) 1013 goto out; 1014 if (!(pProto = GetProtocol(protocolID))) 1015 { 1016 rc = BadValue; 1017 goto out; 1018 } 1019 1020 pMse->protocolID = protocolID; 1021 pMse->oldProtocolID = protocolID; /* hack */ 1022 1023 pMse->autoProbe = FALSE; 1024 /* Collect the options, and process the common options. */ 1025#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 1026 /* need some special handling here. xf86CollectInputOptions will reset 1027 * pInfo->options if the second argument is not-null. To re-merge the 1028 * previously set arguments, pass the original pInfo->options in. 1029 */ 1030 xf86CollectInputOptions(pInfo, pProto->defaults, pInfo->options); 1031#else 1032 COLLECT_INPUT_OPTIONS(pInfo, pProto->defaults); 1033#endif 1034 xf86ProcessCommonOptions(pInfo, pInfo->options); 1035 1036 /* Check if the device can be opened. */ 1037 pInfo->fd = xf86OpenSerial(pInfo->options); 1038 if (pInfo->fd == -1) { 1039 if (xf86GetAllowMouseOpenFail()) 1040 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 1041 else { 1042 xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); 1043 if (pMse->mousePriv) 1044 free(pMse->mousePriv); 1045 free(pMse); 1046 pInfo->private = NULL; 1047 rc = BadValue; 1048 goto out; 1049 } 1050 } 1051 xf86CloseSerial(pInfo->fd); 1052 pInfo->fd = -1; 1053 1054 if (!(mPriv = (pointer) calloc(sizeof(mousePrivRec), 1))) 1055 { 1056 rc = BadAlloc; 1057 goto out; 1058 } 1059 1060 pMse->mousePriv = mPriv; 1061 pMse->CommonOptions(pInfo); 1062 pMse->checkMovements = checkForErraticMovements; 1063 pMse->autoProbeMouse = autoProbeMouse; 1064 pMse->collectData = collectData; 1065 pMse->dataGood = autoGood; 1066 1067 MouseHWOptions(pInfo); 1068 MouseSerialOptions(pInfo); 1069 1070out: 1071 return rc; 1072} 1073 1074static void MouseInitButtonLabels(Atom *btn_labels) 1075{ 1076 int i; 1077 Atom unknown_btn; 1078 1079 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 1080 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 1081 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 1082 btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 1083 btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 1084 btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 1085 btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 1086 1087 unknown_btn = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN); 1088 for (i = 7; i < MSE_MAXBUTTONS; i++) 1089 btn_labels[i] = unknown_btn; 1090} 1091 1092static int 1093MouseSetProperty(DeviceIntPtr device, Atom atom, 1094 XIPropertyValuePtr val, BOOL checkonly) 1095{ 1096 InputInfoPtr pInfo = device->public.devicePrivate; 1097 MouseDevPtr pMse = pInfo->private; 1098 1099 if (atom == prop_mbemu) 1100 { 1101 if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER) 1102 return BadMatch; 1103 1104 if (!checkonly) 1105 Emulate3ButtonsSetEnabled(pInfo, *((BOOL*)val->data)); 1106 } 1107 else if (atom == prop_mbtimeout) 1108 { 1109 if (val->format != 32 || val->size != 1 || val->type != XA_INTEGER) 1110 return BadMatch; 1111 1112 if (!checkonly) 1113 pMse->emulate3Timeout = *((CARD32*)val->data); 1114 } 1115 1116 return Success; 1117} 1118 1119static void 1120MouseInitProperties(DeviceIntPtr device) 1121{ 1122 InputInfoPtr pInfo = device->public.devicePrivate; 1123 MouseDevPtr pMse = pInfo->private; 1124 int rc; 1125 1126#ifdef XI_PROP_DEVICE_NODE 1127 const char *device_node = 1128 xf86CheckStrOption(pInfo->options, "Device", NULL); 1129 1130 if (device_node) 1131 { 1132 Atom prop_device = MakeAtom(XI_PROP_DEVICE_NODE, 1133 strlen(XI_PROP_DEVICE_NODE), TRUE); 1134 XIChangeDeviceProperty(device, prop_device, XA_STRING, 8, 1135 PropModeReplace, 1136 strlen(device_node), device_node, FALSE); 1137 } 1138#endif /* XI_PROP_DEVICE_NODE */ 1139 1140 /* Button labels */ 1141 if (pMse->buttons > 0) 1142 { 1143 Atom prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP); 1144 1145 if (prop_btn_label) 1146 { 1147 Atom btn_labels[MSE_MAXBUTTONS]; 1148 MouseInitButtonLabels(btn_labels); 1149 1150 XIChangeDeviceProperty(device, prop_btn_label, XA_ATOM, 32, 1151 PropModeReplace, pMse->buttons, 1152 btn_labels, FALSE); 1153 XISetDevicePropertyDeletable(device, prop_btn_label, FALSE); 1154 } 1155 } 1156 1157 /* Middle button emulation - which this driver calls 3rd button emulation, 1158 * but evdev's properties considers that to be simulating right button 1159 * clicks from a one button mouse, which this driver does not currently 1160 * support, so we use this name for better consistency. 1161 */ 1162 prop_mbemu = MakeAtom(MOUSE_PROP_MIDBUTTON, strlen(MOUSE_PROP_MIDBUTTON), 1163 TRUE); 1164 rc = XIChangeDeviceProperty(device, prop_mbemu, XA_INTEGER, 8, 1165 PropModeReplace, 1, 1166 &pMse->emulate3Buttons, FALSE); 1167 if (rc != Success) 1168 return; 1169 XISetDevicePropertyDeletable(device, prop_mbemu, FALSE); 1170 1171 prop_mbtimeout = MakeAtom(MOUSE_PROP_MIDBUTTON_TIMEOUT, 1172 strlen(MOUSE_PROP_MIDBUTTON_TIMEOUT), TRUE); 1173 rc = XIChangeDeviceProperty(device, prop_mbtimeout, XA_INTEGER, 32, 1174 PropModeReplace, 1, 1175 &pMse->emulate3Timeout, FALSE); 1176 1177 if (rc != Success) 1178 return; 1179 XISetDevicePropertyDeletable(device, prop_mbtimeout, FALSE); 1180 1181 XIRegisterPropertyHandler(device, MouseSetProperty, NULL, NULL); 1182} 1183 1184static void 1185MouseReadInput(InputInfoPtr pInfo) 1186{ 1187 MouseDevPtr pMse; 1188 int j, buttons, dx, dy, dz, dw, baddata; 1189 int pBufP; 1190 int c; 1191 unsigned char *pBuf, u; 1192 1193 1194 pMse = pInfo->private; 1195 pBufP = pMse->protoBufTail; 1196 pBuf = pMse->protoBuf; 1197 1198 if (pInfo->fd == -1) 1199 return; 1200 1201 /* 1202 * Set blocking to -1 on the first call because we know there is data to 1203 * read. Xisb automatically clears it after one successful read so that 1204 * succeeding reads are preceded by a select with a 0 timeout to prevent 1205 * read from blocking indefinitely. 1206 */ 1207 XisbBlockDuration(pMse->buffer, -1); 1208 1209 while ((c = XisbRead(pMse->buffer)) >= 0) { 1210 u = (unsigned char)c; 1211 1212#if defined (EXTMOUSEDEBUG) || defined (MOUSEDATADEBUG) 1213 LogMessageVerbSigSafe(X_INFO, -1, "mouse byte: %x\n",u); 1214#endif 1215 1216 /* if we do autoprobing collect the data */ 1217 if (pMse->collectData && pMse->autoProbe) 1218 if (pMse->collectData(pMse,u)) 1219 continue; 1220 1221#ifdef SUPPORT_MOUSE_RESET 1222 if (mouseReset(pInfo,u)) { 1223 pBufP = 0; 1224 continue; 1225 } 1226#endif 1227 if (pBufP >= pMse->protoPara[4]) { 1228 /* 1229 * Buffer contains a full packet, which has already been processed: 1230 * Empty the buffer and check for optional 4th byte, which will be 1231 * processed directly, without being put into the buffer first. 1232 */ 1233 pBufP = 0; 1234 if ((u & pMse->protoPara[0]) != pMse->protoPara[1] && 1235 (u & pMse->protoPara[5]) == pMse->protoPara[6]) { 1236 /* 1237 * Hack for Logitech MouseMan Mouse - Middle button 1238 * 1239 * Unfortunately this mouse has variable length packets: the 1240 * standard Microsoft 3 byte packet plus an optional 4th byte 1241 * whenever the middle button status changes. 1242 * 1243 * We have already processed the standard packet with the 1244 * movement and button info. Now post an event message with 1245 * the old status of the left and right buttons and the 1246 * updated middle button. 1247 */ 1248 /* 1249 * Even worse, different MouseMen and TrackMen differ in the 1250 * 4th byte: some will send 0x00/0x20, others 0x01/0x21, or 1251 * even 0x02/0x22, so I have to strip off the lower bits. 1252 * [CHRIS-211092] 1253 * 1254 * [JCH-96/01/21] 1255 * HACK for ALPS "fourth button". (It's bit 0x10 of the 1256 * "fourth byte" and it is activated by tapping the glidepad 1257 * with the finger! 8^) We map it to bit bit3, and the 1258 * reverse map in xf86Events just has to be extended so that 1259 * it is identified as Button 4. The lower half of the 1260 * reverse-map may remain unchanged. 1261 */ 1262 /* 1263 * [KAZU-030897] 1264 * Receive the fourth byte only when preceding three bytes 1265 * have been detected (pBufP >= pMse->protoPara[4]). In the 1266 * previous versions, the test was pBufP == 0; we may have 1267 * mistakingly received a byte even if we didn't see anything 1268 * preceding the byte. 1269 */ 1270#ifdef EXTMOUSEDEBUG 1271 LogMessageVerbSigSafe(X_INFO, -1, "mouse 4th byte %x\n",u); 1272#endif 1273 dx = dy = dz = dw = 0; 1274 buttons = 0; 1275 switch (pMse->protocolID) { 1276 1277 /* 1278 * [KAZU-221197] 1279 * IntelliMouse, NetMouse (including NetMouse Pro) and Mie 1280 * Mouse always send the fourth byte, whereas the fourth byte 1281 * is optional for GlidePoint and ThinkingMouse. The fourth 1282 * byte is also optional for MouseMan+ and FirstMouse+ in 1283 * their native mode. It is always sent if they are in the 1284 * IntelliMouse compatible mode. 1285 */ 1286 case PROT_IMSERIAL: /* IntelliMouse, NetMouse, Mie Mouse, 1287 MouseMan+ */ 1288 dz = (u & 0x08) ? 1289 (u & 0x0f) - 16 : (u & 0x0f); 1290 if ((dz >= 7) || (dz <= -7)) 1291 dz = 0; 1292 buttons |= ((int)(u & 0x10) >> 3) 1293 | ((int)(u & 0x20) >> 2) 1294 | (pMse->lastButtons & 0x05); 1295 break; 1296 1297 case PROT_GLIDE: 1298 case PROT_THINKING: 1299 buttons |= ((int)(u & 0x10) >> 1); 1300 /* fall through */ 1301 1302 default: 1303 buttons |= ((int)(u & 0x20) >> 4) | 1304 (pMse->lastButtons & 0x05); 1305 break; 1306 } 1307 goto post_event; 1308 } 1309 } 1310 /* End of packet buffer flush and 4th byte hack. */ 1311 1312 /* 1313 * Append next byte to buffer (which is empty or contains an 1314 * incomplete packet); iterate if packet (still) not complete. 1315 */ 1316 pBuf[pBufP++] = u; 1317 if (pBufP != pMse->protoPara[4]) continue; 1318#ifdef EXTMOUSEDEBUG2 1319 { 1320 int i; 1321 LogMessageVerbSigSafe(X_INFO, -1, "received %d bytes",pBufP); 1322 for ( i=0; i < pBufP; i++) 1323 LogMessageVerbSigSafe(X_INFO, -1, " %x",pBuf[i]); 1324 LogMessageVerbSigSafe(X_INFO, -1, "\n"); 1325 } 1326#endif 1327 1328 /* 1329 * Hack for resyncing: We check here for a package that is: 1330 * a) illegal (detected by wrong data-package header) 1331 * b) invalid (0x80 == -128 and that might be wrong for MouseSystems) 1332 * c) bad header-package 1333 * 1334 * NOTE: b) is a violation of the MouseSystems-Protocol, since values 1335 * of -128 are allowed, but since they are very seldom we can 1336 * easily use them as package-header with no button pressed. 1337 * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. 1338 * Furthermore, 0x80 is not valid as a header byte. For a PS/2 1339 * mouse we skip checking data bytes. For resyncing a PS/2 1340 * mouse we require the two most significant bits in the header 1341 * byte to be 0. These are the overflow bits, and in case of 1342 * an overflow we actually lose sync. Overflows are very rare, 1343 * however, and we quickly gain sync again after an overflow 1344 * condition. This is the best we can do. (Actually, we could 1345 * use bit 0x08 in the header byte for resyncing, since that 1346 * bit is supposed to be always on, but nobody told Microsoft...) 1347 */ 1348 1349 /* 1350 * [KAZU,OYVIND-120398] 1351 * The above hack is wrong! Because of b) above, we shall see 1352 * erroneous mouse events so often when the MouseSystem mouse is 1353 * moved quickly. As for the PS/2 and its variants, we don't need 1354 * to treat them as special cases, because protoPara[2] and 1355 * protoPara[3] are both 0x00 for them, thus, any data bytes will 1356 * never be discarded. 0x80 is rejected for MMSeries, Logitech 1357 * and MMHittab protocols, because protoPara[2] and protoPara[3] 1358 * are 0x80 and 0x00 respectively. The other protocols are 7-bit 1359 * protocols; there is no use checking 0x80. 1360 * 1361 * All in all we should check the condition a) only. 1362 */ 1363 1364 /* 1365 * [OYVIND-120498] 1366 * Check packet for valid data: 1367 * If driver is in sync with datastream, the packet is considered 1368 * bad if any byte (header and/or data) contains an invalid value. 1369 * 1370 * If packet is bad, we discard the first byte and shift the buffer. 1371 * Next iteration will then check the new situation for validity. 1372 * 1373 * If flag MF_SAFE is set in proto[7] and the driver 1374 * is out of sync, the packet is also considered bad if 1375 * any of the data bytes contains a valid header byte value. 1376 * This situation could occur if the buffer contains 1377 * the tail of one packet and the header of the next. 1378 * 1379 * Note: The driver starts in out-of-sync mode (pMse->inSync = 0). 1380 */ 1381 1382 baddata = 0; 1383 1384 /* All databytes must be valid. */ 1385 for (j = 1; j < pBufP; j++ ) 1386 if ((pBuf[j] & pMse->protoPara[2]) != pMse->protoPara[3]) 1387 baddata = 1; 1388 1389 /* If out of sync, don't mistake a header byte for data. */ 1390 if ((pMse->protoPara[7] & MPF_SAFE) && !pMse->inSync) 1391 for (j = 1; j < pBufP; j++ ) 1392 if ((pBuf[j] & pMse->protoPara[0]) == pMse->protoPara[1]) 1393 baddata = 1; 1394 1395 /* Accept or reject the packet ? */ 1396 if ((pBuf[0] & pMse->protoPara[0]) != pMse->protoPara[1] || baddata) { 1397 if (pMse->inSync) { 1398#ifdef EXTMOUSEDEBUG 1399 LogMessageVerbSigSafe(X_INFO, -1, "mouse driver lost sync\n"); 1400#endif 1401 } 1402#ifdef EXTMOUSEDEBUG 1403 LogMessageVerbSigSafe(X_INFO, -1, "skipping byte %x\n",*pBuf); 1404#endif 1405 /* Tell auto probe that we are out of sync */ 1406 if (pMse->autoProbeMouse && pMse->autoProbe) 1407 pMse->autoProbeMouse(pInfo, FALSE, pMse->inSync); 1408 pMse->protoBufTail = --pBufP; 1409 for (j = 0; j < pBufP; j++) 1410 pBuf[j] = pBuf[j+1]; 1411 pMse->inSync = 0; 1412 continue; 1413 } 1414 /* Tell auto probe that we were successful */ 1415 if (pMse->autoProbeMouse && pMse->autoProbe) 1416 pMse->autoProbeMouse(pInfo, TRUE, FALSE); 1417 1418 if (!pMse->inSync) { 1419#ifdef EXTMOUSEDEBUG 1420 LogMessageVerbSigSafe(X_INFO, -1, "mouse driver back in sync\n"); 1421#endif 1422 pMse->inSync = 1; 1423 } 1424 1425 if (!pMse->dataGood(pMse)) 1426 continue; 1427 1428 /* 1429 * Packet complete and verified, now process it ... 1430 */ 1431 REDO_INTERPRET: 1432 dz = dw = 0; 1433 switch (pMse->protocolID) { 1434 case PROT_LOGIMAN: /* MouseMan / TrackMan [CHRIS-211092] */ 1435 case PROT_MS: /* Microsoft */ 1436 if (pMse->chordMiddle) 1437 buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 : 1438 ((int)(pBuf[0] & 0x20) >> 3) 1439 | ((int)(pBuf[0] & 0x10) >> 4); 1440 else 1441 buttons = (pMse->lastButtons & 2) 1442 | ((int)(pBuf[0] & 0x20) >> 3) 1443 | ((int)(pBuf[0] & 0x10) >> 4); 1444 dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 1445 dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 1446 break; 1447 1448 case PROT_GLIDE: /* ALPS GlidePoint */ 1449 case PROT_THINKING: /* ThinkingMouse */ 1450 case PROT_IMSERIAL: /* IntelliMouse, NetMouse, Mie Mouse, MouseMan+ */ 1451 buttons = (pMse->lastButtons & (8 + 2)) 1452 | ((int)(pBuf[0] & 0x20) >> 3) 1453 | ((int)(pBuf[0] & 0x10) >> 4); 1454 dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 1455 dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 1456 break; 1457 1458 case PROT_MSC: /* Mouse Systems Corp */ 1459 buttons = (~pBuf[0]) & 0x07; 1460 dx = (signed char)(pBuf[1]) + (char)(pBuf[3]); 1461 dy = - ((signed char)(pBuf[2]) + (char)(pBuf[4])); 1462 break; 1463 1464 case PROT_MMHIT: /* MM_HitTablet */ 1465 buttons = pBuf[0] & 0x07; 1466 if (buttons != 0) 1467 buttons = 1 << (buttons - 1); 1468 dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 1469 dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 1470 break; 1471 1472 case PROT_ACECAD: /* ACECAD */ 1473 /* ACECAD is almost exactly like MM but the buttons are different */ 1474 buttons = (pBuf[0] & 0x02) | ((pBuf[0] & 0x04) >> 2) | 1475 ((pBuf[0] & 1) << 2); 1476 dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 1477 dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 1478 break; 1479 1480 case PROT_MM: /* MM Series */ 1481 case PROT_LOGI: /* Logitech Mice */ 1482 buttons = pBuf[0] & 0x07; 1483 dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 1484 dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 1485 break; 1486 1487 case PROT_BM: /* BusMouse */ 1488 buttons = (~pBuf[0]) & 0x07; 1489 dx = (signed char)pBuf[1]; 1490 dy = - (signed char)pBuf[2]; 1491 break; 1492 1493 case PROT_PS2: /* PS/2 mouse */ 1494 case PROT_GENPS2: /* generic PS/2 mouse */ 1495 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1496 (pBuf[0] & 0x02) >> 1 | /* Right */ 1497 (pBuf[0] & 0x01) << 2; /* Left */ 1498 dx = (pBuf[0] & 0x10) ? (int)pBuf[1]-256 : (int)pBuf[1]; 1499 dy = (pBuf[0] & 0x20) ? -((int)pBuf[2]-256) : -(int)pBuf[2]; 1500 break; 1501 1502 /* PS/2 mouse variants */ 1503 case PROT_IMPS2: /* IntelliMouse PS/2 */ 1504 case PROT_NETPS2: /* NetMouse PS/2 */ 1505 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1506 (pBuf[0] & 0x02) >> 1 | /* Right */ 1507 (pBuf[0] & 0x01) << 2 | /* Left */ 1508 (pBuf[0] & 0x40) >> 3 | /* button 4 */ 1509 (pBuf[0] & 0x80) >> 3; /* button 5 */ 1510 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 1511 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 1512 /* 1513 * The next cast must be 'signed char' for platforms (like PPC) 1514 * where char defaults to unsigned. 1515 */ 1516 dz = (signed char)(pBuf[3] | ((pBuf[3] & 0x08) ? 0xf8 : 0)); 1517 if ((pBuf[3] & 0xf8) && ((pBuf[3] & 0xf8) != 0xf8)) { 1518 if (pMse->autoProbe) { 1519 SetMouseProto(pMse, PROT_EXPPS2); 1520 xf86Msg(X_INFO, 1521 "Mouse autoprobe: Changing protocol to %s\n", 1522 pMse->protocol); 1523 1524 goto REDO_INTERPRET; 1525 } else 1526 dz = 0; 1527 } 1528 break; 1529 1530 case PROT_EXPPS2: /* IntelliMouse Explorer PS/2 */ 1531 if (pMse->autoProbe && (pBuf[3] & 0xC0)) { 1532 SetMouseProto(pMse, PROT_IMPS2); 1533 xf86Msg(X_INFO,"Mouse autoprobe: Changing protocol to %s\n", 1534 pMse->protocol); 1535 goto REDO_INTERPRET; 1536 } 1537 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1538 (pBuf[0] & 0x02) >> 1 | /* Right */ 1539 (pBuf[0] & 0x01) << 2 | /* Left */ 1540 (pBuf[3] & 0x10) >> 1 | /* button 4 */ 1541 (pBuf[3] & 0x20) >> 1; /* button 5 */ 1542 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 1543 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 1544 if (pMse->negativeW != MSE_NOAXISMAP) { 1545 switch (pBuf[3] & 0x0f) { 1546 case 0x00: break; 1547 case 0x01: dz = 1; break; 1548 case 0x02: dw = 1; break; 1549 case 0x0e: dw = -1; break; 1550 case 0x0f: dz = -1; break; 1551 default: 1552 xf86Msg(X_INFO, 1553 "Mouse autoprobe: Disabling secondary wheel\n"); 1554 pMse->negativeW = pMse->positiveW = MSE_NOAXISMAP; 1555 } 1556 } 1557 if (pMse->negativeW == MSE_NOAXISMAP) 1558 dz = (pBuf[3]&0x08) ? (pBuf[3]&0x0f) - 16 : (pBuf[3]&0x0f); 1559 break; 1560 1561 case PROT_MMPS2: /* MouseMan+ PS/2 */ 1562 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1563 (pBuf[0] & 0x02) >> 1 | /* Right */ 1564 (pBuf[0] & 0x01) << 2; /* Left */ 1565 dx = (pBuf[0] & 0x10) ? pBuf[1] - 256 : pBuf[1]; 1566 if (((pBuf[0] & 0x48) == 0x48) && 1567 (abs(dx) > 191) && 1568 ((((pBuf[2] & 0x03) << 2) | 0x02) == (pBuf[1] & 0x0f))) { 1569 /* extended data packet */ 1570 switch ((((pBuf[0] & 0x30) >> 2) | ((pBuf[1] & 0x30) >> 4))) { 1571 case 1: /* wheel data packet */ 1572 buttons |= ((pBuf[2] & 0x10) ? 0x08 : 0) | /* 4th button */ 1573 ((pBuf[2] & 0x20) ? 0x10 : 0); /* 5th button */ 1574 dx = dy = 0; 1575 dz = (pBuf[2] & 0x08) ? (pBuf[2] & 0x0f) - 16 : 1576 (pBuf[2] & 0x0f); 1577 break; 1578 case 2: /* Logitech reserves this packet type */ 1579 /* 1580 * IBM ScrollPoint uses this packet to encode its 1581 * stick movement. 1582 */ 1583 buttons |= (pMse->lastButtons & ~0x07); 1584 dx = dy = 0; 1585 dz = (pBuf[2] & 0x80) ? ((pBuf[2] >> 4) & 0x0f) - 16 : 1586 ((pBuf[2] >> 4) & 0x0f); 1587 dw = (pBuf[2] & 0x08) ? (pBuf[2] & 0x0f) - 16 : 1588 (pBuf[2] & 0x0f); 1589 break; 1590 case 0: /* device type packet - shouldn't happen */ 1591 default: 1592 buttons |= (pMse->lastButtons & ~0x07); 1593 dx = dy = 0; 1594 dz = 0; 1595 break; 1596 } 1597 } else { 1598 buttons |= (pMse->lastButtons & ~0x07); 1599 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 1600 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 1601 } 1602 break; 1603 1604 case PROT_GLIDEPS2: /* GlidePoint PS/2 */ 1605 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1606 (pBuf[0] & 0x02) >> 1 | /* Right */ 1607 (pBuf[0] & 0x01) << 2 | /* Left */ 1608 ((pBuf[0] & 0x08) ? 0 : 0x08);/* fourth button */ 1609 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 1610 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 1611 break; 1612 1613 case PROT_NETSCPS2: /* NetScroll PS/2 */ 1614 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1615 (pBuf[0] & 0x02) >> 1 | /* Right */ 1616 (pBuf[0] & 0x01) << 2 | /* Left */ 1617 ((pBuf[3] & 0x02) ? 0x08 : 0) | /* button 4 */ 1618 ((pBuf[3] & 0x01) ? 0x10 : 0); /* button 5 */ 1619 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 1620 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 1621 dz = (pBuf[3] & 0x10) ? pBuf[4] - 256 : pBuf[4]; 1622 break; 1623 1624 case PROT_THINKPS2: /* ThinkingMouse PS/2 */ 1625 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 1626 (pBuf[0] & 0x02) >> 1 | /* Right */ 1627 (pBuf[0] & 0x01) << 2 | /* Left */ 1628 ((pBuf[0] & 0x08) ? 0x08 : 0);/* fourth button */ 1629 pBuf[1] |= (pBuf[0] & 0x40) ? 0x80 : 0x00; 1630 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 1631 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 1632 break; 1633 1634 case PROT_SYSMOUSE: /* sysmouse */ 1635 buttons = (~pBuf[0]) & 0x07; 1636 dx = (signed char)(pBuf[1]) + (signed char)(pBuf[3]); 1637 dy = - ((signed char)(pBuf[2]) + (signed char)(pBuf[4])); 1638 /* FreeBSD sysmouse sends additional data bytes */ 1639 if (pMse->protoPara[4] >= 8) { 1640 /* 1641 * These casts must be 'signed char' for platforms (like PPC) 1642 * where char defaults to unsigned. 1643 */ 1644 dz = ((signed char)(pBuf[5] << 1) + 1645 (signed char)(pBuf[6] << 1)) >> 1; 1646 buttons |= (int)(~pBuf[7] & 0x7f) << 3; 1647 } 1648 break; 1649 1650 case PROT_VALUMOUSESCROLL: /* Kensington ValuMouseScroll */ 1651 buttons = ((int)(pBuf[0] & 0x20) >> 3) 1652 | ((int)(pBuf[0] & 0x10) >> 4) 1653 | ((int)(pBuf[3] & 0x10) >> 3); 1654 dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 1655 dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 1656 dz = (pBuf[3] & 0x08) ? ((int)(pBuf[3] & 0x0F) - 0x10) : 1657 ((int)(pBuf[3] & 0x0F)); 1658 break; 1659 1660 default: /* There's a table error */ 1661#ifdef EXTMOUSEDEBUG 1662 LogMessageVerbSigSafe(X_INFO, -1, "mouse table error\n"); 1663#endif 1664 continue; 1665 } 1666#ifdef EXTMOUSEDEBUG 1667 LogMessageVerbSigSafe(X_INFO, -1, "packet"); 1668 for ( j=0; j < pBufP; j++) 1669 LogMessageVerbSigSafe(X_INFO, -1, " %x",pBuf[j]); 1670 LogMessageVerbSigSafe(X_INFO, -1, "\n"); 1671#endif 1672 1673post_event: 1674#ifdef EXTMOUSEDEBUG 1675 LogMessageVerbSigSafe(X_INFO, -1, "dx=%i dy=%i dz=%i dw=%i buttons=%x\n",dx,dy,dz,dw,buttons); 1676#endif 1677 /* When auto-probing check if data makes sense */ 1678 if (pMse->checkMovements && pMse->autoProbe) 1679 pMse->checkMovements(pInfo,dx,dy); 1680 /* post an event */ 1681 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 1682 1683 /* 1684 * We don't reset pBufP here yet, as there may be an additional data 1685 * byte in some protocols. See above. 1686 */ 1687 } 1688 pMse->protoBufTail = pBufP; 1689} 1690 1691/* 1692 * MouseCtrl -- 1693 * Alter the control parameters for the mouse. Note that all 1694 * settings are now handled by dix. 1695 */ 1696 1697static void 1698MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl) 1699{ 1700 /* This function intentionally left blank */ 1701} 1702 1703/* 1704 *************************************************************************** 1705 * 1706 * MouseProc -- 1707 * 1708 *************************************************************************** 1709 */ 1710 1711static int 1712MouseProc(DeviceIntPtr device, int what) 1713{ 1714 InputInfoPtr pInfo; 1715 MouseDevPtr pMse; 1716 mousePrivPtr mPriv; 1717 unsigned char map[MSE_MAXBUTTONS + 1]; 1718 int i; 1719 Atom btn_labels[MSE_MAXBUTTONS] = {0}; 1720 Atom axes_labels[2] = { 0, 0 }; 1721 1722 pInfo = device->public.devicePrivate; 1723 pMse = pInfo->private; 1724 pMse->device = device; 1725 1726 switch (what) 1727 { 1728 case DEVICE_INIT: 1729 device->public.on = FALSE; 1730 /* 1731 * [KAZU-241097] We don't know exactly how many buttons the 1732 * device has, so setup the map with the maximum number. 1733 */ 1734 for (i = 0; i < MSE_MAXBUTTONS; i++) 1735 map[i + 1] = i + 1; 1736 1737 MouseInitButtonLabels(btn_labels); 1738 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 1739 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 1740 1741 InitPointerDeviceStruct((DevicePtr)device, map, 1742 min(pMse->buttons, MSE_MAXBUTTONS), 1743 btn_labels, 1744 pMse->Ctrl, 1745 GetMotionHistorySize(), 2, 1746 axes_labels 1747 ); 1748 1749 /* X valuator */ 1750 xf86InitValuatorAxisStruct(device, 0, 1751 axes_labels[0], 1752 -1, -1, 1, 0, 1 1753#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 1754 , Relative 1755#endif 1756 ); 1757 xf86InitValuatorDefaults(device, 0); 1758 /* Y valuator */ 1759 xf86InitValuatorAxisStruct(device, 1, 1760 axes_labels[1], 1761 -1, -1, 1, 0, 1 1762#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 1763 , Relative 1764#endif 1765 ); 1766 xf86InitValuatorDefaults(device, 1); 1767 1768#ifdef EXTMOUSEDEBUG 1769 ErrorF("assigning %p name=%s\n", device, pInfo->name); 1770#endif 1771 MouseInitProperties(device); 1772 break; 1773 1774 case DEVICE_ON: 1775 pInfo->fd = xf86OpenSerial(pInfo->options); 1776 if (pInfo->fd == -1) 1777 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 1778 else { 1779#if defined(__NetBSD__) && defined(WSCONS_SUPPORT) && defined(WSMOUSEIO_SETVERSION) 1780 int version = WSMOUSE_EVENT_VERSION; 1781 if (ioctl(pInfo->fd, WSMOUSEIO_SETVERSION, &version) == -1) 1782 xf86Msg(X_WARNING, "%s: cannot set version\n", pInfo->name); 1783#endif 1784 if (pMse->xisbscale) 1785 pMse->buffer = XisbNew(pInfo->fd, pMse->xisbscale * 4); 1786 else 1787 pMse->buffer = XisbNew(pInfo->fd, 64); 1788 if (!pMse->buffer) { 1789 xf86CloseSerial(pInfo->fd); 1790 pInfo->fd = -1; 1791 } else { 1792 if (!SetupMouse(pInfo)) { 1793 xf86CloseSerial(pInfo->fd); 1794 pInfo->fd = -1; 1795 XisbFree(pMse->buffer); 1796 pMse->buffer = NULL; 1797 } else { 1798 mPriv = (mousePrivPtr)pMse->mousePriv; 1799 if (mPriv != NULL) { 1800 if ( pMse->protocolID != PROT_AUTO) { 1801 pMse->inSync = TRUE; /* @@@ */ 1802 if (mPriv->soft) 1803 mPriv->autoState = AUTOPROBE_GOOD; 1804 else 1805 mPriv->autoState = AUTOPROBE_H_GOOD; 1806 } else { 1807 if (mPriv->soft) 1808 mPriv->autoState = AUTOPROBE_NOPROTO; 1809 else 1810 mPriv->autoState = AUTOPROBE_H_NOPROTO; 1811 } 1812 } 1813 xf86FlushInput(pInfo->fd); 1814 xf86AddEnabledDevice(pInfo); 1815 if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) { 1816 RegisterBlockAndWakeupHandlers (MouseBlockHandler, 1817 MouseWakeupHandler, 1818 (pointer) pInfo); 1819 } 1820 } 1821 } 1822 } 1823 pMse->lastButtons = 0; 1824 pMse->lastMappedButtons = 0; 1825 pMse->emulateState = 0; 1826 pMse->emulate3Pending = FALSE; 1827 pMse->wheelButtonExpires = GetTimeInMillis (); 1828 device->public.on = TRUE; 1829 FlushButtons(pMse); 1830 break; 1831 1832 case DEVICE_OFF: 1833 if (pInfo->fd != -1) { 1834 xf86RemoveEnabledDevice(pInfo); 1835 if (pMse->buffer) { 1836 XisbFree(pMse->buffer); 1837 pMse->buffer = NULL; 1838 } 1839 xf86CloseSerial(pInfo->fd); 1840 pInfo->fd = -1; 1841 if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) 1842 { 1843 RemoveBlockAndWakeupHandlers (MouseBlockHandler, 1844 MouseWakeupHandler, 1845 (pointer) pInfo); 1846 } 1847 } 1848 device->public.on = FALSE; 1849 break; 1850 case DEVICE_CLOSE: 1851 free(pMse->mousePriv); 1852 pMse->mousePriv = NULL; 1853 break; 1854 1855 default: 1856 return BadValue; 1857 } 1858 return Success; 1859} 1860 1861/********************************************************************** 1862 * 1863 * FlushButtons -- reset button states. 1864 * 1865 **********************************************************************/ 1866 1867static void 1868FlushButtons(MouseDevPtr pMse) 1869{ 1870 pMse->lastButtons = 0; 1871 pMse->lastMappedButtons = 0; 1872} 1873 1874/********************************************************************** 1875 * 1876 * Emulate3Button support code 1877 * 1878 **********************************************************************/ 1879 1880 1881/* 1882 * Lets create a simple finite-state machine for 3 button emulation: 1883 * 1884 * We track buttons 1 and 3 (left and right). There are 11 states: 1885 * 0 ground - initial state 1886 * 1 delayed left - left pressed, waiting for right 1887 * 2 delayed right - right pressed, waiting for left 1888 * 3 pressed middle - right and left pressed, emulated middle sent 1889 * 4 pressed left - left pressed and sent 1890 * 5 pressed right - right pressed and sent 1891 * 6 released left - left released after emulated middle 1892 * 7 released right - right released after emulated middle 1893 * 8 repressed left - left pressed after released left 1894 * 9 repressed right - right pressed after released right 1895 * 10 pressed both - both pressed, not emulating middle 1896 * 1897 * At each state, we need handlers for the following events 1898 * 0: no buttons down 1899 * 1: left button down 1900 * 2: right button down 1901 * 3: both buttons down 1902 * 4: emulate3Timeout passed without a button change 1903 * Note that button events are not deltas, they are the set of buttons being 1904 * pressed now. It's possible (ie, mouse hardware does it) to go from (eg) 1905 * left down to right down without anything in between, so all cases must be 1906 * handled. 1907 * 1908 * a handler consists of three values: 1909 * 0: action1 1910 * 1: action2 1911 * 2: new emulation state 1912 * 1913 * action > 0: ButtonPress 1914 * action = 0: nothing 1915 * action < 0: ButtonRelease 1916 * 1917 * The comment preceding each section is the current emulation state. 1918 * The comments to the right are of the form 1919 * <button state> (<events>) -> <new emulation state> 1920 * which should be read as 1921 * If the buttons are in <button state>, generate <events> then go to 1922 * <new emulation state>. 1923 */ 1924static signed char stateTab[11][5][3] = { 1925/* 0 ground */ 1926 { 1927 { 0, 0, 0 }, /* nothing -> ground (no change) */ 1928 { 0, 0, 1 }, /* left -> delayed left */ 1929 { 0, 0, 2 }, /* right -> delayed right */ 1930 { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ 1931 { 0, 0, -1 } /* timeout N/A */ 1932 }, 1933/* 1 delayed left */ 1934 { 1935 { 1, -1, 0 }, /* nothing (left event) -> ground */ 1936 { 0, 0, 1 }, /* left -> delayed left (no change) */ 1937 { 1, -1, 2 }, /* right (left event) -> delayed right */ 1938 { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ 1939 { 1, 0, 4 }, /* timeout (left press) -> pressed left */ 1940 }, 1941/* 2 delayed right */ 1942 { 1943 { 3, -3, 0 }, /* nothing (right event) -> ground */ 1944 { 3, -3, 1 }, /* left (right event) -> delayed left (no change) */ 1945 { 0, 0, 2 }, /* right -> delayed right (no change) */ 1946 { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ 1947 { 3, 0, 5 }, /* timeout (right press) -> pressed right */ 1948 }, 1949/* 3 pressed middle */ 1950 { 1951 { -2, 0, 0 }, /* nothing (middle release) -> ground */ 1952 { 0, 0, 7 }, /* left -> released right */ 1953 { 0, 0, 6 }, /* right -> released left */ 1954 { 0, 0, 3 }, /* left & right -> pressed middle (no change) */ 1955 { 0, 0, -1 }, /* timeout N/A */ 1956 }, 1957/* 4 pressed left */ 1958 { 1959 { -1, 0, 0 }, /* nothing (left release) -> ground */ 1960 { 0, 0, 4 }, /* left -> pressed left (no change) */ 1961 { -1, 0, 2 }, /* right (left release) -> delayed right */ 1962 { 3, 0, 10 }, /* left & right (right press) -> pressed both */ 1963 { 0, 0, -1 }, /* timeout N/A */ 1964 }, 1965/* 5 pressed right */ 1966 { 1967 { -3, 0, 0 }, /* nothing (right release) -> ground */ 1968 { -3, 0, 1 }, /* left (right release) -> delayed left */ 1969 { 0, 0, 5 }, /* right -> pressed right (no change) */ 1970 { 1, 0, 10 }, /* left & right (left press) -> pressed both */ 1971 { 0, 0, -1 }, /* timeout N/A */ 1972 }, 1973/* 6 released left */ 1974 { 1975 { -2, 0, 0 }, /* nothing (middle release) -> ground */ 1976 { -2, 0, 1 }, /* left (middle release) -> delayed left */ 1977 { 0, 0, 6 }, /* right -> released left (no change) */ 1978 { 1, 0, 8 }, /* left & right (left press) -> repressed left */ 1979 { 0, 0, -1 }, /* timeout N/A */ 1980 }, 1981/* 7 released right */ 1982 { 1983 { -2, 0, 0 }, /* nothing (middle release) -> ground */ 1984 { 0, 0, 7 }, /* left -> released right (no change) */ 1985 { -2, 0, 2 }, /* right (middle release) -> delayed right */ 1986 { 3, 0, 9 }, /* left & right (right press) -> repressed right */ 1987 { 0, 0, -1 }, /* timeout N/A */ 1988 }, 1989/* 8 repressed left */ 1990 { 1991 { -2, -1, 0 }, /* nothing (middle release, left release) -> ground */ 1992 { -2, 0, 4 }, /* left (middle release) -> pressed left */ 1993 { -1, 0, 6 }, /* right (left release) -> released left */ 1994 { 0, 0, 8 }, /* left & right -> repressed left (no change) */ 1995 { 0, 0, -1 }, /* timeout N/A */ 1996 }, 1997/* 9 repressed right */ 1998 { 1999 { -2, -3, 0 }, /* nothing (middle release, right release) -> ground */ 2000 { -3, 0, 7 }, /* left (right release) -> released right */ 2001 { -2, 0, 5 }, /* right (middle release) -> pressed right */ 2002 { 0, 0, 9 }, /* left & right -> repressed right (no change) */ 2003 { 0, 0, -1 }, /* timeout N/A */ 2004 }, 2005/* 10 pressed both */ 2006 { 2007 { -1, -3, 0 }, /* nothing (left release, right release) -> ground */ 2008 { -3, 0, 4 }, /* left (right release) -> pressed left */ 2009 { -1, 0, 5 }, /* right (left release) -> pressed right */ 2010 { 0, 0, 10 }, /* left & right -> pressed both (no change) */ 2011 { 0, 0, -1 }, /* timeout N/A */ 2012 }, 2013}; 2014 2015/* 2016 * Table to allow quick reversal of natural button mapping to correct mapping 2017 */ 2018 2019/* 2020 * [JCH-96/01/21] The ALPS GlidePoint pad extends the MS protocol 2021 * with a fourth button activated by tapping the PAD. 2022 * The 2nd line corresponds to 4th button on; the drv sends 2023 * the buttons in the following map (MSBit described first) : 2024 * 0 | 4th | 1st | 2nd | 3rd 2025 * And we remap them (MSBit described first) : 2026 * 0 | 4th | 3rd | 2nd | 1st 2027 */ 2028static char reverseMap[16] = { 0, 4, 2, 6, 2029 1, 5, 3, 7, 2030 8, 12, 10, 14, 2031 9, 13, 11, 15 }; 2032 2033static char hitachMap[16] = { 0, 2, 1, 3, 2034 8, 10, 9, 11, 2035 4, 6, 5, 7, 2036 12, 14, 13, 15 }; 2037 2038#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f]) 2039 2040static CARD32 2041buttonTimer(InputInfoPtr pInfo) 2042{ 2043 MouseDevPtr pMse; 2044#if !HAVE_THREADED_INPUT 2045 int sigstate; 2046#endif 2047 int id; 2048 2049 pMse = pInfo->private; 2050 2051#if HAVE_THREADED_INPUT 2052 input_lock(); 2053#else 2054 sigstate = xf86BlockSIGIO (); 2055#endif 2056 2057 pMse->emulate3Pending = FALSE; 2058 if ((id = stateTab[pMse->emulateState][4][0]) != 0) { 2059 xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0); 2060 pMse->emulateState = stateTab[pMse->emulateState][4][2]; 2061 } else { 2062 LogMessageVerbSigSafe(X_WARNING, -1, 2063 "Got unexpected buttonTimer in state %d\n", pMse->emulateState); 2064 } 2065 2066#if HAVE_THREADED_INPUT 2067 input_unlock(); 2068#else 2069 xf86UnblockSIGIO (sigstate); 2070#endif 2071 return 0; 2072} 2073 2074static void 2075Emulate3ButtonsSetEnabled(InputInfoPtr pInfo, Bool enable) 2076{ 2077 MouseDevPtr pMse = pInfo->private; 2078 2079 if (pMse->emulate3Buttons == enable) 2080 return; 2081 2082 pMse->emulate3Buttons = enable; 2083 2084 if (enable) { 2085 pMse->emulateState = 0; 2086 pMse->emulate3Pending = FALSE; 2087 pMse->emulate3ButtonsSoft = FALSE; /* specifically requested now */ 2088 2089 RegisterBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler, 2090 (pointer) pInfo); 2091 } else { 2092 if (pMse->emulate3Pending) 2093 buttonTimer(pInfo); 2094 2095 RemoveBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler, 2096 (pointer) pInfo); 2097 } 2098} 2099 2100static Bool 2101Emulate3ButtonsSoft(InputInfoPtr pInfo) 2102{ 2103 MouseDevPtr pMse = pInfo->private; 2104 2105 if (!pMse->emulate3ButtonsSoft) 2106 return TRUE; 2107 2108#if defined(__NetBSD__) && defined(WSCONS_SUPPORT) 2109 /* 2110 * On NetBSD a wsmouse is a multiplexed device. Imagine a notebook 2111 * with two-button mousepad, and an external USB mouse plugged in 2112 * temporarily. After using button 3 on the external mouse and 2113 * unplugging it again, the mousepad will still need to emulate 2114 * 3 buttons. 2115 */ 2116 return TRUE; 2117#else 2118 LogMessageVerbSigSafe(X_INFO, 4, 2119 "mouse: 3rd Button detected: disabling emulate3Button\n"); 2120 2121 Emulate3ButtonsSetEnabled(pInfo, FALSE); 2122 2123 return FALSE; 2124#endif 2125} 2126 2127static void MouseBlockHandler(BLOCK_HANDLER_ARGS) 2128{ 2129 InputInfoPtr pInfo = (InputInfoPtr) data; 2130 MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 2131 int ms; 2132 2133 if (pMse->emulate3Pending) 2134 { 2135 ms = pMse->emulate3Expires - GetTimeInMillis (); 2136 if (ms <= 0) 2137 ms = 0; 2138 AdjustWaitForDelay (waitTime, ms); 2139 } 2140} 2141 2142static void MouseWakeupHandler(WAKEUP_HANDLER_ARGS) 2143{ 2144 InputInfoPtr pInfo = (InputInfoPtr) data; 2145 MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 2146 int ms; 2147 2148 if (pMse->emulate3Pending) 2149 { 2150 ms = pMse->emulate3Expires - GetTimeInMillis (); 2151 if (ms <= 0) 2152 buttonTimer (pInfo); 2153 } 2154} 2155 2156/******************************************************************* 2157 * 2158 * Post mouse events 2159 * 2160 *******************************************************************/ 2161 2162static void 2163MouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy) 2164{ 2165 MouseDevPtr pMse; 2166 int emulateButtons; 2167 int id, change; 2168 int emuWheelDelta, emuWheelButton, emuWheelButtonMask; 2169 int wheelButtonMask; 2170 int ms; 2171 2172 pMse = pInfo->private; 2173 2174 change = buttons ^ pMse->lastMappedButtons; 2175 pMse->lastMappedButtons = buttons; 2176 2177 /* Do single button double click */ 2178 if (pMse->doubleClickSourceButtonMask) { 2179 if (buttons & pMse->doubleClickSourceButtonMask) { 2180 if (!(pMse->doubleClickOldSourceState)) { 2181 /* double-click button has just been pressed. 2182 * Ignore it if target button is already down. 2183 */ 2184 if (!(buttons & pMse->doubleClickTargetButtonMask)) { 2185 /* Target button isn't down, so send a double-click */ 2186 xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 1, 0, 0); 2187 xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 0, 0, 0); 2188 xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 1, 0, 0); 2189 xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 0, 0, 0); 2190 } 2191 } 2192 pMse->doubleClickOldSourceState = 1; 2193 } 2194 else 2195 pMse->doubleClickOldSourceState = 0; 2196 2197 /* Whatever happened, mask the double-click button so it doesn't get 2198 * processed as a normal button as well. 2199 */ 2200 buttons &= ~(pMse->doubleClickSourceButtonMask); 2201 change &= ~(pMse->doubleClickSourceButtonMask); 2202 } 2203 2204 if (pMse->emulateWheel) { 2205 /* Emulate wheel button handling */ 2206 if(pMse->wheelButton == 0) 2207 wheelButtonMask = 0; 2208 else 2209 wheelButtonMask = 1 << (pMse->wheelButton - 1); 2210 2211 if (change & wheelButtonMask) { 2212 if (buttons & wheelButtonMask) { 2213 /* Start timeout handling */ 2214 pMse->wheelButtonExpires = GetTimeInMillis () + pMse->wheelButtonTimeout; 2215 ms = - pMse->wheelButtonTimeout; 2216 } else { 2217 ms = pMse->wheelButtonExpires - GetTimeInMillis (); 2218 2219 if (0 < ms) { 2220 /* 2221 * If the button is released early enough emit the button 2222 * press/release events 2223 */ 2224 xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 2225 1, 0, 0); 2226 xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 2227 0, 0, 0); 2228 } 2229 } 2230 } else 2231 ms = pMse->wheelButtonExpires - GetTimeInMillis (); 2232 2233 /* Intercept wheel emulation if the necessary button is depressed or 2234 if no button is necessary */ 2235 if ((buttons & wheelButtonMask) || wheelButtonMask==0) { 2236 if (ms <= 0 || wheelButtonMask==0) { 2237 /* Y axis movement */ 2238 if (pMse->negativeY != MSE_NOAXISMAP) { 2239 pMse->wheelYDistance += dy; 2240 if (pMse->wheelYDistance < 0) { 2241 emuWheelDelta = -pMse->wheelInertia; 2242 emuWheelButton = pMse->negativeY; 2243 } else { 2244 emuWheelDelta = pMse->wheelInertia; 2245 emuWheelButton = pMse->positiveY; 2246 } 2247 emuWheelButtonMask = 1 << (emuWheelButton - 1); 2248 while (abs(pMse->wheelYDistance) > pMse->wheelInertia) { 2249 pMse->wheelYDistance -= emuWheelDelta; 2250 2251 pMse->wheelXDistance = 0; 2252 /* 2253 * Synthesize the press and release, but not when 2254 * the button to be synthesized is already pressed 2255 * "for real". 2256 */ 2257 if (!(emuWheelButtonMask & buttons) || 2258 (emuWheelButtonMask & wheelButtonMask)) { 2259 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2260 1, 0, 0); 2261 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2262 0, 0, 0); 2263 } 2264 } 2265 } 2266 2267 /* X axis movement */ 2268 if (pMse->negativeX != MSE_NOAXISMAP) { 2269 pMse->wheelXDistance += dx; 2270 if (pMse->wheelXDistance < 0) { 2271 emuWheelDelta = -pMse->wheelInertia; 2272 emuWheelButton = pMse->negativeX; 2273 } else { 2274 emuWheelDelta = pMse->wheelInertia; 2275 emuWheelButton = pMse->positiveX; 2276 } 2277 emuWheelButtonMask = 1 << (emuWheelButton - 1); 2278 while (abs(pMse->wheelXDistance) > pMse->wheelInertia) { 2279 pMse->wheelXDistance -= emuWheelDelta; 2280 2281 pMse->wheelYDistance = 0; 2282 /* 2283 * Synthesize the press and release, but not when 2284 * the button to be synthesized is already pressed 2285 * "for real". 2286 */ 2287 if (!(emuWheelButtonMask & buttons) || 2288 (emuWheelButtonMask & wheelButtonMask)) { 2289 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2290 1, 0, 0); 2291 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2292 0, 0, 0); 2293 } 2294 } 2295 } 2296 } 2297 2298 /* Absorb the mouse movement while the wheel button is pressed. */ 2299 dx = 0; 2300 dy = 0; 2301 } 2302 /* 2303 * Button events for the wheel button are only emitted through 2304 * the timeout code. 2305 */ 2306 buttons &= ~wheelButtonMask; 2307 change &= ~wheelButtonMask; 2308 } 2309 2310 if (pMse->emulate3ButtonsSoft && pMse->emulate3Pending && (dx || dy)) 2311 buttonTimer(pInfo); 2312 2313 if (dx || dy) 2314 xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy); 2315 2316 if (change) { 2317 2318 /* 2319 * adjust buttons state for drag locks! 2320 * if there is drag locks 2321 */ 2322 if (pMse->pDragLock) { 2323 DragLockPtr pLock; 2324 int tarOfGoingDown, tarOfDown; 2325 int realbuttons; 2326 2327 /* get drag lock block */ 2328 pLock = pMse->pDragLock; 2329 /* save real buttons */ 2330 realbuttons = buttons; 2331 2332 /* if drag lock used */ 2333 2334 /* state of drag lock buttons not seen always up */ 2335 2336 buttons &= ~pLock->lockButtonsM; 2337 2338 /* 2339 * if lock buttons being depressed changes state of 2340 * targets simulatedDown. 2341 */ 2342 tarOfGoingDown = lock2targetMap(pLock, 2343 realbuttons & change & pLock->lockButtonsM); 2344 pLock->simulatedDown ^= tarOfGoingDown; 2345 2346 /* targets of drag locks down */ 2347 tarOfDown = lock2targetMap(pLock, 2348 realbuttons & pLock->lockButtonsM); 2349 2350 /* 2351 * when simulatedDown set and target pressed, 2352 * simulatedDown goes false 2353 */ 2354 pLock->simulatedDown &= ~(realbuttons & change); 2355 2356 /* 2357 * if master drag lock released 2358 * then master drag lock state on 2359 */ 2360 pLock->masterTS |= (~realbuttons & change) & pLock->masterLockM; 2361 2362 /* if master state, buttons going down are simulatedDown */ 2363 if (pLock->masterTS) 2364 pLock->simulatedDown |= (realbuttons & change); 2365 2366 /* if any button pressed, no longer in master drag lock state */ 2367 if (realbuttons & change) 2368 pLock->masterTS = 0; 2369 2370 /* if simulatedDown or drag lock down, simulate down */ 2371 buttons |= (pLock->simulatedDown | tarOfDown); 2372 2373 /* master button not seen */ 2374 buttons &= ~(pLock->masterLockM); 2375 2376 /* buttons changed since last time */ 2377 change = buttons ^ pLock->lockLastButtons; 2378 2379 /* save this time for next last time. */ 2380 pLock->lockLastButtons = buttons; 2381 } 2382 2383 if (pMse->emulate3Buttons 2384 && (!(buttons & 0x02) || Emulate3ButtonsSoft(pInfo))) { 2385 2386 /* handle all but buttons 1 & 3 normally */ 2387 2388 change &= ~05; 2389 2390 /* emulate the third button by the other two */ 2391 2392 emulateButtons = (buttons & 01) | ((buttons &04) >> 1); 2393 2394 if ((id = stateTab[pMse->emulateState][emulateButtons][0]) != 0) 2395 xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0); 2396 if ((id = stateTab[pMse->emulateState][emulateButtons][1]) != 0) 2397 xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0); 2398 2399 pMse->emulateState = 2400 stateTab[pMse->emulateState][emulateButtons][2]; 2401 2402 if (stateTab[pMse->emulateState][4][0] != 0) { 2403 pMse->emulate3Expires = 2404 GetTimeInMillis() + pMse->emulate3Timeout; 2405 pMse->emulate3Pending = TRUE; 2406 } else { 2407 pMse->emulate3Pending = FALSE; 2408 } 2409 } 2410 2411 while (change) { 2412 id = ffs(change); 2413 change &= ~(1 << (id - 1)); 2414 xf86PostButtonEvent(pInfo->dev, 0, id, 2415 (buttons & (1 << (id - 1))), 0, 0); 2416 } 2417 2418 } 2419} 2420 2421static void 2422MousePostEvent(InputInfoPtr pInfo, int truebuttons, 2423 int dx, int dy, int dz, int dw) 2424{ 2425 MouseDevPtr pMse; 2426 mousePrivPtr mousepriv; 2427 int zbutton = 0, wbutton = 0, zbuttoncount = 0, wbuttoncount = 0; 2428 int i, b, buttons = 0; 2429 2430 pMse = pInfo->private; 2431 mousepriv = (mousePrivPtr)pMse->mousePriv; 2432 2433 if (pMse->protocolID == PROT_MMHIT) 2434 b = reverseBits(hitachMap, truebuttons); 2435 else 2436 b = reverseBits(reverseMap, truebuttons); 2437 2438 /* Remap mouse buttons */ 2439 b &= (1<<MSE_MAXBUTTONS)-1; 2440 for (i = 0; b; i++) { 2441 if (b & 1) 2442 buttons |= pMse->buttonMap[i]; 2443 b >>= 1; 2444 } 2445 2446 /* Map the Z axis movement. */ 2447 /* XXX Could this go in the conversion_proc? */ 2448 switch (pMse->negativeZ) { 2449 case MSE_NOZMAP: /* do nothing */ 2450 dz = 0; 2451 break; 2452 case MSE_MAPTOX: 2453 if (dz != 0) { 2454 dx = dz; 2455 dz = 0; 2456 } 2457 break; 2458 case MSE_MAPTOY: 2459 if (dz != 0) { 2460 dy = dz; 2461 dz = 0; 2462 } 2463 break; 2464 default: /* buttons */ 2465 buttons &= ~(pMse->negativeZ | pMse->positiveZ); 2466 if (dz < 0) { 2467 zbutton = pMse->negativeZ; 2468 zbuttoncount = -dz; 2469 } else if (dz > 0) { 2470 zbutton = pMse->positiveZ; 2471 zbuttoncount = dz; 2472 } 2473 dz = 0; 2474 break; 2475 } 2476 switch (pMse->negativeW) { 2477 case MSE_NOZMAP: /* do nothing */ 2478 dw = 0; 2479 break; 2480 case MSE_MAPTOX: 2481 if (dw != 0) { 2482 dx = dw; 2483 dw = 0; 2484 } 2485 break; 2486 case MSE_MAPTOY: 2487 if (dw != 0) { 2488 dy = dw; 2489 dw = 0; 2490 } 2491 break; 2492 default: /* buttons */ 2493 buttons &= ~(pMse->negativeW | pMse->positiveW); 2494 if (dw < 0) { 2495 wbutton = pMse->negativeW; 2496 wbuttoncount = -dw; 2497 } else if (dw > 0) { 2498 wbutton = pMse->positiveW; 2499 wbuttoncount = dw; 2500 } 2501 dw = 0; 2502 break; 2503 } 2504 2505 2506 /* Apply angle offset */ 2507 if (pMse->angleOffset != 0) { 2508 double rad = 3.141592653 * pMse->angleOffset / 180.0; 2509 int ndx = dx; 2510 dx = (int)((dx * cos(rad)) + (dy * sin(rad)) + 0.5); 2511 dy = (int)((dy * cos(rad)) - (ndx * sin(rad)) + 0.5); 2512 } 2513 2514 dx = pMse->invX * dx; 2515 dy = pMse->invY * dy; 2516 if (pMse->flipXY) { 2517 int tmp = dx; 2518 dx = dy; 2519 dy = tmp; 2520 } 2521 2522 /* Accumulate the scaled dx, dy in the private variables 2523 fracdx,fracdy and return the integer number part */ 2524 if (mousepriv) { 2525 mousepriv->fracdx += mousepriv->sensitivity*dx; 2526 mousepriv->fracdy += mousepriv->sensitivity*dy; 2527 mousepriv->fracdx -= ( dx=(int)(mousepriv->fracdx) ); 2528 mousepriv->fracdy -= ( dy=(int)(mousepriv->fracdy) ); 2529 } 2530 2531 /* If mouse wheel movement has to be mapped on a button, we need to 2532 * loop for button press and release events. */ 2533 do { 2534 MouseDoPostEvent(pInfo, buttons | zbutton | wbutton, dx, dy); 2535 dx = dy = 0; 2536 if (zbutton || wbutton) 2537 MouseDoPostEvent(pInfo, buttons, 0, 0); 2538 if (--zbuttoncount <= 0) 2539 zbutton = 0; 2540 if (--wbuttoncount <= 0) 2541 wbutton = 0; 2542 } while (zbutton || wbutton); 2543 2544 pMse->lastButtons = truebuttons; 2545} 2546/****************************************************************** 2547 * 2548 * Mouse Setup Code 2549 * 2550 ******************************************************************/ 2551/* 2552 * This array is indexed by the MouseProtocolID values, so the order of the 2553 * entries must match that of the MouseProtocolID enum in mouse.h. 2554 */ 2555static unsigned char proto[PROT_NUMPROTOS][8] = { 2556 /* --header-- ---data--- packet -4th-byte- mouse */ 2557 /* mask id mask id bytes mask id flags */ 2558 /* Serial mice */ 2559 { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00, MPF_NONE }, /* MicroSoft */ 2560 { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_SAFE }, /* MouseSystems */ 2561 { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MMSeries */ 2562 { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* Logitech */ 2563 { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00, MPF_NONE }, /* MouseMan */ 2564 { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MM_HitTablet */ 2565 { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00, MPF_NONE }, /* GlidePoint */ 2566 { 0x40, 0x40, 0x40, 0x00, 3, ~0x3f, 0x00, MPF_NONE }, /* IntelliMouse */ 2567 { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00, MPF_NONE }, /* ThinkingMouse */ 2568 { 0x80, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* ACECAD */ 2569 { 0x40, 0x40, 0x40, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* ValuMouseScroll */ 2570 /* PS/2 variants */ 2571 { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* PS/2 mouse */ 2572 { 0xc8, 0x08, 0x00, 0x00, 3, 0x00, 0x00, MPF_NONE }, /* genericPS/2 mouse*/ 2573 { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* IntelliMouse */ 2574 { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* Explorer */ 2575 { 0x80, 0x80, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* ThinkingMouse */ 2576 { 0x08, 0x08, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MouseMan+ */ 2577 { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* GlidePoint */ 2578 { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* NetMouse */ 2579 { 0xc0, 0x00, 0x00, 0x00, 6, 0x00, 0xff, MPF_NONE }, /* NetScroll */ 2580 /* Bus Mouse */ 2581 { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_NONE }, /* BusMouse */ 2582 { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_NONE }, /* Auto (dummy) */ 2583 { 0xf8, 0x80, 0x00, 0x00, 8, 0x00, 0xff, MPF_NONE }, /* SysMouse */ 2584}; 2585 2586 2587/* 2588 * SetupMouse -- 2589 * Sets up the mouse parameters 2590 */ 2591static Bool 2592SetupMouse(InputInfoPtr pInfo) 2593{ 2594 MouseDevPtr pMse; 2595 int protoPara[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; 2596 const char *name = NULL; 2597 Bool automatic = FALSE; 2598 2599 pMse = pInfo->private; 2600 2601 /* Handle the "Auto" protocol. */ 2602 if (pMse->protocolID == PROT_AUTO) { 2603 /* 2604 * We come here when user specifies protocol "auto" in 2605 * the configuration file or through the xf86misc extensions. 2606 * So we initialize autoprobing here. 2607 * Probe for PnP/OS mouse first. If unsuccessful 2608 * try to guess protocol from incoming data. 2609 */ 2610 automatic = TRUE; 2611 pMse->autoProbe = TRUE; 2612 name = autoOSProtocol(pInfo,protoPara); 2613 if (name) { 2614#ifdef EXTMOUSEDEBUG 2615 ErrorF("PnP/OS Mouse detected: %s\n",name); 2616#endif 2617 } 2618 } 2619 2620 SetMouseProto(pMse, pMse->protocolID); 2621 2622 if (automatic) { 2623 if (name) { 2624 /* Possible protoPara overrides from SetupAuto. */ 2625 for (size_t i = 0; i < sizeof(pMse->protoPara); i++) 2626 if (protoPara[i] != -1) 2627 pMse->protoPara[i] = protoPara[i]; 2628 /* if we come here PnP/OS mouse probing was successful */ 2629 } else { 2630 /* PnP/OS mouse probing wasn't successful; we look at data */ 2631 } 2632 } 2633 2634 /* 2635 * If protocol has changed fetch the default options 2636 * for the new protocol. 2637 */ 2638 if (pMse->oldProtocolID != pMse->protocolID) { 2639 if ((pMse->protocolID >= 0) 2640 && (pMse->protocolID < PROT_NUMPROTOS) 2641 && mouseProtocols[pMse->protocolID].defaults) { 2642 pointer tmp = xf86OptionListCreate( 2643 mouseProtocols[pMse->protocolID].defaults, -1, 0); 2644 pInfo->options = xf86OptionListMerge(pInfo->options, tmp); 2645 } 2646 /* 2647 * If baudrate is set write it back to the option 2648 * list so that the serial interface code can access 2649 * the new value. Not set means default. 2650 */ 2651 if (pMse->baudRate) 2652 xf86ReplaceIntOption(pInfo->options, "BaudRate", pMse->baudRate); 2653 pMse->oldProtocolID = pMse->protocolID; /* hack */ 2654 } 2655 2656 2657 /* Set the port parameters. */ 2658 if (!automatic) 2659 xf86SetSerial(pInfo->fd, pInfo->options); 2660 2661 if (!initMouseHW(pInfo)) 2662 return FALSE; 2663 2664 pMse->protoBufTail = 0; 2665 pMse->inSync = 0; 2666 2667 return TRUE; 2668} 2669 2670/******************************************************************** 2671 * 2672 * Mouse HW setup code 2673 * 2674 ********************************************************************/ 2675 2676/* 2677** The following lines take care of the Logitech MouseMan protocols. 2678** The "Logitech" protocol is for the old "series 9" Logitech products. 2679** All products since then use the "MouseMan" protocol. Some models 2680** were programmable, but most (all?) of the current models are not. 2681** 2682** NOTE: There are different versions of both MouseMan and TrackMan! 2683** Hence I add another protocol PROT_LOGIMAN, which the user can 2684** specify as MouseMan in an xorg.conf file. This entry was 2685** formerly handled as a special case of PROT_MS. However, people 2686** who don't have the middle button problem, can still specify 2687** Microsoft and use PROT_MS. 2688** 2689** By default, these mice should use a 3 byte Microsoft protocol 2690** plus a 4th byte for the middle button. However, the mouse might 2691** have switched to a different protocol before we use it, so I send 2692** the proper sequence just in case. 2693** 2694** NOTE: - all commands to (at least the European) MouseMan have to 2695** be sent at 1200 Baud. 2696** - each command starts with a '*'. 2697** - whenever the MouseMan receives a '*', it will switch back 2698** to 1200 Baud. Hence I have to select the desired protocol 2699** first, then select the baud rate. 2700** 2701** The protocols supported by the (European) MouseMan are: 2702** - 5 byte packed binary protocol, as with the Mouse Systems 2703** mouse. Selected by sequence "*U". 2704** - 2 button 3 byte MicroSoft compatible protocol. Selected 2705** by sequence "*V". 2706** - 3 button 3+1 byte MicroSoft compatible protocol (default). 2707** Selected by sequence "*X". 2708** 2709** The following baud rates are supported: 2710** - 1200 Baud (default). Selected by sequence "*n". 2711** - 9600 Baud. Selected by sequence "*q". 2712** 2713** Selecting a sample rate is no longer supported with the MouseMan! 2714** [CHRIS-211092] 2715*/ 2716 2717/* 2718 * Do a reset wrap mode before reset. 2719 */ 2720#define do_ps2Reset(x) { \ 2721 int i = RETRY_COUNT;\ 2722 while (i-- > 0) { \ 2723 xf86FlushInput(x->fd); \ 2724 if (ps2Reset(x)) break; \ 2725 } \ 2726 } 2727 2728 2729static Bool 2730initMouseHW(InputInfoPtr pInfo) 2731{ 2732 MouseDevPtr pMse = pInfo->private; 2733 const char *s; 2734 unsigned char c; 2735 int speed; 2736 pointer options; 2737 unsigned char *param = NULL; 2738 int paramlen = 0; 2739 int count = RETRY_COUNT; 2740 Bool ps2Init = TRUE; 2741 2742 switch (pMse->protocolID) { 2743 case PROT_LOGI: /* Logitech Mice */ 2744 /* 2745 * The baud rate selection command must be sent at the current 2746 * baud rate; try all likely settings. 2747 */ 2748 speed = pMse->baudRate; 2749 switch (speed) { 2750 case 9600: 2751 s = "*q"; 2752 break; 2753 case 4800: 2754 s = "*p"; 2755 break; 2756 case 2400: 2757 s = "*o"; 2758 break; 2759 case 1200: 2760 s = "*n"; 2761 break; 2762 default: 2763 /* Fallback value */ 2764 speed = 1200; 2765 s = "*n"; 2766 } 2767 xf86SetSerialSpeed(pInfo->fd, 9600); 2768 xf86WriteSerial(pInfo->fd, s, 2); 2769 usleep(100000); 2770 xf86SetSerialSpeed(pInfo->fd, 4800); 2771 xf86WriteSerial(pInfo->fd, s, 2); 2772 usleep(100000); 2773 xf86SetSerialSpeed(pInfo->fd, 2400); 2774 xf86WriteSerial(pInfo->fd, s, 2); 2775 usleep(100000); 2776 xf86SetSerialSpeed(pInfo->fd, 1200); 2777 xf86WriteSerial(pInfo->fd, s, 2); 2778 usleep(100000); 2779 xf86SetSerialSpeed(pInfo->fd, speed); 2780 2781 /* Select MM series data format. */ 2782 xf86WriteSerial(pInfo->fd, "S", 1); 2783 usleep(100000); 2784 /* Set the parameters up for the MM series protocol. */ 2785 options = pInfo->options; 2786 COLLECT_INPUT_OPTIONS(pInfo, mmDefaults); 2787 xf86SetSerial(pInfo->fd, pInfo->options); 2788 pInfo->options = options; 2789 2790 /* Select report rate/frequency. */ 2791 if (pMse->sampleRate <= 0) c = 'O'; /* 100 */ 2792 else if (pMse->sampleRate <= 15) c = 'J'; /* 10 */ 2793 else if (pMse->sampleRate <= 27) c = 'K'; /* 20 */ 2794 else if (pMse->sampleRate <= 42) c = 'L'; /* 35 */ 2795 else if (pMse->sampleRate <= 60) c = 'R'; /* 50 */ 2796 else if (pMse->sampleRate <= 85) c = 'M'; /* 67 */ 2797 else if (pMse->sampleRate <= 125) c = 'Q'; /* 100 */ 2798 else c = 'N'; /* 150 */ 2799 xf86WriteSerial(pInfo->fd, &c, 1); 2800 break; 2801 2802 case PROT_LOGIMAN: 2803 speed = pMse->baudRate; 2804 switch (speed) { 2805 case 9600: 2806 s = "*q"; 2807 break; 2808 case 1200: 2809 s = "*n"; 2810 break; 2811 default: 2812 /* Fallback value */ 2813 speed = 1200; 2814 s = "*n"; 2815 } 2816 xf86SetSerialSpeed(pInfo->fd, 1200); 2817 xf86WriteSerial(pInfo->fd, "*n", 2); 2818 xf86WriteSerial(pInfo->fd, "*X", 2); 2819 xf86WriteSerial(pInfo->fd, s, 2); 2820 usleep(100000); 2821 xf86SetSerialSpeed(pInfo->fd, speed); 2822 break; 2823 2824 case PROT_MMHIT: /* MM_HitTablet */ 2825 /* 2826 * Initialize Hitachi PUMA Plus - Model 1212E to desired settings. 2827 * The tablet must be configured to be in MM mode, NO parity, 2828 * Binary Format. pMse->sampleRate controls the sensitivity 2829 * of the tablet. We only use this tablet for it's 4-button puck 2830 * so we don't run in "Absolute Mode". 2831 */ 2832 xf86WriteSerial(pInfo->fd, "z8", 2); /* Set Parity = "NONE" */ 2833 usleep(50000); 2834 xf86WriteSerial(pInfo->fd, "zb", 2); /* Set Format = "Binary" */ 2835 usleep(50000); 2836 xf86WriteSerial(pInfo->fd, "@", 1); /* Set Report Mode = "Stream" */ 2837 usleep(50000); 2838 xf86WriteSerial(pInfo->fd, "R", 1); /* Set Output Rate = "45 rps" */ 2839 usleep(50000); 2840 xf86WriteSerial(pInfo->fd, "I\x20", 2); /* Set Incrememtal Mode "20" */ 2841 usleep(50000); 2842 xf86WriteSerial(pInfo->fd, "E", 1); /* Set Data Type = "Relative */ 2843 usleep(50000); 2844 /* 2845 * These sample rates translate to 'lines per inch' on the Hitachi 2846 * tablet. 2847 */ 2848 if (pMse->sampleRate <= 40) c = 'g'; 2849 else if (pMse->sampleRate <= 100) c = 'd'; 2850 else if (pMse->sampleRate <= 200) c = 'e'; 2851 else if (pMse->sampleRate <= 500) c = 'h'; 2852 else if (pMse->sampleRate <= 1000) c = 'j'; 2853 else c = 'd'; 2854 xf86WriteSerial(pInfo->fd, &c, 1); 2855 usleep(50000); 2856 xf86WriteSerial(pInfo->fd, "\021", 1); /* Resume DATA output */ 2857 break; 2858 2859 case PROT_THINKING: /* ThinkingMouse */ 2860 /* This mouse may send a PnP ID string, ignore it. */ 2861 usleep(200000); 2862 xf86FlushInput(pInfo->fd); 2863 /* Send the command to initialize the beast. */ 2864 for (s = "E5E5"; *s; ++s) { 2865 xf86WriteSerial(pInfo->fd, s, 1); 2866 if ((xf86WaitForInput(pInfo->fd, 1000000) <= 0)) 2867 break; 2868 xf86ReadSerial(pInfo->fd, &c, 1); 2869 if (c != *s) 2870 break; 2871 } 2872 break; 2873 2874 case PROT_MSC: /* MouseSystems Corp */ 2875 usleep(100000); 2876 xf86FlushInput(pInfo->fd); 2877 break; 2878 2879 case PROT_ACECAD: 2880 /* initialize */ 2881 /* A nul character resets. */ 2882 xf86WriteSerial(pInfo->fd, "", 1); 2883 usleep(50000); 2884 /* Stream out relative mode high resolution increments of 1. */ 2885 xf86WriteSerial(pInfo->fd, "@EeI!", 5); 2886 break; 2887 2888 case PROT_BM: /* bus/InPort mouse */ 2889 if (osInfo->SetBMRes) 2890 osInfo->SetBMRes(pInfo, pMse->protocol, pMse->sampleRate, 2891 pMse->resolution); 2892 break; 2893 2894 case PROT_GENPS2: 2895 ps2Init = FALSE; 2896 break; 2897 2898 case PROT_PS2: 2899 case PROT_GLIDEPS2: 2900 break; 2901 2902 case PROT_IMPS2: /* IntelliMouse */ 2903 { 2904 static unsigned char seq[] = { 243, 200, 243, 100, 243, 80 }; 2905 param = seq; 2906 paramlen = sizeof(seq); 2907 } 2908 break; 2909 2910 case PROT_EXPPS2: /* IntelliMouse Explorer */ 2911 { 2912 static unsigned char seq[] = { 243, 200, 243, 100, 243, 80, 2913 243, 200, 243, 200, 243, 80 }; 2914 2915 param = seq; 2916 paramlen = sizeof(seq); 2917 } 2918 break; 2919 2920 case PROT_NETPS2: /* NetMouse, NetMouse Pro, Mie Mouse */ 2921 case PROT_NETSCPS2: /* NetScroll */ 2922 { 2923 static unsigned char seq[] = { 232, 3, 230, 230, 230, 233 }; 2924 2925 param = seq; 2926 paramlen = sizeof(seq); 2927 } 2928 break; 2929 2930 case PROT_MMPS2: /* MouseMan+, FirstMouse+ */ 2931 { 2932 static unsigned char seq[] = { 230, 232, 0, 232, 3, 232, 2, 232, 1, 2933 230, 232, 3, 232, 1, 232, 2, 232, 3 }; 2934 param = seq; 2935 paramlen = sizeof(seq); 2936 } 2937 break; 2938 2939 case PROT_THINKPS2: /* ThinkingMouse */ 2940 { 2941 static unsigned char seq[] = { 243, 10, 232, 0, 243, 20, 243, 60, 2942 243, 40, 243, 20, 243, 20, 243, 60, 2943 243, 40, 243, 20, 243, 20 }; 2944 param = seq; 2945 paramlen = sizeof(seq); 2946 } 2947 break; 2948 case PROT_SYSMOUSE: 2949 if (osInfo->SetMiscRes) 2950 osInfo->SetMiscRes(pInfo, pMse->protocol, pMse->sampleRate, 2951 pMse->resolution); 2952 break; 2953 2954 default: 2955 /* Nothing to do. */ 2956 break; 2957 } 2958 2959 if (pMse->class & (MSE_PS2 | MSE_XPS2)) { 2960 /* 2961 * If one part of the PS/2 mouse initialization fails 2962 * redo complete initialization. There are mice which 2963 * have occasional problems with initialization and 2964 * are in an unknown state. 2965 */ 2966 if (ps2Init) { 2967 REDO: 2968 do_ps2Reset(pInfo); 2969 if (paramlen > 0) { 2970 if (!ps2SendPacket(pInfo,param,paramlen)) { 2971 usleep(30000); 2972 xf86FlushInput(pInfo->fd); 2973 if (!count--) 2974 return TRUE; 2975 goto REDO; 2976 } 2977 ps2GetDeviceID(pInfo); 2978 usleep(30000); 2979 xf86FlushInput(pInfo->fd); 2980 } 2981 2982 if (osInfo->SetPS2Res) { 2983 osInfo->SetPS2Res(pInfo, pMse->protocol, pMse->sampleRate, 2984 pMse->resolution); 2985 } else { 2986 unsigned char c2[2]; 2987 2988 c = 0xE6; /*230*/ /* 1:1 scaling */ 2989 if (!ps2SendPacket(pInfo,&c,1)) { 2990 if (!count--) 2991 return TRUE; 2992 goto REDO; 2993 } 2994 c2[0] = 0xF3; /*243*/ /* set sampling rate */ 2995 if (pMse->sampleRate > 0) { 2996 if (pMse->sampleRate >= 200) 2997 c2[1] = 200; 2998 else if (pMse->sampleRate >= 100) 2999 c2[1] = 100; 3000 else if (pMse->sampleRate >= 80) 3001 c2[1] = 80; 3002 else if (pMse->sampleRate >= 60) 3003 c2[1] = 60; 3004 else if (pMse->sampleRate >= 40) 3005 c2[1] = 40; 3006 else 3007 c2[1] = 20; 3008 } else { 3009 c2[1] = 100; 3010 } 3011 if (!ps2SendPacket(pInfo,c2,2)) { 3012 if (!count--) 3013 return TRUE; 3014 goto REDO; 3015 } 3016 c2[0] = 0xE8; /*232*/ /* set device resolution */ 3017 if (pMse->resolution > 0) { 3018 if (pMse->resolution >= 200) 3019 c2[1] = 3; 3020 else if (pMse->resolution >= 100) 3021 c2[1] = 2; 3022 else if (pMse->resolution >= 50) 3023 c2[1] = 1; 3024 else 3025 c2[1] = 0; 3026 } else { 3027 c2[1] = 3; /* used to be 2, W. uses 3 */ 3028 } 3029 if (!ps2SendPacket(pInfo,c2,2)) { 3030 if (!count--) 3031 return TRUE; 3032 goto REDO; 3033 } 3034 usleep(30000); 3035 xf86FlushInput(pInfo->fd); 3036 if (!ps2EnableDataReporting(pInfo)) { 3037 xf86Msg(X_INFO, "%s: ps2EnableDataReporting: failed\n", 3038 pInfo->name); 3039 xf86FlushInput(pInfo->fd); 3040 if (!count--) 3041 return TRUE; 3042 goto REDO; 3043 } else { 3044 xf86Msg(X_INFO, "%s: ps2EnableDataReporting: succeeded\n", 3045 pInfo->name); 3046 } 3047 } 3048 /* 3049 * The PS/2 reset handling needs to be rechecked. 3050 * We need to wait until after the 4.3 release. 3051 */ 3052 } 3053 } else { 3054 if (paramlen > 0) { 3055 if (xf86WriteSerial(pInfo->fd, param, paramlen) != paramlen) 3056 xf86Msg(X_ERROR, "%s: Mouse initialization failed\n", 3057 pInfo->name); 3058 usleep(30000); 3059 xf86FlushInput(pInfo->fd); 3060 } 3061 } 3062 3063 return TRUE; 3064} 3065 3066#ifdef SUPPORT_MOUSE_RESET 3067static Bool 3068mouseReset(InputInfoPtr pInfo, unsigned char val) 3069{ 3070 MouseDevPtr pMse = pInfo->private; 3071 mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv; 3072 CARD32 prevEvent = mousepriv->lastEvent; 3073 Bool expectReset = FALSE; 3074 Bool ret = FALSE; 3075 3076 mousepriv->lastEvent = GetTimeInMillis(); 3077 3078#ifdef EXTMOUSEDEBUG 3079 LogMessageVerbSigSafe(X_INFO, -1, "byte: 0x%x time: %li\n",val,mousepriv->lastEvent); 3080#endif 3081 /* 3082 * We believe that the following is true: 3083 * When the mouse is replugged it will send a reset package 3084 * It takes several seconds to replug a mouse: We don't see 3085 * events for several seconds before we see the replug event package. 3086 * There is no significant delay between consecutive bytes 3087 * of a replug event package. 3088 * There are no bytes sent after the replug event package until 3089 * the mouse is reset. 3090 */ 3091 3092 if (mousepriv->current == 0 3093 && (mousepriv->lastEvent - prevEvent) < 4000) 3094 return FALSE; 3095 3096 if (mousepriv->current > 0 3097 && (mousepriv->lastEvent - prevEvent) >= 1000) { 3098 mousepriv->inReset = FALSE; 3099 mousepriv->current = 0; 3100 return FALSE; 3101 } 3102 3103 if (mousepriv->inReset) 3104 mousepriv->inReset = FALSE; 3105 3106#ifdef EXTMOUSEDEBUG 3107 LogMessageVerbSigSafe(X_INFO, -1, "Mouse Current: %i 0x%x\n",mousepriv->current, val); 3108#endif 3109 3110 /* here we put the mouse specific reset detection */ 3111 /* They need to do three things: */ 3112 /* Check if byte may be a reset byte */ 3113 /* If so: Set expectReset TRUE */ 3114 /* If convinced: Set inReset TRUE */ 3115 /* Register BlockAndWakeupHandler */ 3116 3117 /* PS/2 */ 3118 { 3119 unsigned char seq[] = { 0xaa, 0x00 }; 3120 int len = sizeof(seq); 3121 3122 if (seq[mousepriv->current] == val) 3123 expectReset = TRUE; 3124 3125 if (len == mousepriv->current + 1) { 3126 mousepriv->inReset = TRUE; 3127 mousepriv->expires = GetTimeInMillis() + 1000; 3128 3129#ifdef EXTMOUSEDEBUG 3130 LogMessageVerbSigSafe(X_INFO, -1, "Found PS/2 Reset string\n"); 3131#endif 3132 RegisterBlockAndWakeupHandlers (ps2BlockHandler, 3133 ps2WakeupHandler, (pointer) pInfo); 3134 ret = TRUE; 3135 } 3136 } 3137 3138 if (!expectReset) 3139 mousepriv->current = 0; 3140 else 3141 mousepriv->current++; 3142 return ret; 3143} 3144 3145static void 3146ps2BlockHandler(pointer data, struct timeval **waitTime, 3147 pointer LastSelectMask) 3148{ 3149 InputInfoPtr pInfo = (InputInfoPtr) data; 3150 MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 3151 mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv; 3152 int ms; 3153 3154 if (mousepriv->inReset) { 3155 ms = mousepriv->expires - GetTimeInMillis (); 3156 if (ms <= 0) 3157 ms = 0; 3158 AdjustWaitForDelay (waitTime, ms); 3159 } else 3160 RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler, 3161 (pointer) pInfo); 3162} 3163 3164static void 3165ps2WakeupHandler(pointer data, int i, pointer LastSelectMask) 3166{ 3167 InputInfoPtr pInfo = (InputInfoPtr) data; 3168 MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 3169 mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv; 3170 int ms; 3171 3172 if (mousepriv->inReset) { 3173 unsigned char val; 3174 int blocked; 3175 3176 ms = mousepriv->expires - GetTimeInMillis(); 3177 if (ms > 0) 3178 return; 3179 3180 blocked = xf86BlockSIGIO (); 3181 3182 xf86MsgVerb(X_INFO,3, 3183 "Got reinsert event: reinitializing PS/2 mouse\n"); 3184 val = 0xf4; 3185 if (xf86WriteSerial(pInfo->fd, &val, 1) != 1) 3186 xf86Msg(X_ERROR, "%s: Write to mouse failed\n", 3187 pInfo->name); 3188 xf86UnblockSIGIO(blocked); 3189 } 3190 RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler, 3191 (pointer) pInfo); 3192} 3193#endif /* SUPPORT_MOUSE_RESET */ 3194 3195/************************************************************ 3196 * 3197 * Autoprobe stuff 3198 * 3199 ************************************************************/ 3200#ifdef EXTMOUSEDEBUG 3201# define AP_DBG(x) { ErrorF("Autoprobe: "); ErrorF x; } 3202# define AP_DBGC(x) ErrorF x ; 3203# else 3204# define AP_DBG(x) 3205# define AP_DBGC(x) 3206#endif 3207 3208static 3209MouseProtocolID hardProtocolList[] = { PROT_MSC, PROT_MM, PROT_LOGI, 3210 PROT_LOGIMAN, PROT_MMHIT, 3211 PROT_GLIDE, PROT_IMSERIAL, 3212 PROT_THINKING, PROT_ACECAD, 3213 PROT_THINKPS2, PROT_MMPS2, 3214 PROT_GLIDEPS2, 3215 PROT_NETSCPS2, PROT_EXPPS2,PROT_IMPS2, 3216 PROT_GENPS2, PROT_NETPS2, 3217 PROT_MS, 3218 PROT_UNKNOWN 3219}; 3220 3221static 3222MouseProtocolID softProtocolList[] = { PROT_MSC, PROT_MM, PROT_LOGI, 3223 PROT_LOGIMAN, PROT_MMHIT, 3224 PROT_GLIDE, PROT_IMSERIAL, 3225 PROT_THINKING, PROT_ACECAD, 3226 PROT_THINKPS2, PROT_MMPS2, 3227 PROT_GLIDEPS2, 3228 PROT_NETSCPS2 ,PROT_IMPS2, 3229 PROT_GENPS2, 3230 PROT_MS, 3231 PROT_UNKNOWN 3232}; 3233 3234static const char * 3235autoOSProtocol(InputInfoPtr pInfo, int *protoPara) 3236{ 3237 MouseDevPtr pMse = pInfo->private; 3238 const char *name = NULL; 3239 MouseProtocolID protocolID = PROT_UNKNOWN; 3240 3241 /* Check if the OS has a detection mechanism. */ 3242 if (osInfo->SetupAuto) { 3243 name = osInfo->SetupAuto(pInfo, protoPara); 3244 if (name) { 3245 protocolID = ProtocolNameToID(name); 3246 switch (protocolID) { 3247 case PROT_UNKNOWN: 3248 /* Check for a builtin OS-specific protocol. */ 3249 if (osInfo->CheckProtocol && osInfo->CheckProtocol(name)) { 3250 /* We can only come here if the protocol has been 3251 * changed to auto through the xf86misc extension 3252 * and we have detected an OS specific builtin 3253 * protocol. Currently we cannot handle this */ 3254 name = NULL; 3255 } else 3256 name = NULL; 3257 break; 3258 case PROT_UNSUP: 3259 name = NULL; 3260 break; 3261 default: 3262 break; 3263 } 3264 } 3265 } 3266 if (!name) { 3267 /* A PnP serial mouse? */ 3268 protocolID = MouseGetPnpProtocol(pInfo); 3269 if (protocolID >= 0 && protocolID < PROT_NUMPROTOS) { 3270 name = ProtocolIDToName(protocolID); 3271 xf86Msg(X_PROBED, "%s: PnP-detected protocol: \"%s\"\n", 3272 pInfo->name, name); 3273 } 3274 } 3275 if (!name && osInfo->GuessProtocol) { 3276 name = osInfo->GuessProtocol(pInfo, 0); 3277 if (name) 3278 protocolID = ProtocolNameToID(name); 3279 } 3280 3281 if (name) { 3282 pMse->protocolID = protocolID; 3283 } 3284 3285 return name; 3286} 3287 3288/* 3289 * createProtocolList() -- create a list of protocols which may 3290 * match on the incoming data stream. 3291 */ 3292static void 3293createProtoList(MouseDevPtr pMse, MouseProtocolID *protoList) 3294{ 3295 int i, j, k = 0; 3296 MouseProtocolID prot; 3297 unsigned char *para; 3298 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3299 MouseProtocolID *tmplist = NULL; 3300#if !HAVE_THREADED_INPUT 3301 int blocked; 3302#endif 3303 3304 AP_DBGC(("Autoprobe: ")); 3305 for (i = 0; i < mPriv->count; i++) 3306 AP_DBGC(("%2.2x ", (unsigned char) mPriv->data[i])); 3307 AP_DBGC(("\n")); 3308 3309#if HAVE_THREADED_INPUT 3310 input_lock(); 3311#else 3312 blocked = xf86BlockSIGIO (); 3313#endif 3314 3315 /* create a private copy first so we can write in the old list */ 3316 if ((tmplist = malloc(sizeof(MouseProtocolID) * NUM_AUTOPROBE_PROTOS))){ 3317 for (i = 0; protoList[i] != PROT_UNKNOWN; i++) { 3318 tmplist[i] = protoList[i]; 3319 } 3320 tmplist[i] = PROT_UNKNOWN; 3321 protoList = tmplist; 3322 } else 3323 return; 3324 3325 for (i = 0; ((prot = protoList[i]) != PROT_UNKNOWN 3326 && (k < NUM_AUTOPROBE_PROTOS - 1)) ; i++) { 3327 Bool bad = TRUE; 3328 unsigned char byte = 0; 3329 int count = 0; 3330 int next_header_candidate = 0; 3331 int header_count = 0; 3332 3333 if (!GetProtocol(prot)) 3334 continue; 3335 para = proto[prot]; 3336 3337 AP_DBG(("Protocol: %s ", ProtocolIDToName(prot))); 3338 3339#ifdef EXTMOUSEDEBUG 3340 for (j = 0; j < 7; j++) 3341 AP_DBGC(("%2.2x ", (unsigned char) para[j])); 3342 AP_DBGC(("\n")); 3343#endif 3344 j = 0; 3345 while (1) { 3346 /* look for header */ 3347 while (j < mPriv->count) { 3348 if (((byte = mPriv->data[j++]) & para[0]) == para[1]){ 3349 AP_DBG(("found header %2.2x\n",byte)); 3350 next_header_candidate = j; 3351 count = 1; 3352 break; 3353 } else { 3354 /* 3355 * Bail out if number of bytes per package have 3356 * been tested for header. 3357 * Take bytes per package of leading garbage into 3358 * account. 3359 */ 3360 if (j > para[4] && ++header_count > para[4]) { 3361 j = mPriv->count; 3362 break; 3363 } 3364 } 3365 } 3366 /* check if remaining data matches protocol */ 3367 while (j < mPriv->count) { 3368 byte = mPriv->data[j++]; 3369 if (count == para[4]) { 3370 count = 0; 3371 /* check and eat excess byte */ 3372 if (((byte & para[0]) != para[1]) 3373 && ((byte & para[5]) == para[6])) { 3374 AP_DBG(("excess byte found\n")); 3375 continue; 3376 } 3377 } 3378 if (count == 0) { 3379 /* validate next header */ 3380 bad = FALSE; 3381 AP_DBG(("Complete set found\n")); 3382 if ((byte & para[0]) != para[1]) { 3383 AP_DBG(("Autoprobe: header bad\n")); 3384 bad = TRUE; 3385 break; 3386 } else { 3387 count++; 3388 continue; 3389 } 3390 } 3391 /* validate data */ 3392 else if (((byte & para[2]) != para[3]) 3393 || ((para[7] & MPF_SAFE) 3394 && ((byte & para[0]) == para[1]))) { 3395 AP_DBG(("data bad\n")); 3396 bad = TRUE; 3397 break; 3398 } else { 3399 count ++; 3400 continue; 3401 } 3402 } 3403 if (!bad) { 3404 /* this is a matching protocol */ 3405 mPriv->protoList[k++] = prot; 3406 AP_DBG(("Autoprobe: Adding protocol %s to list (entry %i)\n", 3407 ProtocolIDToName(prot),k-1)); 3408 break; 3409 } 3410 j = next_header_candidate; 3411 next_header_candidate = 0; 3412 /* we have tested number of bytes per package for header */ 3413 if (j > para[4] && ++header_count > para[4]) 3414 break; 3415 /* we have not found anything that looks like a header */ 3416 if (!next_header_candidate) 3417 break; 3418 AP_DBG(("Looking for new header\n")); 3419 } 3420 } 3421 3422#if HAVE_THREADED_INPUT 3423 input_unlock(); 3424#else 3425 xf86UnblockSIGIO(blocked); 3426#endif 3427 3428 mPriv->protoList[k] = PROT_UNKNOWN; 3429 3430 free(tmplist); 3431} 3432 3433 3434/* This only needs to be done once */ 3435static void **serialDefaultsList = NULL; 3436 3437/* 3438 * createSerialDefaultsLists() - create a list of the different default 3439 * settings for the serial interface of the known protocols. 3440 */ 3441static void 3442createSerialDefaultsList(void) 3443{ 3444 int i = 0, j, k; 3445 3446 serialDefaultsList = (void **)xnfalloc(sizeof(void*)); 3447 serialDefaultsList[0] = NULL; 3448 3449 for (j = 0; mouseProtocols[j].name; j++) { 3450 if (!mouseProtocols[j].defaults) 3451 continue; 3452 for (k = 0; k < i; k++) 3453 if (mouseProtocols[j].defaults == serialDefaultsList[k]) 3454 continue; 3455 i++; 3456 serialDefaultsList = (void**)xnfrealloc(serialDefaultsList, 3457 sizeof(void*)*(i+1)); 3458 serialDefaultsList[i-1] = mouseProtocols[j].defaults; 3459 serialDefaultsList[i] = NULL; 3460 } 3461} 3462 3463typedef enum { 3464 STATE_INVALID, 3465 STATE_UNCERTAIN, 3466 STATE_VALID 3467} validState; 3468 3469/* Probing threshold values */ 3470#define PROBE_UNCERTAINTY 50 3471#define BAD_CERTAINTY 6 3472#define BAD_INC_CERTAINTY 1 3473#define BAD_INC_CERTAINTY_WHEN_SYNC_LOST 2 3474 3475static validState 3476validCount(mousePrivPtr mPriv, Bool inSync, Bool lostSync) 3477{ 3478 if (inSync) { 3479 if (!--mPriv->goodCount) { 3480 /* we are sure to have found the correct protocol */ 3481 mPriv->badCount = 0; 3482 return STATE_VALID; 3483 } 3484 AP_DBG(("%i successful rounds to go\n", 3485 mPriv->goodCount)); 3486 return STATE_UNCERTAIN; 3487 } 3488 3489 3490 /* We are out of sync again */ 3491 mPriv->goodCount = PROBE_UNCERTAINTY; 3492 /* We increase uncertainty of having the correct protocol */ 3493 mPriv->badCount+= lostSync ? BAD_INC_CERTAINTY_WHEN_SYNC_LOST 3494 : BAD_INC_CERTAINTY; 3495 3496 if (mPriv->badCount < BAD_CERTAINTY) { 3497 /* We are not convinced yet to have the wrong protocol */ 3498 AP_DBG(("Changing protocol after: %i rounds\n", 3499 BAD_CERTAINTY - mPriv->badCount)); 3500 return STATE_UNCERTAIN; 3501 } 3502 return STATE_INVALID; 3503} 3504 3505#define RESET_VALIDATION mPriv->goodCount = PROBE_UNCERTAINTY;\ 3506 mPriv->badCount = 0;\ 3507 mPriv->prevDx = 0;\ 3508 mPriv->prevDy = 0;\ 3509 mPriv->accDx = 0;\ 3510 mPriv->accDy = 0;\ 3511 mPriv->acc = 0; 3512 3513static void 3514autoProbeMouse(InputInfoPtr pInfo, Bool inSync, Bool lostSync) 3515{ 3516 MouseDevPtr pMse = pInfo->private; 3517 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3518 3519 MouseProtocolID *protocolList = NULL; 3520 3521 while (1) { 3522 switch (mPriv->autoState) { 3523 case AUTOPROBE_GOOD: 3524 if (inSync) 3525 return; 3526 AP_DBG(("State GOOD\n")); 3527 RESET_VALIDATION; 3528 mPriv->autoState = AUTOPROBE_VALIDATE1; 3529 return; 3530 case AUTOPROBE_H_GOOD: 3531 if (inSync) 3532 return; 3533 AP_DBG(("State H_GOOD\n")); 3534 RESET_VALIDATION; 3535 mPriv->autoState = AUTOPROBE_H_VALIDATE2; 3536 return; 3537 case AUTOPROBE_H_NOPROTO: 3538 AP_DBG(("State H_NOPROTO\n")); 3539 mPriv->protocolID = 0; 3540 mPriv->autoState = AUTOPROBE_H_SETPROTO; 3541 break; 3542 case AUTOPROBE_H_SETPROTO: 3543 AP_DBG(("State H_SETPROTO\n")); 3544 if ((pMse->protocolID = hardProtocolList[mPriv->protocolID++]) 3545 == PROT_UNKNOWN) { 3546 mPriv->protocolID = 0; 3547 break; 3548 } else if (GetProtocol(pMse->protocolID) && SetupMouse(pInfo)) { 3549 FlushButtons(pMse); 3550 RESET_VALIDATION; 3551 AP_DBG(("Autoprobe: Trying Protocol: %s\n", 3552 ProtocolIDToName(pMse->protocolID))); 3553 mPriv->autoState = AUTOPROBE_H_VALIDATE1; 3554 return; 3555 } 3556 break; 3557 case AUTOPROBE_H_VALIDATE1: 3558 AP_DBG(("State H_VALIDATE1\n")); 3559 switch (validCount(mPriv,inSync,lostSync)) { 3560 case STATE_INVALID: 3561 mPriv->autoState = AUTOPROBE_H_SETPROTO; 3562 break; 3563 case STATE_VALID: 3564 xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 3565 ProtocolIDToName(pMse->protocolID)); 3566 mPriv->autoState = AUTOPROBE_H_GOOD; 3567 return; 3568 case STATE_UNCERTAIN: 3569 return; 3570 default: 3571 break; 3572 } 3573 break; 3574 case AUTOPROBE_H_VALIDATE2: 3575 AP_DBG(("State H_VALIDATE2\n")); 3576 switch (validCount(mPriv,inSync,lostSync)) { 3577 case STATE_INVALID: 3578 mPriv->autoState = AUTOPROBE_H_AUTODETECT; 3579 break; 3580 case STATE_VALID: 3581 xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 3582 ProtocolIDToName(pMse->protocolID)); 3583 mPriv->autoState = AUTOPROBE_H_GOOD; 3584 return; 3585 case STATE_UNCERTAIN: 3586 return; 3587 } 3588 break; 3589 case AUTOPROBE_H_AUTODETECT: 3590 AP_DBG(("State H_AUTODETECT\n")); 3591 pMse->protocolID = PROT_AUTO; 3592 AP_DBG(("Looking for PnP/OS mouse\n")); 3593 mPriv->count = 0; 3594 SetupMouse(pInfo); 3595 if (pMse->protocolID != PROT_AUTO) 3596 mPriv->autoState = AUTOPROBE_H_GOOD; 3597 else 3598 mPriv->autoState = AUTOPROBE_H_NOPROTO; 3599 break; 3600 case AUTOPROBE_NOPROTO: 3601 AP_DBG(("State NOPROTO\n")); 3602 mPriv->count = 0; 3603 mPriv->serialDefaultsNum = -1; 3604 mPriv->autoState = AUTOPROBE_COLLECT; 3605 break; 3606 case AUTOPROBE_COLLECT: 3607 AP_DBG(("State COLLECT\n")); 3608 if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES) 3609 return; 3610 protocolList = softProtocolList; 3611 mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST; 3612 break; 3613 case AUTOPROBE_CREATE_PROTOLIST: 3614 AP_DBG(("State CREATE_PROTOLIST\n")); 3615 createProtoList(pMse, protocolList); 3616 mPriv->protocolID = 0; 3617 mPriv->autoState = AUTOPROBE_SWITCH_PROTOCOL; 3618 break; 3619 case AUTOPROBE_AUTODETECT: 3620 AP_DBG(("State AUTODETECT\n")); 3621 pMse->protocolID = PROT_AUTO; 3622 AP_DBG(("Looking for PnP/OS mouse\n")); 3623 mPriv->count = 0; 3624 SetupMouse(pInfo); 3625 if (pMse->protocolID != PROT_AUTO) 3626 mPriv->autoState = AUTOPROBE_GOOD; 3627 else 3628 mPriv->autoState = AUTOPROBE_NOPROTO; 3629 break; 3630 case AUTOPROBE_VALIDATE1: 3631 AP_DBG(("State VALIDATE1\n")); 3632 switch (validCount(mPriv,inSync,lostSync)) { 3633 case STATE_INVALID: 3634 mPriv->autoState = AUTOPROBE_AUTODETECT; 3635 break; 3636 case STATE_VALID: 3637 xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 3638 ProtocolIDToName(pMse->protocolID)); 3639 mPriv->autoState = AUTOPROBE_GOOD; 3640 break; 3641 case STATE_UNCERTAIN: 3642 return; 3643 } 3644 break; 3645 case AUTOPROBE_VALIDATE2: 3646 AP_DBG(("State VALIDATE2\n")); 3647 switch (validCount(mPriv,inSync,lostSync)) { 3648 case STATE_INVALID: 3649 protocolList = &mPriv->protoList[mPriv->protocolID]; 3650 mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST; 3651 break; 3652 case STATE_VALID: 3653 xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 3654 ProtocolIDToName(pMse->protocolID)); 3655 mPriv->autoState = AUTOPROBE_GOOD; 3656 break; 3657 case STATE_UNCERTAIN: 3658 return; 3659 } 3660 break; 3661 case AUTOPROBE_SWITCHSERIAL: 3662 { 3663 pointer serialDefaults; 3664 AP_DBG(("State SWITCHSERIAL\n")); 3665 3666 if (!serialDefaultsList) 3667 createSerialDefaultsList(); 3668 3669 AP_DBG(("Switching serial params\n")); 3670 if ((serialDefaults = 3671 serialDefaultsList[++mPriv->serialDefaultsNum]) == NULL) { 3672 mPriv->serialDefaultsNum = 0; 3673 } else { 3674 pointer tmp = xf86OptionListCreate(serialDefaults, -1, 0); 3675 xf86SetSerial(pInfo->fd, tmp); 3676 xf86OptionListFree(tmp); 3677 mPriv->count = 0; 3678 mPriv->autoState = AUTOPROBE_COLLECT; 3679 } 3680 break; 3681 } 3682 case AUTOPROBE_SWITCH_PROTOCOL: 3683 { 3684 MouseProtocolID prot; 3685 MouseProtocolPtr pProto; 3686 void *defaults; 3687 AP_DBG(("State SWITCH_PROTOCOL\n")); 3688 prot = mPriv->protoList[mPriv->protocolID++]; 3689 if (prot == PROT_UNKNOWN) 3690 mPriv->autoState = AUTOPROBE_SWITCHSERIAL; 3691 else if (!((pProto = GetProtocol(prot)) && 3692 ((defaults = pProto->defaults))) 3693 || (mPriv->serialDefaultsNum == -1 3694 && (defaults == msDefaults)) 3695 || (mPriv->serialDefaultsNum != -1 3696 && serialDefaultsList[mPriv->serialDefaultsNum] 3697 == defaults)) { 3698 AP_DBG(("Changing Protocol to %s\n", 3699 ProtocolIDToName(prot))); 3700 SetMouseProto(pMse,prot); 3701 FlushButtons(pMse); 3702 RESET_VALIDATION; 3703 mPriv->autoState = AUTOPROBE_VALIDATE2; 3704 return; 3705 } 3706 break; 3707 } 3708 } 3709 } 3710} 3711 3712static Bool 3713autoGood(MouseDevPtr pMse) 3714{ 3715 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3716 3717 if (!pMse->autoProbe) 3718 return TRUE; 3719 3720 switch (mPriv->autoState) { 3721 case AUTOPROBE_GOOD: 3722 case AUTOPROBE_H_GOOD: 3723 return TRUE; 3724 case AUTOPROBE_VALIDATE1: /* @@@ */ 3725 case AUTOPROBE_H_VALIDATE1: /* @@@ */ 3726 case AUTOPROBE_VALIDATE2: 3727 case AUTOPROBE_H_VALIDATE2: 3728 if (mPriv->goodCount < PROBE_UNCERTAINTY/2) 3729 return TRUE; 3730 /* FALLTHROUGH */ 3731 default: 3732 return FALSE; 3733 } 3734} 3735 3736 3737#define TOT_THRESHOLD 3000 3738#define VAL_THRESHOLD 40 3739 3740/* 3741 * checkForErraticMovements() -- check if mouse 'jumps around'. 3742 */ 3743static void 3744checkForErraticMovements(InputInfoPtr pInfo, int dx, int dy) 3745{ 3746 MouseDevPtr pMse = pInfo->private; 3747 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3748 3749 if (!mPriv->goodCount) 3750 return; 3751 3752#if 0 3753 if (abs(dx - mPriv->prevDx) > 300 3754 || abs(dy - mPriv->prevDy) > 300) 3755 AP_DBG(("erratic1 behaviour\n")); 3756#endif 3757 if (abs(dx) > VAL_THRESHOLD) { 3758 if (sign(dx) == sign(mPriv->prevDx)) { 3759 mPriv->accDx += dx; 3760 if (abs(mPriv->accDx) > mPriv->acc) { 3761 mPriv->acc = abs(mPriv->accDx); 3762 AP_DBG(("acc=%i\n",mPriv->acc)); 3763 } 3764 else { 3765 AP_DBG(("accDx=%i\n",mPriv->accDx)); 3766 } 3767 } else { 3768 mPriv->accDx = 0; 3769 } 3770 } 3771 3772 if (abs(dy) > VAL_THRESHOLD) { 3773 if (sign(dy) == sign(mPriv->prevDy)) { 3774 mPriv->accDy += dy; 3775 if (abs(mPriv->accDy) > mPriv->acc) { 3776 mPriv->acc = abs(mPriv->accDy); 3777 AP_DBG(("acc: %i\n",mPriv->acc)); 3778 } else { 3779 AP_DBG(("accDy=%i\n",mPriv->accDy)); 3780 } 3781 } else { 3782 mPriv->accDy = 0; 3783 } 3784 } 3785 mPriv->prevDx = dx; 3786 mPriv->prevDy = dy; 3787 if (mPriv->acc > TOT_THRESHOLD) { 3788 mPriv->goodCount = PROBE_UNCERTAINTY; 3789 mPriv->prevDx = 0; 3790 mPriv->prevDy = 0; 3791 mPriv->accDx = 0; 3792 mPriv->accDy = 0; 3793 mPriv->acc = 0; 3794 AP_DBG(("erratic2 behaviour\n")); 3795 autoProbeMouse(pInfo, FALSE,TRUE); 3796 } 3797} 3798 3799static void 3800SetMouseProto(MouseDevPtr pMse, MouseProtocolID protocolID) 3801{ 3802 pMse->protocolID = protocolID; 3803 pMse->protocol = ProtocolIDToName(pMse->protocolID); 3804 pMse->class = ProtocolIDToClass(pMse->protocolID); 3805 if ((pMse->protocolID >= 0) && (pMse->protocolID < PROT_NUMPROTOS)) 3806 memcpy(pMse->protoPara, proto[pMse->protocolID], 3807 sizeof(pMse->protoPara)); 3808 3809 if (pMse->emulate3ButtonsSoft) 3810 pMse->emulate3Buttons = TRUE; 3811} 3812 3813/* 3814 * collectData() -- collect data bytes sent by mouse. 3815 */ 3816static Bool 3817collectData(MouseDevPtr pMse, unsigned char u) 3818{ 3819 mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3820 if (mPriv->count < NUM_MSE_AUTOPROBE_TOTAL) { 3821 mPriv->data[mPriv->count++] = u; 3822 if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES) { 3823 return TRUE; 3824 } 3825 } 3826 return FALSE; 3827} 3828 3829/**************** end of autoprobe stuff *****************/ 3830 3831 3832static void 3833xf86MouseUnplug(pointer p) 3834{ 3835} 3836static pointer 3837xf86MousePlug(pointer module, 3838 pointer options, 3839 int *errmaj, 3840 int *errmin) 3841{ 3842 static Bool Initialised = FALSE; 3843 3844 if (!Initialised) 3845 Initialised = TRUE; 3846 3847 xf86AddInputDriver(&MOUSE, module, 0); 3848 3849 return module; 3850} 3851 3852static XF86ModuleVersionInfo xf86MouseVersionRec = 3853{ 3854 "mouse", 3855 MODULEVENDORSTRING, 3856 MODINFOSTRING1, 3857 MODINFOSTRING2, 3858 XORG_VERSION_CURRENT, 3859 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 3860 ABI_CLASS_XINPUT, 3861 ABI_XINPUT_VERSION, 3862 MOD_CLASS_XINPUT, 3863 {0, 0, 0, 0} /* signature, to be patched into the file by */ 3864 /* a tool */ 3865}; 3866 3867_X_EXPORT XF86ModuleData mouseModuleData = { 3868 &xf86MouseVersionRec, 3869 xf86MousePlug, 3870 xf86MouseUnplug 3871}; 3872 3873/* 3874 Look at hitachi device stuff. 3875*/ 3876