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