VirtualBox

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

Last change on this file since 34079 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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