VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/xmouse/xorg70/mouse.c@ 6139

Last change on this file since 6139 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette