19bd41f2cSmrg/*
29bd41f2cSmrg * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
39bd41f2cSmrg * Copyright 1993 by David Dawes <dawes@xfree86.org>
49bd41f2cSmrg * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
59bd41f2cSmrg * Copyright 1994-2002 by The XFree86 Project, Inc.
69bd41f2cSmrg * Copyright 2002 by Paul Elliott
79bd41f2cSmrg * Copyright 2002-2006 by VMware, Inc.
89bd41f2cSmrg *
99bd41f2cSmrg * Permission to use, copy, modify, distribute, and sell this software and its
109bd41f2cSmrg * documentation for any purpose is hereby granted without fee, provided that
119bd41f2cSmrg * the above copyright notice appear in all copies and that both that
129bd41f2cSmrg * copyright notice and this permission notice appear in supporting
139bd41f2cSmrg * documentation, and that the names of copyright holders not be
149bd41f2cSmrg * used in advertising or publicity pertaining to distribution of the
159bd41f2cSmrg * software without specific, written prior permission.  The copyright holders
169bd41f2cSmrg * make no representations about the suitability of this
179bd41f2cSmrg * software for any purpose.  It is provided "as is" without express or
189bd41f2cSmrg * implied warranty.
199bd41f2cSmrg *
209bd41f2cSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
219bd41f2cSmrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
229bd41f2cSmrg * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
239bd41f2cSmrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
249bd41f2cSmrg * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
259bd41f2cSmrg * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
269bd41f2cSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
279bd41f2cSmrg *
289bd41f2cSmrg */
299bd41f2cSmrg
309bd41f2cSmrg/*
319bd41f2cSmrg * vmmouse.c --
329bd41f2cSmrg *
339bd41f2cSmrg * 	This is a modified version of the mouse input driver
349bd41f2cSmrg * 	provided in Xserver/hw/xfree86/input/mouse/mouse.c
35d075918cSmrg *
369bd41f2cSmrg *      Although all data is read using the vmmouse protocol, notification
379bd41f2cSmrg *      is still done through the PS/2 port, so all the basic code for
389bd41f2cSmrg *      interacting with the port is retained.
39d075918cSmrg *
409bd41f2cSmrg */
419bd41f2cSmrg
429bd41f2cSmrg
439bd41f2cSmrg/*****************************************************************************
449bd41f2cSmrg *	Standard Headers
459bd41f2cSmrg ****************************************************************************/
469bd41f2cSmrg#ifdef HAVE_CONFIG_H
479bd41f2cSmrg#include "config.h"
489bd41f2cSmrg#endif
499bd41f2cSmrg
509bd41f2cSmrg#include <stdio.h>
519bd41f2cSmrg#include <X11/X.h>
529bd41f2cSmrg#include <X11/Xproto.h>
539bd41f2cSmrg
549bd41f2cSmrg#include "xf86.h"
559bd41f2cSmrg
569bd41f2cSmrg#ifdef XINPUT
579bd41f2cSmrg#include <X11/extensions/XI.h>
589bd41f2cSmrg#include <X11/extensions/XIproto.h>
599bd41f2cSmrg#include "extnsionst.h"
609bd41f2cSmrg#include "extinit.h"
619bd41f2cSmrg#else
629bd41f2cSmrg#include "inputstr.h"
639bd41f2cSmrg#endif
649bd41f2cSmrg
659bd41f2cSmrg#include "xf86Xinput.h"
669bd41f2cSmrg#include "xf86_OSproc.h"
679bd41f2cSmrg#include "xf86OSmouse.h"
680da4cdccSmrg#include "xf86Priv.h"
699bd41f2cSmrg#include "compiler.h"
709bd41f2cSmrg
71b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
72b15a006bSmrg#include <xserver-properties.h>
73ea0de359Smrg#include "exevents.h"
74b15a006bSmrg#endif
75b15a006bSmrg
760da4cdccSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 18
770da4cdccSmrg#define LogMessageVerbSigSafe xf86MsgVerb
780da4cdccSmrg#endif
790da4cdccSmrg
809bd41f2cSmrg#include "xisb.h"
819bd41f2cSmrg#include "mipointer.h"
829bd41f2cSmrg
83c4f7863aSmrg#ifndef HAVE_XORG_SERVER_1_5_0
84c4f7863aSmrg#include <xf86_ansic.h>
85c4f7863aSmrg#include <xf86_libc.h>
86c4f7863aSmrg#endif
87c4f7863aSmrg
889bd41f2cSmrg/*****************************************************************************
899bd41f2cSmrg *	Local Headers
909bd41f2cSmrg ****************************************************************************/
919bd41f2cSmrg#include "vmmouse_client.h"
929bd41f2cSmrg
939bd41f2cSmrg/*
949bd41f2cSmrg * This is the only way I know to turn a #define of an integer constant into
959bd41f2cSmrg * a constant string.
969bd41f2cSmrg */
979bd41f2cSmrg#define VMW_INNERSTRINGIFY(s) #s
989bd41f2cSmrg#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
999bd41f2cSmrg
1009bd41f2cSmrg/*
1019bd41f2cSmrg * So that the file compiles unmodified when dropped into an xfree source tree.
1029bd41f2cSmrg */
1039bd41f2cSmrg#ifndef XORG_VERSION_CURRENT
1049bd41f2cSmrg#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT
1059bd41f2cSmrg#endif
1069bd41f2cSmrg
1079bd41f2cSmrg/*
1089bd41f2cSmrg * Version constants
1099bd41f2cSmrg */
1109bd41f2cSmrg#define VMMOUSE_DRIVER_VERSION \
1119418810dSmrg   (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
1129bd41f2cSmrg#define VMMOUSE_DRIVER_VERSION_STRING \
1139418810dSmrg    VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
1149418810dSmrg    "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
1159bd41f2cSmrg
1169bd41f2cSmrg/*
1179bd41f2cSmrg * Standard four digit version string expected by VMware Tools installer.
118c4f7863aSmrg * As the driver's version is only  {major, minor, patchlevel},
119c4f7863aSmrg * The fourth digit may describe the commit number relative to the
120c4f7863aSmrg * last version tag as output from `git describe`
1219bd41f2cSmrg */
1229bd41f2cSmrg#ifdef __GNUC__
123c4f7863aSmrg#ifdef VMW_SUBPATCH
124c4f7863aSmrgconst char vm_mouse_version[] __attribute__((section(".modinfo"),unused)) =
125c4f7863aSmrg    "version=" VMMOUSE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
126c4f7863aSmrg#else
1279bd41f2cSmrgconst char vm_mouse_version[] __attribute__((section(".modinfo"),unused)) =
1289bd41f2cSmrg    "version=" VMMOUSE_DRIVER_VERSION_STRING ".0";
129c4f7863aSmrg#endif /*VMW_SUBPATCH*/
1309bd41f2cSmrg#endif
1319bd41f2cSmrg
1329bd41f2cSmrg
1339bd41f2cSmrg/*****************************************************************************
1349bd41f2cSmrg *	static function header
1359bd41f2cSmrg ****************************************************************************/
136c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
137c4f7863aSmrgstatic int VMMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
138c4f7863aSmrg#else
1399bd41f2cSmrgstatic InputInfoPtr VMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags);
140c4f7863aSmrgstatic void VMMouseCloseProc(InputInfoPtr pInfo);
141c4f7863aSmrgstatic Bool VMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
142c4f7863aSmrg			       int v3, int v4, int v5, int *x, int *y);
143c4f7863aSmrg#endif
1449bd41f2cSmrgstatic void VMMouseUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
1459bd41f2cSmrgstatic void MouseCommonOptions(InputInfoPtr pInfo);
1469bd41f2cSmrgstatic void GetVMMouseMotionEvent(InputInfoPtr pInfo);
1479bd41f2cSmrgstatic void VMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw);
1489bd41f2cSmrgstatic void VMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy);
1499bd41f2cSmrgstatic Bool VMMouseDeviceControl(DeviceIntPtr device, int mode);
150c4f7863aSmrgstatic int  VMMouseControlProc(InputInfoPtr pInfo, xDeviceCtl * control);
1519bd41f2cSmrgstatic void VMMouseReadInput(InputInfoPtr pInfo);
1529bd41f2cSmrgstatic int  VMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode);
1539bd41f2cSmrgstatic void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl);
1549bd41f2cSmrg
1559bd41f2cSmrg/******************************************************************************
1569bd41f2cSmrg *		Definitions
1579bd41f2cSmrg *****************************************************************************/
1589bd41f2cSmrgtypedef struct {
159d075918cSmrg   int                 screenNum;
160d075918cSmrg   Bool                vmmouseAvailable;
161d075918cSmrg   VMMOUSE_INPUT_DATA  vmmousePrevInput;
162d075918cSmrg   Bool                isCurrRelative;
163d075918cSmrg   Bool                absoluteRequested;
1649bd41f2cSmrg} VMMousePrivRec, *VMMousePrivPtr;
1659bd41f2cSmrg
1669418810dSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7
1679bd41f2cSmrgstatic const char *reqSymbols[] = {
1689bd41f2cSmrg   "InitPointerDeviceStruct",
1699bd41f2cSmrg   "LoaderSymbol",
1709bd41f2cSmrg   "LoadSubModule",
1719bd41f2cSmrg   "miPointerGetMotionBufferSize",
1729bd41f2cSmrg   "miPointerGetMotionEvents",
1739bd41f2cSmrg   "screenInfo",
1749bd41f2cSmrg   "Xcalloc",
1759bd41f2cSmrg   "xf86AddEnabledDevice",
1769bd41f2cSmrg   "xf86AddInputDriver",
1779bd41f2cSmrg   "xf86AddModuleInfo",
1789bd41f2cSmrg   "xf86AllocateInput",
1799bd41f2cSmrg   "xf86BlockSIGIO",
1809bd41f2cSmrg   "xf86CloseSerial",
1819bd41f2cSmrg   "xf86CollectInputOptions",
1829bd41f2cSmrg   "xf86ffs",
1839bd41f2cSmrg   "xf86FlushInput",
1849bd41f2cSmrg   "xf86GetAllowMouseOpenFail",
1859bd41f2cSmrg   "xf86GetMotionEvents",
1869bd41f2cSmrg   "xf86InitValuatorAxisStruct",
1879bd41f2cSmrg   "xf86InitValuatorDefaults",
1889bd41f2cSmrg   "xf86LoaderCheckSymbol",
1899bd41f2cSmrg   "xf86MotionHistoryAllocate",
1909bd41f2cSmrg   "xf86Msg",
1919bd41f2cSmrg   "xf86NameCmp",
1929bd41f2cSmrg   "xf86OpenSerial",
1939bd41f2cSmrg   "xf86OSMouseInit",
1949bd41f2cSmrg   "xf86PostButtonEvent",
1959bd41f2cSmrg   "xf86PostMotionEvent",
1969bd41f2cSmrg   "xf86ProcessCommonOptions",
1979bd41f2cSmrg   "xf86RemoveEnabledDevice",
1989bd41f2cSmrg   "xf86SetIntOption",
1999bd41f2cSmrg   "xf86SetStrOption",
2009bd41f2cSmrg   "xf86sprintf",
2019bd41f2cSmrg   "xf86sscanf",
2029bd41f2cSmrg   "xf86UnblockSIGIO",
2039bd41f2cSmrg   "xf86usleep",
2049bd41f2cSmrg   "xf86XInputSetScreen",
2059bd41f2cSmrg   "Xfree",
2069bd41f2cSmrg   "XisbBlockDuration",
2079bd41f2cSmrg   "XisbFree",
2089bd41f2cSmrg   "XisbNew",
2099bd41f2cSmrg   "XisbRead",
2109bd41f2cSmrg   "Xstrdup",
2119bd41f2cSmrg   NULL
2129bd41f2cSmrg};
2139418810dSmrg#endif
2149bd41f2cSmrg
2159bd41f2cSmrgInputDriverRec VMMOUSE = {
2169bd41f2cSmrg   1,
2179bd41f2cSmrg   "vmmouse",
2189bd41f2cSmrg   NULL,
2199bd41f2cSmrg   VMMousePreInit,
220d075918cSmrg   VMMouseUnInit,
221c4f7863aSmrg   NULL
222c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 11
223c4f7863aSmrg       ,
2249bd41f2cSmrg   0
225c4f7863aSmrg#endif
2269bd41f2cSmrg};
2279bd41f2cSmrg
2289bd41f2cSmrgstatic char reverseMap[32] = { 0,  4,  2,  6,  1,  5,  3,  7,
2299bd41f2cSmrg			       8, 12, 10, 14,  9, 13, 11, 15,
2309bd41f2cSmrg			      16, 20, 18, 22, 17, 21, 19, 23,
2319bd41f2cSmrg			      24, 28, 26, 30, 25, 29, 27, 31};
2329bd41f2cSmrg
2339bd41f2cSmrg#define reverseBits(map, b)	(((b) & ~0x0f) | map[(b) & 0x0f])
2349bd41f2cSmrg
235c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
2360da4cdccSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 14
2370da4cdccSmrg
2380da4cdccSmrgstatic InputOption*
2390da4cdccSmrginput_option_new(InputOption *list, char *key, char *value)
2400da4cdccSmrg{
2410da4cdccSmrg   InputOption *new;
2420da4cdccSmrg
2430da4cdccSmrg   new = calloc(1, sizeof(InputOption));
2440da4cdccSmrg   new->key = key;
2450da4cdccSmrg   new->value = value;
2460da4cdccSmrg   new->next = list;
2470da4cdccSmrg   return new;
2480da4cdccSmrg}
2490da4cdccSmrg
2500da4cdccSmrgstatic void
2510da4cdccSmrginput_option_free_list(InputOption **opts)
2520da4cdccSmrg{
2530da4cdccSmrg   InputOption *tmp = *opts;
2540da4cdccSmrg   while(*opts)
2550da4cdccSmrg   {
2560da4cdccSmrg      tmp = (*opts)->next;
2570da4cdccSmrg      free((*opts)->key);
2580da4cdccSmrg      free((*opts)->value);
2590da4cdccSmrg      free((*opts));
2600da4cdccSmrg      *opts = tmp;
2610da4cdccSmrg   }
2620da4cdccSmrg}
2630da4cdccSmrg#endif
2640da4cdccSmrg
265c4f7863aSmrgstatic int
266c4f7863aSmrgVMMouseInitPassthru(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
267c4f7863aSmrg{
268c4f7863aSmrg   InputAttributes *attrs = NULL;
2690da4cdccSmrg   InputOption *input_options = NULL;
270c4f7863aSmrg   pointer options;
271c4f7863aSmrg   DeviceIntPtr dev;
272c4f7863aSmrg   int rc;
273c4f7863aSmrg
274c4f7863aSmrg   options = xf86OptionListDuplicate(pInfo->options);
275c4f7863aSmrg   options = xf86ReplaceStrOption(options, "Driver", "mouse");
276c4f7863aSmrg
277c4f7863aSmrg   while(options) {
2780da4cdccSmrg      input_options = input_option_new(input_options,
2790da4cdccSmrg                                       xf86OptionName(options),
2800da4cdccSmrg                                       xf86OptionValue(options));
281c4f7863aSmrg      options = xf86NextOption(options);
282c4f7863aSmrg   }
283c4f7863aSmrg
284c4f7863aSmrg   rc = NewInputDeviceRequest(input_options, attrs, &dev);
285c4f7863aSmrg
2860da4cdccSmrg   input_option_free_list(&input_options);
287c4f7863aSmrg
288c4f7863aSmrg   return rc;
289c4f7863aSmrg}
290c4f7863aSmrg
291c4f7863aSmrg#else /* if ABI_XINPUT_VERSION < 12 */
292c4f7863aSmrgstatic InputInfoPtr
293c4f7863aSmrgVMMouseInitPassthru(InputDriverPtr drv, IDevPtr dev, int flags)
294c4f7863aSmrg{
295c4f7863aSmrg   InputDriverRec *passthruMouse;
296c4f7863aSmrg   passthruMouse = (InputDriverRec *)LoaderSymbol("MOUSE");
297c4f7863aSmrg   if(passthruMouse != NULL) {
298c4f7863aSmrg      return (passthruMouse->PreInit)(drv, dev, flags);
299c4f7863aSmrg   } else {
300c4f7863aSmrg      return NULL;
301c4f7863aSmrg   }
302c4f7863aSmrg}
303c4f7863aSmrg#endif
3049bd41f2cSmrg
3059bd41f2cSmrg/*
3069bd41f2cSmrg *----------------------------------------------------------------------
3079bd41f2cSmrg *
3089bd41f2cSmrg * VMMousePreInit --
3099bd41f2cSmrg *	This function collect all the information that is necessary to
3109bd41f2cSmrg *	determine the configuration of the hardware and to prepare the
3119bd41f2cSmrg *	device for being used
312d075918cSmrg *
3139bd41f2cSmrg * Results:
3149bd41f2cSmrg * 	An InputInfoPtr object which points to vmmouse's information,
3159bd41f2cSmrg *	if the absolute pointing device available
3169bd41f2cSmrg *	Otherwise, an InputInfoPtr of regular mouse
317d075918cSmrg *
3189bd41f2cSmrg * Side effects:
3199bd41f2cSmrg * 	VMMouse was initialized with necessary information
3209bd41f2cSmrg *
3219bd41f2cSmrg *----------------------------------------------------------------------
3229bd41f2cSmrg */
3239bd41f2cSmrg
324c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
325c4f7863aSmrgstatic int
326c4f7863aSmrgVMMouseNewPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
327c4f7863aSmrg
3289bd41f2cSmrgstatic InputInfoPtr
3299bd41f2cSmrgVMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
330d075918cSmrg{
3319bd41f2cSmrg   InputInfoPtr pInfo;
332b15a006bSmrg
333b15a006bSmrg#ifndef NO_MOUSE_MODULE
334b15a006bSmrg{
3359bd41f2cSmrg   OSMouseInfoPtr osInfo = NULL;
3369bd41f2cSmrg
3379bd41f2cSmrg   /*
3389bd41f2cSmrg    * let Xserver init the mouse first
339d075918cSmrg    */
3409bd41f2cSmrg   osInfo = xf86OSMouseInit(0);
3419bd41f2cSmrg   if (!osInfo)
3429bd41f2cSmrg      return FALSE;
343b15a006bSmrg}
344b15a006bSmrg#endif
345d075918cSmrg
3460da4cdccSmrg   /*
3470da4cdccSmrg    * enable hardware access
3480da4cdccSmrg    */
3490da4cdccSmrg   if (!xorgHWAccess) {
3500da4cdccSmrg      if (xf86EnableIO())
3510da4cdccSmrg          xorgHWAccess = TRUE;
3520da4cdccSmrg      else
3530da4cdccSmrg          return NULL;
3540da4cdccSmrg   }
3550da4cdccSmrg
3569bd41f2cSmrg   /*
3579bd41f2cSmrg    * try to enable vmmouse here
3589bd41f2cSmrg    */
3599bd41f2cSmrg   if (!VMMouseClient_Enable()) {
3609bd41f2cSmrg      /*
3619bd41f2cSmrg       * vmmouse failed
3629bd41f2cSmrg       * Fall back to normal mouse module
3639bd41f2cSmrg       */
3649bd41f2cSmrg      xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n");
365c4f7863aSmrg      return VMMouseInitPassthru(drv, dev, flags);
3669bd41f2cSmrg   } else {
3679bd41f2cSmrg      /*
3689bd41f2cSmrg       * vmmouse is available
3699bd41f2cSmrg       */
3709bd41f2cSmrg      xf86Msg(X_INFO, "VMWARE(0): vmmouse is available\n");
3719bd41f2cSmrg      /*
3729bd41f2cSmrg       * Disable the absolute pointing device for now
3739bd41f2cSmrg       * It will be enabled during DEVICE_ON phase
3749bd41f2cSmrg       */
375d075918cSmrg      VMMouseClient_Disable();
3769bd41f2cSmrg   }
377d075918cSmrg
3789bd41f2cSmrg   if (!(pInfo = xf86AllocateInput(drv, 0))) {
3799bd41f2cSmrg      return NULL;
380d075918cSmrg   }
3819bd41f2cSmrg
382d075918cSmrg   pInfo->name = dev->identifier;
3839bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
3849bd41f2cSmrg   pInfo->motion_history_proc = xf86GetMotionEvents;
3859bd41f2cSmrg#endif
3869bd41f2cSmrg   pInfo->close_proc = VMMouseCloseProc;
3879bd41f2cSmrg   pInfo->conversion_proc = VMMouseConvertProc;
3889bd41f2cSmrg   pInfo->reverse_conversion_proc = NULL;
3899bd41f2cSmrg   pInfo->fd = -1;
3909bd41f2cSmrg   pInfo->dev = NULL;
3919bd41f2cSmrg   pInfo->private_flags = 0;
3929bd41f2cSmrg   pInfo->always_core_feedback = 0;
3939bd41f2cSmrg   pInfo->conf_idev = dev;
394c4f7863aSmrg   pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
395c4f7863aSmrg
396c4f7863aSmrg   /* Collect the options, and process the common options. */
397c4f7863aSmrg   xf86CollectInputOptions(pInfo, NULL, NULL);
398c4f7863aSmrg   xf86ProcessCommonOptions(pInfo, pInfo->options);
399c4f7863aSmrg
400c4f7863aSmrg   if (VMMouseNewPreInit(drv, pInfo, flags) == Success)
401c4f7863aSmrg       pInfo->flags |= XI86_CONFIGURED;
402c4f7863aSmrg
403c4f7863aSmrg   return pInfo;
404c4f7863aSmrg}
405c4f7863aSmrg
406c4f7863aSmrgstatic int
407c4f7863aSmrgVMMouseNewPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
408c4f7863aSmrg#else /* if ABI_XINPUT_VERSION >= 12 */
409c4f7863aSmrgstatic int
410c4f7863aSmrgVMMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
411c4f7863aSmrg#endif
412c4f7863aSmrg{
413c4f7863aSmrg   MouseDevPtr pMse = NULL;
414c4f7863aSmrg   VMMousePrivPtr mPriv = NULL;
415c4f7863aSmrg   int rc = Success;
416c4f7863aSmrg
4170da4cdccSmrg   /* Enable hardware access. */
4180da4cdccSmrg   if (!xorgHWAccess) {
4190da4cdccSmrg      if (xf86EnableIO())
4200da4cdccSmrg          xorgHWAccess = TRUE;
4210da4cdccSmrg      else {
4220da4cdccSmrg          rc = BadValue;
4230da4cdccSmrg          goto error;
4240da4cdccSmrg      }
4250da4cdccSmrg   }
4260da4cdccSmrg
427c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
428c4f7863aSmrg   /* For ABI < 12, we need to return the wrapped driver's pInfo (see
429c4f7863aSmrg    * above). ABI 12, we call NIDR and are done */
430c4f7863aSmrg   if (!VMMouseClient_Enable()) {
431c4f7863aSmrg      xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n");
432c4f7863aSmrg      return VMMouseInitPassthru(drv, pInfo, flags);
433c4f7863aSmrg   } else {
434c4f7863aSmrg      xf86Msg(X_INFO, "VMWARE(0): vmmouse is available\n");
435c4f7863aSmrg      VMMouseClient_Disable();
436c4f7863aSmrg   }
437c4f7863aSmrg#endif
438c4f7863aSmrg
439c4f7863aSmrg   mPriv = calloc (1, sizeof (VMMousePrivRec));
440c4f7863aSmrg
441c4f7863aSmrg   if (!mPriv) {
442c4f7863aSmrg      rc = BadAlloc;
443c4f7863aSmrg      goto error;
444c4f7863aSmrg   }
445c4f7863aSmrg
446c4f7863aSmrg   mPriv->absoluteRequested = FALSE;
447c4f7863aSmrg   mPriv->vmmouseAvailable = TRUE;
448c4f7863aSmrg
449c4f7863aSmrg   /* Settup the pInfo */
450c4f7863aSmrg   pInfo->type_name = XI_MOUSE;
451c4f7863aSmrg   pInfo->device_control = VMMouseDeviceControl;
452c4f7863aSmrg   pInfo->read_input = VMMouseReadInput;
453c4f7863aSmrg   pInfo->control_proc = VMMouseControlProc;
454c4f7863aSmrg   pInfo->switch_mode = VMMouseSwitchMode;
4559bd41f2cSmrg
4569bd41f2cSmrg   /* Allocate the MouseDevRec and initialise it. */
457c4f7863aSmrg   if (!(pMse = calloc(sizeof(MouseDevRec), 1))) {
458c4f7863aSmrg      rc = BadAlloc;
459c4f7863aSmrg      goto error;
4609bd41f2cSmrg   }
4619bd41f2cSmrg
4629bd41f2cSmrg   pInfo->private = pMse;
4639bd41f2cSmrg   pMse->Ctrl = MouseCtrl;
4649bd41f2cSmrg   pMse->PostEvent = VMMousePostEvent;
4659bd41f2cSmrg   pMse->CommonOptions = MouseCommonOptions;
4669bd41f2cSmrg   pMse->mousePriv = mPriv;
467d075918cSmrg
4689bd41f2cSmrg
4699bd41f2cSmrg   /* Check if the device can be opened. */
4709bd41f2cSmrg   pInfo->fd = xf86OpenSerial(pInfo->options);
4719bd41f2cSmrg   if (pInfo->fd == -1) {
4729bd41f2cSmrg      if (xf86GetAllowMouseOpenFail())
4739bd41f2cSmrg	 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
4749bd41f2cSmrg      else {
4759bd41f2cSmrg	 xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
476c4f7863aSmrg	 rc = BadValue;
477c4f7863aSmrg	 goto error;
4789bd41f2cSmrg      }
4799bd41f2cSmrg   }
4809bd41f2cSmrg   xf86CloseSerial(pInfo->fd);
4819bd41f2cSmrg   pInfo->fd = -1;
482d075918cSmrg
4839bd41f2cSmrg   /* Process the options */
4849bd41f2cSmrg   pMse->CommonOptions(pInfo);
485d075918cSmrg
4869bd41f2cSmrg   /* set up the current screen num */
4879bd41f2cSmrg   mPriv->screenNum = xf86SetIntOption(pInfo->options, "ScreenNumber", 0);
488d075918cSmrg
489c4f7863aSmrg   return Success;
490c4f7863aSmrg
491c4f7863aSmrgerror:
492c4f7863aSmrg   pInfo->private = NULL;
493c4f7863aSmrg   if (mPriv)
494c4f7863aSmrg      free(mPriv);
495c4f7863aSmrg   if (pMse)
496c4f7863aSmrg      free(pMse);
497c4f7863aSmrg
498c4f7863aSmrg   return rc;
4999bd41f2cSmrg}
5009bd41f2cSmrg
5019bd41f2cSmrg
5029bd41f2cSmrg/*
5039bd41f2cSmrg *----------------------------------------------------------------------
5049bd41f2cSmrg *
5059bd41f2cSmrg * MouseCtrl --
506d075918cSmrg *     Alter the control paramters for the mouse.
507d075918cSmrg *
5089bd41f2cSmrg * Results:
509d075918cSmrg * 	None
510d075918cSmrg *
5119bd41f2cSmrg * Side effects:
5129bd41f2cSmrg * 	None
5139bd41f2cSmrg *
5149bd41f2cSmrg *----------------------------------------------------------------------
5159bd41f2cSmrg */
5169bd41f2cSmrg
5179bd41f2cSmrgstatic void
5189bd41f2cSmrgMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
5199bd41f2cSmrg{
5209bd41f2cSmrg    InputInfoPtr pInfo;
5219bd41f2cSmrg    MouseDevPtr pMse;
5229bd41f2cSmrg
5239bd41f2cSmrg    pInfo = device->public.devicePrivate;
5249bd41f2cSmrg    pMse = pInfo->private;
5259bd41f2cSmrg
5269bd41f2cSmrg#ifdef EXTMOUSEDEBUG
5279bd41f2cSmrg    xf86Msg(X_INFO, "VMMOUSE(0): MouseCtrl pMse=%p\n", pMse);
5289bd41f2cSmrg#endif
529d075918cSmrg
5309bd41f2cSmrg    pMse->num       = ctrl->num;
5319bd41f2cSmrg    pMse->den       = ctrl->den;
5329bd41f2cSmrg    pMse->threshold = ctrl->threshold;
5339bd41f2cSmrg}
5349bd41f2cSmrg
5359bd41f2cSmrg
5369bd41f2cSmrg/*
5379bd41f2cSmrg *----------------------------------------------------------------------
5389bd41f2cSmrg *
5399bd41f2cSmrg * VMMouseDoPostEvent --
5409bd41f2cSmrg *	Post the mouse button event and mouse motion event to Xserver
541d075918cSmrg *
5429bd41f2cSmrg * Results:
5439bd41f2cSmrg * 	None
544d075918cSmrg *
5459bd41f2cSmrg * Side effects:
5469bd41f2cSmrg * 	Mouse location and button status was updated
5479bd41f2cSmrg *
5489bd41f2cSmrg *----------------------------------------------------------------------
5499bd41f2cSmrg */
5509bd41f2cSmrg
5519bd41f2cSmrgstatic void
5529bd41f2cSmrgVMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy)
5539bd41f2cSmrg{
5549bd41f2cSmrg    MouseDevPtr pMse;
5559bd41f2cSmrg    VMMousePrivPtr mPriv;
5569bd41f2cSmrg    int truebuttons;
5579bd41f2cSmrg    int id, change;
558d075918cSmrg    Bool mouseMoved = FALSE;
559d075918cSmrg
5609bd41f2cSmrg    pMse = pInfo->private;
5619bd41f2cSmrg    mPriv = (VMMousePrivPtr)pMse->mousePriv;
5629bd41f2cSmrg
5639bd41f2cSmrg    /*
5649bd41f2cSmrg     * The following truebuttons/reverseBits and lastButtons are
5659bd41f2cSmrg     * used to compare the current buttons and the previous buttons
5669bd41f2cSmrg     * to find the button changes during two mouse events
567d075918cSmrg     */
5689bd41f2cSmrg    truebuttons = buttons;
5699bd41f2cSmrg
5709bd41f2cSmrg    buttons = reverseBits(reverseMap, buttons);
5719bd41f2cSmrg
572d075918cSmrg    if (mPriv->isCurrRelative) {
573d075918cSmrg       mouseMoved = dx || dy;
574d075918cSmrg    } else {
575d075918cSmrg       mouseMoved = (dx != mPriv->vmmousePrevInput.X) ||
576d075918cSmrg                    (dy != mPriv->vmmousePrevInput.Y) ||
577d075918cSmrg                    (mPriv->vmmousePrevInput.Flags & VMMOUSE_MOVE_RELATIVE);
578d075918cSmrg    }
579d075918cSmrg    if (mouseMoved) {
5809bd41f2cSmrg
581d075918cSmrg#ifdef CALL_CONVERSION_PROC
5829bd41f2cSmrg        /*
583d075918cSmrg         * Xservers between 1.3.99.0 - 1.4.0.90 do not call conversion_proc, so
584d075918cSmrg         * we need to do the conversion from device to screen space.
5859bd41f2cSmrg         */
5869bd41f2cSmrg        VMMouseConvertProc(pInfo, 0, 2, dx, dy, 0, 0, 0, 0, &dx, &dy);
587d075918cSmrg#endif
588d075918cSmrg        xf86PostMotionEvent(pInfo->dev, !mPriv->isCurrRelative, 0, 2, dx, dy);
5899bd41f2cSmrg    }
590d075918cSmrg
5919bd41f2cSmrg    if (truebuttons != pMse->lastButtons) {
5929bd41f2cSmrg       change = buttons ^ reverseBits(reverseMap, pMse->lastButtons);
5939bd41f2cSmrg       while (change) {
5949bd41f2cSmrg	  id = ffs(change);
5959bd41f2cSmrg	  change &= ~(1 << (id - 1));
5969bd41f2cSmrg	  xf86PostButtonEvent(pInfo->dev, 0, id,
5979bd41f2cSmrg			      (buttons & (1 << (id - 1))), 0, 0);
5989bd41f2cSmrg       }
5999bd41f2cSmrg       pMse->lastButtons = truebuttons;
6009bd41f2cSmrg    }
6019bd41f2cSmrg}
6029bd41f2cSmrg
6039bd41f2cSmrg
6049bd41f2cSmrg/*
6059bd41f2cSmrg *----------------------------------------------------------------------
6069bd41f2cSmrg *
6079bd41f2cSmrg * VMMousePostEvent --
6089bd41f2cSmrg *	Prepare the mouse status according to the Z axis mapping
6099bd41f2cSmrg *	before we post the event to Xserver
610d075918cSmrg *
6119bd41f2cSmrg * Results:
6129bd41f2cSmrg * 	None
613d075918cSmrg *
6149bd41f2cSmrg * Side effects:
6159bd41f2cSmrg * 	Buttons was updated according to Z axis mapping
6169bd41f2cSmrg *
6179bd41f2cSmrg *----------------------------------------------------------------------
6189bd41f2cSmrg */
6199bd41f2cSmrg
6209bd41f2cSmrgstatic void
6219bd41f2cSmrgVMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw)
6229bd41f2cSmrg{
6239bd41f2cSmrg    MouseDevPtr pMse;
6249bd41f2cSmrg    int zbutton = 0;
6259bd41f2cSmrg    VMMousePrivPtr mPriv;
626d075918cSmrg
6279bd41f2cSmrg    pMse = pInfo->private;
6289bd41f2cSmrg    mPriv = (VMMousePrivPtr)pMse->mousePriv;
6299bd41f2cSmrg    /* Map the Z axis movement. */
6309bd41f2cSmrg    /* XXX Could this go in the conversion_proc? */
6319bd41f2cSmrg    switch (pMse->negativeZ) {
6329bd41f2cSmrg    case MSE_NOZMAP:	/* do nothing */
6339bd41f2cSmrg	break;
6349bd41f2cSmrg    case MSE_MAPTOX:
6359bd41f2cSmrg	if (dz != 0) {
636d075918cSmrg	   if(mPriv->isCurrRelative)
6379bd41f2cSmrg	      dx = dz;
6389bd41f2cSmrg	   else
639d075918cSmrg	      dx += dz;
6409bd41f2cSmrg	    dz = 0;
6419bd41f2cSmrg	}
6429bd41f2cSmrg	break;
6439bd41f2cSmrg    case MSE_MAPTOY:
6449bd41f2cSmrg	if (dz != 0) {
645d075918cSmrg	   if(mPriv->isCurrRelative)
6469bd41f2cSmrg	      dy = dz;
6479bd41f2cSmrg	   else
648d075918cSmrg	      dy += dz;
6499bd41f2cSmrg	    dz = 0;
6509bd41f2cSmrg	}
6519bd41f2cSmrg	break;
6529bd41f2cSmrg    default:	/* buttons */
6539bd41f2cSmrg	buttons &= ~(pMse->negativeZ | pMse->positiveZ
6549bd41f2cSmrg		   | pMse->negativeW | pMse->positiveW);
6559bd41f2cSmrg	if (dw < 0 || dz < -1) {
6569bd41f2cSmrg	    zbutton = pMse->negativeW;
6579bd41f2cSmrg	}
6589bd41f2cSmrg	else if (dz < 0) {
6599bd41f2cSmrg	    zbutton = pMse->negativeZ;
6609bd41f2cSmrg	}
6619bd41f2cSmrg	else if (dw > 0 || dz > 1) {
6629bd41f2cSmrg	    zbutton = pMse->positiveW;
6639bd41f2cSmrg	}
6649bd41f2cSmrg	else if (dz > 0) {
6659bd41f2cSmrg	    zbutton = pMse->positiveZ;
6669bd41f2cSmrg	}
6679bd41f2cSmrg	buttons |= zbutton;
6689bd41f2cSmrg	dz = 0;
6699bd41f2cSmrg	break;
6709bd41f2cSmrg    }
6719bd41f2cSmrg
6729bd41f2cSmrg    VMMouseDoPostEvent(pInfo, buttons, dx, dy);
6739bd41f2cSmrg
6749bd41f2cSmrg    /*
6759bd41f2cSmrg     * If dz has been mapped to a button `down' event, we need to cook up
6769bd41f2cSmrg     * a corresponding button `up' event.
6779bd41f2cSmrg     */
6789bd41f2cSmrg    if (zbutton) {
6799bd41f2cSmrg	buttons &= ~zbutton;
680d075918cSmrg	if(mPriv->isCurrRelative)
6819bd41f2cSmrg	   VMMouseDoPostEvent(pInfo, buttons, 0, 0);
6829bd41f2cSmrg	else
6839bd41f2cSmrg	   VMMouseDoPostEvent(pInfo, buttons, dx, dy);
6849bd41f2cSmrg    }
6859bd41f2cSmrg}
6869bd41f2cSmrg
6879bd41f2cSmrg
6889bd41f2cSmrg/*
6899bd41f2cSmrg *----------------------------------------------------------------------
6909bd41f2cSmrg *
6919bd41f2cSmrg * FlushButtons --
6929bd41f2cSmrg *
693d075918cSmrg * 	FlushButtons -- reset button states.
6949bd41f2cSmrg *
6959bd41f2cSmrg * Results:
6969bd41f2cSmrg * 	None
697d075918cSmrg *
6989bd41f2cSmrg * Side effects:
6999bd41f2cSmrg * 	None
7009bd41f2cSmrg *
7019bd41f2cSmrg *----------------------------------------------------------------------
7029bd41f2cSmrg */
7039bd41f2cSmrg
7049bd41f2cSmrgstatic void
7059bd41f2cSmrgFlushButtons(MouseDevPtr pMse)
7069bd41f2cSmrg{
7079bd41f2cSmrg    pMse->lastButtons = 0;
7089bd41f2cSmrg}
7099bd41f2cSmrg
7109bd41f2cSmrg
7119bd41f2cSmrg/*
7129bd41f2cSmrg *----------------------------------------------------------------------
7139bd41f2cSmrg *
7149bd41f2cSmrg * MouseCommonOptions --
7159bd41f2cSmrg *	Process acceptable mouse options. Currently we only process
7169bd41f2cSmrg *	"Buttons" and "ZAxisMapping" options.
717d075918cSmrg *	More options can be added later on
7189bd41f2cSmrg *
7199bd41f2cSmrg * Results:
7209bd41f2cSmrg * 	None
721d075918cSmrg *
7229bd41f2cSmrg * Side effects:
7239bd41f2cSmrg * 	The buttons was setup according to the options
7249bd41f2cSmrg *
7259bd41f2cSmrg *----------------------------------------------------------------------
7269bd41f2cSmrg */
7279bd41f2cSmrg
7289bd41f2cSmrgstatic void
7299bd41f2cSmrgMouseCommonOptions(InputInfoPtr pInfo)
7309bd41f2cSmrg{
7319bd41f2cSmrg   MouseDevPtr pMse;
7329bd41f2cSmrg   char *s;
7339bd41f2cSmrg
7349bd41f2cSmrg   pMse = pInfo->private;
7359bd41f2cSmrg
7369bd41f2cSmrg   pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
7379bd41f2cSmrg   if (!pMse->buttons) {
7389bd41f2cSmrg      pMse->buttons = MSE_DFLTBUTTONS;
7399bd41f2cSmrg   }
7409bd41f2cSmrg
7419bd41f2cSmrg   /*
7429bd41f2cSmrg    * "emulate3Buttons" and "Drag Lock" is not supported
7439bd41f2cSmrg    */
7449bd41f2cSmrg
7459bd41f2cSmrg   /*
7469bd41f2cSmrg    * Process option for ZAxisMapping
7479bd41f2cSmrg    */
748d075918cSmrg   s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5");
7499bd41f2cSmrg   if (s) {
7509bd41f2cSmrg      int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
7519bd41f2cSmrg      char *msg = NULL;
7529bd41f2cSmrg
7539bd41f2cSmrg      if (!xf86NameCmp(s, "x")) {
7549bd41f2cSmrg	 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX;
7559bd41f2cSmrg	 pMse->negativeW = pMse->positiveW = MSE_MAPTOX;
7569bd41f2cSmrg	 msg = xstrdup("X axis");
7579bd41f2cSmrg      } else if (!xf86NameCmp(s, "y")) {
7589bd41f2cSmrg	 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY;
7599bd41f2cSmrg	 pMse->negativeW = pMse->positiveW = MSE_MAPTOY;
7609bd41f2cSmrg	 msg = xstrdup("Y axis");
7619bd41f2cSmrg      } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 &&
7629bd41f2cSmrg		 b1 > 0 && b1 <= MSE_MAXBUTTONS &&
7639bd41f2cSmrg		 b2 > 0 && b2 <= MSE_MAXBUTTONS) {
7649bd41f2cSmrg	 msg = xstrdup("buttons XX and YY");
7659bd41f2cSmrg	 if (msg)
7669bd41f2cSmrg	    sprintf(msg, "buttons %d and %d", b1, b2);
7679bd41f2cSmrg	 pMse->negativeZ = pMse->negativeW = 1 << (b1-1);
7689bd41f2cSmrg	 pMse->positiveZ = pMse->positiveW = 1 << (b2-1);
7699bd41f2cSmrg	 if (b1 > pMse->buttons) pMse->buttons = b1;
7709bd41f2cSmrg	 if (b2 > pMse->buttons) pMse->buttons = b2;
771d075918cSmrg
7729bd41f2cSmrg	 /*
773d075918cSmrg	  * Option "ZAxisMapping" "N1 N2 N3 N4" not supported
7749bd41f2cSmrg	  */
7759bd41f2cSmrg	 pMse->negativeW = pMse->positiveW = MSE_NOZMAP;
7769bd41f2cSmrg      } else {
7779bd41f2cSmrg	 pMse->negativeZ = pMse->positiveZ = MSE_NOZMAP;
7789bd41f2cSmrg	 pMse->negativeW = pMse->positiveW = MSE_NOZMAP;
7799bd41f2cSmrg      }
7809bd41f2cSmrg      if (msg) {
7819bd41f2cSmrg	 xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg);
782c4f7863aSmrg	 free(msg);
7839bd41f2cSmrg      } else {
7849bd41f2cSmrg	 xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n",
7859bd41f2cSmrg		 pInfo->name, s);
7869bd41f2cSmrg      }
7879bd41f2cSmrg   }
7889bd41f2cSmrg}
7899bd41f2cSmrg
7909bd41f2cSmrg
7919bd41f2cSmrg/*
7929bd41f2cSmrg *----------------------------------------------------------------------
7939bd41f2cSmrg *
7949bd41f2cSmrg * VMMouseUnInit --
7959bd41f2cSmrg * 	This function was supposed to be called by Xserver to do Un-Init.
7969bd41f2cSmrg *	But it was unused now
7979bd41f2cSmrg *
7989bd41f2cSmrg * Results:
7999bd41f2cSmrg * 	None
800d075918cSmrg *
8019bd41f2cSmrg * Side effects:
8029bd41f2cSmrg * 	None
8039bd41f2cSmrg *
8049bd41f2cSmrg *----------------------------------------------------------------------
8059bd41f2cSmrg */
8069bd41f2cSmrg
807d075918cSmrgstatic void
808c4f7863aSmrgVMMouseUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
8099bd41f2cSmrg{
8108746cb53Smrg   MouseDevPtr pMse = pInfo->private;
8118746cb53Smrg
8129bd41f2cSmrg   xf86Msg(X_INFO, "VMWARE(0): VMMouseUnInit\n");
8138746cb53Smrg
8148746cb53Smrg   if (pMse) {
8158746cb53Smrg       VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv;
8168746cb53Smrg       free(mPriv);
8178746cb53Smrg   }
8188746cb53Smrg
8198746cb53Smrg   xf86DeleteInput(pInfo, flags);
8209bd41f2cSmrg}
8219bd41f2cSmrg
8229bd41f2cSmrg
8239bd41f2cSmrg/*
8249bd41f2cSmrg *----------------------------------------------------------------------
8259bd41f2cSmrg *
8269bd41f2cSmrg * VMMouseDeviceControl --
8279bd41f2cSmrg * 	This function was called by Xserver during DEVICE_INIT, DEVICE_ON,
828d075918cSmrg *	DEVICE_OFF and DEVICE_CLOSE phase
829d075918cSmrg *
8309bd41f2cSmrg * Results:
8319bd41f2cSmrg * 	TRUE, if sucessful
8329bd41f2cSmrg *	FALSE, if failed
833d075918cSmrg *
8349bd41f2cSmrg * Side effects:
8359bd41f2cSmrg * 	Absolute pointing device is enabled during DEVICE_ON
8369bd41f2cSmrg *	Absolute pointing device is disabled during DEVICE_OFF
8379bd41f2cSmrg *	and DEVICE_CLOSE
8389bd41f2cSmrg *
8399bd41f2cSmrg *----------------------------------------------------------------------
8409bd41f2cSmrg */
8419bd41f2cSmrg
8429bd41f2cSmrgstatic Bool
8439bd41f2cSmrgVMMouseDeviceControl(DeviceIntPtr device, int mode)
8449bd41f2cSmrg{
8459bd41f2cSmrg   InputInfoPtr pInfo;
8469bd41f2cSmrg   MouseDevPtr pMse;
8479bd41f2cSmrg   unsigned char map[MSE_MAXBUTTONS + 1];
8489bd41f2cSmrg   int i;
849b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
850b15a006bSmrg   Atom btn_labels[MSE_MAXBUTTONS] = {0};
851b15a006bSmrg   Atom axes_labels[2] = { 0, 0 };
852b15a006bSmrg#endif
853d075918cSmrg
8549bd41f2cSmrg   pInfo = device->public.devicePrivate;
8559bd41f2cSmrg   pMse = pInfo->private;
8569bd41f2cSmrg   pMse->device = device;
8579bd41f2cSmrg
8589bd41f2cSmrg   switch (mode){
8599bd41f2cSmrg   case DEVICE_INIT:
8609bd41f2cSmrg      device->public.on = FALSE;
8619bd41f2cSmrg      /*
8629bd41f2cSmrg       * [KAZU-241097] We don't know exactly how many buttons the
8639bd41f2cSmrg       * device has, so setup the map with the maximum number.
8649bd41f2cSmrg       */
8659bd41f2cSmrg      for (i = 0; i < MSE_MAXBUTTONS; i++)
8669bd41f2cSmrg	 map[i + 1] = i + 1;
867b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
868b15a006bSmrg      btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
869b15a006bSmrg      btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
870b15a006bSmrg      btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
8718746cb53Smrg      btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
8728746cb53Smrg      btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
8738746cb53Smrg      btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
8748746cb53Smrg      btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
875b15a006bSmrg      /* other buttons are unknown */
876b15a006bSmrg
877b15a006bSmrg#ifdef ABS_VALUATOR_AXES
878b15a006bSmrg      axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
879b15a006bSmrg      axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
880b15a006bSmrg#else
881b15a006bSmrg      axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
882b15a006bSmrg      axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
883b15a006bSmrg#endif /* ABS_VALUATOR_AXES */
884b15a006bSmrg#endif
8859bd41f2cSmrg
8869bd41f2cSmrg      InitPointerDeviceStruct((DevicePtr)device, map,
8879bd41f2cSmrg			      min(pMse->buttons, MSE_MAXBUTTONS),
888b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
889b15a006bSmrg				btn_labels,
890b15a006bSmrg#endif
8919bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
8929bd41f2cSmrg				miPointerGetMotionEvents,
893d075918cSmrg#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
8949bd41f2cSmrg                                GetMotionHistory,
8959bd41f2cSmrg#endif
8969bd41f2cSmrg                                pMse->Ctrl,
8979bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
8989bd41f2cSmrg				miPointerGetMotionBufferSize()
8999bd41f2cSmrg#else
9009bd41f2cSmrg                                GetMotionHistorySize(), 2
901b15a006bSmrg#endif
902b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
903b15a006bSmrg				, axes_labels
9049bd41f2cSmrg#endif
9059bd41f2cSmrg                                );
9069bd41f2cSmrg
9079bd41f2cSmrg      /* X valuator */
908d075918cSmrg#ifdef ABS_VALUATOR_AXES
909b15a006bSmrg      xf86InitValuatorAxisStruct(device, 0,
910b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
911b15a006bSmrg				axes_labels[0],
912b15a006bSmrg#endif
913c4f7863aSmrg				0, 65535, 10000, 0, 10000
914c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
915c4f7863aSmrg                                , Absolute
916c4f7863aSmrg#endif
917c4f7863aSmrg                                );
918d075918cSmrg#else
919b15a006bSmrg      xf86InitValuatorAxisStruct(device, 0,
920b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
921b15a006bSmrg				axes_labels[0],
922b15a006bSmrg#endif
923c4f7863aSmrg				0, -1, 1, 0, 1
924c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
925c4f7863aSmrg                                , Relative
926c4f7863aSmrg#endif
927c4f7863aSmrg                                );
928d075918cSmrg#endif
9299bd41f2cSmrg      xf86InitValuatorDefaults(device, 0);
9309bd41f2cSmrg      /* Y valuator */
931d075918cSmrg#ifdef ABS_VALUATOR_AXES
932b15a006bSmrg      xf86InitValuatorAxisStruct(device, 1,
933b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
934b15a006bSmrg				axes_labels[1],
935b15a006bSmrg#endif
936c4f7863aSmrg				0, 65535, 10000, 0, 10000
937c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
938c4f7863aSmrg                                , Absolute
939c4f7863aSmrg#endif
940c4f7863aSmrg                                );
941d075918cSmrg#else
942b15a006bSmrg      xf86InitValuatorAxisStruct(device, 1,
943b15a006bSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
944b15a006bSmrg				axes_labels[1],
945b15a006bSmrg#endif
946c4f7863aSmrg				0, -1, 1, 0, 1
947c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
948c4f7863aSmrg                                , Relative
949c4f7863aSmrg#endif
950c4f7863aSmrg                                );
951d075918cSmrg#endif
9529bd41f2cSmrg      xf86InitValuatorDefaults(device, 1);
9539bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
9549bd41f2cSmrg      xf86MotionHistoryAllocate(pInfo);
9559bd41f2cSmrg#endif
9569bd41f2cSmrg
9579bd41f2cSmrg      xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_INIT\n");
9589bd41f2cSmrg#ifdef EXTMOUSEDEBUG
9599bd41f2cSmrg      xf86Msg(X_INFO, "assigning %p atom=%d name=%s\n", device, pInfo->atom,
9609bd41f2cSmrg	     pInfo->name);
9619bd41f2cSmrg#endif
9629bd41f2cSmrg      break;
9639bd41f2cSmrg
9649bd41f2cSmrg   case DEVICE_ON:
9659bd41f2cSmrg      xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_ON\n");
9669bd41f2cSmrg      pInfo->fd = xf86OpenSerial(pInfo->options);
9679bd41f2cSmrg      if (pInfo->fd == -1)
9689bd41f2cSmrg	 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
9699bd41f2cSmrg      else {
9709bd41f2cSmrg	 pMse->buffer = XisbNew(pInfo->fd, 64);
9719bd41f2cSmrg	 if (!pMse->buffer) {
9729bd41f2cSmrg	    xf86CloseSerial(pInfo->fd);
9739bd41f2cSmrg	    pInfo->fd = -1;
9749bd41f2cSmrg	 } else {
9759bd41f2cSmrg	    VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv;
9769bd41f2cSmrg	    if (mPriv != NULL) {
9779bd41f2cSmrg	       /*
9789bd41f2cSmrg		* enable absolute pointing device here
9799bd41f2cSmrg		*/
980d075918cSmrg	       if (!VMMouseClient_Enable()) {
9819bd41f2cSmrg		  xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n");
9829bd41f2cSmrg		  mPriv->vmmouseAvailable = FALSE;
9839bd41f2cSmrg		  device->public.on = FALSE;
9849bd41f2cSmrg		  return FALSE;
9859bd41f2cSmrg	       } else {
986d075918cSmrg		  mPriv->vmmouseAvailable = TRUE;
9879bd41f2cSmrg		  xf86Msg(X_INFO, "VMWARE(0): vmmouse enabled\n");
988d075918cSmrg	       }
9899bd41f2cSmrg	    }
9909bd41f2cSmrg	    xf86FlushInput(pInfo->fd);
9919bd41f2cSmrg	    xf86AddEnabledDevice(pInfo);
9929bd41f2cSmrg	 }
9939bd41f2cSmrg      }
9949bd41f2cSmrg      pMse->lastButtons = 0;
9959bd41f2cSmrg      device->public.on = TRUE;
9969bd41f2cSmrg      FlushButtons(pMse);
997d075918cSmrg      break;
9989bd41f2cSmrg   case DEVICE_OFF:
9999bd41f2cSmrg   case DEVICE_CLOSE:
10009bd41f2cSmrg      xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_OFF/CLOSE\n");
10019bd41f2cSmrg
10029bd41f2cSmrg      if (pInfo->fd != -1) {
10039bd41f2cSmrg	 VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv;
10049bd41f2cSmrg	 if( mPriv->vmmouseAvailable ) {
10059bd41f2cSmrg	    VMMouseClient_Disable();
1006d075918cSmrg            mPriv->vmmouseAvailable = FALSE;
1007d075918cSmrg            mPriv->absoluteRequested = FALSE;
10089bd41f2cSmrg	 }
1009d075918cSmrg
10109bd41f2cSmrg	 xf86RemoveEnabledDevice(pInfo);
10119bd41f2cSmrg	 if (pMse->buffer) {
10129bd41f2cSmrg	    XisbFree(pMse->buffer);
10139bd41f2cSmrg	    pMse->buffer = NULL;
10149bd41f2cSmrg	 }
10159bd41f2cSmrg	 xf86CloseSerial(pInfo->fd);
10169bd41f2cSmrg	 pInfo->fd = -1;
10179bd41f2cSmrg      }
10189bd41f2cSmrg      device->public.on = FALSE;
10199bd41f2cSmrg      usleep(300000);
10209bd41f2cSmrg      break;
10219bd41f2cSmrg
10228746cb53Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) * 100 + GET_ABI_MINOR(ABI_XINPUT_VERSION) >= 1901
10238746cb53Smrg   case  DEVICE_ABORT:
10248746cb53Smrg      if (pInfo->fd != -1) {
10258746cb53Smrg	 VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv;
10268746cb53Smrg	 if( mPriv->vmmouseAvailable )
10278746cb53Smrg	    VMMouseClient_Disable();
10288746cb53Smrg         break;
10298746cb53Smrg      }
10308746cb53Smrg#endif
10319bd41f2cSmrg   }
10329bd41f2cSmrg
10339bd41f2cSmrg   return Success;
10349bd41f2cSmrg}
10359bd41f2cSmrg
10369bd41f2cSmrg
10379bd41f2cSmrg/*
10389bd41f2cSmrg *----------------------------------------------------------------------
10399bd41f2cSmrg *
10409bd41f2cSmrg * VMMouseReadInput --
10419bd41f2cSmrg * 	This function was called by Xserver when there is data available
10429bd41f2cSmrg *	in the input device
1043d075918cSmrg *
10449bd41f2cSmrg * Results:
10459bd41f2cSmrg * 	None
1046d075918cSmrg *
10479bd41f2cSmrg * Side effects:
10489bd41f2cSmrg * 	Input data in regular PS/2 fd was cleared
10499bd41f2cSmrg *	Real mouse data was read from the absolute pointing device
10509bd41f2cSmrg *	and posted to Xserver
1051d075918cSmrg *
10529bd41f2cSmrg *----------------------------------------------------------------------
10539bd41f2cSmrg */
10549bd41f2cSmrg
10559bd41f2cSmrgstatic void
10569bd41f2cSmrgVMMouseReadInput(InputInfoPtr pInfo)
10579bd41f2cSmrg{
10589bd41f2cSmrg   MouseDevPtr pMse;
1059d075918cSmrg   VMMousePrivPtr mPriv;
10609bd41f2cSmrg   int c;
1061d075918cSmrg   int len = 0;
10629bd41f2cSmrg
10639bd41f2cSmrg   pMse = pInfo->private;
10649bd41f2cSmrg   mPriv = pMse->mousePriv;
1065d075918cSmrg
1066d075918cSmrg   if (!mPriv->absoluteRequested) {
1067d075918cSmrg      /*
1068d075918cSmrg       * We can request for absolute mode, but it depends on
1069d075918cSmrg       * host whether it will send us absolute or relative
1070d075918cSmrg       * position.
1071d075918cSmrg       */
1072d075918cSmrg      VMMouseClient_RequestAbsolute();
1073d075918cSmrg      mPriv->absoluteRequested = TRUE;
10740da4cdccSmrg      LogMessageVerbSigSafe(X_INFO, -1, "VMWARE(0): vmmouse enable absolute mode\n");
1075d075918cSmrg   }
1076d075918cSmrg
10779bd41f2cSmrg   /*
10789bd41f2cSmrg    * First read the bytes in input device to clear the regular PS/2 fd so
1079d075918cSmrg    * we don't get called again.
10809bd41f2cSmrg    */
10819bd41f2cSmrg   /*
10829bd41f2cSmrg    * Set blocking to -1 on the first call because we know there is data to
10839bd41f2cSmrg    * read. Xisb automatically clears it after one successful read so that
10849bd41f2cSmrg    * succeeding reads are preceeded by a select with a 0 timeout to prevent
10859bd41f2cSmrg    * read from blocking indefinitely.
10869bd41f2cSmrg    */
10879bd41f2cSmrg   XisbBlockDuration(pMse->buffer, -1);
10889bd41f2cSmrg   while ((c = XisbRead(pMse->buffer)) >= 0) {
10899bd41f2cSmrg      len++;
10909bd41f2cSmrg      /*
10919bd41f2cSmrg       * regular PS packet consists of 3 bytes
1092d075918cSmrg       * We read 3 bytes to drain the PS/2 packet
10939bd41f2cSmrg       */
10949bd41f2cSmrg      if(len < 3) continue;
1095d075918cSmrg      len = 0;
10969bd41f2cSmrg      /*
10979bd41f2cSmrg       * Now get the real data from absolute pointing device
10989bd41f2cSmrg       */
10999bd41f2cSmrg      GetVMMouseMotionEvent(pInfo);
11009bd41f2cSmrg   }
11019bd41f2cSmrg   /*
11029bd41f2cSmrg    * There maybe still vmmouse data available
11039bd41f2cSmrg    */
11049bd41f2cSmrg   GetVMMouseMotionEvent(pInfo);
11059bd41f2cSmrg}
11069bd41f2cSmrg
11079bd41f2cSmrg
11089bd41f2cSmrg/*
11099bd41f2cSmrg *----------------------------------------------------------------------
11109bd41f2cSmrg *
11119bd41f2cSmrg * GetVMMouseMotionEvent --
11129bd41f2cSmrg * 	Read all the mouse data available from the absolute
11139bd41f2cSmrg * 	pointing device	and post it to the Xserver
1114d075918cSmrg *
11159bd41f2cSmrg * Results:
11169bd41f2cSmrg * 	None
1117d075918cSmrg *
11189bd41f2cSmrg * Side effects:
11199bd41f2cSmrg *	Real mouse data was read from the absolute pointing
11209bd41f2cSmrg *	device and posted to Xserver
1121d075918cSmrg *
11229bd41f2cSmrg *----------------------------------------------------------------------
11239bd41f2cSmrg */
11249bd41f2cSmrg
11259bd41f2cSmrgstatic void
11269bd41f2cSmrgGetVMMouseMotionEvent(InputInfoPtr pInfo){
11279bd41f2cSmrg   MouseDevPtr pMse;
1128d075918cSmrg   VMMousePrivPtr mPriv;
11299bd41f2cSmrg   int buttons, dx, dy, dz, dw;
11309bd41f2cSmrg   VMMOUSE_INPUT_DATA  vmmouseInput;
11319bd41f2cSmrg   int numPackets;
11329bd41f2cSmrg
1133d075918cSmrg   pMse = pInfo->private;
1134d075918cSmrg   mPriv = (VMMousePrivPtr)pMse->mousePriv;
11359bd41f2cSmrg   while((numPackets = VMMouseClient_GetInput(&vmmouseInput))){
11360da4cdccSmrg      int ps2Buttons = 0;
11379bd41f2cSmrg      if (numPackets == VMMOUSE_ERROR) {
11389bd41f2cSmrg         VMMouseClient_Disable();
11399bd41f2cSmrg         VMMouseClient_Enable();
11409bd41f2cSmrg         VMMouseClient_RequestAbsolute();
11410da4cdccSmrg         LogMessageVerbSigSafe(X_INFO, -1, "VMWARE(0): re-requesting absolute mode after reset\n");
11429bd41f2cSmrg         break;
11439bd41f2cSmrg      }
11449bd41f2cSmrg
11459bd41f2cSmrg      if(vmmouseInput.Buttons & VMMOUSE_MIDDLE_BUTTON)
11469bd41f2cSmrg	 ps2Buttons |= 0x04; 			/* Middle*/
11479bd41f2cSmrg      if(vmmouseInput.Buttons & VMMOUSE_RIGHT_BUTTON)
11489bd41f2cSmrg	 ps2Buttons |= 0x02; 			/* Right*/
11499bd41f2cSmrg      if(vmmouseInput.Buttons & VMMOUSE_LEFT_BUTTON)
11509bd41f2cSmrg	 ps2Buttons |= 0x01; 			/* Left*/
1151d075918cSmrg
11529bd41f2cSmrg      buttons = (ps2Buttons & 0x04) >> 1 |	/* Middle */
11539bd41f2cSmrg	 (ps2Buttons & 0x02) >> 1 |       	/* Right */
11549bd41f2cSmrg	 (ps2Buttons & 0x01) << 2;       	/* Left */
1155d075918cSmrg
11569bd41f2cSmrg      dx = vmmouseInput.X;
1157d075918cSmrg      dy = vmmouseInput.Y;
11589bd41f2cSmrg      dz = (char)vmmouseInput.Z;
11599bd41f2cSmrg      dw = 0;
1160d075918cSmrg      /*
1161d075918cSmrg       * Get the per package relative or absolute information.
1162d075918cSmrg       */
1163d075918cSmrg      mPriv->isCurrRelative = vmmouseInput.Flags & VMMOUSE_MOVE_RELATIVE;
11649bd41f2cSmrg      /* post an event */
11659bd41f2cSmrg      pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
1166d075918cSmrg      mPriv->vmmousePrevInput = vmmouseInput;
11679bd41f2cSmrg   }
11689bd41f2cSmrg}
11699bd41f2cSmrg
11709bd41f2cSmrg
11719bd41f2cSmrg/*
11729bd41f2cSmrg *----------------------------------------------------------------------
11739bd41f2cSmrg *
11749bd41f2cSmrg * VMMouseControlProc --
1175d075918cSmrg *	This function is unused
11769bd41f2cSmrg *
11779bd41f2cSmrg * Results:
11789bd41f2cSmrg * 	None
1179d075918cSmrg *
11809bd41f2cSmrg * Side effects:
11819bd41f2cSmrg * 	None
11829bd41f2cSmrg *
11839bd41f2cSmrg *----------------------------------------------------------------------
11849bd41f2cSmrg */
11859bd41f2cSmrg
11869bd41f2cSmrgstatic int
1187c4f7863aSmrgVMMouseControlProc(InputInfoPtr pInfo, xDeviceCtl * control)
11889bd41f2cSmrg{
11899bd41f2cSmrg   xf86Msg(X_INFO, "VMWARE(0): VMMouseControlProc\n");
11909bd41f2cSmrg   return (Success);
11919bd41f2cSmrg}
11929bd41f2cSmrg
11939bd41f2cSmrg
11949bd41f2cSmrg/*
11959bd41f2cSmrg *----------------------------------------------------------------------
11969bd41f2cSmrg *
11979bd41f2cSmrg *  VMMouseCloseProc --
1198d075918cSmrg *	This function is unused
11999bd41f2cSmrg *
12009bd41f2cSmrg * Results:
12019bd41f2cSmrg * 	None
1202d075918cSmrg *
12039bd41f2cSmrg * Side effects:
12049bd41f2cSmrg * 	None
12059bd41f2cSmrg *
12069bd41f2cSmrg *----------------------------------------------------------------------
12079bd41f2cSmrg */
12089bd41f2cSmrg
1209c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
12109bd41f2cSmrgstatic void
1211c4f7863aSmrgVMMouseCloseProc(InputInfoPtr pInfo)
12129bd41f2cSmrg{
12139bd41f2cSmrg   xf86Msg(X_INFO, "VMWARE(0): VMMouseCloseProc\n");
12149bd41f2cSmrg}
1215c4f7863aSmrg#endif
12169bd41f2cSmrg
12179bd41f2cSmrg
12189bd41f2cSmrg/*
12199bd41f2cSmrg *----------------------------------------------------------------------
12209bd41f2cSmrg *
12219bd41f2cSmrg *  VMMouseSwitchProc --
1222d075918cSmrg *	This function is unused
12239bd41f2cSmrg *
12249bd41f2cSmrg * Results:
12259bd41f2cSmrg * 	None
1226d075918cSmrg *
12279bd41f2cSmrg * Side effects:
12289bd41f2cSmrg * 	None
12299bd41f2cSmrg *
12309bd41f2cSmrg *----------------------------------------------------------------------
12319bd41f2cSmrg */
12329bd41f2cSmrg
12339bd41f2cSmrgstatic int
12349bd41f2cSmrgVMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
12359bd41f2cSmrg{
12369bd41f2cSmrg   xf86Msg(X_INFO, "VMWARE(0): VMMouseSwitchMode\n");
12379bd41f2cSmrg   return (Success);
12389bd41f2cSmrg}
12399bd41f2cSmrg
12409bd41f2cSmrg
12419bd41f2cSmrg/*
12429bd41f2cSmrg *----------------------------------------------------------------------
12439bd41f2cSmrg *
12449bd41f2cSmrg * VMMouseConvertProc  --
12459bd41f2cSmrg * 	This function was called by Xserver to convert valuators to X and Y
1246d075918cSmrg *
12479bd41f2cSmrg * Results:
12489bd41f2cSmrg * 	TRUE
1249d075918cSmrg *
12509bd41f2cSmrg * Side effects:
12519bd41f2cSmrg * 	X and Y was converted according to current Screen dimension
1252d075918cSmrg *
12539bd41f2cSmrg *----------------------------------------------------------------------
12549bd41f2cSmrg */
12559bd41f2cSmrg
1256c4f7863aSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
12579bd41f2cSmrgstatic Bool
12589bd41f2cSmrgVMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
12599bd41f2cSmrg	     int v3, int v4, int v5, int *x, int *y)
12609bd41f2cSmrg{
12619bd41f2cSmrg   MouseDevPtr pMse;
12629bd41f2cSmrg   VMMousePrivPtr mPriv;
12639bd41f2cSmrg   double factorX, factorY;
12649bd41f2cSmrg
12659bd41f2cSmrg   pMse = pInfo->private;
12669bd41f2cSmrg   mPriv = pMse->mousePriv;
12679bd41f2cSmrg
12689bd41f2cSmrg   if (first != 0 || num != 2)
12699bd41f2cSmrg      return FALSE;
1270d075918cSmrg
1271d075918cSmrg   if(mPriv->isCurrRelative) {
12729bd41f2cSmrg      *x = v0;
12739bd41f2cSmrg      *y = v1;
12749bd41f2cSmrg   } else {
12759bd41f2cSmrg      factorX = ((double) screenInfo.screens[mPriv->screenNum]->width) / (double) 65535;
12769bd41f2cSmrg      factorY = ((double) screenInfo.screens[mPriv->screenNum]->height) / (double) 65535;
1277d075918cSmrg
12789bd41f2cSmrg      *x = v0 * factorX + 0.5;
12799bd41f2cSmrg      *y = v1 * factorY + 0.5;
1280d075918cSmrg
12819bd41f2cSmrg      if (mPriv->screenNum != -1) {
12829bd41f2cSmrg	 xf86XInputSetScreen(pInfo, mPriv->screenNum, *x, *y);
12839bd41f2cSmrg      }
12849bd41f2cSmrg   }
12859bd41f2cSmrg   return TRUE;
12869bd41f2cSmrg}
1287c4f7863aSmrg#endif
12889bd41f2cSmrg
12899bd41f2cSmrg
12909bd41f2cSmrg#ifdef XFree86LOADER
12919bd41f2cSmrg
12929bd41f2cSmrg/*
12939bd41f2cSmrg *----------------------------------------------------------------------
12949bd41f2cSmrg *
12959bd41f2cSmrg * VMMouseUnplug  --
12969bd41f2cSmrg * 	This function was called by Xserver when unplug
1297d075918cSmrg *
12989bd41f2cSmrg * Results:
12999bd41f2cSmrg * 	None
1300d075918cSmrg *
13019bd41f2cSmrg * Side effects:
13029bd41f2cSmrg * 	None
1303d075918cSmrg *
13049bd41f2cSmrg *----------------------------------------------------------------------
13059bd41f2cSmrg */
13069bd41f2cSmrg
13079bd41f2cSmrgstatic void
13089bd41f2cSmrgVMMouseUnplug(pointer p)
13099bd41f2cSmrg{
13109bd41f2cSmrg   xf86Msg(X_INFO, "VMWARE(0): VMMouseUnplug\n");
13119bd41f2cSmrg}
13129bd41f2cSmrg
13139bd41f2cSmrg
13149bd41f2cSmrg/*
13159bd41f2cSmrg *----------------------------------------------------------------------
13169bd41f2cSmrg *
13179bd41f2cSmrg * VMMousePlug  --
13189bd41f2cSmrg * 	This function was called when Xserver load vmmouse module. It will
1319d075918cSmrg * 	integrate the  module infto the XFree86 loader architecutre.
1320d075918cSmrg *
13219bd41f2cSmrg * Results:
13229bd41f2cSmrg * 	TRUE
1323d075918cSmrg *
13249bd41f2cSmrg * Side effects:
1325d075918cSmrg * 	Regular mouse module was loaded as a submodule. In case
13269bd41f2cSmrg * 	absolute pointing device is not available, we can always fall back
13279bd41f2cSmrg *	to the regular mouse module
1328d075918cSmrg *
13299bd41f2cSmrg *----------------------------------------------------------------------
13309bd41f2cSmrg */
13319bd41f2cSmrg
13329bd41f2cSmrgstatic pointer
13339bd41f2cSmrgVMMousePlug(pointer	module,
13349bd41f2cSmrg	    pointer	options,
13359bd41f2cSmrg	    int		*errmaj,
13369bd41f2cSmrg	    int		*errmin)
13379bd41f2cSmrg{
13389bd41f2cSmrg   static Bool Initialised = FALSE;
13399bd41f2cSmrg
13409418810dSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7
13419bd41f2cSmrg   xf86LoaderReqSymLists(reqSymbols, NULL);
13429418810dSmrg#endif
1343d075918cSmrg
1344d075918cSmrg   if (!Initialised)
13459bd41f2cSmrg      Initialised = TRUE;
13469bd41f2cSmrg
13479bd41f2cSmrg   xf86Msg(X_INFO, "VMWARE(0): VMMOUSE module was loaded\n");
13489bd41f2cSmrg   xf86AddInputDriver(&VMMOUSE, module, 0);
13499bd41f2cSmrg
1350b15a006bSmrg#ifndef NO_MOUSE_MODULE
1351b15a006bSmrg{
1352b15a006bSmrg   char *name;
13539bd41f2cSmrg   /*
13549bd41f2cSmrg    * Load the normal mouse module as submodule
13559bd41f2cSmrg    * If we fail in PreInit later, this allows us to fall back to normal mouse module
13569bd41f2cSmrg    */
13579bd41f2cSmrg#ifndef NORMALISE_MODULE_NAME
13589bd41f2cSmrg   name = xstrdup("mouse");
13599bd41f2cSmrg#else
13609bd41f2cSmrg   /* Normalise the module name */
13619bd41f2cSmrg   name = xf86NormalizeName("mouse");
13629bd41f2cSmrg#endif
13639bd41f2cSmrg
13649bd41f2cSmrg   if (!LoadSubModule(module, name, NULL, NULL, NULL, NULL, errmaj, errmin)) {
13659bd41f2cSmrg      LoaderErrorMsg(NULL, name, *errmaj, *errmin);
13669bd41f2cSmrg   }
1367c4f7863aSmrg   free(name);
1368b15a006bSmrg}
1369b15a006bSmrg#endif
1370d075918cSmrg
13719bd41f2cSmrg   return module;
13729bd41f2cSmrg}
13739bd41f2cSmrg
13749bd41f2cSmrgstatic XF86ModuleVersionInfo VMMouseVersionRec = {
13759bd41f2cSmrg   "vmmouse",
13769bd41f2cSmrg   MODULEVENDORSTRING,
13779bd41f2cSmrg   MODINFOSTRING1,
13789bd41f2cSmrg   MODINFOSTRING2,
13799bd41f2cSmrg   XORG_VERSION_CURRENT,
13809418810dSmrg   PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
13819bd41f2cSmrg   ABI_CLASS_XINPUT,
13829bd41f2cSmrg   ABI_XINPUT_VERSION,
13839bd41f2cSmrg   MOD_CLASS_XINPUT,
13849bd41f2cSmrg   {0, 0, 0, 0}		/* signature, to be patched into the file by a tool */
13859bd41f2cSmrg};
13869bd41f2cSmrg
13879bd41f2cSmrg/*
13889bd41f2cSmrg * The variable contains the necessary information to load and initialize the module
13899bd41f2cSmrg */
1390b15a006bSmrg_X_EXPORT XF86ModuleData vmmouseModuleData = {
13919bd41f2cSmrg   &VMMouseVersionRec,
13929bd41f2cSmrg   VMMousePlug,
13939bd41f2cSmrg   VMMouseUnplug
13949bd41f2cSmrg};
13959bd41f2cSmrg#endif /* XFree86LOADER */
1396