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