(file) Return to mouse.c CVS log (file) (dir) Up to [XFree86 CVS] / xc / programs / Xserver / hw / xfree86 / input / mouse

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

Powered by
ViewCVS 0.9.2