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