mouse.c revision 751d7a2a
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    if (osInfo->SetupMouse)
2543	if (!osInfo->SetupMouse(pInfo))
2544	    return FALSE;
2545
2546    /* Handle the "Auto" protocol. */
2547    if (pMse->protocolID == PROT_AUTO) {
2548	/*
2549	 * We come here when user specifies protocol "auto" in
2550	 * the configuration file or thru the xf86misc extensions.
2551	 * So we initialize autoprobing here.
2552	 * Probe for PnP/OS mouse first. If unsuccessful
2553	 * try to guess protocol from incoming data.
2554	 */
2555	automatic = TRUE;
2556	pMse->autoProbe = TRUE;
2557	name = autoOSProtocol(pInfo,protoPara);
2558	if (name)  {
2559#ifdef EXTMOUSEDEBUG
2560	    ErrorF("PnP/OS Mouse detected: %s\n",name);
2561#endif
2562	}
2563    }
2564
2565    SetMouseProto(pMse, pMse->protocolID);
2566
2567    if (automatic) {
2568	if (name) {
2569	    /* Possible protoPara overrides from SetupAuto. */
2570	    for (i = 0; i < sizeof(pMse->protoPara); i++)
2571		if (protoPara[i] != -1)
2572		    pMse->protoPara[i] = protoPara[i];
2573	    /* if we come here PnP/OS mouse probing was successful */
2574	} else {
2575#if 1
2576	    /* PnP/OS mouse probing wasn't successful; we look at data */
2577#else
2578  	    xf86Msg(X_ERROR, "%s: cannot determine the mouse protocol\n",
2579		    pInfo->name);
2580	    return FALSE;
2581#endif
2582	}
2583    }
2584
2585    /*
2586     * If protocol has changed fetch the default options
2587     * for the new protocol.
2588     */
2589    if (pMse->oldProtocolID != pMse->protocolID) {
2590	pointer tmp = NULL;
2591	if ((pMse->protocolID >= 0)
2592	    && (pMse->protocolID < PROT_NUMPROTOS)
2593	    && mouseProtocols[pMse->protocolID].defaults)
2594	    tmp = xf86OptionListCreate(
2595		mouseProtocols[pMse->protocolID].defaults, -1, 0);
2596	pInfo->options = xf86OptionListMerge(pInfo->options, tmp);
2597	/*
2598	 * If baudrate is set write it back to the option
2599	 * list so that the serial interface code can access
2600	 * the new value. Not set means default.
2601	 */
2602	if (pMse->baudRate)
2603	    xf86ReplaceIntOption(pInfo->options, "BaudRate", pMse->baudRate);
2604	pMse->oldProtocolID = pMse->protocolID; /* hack */
2605    }
2606
2607
2608    /* Set the port parameters. */
2609    if (!automatic)
2610	xf86SetSerial(pInfo->fd, pInfo->options);
2611
2612    if (!initMouseHW(pInfo))
2613	return FALSE;
2614
2615    pMse->protoBufTail = 0;
2616    pMse->inSync = 0;
2617
2618    return TRUE;
2619}
2620
2621/********************************************************************
2622 *
2623 * Mouse HW setup code
2624 *
2625 ********************************************************************/
2626
2627/*
2628** The following lines take care of the Logitech MouseMan protocols.
2629** The "Logitech" protocol is for the old "series 9" Logitech products.
2630** All products since then use the "MouseMan" protocol.  Some models
2631** were programmable, but most (all?) of the current models are not.
2632**
2633** NOTE: There are different versions of both MouseMan and TrackMan!
2634**       Hence I add another protocol PROT_LOGIMAN, which the user can
2635**       specify as MouseMan in his XF86Config file. This entry was
2636**       formerly handled as a special case of PROT_MS. However, people
2637**       who don't have the middle button problem, can still specify
2638**       Microsoft and use PROT_MS.
2639**
2640** By default, these mice should use a 3 byte Microsoft protocol
2641** plus a 4th byte for the middle button. However, the mouse might
2642** have switched to a different protocol before we use it, so I send
2643** the proper sequence just in case.
2644**
2645** NOTE: - all commands to (at least the European) MouseMan have to
2646**         be sent at 1200 Baud.
2647**       - each command starts with a '*'.
2648**       - whenever the MouseMan receives a '*', it will switch back
2649**	 to 1200 Baud. Hence I have to select the desired protocol
2650**	 first, then select the baud rate.
2651**
2652** The protocols supported by the (European) MouseMan are:
2653**   -  5 byte packed binary protocol, as with the Mouse Systems
2654**      mouse. Selected by sequence "*U".
2655**   -  2 button 3 byte MicroSoft compatible protocol. Selected
2656**      by sequence "*V".
2657**   -  3 button 3+1 byte MicroSoft compatible protocol (default).
2658**      Selected by sequence "*X".
2659**
2660** The following baud rates are supported:
2661**   -  1200 Baud (default). Selected by sequence "*n".
2662**   -  9600 Baud. Selected by sequence "*q".
2663**
2664** Selecting a sample rate is no longer supported with the MouseMan!
2665**               [CHRIS-211092]
2666*/
2667
2668/*
2669 * Do a reset wrap mode before reset.
2670 */
2671#define do_ps2Reset(x)  { \
2672    int i = RETRY_COUNT;\
2673     while (i-- > 0) { \
2674       xf86FlushInput(x->fd); \
2675       if (ps2Reset(x)) break; \
2676    } \
2677  }
2678
2679
2680static Bool
2681initMouseHW(InputInfoPtr pInfo)
2682{
2683    MouseDevPtr pMse = pInfo->private;
2684    const char *s;
2685    unsigned char c;
2686    int speed;
2687    pointer options;
2688    unsigned char *param = NULL;
2689    int paramlen = 0;
2690    int count = RETRY_COUNT;
2691    Bool ps2Init = TRUE;
2692
2693    switch (pMse->protocolID) {
2694	case PROT_LOGI:		/* Logitech Mice */
2695	    /*
2696	     * The baud rate selection command must be sent at the current
2697	     * baud rate; try all likely settings.
2698	     */
2699	    speed = pMse->baudRate;
2700	    switch (speed) {
2701		case 9600:
2702		    s = "*q";
2703		    break;
2704		case 4800:
2705		    s = "*p";
2706		    break;
2707		case 2400:
2708		    s = "*o";
2709		    break;
2710		case 1200:
2711		    s = "*n";
2712		    break;
2713		default:
2714		    /* Fallback value */
2715		    speed = 1200;
2716		    s = "*n";
2717	    }
2718	    xf86SetSerialSpeed(pInfo->fd, 9600);
2719	    xf86WriteSerial(pInfo->fd, s, 2);
2720	    usleep(100000);
2721	    xf86SetSerialSpeed(pInfo->fd, 4800);
2722	    xf86WriteSerial(pInfo->fd, s, 2);
2723	    usleep(100000);
2724	    xf86SetSerialSpeed(pInfo->fd, 2400);
2725	    xf86WriteSerial(pInfo->fd, s, 2);
2726	    usleep(100000);
2727	    xf86SetSerialSpeed(pInfo->fd, 1200);
2728	    xf86WriteSerial(pInfo->fd, s, 2);
2729	    usleep(100000);
2730	    xf86SetSerialSpeed(pInfo->fd, speed);
2731
2732	    /* Select MM series data format. */
2733	    xf86WriteSerial(pInfo->fd, "S", 1);
2734	    usleep(100000);
2735	    /* Set the parameters up for the MM series protocol. */
2736	    options = pInfo->options;
2737	    xf86CollectInputOptions(pInfo, mmDefaults, NULL);
2738	    xf86SetSerial(pInfo->fd, pInfo->options);
2739	    pInfo->options = options;
2740
2741	    /* Select report rate/frequency. */
2742	    if      (pMse->sampleRate <=   0)  c = 'O';  /* 100 */
2743	    else if (pMse->sampleRate <=  15)  c = 'J';  /*  10 */
2744	    else if (pMse->sampleRate <=  27)  c = 'K';  /*  20 */
2745	    else if (pMse->sampleRate <=  42)  c = 'L';  /*  35 */
2746	    else if (pMse->sampleRate <=  60)  c = 'R';  /*  50 */
2747	    else if (pMse->sampleRate <=  85)  c = 'M';  /*  67 */
2748	    else if (pMse->sampleRate <= 125)  c = 'Q';  /* 100 */
2749	    else                               c = 'N';  /* 150 */
2750	    xf86WriteSerial(pInfo->fd, &c, 1);
2751	    break;
2752
2753	case PROT_LOGIMAN:
2754	    speed = pMse->baudRate;
2755	    switch (speed) {
2756		case 9600:
2757		    s = "*q";
2758		    break;
2759		case 1200:
2760		    s = "*n";
2761		    break;
2762		default:
2763		    /* Fallback value */
2764		    speed = 1200;
2765		    s = "*n";
2766	    }
2767	    xf86SetSerialSpeed(pInfo->fd, 1200);
2768	    xf86WriteSerial(pInfo->fd, "*n", 2);
2769	    xf86WriteSerial(pInfo->fd, "*X", 2);
2770	    xf86WriteSerial(pInfo->fd, s, 2);
2771	    usleep(100000);
2772	    xf86SetSerialSpeed(pInfo->fd, speed);
2773	    break;
2774
2775	case PROT_MMHIT:		/* MM_HitTablet */
2776	    /*
2777	     * Initialize Hitachi PUMA Plus - Model 1212E to desired settings.
2778	     * The tablet must be configured to be in MM mode, NO parity,
2779	     * Binary Format.  pMse->sampleRate controls the sensitivity
2780	     * of the tablet.  We only use this tablet for it's 4-button puck
2781	     * so we don't run in "Absolute Mode".
2782	     */
2783	    xf86WriteSerial(pInfo->fd, "z8", 2);	/* Set Parity = "NONE" */
2784	    usleep(50000);
2785	    xf86WriteSerial(pInfo->fd, "zb", 2);	/* Set Format = "Binary" */
2786	    usleep(50000);
2787	    xf86WriteSerial(pInfo->fd, "@", 1);	/* Set Report Mode = "Stream" */
2788	    usleep(50000);
2789	    xf86WriteSerial(pInfo->fd, "R", 1);	/* Set Output Rate = "45 rps" */
2790	    usleep(50000);
2791	    xf86WriteSerial(pInfo->fd, "I\x20", 2);	/* Set Incrememtal Mode "20" */
2792	    usleep(50000);
2793	    xf86WriteSerial(pInfo->fd, "E", 1);	/* Set Data Type = "Relative */
2794	    usleep(50000);
2795	    /*
2796	     * These sample rates translate to 'lines per inch' on the Hitachi
2797	     * tablet.
2798	     */
2799	    if      (pMse->sampleRate <=   40) c = 'g';
2800	    else if (pMse->sampleRate <=  100) c = 'd';
2801	    else if (pMse->sampleRate <=  200) c = 'e';
2802	    else if (pMse->sampleRate <=  500) c = 'h';
2803	    else if (pMse->sampleRate <= 1000) c = 'j';
2804	    else                               c = 'd';
2805	    xf86WriteSerial(pInfo->fd, &c, 1);
2806	    usleep(50000);
2807	    xf86WriteSerial(pInfo->fd, "\021", 1);	/* Resume DATA output */
2808	    break;
2809
2810	case PROT_THINKING:		/* ThinkingMouse */
2811	    /* This mouse may send a PnP ID string, ignore it. */
2812	    usleep(200000);
2813	    xf86FlushInput(pInfo->fd);
2814	    /* Send the command to initialize the beast. */
2815	    for (s = "E5E5"; *s; ++s) {
2816		xf86WriteSerial(pInfo->fd, s, 1);
2817		if ((xf86WaitForInput(pInfo->fd, 1000000) <= 0))
2818		    break;
2819		xf86ReadSerial(pInfo->fd, &c, 1);
2820		if (c != *s)
2821		    break;
2822	    }
2823	    break;
2824
2825	case PROT_MSC:		/* MouseSystems Corp */
2826	    usleep(100000);
2827	    xf86FlushInput(pInfo->fd);
2828	    break;
2829
2830	case PROT_ACECAD:
2831	    /* initialize */
2832	    /* A nul character resets. */
2833	    xf86WriteSerial(pInfo->fd, "", 1);
2834	    usleep(50000);
2835	    /* Stream out relative mode high resolution increments of 1. */
2836	    xf86WriteSerial(pInfo->fd, "@EeI!", 5);
2837	    break;
2838
2839	case PROT_BM:		/* bus/InPort mouse */
2840	    if (osInfo->SetBMRes)
2841		osInfo->SetBMRes(pInfo, pMse->protocol, pMse->sampleRate,
2842				 pMse->resolution);
2843	    break;
2844
2845	case PROT_GENPS2:
2846	    ps2Init = FALSE;
2847	    break;
2848
2849	case PROT_PS2:
2850	case PROT_GLIDEPS2:
2851	    break;
2852
2853	case PROT_IMPS2:		/* IntelliMouse */
2854	{
2855	    static unsigned char seq[] = { 243, 200, 243, 100, 243, 80 };
2856	    param = seq;
2857	    paramlen = sizeof(seq);
2858	}
2859	break;
2860
2861	case PROT_EXPPS2:		/* IntelliMouse Explorer */
2862	{
2863	    static unsigned char seq[] = { 243, 200, 243, 100, 243, 80,
2864					   243, 200, 243, 200, 243, 80 };
2865
2866	    param = seq;
2867	    paramlen = sizeof(seq);
2868	}
2869	break;
2870
2871	case PROT_NETPS2:		/* NetMouse, NetMouse Pro, Mie Mouse */
2872	case PROT_NETSCPS2:		/* NetScroll */
2873	{
2874	    static unsigned char seq[] = { 232, 3, 230, 230, 230, 233 };
2875
2876	    param = seq;
2877	    paramlen = sizeof(seq);
2878	}
2879	break;
2880
2881	case PROT_MMPS2:		/* MouseMan+, FirstMouse+ */
2882	{
2883	    static unsigned char seq[] = { 230, 232, 0, 232, 3, 232, 2, 232, 1,
2884					   230, 232, 3, 232, 1, 232, 2, 232, 3 };
2885	    param = seq;
2886	    paramlen = sizeof(seq);
2887	}
2888	break;
2889
2890	case PROT_THINKPS2:		/* ThinkingMouse */
2891	{
2892	    static unsigned char seq[] = { 243, 10, 232,  0, 243, 20, 243, 60,
2893					   243, 40, 243, 20, 243, 20, 243, 60,
2894					   243, 40, 243, 20, 243, 20 };
2895	    param = seq;
2896	    paramlen = sizeof(seq);
2897	}
2898	break;
2899	case PROT_SYSMOUSE:
2900	    if (osInfo->SetMiscRes)
2901		osInfo->SetMiscRes(pInfo, pMse->protocol, pMse->sampleRate,
2902				   pMse->resolution);
2903	    break;
2904
2905	default:
2906	    /* Nothing to do. */
2907	    break;
2908    }
2909
2910    if (pMse->class & (MSE_PS2 | MSE_XPS2)) {
2911	/*
2912	 * If one part of the PS/2 mouse initialization fails
2913	 * redo complete initialization. There are mice which
2914	 * have occasional problems with initialization and
2915	 * are in an unknown state.
2916	 */
2917	if (ps2Init) {
2918	REDO:
2919	    do_ps2Reset(pInfo);
2920	    if (paramlen > 0) {
2921		if (!ps2SendPacket(pInfo,param,paramlen)) {
2922		    usleep(30000);
2923		    xf86FlushInput(pInfo->fd);
2924		    if (!count--)
2925			return TRUE;
2926		    goto REDO;
2927		}
2928		ps2GetDeviceID(pInfo);
2929		usleep(30000);
2930		xf86FlushInput(pInfo->fd);
2931	    }
2932
2933	    if (osInfo->SetPS2Res) {
2934		osInfo->SetPS2Res(pInfo, pMse->protocol, pMse->sampleRate,
2935				  pMse->resolution);
2936	    } else {
2937		unsigned char c2[2];
2938
2939		c = 0xE6;	/*230*/	/* 1:1 scaling */
2940		if (!ps2SendPacket(pInfo,&c,1)) {
2941		    if (!count--)
2942			return TRUE;
2943		    goto REDO;
2944		}
2945		c2[0] = 0xF3; /*243*/ /* set sampling rate */
2946		if (pMse->sampleRate > 0) {
2947		    if (pMse->sampleRate >= 200)
2948			c2[1] = 200;
2949		    else if (pMse->sampleRate >= 100)
2950			c2[1] = 100;
2951		    else if (pMse->sampleRate >= 80)
2952			c2[1] = 80;
2953		    else if (pMse->sampleRate >= 60)
2954			c2[1] = 60;
2955		    else if (pMse->sampleRate >= 40)
2956			c2[1] = 40;
2957		    else
2958			c2[1] = 20;
2959		} else {
2960		    c2[1] = 100;
2961		}
2962		if (!ps2SendPacket(pInfo,c2,2)) {
2963		    if (!count--)
2964			return TRUE;
2965		    goto REDO;
2966		}
2967		c2[0] = 0xE8; /*232*/	/* set device resolution */
2968		if (pMse->resolution > 0) {
2969		    if (pMse->resolution >= 200)
2970			c2[1] = 3;
2971		    else if (pMse->resolution >= 100)
2972			c2[1] = 2;
2973		    else if (pMse->resolution >= 50)
2974			c2[1] = 1;
2975		    else
2976			c2[1] = 0;
2977		} else {
2978		    c2[1] = 3; /* used to be 2, W. uses 3 */
2979		}
2980		if (!ps2SendPacket(pInfo,c2,2)) {
2981		    if (!count--)
2982			return TRUE;
2983		    goto REDO;
2984		}
2985		usleep(30000);
2986		xf86FlushInput(pInfo->fd);
2987		if (!ps2EnableDataReporting(pInfo)) {
2988		    xf86Msg(X_INFO, "%s: ps2EnableDataReporting: failed\n",
2989			    pInfo->name);
2990		    xf86FlushInput(pInfo->fd);
2991		    if (!count--)
2992			return TRUE;
2993		    goto REDO;
2994		} else {
2995		    xf86Msg(X_INFO, "%s: ps2EnableDataReporting: succeeded\n",
2996			    pInfo->name);
2997		}
2998	    }
2999	    /*
3000	     * The PS/2 reset handling needs to be rechecked.
3001	     * We need to wait until after the 4.3 release.
3002	     */
3003	}
3004    } else {
3005	if (paramlen > 0) {
3006	    if (xf86WriteSerial(pInfo->fd, param, paramlen) != paramlen)
3007		xf86Msg(X_ERROR, "%s: Mouse initialization failed\n",
3008			pInfo->name);
3009	    usleep(30000);
3010	    xf86FlushInput(pInfo->fd);
3011	}
3012    }
3013
3014    return TRUE;
3015}
3016
3017#ifdef SUPPORT_MOUSE_RESET
3018static Bool
3019mouseReset(InputInfoPtr pInfo, unsigned char val)
3020{
3021    MouseDevPtr pMse = pInfo->private;
3022    mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv;
3023    CARD32 prevEvent = mousepriv->lastEvent;
3024    Bool expectReset = FALSE;
3025    Bool ret = FALSE;
3026
3027    mousepriv->lastEvent = GetTimeInMillis();
3028
3029#ifdef EXTMOUSEDEBUG
3030    ErrorF("byte: 0x%x time: %li\n",val,mousepriv->lastEvent);
3031#endif
3032    /*
3033     * We believe that the following is true:
3034     * When the mouse is replugged it will send a reset package
3035     * It takes several seconds to replug a mouse: We don't see
3036     * events for several seconds before we see the replug event package.
3037     * There is no significant delay between consecutive bytes
3038     * of a replug event package.
3039     * There are no bytes sent after the replug event package until
3040     * the mouse is reset.
3041     */
3042
3043    if (mousepriv->current == 0
3044	&& (mousepriv->lastEvent - prevEvent) < 4000)
3045	return FALSE;
3046
3047    if (mousepriv->current > 0
3048	&& (mousepriv->lastEvent - prevEvent) >= 1000) {
3049	mousepriv->inReset = FALSE;
3050	mousepriv->current = 0;
3051	return FALSE;
3052    }
3053
3054    if (mousepriv->inReset)
3055	mousepriv->inReset = FALSE;
3056
3057#ifdef EXTMOUSEDEBUG
3058    ErrorF("Mouse Current: %i 0x%x\n",mousepriv->current, val);
3059#endif
3060
3061    /* here we put the mouse specific reset detction */
3062    /* They need to do three things:                 */
3063    /*  Check if byte may be a reset byte            */
3064    /*  If so: Set expectReset TRUE                  */
3065    /*  If convinced: Set inReset TRUE               */
3066    /*                Register BlockAndWakeupHandler */
3067
3068    /* PS/2 */
3069    {
3070	unsigned char seq[] = { 0xaa, 0x00 };
3071	int len = sizeof(seq);
3072
3073	if (seq[mousepriv->current] == val)
3074	    expectReset = TRUE;
3075
3076	if (len == mousepriv->current + 1) {
3077	    mousepriv->inReset = TRUE;
3078	    mousepriv->expires = GetTimeInMillis() + 1000;
3079
3080#ifdef EXTMOUSEDEBUG
3081	    ErrorF("Found PS/2 Reset string\n");
3082#endif
3083	    RegisterBlockAndWakeupHandlers (ps2BlockHandler,
3084					    ps2WakeupHandler, (pointer) pInfo);
3085	    ret = TRUE;
3086	}
3087    }
3088
3089	if (!expectReset)
3090	    mousepriv->current = 0;
3091	else
3092	    mousepriv->current++;
3093	return ret;
3094}
3095
3096static void
3097ps2BlockHandler(pointer data, struct timeval **waitTime,
3098		pointer LastSelectMask)
3099{
3100    InputInfoPtr    pInfo = (InputInfoPtr) data;
3101    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
3102    mousePrivPtr    mousepriv = (mousePrivPtr)pMse->mousePriv;
3103    int		    ms;
3104
3105    if (mousepriv->inReset) {
3106	ms = mousepriv->expires - GetTimeInMillis ();
3107	if (ms <= 0)
3108	    ms = 0;
3109	AdjustWaitForDelay (waitTime, ms);
3110    } else
3111	RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler,
3112				      (pointer) pInfo);
3113}
3114
3115static void
3116ps2WakeupHandler(pointer data, int i, pointer LastSelectMask)
3117{
3118    InputInfoPtr    pInfo = (InputInfoPtr) data;
3119    MouseDevPtr	    pMse = (MouseDevPtr) pInfo->private;
3120    mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv;
3121    int		    ms;
3122
3123    if (mousepriv->inReset) {
3124	unsigned char val;
3125	int blocked;
3126
3127	ms = mousepriv->expires - GetTimeInMillis();
3128	if (ms > 0)
3129	    return;
3130
3131	blocked = xf86BlockSIGIO ();
3132
3133	xf86MsgVerb(X_INFO,3,
3134		    "Got reinsert event: reinitializing PS/2 mouse\n");
3135	val = 0xf4;
3136	if (xf86WriteSerial(pInfo->fd, &val, 1) != 1)
3137	    xf86Msg(X_ERROR, "%s: Write to mouse failed\n",
3138		    pInfo->name);
3139	xf86UnblockSIGIO(blocked);
3140    }
3141    RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler,
3142				  (pointer) pInfo);
3143}
3144#endif /* SUPPORT_MOUSE_RESET */
3145
3146/************************************************************
3147 *
3148 * Autoprobe stuff
3149 *
3150 ************************************************************/
3151#ifdef EXTMOUSEDEBUG
3152#  define AP_DBG(x) { ErrorF("Autoprobe: "); ErrorF x; }
3153#  define AP_DBGC(x) ErrorF x ;
3154# else
3155#  define AP_DBG(x)
3156#  define AP_DBGC(x)
3157#endif
3158
3159MouseProtocolID hardProtocolList[] = { 	PROT_MSC, PROT_MM, PROT_LOGI,
3160					PROT_LOGIMAN, PROT_MMHIT,
3161					PROT_GLIDE, PROT_IMSERIAL,
3162					PROT_THINKING, PROT_ACECAD,
3163					PROT_THINKPS2, PROT_MMPS2,
3164					PROT_GLIDEPS2,
3165					PROT_NETSCPS2, PROT_EXPPS2,PROT_IMPS2,
3166					PROT_GENPS2, PROT_NETPS2,
3167					PROT_MS,
3168					PROT_UNKNOWN
3169};
3170
3171MouseProtocolID softProtocolList[] = { 	PROT_MSC, PROT_MM, PROT_LOGI,
3172					PROT_LOGIMAN, PROT_MMHIT,
3173					PROT_GLIDE, PROT_IMSERIAL,
3174					PROT_THINKING, PROT_ACECAD,
3175					PROT_THINKPS2, PROT_MMPS2,
3176					PROT_GLIDEPS2,
3177					PROT_NETSCPS2 ,PROT_IMPS2,
3178					PROT_GENPS2,
3179					PROT_MS,
3180					PROT_UNKNOWN
3181};
3182
3183static const char *
3184autoOSProtocol(InputInfoPtr pInfo, int *protoPara)
3185{
3186    MouseDevPtr pMse = pInfo->private;
3187    const char *name = NULL;
3188    MouseProtocolID protocolID = PROT_UNKNOWN;
3189
3190    /* Check if the OS has a detection mechanism. */
3191    if (osInfo->SetupAuto) {
3192	name = osInfo->SetupAuto(pInfo, protoPara);
3193	if (name) {
3194	    protocolID = ProtocolNameToID(name);
3195	    switch (protocolID) {
3196		case PROT_UNKNOWN:
3197		    /* Check for a builtin OS-specific protocol. */
3198		    if (osInfo->CheckProtocol && osInfo->CheckProtocol(name)) {
3199			/* We can only come here if the protocol has been
3200			 * changed to auto thru the xf86misc extension
3201			 * and we have detected an OS specific builtin
3202			 * protocol. Currently we cannot handle this */
3203			name = NULL;
3204		    } else
3205			name = NULL;
3206		    break;
3207		case PROT_UNSUP:
3208		    name = NULL;
3209		    break;
3210		default:
3211		    break;
3212	    }
3213	}
3214    }
3215    if (!name) {
3216	/* A PnP serial mouse? */
3217	protocolID = MouseGetPnpProtocol(pInfo);
3218	if (protocolID >= 0 && protocolID < PROT_NUMPROTOS) {
3219	    name = ProtocolIDToName(protocolID);
3220	    xf86Msg(X_PROBED, "%s: PnP-detected protocol: \"%s\"\n",
3221		    pInfo->name, name);
3222	}
3223    }
3224    if (!name && HAVE_GUESS_PROTOCOL && osInfo->GuessProtocol) {
3225	name = osInfo->GuessProtocol(pInfo, 0);
3226	if (name)
3227	    protocolID = ProtocolNameToID(name);
3228    }
3229
3230    if (name) {
3231	pMse->protocolID = protocolID;
3232    }
3233
3234    return name;
3235}
3236
3237/*
3238 * createProtocolList() -- create a list of protocols which may
3239 * match on the incoming data stream.
3240 */
3241static void
3242createProtoList(MouseDevPtr pMse, MouseProtocolID *protoList)
3243{
3244    int i, j, k  = 0;
3245    MouseProtocolID prot;
3246    unsigned char *para;
3247    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3248    MouseProtocolID *tmplist = NULL;
3249    int blocked;
3250
3251    AP_DBGC(("Autoprobe: "));
3252    for (i = 0; i < mPriv->count; i++)
3253	AP_DBGC(("%2.2x ", (unsigned char) mPriv->data[i]));
3254    AP_DBGC(("\n"));
3255
3256    blocked = xf86BlockSIGIO ();
3257
3258    /* create a private copy first so we can write in the old list */
3259    if ((tmplist = xalloc(sizeof(MouseProtocolID) * NUM_AUTOPROBE_PROTOS))){
3260	for (i = 0; protoList[i] != PROT_UNKNOWN; i++) {
3261	    tmplist[i] = protoList[i];
3262	}
3263	tmplist[i] = PROT_UNKNOWN;
3264	protoList = tmplist;
3265    } else
3266	return;
3267
3268    for (i = 0; ((prot = protoList[i]) != PROT_UNKNOWN
3269		 && (k < NUM_AUTOPROBE_PROTOS - 1)) ; i++) {
3270	Bool bad = TRUE;
3271	unsigned char byte = 0;
3272	int count = 0;
3273	int next_header_candidate = 0;
3274	int header_count = 0;
3275
3276	if (!GetProtocol(prot))
3277	    continue;
3278	para = proto[prot];
3279
3280	AP_DBG(("Protocol: %s ", ProtocolIDToName(prot)));
3281
3282#ifdef EXTMOUSEDEBUG
3283	for (j = 0; j < 7; j++)
3284	    AP_DBGC(("%2.2x ", (unsigned char) para[j]));
3285	AP_DBGC(("\n"));
3286#endif
3287	j = 0;
3288	while (1) {
3289	    /* look for header */
3290	    while (j < mPriv->count) {
3291		if (((byte = mPriv->data[j++]) & para[0]) == para[1]){
3292		    AP_DBG(("found header %2.2x\n",byte));
3293		    next_header_candidate = j;
3294		    count = 1;
3295		    break;
3296		} else {
3297		    /*
3298		     * Bail ot if number of bytes per package have
3299		     * been tested for header.
3300		     * Take bytes per package of leading garbage into
3301		     * account.
3302		     */
3303		    if (j > para[4] && ++header_count > para[4]) {
3304			j = mPriv->count;
3305			break;
3306		    }
3307		}
3308	    }
3309	    /* check if remaining data matches protocol */
3310	    while (j < mPriv->count) {
3311		byte = mPriv->data[j++];
3312		if (count == para[4]) {
3313		    count = 0;
3314		    /* check and eat excess byte */
3315		    if (((byte & para[0]) != para[1])
3316			&& ((byte & para[5]) == para[6])) {
3317			AP_DBG(("excess byte found\n"));
3318			continue;
3319		    }
3320		}
3321		if (count == 0) {
3322		    /* validate next header */
3323		    bad = FALSE;
3324		    AP_DBG(("Complete set found\n"));
3325		    if ((byte & para[0]) != para[1]) {
3326			AP_DBG(("Autoprobe: header bad\n"));
3327			bad = TRUE;
3328			break;
3329		    } else {
3330			count++;
3331			continue;
3332		    }
3333		}
3334		/* validate data */
3335		else if (((byte & para[2]) != para[3])
3336			 || ((para[7] & MPF_SAFE)
3337			     && ((byte & para[0]) == para[1]))) {
3338		    AP_DBG(("data bad\n"));
3339		    bad = TRUE;
3340		    break;
3341		} else {
3342		    count ++;
3343		    continue;
3344		}
3345	    }
3346	    if (!bad) {
3347		/* this is a matching protocol */
3348		mPriv->protoList[k++] = prot;
3349		AP_DBG(("Autoprobe: Adding protocol %s to list (entry %i)\n",
3350			ProtocolIDToName(prot),k-1));
3351		break;
3352	    }
3353	    j = next_header_candidate;
3354	    next_header_candidate = 0;
3355	    /* we have tested number of bytes per package for header */
3356	    if (j > para[4] && ++header_count > para[4])
3357		break;
3358	    /* we have not found anything that looks like a header */
3359	    if (!next_header_candidate)
3360		break;
3361	    AP_DBG(("Looking for new header\n"));
3362	}
3363    }
3364
3365    xf86UnblockSIGIO(blocked);
3366
3367    mPriv->protoList[k] = PROT_UNKNOWN;
3368
3369    xfree(tmplist);
3370}
3371
3372
3373/* This only needs to be done once */
3374void **serialDefaultsList = NULL;
3375
3376/*
3377 * createSerialDefaultsLists() - create a list of the different default
3378 * settings for the serial interface of the known protocols.
3379 */
3380static void
3381createSerialDefaultsList(void)
3382{
3383    int i = 0, j, k;
3384
3385    serialDefaultsList = (void **)xnfalloc(sizeof(void*));
3386    serialDefaultsList[0] = NULL;
3387
3388    for (j = 0; mouseProtocols[j].name; j++) {
3389	if (!mouseProtocols[j].defaults)
3390	    continue;
3391	for (k = 0; k < i; k++)
3392	    if (mouseProtocols[j].defaults == serialDefaultsList[k])
3393		continue;
3394	i++;
3395	serialDefaultsList = (void**)xnfrealloc(serialDefaultsList,
3396						sizeof(void*)*(i+1));
3397	serialDefaultsList[i-1] = mouseProtocols[j].defaults;
3398	serialDefaultsList[i] = NULL;
3399    }
3400}
3401
3402typedef enum {
3403    STATE_INVALID,
3404    STATE_UNCERTAIN,
3405    STATE_VALID
3406} validState;
3407
3408/* Probing threshold values */
3409#define PROBE_UNCERTAINTY 50
3410#define BAD_CERTAINTY 6
3411#define BAD_INC_CERTAINTY 1
3412#define BAD_INC_CERTAINTY_WHEN_SYNC_LOST 2
3413
3414static validState
3415validCount(mousePrivPtr mPriv, Bool inSync, Bool lostSync)
3416{
3417    if (inSync) {
3418	if (!--mPriv->goodCount) {
3419	    /* we are sure to have found the correct protocol */
3420	    mPriv->badCount = 0;
3421	    return STATE_VALID;
3422	}
3423	AP_DBG(("%i successful rounds to go\n",
3424		mPriv->goodCount));
3425	return STATE_UNCERTAIN;
3426    }
3427
3428
3429    /* We are out of sync again */
3430    mPriv->goodCount = PROBE_UNCERTAINTY;
3431    /* We increase uncertainty of having the correct protocol */
3432    mPriv->badCount+= lostSync ? BAD_INC_CERTAINTY_WHEN_SYNC_LOST
3433	: BAD_INC_CERTAINTY;
3434
3435    if (mPriv->badCount < BAD_CERTAINTY) {
3436	/* We are not convinced yet to have the wrong protocol */
3437	AP_DBG(("Changing protocol after: %i rounds\n",
3438		BAD_CERTAINTY - mPriv->badCount));
3439	return STATE_UNCERTAIN;
3440    }
3441    return STATE_INVALID;
3442}
3443
3444#define RESET_VALIDATION	mPriv->goodCount = PROBE_UNCERTAINTY;\
3445				mPriv->badCount = 0;\
3446				mPriv->prevDx = 0;\
3447				mPriv->prevDy = 0;\
3448				mPriv->accDx = 0;\
3449				mPriv->accDy = 0;\
3450				mPriv->acc = 0;
3451
3452static void
3453autoProbeMouse(InputInfoPtr pInfo, Bool inSync, Bool lostSync)
3454{
3455    MouseDevPtr pMse = pInfo->private;
3456    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3457
3458    MouseProtocolID *protocolList = NULL;
3459
3460    while (1) {
3461	switch (mPriv->autoState) {
3462	case AUTOPROBE_GOOD:
3463 	    if (inSync)
3464		return;
3465	    AP_DBG(("State GOOD\n"));
3466	    RESET_VALIDATION;
3467	    mPriv->autoState = AUTOPROBE_VALIDATE1;
3468	    return;
3469	case AUTOPROBE_H_GOOD:
3470	    if (inSync)
3471		return;
3472	    AP_DBG(("State H_GOOD\n"));
3473	    RESET_VALIDATION;
3474	    mPriv->autoState = AUTOPROBE_H_VALIDATE2;
3475	    return;
3476	case AUTOPROBE_H_NOPROTO:
3477	    AP_DBG(("State H_NOPROTO\n"));
3478	    mPriv->protocolID = 0;
3479	    mPriv->autoState = AUTOPROBE_H_SETPROTO;
3480	    break;
3481	case AUTOPROBE_H_SETPROTO:
3482	    AP_DBG(("State H_SETPROTO\n"));
3483	    if ((pMse->protocolID = hardProtocolList[mPriv->protocolID++])
3484		== PROT_UNKNOWN) {
3485		mPriv->protocolID = 0;
3486		break;
3487	    } else if (GetProtocol(pMse->protocolID) &&  SetupMouse(pInfo)) {
3488		FlushButtons(pMse);
3489		RESET_VALIDATION;
3490		AP_DBG(("Autoprobe: Trying Protocol: %s\n",
3491			ProtocolIDToName(pMse->protocolID)));
3492		mPriv->autoState = AUTOPROBE_H_VALIDATE1;
3493		return;
3494	    }
3495	    break;
3496	case AUTOPROBE_H_VALIDATE1:
3497	    AP_DBG(("State H_VALIDATE1\n"));
3498	    switch (validCount(mPriv,inSync,lostSync)) {
3499	    case STATE_INVALID:
3500		mPriv->autoState = AUTOPROBE_H_SETPROTO;
3501		break;
3502	    case STATE_VALID:
3503		    xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3504			    ProtocolIDToName(pMse->protocolID));
3505		    mPriv->autoState = AUTOPROBE_H_GOOD;
3506		    return;
3507	    case STATE_UNCERTAIN:
3508		return;
3509	    default:
3510		break;
3511	    }
3512	    break;
3513	case AUTOPROBE_H_VALIDATE2:
3514	    AP_DBG(("State H_VALIDATE2\n"));
3515	    switch (validCount(mPriv,inSync,lostSync)) {
3516	    case STATE_INVALID:
3517		mPriv->autoState = AUTOPROBE_H_AUTODETECT;
3518		break;
3519	    case STATE_VALID:
3520		xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3521			ProtocolIDToName(pMse->protocolID));
3522		mPriv->autoState = AUTOPROBE_H_GOOD;
3523		return;
3524	    case STATE_UNCERTAIN:
3525		return;
3526	    }
3527	    break;
3528	case AUTOPROBE_H_AUTODETECT:
3529	    AP_DBG(("State H_AUTODETECT\n"));
3530	    pMse->protocolID = PROT_AUTO;
3531	    AP_DBG(("Looking for PnP/OS mouse\n"));
3532	    mPriv->count = 0;
3533	    SetupMouse(pInfo);
3534	    if (pMse->protocolID != PROT_AUTO)
3535		mPriv->autoState = AUTOPROBE_H_GOOD;
3536	    else
3537		mPriv->autoState = AUTOPROBE_H_NOPROTO;
3538	    break;
3539	case AUTOPROBE_NOPROTO:
3540	    AP_DBG(("State NOPROTO\n"));
3541	    mPriv->count = 0;
3542	    mPriv->serialDefaultsNum = -1;
3543	    mPriv->autoState = AUTOPROBE_COLLECT;
3544	    break;
3545	case AUTOPROBE_COLLECT:
3546	    AP_DBG(("State COLLECT\n"));
3547	    if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES)
3548		return;
3549	    protocolList = softProtocolList;
3550	    mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST;
3551	    break;
3552	case AUTOPROBE_CREATE_PROTOLIST:
3553	    AP_DBG(("State CREATE_PROTOLIST\n"));
3554	    createProtoList(pMse, protocolList);
3555	    mPriv->protocolID = 0;
3556	    mPriv->autoState = AUTOPROBE_SWITCH_PROTOCOL;
3557	    break;
3558	case AUTOPROBE_AUTODETECT:
3559	    AP_DBG(("State AUTODETECT\n"));
3560	    pMse->protocolID = PROT_AUTO;
3561	    AP_DBG(("Looking for PnP/OS mouse\n"));
3562	    mPriv->count = 0;
3563	    SetupMouse(pInfo);
3564	    if (pMse->protocolID != PROT_AUTO)
3565		mPriv->autoState = AUTOPROBE_GOOD;
3566	    else
3567		mPriv->autoState = AUTOPROBE_NOPROTO;
3568	    break;
3569	case AUTOPROBE_VALIDATE1:
3570	    AP_DBG(("State VALIDATE1\n"));
3571	    switch (validCount(mPriv,inSync,lostSync)) {
3572	    case STATE_INVALID:
3573		mPriv->autoState = AUTOPROBE_AUTODETECT;
3574		break;
3575	    case STATE_VALID:
3576		xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3577			ProtocolIDToName(pMse->protocolID));
3578		mPriv->autoState = AUTOPROBE_GOOD;
3579		break;
3580	    case STATE_UNCERTAIN:
3581		return;
3582	    }
3583	    break;
3584	case AUTOPROBE_VALIDATE2:
3585	    AP_DBG(("State VALIDATE2\n"));
3586	    switch (validCount(mPriv,inSync,lostSync)) {
3587	    case STATE_INVALID:
3588		protocolList = &mPriv->protoList[mPriv->protocolID];
3589		mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST;
3590		break;
3591	    case STATE_VALID:
3592		xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n",
3593			ProtocolIDToName(pMse->protocolID));
3594		mPriv->autoState = AUTOPROBE_GOOD;
3595		break;
3596	    case STATE_UNCERTAIN:
3597		return;
3598	    }
3599	    break;
3600	case AUTOPROBE_SWITCHSERIAL:
3601	{
3602	    pointer serialDefaults;
3603	    AP_DBG(("State SWITCHSERIAL\n"));
3604
3605	    if (!serialDefaultsList)
3606		createSerialDefaultsList();
3607
3608	    AP_DBG(("Switching serial params\n"));
3609	    if ((serialDefaults =
3610		 serialDefaultsList[++mPriv->serialDefaultsNum]) == NULL) {
3611		mPriv->serialDefaultsNum = 0;
3612	    } else {
3613		pointer tmp = xf86OptionListCreate(serialDefaults, -1, 0);
3614		xf86SetSerial(pInfo->fd, tmp);
3615		xf86OptionListFree(tmp);
3616		mPriv->count = 0;
3617		mPriv->autoState = AUTOPROBE_COLLECT;
3618	    }
3619	    break;
3620	}
3621	case AUTOPROBE_SWITCH_PROTOCOL:
3622	{
3623	    MouseProtocolID proto;
3624	    void *defaults;
3625	    AP_DBG(("State SWITCH_PROTOCOL\n"));
3626	    proto = mPriv->protoList[mPriv->protocolID++];
3627	    if (proto == PROT_UNKNOWN)
3628		mPriv->autoState = AUTOPROBE_SWITCHSERIAL;
3629	    else if (!(defaults = GetProtocol(proto)->defaults)
3630		       || (mPriv->serialDefaultsNum == -1
3631			   && (defaults == msDefaults))
3632		       || (mPriv->serialDefaultsNum != -1
3633			   && serialDefaultsList[mPriv->serialDefaultsNum]
3634			   == defaults)) {
3635		AP_DBG(("Changing Protocol to %s\n",
3636			ProtocolIDToName(proto)));
3637		SetMouseProto(pMse,proto);
3638		FlushButtons(pMse);
3639		RESET_VALIDATION;
3640		mPriv->autoState = AUTOPROBE_VALIDATE2;
3641		return;
3642	    }
3643	    break;
3644	}
3645	}
3646    }
3647}
3648
3649static Bool
3650autoGood(MouseDevPtr pMse)
3651{
3652    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3653
3654    if (!pMse->autoProbe)
3655	return TRUE;
3656
3657    switch (mPriv->autoState) {
3658    case AUTOPROBE_GOOD:
3659    case AUTOPROBE_H_GOOD:
3660	return TRUE;
3661    case AUTOPROBE_VALIDATE1: /* @@@ */
3662    case AUTOPROBE_H_VALIDATE1: /* @@@ */
3663    case AUTOPROBE_VALIDATE2:
3664    case AUTOPROBE_H_VALIDATE2:
3665	if (mPriv->goodCount < PROBE_UNCERTAINTY/2)
3666	    return TRUE;
3667    default:
3668	return FALSE;
3669    }
3670}
3671
3672
3673#define TOT_THRESHOLD 3000
3674#define VAL_THRESHOLD 40
3675
3676/*
3677 * checkForErraticMovements() -- check if mouse 'jumps around'.
3678 */
3679static void
3680checkForErraticMovements(InputInfoPtr pInfo, int dx, int dy)
3681{
3682    MouseDevPtr pMse = pInfo->private;
3683    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3684#if 1
3685    if (!mPriv->goodCount)
3686	return;
3687#endif
3688#if 0
3689    if (abs(dx - mPriv->prevDx) > 300
3690	|| abs(dy - mPriv->prevDy) > 300)
3691	AP_DBG(("erratic1 behaviour\n"));
3692#endif
3693    if (abs(dx) > VAL_THRESHOLD) {
3694	if (sign(dx) == sign(mPriv->prevDx)) {
3695	    mPriv->accDx += dx;
3696	    if (abs(mPriv->accDx) > mPriv->acc) {
3697		mPriv->acc = abs(mPriv->accDx);
3698		AP_DBG(("acc=%i\n",mPriv->acc));
3699	    }
3700	    else
3701		AP_DBG(("accDx=%i\n",mPriv->accDx));
3702	} else {
3703	    mPriv->accDx = 0;
3704	}
3705    }
3706
3707    if (abs(dy) > VAL_THRESHOLD) {
3708	if (sign(dy) == sign(mPriv->prevDy)) {
3709	    mPriv->accDy += dy;
3710	    if (abs(mPriv->accDy) > mPriv->acc) {
3711		mPriv->acc = abs(mPriv->accDy);
3712		AP_DBG(("acc: %i\n",mPriv->acc));
3713	    } else
3714		AP_DBG(("accDy=%i\n",mPriv->accDy));
3715	} else {
3716	    mPriv->accDy = 0;
3717	}
3718    }
3719    mPriv->prevDx = dx;
3720    mPriv->prevDy = dy;
3721    if (mPriv->acc > TOT_THRESHOLD) {
3722	mPriv->goodCount = PROBE_UNCERTAINTY;
3723	mPriv->prevDx = 0;
3724	mPriv->prevDy = 0;
3725	mPriv->accDx = 0;
3726	mPriv->accDy = 0;
3727	mPriv->acc = 0;
3728	AP_DBG(("erratic2 behaviour\n"));
3729	autoProbeMouse(pInfo, FALSE,TRUE);
3730    }
3731}
3732
3733static void
3734SetMouseProto(MouseDevPtr pMse, MouseProtocolID protocolID)
3735{
3736    pMse->protocolID = protocolID;
3737    pMse->protocol = ProtocolIDToName(pMse->protocolID);
3738    pMse->class = ProtocolIDToClass(pMse->protocolID);
3739    if ((pMse->protocolID >= 0) && (pMse->protocolID < PROT_NUMPROTOS))
3740	memcpy(pMse->protoPara, proto[pMse->protocolID],
3741	       sizeof(pMse->protoPara));
3742
3743    if (pMse->emulate3ButtonsSoft)
3744	pMse->emulate3Buttons = TRUE;
3745}
3746
3747/*
3748 * collectData() -- collect data bytes sent by mouse.
3749 */
3750static Bool
3751collectData(MouseDevPtr pMse, unsigned char u)
3752{
3753    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
3754    if (mPriv->count < NUM_MSE_AUTOPROBE_TOTAL) {
3755	mPriv->data[mPriv->count++] = u;
3756	if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES) {
3757		return TRUE;
3758	}
3759    }
3760    return FALSE;
3761}
3762
3763/**************** end of autoprobe stuff *****************/
3764
3765
3766
3767#ifdef XFree86LOADER
3768ModuleInfoRec MouseInfo = {
3769    1,
3770    "MOUSE",
3771    NULL,
3772    0,
3773    MouseAvailableOptions,
3774};
3775
3776static void
3777xf86MouseUnplug(pointer	p)
3778{
3779}
3780static pointer
3781xf86MousePlug(pointer	module,
3782	    pointer	options,
3783	    int		*errmaj,
3784	    int		*errmin)
3785{
3786    static Bool Initialised = FALSE;
3787
3788    if (!Initialised) {
3789	Initialised = TRUE;
3790#ifndef REMOVE_LOADER_CHECK_MODULE_INFO
3791	if (xf86LoaderCheckSymbol("xf86AddModuleInfo"))
3792#endif
3793	xf86AddModuleInfo(&MouseInfo, module);
3794    }
3795
3796    xf86AddInputDriver(&MOUSE, module, 0);
3797
3798    return module;
3799}
3800
3801static XF86ModuleVersionInfo xf86MouseVersionRec =
3802{
3803    "mouse",
3804    MODULEVENDORSTRING,
3805    MODINFOSTRING1,
3806    MODINFOSTRING2,
3807    XORG_VERSION_CURRENT,
3808    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
3809    ABI_CLASS_XINPUT,
3810    ABI_XINPUT_VERSION,
3811    MOD_CLASS_XINPUT,
3812    {0, 0, 0, 0}		/* signature, to be patched into the file by */
3813				/* a tool */
3814};
3815
3816_X_EXPORT XF86ModuleData mouseModuleData = {
3817    &xf86MouseVersionRec,
3818    xf86MousePlug,
3819    xf86MouseUnplug
3820};
3821
3822/*
3823  Look at hitachi device stuff.
3824*/
3825#endif /* XFree86LOADER */
3826
3827
3828