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