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