VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xmouse/mouse.c@ 16774

Last change on this file since 16774 was 8130, checked in by vboxsync, 17 years ago

rebranding the additions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 71.0 KB
Line 
1/*
2 *
3 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
4 * Copyright 1993 by David Dawes <dawes@xfree86.org>
5 * Copyright 1994-2001 by The XFree86 Project, Inc.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the names of copyright holders not be
12 * used in advertising or publicity pertaining to distribution of the
13 * software without specific, written prior permission. The copyright holders
14 * make no representations about the suitability of this
15 * software for any purpose. It is provided "as is" without express or
16 * implied warranty.
17 *
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
19 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
23 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
24 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 */
27/* Patch for PS/2 Intellimouse - Tim Goodwin 1997-11-06. */
28
29/*
30 * [JCH-96/01/21] Added fourth button support for PROT_GLIDEPOINT mouse
31 * protocol.
32 */
33
34/*
35 * [TVO-97/03/05] Added microsoft IntelliMouse support
36 */
37
38#define NEED_EVENTS
39#include "X.h"
40#include "Xproto.h"
41
42#include "xf86.h"
43
44#ifdef XINPUT
45#include "XI.h"
46#include "XIproto.h"
47#include "extnsionst.h"
48#include "extinit.h"
49#else
50#include "inputstr.h"
51#endif
52
53#include "xf86Xinput.h"
54#include "xf86_OSproc.h"
55#include "xf86OSmouse.h"
56#define NEED_XF86_TYPES /* for xisb.h when !XFree86LOADER */
57#include "xf86_ansic.h"
58#include "compiler.h"
59
60#include "xisb.h"
61#include "mouse.h"
62#include "mousePriv.h"
63#include "mipointer.h"
64
65#ifdef VBOX
66#include "VBoxUtils.h"
67#include "version-generated.h"
68#endif
69
70static const OptionInfoRec *MouseAvailableOptions(void *unused);
71static InputInfoPtr MousePreInit(InputDriverPtr drv, IDevPtr dev, int flags);
72#if 0
73static void MouseUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
74#endif
75
76static int MouseProc(DeviceIntPtr device, int what);
77static Bool MouseConvert(LocalDevicePtr local, int first, int num, int v0,
78 int v1, int v2, int v3, int v4, int v5, int *x,
79 int *y);
80
81static void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl);
82static void MousePostEvent(InputInfoPtr pInfo, int buttons,
83 int dx, int dy, int dz, int dw);
84static void MouseReadInput(InputInfoPtr pInfo);
85static void initPs2(InputInfoPtr pInfo, Bool reinsert);
86static Bool ps2mouseReset(InputInfoPtr pInfo, unsigned char val);
87
88#undef MOUSE
89InputDriverRec MOUSE = {
90 1,
91#ifdef VBOX
92 "vboxmouse",
93#else
94 "mouse",
95#endif
96 NULL,
97 MousePreInit,
98 /*MouseUnInit,*/NULL,
99 NULL,
100 0
101};
102
103typedef enum {
104 OPTION_ALWAYS_CORE,
105 OPTION_SEND_CORE_EVENTS,
106 OPTION_CORE_POINTER,
107 OPTION_SEND_DRAG_EVENTS,
108 OPTION_HISTORY_SIZE,
109 OPTION_DEVICE,
110 OPTION_PROTOCOL,
111 OPTION_BUTTONS,
112 OPTION_EMULATE_3_BUTTONS,
113 OPTION_EMULATE_3_TIMEOUT,
114 OPTION_CHORD_MIDDLE,
115 OPTION_FLIP_XY,
116 OPTION_INV_X,
117 OPTION_INV_Y,
118 OPTION_Z_AXIS_MAPPING,
119 OPTION_SAMPLE_RATE,
120 OPTION_RESOLUTION,
121 OPTION_CLEAR_DTR,
122 OPTION_CLEAR_RTS,
123 OPTION_BAUD_RATE,
124 OPTION_DATA_BITS,
125 OPTION_STOP_BITS,
126 OPTION_PARITY,
127 OPTION_FLOW_CONTROL,
128 OPTION_VTIME,
129 OPTION_VMIN,
130 OPTION_EMULATE_WHEEL,
131 OPTION_EMU_WHEEL_BUTTON,
132 OPTION_EMU_WHEEL_INERTIA,
133 OPTION_X_AXIS_MAPPING,
134 OPTION_Y_AXIS_MAPPING
135} MouseOpts;
136
137static const OptionInfoRec mouseOptions[] = {
138 { OPTION_ALWAYS_CORE, "AlwaysCore", OPTV_BOOLEAN, {0}, FALSE },
139 { OPTION_SEND_CORE_EVENTS, "SendCoreEvents", OPTV_BOOLEAN, {0}, FALSE },
140 { OPTION_CORE_POINTER, "CorePointer", OPTV_BOOLEAN, {0}, FALSE },
141 { OPTION_SEND_DRAG_EVENTS, "SendDragEvents", OPTV_BOOLEAN, {0}, FALSE },
142 { OPTION_HISTORY_SIZE, "HistorySize", OPTV_INTEGER, {0}, FALSE },
143 { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE },
144 { OPTION_PROTOCOL, "Protocol", OPTV_STRING, {0}, FALSE },
145 { OPTION_BUTTONS, "Buttons", OPTV_INTEGER, {0}, FALSE },
146 { OPTION_EMULATE_3_BUTTONS, "Emulate3Buttons",OPTV_BOOLEAN, {0}, FALSE },
147 { OPTION_EMULATE_3_TIMEOUT, "Emulate3Timeout",OPTV_INTEGER, {0}, FALSE },
148 { OPTION_CHORD_MIDDLE, "ChordMiddle", OPTV_BOOLEAN, {0}, FALSE },
149 { OPTION_FLIP_XY, "FlipXY", OPTV_BOOLEAN, {0}, FALSE },
150 { OPTION_INV_X, "InvX", OPTV_BOOLEAN, {0}, FALSE },
151 { OPTION_INV_Y, "InvY", OPTV_BOOLEAN, {0}, FALSE },
152 { OPTION_Z_AXIS_MAPPING, "ZAxisMapping", OPTV_STRING, {0}, FALSE },
153 { OPTION_SAMPLE_RATE, "SampleRate", OPTV_INTEGER, {0}, FALSE },
154 { OPTION_RESOLUTION, "Resolution", OPTV_INTEGER, {0}, FALSE },
155 { OPTION_CLEAR_DTR, "ClearDTR", OPTV_BOOLEAN, {0}, FALSE },
156 { OPTION_CLEAR_RTS, "ClearRTS", OPTV_BOOLEAN, {0}, FALSE },
157 { OPTION_BAUD_RATE, "BaudRate", OPTV_INTEGER, {0}, FALSE },
158 { OPTION_DATA_BITS, "DataBits", OPTV_INTEGER, {0}, FALSE },
159 { OPTION_STOP_BITS, "StopBits", OPTV_INTEGER, {0}, FALSE },
160 { OPTION_PARITY, "Parity", OPTV_STRING, {0}, FALSE },
161 { OPTION_FLOW_CONTROL, "FlowControl", OPTV_STRING, {0}, FALSE },
162 { OPTION_VTIME, "VTime", OPTV_INTEGER, {0}, FALSE },
163 { OPTION_VMIN, "VMin", OPTV_INTEGER, {0}, FALSE },
164 { OPTION_EMULATE_WHEEL, "EmulateWheel", OPTV_BOOLEAN, {0}, FALSE },
165 { OPTION_EMU_WHEEL_BUTTON, "EmulateWheelButton", OPTV_INTEGER, {0}, FALSE },
166 { OPTION_EMU_WHEEL_INERTIA, "EmulateWheelInertia", OPTV_INTEGER, {0}, FALSE },
167 { OPTION_X_AXIS_MAPPING, "XAxisMapping", OPTV_STRING, {0}, FALSE },
168 { OPTION_Y_AXIS_MAPPING, "YAxisMapping", OPTV_STRING, {0}, FALSE },
169 { -1, NULL, OPTV_NONE, {0}, FALSE }
170};
171
172/*
173 * Microsoft (all serial models), Logitech MouseMan, First Mouse, etc,
174 * ALPS GlidePoint, Thinking Mouse.
175 */
176static const char *msDefaults[] = {
177 "BaudRate", "1200",
178 "DataBits", "7",
179 "StopBits", "1",
180 "Parity", "None",
181 "FlowControl", "None",
182 "VTime", "0",
183 "VMin", "1",
184 NULL
185};
186/* MouseSystems */
187static const char *mscDefaults[] = {
188 "BaudRate", "1200",
189 "DataBits", "8",
190 "StopBits", "2",
191 "Parity", "None",
192 "FlowControl", "None",
193 "VTime", "0",
194 "VMin", "1",
195 NULL
196};
197/* MMSeries */
198static const char *mmDefaults[] = {
199 "BaudRate", "1200",
200 "DataBits", "8",
201 "StopBits", "1",
202 "Parity", "Odd",
203 "FlowControl", "None",
204 "VTime", "0",
205 "VMin", "1",
206 NULL
207};
208/* Logitech series 9 */
209static const char *logiDefaults[] = {
210 "BaudRate", "1200",
211 "DataBits", "8",
212 "StopBits", "2",
213 "Parity", "None",
214 "FlowControl", "None",
215 "VTime", "0",
216 "VMin", "1",
217 NULL
218};
219/* Hitachi Tablet */
220static const char *mmhitDefaults[] = {
221 "BaudRate", "1200",
222 "DataBits", "8",
223 "StopBits", "1",
224 "Parity", "None",
225 "FlowControl", "None",
226 "VTime", "0",
227 "VMin", "1",
228 NULL
229};
230/* AceCad Tablet */
231static const char *acecadDefaults[] = {
232 "BaudRate", "9600",
233 "DataBits", "8",
234 "StopBits", "1",
235 "Parity", "Odd",
236 "FlowControl", "None",
237 "VTime", "0",
238 "VMin", "1",
239 NULL
240};
241
242static MouseProtocolRec mouseProtocols[] = {
243
244 /* Serial protocols */
245 { "Microsoft", MSE_SERIAL, msDefaults, PROT_MS },
246 { "MouseSystems", MSE_SERIAL, mscDefaults, PROT_MSC },
247 { "MMSeries", MSE_SERIAL, mmDefaults, PROT_MM },
248 { "Logitech", MSE_SERIAL, logiDefaults, PROT_LOGI },
249 { "MouseMan", MSE_SERIAL, msDefaults, PROT_LOGIMAN },
250 { "MMHitTab", MSE_SERIAL, mmhitDefaults, PROT_MMHIT },
251 { "GlidePoint", MSE_SERIAL, msDefaults, PROT_GLIDE },
252 { "IntelliMouse", MSE_SERIAL, msDefaults, PROT_IMSERIAL },
253 { "ThinkingMouse", MSE_SERIAL, msDefaults, PROT_THINKING },
254 { "AceCad", MSE_SERIAL, acecadDefaults, PROT_ACECAD },
255
256 /* Standard PS/2 */
257 { "PS/2", MSE_PS2, NULL, PROT_PS2 },
258
259 /* Extended PS/2 */
260 { "ImPS/2", MSE_XPS2, NULL, PROT_IMPS2 },
261 { "ExplorerPS/2", MSE_XPS2, NULL, PROT_EXPPS2 },
262 { "ThinkingMousePS/2", MSE_XPS2, NULL, PROT_THINKPS2 },
263 { "MouseManPlusPS/2", MSE_XPS2, NULL, PROT_MMPS2 },
264 { "GlidePointPS/2", MSE_XPS2, NULL, PROT_GLIDEPS2 },
265 { "NetMousePS/2", MSE_XPS2, NULL, PROT_NETPS2 },
266 { "NetScrollPS/2", MSE_XPS2, NULL, PROT_NETSCPS2 },
267
268 /* Bus Mouse */
269 { "BusMouse", MSE_BUS, NULL, PROT_BM },
270
271 /* Auto-detect (PnP) */
272 { "Auto", MSE_AUTO, NULL, PROT_AUTO },
273
274 /* Misc (usually OS-specific) */
275 { "SysMouse", MSE_MISC, mscDefaults, PROT_SYSMOUSE },
276
277 /* end of list */
278 { NULL, MSE_NONE, NULL, PROT_UNKNOWN }
279};
280
281/*ARGSUSED*/
282static const OptionInfoRec *
283MouseAvailableOptions(void *unused)
284{
285 return (mouseOptions);
286}
287
288static MouseProtocolID
289ProtocolNameToID(const char *name)
290{
291 int i;
292
293 for (i = 0; mouseProtocols[i].name; i++)
294 if (xf86NameCmp(name, mouseProtocols[i].name) == 0)
295 return mouseProtocols[i].id;
296 return PROT_UNKNOWN;
297}
298
299static const char *
300ProtocolIDToName(MouseProtocolID id)
301{
302 int i;
303
304 switch (id) {
305 case PROT_UNKNOWN:
306 return "Unknown";
307 break;
308 case PROT_UNSUP:
309 return "Unsupported";
310 break;
311 default:
312 for (i = 0; mouseProtocols[i].name; i++)
313 if (id == mouseProtocols[i].id)
314 return mouseProtocols[i].name;
315 return "Invalid";
316 }
317}
318
319const char *
320xf86MouseProtocolIDToName(MouseProtocolID id)
321{
322 return ProtocolIDToName(id);
323}
324
325MouseProtocolID
326xf86MouseProtocolNameToID(const char *name)
327{
328 return ProtocolNameToID(name);
329}
330
331static int
332ProtocolIDToClass(MouseProtocolID id)
333{
334 int i;
335
336 switch (id) {
337 case PROT_UNKNOWN:
338 case PROT_UNSUP:
339 return MSE_NONE;
340 break;
341 default:
342 for (i = 0; mouseProtocols[i].name; i++)
343 if (id == mouseProtocols[i].id)
344 return mouseProtocols[i].class;
345 return MSE_NONE;
346 }
347}
348
349static MouseProtocolPtr
350GetProtocol(MouseProtocolID id) {
351 int i;
352
353 switch (id) {
354 case PROT_UNKNOWN:
355 case PROT_UNSUP:
356 return NULL;
357 break;
358 default:
359 for (i = 0; mouseProtocols[i].name; i++)
360 if (id == mouseProtocols[i].id)
361 return &mouseProtocols[i];
362 return NULL;
363 }
364}
365
366static OSMouseInfoPtr osInfo = NULL;
367
368static Bool
369InitProtocols(void)
370{
371 int classes;
372 int i;
373 const char *osname = NULL;
374
375 if (osInfo)
376 return TRUE;
377
378 osInfo = xf86OSMouseInit(0);
379 if (!osInfo)
380 return FALSE;
381 if (!osInfo->SupportedInterfaces)
382 return FALSE;
383
384 classes = osInfo->SupportedInterfaces();
385 if (!classes)
386 return FALSE;
387
388 /* Mark unsupported interface classes. */
389 for (i = 0; mouseProtocols[i].name; i++)
390 if (!(mouseProtocols[i].class & classes))
391 mouseProtocols[i].id = PROT_UNSUP;
392
393 for (i = 0; mouseProtocols[i].name; i++)
394 if (mouseProtocols[i].class & MSE_MISC)
395 if (!osInfo->CheckProtocol ||
396 !osInfo->CheckProtocol(mouseProtocols[i].name))
397 mouseProtocols[i].id = PROT_UNSUP;
398
399 /* NetBSD uses PROT_BM for "PS/2". */
400 xf86GetOS(&osname, NULL, NULL, NULL);
401 if (osname && xf86NameCmp(osname, "netbsd") == 0)
402 for (i = 0; mouseProtocols[i].name; i++)
403 if (mouseProtocols[i].id == PROT_PS2)
404 mouseProtocols[i].id = PROT_BM;
405
406 return TRUE;
407}
408
409static void MouseBlockHandler(pointer data,
410 struct timeval **waitTime,
411 pointer LastSelectMask);
412
413static void MouseWakeupHandler(pointer data,
414 int i,
415 pointer LastSelectMask);
416
417/* Process options common to all mouse types. */
418static void
419MouseCommonOptions(InputInfoPtr pInfo)
420{
421 MouseDevPtr pMse;
422 MessageType from = X_DEFAULT;
423 char *s;
424 int origButtons;
425
426 pMse = pInfo->private;
427
428 pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
429 from = X_CONFIG;
430 if (!pMse->buttons) {
431 pMse->buttons = MSE_DFLTBUTTONS;
432 from = X_DEFAULT;
433 }
434 origButtons = pMse->buttons;
435
436 pMse->emulate3Buttons = xf86SetBoolOption(pInfo->options,
437 "Emulate3Buttons", FALSE);
438 pMse->emulate3Timeout = xf86SetIntOption(pInfo->options, "Emulate3Timeout",
439 50);
440 if (pMse->emulate3Buttons) {
441 xf86Msg(X_CONFIG, "%s: Emulate3Buttons, Emulate3Timeout: %d\n",
442 pInfo->name, pMse->emulate3Timeout);
443 }
444
445 pMse->chordMiddle = xf86SetBoolOption(pInfo->options, "ChordMiddle", FALSE);
446 if (pMse->chordMiddle)
447 xf86Msg(X_CONFIG, "%s: ChordMiddle\n", pInfo->name);
448 pMse->flipXY = xf86SetBoolOption(pInfo->options, "FlipXY", FALSE);
449 if (pMse->flipXY)
450 xf86Msg(X_CONFIG, "%s: FlipXY\n", pInfo->name);
451 if (xf86SetBoolOption(pInfo->options, "InvX", FALSE)) {
452 pMse->invX = -1;
453 xf86Msg(X_CONFIG, "%s: InvX\n", pInfo->name);
454 } else
455 pMse->invX = 1;
456 if (xf86SetBoolOption(pInfo->options, "InvY", FALSE)) {
457 pMse->invY = -1;
458 xf86Msg(X_CONFIG, "%s: InvY\n", pInfo->name);
459 } else
460 pMse->invY = 1;
461
462 s = xf86SetStrOption(pInfo->options, "ZAxisMapping", NULL);
463 if (s) {
464 int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
465 char *msg = NULL;
466
467 if (!xf86NameCmp(s, "x")) {
468 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX;
469 pMse->negativeW = pMse->positiveW = MSE_MAPTOX;
470 msg = xstrdup("X axis");
471 } else if (!xf86NameCmp(s, "y")) {
472 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY;
473 pMse->negativeW = pMse->positiveW = MSE_MAPTOY;
474 msg = xstrdup("Y axis");
475 } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 &&
476 b1 > 0 && b1 <= MSE_MAXBUTTONS &&
477 b2 > 0 && b2 <= MSE_MAXBUTTONS) {
478 msg = xstrdup("buttons XX and YY");
479 if (msg)
480 sprintf(msg, "buttons %d and %d", b1, b2);
481 pMse->negativeZ = pMse->negativeW = 1 << (b1-1);
482 pMse->positiveZ = pMse->positiveW = 1 << (b2-1);
483 if (b3 > 0 && b3 <= MSE_MAXBUTTONS &&
484 b4 > 0 && b4 <= MSE_MAXBUTTONS) {
485 if (msg)
486 xfree(msg);
487 msg = xstrdup("buttons XX, YY, ZZ and WW");
488 if (msg)
489 sprintf(msg, "buttons %d, %d, %d and %d", b1, b2, b3, b4);
490 pMse->negativeW = 1 << (b3-1);
491 pMse->positiveW = 1 << (b4-1);
492 }
493 if (b1 > pMse->buttons) pMse->buttons = b1;
494 if (b2 > pMse->buttons) pMse->buttons = b2;
495 if (b3 > pMse->buttons) pMse->buttons = b3;
496 if (b4 > pMse->buttons) pMse->buttons = b4;
497 } else {
498 pMse->negativeZ = pMse->positiveZ = MSE_NOZMAP;
499 pMse->negativeW = pMse->positiveW = MSE_NOZMAP;
500 }
501 if (msg) {
502 xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg);
503 xfree(msg);
504 } else {
505 xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n",
506 pInfo->name, s);
507 }
508 }
509 if (xf86SetBoolOption(pInfo->options, "EmulateWheel", FALSE)) {
510 Bool yFromConfig = FALSE;
511 int wheelButton;
512
513 pMse->emulateWheel = TRUE;
514 wheelButton = xf86SetIntOption(pInfo->options,
515 "EmulateWheelButton", 4);
516 if (wheelButton < 0 || wheelButton > MSE_MAXBUTTONS) {
517 xf86Msg(X_WARNING, "%s: Invalid EmulateWheelButton value: %d\n",
518 pInfo->name, wheelButton);
519 wheelButton = 4;
520 }
521 pMse->wheelButtonMask = 1 << (wheelButton - 1);
522
523 pMse->wheelInertia = xf86SetIntOption(pInfo->options,
524 "EmulateWheelInertia", 10);
525 if (pMse->wheelInertia <= 0) {
526 xf86Msg(X_WARNING, "%s: Invalid EmulateWheelInertia value: %d\n",
527 pInfo->name, pMse->wheelInertia);
528 pMse->wheelInertia = 50;
529 }
530
531 pMse->negativeX = MSE_NOAXISMAP;
532 pMse->positiveX = MSE_NOAXISMAP;
533 s = xf86SetStrOption(pInfo->options, "XAxisMapping", NULL);
534 if (s) {
535 int b1 = 0, b2 = 0;
536 char *msg = NULL;
537
538 if ((sscanf(s, "%d %d", &b1, &b2) == 2) &&
539 b1 > 0 && b1 <= MSE_MAXBUTTONS &&
540 b2 > 0 && b2 <= MSE_MAXBUTTONS) {
541 msg = xstrdup("buttons XX and YY");
542 if (msg)
543 sprintf(msg, "buttons %d and %d", b1, b2);
544 pMse->negativeX = b1;
545 pMse->positiveX = b2;
546 if (b1 > pMse->buttons) pMse->buttons = b1;
547 if (b2 > pMse->buttons) pMse->buttons = b2;
548 } else {
549 xf86Msg(X_WARNING, "%s: Invalid XAxisMapping value: \"%s\"\n",
550 pInfo->name, s);
551 }
552 if (msg) {
553 xf86Msg(X_CONFIG, "%s: XAxisMapping: %s\n", pInfo->name, msg);
554 xfree(msg);
555 }
556 }
557 s = xf86SetStrOption(pInfo->options, "YAxisMapping", NULL);
558 if (s) {
559 int b1 = 0, b2 = 0;
560 char *msg = NULL;
561
562 if ((sscanf(s, "%d %d", &b1, &b2) == 2) &&
563 b1 > 0 && b1 <= MSE_MAXBUTTONS &&
564 b2 > 0 && b2 <= MSE_MAXBUTTONS) {
565 msg = xstrdup("buttons XX and YY");
566 if (msg)
567 sprintf(msg, "buttons %d and %d", b1, b2);
568 pMse->negativeY = b1;
569 pMse->positiveY = b2;
570 if (b1 > pMse->buttons) pMse->buttons = b1;
571 if (b2 > pMse->buttons) pMse->buttons = b2;
572 yFromConfig = TRUE;
573 } else {
574 xf86Msg(X_WARNING, "%s: Invalid YAxisMapping value: \"%s\"\n",
575 pInfo->name, s);
576 }
577 if (msg) {
578 xf86Msg(X_CONFIG, "%s: YAxisMapping: %s\n", pInfo->name, msg);
579 xfree(msg);
580 }
581 }
582 if (!yFromConfig) {
583 pMse->negativeY = 4;
584 pMse->positiveY = 5;
585 if (pMse->negativeY > pMse->buttons)
586 pMse->buttons = pMse->negativeY;
587 if (pMse->positiveY > pMse->buttons)
588 pMse->buttons = pMse->positiveY;
589 xf86Msg(X_DEFAULT, "%s: YAxisMapping: buttons %d and %d\n",
590 pInfo->name, pMse->negativeY, pMse->positiveY);
591 }
592 xf86Msg(X_CONFIG, "%s: EmulateWheel, EmulateWheelButton: %d, "
593 "EmulateWheelInertia: %d\n",
594 pInfo->name, wheelButton, pMse->wheelInertia);
595 }
596 if (origButtons != pMse->buttons)
597 from = X_CONFIG;
598 xf86Msg(from, "%s: Buttons: %d\n", pInfo->name, pMse->buttons);
599
600}
601
602static InputInfoPtr
603MousePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
604{
605 InputInfoPtr pInfo;
606 MouseDevPtr pMse;
607 MessageType from = X_DEFAULT;
608 const char *protocol;
609 MouseProtocolID protocolID;
610 MouseProtocolPtr pProto;
611
612#ifdef VBOX
613 xf86Msg(X_INFO,
614 "VirtualBox guest additions mouse driver version "
615 VBOX_VERSION_STRING "\n");
616#endif
617
618 if (!InitProtocols())
619 return NULL;
620
621 if (!(pInfo = xf86AllocateInput(drv, 0)))
622 return NULL;
623
624 /* Initialise the InputInfoRec. */
625 pInfo->name = dev->identifier;
626 pInfo->type_name = XI_MOUSE;
627 pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
628 pInfo->device_control = MouseProc;
629 pInfo->read_input = MouseReadInput;
630 pInfo->motion_history_proc = xf86GetMotionEvents;
631 pInfo->history_size = 0;
632 pInfo->control_proc = NULL;
633 pInfo->close_proc = NULL;
634 pInfo->switch_mode = NULL;
635 pInfo->conversion_proc = MouseConvert;
636 pInfo->reverse_conversion_proc = NULL;
637 pInfo->fd = -1;
638 pInfo->dev = NULL;
639 pInfo->private_flags = 0;
640 pInfo->always_core_feedback = 0;
641 pInfo->conf_idev = dev;
642
643 /* Allocate the MouseDevRec and initialise it. */
644 /*
645 * XXX This should be done by a function in the core server since the
646 * MouseDevRec is defined in the os-support layer.
647 */
648 if (!(pMse = xcalloc(sizeof(MouseDevRec), 1)))
649 return pInfo;
650 pInfo->private = pMse;
651 pMse->Ctrl = MouseCtrl;
652 pMse->PostEvent = MousePostEvent;
653 pMse->CommonOptions = MouseCommonOptions;
654
655#ifdef VBOX
656 protocol = "ImPS/2";
657 from = X_CONFIG;
658#else
659 /* Find the protocol type. */
660 protocol = xf86SetStrOption(dev->commonOptions, "Protocol", NULL);
661 if (protocol) {
662 from = X_CONFIG;
663 } else if (osInfo->DefaultProtocol) {
664 protocol = osInfo->DefaultProtocol();
665 from = X_DEFAULT;
666 }
667 if (!protocol) {
668 xf86Msg(X_ERROR, "%s: No Protocol specified\n", pInfo->name);
669 return pInfo;
670 }
671#endif /* VBOX */
672 protocolID = ProtocolNameToID(protocol);
673 switch (protocolID) {
674 case PROT_UNKNOWN:
675 /* Check for a builtin OS-specific protocol, and call its PreInit. */
676 if (osInfo->CheckProtocol && osInfo->CheckProtocol(protocol)) {
677 if (osInfo->PreInit) {
678 osInfo->PreInit(pInfo, protocol, 0);
679 }
680 return pInfo;
681 }
682 xf86Msg(X_ERROR, "%s: Unknown protocol \"%s\"\n", pInfo->name,
683 protocol);
684 return pInfo;
685 break;
686 case PROT_UNSUP:
687 xf86Msg(X_ERROR,
688 "%s: Protocol \"%s\" is not supported on this platform\n",
689 pInfo->name, protocol);
690 return pInfo;
691 break;
692 default:
693 xf86Msg(from, "%s: Protocol: \"%s\"\n", pInfo->name, protocol);
694 }
695
696 if (!(pProto = GetProtocol(protocolID)))
697 return pInfo;
698
699 pMse->protocol = protocol;
700 pMse->protocolID = protocolID;
701 pMse->oldProtocolID = protocolID; /* hack */
702 pMse->origProtocolID = protocolID;
703 pMse->origProtocol = protocol;
704 pMse->class = ProtocolIDToClass(protocolID);
705
706 /* Collect the options, and process the common options. */
707 xf86CollectInputOptions(pInfo, pProto->defaults, NULL);
708 xf86ProcessCommonOptions(pInfo, pInfo->options);
709
710 /* XXX should handle this OS dependency elsewhere. */
711#ifndef __OS2ELF__
712 /* OS/2 has a mouse handled by the OS - it cannot fail here */
713
714 /* Check if the device can be opened. */
715 pInfo->fd = xf86OpenSerial(pInfo->options);
716 if (pInfo->fd == -1) {
717 if (xf86GetAllowMouseOpenFail())
718 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
719 else {
720 xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
721 if (pMse->mousePriv)
722 xfree(pMse->mousePriv);
723 xfree(pMse);
724 pInfo->private = NULL;
725 return pInfo;
726 }
727 }
728 xf86CloseSerial(pInfo->fd);
729#endif
730 pInfo->fd = -1;
731
732 pMse->CommonOptions(pInfo);
733
734 pMse->sampleRate = xf86SetIntOption(pInfo->options, "SampleRate", 0);
735 if (pMse->sampleRate) {
736 xf86Msg(X_CONFIG, "%s: SampleRate: %d\n", pInfo->name,
737 pMse->sampleRate);
738 }
739 pMse->baudRate = xf86SetIntOption(pInfo->options, "BaudRate", 0);
740 if (pMse->baudRate) {
741 xf86Msg(X_CONFIG, "%s: BaudRate: %d\n", pInfo->name,
742 pMse->baudRate);
743 }
744 pMse->resolution = xf86SetIntOption(pInfo->options, "Resolution", 0);
745 if (pMse->resolution) {
746 xf86Msg(X_CONFIG, "%s: Resolution: %d\n", pInfo->name,
747 pMse->resolution);
748 }
749
750 pMse->clearDTR = xf86SetBoolOption(pInfo->options, "ClearDTR", FALSE);
751 pMse->clearRTS = xf86SetBoolOption(pInfo->options, "ClearRTS", FALSE);
752 if (pMse->clearDTR || pMse->clearRTS) {
753 xf86Msg(X_CONFIG, "%s: ", pInfo->name);
754 if (pMse->clearDTR) {
755 xf86ErrorF("ClearDTR");
756 if (pMse->clearRTS)
757 xf86ErrorF(", ");
758 }
759 if (pMse->clearRTS) {
760 xf86ErrorF("ClearRTS");
761 }
762 xf86ErrorF("\n");
763 }
764
765 pInfo->flags |= XI86_CONFIGURED;
766 return pInfo;
767}
768
769/*
770 * This array is indexed by the MouseProtocolID values, so the order of the entries
771 * must match that of the MouseProtocolID enum in mouse.h.
772 */
773static unsigned char proto[PROT_NUMPROTOS][8] = {
774 /* --header-- ---data--- packet -4th-byte- mouse */
775 /* mask id mask id bytes mask id flags */
776 /* Serial mice */
777 { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00, MPF_NONE }, /* MicroSoft */
778 { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_SAFE }, /* MouseSystems */
779 { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MMSeries */
780 { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* Logitech */
781 { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00, MPF_NONE }, /* MouseMan */
782 { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MM_HitTablet */
783 { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00, MPF_NONE }, /* GlidePoint */
784 { 0x40, 0x40, 0x40, 0x00, 3, ~0x3f, 0x00, MPF_NONE }, /* IntelliMouse */
785 { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00, MPF_NONE }, /* ThinkingMouse */
786 { 0x80, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* ACECAD */
787 /* PS/2 variants */
788 { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* PS/2 mouse */
789 { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* IntelliMouse */
790 { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* Explorer */
791 { 0x80, 0x80, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* ThinkingMouse */
792 { 0x08, 0x08, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MouseMan+ */
793 { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* GlidePoint */
794 { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* NetMouse */
795 { 0xc0, 0x00, 0x00, 0x00, 6, 0x00, 0xff, MPF_NONE }, /* NetScroll */
796 /* Bus Mouse */
797 { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_NONE }, /* BusMouse */
798 { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_NONE }, /* Auto (dummy) */
799 { 0xf8, 0x80, 0x00, 0x00, 8, 0x00, 0xff, MPF_NONE }, /* SysMouse */
800};
801
802/*
803 * SetupMouse --
804 * Sets up the mouse parameters
805 */
806static Bool
807SetupMouse(InputInfoPtr pInfo)
808{
809 /*
810 ** The following lines take care of the Logitech MouseMan protocols.
811 ** The "Logitech" protocol is for the old "series 9" Logitech products.
812 ** All products since then use the "MouseMan" protocol. Some models
813 ** were programmable, but most (all?) of the current models are not.
814 **
815 ** NOTE: There are different versions of both MouseMan and TrackMan!
816 ** Hence I add another protocol PROT_LOGIMAN, which the user can
817 ** specify as MouseMan in his XF86Config file. This entry was
818 ** formerly handled as a special case of PROT_MS. However, people
819 ** who don't have the middle button problem, can still specify
820 ** Microsoft and use PROT_MS.
821 **
822 ** By default, these mice should use a 3 byte Microsoft protocol
823 ** plus a 4th byte for the middle button. However, the mouse might
824 ** have switched to a different protocol before we use it, so I send
825 ** the proper sequence just in case.
826 **
827 ** NOTE: - all commands to (at least the European) MouseMan have to
828 ** be sent at 1200 Baud.
829 ** - each command starts with a '*'.
830 ** - whenever the MouseMan receives a '*', it will switch back
831 ** to 1200 Baud. Hence I have to select the desired protocol
832 ** first, then select the baud rate.
833 **
834 ** The protocols supported by the (European) MouseMan are:
835 ** - 5 byte packed binary protocol, as with the Mouse Systems
836 ** mouse. Selected by sequence "*U".
837 ** - 2 button 3 byte MicroSoft compatible protocol. Selected
838 ** by sequence "*V".
839 ** - 3 button 3+1 byte MicroSoft compatible protocol (default).
840 ** Selected by sequence "*X".
841 **
842 ** The following baud rates are supported:
843 ** - 1200 Baud (default). Selected by sequence "*n".
844 ** - 9600 Baud. Selected by sequence "*q".
845 **
846 ** Selecting a sample rate is no longer supported with the MouseMan!
847 ** [CHRIS-211092]
848 */
849
850 MouseDevPtr pMse;
851 int i;
852 int speed;
853 int protoPara[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
854 const char *name = NULL;
855 const char *s;
856 Bool automatic = FALSE;
857 unsigned char c;
858 pointer options;
859
860 pMse = pInfo->private;
861 /* Handle the "Auto" protocol. */
862 if (pMse->origProtocolID == PROT_AUTO) {
863 MouseProtocolID protocolID = PROT_UNKNOWN;
864
865 automatic = TRUE;
866
867 /* Check if the OS has a detection mechanism. */
868 if (osInfo->SetupAuto) {
869 name = osInfo->SetupAuto(pInfo, protoPara);
870 if (name) {
871 protocolID = ProtocolNameToID(name);
872 switch (protocolID) {
873 case PROT_UNKNOWN:
874 /* Check for a builtin OS-specific protocol. */
875 if (osInfo->CheckProtocol && osInfo->CheckProtocol(name)) {
876 /* XXX need to handle auto-detected builtin protocols */
877 } else
878 name = NULL;
879 break;
880 case PROT_UNSUP:
881 name = NULL;
882 break;
883 default:
884 break;
885 }
886 }
887 }
888#ifdef PNP_MOUSE
889 if (!name) {
890 /* A PnP serial mouse? */
891 protocolID = MouseGetPnpProtocol(pInfo);
892 if (protocolID >= 0 && protocolID < PROT_NUMPROTOS) {
893 name = ProtocolIDToName(protocolID);
894 xf86Msg(X_PROBED, "%s: PnP-detected protocol: \"%s\"\n",
895 pInfo->name, name);
896 }
897 }
898#endif
899 if (name) {
900 pMse->protocol = name;
901 pMse->protocolID = protocolID;
902 }
903 }
904 memcpy(pMse->protoPara, proto[pMse->protocolID], sizeof(pMse->protoPara));
905 if (automatic) {
906
907 if (name) {
908 /* Possible protoPara overrides from SetupAuto. */
909 for (i = 0; i < sizeof(pMse->protoPara); i++)
910 if (protoPara[i] != -1)
911 pMse->protoPara[i] = protoPara[i];
912 } else {
913 xf86Msg(X_ERROR, "%s: cannot determine the mouse protocol\n",
914 pInfo->name);
915 return FALSE;
916 }
917 }
918 /*
919 * If protocol has changed fetch the default options
920 * for the new protocol.
921 */
922 if (pMse->oldProtocolID != pMse->protocolID) {
923 pointer tmp = NULL;
924 if (mouseProtocols[pMse->protocolID].defaults)
925 tmp = xf86OptionListCreate(
926 mouseProtocols[pMse->protocolID].defaults, -1, 0);
927 pInfo->options = xf86OptionListMerge(pInfo->options, tmp);
928 /* baudrate is not explicitely set: fetch the default one */
929 if (!pMse->baudRate)
930 pMse->baudRate = xf86SetIntOption(pInfo->options, "BaudRate", 0);
931 pMse->oldProtocolID = pMse->protocolID; /* hack */
932 }
933 /*
934 * Write the baudrate back th the option list so that the serial
935 * interface code can access the new value.
936 */
937 if (pMse->baudRate)
938 xf86ReplaceIntOption(pInfo->options, "BaudRate", pMse->baudRate);
939
940 /* Set the port parameters. */
941 if (!automatic)
942 xf86SetSerial(pInfo->fd, pInfo->options);
943
944 switch (pMse->protocolID) {
945 case PROT_LOGI: /* Logitech Mice */
946 /*
947 * The baud rate selection command must be sent at the current
948 * baud rate; try all likely settings.
949 */
950 speed = pMse->baudRate;
951 switch (speed) {
952 case 9600:
953 s = "*q";
954 break;
955 case 4800:
956 s = "*p";
957 break;
958 case 2400:
959 s = "*o";
960 break;
961 case 1200:
962 s = "*n";
963 break;
964 default:
965 /* Fallback value */
966 speed = 1200;
967 s = "*n";
968 }
969 xf86SetSerialSpeed(pInfo->fd, 9600);
970 xf86WriteSerial(pInfo->fd, s, 2);
971 usleep(100000);
972 xf86SetSerialSpeed(pInfo->fd, 4800);
973 xf86WriteSerial(pInfo->fd, s, 2);
974 usleep(100000);
975 xf86SetSerialSpeed(pInfo->fd, 2400);
976 xf86WriteSerial(pInfo->fd, s, 2);
977 usleep(100000);
978 xf86SetSerialSpeed(pInfo->fd, 1200);
979 xf86WriteSerial(pInfo->fd, s, 2);
980 usleep(100000);
981 xf86SetSerialSpeed(pInfo->fd, speed);
982
983 /* Select MM series data format. */
984 xf86WriteSerial(pInfo->fd, "S", 1);
985 usleep(100000);
986 /* Set the parameters up for the MM series protocol. */
987 options = pInfo->options;
988 xf86CollectInputOptions(pInfo, mmDefaults, NULL);
989 xf86SetSerial(pInfo->fd, pInfo->options);
990 pInfo->options = options;
991
992 /* Select report rate/frequency. */
993 if (pMse->sampleRate <= 0) c = 'O'; /* 100 */
994 else if (pMse->sampleRate <= 15) c = 'J'; /* 10 */
995 else if (pMse->sampleRate <= 27) c = 'K'; /* 20 */
996 else if (pMse->sampleRate <= 42) c = 'L'; /* 35 */
997 else if (pMse->sampleRate <= 60) c = 'R'; /* 50 */
998 else if (pMse->sampleRate <= 85) c = 'M'; /* 67 */
999 else if (pMse->sampleRate <= 125) c = 'Q'; /* 100 */
1000 else c = 'N'; /* 150 */
1001 xf86WriteSerial(pInfo->fd, &c, 1);
1002 break;
1003
1004 case PROT_LOGIMAN:
1005 speed = pMse->baudRate;
1006 switch (speed) {
1007 case 9600:
1008 s = "*q";
1009 break;
1010 case 1200:
1011 s = "*n";
1012 break;
1013 default:
1014 /* Fallback value */
1015 speed = 1200;
1016 s = "*n";
1017 }
1018 xf86SetSerialSpeed(pInfo->fd, 1200);
1019 xf86WriteSerial(pInfo->fd, "*n", 2);
1020 xf86WriteSerial(pInfo->fd, "*X", 2);
1021 xf86WriteSerial(pInfo->fd, s, 2);
1022 usleep(100000);
1023 xf86SetSerialSpeed(pInfo->fd, speed);
1024 break;
1025
1026 case PROT_MMHIT: /* MM_HitTablet */
1027 /*
1028 * Initialize Hitachi PUMA Plus - Model 1212E to desired settings.
1029 * The tablet must be configured to be in MM mode, NO parity,
1030 * Binary Format. pMse->sampleRate controls the sensitivity
1031 * of the tablet. We only use this tablet for it's 4-button puck
1032 * so we don't run in "Absolute Mode".
1033 */
1034 xf86WriteSerial(pInfo->fd, "z8", 2); /* Set Parity = "NONE" */
1035 usleep(50000);
1036 xf86WriteSerial(pInfo->fd, "zb", 2); /* Set Format = "Binary" */
1037 usleep(50000);
1038 xf86WriteSerial(pInfo->fd, "@", 1); /* Set Report Mode = "Stream" */
1039 usleep(50000);
1040 xf86WriteSerial(pInfo->fd, "R", 1); /* Set Output Rate = "45 rps" */
1041 usleep(50000);
1042 xf86WriteSerial(pInfo->fd, "I\x20", 2); /* Set Incrememtal Mode "20" */
1043 usleep(50000);
1044 xf86WriteSerial(pInfo->fd, "E", 1); /* Set Data Type = "Relative */
1045 usleep(50000);
1046 /*
1047 * These sample rates translate to 'lines per inch' on the Hitachi
1048 * tablet.
1049 */
1050 if (pMse->sampleRate <= 40) c = 'g';
1051 else if (pMse->sampleRate <= 100) c = 'd';
1052 else if (pMse->sampleRate <= 200) c = 'e';
1053 else if (pMse->sampleRate <= 500) c = 'h';
1054 else if (pMse->sampleRate <= 1000) c = 'j';
1055 else c = 'd';
1056 xf86WriteSerial(pInfo->fd, &c, 1);
1057 usleep(50000);
1058 xf86WriteSerial(pInfo->fd, "\021", 1); /* Resume DATA output */
1059 break;
1060
1061 case PROT_THINKING: /* ThinkingMouse */
1062 /* This mouse may send a PnP ID string, ignore it. */
1063 usleep(200000);
1064 xf86FlushInput(pInfo->fd);
1065 /* Send the command to initialize the beast. */
1066 for (s = "E5E5"; *s; ++s) {
1067 xf86WriteSerial(pInfo->fd, s, 1);
1068 if ((xf86WaitForInput(pInfo->fd, 1000000) <= 0))
1069 break;
1070 xf86ReadSerial(pInfo->fd, &c, 1);
1071 if (c != *s)
1072 break;
1073 }
1074 break;
1075
1076 case PROT_MSC: /* MouseSystems Corp */
1077 usleep(100000);
1078 xf86FlushInput(pInfo->fd);
1079 break;
1080
1081 case PROT_ACECAD:
1082 /* initialize */
1083 /* A nul character resets. */
1084 xf86WriteSerial(pInfo->fd, "", 1);
1085 usleep(50000);
1086 /* Stream out relative mode high resolution increments of 1. */
1087 xf86WriteSerial(pInfo->fd, "@EeI!", 5);
1088 break;
1089
1090 case PROT_BM: /* bus/InPort mouse */
1091 if (osInfo->SetBMRes)
1092 osInfo->SetBMRes(pInfo, pMse->protocol, pMse->sampleRate,
1093 pMse->resolution);
1094 break;
1095
1096 case PROT_PS2:
1097 case PROT_IMPS2: /* IntelliMouse */
1098 case PROT_EXPPS2: /* IntelliMouse Explorer */
1099 case PROT_THINKPS2: /* ThinkingMouse */
1100 case PROT_MMPS2: /* MouseMan+, FirstMouse+ */
1101 case PROT_GLIDEPS2:
1102 case PROT_NETPS2: /* NetMouse, NetMouse Pro, Mie Mouse */
1103 case PROT_NETSCPS2: /* NetScroll */
1104#ifndef VBOX
1105 if ((pMse->mousePriv =
1106 (pointer) xcalloc(sizeof(ps2PrivRec), 1)) == 0)
1107 return FALSE;
1108#endif
1109 initPs2(pInfo,TRUE);
1110 break;
1111 case PROT_SYSMOUSE:
1112 if (osInfo->SetMiscRes)
1113 osInfo->SetMiscRes(pInfo, pMse->protocol, pMse->sampleRate,
1114 pMse->resolution);
1115 break;
1116
1117 default:
1118 /* Nothing to do. */
1119 break;
1120 }
1121
1122
1123 pMse->protoBufTail = 0;
1124 pMse->inSync = 0;
1125
1126 return TRUE;
1127}
1128
1129static void
1130MouseReadInput(InputInfoPtr pInfo)
1131{
1132 MouseDevPtr pMse;
1133 int j, buttons, dx, dy, dz, dw, baddata;
1134 int pBufP;
1135 int c;
1136 unsigned char *pBuf, u;
1137
1138 pMse = pInfo->private;
1139 pBufP = pMse->protoBufTail;
1140 pBuf = pMse->protoBuf;
1141
1142 /*
1143 * Set blocking to -1 on the first call because we know there is data to
1144 * read. Xisb automatically clears it after one successful read so that
1145 * succeeding reads are preceeded by a select with a 0 timeout to prevent
1146 * read from blocking indefinitely.
1147 */
1148 XisbBlockDuration(pMse->buffer, -1);
1149
1150 while ((c = XisbRead(pMse->buffer)) >= 0) {
1151 u = (unsigned char)c;
1152
1153 if (pMse->class & (MSE_PS2 | MSE_XPS2)) {
1154 if (ps2mouseReset(pInfo,u)) {
1155 pBufP = 0;
1156 continue;
1157 }
1158 }
1159
1160 if (pBufP >= pMse->protoPara[4]) {
1161 /*
1162 * Buffer contains a full packet, which has already been processed:
1163 * Empty the buffer and check for optional 4th byte, which will be
1164 * processed directly, without being put into the buffer first.
1165 */
1166 pBufP = 0;
1167
1168 if ((u & pMse->protoPara[0]) != pMse->protoPara[1] &&
1169 (u & pMse->protoPara[5]) == pMse->protoPara[6]) {
1170 /*
1171 * Hack for Logitech MouseMan Mouse - Middle button
1172 *
1173 * Unfortunately this mouse has variable length packets: the
1174 * standard Microsoft 3 byte packet plus an optional 4th byte
1175 * whenever the middle button status changes.
1176 *
1177 * We have already processed the standard packet with the
1178 * movement and button info. Now post an event message with
1179 * the old status of the left and right buttons and the
1180 * updated middle button.
1181 */
1182 /*
1183 * Even worse, different MouseMen and TrackMen differ in the
1184 * 4th byte: some will send 0x00/0x20, others 0x01/0x21, or
1185 * even 0x02/0x22, so I have to strip off the lower bits.
1186 * [CHRIS-211092]
1187 *
1188 * [JCH-96/01/21]
1189 * HACK for ALPS "fourth button". (It's bit 0x10 of the
1190 * "fourth byte" and it is activated by tapping the glidepad
1191 * with the finger! 8^) We map it to bit bit3, and the
1192 * reverse map in xf86Events just has to be extended so that
1193 * it is identified as Button 4. The lower half of the
1194 * reverse-map may remain unchanged.
1195 */
1196 /*
1197 * [KAZU-030897]
1198 * Receive the fourth byte only when preceeding three bytes
1199 * have been detected (pBufP >= pMse->protoPara[4]). In the
1200 * previous versions, the test was pBufP == 0; we may have
1201 * mistakingly received a byte even if we didn't see anything
1202 * preceeding the byte.
1203 */
1204
1205#ifdef EXTMOUSEDEBUG
1206 ErrorF("mouse 4th byte %02x",u);
1207#endif
1208 dx = dy = dz = dw = 0;
1209 buttons = 0;
1210 switch (pMse->protocolID) {
1211
1212 /*
1213 * [KAZU-221197]
1214 * IntelliMouse, NetMouse (including NetMouse Pro) and Mie
1215 * Mouse always send the fourth byte, whereas the fourth byte
1216 * is optional for GlidePoint and ThinkingMouse. The fourth
1217 * byte is also optional for MouseMan+ and FirstMouse+ in
1218 * their native mode. It is always sent if they are in the
1219 * IntelliMouse compatible mode.
1220 */
1221 case PROT_IMSERIAL: /* IntelliMouse, NetMouse, Mie Mouse,
1222 MouseMan+ */
1223 dz = (u & 0x08) ?
1224 (u & 0x0f) - 16 : (u & 0x0f);
1225 if ((dz >= 7) || (dz <= -7))
1226 dz = 0;
1227 buttons |= ((int)(u & 0x10) >> 3)
1228 | ((int)(u & 0x20) >> 2)
1229 | (pMse->lastButtons & 0x05);
1230 break;
1231
1232 case PROT_GLIDE:
1233 case PROT_THINKING:
1234 buttons |= ((int)(u & 0x10) >> 1);
1235 /* fall through */
1236
1237 default:
1238 buttons |= ((int)(u & 0x20) >> 4) |
1239 (pMse->lastButtons & 0x05);
1240 break;
1241 }
1242 goto post_event;
1243 }
1244 }
1245 /* End of packet buffer flush and 4th byte hack. */
1246
1247 /*
1248 * Append next byte to buffer (which is empty or contains an
1249 * incomplete packet); iterate if packet (still) not complete.
1250 */
1251 pBuf[pBufP++] = u;
1252 if (pBufP != pMse->protoPara[4]) continue;
1253#ifdef EXTMOUSEDEBUG2
1254 {
1255 int i;
1256 ErrorF("received %d bytes",pBufP);
1257 for ( i=0; i < pBufP; i++)
1258 ErrorF(" %02x",pBuf[i]);
1259 ErrorF("\n");
1260 }
1261#endif
1262
1263 /*
1264 * Hack for resyncing: We check here for a package that is:
1265 * a) illegal (detected by wrong data-package header)
1266 * b) invalid (0x80 == -128 and that might be wrong for MouseSystems)
1267 * c) bad header-package
1268 *
1269 * NOTE: b) is a violation of the MouseSystems-Protocol, since values
1270 * of -128 are allowed, but since they are very seldom we can
1271 * easily use them as package-header with no button pressed.
1272 * NOTE/2: On a PS/2 mouse any byte is valid as a data byte.
1273 * Furthermore, 0x80 is not valid as a header byte. For a PS/2
1274 * mouse we skip checking data bytes. For resyncing a PS/2
1275 * mouse we require the two most significant bits in the header
1276 * byte to be 0. These are the overflow bits, and in case of
1277 * an overflow we actually lose sync. Overflows are very rare,
1278 * however, and we quickly gain sync again after an overflow
1279 * condition. This is the best we can do. (Actually, we could
1280 * use bit 0x08 in the header byte for resyncing, since that
1281 * bit is supposed to be always on, but nobody told Microsoft...)
1282 */
1283
1284 /*
1285 * [KAZU,OYVIND-120398]
1286 * The above hack is wrong! Because of b) above, we shall see
1287 * erroneous mouse events so often when the MouseSystem mouse is
1288 * moved quickly. As for the PS/2 and its variants, we don't need
1289 * to treat them as special cases, because protoPara[2] and
1290 * protoPara[3] are both 0x00 for them, thus, any data bytes will
1291 * never be discarded. 0x80 is rejected for MMSeries, Logitech
1292 * and MMHittab protocols, because protoPara[2] and protoPara[3]
1293 * are 0x80 and 0x00 respectively. The other protocols are 7-bit
1294 * protocols; there is no use checking 0x80.
1295 *
1296 * All in all we should check the condition a) only.
1297 */
1298
1299 /*
1300 * [OYVIND-120498]
1301 * Check packet for valid data:
1302 * If driver is in sync with datastream, the packet is considered
1303 * bad if any byte (header and/or data) contains an invalid value.
1304 *
1305 * If packet is bad, we discard the first byte and shift the buffer.
1306 * Next iteration will then check the new situation for validity.
1307 *
1308 * If flag MF_SAFE is set in proto[7] and the driver
1309 * is out of sync, the packet is also considered bad if
1310 * any of the data bytes contains a valid header byte value.
1311 * This situation could occur if the buffer contains
1312 * the tail of one packet and the header of the next.
1313 *
1314 * Note: The driver starts in out-of-sync mode (pMse->inSync = 0).
1315 */
1316
1317 baddata = 0;
1318
1319 /* All databytes must be valid. */
1320 for (j = 1; j < pBufP; j++ )
1321 if ((pBuf[j] & pMse->protoPara[2]) != pMse->protoPara[3])
1322 baddata = 1;
1323
1324 /* If out of sync, don't mistake a header byte for data. */
1325 if ((pMse->protoPara[7] & MPF_SAFE) && !pMse->inSync)
1326 for (j = 1; j < pBufP; j++ )
1327 if ((pBuf[j] & pMse->protoPara[0]) == pMse->protoPara[1])
1328 baddata = 1;
1329
1330 /* Accept or reject the packet ? */
1331 if ((pBuf[0] & pMse->protoPara[0]) != pMse->protoPara[1] || baddata) {
1332#ifdef EXTMOUSEDEBUG
1333 if (pMse->inSync)
1334 ErrorF("mouse driver lost sync\n");
1335 ErrorF("skipping byte %02x\n",*pBuf);
1336#endif
1337 pMse->protoBufTail = --pBufP;
1338 for (j = 0; j < pBufP; j++)
1339 pBuf[j] = pBuf[j+1];
1340 pMse->inSync = 0;
1341 continue;
1342 }
1343
1344 if (!pMse->inSync) {
1345#ifdef EXTMOUSEDEBUG
1346 ErrorF("mouse driver back in sync\n");
1347#endif
1348 pMse->inSync = 1;
1349 }
1350
1351 /*
1352 * Packet complete and verified, now process it ...
1353 */
1354
1355 dz = dw = 0;
1356 switch (pMse->protocolID) {
1357 case PROT_LOGIMAN: /* MouseMan / TrackMan [CHRIS-211092] */
1358 case PROT_MS: /* Microsoft */
1359 if (pMse->chordMiddle)
1360 buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 :
1361 ((int)(pBuf[0] & 0x20) >> 3)
1362 | ((int)(pBuf[0] & 0x10) >> 4);
1363 else
1364 buttons = (pMse->lastButtons & 2)
1365 | ((int)(pBuf[0] & 0x20) >> 3)
1366 | ((int)(pBuf[0] & 0x10) >> 4);
1367 dx = (char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F));
1368 dy = (char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F));
1369 break;
1370
1371 case PROT_GLIDE: /* ALPS GlidePoint */
1372 case PROT_THINKING: /* ThinkingMouse */
1373 case PROT_IMSERIAL: /* IntelliMouse, NetMouse, Mie Mouse, MouseMan+ */
1374 buttons = (pMse->lastButtons & (8 + 2))
1375 | ((int)(pBuf[0] & 0x20) >> 3)
1376 | ((int)(pBuf[0] & 0x10) >> 4);
1377 dx = (char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F));
1378 dy = (char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F));
1379 break;
1380
1381 case PROT_MSC: /* Mouse Systems Corp */
1382 buttons = (~pBuf[0]) & 0x07;
1383 dx = (char)(pBuf[1]) + (char)(pBuf[3]);
1384 dy = - ((char)(pBuf[2]) + (char)(pBuf[4]));
1385 break;
1386
1387 case PROT_MMHIT: /* MM_HitTablet */
1388 buttons = pBuf[0] & 0x07;
1389 if (buttons != 0)
1390 buttons = 1 << (buttons - 1);
1391 dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1];
1392 dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2];
1393 break;
1394
1395 case PROT_ACECAD: /* ACECAD */
1396 /* ACECAD is almost exactly like MM but the buttons are different */
1397 buttons = (pBuf[0] & 0x02) | ((pBuf[0] & 0x04) >> 2) |
1398 ((pBuf[0] & 1) << 2);
1399 dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1];
1400 dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2];
1401 break;
1402
1403 case PROT_MM: /* MM Series */
1404 case PROT_LOGI: /* Logitech Mice */
1405 buttons = pBuf[0] & 0x07;
1406 dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1];
1407 dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2];
1408 break;
1409
1410 case PROT_BM: /* BusMouse */
1411 buttons = (~pBuf[0]) & 0x07;
1412 dx = (char)pBuf[1];
1413 dy = - (char)pBuf[2];
1414 break;
1415
1416 case PROT_PS2: /* PS/2 mouse */
1417 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1418 (pBuf[0] & 0x02) >> 1 | /* Right */
1419 (pBuf[0] & 0x01) << 2; /* Left */
1420 dx = (pBuf[0] & 0x10) ? (int)pBuf[1]-256 : (int)pBuf[1];
1421 dy = (pBuf[0] & 0x20) ? -((int)pBuf[2]-256) : -(int)pBuf[2];
1422 break;
1423
1424 /* PS/2 mouse variants */
1425 case PROT_IMPS2: /* IntelliMouse PS/2 */
1426 case PROT_NETPS2: /* NetMouse PS/2 */
1427 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1428 (pBuf[0] & 0x02) >> 1 | /* Right */
1429 (pBuf[0] & 0x01) << 2 | /* Left */
1430 (pBuf[0] & 0x40) >> 3 | /* button 4 */
1431 (pBuf[0] & 0x80) >> 3; /* button 5 */
1432 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1];
1433 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2];
1434 dz = (char)pBuf[3];
1435 if ((dz >= 7) || (dz <= -7))
1436 dz = 0;
1437 break;
1438
1439 case PROT_EXPPS2: /* IntelliMouse Explorer PS/2 */
1440 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1441 (pBuf[0] & 0x02) >> 1 | /* Right */
1442 (pBuf[0] & 0x01) << 2 | /* Left */
1443 (pBuf[3] & 0x10) >> 1 | /* button 4 */
1444 (pBuf[3] & 0x20) >> 1; /* button 5 */
1445 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1];
1446 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2];
1447 dz = (pBuf[3] & 0x08) ? (pBuf[3] & 0x0f) - 16 : (pBuf[3] & 0x0f);
1448 break;
1449
1450 case PROT_MMPS2: /* MouseMan+ PS/2 */
1451 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1452 (pBuf[0] & 0x02) >> 1 | /* Right */
1453 (pBuf[0] & 0x01) << 2; /* Left */
1454 dx = (pBuf[0] & 0x10) ? pBuf[1] - 256 : pBuf[1];
1455 if (((pBuf[0] & 0x48) == 0x48) &&
1456 (abs(dx) > 191) &&
1457 ((((pBuf[2] & 0x03) << 2) | 0x02) == (pBuf[1] & 0x0f))) {
1458 /* extended data packet */
1459 switch ((((pBuf[0] & 0x30) >> 2) | ((pBuf[1] & 0x30) >> 4))) {
1460 case 1: /* wheel data packet */
1461 buttons |= ((pBuf[2] & 0x10) ? 0x08 : 0) | /* 4th button */
1462 ((pBuf[2] & 0x20) ? 0x10 : 0); /* 5th button */
1463 dx = dy = 0;
1464 dz = (pBuf[2] & 0x08) ? (pBuf[2] & 0x0f) - 16 :
1465 (pBuf[2] & 0x0f);
1466 break;
1467 case 2: /* Logitech reserves this packet type */
1468 /*
1469 * IBM ScrollPoint uses this packet to encode its
1470 * stick movement.
1471 */
1472 buttons |= (pMse->lastButtons & ~0x07);
1473 dx = dy = 0;
1474 dz = (pBuf[2] & 0x80) ? ((pBuf[2] >> 4) & 0x0f) - 16 :
1475 ((pBuf[2] >> 4) & 0x0f);
1476 dw = (pBuf[2] & 0x08) ? (pBuf[2] & 0x0f) - 16 :
1477 (pBuf[2] & 0x0f);
1478 break;
1479 case 0: /* device type packet - shouldn't happen */
1480 default:
1481 buttons |= (pMse->lastButtons & ~0x07);
1482 dx = dy = 0;
1483 dz = 0;
1484 break;
1485 }
1486 } else {
1487 buttons |= (pMse->lastButtons & ~0x07);
1488 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1];
1489 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2];
1490 }
1491 break;
1492
1493 case PROT_GLIDEPS2: /* GlidePoint PS/2 */
1494 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1495 (pBuf[0] & 0x02) >> 1 | /* Right */
1496 (pBuf[0] & 0x01) << 2 | /* Left */
1497 ((pBuf[0] & 0x08) ? 0 : 0x08);/* fourth button */
1498 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1];
1499 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2];
1500 break;
1501
1502 case PROT_NETSCPS2: /* NetScroll PS/2 */
1503 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1504 (pBuf[0] & 0x02) >> 1 | /* Right */
1505 (pBuf[0] & 0x01) << 2 | /* Left */
1506 ((pBuf[3] & 0x02) ? 0x08 : 0) | /* button 4 */
1507 ((pBuf[3] & 0x01) ? 0x10 : 0); /* button 5 */
1508 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1];
1509 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2];
1510 dz = (pBuf[3] & 0x10) ? pBuf[4] - 256 : pBuf[4];
1511 break;
1512
1513 case PROT_THINKPS2: /* ThinkingMouse PS/2 */
1514 buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
1515 (pBuf[0] & 0x02) >> 1 | /* Right */
1516 (pBuf[0] & 0x01) << 2 | /* Left */
1517 ((pBuf[0] & 0x08) ? 0x08 : 0);/* fourth button */
1518 pBuf[1] |= (pBuf[0] & 0x40) ? 0x80 : 0x00;
1519 dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1];
1520 dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2];
1521 break;
1522
1523 case PROT_SYSMOUSE: /* sysmouse */
1524 buttons = (~pBuf[0]) & 0x07;
1525 dx = (char)(pBuf[1]) + (char)(pBuf[3]);
1526 dy = - ((char)(pBuf[2]) + (char)(pBuf[4]));
1527 /* FreeBSD sysmouse sends additional data bytes */
1528 if (pMse->protoPara[4] >= 8) {
1529 dz = ((char)(pBuf[5] << 1) + (char)(pBuf[6] << 1)) / 2;
1530 buttons |= (int)(~pBuf[7] & 0x07) << 3;
1531 }
1532 break;
1533
1534 default: /* There's a table error */
1535#ifdef EXTMOUSEDEBUG
1536 ErrorF("mouse table error\n");
1537#endif
1538 continue;
1539 }
1540
1541#ifdef EXTMOUSEDEBUG
1542 ErrorF("packet");
1543 for ( j=0; j < pBufP; j++)
1544 ErrorF(" %02x",pBuf[j]);
1545#endif
1546
1547post_event:
1548 /* post an event */
1549 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
1550
1551 /*
1552 * We don't reset pBufP here yet, as there may be an additional data
1553 * byte in some protocols. See above.
1554 */
1555 }
1556 pMse->protoBufTail = pBufP;
1557}
1558
1559/*
1560 * MouseCtrl --
1561 * Alter the control parameters for the mouse. Note that all special
1562 * protocol values are handled by dix.
1563 */
1564
1565static void
1566MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
1567{
1568 InputInfoPtr pInfo;
1569 MouseDevPtr pMse;
1570
1571 pInfo = device->public.devicePrivate;
1572 pMse = pInfo->private;
1573
1574#ifdef EXTMOUSEDEBUG
1575 ErrorF("MouseCtrl pMse=%p\n", pMse);
1576#endif
1577
1578 pMse->num = ctrl->num;
1579 pMse->den = ctrl->den;
1580 pMse->threshold = ctrl->threshold;
1581}
1582
1583/*
1584 ***************************************************************************
1585 *
1586 * MouseProc --
1587 *
1588 ***************************************************************************
1589 */
1590static int
1591MouseProc(DeviceIntPtr device, int what)
1592{
1593 InputInfoPtr pInfo;
1594 MouseDevPtr pMse;
1595 unsigned char map[MSE_MAXBUTTONS + 1];
1596 int i, blocked;
1597#ifdef VBOX
1598 mousePrivPtr pPriv;
1599#endif
1600
1601 pInfo = device->public.devicePrivate;
1602 pMse = pInfo->private;
1603 pMse->device = device;
1604#ifdef VBOX
1605 pPriv = pMse->mousePriv;
1606#endif
1607
1608 switch (what)
1609 {
1610 case DEVICE_INIT:
1611 device->public.on = FALSE;
1612 /*
1613 * [KAZU-241097] We don't know exactly how many buttons the
1614 * device has, so setup the map with the maximum number.
1615 */
1616 for (i = 0; i < MSE_MAXBUTTONS; i++)
1617 map[i + 1] = i + 1;
1618
1619 InitPointerDeviceStruct((DevicePtr)device, map,
1620 min(pMse->buttons, MSE_MAXBUTTONS),
1621 miPointerGetMotionEvents, pMse->Ctrl,
1622 miPointerGetMotionBufferSize());
1623
1624 /* X valuator */
1625 xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
1626 xf86InitValuatorDefaults(device, 0);
1627 /* Y valuator */
1628 xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
1629 xf86InitValuatorDefaults(device, 1);
1630 xf86MotionHistoryAllocate(pInfo);
1631
1632#ifdef EXTMOUSEDEBUG
1633 ErrorF("assigning %p atom=%d name=%s\n", device, pInfo->atom,
1634 pInfo->name);
1635#endif
1636 break;
1637
1638 case DEVICE_ON:
1639#ifdef VBOX
1640 if (!pPriv)
1641 {
1642 pPriv = (pointer)xcalloc(sizeof(mousePrivRec), 1);
1643 if (pPriv)
1644 {
1645 pMse->mousePriv = pPriv;
1646 pPriv->pScrn = 0;
1647 pPriv->screen_no = xf86SetIntOption(pInfo->options,
1648 "ScreenNo", 0);
1649 xf86Msg(X_CONFIG, "VirtualBox Mouse Integration associated with screen %d\n",
1650 pPriv->screen_no);
1651 }
1652 }
1653 if (pPriv)
1654 {
1655 if ( pPriv->screen_no >= screenInfo.numScreens
1656 || pPriv->screen_no < 0)
1657 {
1658 pPriv->screen_no = 0;
1659 }
1660 VBoxMouseInit();
1661 pPriv->pScrn = screenInfo.screens[pPriv->screen_no];
1662 }
1663#endif
1664 pInfo->fd = xf86OpenSerial(pInfo->options);
1665 if (pInfo->fd == -1)
1666 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
1667 else {
1668 pMse->buffer = XisbNew(pInfo->fd, 64);
1669 if (!pMse->buffer) {
1670 xf86CloseSerial(pInfo->fd);
1671 pInfo->fd = -1;
1672 } else {
1673 if (!SetupMouse(pInfo)) {
1674 xf86CloseSerial(pInfo->fd);
1675 pInfo->fd = -1;
1676 XisbFree(pMse->buffer);
1677 pMse->buffer = NULL;
1678 } else {
1679 xf86FlushInput(pInfo->fd);
1680 if (pMse->protocolID == PROT_PS2)
1681 xf86WriteSerial(pInfo->fd, "\364", 1);
1682 xf86AddEnabledDevice(pInfo);
1683 }
1684 }
1685 }
1686 pMse->lastButtons = 0;
1687 pMse->emulateState = 0;
1688 pMse->emulate3Pending = FALSE;
1689 device->public.on = TRUE;
1690 /*
1691 * send button up events for sanity. If no button down is pending
1692 * xf86PostButtonEvent() will discard them. So we are on the safe side.
1693 */
1694 blocked = xf86BlockSIGIO ();
1695 for (i = 1; i <= 5; i++)
1696 xf86PostButtonEvent(device,0,i,0,0,0);
1697 xf86UnblockSIGIO (blocked);
1698 if (pMse->emulate3Buttons)
1699 {
1700 RegisterBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
1701 (pointer) pInfo);
1702 }
1703 break;
1704
1705 case DEVICE_OFF:
1706 case DEVICE_CLOSE:
1707#ifdef VBOX
1708 if (VBoxMouseFini())
1709 {
1710 /** @todo what to do? */
1711 }
1712#endif
1713 if (pInfo->fd != -1) {
1714 xf86RemoveEnabledDevice(pInfo);
1715 if (pMse->buffer) {
1716 XisbFree(pMse->buffer);
1717 pMse->buffer = NULL;
1718 }
1719 if (pMse->mousePriv)
1720 xfree(pMse->mousePriv);
1721 pMse->mousePriv = NULL;
1722 xf86CloseSerial(pInfo->fd);
1723 pInfo->fd = -1;
1724 if (pMse->emulate3Buttons)
1725 {
1726 RemoveBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler,
1727 (pointer) pInfo);
1728 }
1729 }
1730 device->public.on = FALSE;
1731 usleep(300000);
1732 break;
1733 }
1734 return Success;
1735}
1736
1737/*
1738 ***************************************************************************
1739 *
1740 * MouseConvert --
1741 * Convert valuators to X and Y.
1742 *
1743 ***************************************************************************
1744 */
1745static Bool
1746MouseConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
1747 int v3, int v4, int v5, int *x, int *y)
1748{
1749 if (first != 0 || num != 2)
1750 return FALSE;
1751
1752 *x = v0;
1753 *y = v1;
1754
1755 return TRUE;
1756}
1757
1758/*
1759 * Lets create a simple finite-state machine for 3 button emulation:
1760 *
1761 * We track buttons 1 and 3 (left and right). There are 11 states:
1762 * 0 ground - initial state
1763 * 1 delayed left - left pressed, waiting for right
1764 * 2 delayed right - right pressed, waiting for left
1765 * 3 pressed middle - right and left pressed, emulated middle sent
1766 * 4 pressed left - left pressed and sent
1767 * 5 pressed right - right pressed and sent
1768 * 6 released left - left released after emulated middle
1769 * 7 released right - right released after emulated middle
1770 * 8 repressed left - left pressed after released left
1771 * 9 repressed right - right pressed after released right
1772 * 10 pressed both - both pressed, not emulating middle
1773 *
1774 * At each state, we need handlers for the following events
1775 * 0: no buttons down
1776 * 1: left button down
1777 * 2: right button down
1778 * 3: both buttons down
1779 * 4: emulate3Timeout passed without a button change
1780 * Note that button events are not deltas, they are the set of buttons being
1781 * pressed now. It's possible (ie, mouse hardware does it) to go from (eg)
1782 * left down to right down without anything in between, so all cases must be
1783 * handled.
1784 *
1785 * a handler consists of three values:
1786 * 0: action1
1787 * 1: action2
1788 * 2: new emulation state
1789 *
1790 * action > 0: ButtonPress
1791 * action = 0: nothing
1792 * action < 0: ButtonRelease
1793 *
1794 * The comment preceeding each section is the current emulation state.
1795 * The comments to the right are of the form
1796 * <button state> (<events>) -> <new emulation state>
1797 * which should be read as
1798 * If the buttons are in <button state>, generate <events> then go to
1799 * <new emulation state>.
1800 */
1801static signed char stateTab[11][5][3] = {
1802/* 0 ground */
1803 {
1804 { 0, 0, 0 }, /* nothing -> ground (no change) */
1805 { 0, 0, 1 }, /* left -> delayed left */
1806 { 0, 0, 2 }, /* right -> delayed right */
1807 { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
1808 { 0, 0, -1 } /* timeout N/A */
1809 },
1810/* 1 delayed left */
1811 {
1812 { 1, -1, 0 }, /* nothing (left event) -> ground */
1813 { 0, 0, 1 }, /* left -> delayed left (no change) */
1814 { 1, -1, 2 }, /* right (left event) -> delayed right */
1815 { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
1816 { 1, 0, 4 }, /* timeout (left press) -> pressed left */
1817 },
1818/* 2 delayed right */
1819 {
1820 { 3, -3, 0 }, /* nothing (right event) -> ground */
1821 { 3, -3, 1 }, /* left (right event) -> delayed left (no change) */
1822 { 0, 0, 2 }, /* right -> delayed right (no change) */
1823 { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */
1824 { 3, 0, 5 }, /* timeout (right press) -> pressed right */
1825 },
1826/* 3 pressed middle */
1827 {
1828 { -2, 0, 0 }, /* nothing (middle release) -> ground */
1829 { 0, 0, 7 }, /* left -> released right */
1830 { 0, 0, 6 }, /* right -> released left */
1831 { 0, 0, 3 }, /* left & right -> pressed middle (no change) */
1832 { 0, 0, -1 }, /* timeout N/A */
1833 },
1834/* 4 pressed left */
1835 {
1836 { -1, 0, 0 }, /* nothing (left release) -> ground */
1837 { 0, 0, 4 }, /* left -> pressed left (no change) */
1838 { -1, 0, 2 }, /* right (left release) -> delayed right */
1839 { 3, 0, 10 }, /* left & right (right press) -> pressed both */
1840 { 0, 0, -1 }, /* timeout N/A */
1841 },
1842/* 5 pressed right */
1843 {
1844 { -3, 0, 0 }, /* nothing (right release) -> ground */
1845 { -3, 0, 1 }, /* left (right release) -> delayed left */
1846 { 0, 0, 5 }, /* right -> pressed right (no change) */
1847 { 1, 0, 10 }, /* left & right (left press) -> pressed both */
1848 { 0, 0, -1 }, /* timeout N/A */
1849 },
1850/* 6 released left */
1851 {
1852 { -2, 0, 0 }, /* nothing (middle release) -> ground */
1853 { -2, 0, 1 }, /* left (middle release) -> delayed left */
1854 { 0, 0, 6 }, /* right -> released left (no change) */
1855 { 1, 0, 8 }, /* left & right (left press) -> repressed left */
1856 { 0, 0, -1 }, /* timeout N/A */
1857 },
1858/* 7 released right */
1859 {
1860 { -2, 0, 0 }, /* nothing (middle release) -> ground */
1861 { 0, 0, 7 }, /* left -> released right (no change) */
1862 { -2, 0, 2 }, /* right (middle release) -> delayed right */
1863 { 3, 0, 9 }, /* left & right (right press) -> repressed right */
1864 { 0, 0, -1 }, /* timeout N/A */
1865 },
1866/* 8 repressed left */
1867 {
1868 { -2, -1, 0 }, /* nothing (middle release, left release) -> ground */
1869 { -2, 0, 4 }, /* left (middle release) -> pressed left */
1870 { -1, 0, 6 }, /* right (left release) -> released left */
1871 { 0, 0, 8 }, /* left & right -> repressed left (no change) */
1872 { 0, 0, -1 }, /* timeout N/A */
1873 },
1874/* 9 repressed right */
1875 {
1876 { -2, -3, 0 }, /* nothing (middle release, right release) -> ground */
1877 { -3, 0, 7 }, /* left (right release) -> released right */
1878 { -2, 0, 5 }, /* right (middle release) -> pressed right */
1879 { 0, 0, 9 }, /* left & right -> repressed right (no change) */
1880 { 0, 0, -1 }, /* timeout N/A */
1881 },
1882/* 10 pressed both */
1883 {
1884 { -1, -3, 0 }, /* nothing (left release, right release) -> ground */
1885 { -3, 0, 4 }, /* left (right release) -> pressed left */
1886 { -1, 0, 5 }, /* right (left release) -> pressed right */
1887 { 0, 0, 10 }, /* left & right -> pressed both (no change) */
1888 { 0, 0, -1 }, /* timeout N/A */
1889 },
1890};
1891
1892/*
1893 * Table to allow quick reversal of natural button mapping to correct mapping
1894 */
1895
1896/*
1897 * [JCH-96/01/21] The ALPS GlidePoint pad extends the MS protocol
1898 * with a fourth button activated by tapping the PAD.
1899 * The 2nd line corresponds to 4th button on; the drv sends
1900 * the buttons in the following map (MSBit described first) :
1901 * 0 | 4th | 1st | 2nd | 3rd
1902 * And we remap them (MSBit described first) :
1903 * 0 | 4th | 3rd | 2nd | 1st
1904 */
1905static char reverseMap[32] = { 0, 4, 2, 6, 1, 5, 3, 7,
1906 8, 12, 10, 14, 9, 13, 11, 15,
1907 16, 20, 18, 22, 17, 21, 19, 23,
1908 24, 28, 26, 30, 25, 29, 27, 31};
1909
1910
1911static char hitachMap[16] = { 0, 2, 1, 3,
1912 8, 10, 9, 11,
1913 4, 6, 5, 7,
1914 12, 14, 13, 15 };
1915
1916#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f])
1917
1918static CARD32
1919buttonTimer(InputInfoPtr pInfo)
1920{
1921 MouseDevPtr pMse;
1922 int sigstate;
1923 int id;
1924
1925 pMse = pInfo->private;
1926
1927 sigstate = xf86BlockSIGIO ();
1928
1929 pMse->emulate3Pending = FALSE;
1930 if ((id = stateTab[pMse->emulateState][4][0]) != 0) {
1931 xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
1932 pMse->emulateState = stateTab[pMse->emulateState][4][2];
1933 } else {
1934 ErrorF("Got unexpected buttonTimer in state %d\n", pMse->emulateState);
1935 }
1936
1937 xf86UnblockSIGIO (sigstate);
1938 return 0;
1939}
1940
1941static void MouseBlockHandler(pointer data,
1942 struct timeval **waitTime,
1943 pointer LastSelectMask)
1944{
1945 InputInfoPtr pInfo = (InputInfoPtr) data;
1946 MouseDevPtr pMse = (MouseDevPtr) pInfo->private;
1947 int ms;
1948
1949 if (pMse->emulate3Pending)
1950 {
1951 ms = pMse->emulate3Expires - GetTimeInMillis ();
1952 if (ms <= 0)
1953 ms = 0;
1954 AdjustWaitForDelay (waitTime, ms);
1955 }
1956}
1957
1958static void MouseWakeupHandler(pointer data,
1959 int i,
1960 pointer LastSelectMask)
1961{
1962 InputInfoPtr pInfo = (InputInfoPtr) data;
1963 MouseDevPtr pMse = (MouseDevPtr) pInfo->private;
1964 int ms;
1965
1966 if (pMse->emulate3Pending)
1967 {
1968 ms = pMse->emulate3Expires - GetTimeInMillis ();
1969 if (ms <= 0)
1970 buttonTimer (pInfo);
1971 }
1972}
1973
1974static void
1975MouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy)
1976{
1977 MouseDevPtr pMse;
1978 int truebuttons, emulateButtons;
1979 int id, change;
1980 int emuWheelDelta, emuWheelButton, emuWheelButtonMask;
1981
1982 pMse = pInfo->private;
1983
1984 truebuttons = buttons;
1985 if (pMse->protocolID == PROT_MMHIT)
1986 buttons = reverseBits(hitachMap, buttons);
1987 else
1988 buttons = reverseBits(reverseMap, buttons);
1989
1990 /* Intercept wheel emulation. */
1991 if (pMse->emulateWheel && (buttons & pMse->wheelButtonMask)) {
1992 /* Y axis movement */
1993 if (pMse->negativeY != MSE_NOAXISMAP) {
1994 pMse->wheelYDistance += dy;
1995 if (pMse->wheelYDistance < 0) {
1996 emuWheelDelta = -pMse->wheelInertia;
1997 emuWheelButton = pMse->negativeY;
1998 } else {
1999 emuWheelDelta = pMse->wheelInertia;
2000 emuWheelButton = pMse->positiveY;
2001 }
2002 emuWheelButtonMask = 1 << (emuWheelButton - 1);
2003 while (abs(pMse->wheelYDistance) > pMse->wheelInertia) {
2004 pMse->wheelYDistance -= emuWheelDelta;
2005
2006 /*
2007 * Synthesize the press and release, but not when the button
2008 * to be synthesized is already pressed "for real".
2009 */
2010 if (!(emuWheelButtonMask & buttons) ||
2011 (emuWheelButtonMask & pMse->wheelButtonMask)) {
2012 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
2013 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
2014 }
2015 }
2016 }
2017
2018 /* X axis movement */
2019 if (pMse->negativeX != MSE_NOAXISMAP) {
2020 pMse->wheelXDistance += dx;
2021 if (pMse->wheelXDistance < 0) {
2022 emuWheelDelta = -pMse->wheelInertia;
2023 emuWheelButton = pMse->negativeX;
2024 } else {
2025 emuWheelDelta = pMse->wheelInertia;
2026 emuWheelButton = pMse->positiveX;
2027 }
2028 emuWheelButtonMask = 1 << (emuWheelButton - 1);
2029 while (abs(pMse->wheelXDistance) > pMse->wheelInertia) {
2030 pMse->wheelXDistance -= emuWheelDelta;
2031
2032 /*
2033 * Synthesize the press and release, but not when the button
2034 * to be synthesized is already pressed "for real".
2035 */
2036 if (!(emuWheelButtonMask & buttons) ||
2037 (emuWheelButtonMask & pMse->wheelButtonMask)) {
2038 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
2039 xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
2040 }
2041 }
2042 }
2043
2044 /* Absorb the mouse movement and the wheel button press. */
2045 dx = 0;
2046 dy = 0;
2047 buttons &= ~pMse->wheelButtonMask;
2048 }
2049
2050#ifdef VBOX
2051 if (dx || dy)
2052 {
2053 mousePrivPtr pPriv = pMse->mousePriv;
2054 if (pPriv && pPriv->pScrn)
2055 {
2056 unsigned int abs_x;
2057 unsigned int abs_y;
2058 if (VBoxMouseQueryPosition(&abs_x, &abs_y) == 0)
2059 {
2060 /* convert to screen resolution */
2061 int x, y;
2062 x = (abs_x * pPriv->pScrn->width) / 65535;
2063 y = (abs_y * pPriv->pScrn->height) / 65535;
2064 /* send absolute movement */
2065 xf86PostMotionEvent(pInfo->dev, 1, 0, 2, x, y);
2066 }
2067 else
2068 {
2069 /* send relative event */
2070 xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
2071 }
2072 }
2073 else
2074 {
2075 /* send relative event */
2076 xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
2077 }
2078 }
2079#else
2080 if (dx || dy)
2081 xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
2082#endif /* !VBOX */
2083
2084 if (truebuttons != pMse->lastButtons) {
2085
2086 if (pMse->protocolID == PROT_MMHIT)
2087 change = buttons ^ reverseBits(hitachMap, pMse->lastButtons);
2088 else
2089 change = buttons ^ reverseBits(reverseMap, pMse->lastButtons);
2090
2091 if (pMse->emulate3Buttons) {
2092
2093 /* handle all but buttons 1 & 3 normally */
2094
2095 change &= ~05;
2096
2097 /* emulate the third button by the other two */
2098
2099 emulateButtons = (buttons & 01) | ((buttons &04) >> 1);
2100
2101 if ((id = stateTab[pMse->emulateState][emulateButtons][0]) != 0)
2102 xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
2103 if ((id = stateTab[pMse->emulateState][emulateButtons][1]) != 0)
2104 xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
2105
2106 pMse->emulateState =
2107 stateTab[pMse->emulateState][emulateButtons][2];
2108
2109 if (stateTab[pMse->emulateState][4][0] != 0) {
2110 pMse->emulate3Expires = GetTimeInMillis () + pMse->emulate3Timeout;
2111 pMse->emulate3Pending = TRUE;
2112 } else {
2113 pMse->emulate3Pending = FALSE;
2114 }
2115 }
2116
2117 while (change) {
2118 id = ffs(change);
2119 change &= ~(1 << (id - 1));
2120 xf86PostButtonEvent(pInfo->dev, 0, id,
2121 (buttons & (1 << (id - 1))), 0, 0);
2122 }
2123
2124 pMse->lastButtons = truebuttons;
2125 }
2126}
2127
2128static void
2129MousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw)
2130{
2131 MouseDevPtr pMse;
2132 int zbutton = 0;
2133
2134
2135 pMse = pInfo->private;
2136
2137 /* Map the Z axis movement. */
2138 /* XXX Could this go in the conversion_proc? */
2139 switch (pMse->negativeZ) {
2140 case MSE_NOZMAP: /* do nothing */
2141 break;
2142 case MSE_MAPTOX:
2143 if (dz != 0) {
2144 dx = dz;
2145 dz = 0;
2146 }
2147 break;
2148 case MSE_MAPTOY:
2149 if (dz != 0) {
2150 dy = dz;
2151 dz = 0;
2152 }
2153 break;
2154 default: /* buttons */
2155 buttons &= ~(pMse->negativeZ | pMse->positiveZ
2156 | pMse->negativeW | pMse->positiveW);
2157 if (dw < 0 || dz < -1)
2158 zbutton = pMse->negativeW;
2159 else if (dz < 0)
2160 zbutton = pMse->negativeZ;
2161 else if (dw > 0 || dz > 1)
2162 zbutton = pMse->positiveW;
2163 else if (dz > 0)
2164 zbutton = pMse->positiveZ;
2165 buttons |= zbutton;
2166 dz = 0;
2167 break;
2168 }
2169 dx = pMse->invX * dx;
2170 dy = pMse->invY * dy;
2171 if (pMse->flipXY) {
2172 int tmp = dx;
2173 dx = dy;
2174 dy = tmp;
2175 }
2176 MouseDoPostEvent(pInfo, buttons, dx, dy);
2177
2178 /*
2179 * If dz has been mapped to a button `down' event, we need to cook up
2180 * a corresponding button `up' event.
2181 */
2182 if (zbutton) {
2183 buttons &= ~zbutton;
2184 MouseDoPostEvent(pInfo, buttons, 0, 0);
2185 }
2186}
2187
2188static void
2189initPs2(InputInfoPtr pInfo, Bool reinsert)
2190{
2191 MouseDevPtr pMse = pInfo->private;
2192 unsigned char *param = NULL;
2193 int paramlen = 0;
2194 unsigned char c;
2195
2196 if (reinsert) {
2197 unsigned char init = 0xF4;
2198 if (xf86WriteSerial(pInfo->fd, &init, 1) != 1)
2199 xf86Msg(X_ERROR, "%s: Write to mouse failed\n", pInfo->name);
2200 usleep(30000);
2201 xf86FlushInput(pInfo->fd);
2202 }
2203
2204 switch (pMse->protocolID) {
2205 case PROT_IMPS2: /* IntelliMouse */
2206 {
2207 static unsigned char seq[] = { 243, 200, 243, 100, 243, 80, 242 };
2208
2209 param = seq;
2210 paramlen = sizeof(seq);
2211 }
2212 break;
2213
2214 case PROT_EXPPS2: /* IntelliMouse Explorer */
2215 {
2216 static unsigned char seq[] = { 243, 200, 243, 100, 243, 80,
2217 243, 200, 243, 200, 243, 80, 242 };
2218
2219 param = seq;
2220 paramlen = sizeof(seq);
2221 }
2222 break;
2223
2224 case PROT_NETPS2: /* NetMouse, NetMouse Pro, Mie Mouse */
2225 case PROT_NETSCPS2: /* NetScroll */
2226 {
2227 static unsigned char seq[] = { 232, 3, 230, 230, 230, };
2228
2229 param = seq;
2230 paramlen = sizeof(seq);
2231 }
2232 break;
2233
2234 case PROT_MMPS2: /* MouseMan+, FirstMouse+ */
2235 {
2236 static unsigned char seq[] = { 230, 232, 0, 232, 3, 232, 2, 232, 1,
2237 230, 232, 3, 232, 1, 232, 2, 232, 3, };
2238 param = seq;
2239 paramlen = sizeof(seq);
2240 }
2241 break;
2242
2243 case PROT_THINKPS2: /* ThinkingMouse */
2244 {
2245 static unsigned char seq[] = { 243, 10, 232, 0, 243, 20, 243, 60,
2246 243, 40, 243, 20, 243, 20, 243, 60,
2247 243, 40, 243, 20, 243, 20, };
2248 param = seq;
2249 paramlen = sizeof(seq);
2250 }
2251 }
2252
2253 if (paramlen > 0) {
2254#ifdef EXTMOUSEDEBUG
2255 for (i = 0; i < paramlen; ++i) {
2256 if (xf86WriteSerial(pInfo->fd, &param[i], 1) != 1)
2257 ErrorF("SetupMouse: Write to mouse failed (%s)\n",
2258 strerror(errno));
2259 usleep(30000);
2260 xf86ReadSerial(pInfo->fd, &c, 1);
2261 ErrorF("SetupMouse: got %02x\n", c);
2262 }
2263#else
2264 if (xf86WriteSerial(pInfo->fd, param, paramlen) != paramlen)
2265 xf86Msg(X_ERROR, "%s: Write to mouse failed\n", pInfo->name);
2266#endif
2267 usleep(30000);
2268 xf86FlushInput(pInfo->fd);
2269 }
2270
2271#ifdef VBOX
2272 ((mousePrivPtr)(pMse->mousePriv))->ps2_state = 0;
2273#else
2274 ((ps2PrivPtr)(pMse->mousePriv))->state = 0;
2275#endif
2276 if (osInfo->SetPS2Res) {
2277 osInfo->SetPS2Res(pInfo, pMse->protocol, pMse->sampleRate,
2278 pMse->resolution);
2279 } else {
2280 unsigned char c2[2];
2281
2282 c = 230; /* 1:1 scaling */
2283 xf86WriteSerial(pInfo->fd, &c, 1);
2284 c = 244; /* enable mouse */
2285 xf86WriteSerial(pInfo->fd, &c, 1);
2286 c2[0] = 243; /* set sampling rate */
2287 if (pMse->sampleRate > 0) {
2288 if (pMse->sampleRate >= 200)
2289 c2[1] = 200;
2290 else if (pMse->sampleRate >= 100)
2291 c2[1] = 100;
2292 else if (pMse->sampleRate >= 80)
2293 c2[1] = 80;
2294 else if (pMse->sampleRate >= 60)
2295 c2[1] = 60;
2296 else if (pMse->sampleRate >= 40)
2297 c2[1] = 40;
2298 else
2299 c2[1] = 20;
2300 } else {
2301 c2[1] = 100;
2302 }
2303 xf86WriteSerial(pInfo->fd, c2, 2);
2304 c2[0] = 232; /* set device resolution */
2305 if (pMse->resolution > 0) {
2306 if (pMse->resolution >= 200)
2307 c2[1] = 3;
2308 else if (pMse->resolution >= 100)
2309 c2[1] = 2;
2310 else if (pMse->resolution >= 50)
2311 c2[1] = 1;
2312 else
2313 c2[1] = 0;
2314 } else {
2315 c2[1] = 2;
2316 }
2317 xf86WriteSerial(pInfo->fd, c2, 2);
2318 usleep(30000);
2319 xf86FlushInput(pInfo->fd);
2320 }
2321}
2322
2323static Bool
2324ps2mouseReset(InputInfoPtr pInfo, unsigned char val)
2325{
2326 MouseDevPtr pMse = pInfo->private;
2327#ifdef VBOX
2328 mousePrivPtr pPriv = (mousePrivPtr)pMse->mousePriv;
2329#else
2330 ps2PrivPtr ps2priv = (ps2PrivPtr)pMse->mousePriv;
2331#endif
2332#ifdef EXTMOUSEDEBUG
2333 ErrorF("Ps/2 Mouse State: %i, 0x%x\n",ps2priv->state,val);
2334#endif
2335#ifdef VBOX
2336 switch (pPriv->ps2_state) {
2337 case 0:
2338 if (val == 0xaa)
2339 pPriv->ps2_state = 1;
2340 else
2341 pPriv->ps2_state = 0;
2342 return FALSE;
2343 case 1:
2344 pPriv->ps2_state = 0;
2345 if (val == 0x00) {
2346 xf86MsgVerb(X_INFO,3,
2347 "Got reinsert event: reinitializing PS/2 mouse\n");
2348 initPs2(pInfo, TRUE);
2349 return TRUE;
2350 } else
2351 return FALSE;
2352 default:
2353 return FALSE;
2354 }
2355#else /* !VBOX */
2356 switch (ps2priv->state) {
2357 case 0:
2358 if (val == 0xaa)
2359 ps2priv->state = 1;
2360 else
2361 ps2priv->state = 0;
2362 return FALSE;
2363 case 1:
2364 ps2priv->state = 0;
2365 if (val == 0x00) {
2366 xf86MsgVerb(X_INFO,3,
2367 "Got reinsert event: reinitializing PS/2 mouse\n");
2368 initPs2(pInfo, TRUE);
2369 return TRUE;
2370 } else
2371 return FALSE;
2372 default:
2373 return FALSE;
2374 }
2375#endif /* !VBOX */
2376}
2377
2378#ifdef XFree86LOADER
2379ModuleInfoRec MouseInfo = {
2380 1,
2381 "MOUSE",
2382 NULL,
2383 0,
2384 MouseAvailableOptions,
2385};
2386
2387static void
2388xf86MouseUnplug(pointer p)
2389{
2390}
2391static pointer
2392xf86MousePlug(pointer module,
2393 pointer options,
2394 int *errmaj,
2395 int *errmin)
2396{
2397 static Bool Initialised = FALSE;
2398
2399 if (!Initialised) {
2400 Initialised = TRUE;
2401#ifndef REMOVE_LOADER_CHECK_MODULE_INFO
2402 if (xf86LoaderCheckSymbol("xf86AddModuleInfo"))
2403#endif
2404 xf86AddModuleInfo(&MouseInfo, module);
2405 }
2406
2407 xf86AddInputDriver(&MOUSE, module, 0);
2408
2409 return module;
2410}
2411
2412static XF86ModuleVersionInfo xf86MouseVersionRec =
2413{
2414#ifdef VBOX
2415 "vboxmouse",
2416 "Sun Microsystems, Inc.",
2417#else
2418 "mouse",
2419 MODULEVENDORSTRING,
2420#endif
2421 MODINFOSTRING1,
2422 MODINFOSTRING2,
2423 XF86_VERSION_CURRENT,
2424 1, 0, 0,
2425 ABI_CLASS_XINPUT,
2426 ABI_XINPUT_VERSION,
2427 MOD_CLASS_XINPUT,
2428 {0, 0, 0, 0} /* signature, to be patched into the file by */
2429 /* a tool */
2430};
2431
2432#ifndef VBOX
2433XF86ModuleData mouseModuleData =
2434#else
2435XF86ModuleData vboxmouseModuleData =
2436#endif
2437{
2438 &xf86MouseVersionRec,
2439 xf86MousePlug,
2440 xf86MouseUnplug
2441};
2442
2443#endif /* XFree86LOADER */
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