summaryrefslogtreecommitdiff
path: root/driver/xf86-input-vmmouse/src/vmmouse.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 19:58:26 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 19:58:26 +0000
commit075437de9aaeddb5f1d0d501ac0d5a9a8d55c2cd (patch)
treec3f3fe5204af2e093adf2b0bdebb81920d715e1f /driver/xf86-input-vmmouse/src/vmmouse.c
parent1404fdd11b30cf4a47356fa28cc31873c62351c7 (diff)
Importing xf86-input-vmmouse 12.4.0
Diffstat (limited to 'driver/xf86-input-vmmouse/src/vmmouse.c')
-rw-r--r--driver/xf86-input-vmmouse/src/vmmouse.c1173
1 files changed, 1173 insertions, 0 deletions
diff --git a/driver/xf86-input-vmmouse/src/vmmouse.c b/driver/xf86-input-vmmouse/src/vmmouse.c
new file mode 100644
index 000000000..5543c4ca7
--- /dev/null
+++ b/driver/xf86-input-vmmouse/src/vmmouse.c
@@ -0,0 +1,1173 @@
+/*
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ * Copyright 1993 by David Dawes <dawes@xfree86.org>
+ * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+ * Copyright 1994-2002 by The XFree86 Project, Inc.
+ * Copyright 2002 by Paul Elliott
+ * Copyright 2002-2006 by VMware, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of copyright holders not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. The copyright holders
+ * make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * vmmouse.c --
+ *
+ * This is a modified version of the mouse input driver
+ * provided in Xserver/hw/xfree86/input/mouse/mouse.c
+ *
+ * Although all data is read using the vmmouse protocol, notification
+ * is still done through the PS/2 port, so all the basic code for
+ * interacting with the port is retained.
+ *
+ */
+
+
+/*****************************************************************************
+ * Standard Headers
+ ****************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+
+#include "xf86.h"
+
+#ifdef XINPUT
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h"
+#else
+#include "inputstr.h"
+#endif
+
+#include "xf86Xinput.h"
+#include "xf86_OSproc.h"
+#include "xf86OSmouse.h"
+#include "compiler.h"
+
+#include "xisb.h"
+#include "mipointer.h"
+
+/*****************************************************************************
+ * Local Headers
+ ****************************************************************************/
+#include "vmmouse_client.h"
+
+/*
+ * Version constants
+ */
+#define VMMOUSE_MAJOR_VERSION 12
+#define VMMOUSE_MINOR_VERSION 4
+#define VMMOUSE_PATCHLEVEL 0
+
+/*****************************************************************************
+ * static function header
+ ****************************************************************************/
+#ifdef XFree86LOADER
+static const OptionInfoRec *VMMouseAvailableOptions(void *unused);
+#endif
+static InputInfoPtr VMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags);
+static void VMMouseUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
+static void MouseCommonOptions(InputInfoPtr pInfo);
+static void GetVMMouseMotionEvent(InputInfoPtr pInfo);
+static void VMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw);
+static void VMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy);
+static Bool VMMouseDeviceControl(DeviceIntPtr device, int mode);
+static void VMMouseCloseProc(LocalDevicePtr local);
+static int VMMouseControlProc(LocalDevicePtr local, xDeviceCtl * control);
+static void VMMouseReadInput(InputInfoPtr pInfo);
+static int VMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode);
+static Bool VMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
+ int v3, int v4, int v5, int *x, int *y);
+static void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl);
+
+/******************************************************************************
+ * Definitions
+ *****************************************************************************/
+typedef struct {
+ int screenNum;
+ Bool vmmouseAvailable;
+ Bool relative;
+} VMMousePrivRec, *VMMousePrivPtr;
+
+static const char *reqSymbols[] = {
+ "InitPointerDeviceStruct",
+ "LoaderSymbol",
+ "LoadSubModule",
+ "miPointerGetMotionBufferSize",
+ "miPointerGetMotionEvents",
+ "screenInfo",
+ "Xcalloc",
+ "xf86AddEnabledDevice",
+ "xf86AddInputDriver",
+ "xf86AddModuleInfo",
+ "xf86AllocateInput",
+ "xf86BlockSIGIO",
+ "xf86CloseSerial",
+ "xf86CollectInputOptions",
+ "xf86ffs",
+ "xf86FlushInput",
+ "xf86GetAllowMouseOpenFail",
+ "xf86GetMotionEvents",
+ "xf86InitValuatorAxisStruct",
+ "xf86InitValuatorDefaults",
+ "xf86LoaderCheckSymbol",
+ "xf86MotionHistoryAllocate",
+ "xf86Msg",
+ "xf86NameCmp",
+ "xf86OpenSerial",
+ "xf86OSMouseInit",
+ "xf86PostButtonEvent",
+ "xf86PostMotionEvent",
+ "xf86ProcessCommonOptions",
+ "xf86RemoveEnabledDevice",
+ "xf86SetIntOption",
+ "xf86SetStrOption",
+ "xf86sprintf",
+ "xf86sscanf",
+ "xf86UnblockSIGIO",
+ "xf86usleep",
+ "xf86XInputSetScreen",
+ "Xfree",
+ "XisbBlockDuration",
+ "XisbFree",
+ "XisbNew",
+ "XisbRead",
+ "Xstrdup",
+ NULL
+};
+
+InputDriverRec VMMOUSE = {
+ 1,
+ "vmmouse",
+ NULL,
+ VMMousePreInit,
+ VMMouseUnInit,
+ NULL,
+ 0
+};
+
+typedef enum {
+ OPTION_ALWAYS_CORE,
+ OPTION_SEND_CORE_EVENTS,
+ OPTION_CORE_POINTER,
+ OPTION_SEND_DRAG_EVENTS,
+ OPTION_HISTORY_SIZE,
+ OPTION_DEVICE,
+ OPTION_PROTOCOL,
+ OPTION_BUTTONS,
+ OPTION_EMULATE_3_BUTTONS,
+ OPTION_EMULATE_3_TIMEOUT,
+ OPTION_CHORD_MIDDLE,
+ OPTION_FLIP_XY,
+ OPTION_INV_X,
+ OPTION_INV_Y,
+ OPTION_ANGLE_OFFSET,
+ OPTION_Z_AXIS_MAPPING,
+ OPTION_SAMPLE_RATE,
+ OPTION_RESOLUTION,
+ OPTION_EMULATE_WHEEL,
+ OPTION_EMU_WHEEL_BUTTON,
+ OPTION_EMU_WHEEL_INERTIA,
+ OPTION_X_AXIS_MAPPING,
+ OPTION_Y_AXIS_MAPPING,
+ OPTION_AUTO_SOFT,
+ OPTION_DRAGLOCKBUTTONS
+} MouseOpts;
+
+/*
+ * Define the acceptable mouse options
+ * Currently not all of those options are supported
+ *
+ */
+static const OptionInfoRec mouseOptions[] = {
+ { OPTION_ALWAYS_CORE, "AlwaysCore", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SEND_CORE_EVENTS, "SendCoreEvents", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_CORE_POINTER, "CorePointer", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SEND_DRAG_EVENTS, "SendDragEvents", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_HISTORY_SIZE, "HistorySize", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE },
+ { OPTION_PROTOCOL, "Protocol", OPTV_STRING, {0}, FALSE },
+ { OPTION_BUTTONS, "Buttons", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_EMULATE_3_BUTTONS, "Emulate3Buttons",OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_EMULATE_3_TIMEOUT, "Emulate3Timeout",OPTV_INTEGER, {0}, FALSE },
+ { OPTION_CHORD_MIDDLE, "ChordMiddle", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_FLIP_XY, "FlipXY", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_INV_X, "InvX", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_INV_Y, "InvY", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ANGLE_OFFSET, "AngleOffset", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_Z_AXIS_MAPPING, "ZAxisMapping", OPTV_STRING, {0}, FALSE },
+ { OPTION_SAMPLE_RATE, "SampleRate", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_RESOLUTION, "Resolution", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_EMULATE_WHEEL, "EmulateWheel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_EMU_WHEEL_BUTTON, "EmulateWheelButton", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_EMU_WHEEL_INERTIA, "EmulateWheelInertia", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_X_AXIS_MAPPING, "XAxisMapping", OPTV_STRING, {0}, FALSE },
+ { OPTION_Y_AXIS_MAPPING, "YAxisMapping", OPTV_STRING, {0}, FALSE },
+ { OPTION_AUTO_SOFT, "AutoSoft", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DRAGLOCKBUTTONS, "DragLockButtons",OPTV_STRING, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+static char reverseMap[32] = { 0, 4, 2, 6, 1, 5, 3, 7,
+ 8, 12, 10, 14, 9, 13, 11, 15,
+ 16, 20, 18, 22, 17, 21, 19, 23,
+ 24, 28, 26, 30, 25, 29, 27, 31};
+
+#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f])
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMousePreInit --
+ * This function collect all the information that is necessary to
+ * determine the configuration of the hardware and to prepare the
+ * device for being used
+ *
+ * Results:
+ * An InputInfoPtr object which points to vmmouse's information,
+ * if the absolute pointing device available
+ * Otherwise, an InputInfoPtr of regular mouse
+ *
+ * Side effects:
+ * VMMouse was initialized with necessary information
+ *
+ *----------------------------------------------------------------------
+ */
+
+static InputInfoPtr
+VMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+{
+ InputInfoPtr pInfo;
+ MouseDevPtr pMse;
+ VMMousePrivPtr mPriv;
+ OSMouseInfoPtr osInfo = NULL;
+
+ /*
+ * let Xserver init the mouse first
+ */
+ osInfo = xf86OSMouseInit(0);
+ if (!osInfo)
+ return FALSE;
+
+ mPriv = xcalloc (1, sizeof (VMMousePrivRec));
+
+
+ if (!mPriv) {
+ return NULL;
+ }
+ /*
+ * try to enable vmmouse here
+ */
+ if (!VMMouseClient_Enable()) {
+ /*
+ * vmmouse failed
+ * Fall back to normal mouse module
+ */
+ InputDriverRec *passthruMouse;
+ xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n");
+ mPriv->vmmouseAvailable = FALSE;
+ passthruMouse = (InputDriverRec *)LoaderSymbol("MOUSE");
+ xfree(mPriv);
+ if(passthruMouse != NULL){
+ return (passthruMouse->PreInit)(drv, dev, flags);
+ } else {
+ return NULL;
+ }
+
+ } else {
+ /*
+ * vmmouse is available
+ */
+ mPriv->vmmouseAvailable = TRUE;
+ xf86Msg(X_INFO, "VMWARE(0): vmmouse is available\n");
+ /*
+ * Disable the absolute pointing device for now
+ * It will be enabled during DEVICE_ON phase
+ */
+ VMMouseClient_Disable();
+ }
+
+ if (!(pInfo = xf86AllocateInput(drv, 0))) {
+ xfree(mPriv);
+ return NULL;
+ }
+
+ /* Settup the pInfo */
+ pInfo->name = dev->identifier;
+ pInfo->type_name = XI_MOUSE;
+ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ pInfo->device_control = VMMouseDeviceControl;
+ pInfo->read_input = VMMouseReadInput;
+ pInfo->motion_history_proc = xf86GetMotionEvents;
+ pInfo->control_proc = VMMouseControlProc;
+ pInfo->close_proc = VMMouseCloseProc;
+ pInfo->switch_mode = VMMouseSwitchMode;
+ pInfo->conversion_proc = VMMouseConvertProc;
+ pInfo->reverse_conversion_proc = NULL;
+ pInfo->fd = -1;
+ pInfo->dev = NULL;
+ pInfo->private_flags = 0;
+ pInfo->always_core_feedback = 0;
+ pInfo->conf_idev = dev;
+
+ /* Allocate the MouseDevRec and initialise it. */
+ if (!(pMse = xcalloc(sizeof(MouseDevRec), 1))) {
+ xfree(mPriv);
+ return pInfo;
+ }
+
+ pInfo->private = pMse;
+ pMse->Ctrl = MouseCtrl;
+ pMse->PostEvent = VMMousePostEvent;
+ pMse->CommonOptions = MouseCommonOptions;
+ pMse->mousePriv = mPriv;
+
+
+ /* Collect the options, and process the common options. */
+ xf86CollectInputOptions(pInfo, NULL, NULL);
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+ /* Check if the device can be opened. */
+ pInfo->fd = xf86OpenSerial(pInfo->options);
+ if (pInfo->fd == -1) {
+ if (xf86GetAllowMouseOpenFail())
+ xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
+ else {
+ xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
+ if (pMse->mousePriv)
+ xfree(pMse->mousePriv);
+ xfree(pMse);
+ pInfo->private = NULL;
+ return pInfo;
+ }
+ }
+ xf86CloseSerial(pInfo->fd);
+ pInfo->fd = -1;
+
+ /* Process the options */
+ pMse->CommonOptions(pInfo);
+
+ /* set up the current screen num */
+ mPriv->screenNum = xf86SetIntOption(pInfo->options, "ScreenNumber", 0);
+
+ pInfo->flags |= XI86_CONFIGURED;
+ return pInfo;
+}
+
+#ifdef XFree86LOADER
+static const OptionInfoRec *
+VMMouseAvailableOptions(void *unused)
+{
+ return (mouseOptions);
+}
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MouseCtrl --
+ * Alter the control paramters for the mouse.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+ InputInfoPtr pInfo;
+ MouseDevPtr pMse;
+
+ pInfo = device->public.devicePrivate;
+ pMse = pInfo->private;
+
+#ifdef EXTMOUSEDEBUG
+ xf86Msg(X_INFO, "VMMOUSE(0): MouseCtrl pMse=%p\n", pMse);
+#endif
+
+ pMse->num = ctrl->num;
+ pMse->den = ctrl->den;
+ pMse->threshold = ctrl->threshold;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseDoPostEvent --
+ * Post the mouse button event and mouse motion event to Xserver
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Mouse location and button status was updated
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy)
+{
+ MouseDevPtr pMse;
+ VMMousePrivPtr mPriv;
+ int truebuttons;
+ int id, change;
+
+ pMse = pInfo->private;
+ mPriv = (VMMousePrivPtr)pMse->mousePriv;
+
+ /*
+ * The following truebuttons/reverseBits and lastButtons are
+ * used to compare the current buttons and the previous buttons
+ * to find the button changes during two mouse events
+ */
+ truebuttons = buttons;
+
+ buttons = reverseBits(reverseMap, buttons);
+
+ if (dx || dy) {
+ xf86PostMotionEvent(pInfo->dev, !mPriv->relative, 0, 2, dx, dy);
+ }
+
+ if (truebuttons != pMse->lastButtons) {
+ change = buttons ^ reverseBits(reverseMap, pMse->lastButtons);
+ while (change) {
+ id = ffs(change);
+ change &= ~(1 << (id - 1));
+ xf86PostButtonEvent(pInfo->dev, 0, id,
+ (buttons & (1 << (id - 1))), 0, 0);
+ }
+ pMse->lastButtons = truebuttons;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMousePostEvent --
+ * Prepare the mouse status according to the Z axis mapping
+ * before we post the event to Xserver
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Buttons was updated according to Z axis mapping
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw)
+{
+ MouseDevPtr pMse;
+ int zbutton = 0;
+ VMMousePrivPtr mPriv;
+
+ pMse = pInfo->private;
+ mPriv = (VMMousePrivPtr)pMse->mousePriv;
+ /* Map the Z axis movement. */
+ /* XXX Could this go in the conversion_proc? */
+ switch (pMse->negativeZ) {
+ case MSE_NOZMAP: /* do nothing */
+ break;
+ case MSE_MAPTOX:
+ if (dz != 0) {
+ if(mPriv->relative)
+ dx = dz;
+ else
+ dx += dz;
+ dz = 0;
+ }
+ break;
+ case MSE_MAPTOY:
+ if (dz != 0) {
+ if(mPriv->relative)
+ dy = dz;
+ else
+ dy += dz;
+ dz = 0;
+ }
+ break;
+ default: /* buttons */
+ buttons &= ~(pMse->negativeZ | pMse->positiveZ
+ | pMse->negativeW | pMse->positiveW);
+ if (dw < 0 || dz < -1) {
+ zbutton = pMse->negativeW;
+ }
+ else if (dz < 0) {
+ zbutton = pMse->negativeZ;
+ }
+ else if (dw > 0 || dz > 1) {
+ zbutton = pMse->positiveW;
+ }
+ else if (dz > 0) {
+ zbutton = pMse->positiveZ;
+ }
+ buttons |= zbutton;
+ dz = 0;
+ break;
+ }
+
+ VMMouseDoPostEvent(pInfo, buttons, dx, dy);
+
+ /*
+ * If dz has been mapped to a button `down' event, we need to cook up
+ * a corresponding button `up' event.
+ */
+ if (zbutton) {
+ buttons &= ~zbutton;
+ if(mPriv->relative)
+ VMMouseDoPostEvent(pInfo, buttons, 0, 0);
+ else
+ VMMouseDoPostEvent(pInfo, buttons, dx, dy);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FlushButtons --
+ *
+ * FlushButtons -- send button up events for sanity. It is called
+ * during DEVICE_ON in VMMouseDeviceControl
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FlushButtons(MouseDevPtr pMse)
+{
+
+ /* If no button down is pending xf86PostButtonEvent()
+ * will discard them. So we are on the safe side. */
+
+ int i, blocked;
+
+ pMse->lastButtons = 0;
+
+ blocked = xf86BlockSIGIO ();
+ for (i = 1; i <= 5; i++)
+ xf86PostButtonEvent(pMse->device,0,i,0,0,0);
+ xf86UnblockSIGIO (blocked);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MouseCommonOptions --
+ * Process acceptable mouse options. Currently we only process
+ * "Buttons" and "ZAxisMapping" options.
+ * More options can be added later on
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The buttons was setup according to the options
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MouseCommonOptions(InputInfoPtr pInfo)
+{
+ MouseDevPtr pMse;
+ MessageType from = X_DEFAULT;
+ char *s;
+ int origButtons;
+
+ pMse = pInfo->private;
+
+ pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
+ from = X_CONFIG;
+ if (!pMse->buttons) {
+ pMse->buttons = MSE_DFLTBUTTONS;
+ from = X_DEFAULT;
+ }
+ origButtons = pMse->buttons;
+
+ /*
+ * "emulate3Buttons" and "Drag Lock" is not supported
+ */
+
+ /*
+ * Process option for ZAxisMapping
+ */
+ s = xf86SetStrOption(pInfo->options, "ZAxisMapping", NULL);
+ if (s) {
+ int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+ char *msg = NULL;
+
+ if (!xf86NameCmp(s, "x")) {
+ pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX;
+ pMse->negativeW = pMse->positiveW = MSE_MAPTOX;
+ msg = xstrdup("X axis");
+ } else if (!xf86NameCmp(s, "y")) {
+ pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY;
+ pMse->negativeW = pMse->positiveW = MSE_MAPTOY;
+ msg = xstrdup("Y axis");
+ } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 &&
+ b1 > 0 && b1 <= MSE_MAXBUTTONS &&
+ b2 > 0 && b2 <= MSE_MAXBUTTONS) {
+ msg = xstrdup("buttons XX and YY");
+ if (msg)
+ sprintf(msg, "buttons %d and %d", b1, b2);
+ pMse->negativeZ = pMse->negativeW = 1 << (b1-1);
+ pMse->positiveZ = pMse->positiveW = 1 << (b2-1);
+ if (b1 > pMse->buttons) pMse->buttons = b1;
+ if (b2 > pMse->buttons) pMse->buttons = b2;
+
+ /*
+ * Option "ZAxisMapping" "N1 N2 N3 N4" not supported
+ */
+ pMse->negativeW = pMse->positiveW = MSE_NOZMAP;
+ } else {
+ pMse->negativeZ = pMse->positiveZ = MSE_NOZMAP;
+ pMse->negativeW = pMse->positiveW = MSE_NOZMAP;
+ }
+ if (msg) {
+ xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg);
+ xfree(msg);
+ } else {
+ xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n",
+ pInfo->name, s);
+ }
+ }
+
+ /*
+ * Emulatewheel is not supported
+ */
+ if (origButtons != pMse->buttons)
+ from = X_CONFIG;
+
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseUnInit --
+ * This function was supposed to be called by Xserver to do Un-Init.
+ * But it was unused now
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMMouseUnInit(InputDriverPtr drv, LocalDevicePtr local, int flags)
+{
+ xf86Msg(X_INFO, "VMWARE(0): VMMouseUnInit\n");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseDeviceControl --
+ * This function was called by Xserver during DEVICE_INIT, DEVICE_ON,
+ * DEVICE_OFF and DEVICE_CLOSE phase
+ *
+ * Results:
+ * TRUE, if sucessful
+ * FALSE, if failed
+ *
+ * Side effects:
+ * Absolute pointing device is enabled during DEVICE_ON
+ * Absolute pointing device is disabled during DEVICE_OFF
+ * and DEVICE_CLOSE
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+VMMouseDeviceControl(DeviceIntPtr device, int mode)
+{
+ InputInfoPtr pInfo;
+ MouseDevPtr pMse;
+ VMMousePrivPtr mPriv;
+ unsigned char map[MSE_MAXBUTTONS + 1];
+ int i;
+
+ pInfo = device->public.devicePrivate;
+ pMse = pInfo->private;
+ pMse->device = device;
+ mPriv = (VMMousePrivPtr)pMse->mousePriv;
+
+ switch (mode){
+ case DEVICE_INIT:
+ device->public.on = FALSE;
+ /*
+ * [KAZU-241097] We don't know exactly how many buttons the
+ * device has, so setup the map with the maximum number.
+ */
+ for (i = 0; i < MSE_MAXBUTTONS; i++)
+ map[i + 1] = i + 1;
+
+ InitPointerDeviceStruct((DevicePtr)device, map,
+ min(pMse->buttons, MSE_MAXBUTTONS),
+ miPointerGetMotionEvents, pMse->Ctrl,
+ miPointerGetMotionBufferSize());
+
+ /* X valuator */
+ xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
+ xf86InitValuatorDefaults(device, 0);
+ /* Y valuator */
+ xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
+ xf86InitValuatorDefaults(device, 1);
+ xf86MotionHistoryAllocate(pInfo);
+
+ xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_INIT\n");
+#ifdef EXTMOUSEDEBUG
+ xf86Msg(X_INFO, "assigning %p atom=%d name=%s\n", device, pInfo->atom,
+ pInfo->name);
+#endif
+ break;
+
+ case DEVICE_ON:
+ xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_ON\n");
+ pInfo->fd = xf86OpenSerial(pInfo->options);
+ if (pInfo->fd == -1)
+ xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
+ else {
+ pMse->buffer = XisbNew(pInfo->fd, 64);
+ if (!pMse->buffer) {
+ xf86CloseSerial(pInfo->fd);
+ pInfo->fd = -1;
+ } else {
+ VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv;
+ if (mPriv != NULL) {
+ /*
+ * enable absolute pointing device here
+ */
+ if (!VMMouseClient_Enable()) {
+ xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n");
+ mPriv->vmmouseAvailable = FALSE;
+ device->public.on = FALSE;
+ return FALSE;
+ } else {
+ mPriv->vmmouseAvailable = TRUE;
+ VMMouseClient_RequestAbsolute();
+ mPriv->relative = FALSE;
+ xf86Msg(X_INFO, "VMWARE(0): vmmouse enabled\n");
+ }
+ }
+ xf86FlushInput(pInfo->fd);
+ xf86AddEnabledDevice(pInfo);
+ }
+ }
+ pMse->lastButtons = 0;
+ device->public.on = TRUE;
+ FlushButtons(pMse);
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_OFF/CLOSE\n");
+
+ if (pInfo->fd != -1) {
+ VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv;
+ if( mPriv->vmmouseAvailable ) {
+ VMMouseClient_Disable();
+ mPriv->vmmouseAvailable = FALSE;
+ }
+
+ xf86RemoveEnabledDevice(pInfo);
+ if (pMse->buffer) {
+ XisbFree(pMse->buffer);
+ pMse->buffer = NULL;
+ }
+ xf86CloseSerial(pInfo->fd);
+ pInfo->fd = -1;
+ }
+ device->public.on = FALSE;
+ usleep(300000);
+ break;
+
+ }
+
+ return Success;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseReadInput --
+ * This function was called by Xserver when there is data available
+ * in the input device
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Input data in regular PS/2 fd was cleared
+ * Real mouse data was read from the absolute pointing device
+ * and posted to Xserver
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMMouseReadInput(InputInfoPtr pInfo)
+{
+ MouseDevPtr pMse;
+ VMMousePrivPtr mPriv;
+ int c;
+ int len = 0;
+
+ pMse = pInfo->private;
+ mPriv = pMse->mousePriv;
+
+ /*
+ * First read the bytes in input device to clear the regular PS/2 fd so
+ * we don't get called again.
+ */
+ /*
+ * Set blocking to -1 on the first call because we know there is data to
+ * read. Xisb automatically clears it after one successful read so that
+ * succeeding reads are preceeded by a select with a 0 timeout to prevent
+ * read from blocking indefinitely.
+ */
+ XisbBlockDuration(pMse->buffer, -1);
+ while ((c = XisbRead(pMse->buffer)) >= 0) {
+ len++;
+ /*
+ * regular PS packet consists of 3 bytes
+ * We read 3 bytes to drain the PS/2 packet
+ */
+ if(len < 3) continue;
+ len = 0;
+ /*
+ * Now get the real data from absolute pointing device
+ */
+ GetVMMouseMotionEvent(pInfo);
+ }
+ /*
+ * There maybe still vmmouse data available
+ */
+ GetVMMouseMotionEvent(pInfo);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetVMMouseMotionEvent --
+ * Read all the mouse data available from the absolute
+ * pointing device and post it to the Xserver
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Real mouse data was read from the absolute pointing
+ * device and posted to Xserver
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GetVMMouseMotionEvent(InputInfoPtr pInfo){
+ MouseDevPtr pMse;
+ int buttons, dx, dy, dz, dw;
+ VMMOUSE_INPUT_DATA vmmouseInput;
+ int ps2Buttons = 0;
+
+ pMse = pInfo->private;
+ while(VMMouseClient_GetInput(&vmmouseInput)){
+ if(vmmouseInput.Buttons & VMMOUSE_MIDDLE_BUTTON)
+ ps2Buttons |= 0x04; /* Middle*/
+ if(vmmouseInput.Buttons & VMMOUSE_RIGHT_BUTTON)
+ ps2Buttons |= 0x02; /* Right*/
+ if(vmmouseInput.Buttons & VMMOUSE_LEFT_BUTTON)
+ ps2Buttons |= 0x01; /* Left*/
+
+ buttons = (ps2Buttons & 0x04) >> 1 | /* Middle */
+ (ps2Buttons & 0x02) >> 1 | /* Right */
+ (ps2Buttons & 0x01) << 2; /* Left */
+
+ dx = vmmouseInput.X;
+ dy = vmmouseInput.Y;
+ dz = (char)vmmouseInput.Z;
+ dw = 0;
+ /* post an event */
+ pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseControlProc --
+ * This function is unused
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+VMMouseControlProc(LocalDevicePtr local, xDeviceCtl * control)
+{
+ xf86Msg(X_INFO, "VMWARE(0): VMMouseControlProc\n");
+ return (Success);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseCloseProc --
+ * This function is unused
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMMouseCloseProc(LocalDevicePtr local)
+{
+ xf86Msg(X_INFO, "VMWARE(0): VMMouseCloseProc\n");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseSwitchProc --
+ * This function is unused
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+VMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
+{
+ xf86Msg(X_INFO, "VMWARE(0): VMMouseSwitchMode\n");
+ return (Success);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseConvertProc --
+ * This function was called by Xserver to convert valuators to X and Y
+ *
+ * Results:
+ * TRUE
+ *
+ * Side effects:
+ * X and Y was converted according to current Screen dimension
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+VMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
+ int v3, int v4, int v5, int *x, int *y)
+{
+ MouseDevPtr pMse;
+ VMMousePrivPtr mPriv;
+ double factorX, factorY;
+
+ pMse = pInfo->private;
+ mPriv = pMse->mousePriv;
+
+ if (first != 0 || num != 2)
+ return FALSE;
+
+ if(mPriv->relative) {
+ *x = v0;
+ *y = v1;
+ } else {
+ factorX = ((double) screenInfo.screens[mPriv->screenNum]->width) / (double) 65535;
+ factorY = ((double) screenInfo.screens[mPriv->screenNum]->height) / (double) 65535;
+
+ *x = v0 * factorX + 0.5;
+ *y = v1 * factorY + 0.5;
+
+ if (mPriv->screenNum != -1) {
+ xf86XInputSetScreen(pInfo, mPriv->screenNum, *x, *y);
+ }
+ }
+ return TRUE;
+}
+
+
+#ifdef XFree86LOADER
+ModuleInfoRec VMMouseInfo = {
+ 1,
+ "VMMOUSE",
+ NULL,
+ 0,
+ VMMouseAvailableOptions,
+};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMouseUnplug --
+ * This function was called by Xserver when unplug
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+VMMouseUnplug(pointer p)
+{
+ xf86Msg(X_INFO, "VMWARE(0): VMMouseUnplug\n");
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMMousePlug --
+ * This function was called when Xserver load vmmouse module. It will
+ * integrate the module infto the XFree86 loader architecutre.
+ *
+ * Results:
+ * TRUE
+ *
+ * Side effects:
+ * Regular mouse module was loaded as a submodule. In case
+ * absolute pointing device is not available, we can always fall back
+ * to the regular mouse module
+ *
+ *----------------------------------------------------------------------
+ */
+
+static pointer
+VMMousePlug(pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin)
+{
+ static Bool Initialised = FALSE;
+ char *name;
+
+ xf86LoaderReqSymLists(reqSymbols, NULL);
+
+ if (!Initialised) {
+ Initialised = TRUE;
+#ifndef REMOVE_LOADER_CHECK_MODULE_INFO
+ if (xf86LoaderCheckSymbol("xf86AddModuleInfo"))
+#endif
+ xf86AddModuleInfo(&VMMouseInfo, module);
+ }
+
+ xf86Msg(X_INFO, "VMWARE(0): VMMOUSE module was loaded\n");
+ xf86AddInputDriver(&VMMOUSE, module, 0);
+
+ /*
+ * Load the normal mouse module as submodule
+ * If we fail in PreInit later, this allows us to fall back to normal mouse module
+ */
+#ifndef NORMALISE_MODULE_NAME
+ name = xstrdup("mouse");
+#else
+ /* Normalise the module name */
+ name = xf86NormalizeName("mouse");
+#endif
+
+ if (!LoadSubModule(module, name, NULL, NULL, NULL, NULL, errmaj, errmin)) {
+ LoaderErrorMsg(NULL, name, *errmaj, *errmin);
+ }
+ xfree(name);
+
+ return module;
+}
+
+static XF86ModuleVersionInfo VMMouseVersionRec = {
+ "vmmouse",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ VMMOUSE_MAJOR_VERSION, VMMOUSE_MINOR_VERSION, VMMOUSE_PATCHLEVEL,
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature, to be patched into the file by a tool */
+};
+
+/*
+ * The variable contains the necessary information to load and initialize the module
+ */
+XF86ModuleData vmmouseModuleData = {
+ &VMMouseVersionRec,
+ VMMousePlug,
+ VMMouseUnplug
+};
+#endif /* XFree86LOADER */