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