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