VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxmouse/xorg14/mouse.c@ 32340

Last change on this file since 32340 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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