mouse.c revision 5ddc3750
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	    if (!strcmp(pMse->protocol, "wsmouse")) {
1761	        int version = WSMOUSE_EVENT_VERSION;
1762	        if (ioctl(pInfo->fd, WSMOUSEIO_SETVERSION, &version) == -1)
1763	            xf86Msg(X_WARNING, "%s: cannot set version\n", pInfo->name);
1764            }
1765#endif
1766	    if (pMse->xisbscale)
1767		pMse->buffer = XisbNew(pInfo->fd, pMse->xisbscale * 4);
1768	    else
1769		pMse->buffer = XisbNew(pInfo->fd, 64);
1770	    if (!pMse->buffer) {
1771		xf86CloseSerial(pInfo->fd);
1772		pInfo->fd = -1;
1773	    } else {
1774		if (!SetupMouse(pInfo)) {
1775		    xf86CloseSerial(pInfo->fd);
1776		    pInfo->fd = -1;
1777		    XisbFree(pMse->buffer);
1778		    pMse->buffer = NULL;
1779		} else {
1780		    mPriv = (mousePrivPtr)pMse->mousePriv;
1781		    if (mPriv != NULL) {
1782			if ( pMse->protocolID != PROT_AUTO) {
1783			    pMse->inSync = TRUE; /* @@@ */
1784			    if (mPriv->soft)
1785				mPriv->autoState = AUTOPROBE_GOOD;
1786			    else
1787				mPriv->autoState = AUTOPROBE_H_GOOD;
1788			} else {
1789			    if (mPriv->soft)
1790				mPriv->autoState = AUTOPROBE_NOPROTO;
1791			    else
1792				mPriv->autoState = AUTOPROBE_H_NOPROTO;
1793			}
1794		    }
1795		    xf86FlushInput(pInfo->fd);
1796		    xf86AddEnabledDevice(pInfo);
1797		}
1798	    }
1799	}
1800	pMse->lastButtons = 0;
1801	pMse->lastMappedButtons = 0;
1802	pMse->emulateState = 0;
1803	pMse->emulate3Pending = FALSE;
1804	pMse->wheelButtonExpires = GetTimeInMillis ();
1805	device->public.on = TRUE;
1806	FlushButtons(pMse);
1807	if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft)
1808	{
1809	    RegisterBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
1810					    (pointer) pInfo);
1811	}
1812	break;
1813
1814    case DEVICE_OFF:
1815    case DEVICE_CLOSE:
1816	if (pInfo->fd != -1) {
1817	    xf86RemoveEnabledDevice(pInfo);
1818	    if (pMse->buffer) {
1819		XisbFree(pMse->buffer);
1820		pMse->buffer = NULL;
1821	    }
1822	    xf86CloseSerial(pInfo->fd);
1823	    pInfo->fd = -1;
1824	    if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft)
1825	    {
1826		RemoveBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
1827					      (pointer) pInfo);
1828	    }
1829	}
1830	device->public.on = FALSE;
1831	break;
1832    }
1833    return Success;
1834}
1835
1836/*
1837 ***************************************************************************
1838 *
1839 * MouseConvert --
1840 *	Convert valuators to X and Y.
1841 *
1842 ***************************************************************************
1843 */
1844static Bool
1845MouseConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
1846	     int v3, int v4, int v5, int *x, int *y)
1847{
1848    if (first != 0 || num != 2)
1849	return FALSE;
1850
1851    *x = v0;
1852    *y = v1;
1853
1854    return TRUE;
1855}
1856
1857/**********************************************************************
1858 *
1859 * FlushButtons -- reset button states.
1860 *
1861 **********************************************************************/
1862
1863static void
1864FlushButtons(MouseDevPtr pMse)
1865{
1866    pMse->lastButtons = 0;
1867    pMse->lastMappedButtons = 0;
1868}
1869
1870/**********************************************************************
1871 *
1872 *  Emulate3Button support code
1873 *
1874 **********************************************************************/
1875
1876
1877/*
1878 * Lets create a simple finite-state machine for 3 button emulation:
1879 *
1880 * We track buttons 1 and 3 (left and right).  There are 11 states:
1881 *   0 ground           - initial state
1882 *   1 delayed left     - left pressed, waiting for right
1883 *   2 delayed right    - right pressed, waiting for left
1884 *   3 pressed middle   - right and left pressed, emulated middle sent
1885 *   4 pressed left     - left pressed and sent
1886 *   5 pressed right    - right pressed and sent
1887 *   6 released left    - left released after emulated middle
1888 *   7 released right   - right released after emulated middle
1889 *   8 repressed left   - left pressed after released left
1890 *   9 repressed right  - right pressed after released right
1891 *  10 pressed both     - both pressed, not emulating middle
1892 *
1893 * At each state, we need handlers for the following events
1894 *   0: no buttons down
1895 *   1: left button down
1896 *   2: right button down
1897 *   3: both buttons down
1898 *   4: emulate3Timeout passed without a button change
1899 * Note that button events are not deltas, they are the set of buttons being
1900 * pressed now.  It's possible (ie, mouse hardware does it) to go from (eg)
1901 * left down to right down without anything in between, so all cases must be
1902 * handled.
1903 *
1904 * a handler consists of three values:
1905 *   0: action1
1906 *   1: action2
1907 *   2: new emulation state
1908 *
1909 * action > 0: ButtonPress
1910 * action = 0: nothing
1911 * action < 0: ButtonRelease
1912 *
1913 * The comment preceeding each section is the current emulation state.
1914 * The comments to the right are of the form
1915 *      <button state> (<events>) -> <new emulation state>
1916 * which should be read as
1917 *      If the buttons are in <button state>, generate <events> then go to
1918 *      <new emulation state>.
1919 */
1920static signed char stateTab[11][5][3] = {
1921/* 0 ground */
1922  {
1923    {  0,  0,  0 },   /* nothing -> ground (no change) */
1924    {  0,  0,  1 },   /* left -> delayed left */
1925    {  0,  0,  2 },   /* right -> delayed right */
1926    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
1927    {  0,  0, -1 }    /* timeout N/A */
1928  },
1929/* 1 delayed left */
1930  {
1931    {  1, -1,  0 },   /* nothing (left event) -> ground */
1932    {  0,  0,  1 },   /* left -> delayed left (no change) */
1933    {  1, -1,  2 },   /* right (left event) -> delayed right */
1934    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
1935    {  1,  0,  4 },   /* timeout (left press) -> pressed left */
1936  },
1937/* 2 delayed right */
1938  {
1939    {  3, -3,  0 },   /* nothing (right event) -> ground */
1940    {  3, -3,  1 },   /* left (right event) -> delayed left (no change) */
1941    {  0,  0,  2 },   /* right -> delayed right (no change) */
1942    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
1943    {  3,  0,  5 },   /* timeout (right press) -> pressed right */
1944  },
1945/* 3 pressed middle */
1946  {
1947    { -2,  0,  0 },   /* nothing (middle release) -> ground */
1948    {  0,  0,  7 },   /* left -> released right */
1949    {  0,  0,  6 },   /* right -> released left */
1950    {  0,  0,  3 },   /* left & right -> pressed middle (no change) */
1951    {  0,  0, -1 },   /* timeout N/A */
1952  },
1953/* 4 pressed left */
1954  {
1955    { -1,  0,  0 },   /* nothing (left release) -> ground */
1956    {  0,  0,  4 },   /* left -> pressed left (no change) */
1957    { -1,  0,  2 },   /* right (left release) -> delayed right */
1958    {  3,  0, 10 },   /* left & right (right press) -> pressed both */
1959    {  0,  0, -1 },   /* timeout N/A */
1960  },
1961/* 5 pressed right */
1962  {
1963    { -3,  0,  0 },   /* nothing (right release) -> ground */
1964    { -3,  0,  1 },   /* left (right release) -> delayed left */
1965    {  0,  0,  5 },   /* right -> pressed right (no change) */
1966    {  1,  0, 10 },   /* left & right (left press) -> pressed both */
1967    {  0,  0, -1 },   /* timeout N/A */
1968  },
1969/* 6 released left */
1970  {
1971    { -2,  0,  0 },   /* nothing (middle release) -> ground */
1972    { -2,  0,  1 },   /* left (middle release) -> delayed left */
1973    {  0,  0,  6 },   /* right -> released left (no change) */
1974    {  1,  0,  8 },   /* left & right (left press) -> repressed left */
1975    {  0,  0, -1 },   /* timeout N/A */
1976  },
1977/* 7 released right */
1978  {
1979    { -2,  0,  0 },   /* nothing (middle release) -> ground */
1980    {  0,  0,  7 },   /* left -> released right (no change) */
1981    { -2,  0,  2 },   /* right (middle release) -> delayed right */
1982    {  3,  0,  9 },   /* left & right (right press) -> repressed right */
1983    {  0,  0, -1 },   /* timeout N/A */
1984  },
1985/* 8 repressed left */
1986  {
1987    { -2, -1,  0 },   /* nothing (middle release, left release) -> ground */
1988    { -2,  0,  4 },   /* left (middle release) -> pressed left */
1989    { -1,  0,  6 },   /* right (left release) -> released left */
1990    {  0,  0,  8 },   /* left & right -> repressed left (no change) */
1991    {  0,  0, -1 },   /* timeout N/A */
1992  },
1993/* 9 repressed right */
1994  {
1995    { -2, -3,  0 },   /* nothing (middle release, right release) -> ground */
1996    { -3,  0,  7 },   /* left (right release) -> released right */
1997    { -2,  0,  5 },   /* right (middle release) -> pressed right */
1998    {  0,  0,  9 },   /* left & right -> repressed right (no change) */
1999    {  0,  0, -1 },   /* timeout N/A */
2000  },
2001/* 10 pressed both */
2002  {
2003    { -1, -3,  0 },   /* nothing (left release, right release) -> ground */
2004    { -3,  0,  4 },   /* left (right release) -> pressed left */
2005    { -1,  0,  5 },   /* right (left release) -> pressed right */
2006    {  0,  0, 10 },   /* left & right -> pressed both (no change) */
2007    {  0,  0, -1 },   /* timeout N/A */
2008  },
2009};
2010
2011/*
2012 * Table to allow quick reversal of natural button mapping to correct mapping
2013 */
2014
2015/*
2016 * [JCH-96/01/21] The ALPS GlidePoint pad extends the MS protocol
2017 * with a fourth button activated by tapping the PAD.
2018 * The 2nd line corresponds to 4th button on; the drv sends
2019 * the buttons in the following map (MSBit described first) :
2020 * 0 | 4th | 1st | 2nd | 3rd
2021 * And we remap them (MSBit described first) :
2022 * 0 | 4th | 3rd | 2nd | 1st
2023 */
2024static char reverseMap[16] = { 0,  4,  2,  6,
2025			       1,  5,  3,  7,
2026			       8, 12, 10, 14,
2027			       9, 13, 11, 15 };
2028
2029static char hitachMap[16] = {  0,  2,  1,  3,
2030			       8, 10,  9, 11,
2031			       4,  6,  5,  7,
2032			      12, 14, 13, 15 };
2033
2034#define reverseBits(map, b)	(((b) & ~0x0f) | map[(b) & 0x0f])
2035
2036static CARD32
2037buttonTimer(InputInfoPtr pInfo)
2038{
2039    MouseDevPtr pMse;
2040    int	sigstate;
2041    int id;
2042
2043    pMse = pInfo->private;
2044
2045    sigstate = xf86BlockSIGIO ();
2046
2047    pMse->emulate3Pending = FALSE;
2048    if ((id = stateTab[pMse->emulateState][4][0]) != 0) {
2049        xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
2050        pMse->emulateState = stateTab[pMse->emulateState][4][2];
2051    } else {
2052        ErrorF("Got unexpected buttonTimer in state %d\n", pMse->emulateState);
2053    }
2054
2055    xf86UnblockSIGIO (sigstate);
2056    return 0;
2057}
2058
2059static Bool
2060Emulate3ButtonsSoft(InputInfoPtr pInfo)
2061{
2062    MouseDevPtr pMse = pInfo->private;
2063
2064    if (!pMse->emulate3ButtonsSoft)
2065	return TRUE;
2066
2067    pMse->emulate3Buttons = FALSE;
2068
2069    if (pMse->emulate3Pending)
2070	buttonTimer(pInfo);
2071
2072    xf86Msg(X_INFO,"3rd Button detected: disabling emulate3Button\n");
2073
2074    return FALSE;
2075}
2076
2077static void MouseBlockHandler(pointer data,
2078			      struct timeval **waitTime,
2079			      pointer LastSelectMask)
2080{
2081    InputInfoPtr    pInfo = (InputInfoPtr) data;
2082    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
2083    int		    ms;
2084
2085    if (pMse->emulate3Pending)
2086    {
2087	ms = pMse->emulate3Expires - GetTimeInMillis ();
2088	if (ms <= 0)
2089	    ms = 0;
2090	AdjustWaitForDelay (waitTime, ms);
2091    }
2092}
2093
2094static void MouseWakeupHandler(pointer data,
2095			       int i,
2096			       pointer LastSelectMask)
2097{
2098    InputInfoPtr    pInfo = (InputInfoPtr) data;
2099    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
2100    int		    ms;
2101
2102    if (pMse->emulate3Pending)
2103    {
2104	ms = pMse->emulate3Expires - GetTimeInMillis ();
2105	if (ms <= 0)
2106	    buttonTimer (pInfo);
2107    }
2108}
2109
2110/*******************************************************************
2111 *
2112 * Post mouse events
2113 *
2114 *******************************************************************/
2115
2116static void
2117MouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy)
2118{
2119    MouseDevPtr pMse;
2120    int emulateButtons;
2121    int id, change;
2122    int emuWheelDelta, emuWheelButton, emuWheelButtonMask;
2123    int wheelButtonMask;
2124    int ms;
2125
2126    pMse = pInfo->private;
2127
2128    change = buttons ^ pMse->lastMappedButtons;
2129    pMse->lastMappedButtons = buttons;
2130
2131    /* Do single button double click */
2132    if (pMse->doubleClickSourceButtonMask) {
2133        if (buttons & pMse->doubleClickSourceButtonMask) {
2134            if (!(pMse->doubleClickOldSourceState)) {
2135                /* double-click button has just been pressed. Ignore it if target button
2136                 * is already down.
2137                 */
2138                if (!(buttons & pMse->doubleClickTargetButtonMask)) {
2139                    /* Target button isn't down, so send a double-click */
2140                    xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 1, 0, 0);
2141                    xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 0, 0, 0);
2142                    xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 1, 0, 0);
2143                    xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 0, 0, 0);
2144                }
2145            }
2146            pMse->doubleClickOldSourceState = 1;
2147        }
2148        else
2149            pMse->doubleClickOldSourceState = 0;
2150
2151        /* Whatever happened, mask the double-click button so it doesn't get
2152         * processed as a normal button as well.
2153         */
2154        buttons &= ~(pMse->doubleClickSourceButtonMask);
2155        change  &= ~(pMse->doubleClickSourceButtonMask);
2156    }
2157
2158    if (pMse->emulateWheel) {
2159	/* Emulate wheel button handling */
2160	wheelButtonMask = 1 << (pMse->wheelButton - 1);
2161
2162	if (change & wheelButtonMask) {
2163	    if (buttons & wheelButtonMask) {
2164		/* Start timeout handling */
2165		pMse->wheelButtonExpires = GetTimeInMillis () + pMse->wheelButtonTimeout;
2166		ms = - pMse->wheelButtonTimeout;
2167	    } else {
2168		ms = pMse->wheelButtonExpires - GetTimeInMillis ();
2169
2170		if (0 < ms) {
2171		    /*
2172		     * If the button is released early enough emit the button
2173		     * press/release events
2174		     */
2175		    xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 1, 0, 0);
2176		    xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 0, 0, 0);
2177		}
2178	    }
2179	} else
2180	    ms = pMse->wheelButtonExpires - GetTimeInMillis ();
2181
2182	/* Intercept wheel emulation. */
2183	if (buttons & wheelButtonMask) {
2184	    if (ms <= 0) {
2185		/* Y axis movement */
2186		if (pMse->negativeY != MSE_NOAXISMAP) {
2187		    pMse->wheelYDistance += dy;
2188		    if (pMse->wheelYDistance < 0) {
2189			emuWheelDelta = -pMse->wheelInertia;
2190			emuWheelButton = pMse->negativeY;
2191		    } else {
2192			emuWheelDelta = pMse->wheelInertia;
2193			emuWheelButton = pMse->positiveY;
2194		    }
2195		    emuWheelButtonMask = 1 << (emuWheelButton - 1);
2196		    while (abs(pMse->wheelYDistance) > pMse->wheelInertia) {
2197			pMse->wheelYDistance -= emuWheelDelta;
2198
2199			/*
2200			 * Synthesize the press and release, but not when
2201			 * the button to be synthesized is already pressed
2202			 * "for real".
2203			 */
2204			if (!(emuWheelButtonMask & buttons) ||
2205			    (emuWheelButtonMask & wheelButtonMask)) {
2206			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
2207			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
2208			}
2209		    }
2210		}
2211
2212		/* X axis movement */
2213		if (pMse->negativeX != MSE_NOAXISMAP) {
2214		    pMse->wheelXDistance += dx;
2215		    if (pMse->wheelXDistance < 0) {
2216			emuWheelDelta = -pMse->wheelInertia;
2217			emuWheelButton = pMse->negativeX;
2218		    } else {
2219			emuWheelDelta = pMse->wheelInertia;
2220			emuWheelButton = pMse->positiveX;
2221		    }
2222		    emuWheelButtonMask = 1 << (emuWheelButton - 1);
2223		    while (abs(pMse->wheelXDistance) > pMse->wheelInertia) {
2224			pMse->wheelXDistance -= emuWheelDelta;
2225
2226			/*
2227			 * Synthesize the press and release, but not when
2228			 * the button to be synthesized is already pressed
2229			 * "for real".
2230			 */
2231			if (!(emuWheelButtonMask & buttons) ||
2232			    (emuWheelButtonMask & wheelButtonMask)) {
2233			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
2234			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
2235			}
2236		    }
2237		}
2238	    }
2239
2240	    /* Absorb the mouse movement while the wheel button is pressed. */
2241	    dx = 0;
2242	    dy = 0;
2243	}
2244	/*
2245	 * Button events for the wheel button are only emitted through
2246	 * the timeout code.
2247	 */
2248	buttons &= ~wheelButtonMask;
2249	change  &= ~wheelButtonMask;
2250    }
2251
2252    if (pMse->emulate3ButtonsSoft && pMse->emulate3Pending && (dx || dy))
2253	buttonTimer(pInfo);
2254
2255    if (dx || dy)
2256	xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
2257
2258    if (change) {
2259
2260	/*
2261	 * adjust buttons state for drag locks!
2262	 * if there is drag locks
2263	 */
2264        if (pMse->pDragLock) {
2265	    DragLockPtr   pLock;
2266	    int tarOfGoingDown, tarOfDown;
2267	    int realbuttons;
2268
2269	    /* get drag lock block */
2270	    pLock = pMse->pDragLock;
2271	    /* save real buttons */
2272	    realbuttons = buttons;
2273
2274	    /* if drag lock used */
2275
2276	    /* state of drag lock buttons not seen always up */
2277
2278	    buttons &= ~pLock->lockButtonsM;
2279
2280	    /*
2281	     * if lock buttons being depressed changes state of
2282	     * targets simulatedDown.
2283	     */
2284	    tarOfGoingDown = lock2targetMap(pLock,
2285				realbuttons & change & pLock->lockButtonsM);
2286	    pLock->simulatedDown ^= tarOfGoingDown;
2287
2288	    /* targets of drag locks down */
2289	    tarOfDown = lock2targetMap(pLock,
2290				realbuttons & pLock->lockButtonsM);
2291
2292	    /*
2293	     * when simulatedDown set and target pressed,
2294	     * simulatedDown goes false
2295	     */
2296	    pLock->simulatedDown &= ~(realbuttons & change);
2297
2298	    /*
2299	     * if master drag lock released
2300	     * then master drag lock state on
2301	     */
2302	    pLock->masterTS |= (~realbuttons & change) & pLock->masterLockM;
2303
2304	    /* if master state, buttons going down are simulatedDown */
2305	    if (pLock->masterTS)
2306		pLock->simulatedDown |= (realbuttons & change);
2307
2308	    /* if any button pressed, no longer in master drag lock state */
2309	    if (realbuttons & change)
2310		pLock->masterTS = 0;
2311
2312	    /* if simulatedDown or drag lock down, simulate down */
2313	    buttons |= (pLock->simulatedDown | tarOfDown);
2314
2315	    /* master button not seen */
2316	    buttons &= ~(pLock->masterLockM);
2317
2318	    /* buttons changed since last time */
2319	    change = buttons ^ pLock->lockLastButtons;
2320
2321	    /* save this time for next last time. */
2322	    pLock->lockLastButtons = buttons;
2323	}
2324
2325        if (pMse->emulate3Buttons
2326	    && (!(buttons & 0x02) || Emulate3ButtonsSoft(pInfo))) {
2327
2328            /* handle all but buttons 1 & 3 normally */
2329
2330            change &= ~05;
2331
2332            /* emulate the third button by the other two */
2333
2334            emulateButtons = (buttons & 01) | ((buttons &04) >> 1);
2335
2336            if ((id = stateTab[pMse->emulateState][emulateButtons][0]) != 0)
2337                xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
2338            if ((id = stateTab[pMse->emulateState][emulateButtons][1]) != 0)
2339                xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
2340
2341            pMse->emulateState =
2342                stateTab[pMse->emulateState][emulateButtons][2];
2343
2344            if (stateTab[pMse->emulateState][4][0] != 0) {
2345		pMse->emulate3Expires = GetTimeInMillis () + pMse->emulate3Timeout;
2346		pMse->emulate3Pending = TRUE;
2347            } else {
2348		pMse->emulate3Pending = FALSE;
2349            }
2350        }
2351
2352	while (change) {
2353	    id = ffs(change);
2354	    change &= ~(1 << (id - 1));
2355	    xf86PostButtonEvent(pInfo->dev, 0, id,
2356				(buttons & (1 << (id - 1))), 0, 0);
2357	}
2358
2359    }
2360}
2361
2362static void
2363MousePostEvent(InputInfoPtr pInfo, int truebuttons,
2364	       int dx, int dy, int dz, int dw)
2365{
2366    MouseDevPtr pMse;
2367    mousePrivPtr mousepriv;
2368    int zbutton = 0, wbutton = 0, zbuttoncount = 0, wbuttoncount = 0;
2369    int i, b, buttons = 0;
2370
2371    pMse = pInfo->private;
2372    mousepriv = (mousePrivPtr)pMse->mousePriv;
2373
2374    if (pMse->protocolID == PROT_MMHIT)
2375	b = reverseBits(hitachMap, truebuttons);
2376    else
2377	b = reverseBits(reverseMap, truebuttons);
2378
2379    /* Remap mouse buttons */
2380    b &= (1<<MSE_MAXBUTTONS)-1;
2381    for (i = 0; b; i++) {
2382       if (b & 1)
2383	   buttons |= pMse->buttonMap[i];
2384       b >>= 1;
2385    }
2386
2387    /* Map the Z axis movement. */
2388    /* XXX Could this go in the conversion_proc? */
2389    switch (pMse->negativeZ) {
2390    case MSE_NOZMAP:	/* do nothing */
2391	dz = 0;
2392	break;
2393    case MSE_MAPTOX:
2394	if (dz != 0) {
2395	    dx = dz;
2396	    dz = 0;
2397	}
2398	break;
2399    case MSE_MAPTOY:
2400	if (dz != 0) {
2401	    dy = dz;
2402	    dz = 0;
2403	}
2404	break;
2405    default:	/* buttons */
2406	buttons &= ~(pMse->negativeZ | pMse->positiveZ);
2407	if (dz < 0) {
2408	    zbutton = pMse->negativeZ;
2409	    zbuttoncount = -dz;
2410	} else if (dz > 0) {
2411	    zbutton = pMse->positiveZ;
2412	    zbuttoncount = dz;
2413	}
2414	dz = 0;
2415	break;
2416    }
2417    switch (pMse->negativeW) {
2418    case MSE_NOZMAP:	/* do nothing */
2419	dw = 0;
2420	break;
2421    case MSE_MAPTOX:
2422	if (dw != 0) {
2423	    dx = dw;
2424	    dw = 0;
2425	}
2426	break;
2427    case MSE_MAPTOY:
2428	if (dw != 0) {
2429	    dy = dw;
2430	    dw = 0;
2431	}
2432	break;
2433    default:	/* buttons */
2434	buttons &= ~(pMse->negativeW | pMse->positiveW);
2435	if (dw < 0) {
2436	    wbutton = pMse->negativeW;
2437	    wbuttoncount = -dw;
2438	} else if (dw > 0) {
2439	    wbutton = pMse->positiveW;
2440	    wbuttoncount = dw;
2441	}
2442	dw = 0;
2443	break;
2444    }
2445
2446
2447    /* Apply angle offset */
2448    if (pMse->angleOffset != 0) {
2449	double rad = 3.141592653 * pMse->angleOffset / 180.0;
2450	int ndx = dx;
2451	dx = (int)((dx * cos(rad)) + (dy * sin(rad)) + 0.5);
2452	dy = (int)((dy * cos(rad)) - (ndx * sin(rad)) + 0.5);
2453    }
2454
2455    dx = pMse->invX * dx;
2456    dy = pMse->invY * dy;
2457    if (pMse->flipXY) {
2458	int tmp = dx;
2459	dx = dy;
2460	dy = tmp;
2461    }
2462
2463    /* Accumulate the scaled dx, dy in the private variables
2464       fracdx,fracdy and return the integer number part */
2465    if (mousepriv) {
2466	mousepriv->fracdx += mousepriv->sensitivity*dx;
2467	mousepriv->fracdy += mousepriv->sensitivity*dy;
2468	mousepriv->fracdx -= ( dx=(int)(mousepriv->fracdx) );
2469	mousepriv->fracdy -= ( dy=(int)(mousepriv->fracdy) );
2470    }
2471
2472    /* If mouse wheel movement has to be mapped on a button, we need to
2473     * loop for button press and release events. */
2474    do {
2475        MouseDoPostEvent(pInfo, buttons | zbutton | wbutton, dx, dy);
2476	dx = dy = 0;
2477	if (zbutton || wbutton)
2478	    MouseDoPostEvent(pInfo, buttons, 0, 0);
2479	if (--zbuttoncount <= 0)
2480	    zbutton = 0;
2481	if (--wbuttoncount <= 0)
2482	    wbutton = 0;
2483    } while (zbutton || wbutton);
2484
2485    pMse->lastButtons = truebuttons;
2486}
2487/******************************************************************
2488 *
2489 * Mouse Setup Code
2490 *
2491 ******************************************************************/
2492/*
2493 * This array is indexed by the MouseProtocolID values, so the order of the
2494 * entries must match that of the MouseProtocolID enum in xf86OSmouse.h.
2495 */
2496static unsigned char proto[PROT_NUMPROTOS][8] = {
2497  /* --header--  ---data--- packet -4th-byte-  mouse   */
2498  /* mask   id   mask   id  bytes  mask   id   flags   */
2499							    /* Serial mice */
2500  {  0x40, 0x40, 0x40, 0x00,  3,  ~0x23, 0x00, MPF_NONE },  /* MicroSoft */
2501  {  0xf8, 0x80, 0x00, 0x00,  5,   0x00, 0xff, MPF_SAFE },  /* MouseSystems */
2502  {  0xe0, 0x80, 0x80, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* MMSeries */
2503  {  0xe0, 0x80, 0x80, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* Logitech */
2504  {  0x40, 0x40, 0x40, 0x00,  3,  ~0x23, 0x00, MPF_NONE },  /* MouseMan */
2505  {  0xe0, 0x80, 0x80, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* MM_HitTablet */
2506  {  0x40, 0x40, 0x40, 0x00,  3,  ~0x33, 0x00, MPF_NONE },  /* GlidePoint */
2507  {  0x40, 0x40, 0x40, 0x00,  3,  ~0x3f, 0x00, MPF_NONE },  /* IntelliMouse */
2508  {  0x40, 0x40, 0x40, 0x00,  3,  ~0x33, 0x00, MPF_NONE },  /* ThinkingMouse */
2509  {  0x80, 0x80, 0x80, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* ACECAD */
2510  {  0x40, 0x40, 0x40, 0x00,  4,   0x00, 0xff, MPF_NONE },  /* ValuMouseScroll */
2511							    /* PS/2 variants */
2512  {  0xc0, 0x00, 0x00, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* PS/2 mouse */
2513  {  0xc8, 0x08, 0x00, 0x00,  3,   0x00, 0x00, MPF_NONE },  /* genericPS/2 mouse*/
2514  {  0x08, 0x08, 0x00, 0x00,  4,   0x00, 0xff, MPF_NONE },  /* IntelliMouse */
2515  {  0x08, 0x08, 0x00, 0x00,  4,   0x00, 0xff, MPF_NONE },  /* Explorer */
2516  {  0x80, 0x80, 0x00, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* ThinkingMouse */
2517  {  0x08, 0x08, 0x00, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* MouseMan+ */
2518  {  0xc0, 0x00, 0x00, 0x00,  3,   0x00, 0xff, MPF_NONE },  /* GlidePoint */
2519  {  0x08, 0x08, 0x00, 0x00,  4,   0x00, 0xff, MPF_NONE },  /* NetMouse */
2520  {  0xc0, 0x00, 0x00, 0x00,  6,   0x00, 0xff, MPF_NONE },  /* NetScroll */
2521							    /* Bus Mouse */
2522  {  0xf8, 0x80, 0x00, 0x00,  5,   0x00, 0xff, MPF_NONE },  /* BusMouse */
2523  {  0xf8, 0x80, 0x00, 0x00,  5,   0x00, 0xff, MPF_NONE },  /* Auto (dummy) */
2524  {  0xf8, 0x80, 0x00, 0x00,  8,   0x00, 0xff, MPF_NONE },  /* SysMouse */
2525};
2526
2527
2528/*
2529 * SetupMouse --
2530 *	Sets up the mouse parameters
2531 */
2532static Bool
2533SetupMouse(InputInfoPtr pInfo)
2534{
2535    MouseDevPtr pMse;
2536    int i;
2537    int protoPara[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
2538    const char *name = NULL;
2539    Bool automatic = FALSE;
2540
2541    pMse = pInfo->private;
2542
2543    /* Handle the "Auto" protocol. */
2544    if (pMse->protocolID == PROT_AUTO) {
2545	/*
2546	 * We come here when user specifies protocol "auto" in
2547	 * the configuration file or thru the xf86misc extensions.
2548	 * So we initialize autoprobing here.
2549	 * Probe for PnP/OS mouse first. If unsuccessful
2550	 * try to guess protocol from incoming data.
2551	 */
2552	automatic = TRUE;
2553	pMse->autoProbe = TRUE;
2554	name = autoOSProtocol(pInfo,protoPara);
2555	if (name)  {
2556#ifdef EXTMOUSEDEBUG
2557	    ErrorF("PnP/OS Mouse detected: %s\n",name);
2558#endif
2559	}
2560    }
2561
2562    SetMouseProto(pMse, pMse->protocolID);
2563
2564    if (automatic) {
2565	if (name) {
2566	    /* Possible protoPara overrides from SetupAuto. */
2567	    for (i = 0; i < sizeof(pMse->protoPara); i++)
2568		if (protoPara[i] != -1)
2569		    pMse->protoPara[i] = protoPara[i];
2570	    /* if we come here PnP/OS mouse probing was successful */
2571	} else {
2572#if 1
2573	    /* PnP/OS mouse probing wasn't successful; we look at data */
2574#else
2575  	    xf86Msg(X_ERROR, "%s: cannot determine the mouse protocol\n",
2576		    pInfo->name);
2577	    return FALSE;
2578#endif
2579	}
2580    }
2581
2582    /*
2583     * If protocol has changed fetch the default options
2584     * for the new protocol.
2585     */
2586    if (pMse->oldProtocolID != pMse->protocolID) {
2587	pointer tmp = NULL;
2588	if ((pMse->protocolID >= 0)
2589	    && (pMse->protocolID < PROT_NUMPROTOS)
2590	    && mouseProtocols[pMse->protocolID].defaults)
2591	    tmp = xf86OptionListCreate(
2592		mouseProtocols[pMse->protocolID].defaults, -1, 0);
2593	pInfo->options = xf86OptionListMerge(pInfo->options, tmp);
2594	/*
2595	 * If baudrate is set write it back to the option
2596	 * list so that the serial interface code can access
2597	 * the new value. Not set means default.
2598	 */
2599	if (pMse->baudRate)
2600	    xf86ReplaceIntOption(pInfo->options, "BaudRate", pMse->baudRate);
2601	pMse->oldProtocolID = pMse->protocolID; /* hack */
2602    }
2603
2604
2605    /* Set the port parameters. */
2606    if (!automatic)
2607	xf86SetSerial(pInfo->fd, pInfo->options);
2608
2609    if (!initMouseHW(pInfo))
2610	return FALSE;
2611
2612    pMse->protoBufTail = 0;
2613    pMse->inSync = 0;
2614
2615    return TRUE;
2616}
2617
2618/********************************************************************
2619 *
2620 * Mouse HW setup code
2621 *
2622 ********************************************************************/
2623
2624/*
2625** The following lines take care of the Logitech MouseMan protocols.
2626** The "Logitech" protocol is for the old "series 9" Logitech products.
2627** All products since then use the "MouseMan" protocol.  Some models
2628** were programmable, but most (all?) of the current models are not.
2629**
2630** NOTE: There are different versions of both MouseMan and TrackMan!
2631**       Hence I add another protocol PROT_LOGIMAN, which the user can
2632**       specify as MouseMan in his XF86Config file. This entry was
2633**       formerly handled as a special case of PROT_MS. However, people
2634**       who don't have the middle button problem, can still specify
2635**       Microsoft and use PROT_MS.
2636**
2637** By default, these mice should use a 3 byte Microsoft protocol
2638** plus a 4th byte for the middle button. However, the mouse might
2639** have switched to a different protocol before we use it, so I send
2640** the proper sequence just in case.
2641**
2642** NOTE: - all commands to (at least the European) MouseMan have to
2643**         be sent at 1200 Baud.
2644**       - each command starts with a '*'.
2645**       - whenever the MouseMan receives a '*', it will switch back
2646**	 to 1200 Baud. Hence I have to select the desired protocol
2647**	 first, then select the baud rate.
2648**
2649** The protocols supported by the (European) MouseMan are:
2650**   -  5 byte packed binary protocol, as with the Mouse Systems
2651**      mouse. Selected by sequence "*U".
2652**   -  2 button 3 byte MicroSoft compatible protocol. Selected
2653**      by sequence "*V".
2654**   -  3 button 3+1 byte MicroSoft compatible protocol (default).
2655**      Selected by sequence "*X".
2656**
2657** The following baud rates are supported:
2658**   -  1200 Baud (default). Selected by sequence "*n".
2659**   -  9600 Baud. Selected by sequence "*q".
2660**
2661** Selecting a sample rate is no longer supported with the MouseMan!
2662**               [CHRIS-211092]
2663*/
2664
2665/*
2666 * Do a reset wrap mode before reset.
2667 */
2668#define do_ps2Reset(x)  { \
2669    int i = RETRY_COUNT;\
2670     while (i-- > 0) { \
2671       xf86FlushInput(x->fd); \
2672       if (ps2Reset(x)) break; \
2673    } \
2674  }
2675
2676
2677static Bool
2678initMouseHW(InputInfoPtr pInfo)
2679{
2680    MouseDevPtr pMse = pInfo->private;
2681    const char *s;
2682    unsigned char c;
2683    int speed;
2684    pointer options;
2685    unsigned char *param = NULL;
2686    int paramlen = 0;
2687    int count = RETRY_COUNT;
2688    Bool ps2Init = TRUE;
2689
2690    switch (pMse->protocolID) {
2691	case PROT_LOGI:		/* Logitech Mice */
2692	    /*
2693	     * The baud rate selection command must be sent at the current
2694	     * baud rate; try all likely settings.
2695	     */
2696	    speed = pMse->baudRate;
2697	    switch (speed) {
2698		case 9600:
2699		    s = "*q";
2700		    break;
2701		case 4800:
2702		    s = "*p";
2703		    break;
2704		case 2400:
2705		    s = "*o";
2706		    break;
2707		case 1200:
2708		    s = "*n";
2709		    break;
2710		default:
2711		    /* Fallback value */
2712		    speed = 1200;
2713		    s = "*n";
2714	    }
2715	    xf86SetSerialSpeed(pInfo->fd, 9600);
2716	    xf86WriteSerial(pInfo->fd, s, 2);
2717	    usleep(100000);
2718	    xf86SetSerialSpeed(pInfo->fd, 4800);
2719	    xf86WriteSerial(pInfo->fd, s, 2);
2720	    usleep(100000);
2721	    xf86SetSerialSpeed(pInfo->fd, 2400);
2722	    xf86WriteSerial(pInfo->fd, s, 2);
2723	    usleep(100000);
2724	    xf86SetSerialSpeed(pInfo->fd, 1200);
2725	    xf86WriteSerial(pInfo->fd, s, 2);
2726	    usleep(100000);
2727	    xf86SetSerialSpeed(pInfo->fd, speed);
2728
2729	    /* Select MM series data format. */
2730	    xf86WriteSerial(pInfo->fd, "S", 1);
2731	    usleep(100000);
2732	    /* Set the parameters up for the MM series protocol. */
2733	    options = pInfo->options;
2734	    xf86CollectInputOptions(pInfo, mmDefaults, NULL);
2735	    xf86SetSerial(pInfo->fd, pInfo->options);
2736	    pInfo->options = options;
2737
2738	    /* Select report rate/frequency. */
2739	    if      (pMse->sampleRate <=   0)  c = 'O';  /* 100 */
2740	    else if (pMse->sampleRate <=  15)  c = 'J';  /*  10 */
2741	    else if (pMse->sampleRate <=  27)  c = 'K';  /*  20 */
2742	    else if (pMse->sampleRate <=  42)  c = 'L';  /*  35 */
2743	    else if (pMse->sampleRate <=  60)  c = 'R';  /*  50 */
2744	    else if (pMse->sampleRate <=  85)  c = 'M';  /*  67 */
2745	    else if (pMse->sampleRate <= 125)  c = 'Q';  /* 100 */
2746	    else                               c = 'N';  /* 150 */
2747	    xf86WriteSerial(pInfo->fd, &c, 1);
2748	    break;
2749
2750	case PROT_LOGIMAN:
2751	    speed = pMse->baudRate;
2752	    switch (speed) {
2753		case 9600:
2754		    s = "*q";
2755		    break;
2756		case 1200:
2757		    s = "*n";
2758		    break;
2759		default:
2760		    /* Fallback value */
2761		    speed = 1200;
2762		    s = "*n";
2763	    }
2764	    xf86SetSerialSpeed(pInfo->fd, 1200);
2765	    xf86WriteSerial(pInfo->fd, "*n", 2);
2766	    xf86WriteSerial(pInfo->fd, "*X", 2);
2767	    xf86WriteSerial(pInfo->fd, s, 2);
2768	    usleep(100000);
2769	    xf86SetSerialSpeed(pInfo->fd, speed);
2770	    break;
2771
2772	case PROT_MMHIT:		/* MM_HitTablet */
2773	    /*
2774	     * Initialize Hitachi PUMA Plus - Model 1212E to desired settings.
2775	     * The tablet must be configured to be in MM mode, NO parity,
2776	     * Binary Format.  pMse->sampleRate controls the sensitivity
2777	     * of the tablet.  We only use this tablet for it's 4-button puck
2778	     * so we don't run in "Absolute Mode".
2779	     */
2780	    xf86WriteSerial(pInfo->fd, "z8", 2);	/* Set Parity = "NONE" */
2781	    usleep(50000);
2782	    xf86WriteSerial(pInfo->fd, "zb", 2);	/* Set Format = "Binary" */
2783	    usleep(50000);
2784	    xf86WriteSerial(pInfo->fd, "@", 1);	/* Set Report Mode = "Stream" */
2785	    usleep(50000);
2786	    xf86WriteSerial(pInfo->fd, "R", 1);	/* Set Output Rate = "45 rps" */
2787	    usleep(50000);
2788	    xf86WriteSerial(pInfo->fd, "I\x20", 2);	/* Set Incrememtal Mode "20" */
2789	    usleep(50000);
2790	    xf86WriteSerial(pInfo->fd, "E", 1);	/* Set Data Type = "Relative */
2791	    usleep(50000);
2792	    /*
2793	     * These sample rates translate to 'lines per inch' on the Hitachi
2794	     * tablet.
2795	     */
2796	    if      (pMse->sampleRate <=   40) c = 'g';
2797	    else if (pMse->sampleRate <=  100) c = 'd';
2798	    else if (pMse->sampleRate <=  200) c = 'e';
2799	    else if (pMse->sampleRate <=  500) c = 'h';
2800	    else if (pMse->sampleRate <= 1000) c = 'j';
2801	    else                               c = 'd';
2802	    xf86WriteSerial(pInfo->fd, &c, 1);
2803	    usleep(50000);
2804	    xf86WriteSerial(pInfo->fd, "\021", 1);	/* Resume DATA output */
2805	    break;
2806
2807	case PROT_THINKING:		/* ThinkingMouse */
2808	    /* This mouse may send a PnP ID string, ignore it. */
2809	    usleep(200000);
2810	    xf86FlushInput(pInfo->fd);
2811	    /* Send the command to initialize the beast. */
2812	    for (s = "E5E5"; *s; ++s) {
2813		xf86WriteSerial(pInfo->fd, s, 1);
2814		if ((xf86WaitForInput(pInfo->fd, 1000000) <= 0))
2815		    break;
2816		xf86ReadSerial(pInfo->fd, &c, 1);
2817		if (c != *s)
2818		    break;
2819	    }
2820	    break;
2821
2822	case PROT_MSC:		/* MouseSystems Corp */
2823	    usleep(100000);
2824	    xf86FlushInput(pInfo->fd);
2825	    break;
2826
2827	case PROT_ACECAD:
2828	    /* initialize */
2829	    /* A nul character resets. */
2830	    xf86WriteSerial(pInfo->fd, "", 1);
2831	    usleep(50000);
2832	    /* Stream out relative mode high resolution increments of 1. */
2833	    xf86WriteSerial(pInfo->fd, "@EeI!", 5);
2834	    break;
2835
2836	case PROT_BM:		/* bus/InPort mouse */
2837	    if (osInfo->SetBMRes)
2838		osInfo->SetBMRes(pInfo, pMse->protocol, pMse->sampleRate,
2839				 pMse->resolution);
2840	    break;
2841
2842	case PROT_GENPS2:
2843	    ps2Init = FALSE;
2844	    break;
2845
2846	case PROT_PS2:
2847	case PROT_GLIDEPS2:
2848	    break;
2849
2850	case PROT_IMPS2:		/* IntelliMouse */
2851	{
2852	    static unsigned char seq[] = { 243, 200, 243, 100, 243, 80 };
2853	    param = seq;
2854	    paramlen = sizeof(seq);
2855	}
2856	break;
2857
2858	case PROT_EXPPS2:		/* IntelliMouse Explorer */
2859	{
2860	    static unsigned char seq[] = { 243, 200, 243, 100, 243, 80,
2861					   243, 200, 243, 200, 243, 80 };
2862
2863	    param = seq;
2864	    paramlen = sizeof(seq);
2865	}
2866	break;
2867
2868	case PROT_NETPS2:		/* NetMouse, NetMouse Pro, Mie Mouse */
2869	case PROT_NETSCPS2:		/* NetScroll */
2870	{
2871	    static unsigned char seq[] = { 232, 3, 230, 230, 230, 233 };
2872
2873	    param = seq;
2874	    paramlen = sizeof(seq);
2875	}
2876	break;
2877
2878	case PROT_MMPS2:		/* MouseMan+, FirstMouse+ */
2879	{
2880	    static unsigned char seq[] = { 230, 232, 0, 232, 3, 232, 2, 232, 1,
2881					   230, 232, 3, 232, 1, 232, 2, 232, 3 };
2882	    param = seq;
2883	    paramlen = sizeof(seq);
2884	}
2885	break;
2886
2887	case PROT_THINKPS2:		/* ThinkingMouse */
2888	{
2889	    static unsigned char seq[] = { 243, 10, 232,  0, 243, 20, 243, 60,
2890					   243, 40, 243, 20, 243, 20, 243, 60,
2891					   243, 40, 243, 20, 243, 20 };
2892	    param = seq;
2893	    paramlen = sizeof(seq);
2894	}
2895	break;
2896	case PROT_SYSMOUSE:
2897	    if (osInfo->SetMiscRes)
2898		osInfo->SetMiscRes(pInfo, pMse->protocol, pMse->sampleRate,
2899				   pMse->resolution);
2900	    break;
2901
2902	default:
2903	    /* Nothing to do. */
2904	    break;
2905    }
2906
2907    if (pMse->class & (MSE_PS2 | MSE_XPS2)) {
2908	/*
2909	 * If one part of the PS/2 mouse initialization fails
2910	 * redo complete initialization. There are mice which
2911	 * have occasional problems with initialization and
2912	 * are in an unknown state.
2913	 */
2914	if (ps2Init) {
2915	REDO:
2916	    do_ps2Reset(pInfo);
2917	    if (paramlen > 0) {
2918		if (!ps2SendPacket(pInfo,param,paramlen)) {
2919		    usleep(30000);
2920		    xf86FlushInput(pInfo->fd);
2921		    if (!count--)
2922			return TRUE;
2923		    goto REDO;
2924		}
2925		ps2GetDeviceID(pInfo);
2926		usleep(30000);
2927		xf86FlushInput(pInfo->fd);
2928	    }
2929
2930	    if (osInfo->SetPS2Res) {
2931		osInfo->SetPS2Res(pInfo, pMse->protocol, pMse->sampleRate,
2932				  pMse->resolution);
2933	    } else {
2934		unsigned char c2[2];
2935
2936		c = 0xE6;	/*230*/	/* 1:1 scaling */
2937		if (!ps2SendPacket(pInfo,&c,1)) {
2938		    if (!count--)
2939			return TRUE;
2940		    goto REDO;
2941		}
2942		c2[0] = 0xF3; /*243*/ /* set sampling rate */
2943		if (pMse->sampleRate > 0) {
2944		    if (pMse->sampleRate >= 200)
2945			c2[1] = 200;
2946		    else if (pMse->sampleRate >= 100)
2947			c2[1] = 100;
2948		    else if (pMse->sampleRate >= 80)
2949			c2[1] = 80;
2950		    else if (pMse->sampleRate >= 60)
2951			c2[1] = 60;
2952		    else if (pMse->sampleRate >= 40)
2953			c2[1] = 40;
2954		    else
2955			c2[1] = 20;
2956		} else {
2957		    c2[1] = 100;
2958		}
2959		if (!ps2SendPacket(pInfo,c2,2)) {
2960		    if (!count--)
2961			return TRUE;
2962		    goto REDO;
2963		}
2964		c2[0] = 0xE8; /*232*/	/* set device resolution */
2965		if (pMse->resolution > 0) {
2966		    if (pMse->resolution >= 200)
2967			c2[1] = 3;
2968		    else if (pMse->resolution >= 100)
2969			c2[1] = 2;
2970		    else if (pMse->resolution >= 50)
2971			c2[1] = 1;
2972		    else
2973			c2[1] = 0;
2974		} else {
2975		    c2[1] = 3; /* used to be 2, W. uses 3 */
2976		}
2977		if (!ps2SendPacket(pInfo,c2,2)) {
2978		    if (!count--)
2979			return TRUE;
2980		    goto REDO;
2981		}
2982		usleep(30000);
2983		xf86FlushInput(pInfo->fd);
2984		if (!ps2EnableDataReporting(pInfo)) {
2985		    xf86Msg(X_INFO, "%s: ps2EnableDataReporting: failed\n",
2986			    pInfo->name);
2987		    xf86FlushInput(pInfo->fd);
2988		    if (!count--)
2989			return TRUE;
2990		    goto REDO;
2991		} else {
2992		    xf86Msg(X_INFO, "%s: ps2EnableDataReporting: succeeded\n",
2993			    pInfo->name);
2994		}
2995	    }
2996	    /*
2997	     * The PS/2 reset handling needs to be rechecked.
2998	     * We need to wait until after the 4.3 release.
2999	     */
3000	}
3001    } else {
3002	if (paramlen > 0) {
3003	    if (xf86WriteSerial(pInfo->fd, param, paramlen) != paramlen)
3004		xf86Msg(X_ERROR, "%s: Mouse initialization failed\n",
3005			pInfo->name);
3006	    usleep(30000);
3007	    xf86FlushInput(pInfo->fd);
3008	}
3009    }
3010
3011    return TRUE;
3012}
3013
3014#ifdef SUPPORT_MOUSE_RESET
3015static Bool
3016mouseReset(InputInfoPtr pInfo, unsigned char val)
3017{
3018    MouseDevPtr pMse = pInfo->private;
3019    mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv;
3020    CARD32 prevEvent = mousepriv->lastEvent;
3021    Bool expectReset = FALSE;
3022    Bool ret = FALSE;
3023
3024    mousepriv->lastEvent = GetTimeInMillis();
3025
3026#ifdef EXTMOUSEDEBUG
3027    ErrorF("byte: 0x%x time: %li\n",val,mousepriv->lastEvent);
3028#endif
3029    /*
3030     * We believe that the following is true:
3031     * When the mouse is replugged it will send a reset package
3032     * It takes several seconds to replug a mouse: We don't see
3033     * events for several seconds before we see the replug event package.
3034     * There is no significant delay between consecutive bytes
3035     * of a replug event package.
3036     * There are no bytes sent after the replug event package until
3037     * the mouse is reset.
3038     */
3039
3040    if (mousepriv->current == 0
3041	&& (mousepriv->lastEvent - prevEvent) < 4000)
3042	return FALSE;
3043
3044    if (mousepriv->current > 0
3045	&& (mousepriv->lastEvent - prevEvent) >= 1000) {
3046	mousepriv->inReset = FALSE;
3047	mousepriv->current = 0;
3048	return FALSE;
3049    }
3050
3051    if (mousepriv->inReset)
3052	mousepriv->inReset = FALSE;
3053
3054#ifdef EXTMOUSEDEBUG
3055    ErrorF("Mouse Current: %i 0x%x\n",mousepriv->current, val);
3056#endif
3057
3058    /* here we put the mouse specific reset detection */
3059    /* They need to do three things:                 */
3060    /*  Check if byte may be a reset byte            */
3061    /*  If so: Set expectReset TRUE                  */
3062    /*  If convinced: Set inReset TRUE               */
3063    /*                Register BlockAndWakeupHandler */
3064
3065    /* PS/2 */
3066    {
3067	unsigned char seq[] = { 0xaa, 0x00 };
3068	int len = sizeof(seq);
3069
3070	if (seq[mousepriv->current] == val)
3071	    expectReset = TRUE;
3072
3073	if (len == mousepriv->current + 1) {
3074	    mousepriv->inReset = TRUE;
3075	    mousepriv->expires = GetTimeInMillis() + 1000;
3076
3077#ifdef EXTMOUSEDEBUG
3078	    ErrorF("Found PS/2 Reset string\n");
3079#endif
3080	    RegisterBlockAndWakeupHandlers (ps2BlockHandler,
3081					    ps2WakeupHandler, (pointer) pInfo);
3082	    ret = TRUE;
3083	}
3084    }
3085
3086	if (!expectReset)
3087	    mousepriv->current = 0;
3088	else
3089	    mousepriv->current++;
3090	return ret;
3091}
3092
3093static void
3094ps2BlockHandler(pointer data, struct timeval **waitTime,
3095		pointer LastSelectMask)
3096{
3097    InputInfoPtr    pInfo = (InputInfoPtr) data;
3098    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
3099    mousePrivPtr    mousepriv = (mousePrivPtr)pMse->mousePriv;
3100    int		    ms;
3101
3102    if (mousepriv->inReset) {
3103	ms = mousepriv->expires - GetTimeInMillis ();
3104	if (ms <= 0)
3105	    ms = 0;
3106	AdjustWaitForDelay (waitTime, ms);
3107    } else
3108	RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler,
3109				      (pointer) pInfo);
3110}
3111
3112static void
3113ps2WakeupHandler(pointer data, int i, pointer LastSelectMask)
3114{
3115    InputInfoPtr    pInfo = (InputInfoPtr) data;
3116    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
3117    mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv;
3118    int		    ms;
3119
3120    if (mousepriv->inReset) {
3121	unsigned char val;
3122	int blocked;
3123
3124	ms = mousepriv->expires - GetTimeInMillis();
3125	if (ms > 0)
3126	    return;
3127
3128	blocked = xf86BlockSIGIO ();
3129
3130	xf86MsgVerb(X_INFO,3,
3131		    "Got reinsert event: reinitializing PS/2 mouse\n");
3132	val = 0xf4;
3133	if (xf86WriteSerial(pInfo->fd, &val, 1) != 1)
3134	    xf86Msg(X_ERROR, "%s: Write to mouse failed\n",
3135		    pInfo->name);
3136	xf86UnblockSIGIO(blocked);
3137    }
3138    RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler,
3139				  (pointer) pInfo);
3140}
3141#endif /* SUPPORT_MOUSE_RESET */
3142
3143/************************************************************
3144 *
3145 * Autoprobe stuff
3146 *
3147 ************************************************************/
3148#ifdef EXTMOUSEDEBUG
3149#  define AP_DBG(x) { ErrorF("Autoprobe: "); ErrorF x; }
3150#  define AP_DBGC(x) ErrorF x ;
3151# else
3152#  define AP_DBG(x)
3153#  define AP_DBGC(x)
3154#endif
3155
3156static
3157MouseProtocolID hardProtocolList[] = { 	PROT_MSC, PROT_MM, PROT_LOGI,
3158					PROT_LOGIMAN, PROT_MMHIT,
3159					PROT_GLIDE, PROT_IMSERIAL,
3160					PROT_THINKING, PROT_ACECAD,
3161					PROT_THINKPS2, PROT_MMPS2,
3162					PROT_GLIDEPS2,
3163					PROT_NETSCPS2, PROT_EXPPS2,PROT_IMPS2,
3164					PROT_GENPS2, PROT_NETPS2,
3165					PROT_MS,
3166					PROT_UNKNOWN
3167};
3168
3169static
3170MouseProtocolID softProtocolList[] = { 	PROT_MSC, PROT_MM, PROT_LOGI,
3171					PROT_LOGIMAN, PROT_MMHIT,
3172					PROT_GLIDE, PROT_IMSERIAL,
3173					PROT_THINKING, PROT_ACECAD,
3174					PROT_THINKPS2, PROT_MMPS2,
3175					PROT_GLIDEPS2,
3176					PROT_NETSCPS2 ,PROT_IMPS2,
3177					PROT_GENPS2,
3178					PROT_MS,
3179					PROT_UNKNOWN
3180};
3181
3182static const char *
3183autoOSProtocol(InputInfoPtr pInfo, int *protoPara)
3184{
3185    MouseDevPtr pMse = pInfo->private;
3186    const char *name = NULL;
3187    MouseProtocolID protocolID = PROT_UNKNOWN;
3188
3189    /* Check if the OS has a detection mechanism. */
3190    if (osInfo->SetupAuto) {
3191	name = osInfo->SetupAuto(pInfo, protoPara);
3192	if (name) {
3193	    protocolID = ProtocolNameToID(name);
3194	    switch (protocolID) {
3195		case PROT_UNKNOWN:
3196		    /* Check for a builtin OS-specific protocol. */
3197		    if (osInfo->CheckProtocol && osInfo->CheckProtocol(name)) {
3198			/* We can only come here if the protocol has been
3199			 * changed to auto thru the xf86misc extension
3200			 * and we have detected an OS specific builtin
3201			 * protocol. Currently we cannot handle this */
3202			name = NULL;
3203		    } else
3204			name = NULL;
3205		    break;
3206		case PROT_UNSUP:
3207		    name = NULL;
3208		    break;
3209		default:
3210		    break;
3211	    }
3212	}
3213    }
3214    if (!name) {
3215	/* A PnP serial mouse? */
3216	protocolID = MouseGetPnpProtocol(pInfo);
3217	if (protocolID >= 0 && protocolID < PROT_NUMPROTOS) {
3218	    name = ProtocolIDToName(protocolID);
3219	    xf86Msg(X_PROBED, "%s: PnP-detected protocol: \"%s\"\n",
3220		    pInfo->name, name);
3221	}
3222    }
3223    if (!name && osInfo->GuessProtocol) {
3224	name = osInfo->GuessProtocol(pInfo, 0);
3225	if (name)
3226	    protocolID = ProtocolNameToID(name);
3227    }
3228
3229    if (name) {
3230	pMse->protocolID = protocolID;
3231    }
3232
3233    return name;
3234}
3235
3236/*
3237 * createProtocolList() -- create a list of protocols which may
3238 * match on the incoming data stream.
3239 */
3240static void
3241createProtoList(MouseDevPtr pMse, MouseProtocolID *protoList)
3242{
3243    int i, j, k  = 0;
3244    MouseProtocolID prot;
3245    unsigned char *para;
3246    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3247    MouseProtocolID *tmplist = NULL;
3248    int blocked;
3249
3250    AP_DBGC(("Autoprobe: "));
3251    for (i = 0; i < mPriv->count; i++)
3252	AP_DBGC(("%2.2x ", (unsigned char) mPriv->data[i]));
3253    AP_DBGC(("\n"));
3254
3255    blocked = xf86BlockSIGIO ();
3256
3257    /* create a private copy first so we can write in the old list */
3258    if ((tmplist = xalloc(sizeof(MouseProtocolID) * NUM_AUTOPROBE_PROTOS))){
3259	for (i = 0; protoList[i] != PROT_UNKNOWN; i++) {
3260	    tmplist[i] = protoList[i];
3261	}
3262	tmplist[i] = PROT_UNKNOWN;
3263	protoList = tmplist;
3264    } else
3265	return;
3266
3267    for (i = 0; ((prot = protoList[i]) != PROT_UNKNOWN
3268		 && (k < NUM_AUTOPROBE_PROTOS - 1)) ; i++) {
3269	Bool bad = TRUE;
3270	unsigned char byte = 0;
3271	int count = 0;
3272	int next_header_candidate = 0;
3273	int header_count = 0;
3274
3275	if (!GetProtocol(prot))
3276	    continue;
3277	para = proto[prot];
3278
3279	AP_DBG(("Protocol: %s ", ProtocolIDToName(prot)));
3280
3281#ifdef EXTMOUSEDEBUG
3282	for (j = 0; j < 7; j++)
3283	    AP_DBGC(("%2.2x ", (unsigned char) para[j]));
3284	AP_DBGC(("\n"));
3285#endif
3286	j = 0;
3287	while (1) {
3288	    /* look for header */
3289	    while (j < mPriv->count) {
3290		if (((byte = mPriv->data[j++]) & para[0]) == para[1]){
3291		    AP_DBG(("found header %2.2x\n",byte));
3292		    next_header_candidate = j;
3293		    count = 1;
3294		    break;
3295		} else {
3296		    /*
3297		     * Bail out if number of bytes per package have
3298		     * been tested for header.
3299		     * Take bytes per package of leading garbage into
3300		     * account.
3301		     */
3302		    if (j > para[4] && ++header_count > para[4]) {
3303			j = mPriv->count;
3304			break;
3305		    }
3306		}
3307	    }
3308	    /* check if remaining data matches protocol */
3309	    while (j < mPriv->count) {
3310		byte = mPriv->data[j++];
3311		if (count == para[4]) {
3312		    count = 0;
3313		    /* check and eat excess byte */
3314		    if (((byte & para[0]) != para[1])
3315			&& ((byte & para[5]) == para[6])) {
3316			AP_DBG(("excess byte found\n"));
3317			continue;
3318		    }
3319		}
3320		if (count == 0) {
3321		    /* validate next header */
3322		    bad = FALSE;
3323		    AP_DBG(("Complete set found\n"));
3324		    if ((byte & para[0]) != para[1]) {
3325			AP_DBG(("Autoprobe: header bad\n"));
3326			bad = TRUE;
3327			break;
3328		    } else {
3329			count++;
3330			continue;
3331		    }
3332		}
3333		/* validate data */
3334		else if (((byte & para[2]) != para[3])
3335			 || ((para[7] & MPF_SAFE)
3336			     && ((byte & para[0]) == para[1]))) {
3337		    AP_DBG(("data bad\n"));
3338		    bad = TRUE;
3339		    break;
3340		} else {
3341		    count ++;
3342		    continue;
3343		}
3344	    }
3345	    if (!bad) {
3346		/* this is a matching protocol */
3347		mPriv->protoList[k++] = prot;
3348		AP_DBG(("Autoprobe: Adding protocol %s to list (entry %i)\n",
3349			ProtocolIDToName(prot),k-1));
3350		break;
3351	    }
3352	    j = next_header_candidate;
3353	    next_header_candidate = 0;
3354	    /* we have tested number of bytes per package for header */
3355	    if (j > para[4] && ++header_count > para[4])
3356		break;
3357	    /* we have not found anything that looks like a header */
3358	    if (!next_header_candidate)
3359		break;
3360	    AP_DBG(("Looking for new header\n"));
3361	}
3362    }
3363
3364    xf86UnblockSIGIO(blocked);
3365
3366    mPriv->protoList[k] = PROT_UNKNOWN;
3367
3368    xfree(tmplist);
3369}
3370
3371
3372/* This only needs to be done once */
3373static void **serialDefaultsList = NULL;
3374
3375/*
3376 * createSerialDefaultsLists() - create a list of the different default
3377 * settings for the serial interface of the known protocols.
3378 */
3379static void
3380createSerialDefaultsList(void)
3381{
3382    int i = 0, j, k;
3383
3384    serialDefaultsList = (void **)xnfalloc(sizeof(void*));
3385    serialDefaultsList[0] = NULL;
3386
3387    for (j = 0; mouseProtocols[j].name; j++) {
3388	if (!mouseProtocols[j].defaults)
3389	    continue;
3390	for (k = 0; k < i; k++)
3391	    if (mouseProtocols[j].defaults == serialDefaultsList[k])
3392		continue;
3393	i++;
3394	serialDefaultsList = (void**)xnfrealloc(serialDefaultsList,
3395						sizeof(void*)*(i+1));
3396	serialDefaultsList[i-1] = mouseProtocols[j].defaults;
3397	serialDefaultsList[i] = NULL;
3398    }
3399}
3400
3401typedef enum {
3402    STATE_INVALID,
3403    STATE_UNCERTAIN,
3404    STATE_VALID
3405} validState;
3406
3407/* Probing threshold values */
3408#define PROBE_UNCERTAINTY 50
3409#define BAD_CERTAINTY 6
3410#define BAD_INC_CERTAINTY 1
3411#define BAD_INC_CERTAINTY_WHEN_SYNC_LOST 2
3412
3413static validState
3414validCount(mousePrivPtr mPriv, Bool inSync, Bool lostSync)
3415{
3416    if (inSync) {
3417	if (!--mPriv->goodCount) {
3418	    /* we are sure to have found the correct protocol */
3419	    mPriv->badCount = 0;
3420	    return STATE_VALID;
3421	}
3422	AP_DBG(("%i successful rounds to go\n",
3423		mPriv->goodCount));
3424	return STATE_UNCERTAIN;
3425    }
3426
3427
3428    /* We are out of sync again */
3429    mPriv->goodCount = PROBE_UNCERTAINTY;
3430    /* We increase uncertainty of having the correct protocol */
3431    mPriv->badCount+= lostSync ? BAD_INC_CERTAINTY_WHEN_SYNC_LOST
3432	: BAD_INC_CERTAINTY;
3433
3434    if (mPriv->badCount < BAD_CERTAINTY) {
3435	/* We are not convinced yet to have the wrong protocol */
3436	AP_DBG(("Changing protocol after: %i rounds\n",
3437		BAD_CERTAINTY - mPriv->badCount));
3438	return STATE_UNCERTAIN;
3439    }
3440    return STATE_INVALID;
3441}
3442
3443#define RESET_VALIDATION	mPriv->goodCount = PROBE_UNCERTAINTY;\
3444				mPriv->badCount = 0;\
3445				mPriv->prevDx = 0;\
3446				mPriv->prevDy = 0;\
3447				mPriv->accDx = 0;\
3448				mPriv->accDy = 0;\
3449				mPriv->acc = 0;
3450
3451static void
3452autoProbeMouse(InputInfoPtr pInfo, Bool inSync, Bool lostSync)
3453{
3454    MouseDevPtr pMse = pInfo->private;
3455    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3456
3457    MouseProtocolID *protocolList = NULL;
3458
3459    while (1) {
3460	switch (mPriv->autoState) {
3461	case AUTOPROBE_GOOD:
3462 	    if (inSync)
3463		return;
3464	    AP_DBG(("State GOOD\n"));
3465	    RESET_VALIDATION;
3466	    mPriv->autoState = AUTOPROBE_VALIDATE1;
3467	    return;
3468	case AUTOPROBE_H_GOOD:
3469	    if (inSync)
3470		return;
3471	    AP_DBG(("State H_GOOD\n"));
3472	    RESET_VALIDATION;
3473	    mPriv->autoState = AUTOPROBE_H_VALIDATE2;
3474	    return;
3475	case AUTOPROBE_H_NOPROTO:
3476	    AP_DBG(("State H_NOPROTO\n"));
3477	    mPriv->protocolID = 0;
3478	    mPriv->autoState = AUTOPROBE_H_SETPROTO;
3479	    break;
3480	case AUTOPROBE_H_SETPROTO:
3481	    AP_DBG(("State H_SETPROTO\n"));
3482	    if ((pMse->protocolID = hardProtocolList[mPriv->protocolID++])
3483		== PROT_UNKNOWN) {
3484		mPriv->protocolID = 0;
3485		break;
3486	    } else if (GetProtocol(pMse->protocolID) &&  SetupMouse(pInfo)) {
3487		FlushButtons(pMse);
3488		RESET_VALIDATION;
3489		AP_DBG(("Autoprobe: Trying Protocol: %s\n",
3490			ProtocolIDToName(pMse->protocolID)));
3491		mPriv->autoState = AUTOPROBE_H_VALIDATE1;
3492		return;
3493	    }
3494	    break;
3495	case AUTOPROBE_H_VALIDATE1:
3496	    AP_DBG(("State H_VALIDATE1\n"));
3497	    switch (validCount(mPriv,inSync,lostSync)) {
3498	    case STATE_INVALID:
3499		mPriv->autoState = AUTOPROBE_H_SETPROTO;
3500		break;
3501	    case STATE_VALID:
3502		    xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3503			    ProtocolIDToName(pMse->protocolID));
3504		    mPriv->autoState = AUTOPROBE_H_GOOD;
3505		    return;
3506	    case STATE_UNCERTAIN:
3507		return;
3508	    default:
3509		break;
3510	    }
3511	    break;
3512	case AUTOPROBE_H_VALIDATE2:
3513	    AP_DBG(("State H_VALIDATE2\n"));
3514	    switch (validCount(mPriv,inSync,lostSync)) {
3515	    case STATE_INVALID:
3516		mPriv->autoState = AUTOPROBE_H_AUTODETECT;
3517		break;
3518	    case STATE_VALID:
3519		xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3520			ProtocolIDToName(pMse->protocolID));
3521		mPriv->autoState = AUTOPROBE_H_GOOD;
3522		return;
3523	    case STATE_UNCERTAIN:
3524		return;
3525	    }
3526	    break;
3527	case AUTOPROBE_H_AUTODETECT:
3528	    AP_DBG(("State H_AUTODETECT\n"));
3529	    pMse->protocolID = PROT_AUTO;
3530	    AP_DBG(("Looking for PnP/OS mouse\n"));
3531	    mPriv->count = 0;
3532	    SetupMouse(pInfo);
3533	    if (pMse->protocolID != PROT_AUTO)
3534		mPriv->autoState = AUTOPROBE_H_GOOD;
3535	    else
3536		mPriv->autoState = AUTOPROBE_H_NOPROTO;
3537	    break;
3538	case AUTOPROBE_NOPROTO:
3539	    AP_DBG(("State NOPROTO\n"));
3540	    mPriv->count = 0;
3541	    mPriv->serialDefaultsNum = -1;
3542	    mPriv->autoState = AUTOPROBE_COLLECT;
3543	    break;
3544	case AUTOPROBE_COLLECT:
3545	    AP_DBG(("State COLLECT\n"));
3546	    if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES)
3547		return;
3548	    protocolList = softProtocolList;
3549	    mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST;
3550	    break;
3551	case AUTOPROBE_CREATE_PROTOLIST:
3552	    AP_DBG(("State CREATE_PROTOLIST\n"));
3553	    createProtoList(pMse, protocolList);
3554	    mPriv->protocolID = 0;
3555	    mPriv->autoState = AUTOPROBE_SWITCH_PROTOCOL;
3556	    break;
3557	case AUTOPROBE_AUTODETECT:
3558	    AP_DBG(("State AUTODETECT\n"));
3559	    pMse->protocolID = PROT_AUTO;
3560	    AP_DBG(("Looking for PnP/OS mouse\n"));
3561	    mPriv->count = 0;
3562	    SetupMouse(pInfo);
3563	    if (pMse->protocolID != PROT_AUTO)
3564		mPriv->autoState = AUTOPROBE_GOOD;
3565	    else
3566		mPriv->autoState = AUTOPROBE_NOPROTO;
3567	    break;
3568	case AUTOPROBE_VALIDATE1:
3569	    AP_DBG(("State VALIDATE1\n"));
3570	    switch (validCount(mPriv,inSync,lostSync)) {
3571	    case STATE_INVALID:
3572		mPriv->autoState = AUTOPROBE_AUTODETECT;
3573		break;
3574	    case STATE_VALID:
3575		xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3576			ProtocolIDToName(pMse->protocolID));
3577		mPriv->autoState = AUTOPROBE_GOOD;
3578		break;
3579	    case STATE_UNCERTAIN:
3580		return;
3581	    }
3582	    break;
3583	case AUTOPROBE_VALIDATE2:
3584	    AP_DBG(("State VALIDATE2\n"));
3585	    switch (validCount(mPriv,inSync,lostSync)) {
3586	    case STATE_INVALID:
3587		protocolList = &mPriv->protoList[mPriv->protocolID];
3588		mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST;
3589		break;
3590	    case STATE_VALID:
3591		xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3592			ProtocolIDToName(pMse->protocolID));
3593		mPriv->autoState = AUTOPROBE_GOOD;
3594		break;
3595	    case STATE_UNCERTAIN:
3596		return;
3597	    }
3598	    break;
3599	case AUTOPROBE_SWITCHSERIAL:
3600	{
3601	    pointer serialDefaults;
3602	    AP_DBG(("State SWITCHSERIAL\n"));
3603
3604	    if (!serialDefaultsList)
3605		createSerialDefaultsList();
3606
3607	    AP_DBG(("Switching serial params\n"));
3608	    if ((serialDefaults =
3609		 serialDefaultsList[++mPriv->serialDefaultsNum]) == NULL) {
3610		mPriv->serialDefaultsNum = 0;
3611	    } else {
3612		pointer tmp = xf86OptionListCreate(serialDefaults, -1, 0);
3613		xf86SetSerial(pInfo->fd, tmp);
3614		xf86OptionListFree(tmp);
3615		mPriv->count = 0;
3616		mPriv->autoState = AUTOPROBE_COLLECT;
3617	    }
3618	    break;
3619	}
3620	case AUTOPROBE_SWITCH_PROTOCOL:
3621	{
3622	    MouseProtocolID proto;
3623	    void *defaults;
3624	    AP_DBG(("State SWITCH_PROTOCOL\n"));
3625	    proto = mPriv->protoList[mPriv->protocolID++];
3626	    if (proto == PROT_UNKNOWN)
3627		mPriv->autoState = AUTOPROBE_SWITCHSERIAL;
3628	    else if (!(defaults = GetProtocol(proto)->defaults)
3629		       || (mPriv->serialDefaultsNum == -1
3630			   && (defaults == msDefaults))
3631		       || (mPriv->serialDefaultsNum != -1
3632			   && serialDefaultsList[mPriv->serialDefaultsNum]
3633			   == defaults)) {
3634		AP_DBG(("Changing Protocol to %s\n",
3635			ProtocolIDToName(proto)));
3636		SetMouseProto(pMse,proto);
3637		FlushButtons(pMse);
3638		RESET_VALIDATION;
3639		mPriv->autoState = AUTOPROBE_VALIDATE2;
3640		return;
3641	    }
3642	    break;
3643	}
3644	}
3645    }
3646}
3647
3648static Bool
3649autoGood(MouseDevPtr pMse)
3650{
3651    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3652
3653    if (!pMse->autoProbe)
3654	return TRUE;
3655
3656    switch (mPriv->autoState) {
3657    case AUTOPROBE_GOOD:
3658    case AUTOPROBE_H_GOOD:
3659	return TRUE;
3660    case AUTOPROBE_VALIDATE1: /* @@@ */
3661    case AUTOPROBE_H_VALIDATE1: /* @@@ */
3662    case AUTOPROBE_VALIDATE2:
3663    case AUTOPROBE_H_VALIDATE2:
3664	if (mPriv->goodCount < PROBE_UNCERTAINTY/2)
3665	    return TRUE;
3666    default:
3667	return FALSE;
3668    }
3669}
3670
3671
3672#define TOT_THRESHOLD 3000
3673#define VAL_THRESHOLD 40
3674
3675/*
3676 * checkForErraticMovements() -- check if mouse 'jumps around'.
3677 */
3678static void
3679checkForErraticMovements(InputInfoPtr pInfo, int dx, int dy)
3680{
3681    MouseDevPtr pMse = pInfo->private;
3682    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3683
3684    if (!mPriv->goodCount)
3685	return;
3686
3687#if 0
3688    if (abs(dx - mPriv->prevDx) > 300
3689	|| abs(dy - mPriv->prevDy) > 300)
3690	AP_DBG(("erratic1 behaviour\n"));
3691#endif
3692    if (abs(dx) > VAL_THRESHOLD) {
3693	if (sign(dx) == sign(mPriv->prevDx)) {
3694	    mPriv->accDx += dx;
3695	    if (abs(mPriv->accDx) > mPriv->acc) {
3696		mPriv->acc = abs(mPriv->accDx);
3697		AP_DBG(("acc=%i\n",mPriv->acc));
3698	    }
3699	    else
3700		AP_DBG(("accDx=%i\n",mPriv->accDx));
3701	} else {
3702	    mPriv->accDx = 0;
3703	}
3704    }
3705
3706    if (abs(dy) > VAL_THRESHOLD) {
3707	if (sign(dy) == sign(mPriv->prevDy)) {
3708	    mPriv->accDy += dy;
3709	    if (abs(mPriv->accDy) > mPriv->acc) {
3710		mPriv->acc = abs(mPriv->accDy);
3711		AP_DBG(("acc: %i\n",mPriv->acc));
3712	    } else
3713		AP_DBG(("accDy=%i\n",mPriv->accDy));
3714	} else {
3715	    mPriv->accDy = 0;
3716	}
3717    }
3718    mPriv->prevDx = dx;
3719    mPriv->prevDy = dy;
3720    if (mPriv->acc > TOT_THRESHOLD) {
3721	mPriv->goodCount = PROBE_UNCERTAINTY;
3722	mPriv->prevDx = 0;
3723	mPriv->prevDy = 0;
3724	mPriv->accDx = 0;
3725	mPriv->accDy = 0;
3726	mPriv->acc = 0;
3727	AP_DBG(("erratic2 behaviour\n"));
3728	autoProbeMouse(pInfo, FALSE,TRUE);
3729    }
3730}
3731
3732static void
3733SetMouseProto(MouseDevPtr pMse, MouseProtocolID protocolID)
3734{
3735    pMse->protocolID = protocolID;
3736    pMse->protocol = ProtocolIDToName(pMse->protocolID);
3737    pMse->class = ProtocolIDToClass(pMse->protocolID);
3738    if ((pMse->protocolID >= 0) && (pMse->protocolID < PROT_NUMPROTOS))
3739	memcpy(pMse->protoPara, proto[pMse->protocolID],
3740	       sizeof(pMse->protoPara));
3741
3742    if (pMse->emulate3ButtonsSoft)
3743	pMse->emulate3Buttons = TRUE;
3744}
3745
3746/*
3747 * collectData() -- collect data bytes sent by mouse.
3748 */
3749static Bool
3750collectData(MouseDevPtr pMse, unsigned char u)
3751{
3752    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3753    if (mPriv->count < NUM_MSE_AUTOPROBE_TOTAL) {
3754	mPriv->data[mPriv->count++] = u;
3755	if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES) {
3756		return TRUE;
3757	}
3758    }
3759    return FALSE;
3760}
3761
3762/**************** end of autoprobe stuff *****************/
3763
3764
3765
3766ModuleInfoRec MouseInfo = {
3767    1,
3768    "MOUSE",
3769    NULL,
3770    0,
3771    MouseAvailableOptions,
3772};
3773
3774static void
3775xf86MouseUnplug(pointer	p)
3776{
3777}
3778static pointer
3779xf86MousePlug(pointer	module,
3780	    pointer	options,
3781	    int		*errmaj,
3782	    int		*errmin)
3783{
3784    static Bool Initialised = FALSE;
3785
3786    if (!Initialised)
3787	Initialised = TRUE;
3788
3789    xf86AddInputDriver(&MOUSE, module, 0);
3790
3791    return module;
3792}
3793
3794static XF86ModuleVersionInfo xf86MouseVersionRec =
3795{
3796    "mouse",
3797    MODULEVENDORSTRING,
3798    MODINFOSTRING1,
3799    MODINFOSTRING2,
3800    XORG_VERSION_CURRENT,
3801    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
3802    ABI_CLASS_XINPUT,
3803    ABI_XINPUT_VERSION,
3804    MOD_CLASS_XINPUT,
3805    {0, 0, 0, 0}		/* signature, to be patched into the file by */
3806				/* a tool */
3807};
3808
3809_X_EXPORT XF86ModuleData mouseModuleData = {
3810    &xf86MouseVersionRec,
3811    xf86MousePlug,
3812    xf86MouseUnplug
3813};
3814
3815/*
3816  Look at hitachi device stuff.
3817*/
3818