VirtualBox

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

Last change on this file since 1248 was 1, checked in by vboxsync, 55 years ago

import

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