VirtualBox

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

Last change on this file since 29813 was 28372, checked in by vboxsync, 15 years ago

X11 additions: branding

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