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