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