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