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