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