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