VirtualBox

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

最後變更 在這個檔案從27700是 25454,由 vboxsync 提交於 15 年 前

Additions/x11/vboxmouse: build the XFree86 vboxmouse driver against the XFree86 4.3 headers which support amd64

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette