vmmouse.c revision 9bd41f2c
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 359bd41f2cSmrg * 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. 399bd41f2cSmrg * 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#define NEED_EVENTS 529bd41f2cSmrg#include <X11/X.h> 539bd41f2cSmrg#include <X11/Xproto.h> 549bd41f2cSmrg 559bd41f2cSmrg#include "xf86.h" 569bd41f2cSmrg 579bd41f2cSmrg#ifdef XINPUT 589bd41f2cSmrg#include <X11/extensions/XI.h> 599bd41f2cSmrg#include <X11/extensions/XIproto.h> 609bd41f2cSmrg#include "extnsionst.h" 619bd41f2cSmrg#include "extinit.h" 629bd41f2cSmrg#else 639bd41f2cSmrg#include "inputstr.h" 649bd41f2cSmrg#endif 659bd41f2cSmrg 669bd41f2cSmrg#include "xf86Xinput.h" 679bd41f2cSmrg#include "xf86_OSproc.h" 689bd41f2cSmrg#include "xf86OSmouse.h" 699bd41f2cSmrg#include "compiler.h" 709bd41f2cSmrg 719bd41f2cSmrg#include "xisb.h" 729bd41f2cSmrg#include "mipointer.h" 739bd41f2cSmrg 749bd41f2cSmrg/***************************************************************************** 759bd41f2cSmrg * Local Headers 769bd41f2cSmrg ****************************************************************************/ 779bd41f2cSmrg#include "vmmouse_client.h" 789bd41f2cSmrg 799bd41f2cSmrg/* 809bd41f2cSmrg * This is the only way I know to turn a #define of an integer constant into 819bd41f2cSmrg * a constant string. 829bd41f2cSmrg */ 839bd41f2cSmrg#define VMW_INNERSTRINGIFY(s) #s 849bd41f2cSmrg#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) 859bd41f2cSmrg 869bd41f2cSmrg/* 879bd41f2cSmrg * So that the file compiles unmodified when dropped into an xfree source tree. 889bd41f2cSmrg */ 899bd41f2cSmrg#ifndef XORG_VERSION_CURRENT 909bd41f2cSmrg#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT 919bd41f2cSmrg#endif 929bd41f2cSmrg 939bd41f2cSmrg/* 949bd41f2cSmrg * Version constants 959bd41f2cSmrg */ 969bd41f2cSmrg#define VMMOUSE_MAJOR_VERSION 12 979bd41f2cSmrg#define VMMOUSE_MINOR_VERSION 4 989bd41f2cSmrg#define VMMOUSE_PATCHLEVEL 3 999bd41f2cSmrg#define VMMOUSE_DRIVER_VERSION \ 1009bd41f2cSmrg (VMMOUSE_MAJOR_VERSION * 65536 + VMMOUSE_MINOR_VERSION * 256 + VMMOUSE_PATCHLEVEL) 1019bd41f2cSmrg#define VMMOUSE_DRIVER_VERSION_STRING \ 1029bd41f2cSmrg VMW_STRING(VMMOUSE_MAJOR_VERSION) "." VMW_STRING(VMMOUSE_MINOR_VERSION) \ 1039bd41f2cSmrg "." VMW_STRING(VMMOUSE_PATCHLEVEL) 1049bd41f2cSmrg 1059bd41f2cSmrg/* 1069bd41f2cSmrg * Standard four digit version string expected by VMware Tools installer. 1079bd41f2cSmrg * As the driver's version is only {major, minor, patchlevel}, simply append an 1089bd41f2cSmrg * extra zero for the fourth digit. 1099bd41f2cSmrg */ 1109bd41f2cSmrg#ifdef __GNUC__ 1119bd41f2cSmrgconst char vm_mouse_version[] __attribute__((section(".modinfo"),unused)) = 1129bd41f2cSmrg "version=" VMMOUSE_DRIVER_VERSION_STRING ".0"; 1139bd41f2cSmrg#endif 1149bd41f2cSmrg 1159bd41f2cSmrg 1169bd41f2cSmrg/***************************************************************************** 1179bd41f2cSmrg * static function header 1189bd41f2cSmrg ****************************************************************************/ 1199bd41f2cSmrg#ifdef XFree86LOADER 1209bd41f2cSmrgstatic const OptionInfoRec *VMMouseAvailableOptions(void *unused); 1219bd41f2cSmrg#endif 1229bd41f2cSmrgstatic InputInfoPtr VMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags); 1239bd41f2cSmrgstatic void VMMouseUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 1249bd41f2cSmrgstatic void MouseCommonOptions(InputInfoPtr pInfo); 1259bd41f2cSmrgstatic void GetVMMouseMotionEvent(InputInfoPtr pInfo); 1269bd41f2cSmrgstatic void VMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw); 1279bd41f2cSmrgstatic void VMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy); 1289bd41f2cSmrgstatic Bool VMMouseDeviceControl(DeviceIntPtr device, int mode); 1299bd41f2cSmrgstatic void VMMouseCloseProc(LocalDevicePtr local); 1309bd41f2cSmrgstatic int VMMouseControlProc(LocalDevicePtr local, xDeviceCtl * control); 1319bd41f2cSmrgstatic void VMMouseReadInput(InputInfoPtr pInfo); 1329bd41f2cSmrgstatic int VMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode); 1339bd41f2cSmrgstatic Bool VMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, 1349bd41f2cSmrg int v3, int v4, int v5, int *x, int *y); 1359bd41f2cSmrgstatic void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl); 1369bd41f2cSmrg 1379bd41f2cSmrg/****************************************************************************** 1389bd41f2cSmrg * Definitions 1399bd41f2cSmrg *****************************************************************************/ 1409bd41f2cSmrgtypedef struct { 1419bd41f2cSmrg int screenNum; 1429bd41f2cSmrg Bool vmmouseAvailable; 1439bd41f2cSmrg Bool relative; 1449bd41f2cSmrg} VMMousePrivRec, *VMMousePrivPtr; 1459bd41f2cSmrg 1469bd41f2cSmrgstatic const char *reqSymbols[] = { 1479bd41f2cSmrg "InitPointerDeviceStruct", 1489bd41f2cSmrg "LoaderSymbol", 1499bd41f2cSmrg "LoadSubModule", 1509bd41f2cSmrg "miPointerGetMotionBufferSize", 1519bd41f2cSmrg "miPointerGetMotionEvents", 1529bd41f2cSmrg "screenInfo", 1539bd41f2cSmrg "Xcalloc", 1549bd41f2cSmrg "xf86AddEnabledDevice", 1559bd41f2cSmrg "xf86AddInputDriver", 1569bd41f2cSmrg "xf86AddModuleInfo", 1579bd41f2cSmrg "xf86AllocateInput", 1589bd41f2cSmrg "xf86BlockSIGIO", 1599bd41f2cSmrg "xf86CloseSerial", 1609bd41f2cSmrg "xf86CollectInputOptions", 1619bd41f2cSmrg "xf86ffs", 1629bd41f2cSmrg "xf86FlushInput", 1639bd41f2cSmrg "xf86GetAllowMouseOpenFail", 1649bd41f2cSmrg "xf86GetMotionEvents", 1659bd41f2cSmrg "xf86InitValuatorAxisStruct", 1669bd41f2cSmrg "xf86InitValuatorDefaults", 1679bd41f2cSmrg "xf86LoaderCheckSymbol", 1689bd41f2cSmrg "xf86MotionHistoryAllocate", 1699bd41f2cSmrg "xf86Msg", 1709bd41f2cSmrg "xf86NameCmp", 1719bd41f2cSmrg "xf86OpenSerial", 1729bd41f2cSmrg "xf86OSMouseInit", 1739bd41f2cSmrg "xf86PostButtonEvent", 1749bd41f2cSmrg "xf86PostMotionEvent", 1759bd41f2cSmrg "xf86ProcessCommonOptions", 1769bd41f2cSmrg "xf86RemoveEnabledDevice", 1779bd41f2cSmrg "xf86SetIntOption", 1789bd41f2cSmrg "xf86SetStrOption", 1799bd41f2cSmrg "xf86sprintf", 1809bd41f2cSmrg "xf86sscanf", 1819bd41f2cSmrg "xf86UnblockSIGIO", 1829bd41f2cSmrg "xf86usleep", 1839bd41f2cSmrg "xf86XInputSetScreen", 1849bd41f2cSmrg "Xfree", 1859bd41f2cSmrg "XisbBlockDuration", 1869bd41f2cSmrg "XisbFree", 1879bd41f2cSmrg "XisbNew", 1889bd41f2cSmrg "XisbRead", 1899bd41f2cSmrg "Xstrdup", 1909bd41f2cSmrg NULL 1919bd41f2cSmrg}; 1929bd41f2cSmrg 1939bd41f2cSmrgInputDriverRec VMMOUSE = { 1949bd41f2cSmrg 1, 1959bd41f2cSmrg "vmmouse", 1969bd41f2cSmrg NULL, 1979bd41f2cSmrg VMMousePreInit, 1989bd41f2cSmrg VMMouseUnInit, 1999bd41f2cSmrg NULL, 2009bd41f2cSmrg 0 2019bd41f2cSmrg}; 2029bd41f2cSmrg 2039bd41f2cSmrgtypedef enum { 2049bd41f2cSmrg OPTION_ALWAYS_CORE, 2059bd41f2cSmrg OPTION_SEND_CORE_EVENTS, 2069bd41f2cSmrg OPTION_CORE_POINTER, 2079bd41f2cSmrg OPTION_SEND_DRAG_EVENTS, 2089bd41f2cSmrg OPTION_HISTORY_SIZE, 2099bd41f2cSmrg OPTION_DEVICE, 2109bd41f2cSmrg OPTION_PROTOCOL, 2119bd41f2cSmrg OPTION_BUTTONS, 2129bd41f2cSmrg OPTION_EMULATE_3_BUTTONS, 2139bd41f2cSmrg OPTION_EMULATE_3_TIMEOUT, 2149bd41f2cSmrg OPTION_CHORD_MIDDLE, 2159bd41f2cSmrg OPTION_FLIP_XY, 2169bd41f2cSmrg OPTION_INV_X, 2179bd41f2cSmrg OPTION_INV_Y, 2189bd41f2cSmrg OPTION_ANGLE_OFFSET, 2199bd41f2cSmrg OPTION_Z_AXIS_MAPPING, 2209bd41f2cSmrg OPTION_SAMPLE_RATE, 2219bd41f2cSmrg OPTION_RESOLUTION, 2229bd41f2cSmrg OPTION_EMULATE_WHEEL, 2239bd41f2cSmrg OPTION_EMU_WHEEL_BUTTON, 2249bd41f2cSmrg OPTION_EMU_WHEEL_INERTIA, 2259bd41f2cSmrg OPTION_X_AXIS_MAPPING, 2269bd41f2cSmrg OPTION_Y_AXIS_MAPPING, 2279bd41f2cSmrg OPTION_AUTO_SOFT, 2289bd41f2cSmrg OPTION_DRAGLOCKBUTTONS 2299bd41f2cSmrg} MouseOpts; 2309bd41f2cSmrg 2319bd41f2cSmrg/* 2329bd41f2cSmrg * Define the acceptable mouse options 2339bd41f2cSmrg * Currently not all of those options are supported 2349bd41f2cSmrg * 2359bd41f2cSmrg */ 2369bd41f2cSmrgstatic const OptionInfoRec mouseOptions[] = { 2379bd41f2cSmrg { OPTION_ALWAYS_CORE, "AlwaysCore", OPTV_BOOLEAN, {0}, FALSE }, 2389bd41f2cSmrg { OPTION_SEND_CORE_EVENTS, "SendCoreEvents", OPTV_BOOLEAN, {0}, FALSE }, 2399bd41f2cSmrg { OPTION_CORE_POINTER, "CorePointer", OPTV_BOOLEAN, {0}, FALSE }, 2409bd41f2cSmrg { OPTION_SEND_DRAG_EVENTS, "SendDragEvents", OPTV_BOOLEAN, {0}, FALSE }, 2419bd41f2cSmrg { OPTION_HISTORY_SIZE, "HistorySize", OPTV_INTEGER, {0}, FALSE }, 2429bd41f2cSmrg { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE }, 2439bd41f2cSmrg { OPTION_PROTOCOL, "Protocol", OPTV_STRING, {0}, FALSE }, 2449bd41f2cSmrg { OPTION_BUTTONS, "Buttons", OPTV_INTEGER, {0}, FALSE }, 2459bd41f2cSmrg { OPTION_EMULATE_3_BUTTONS, "Emulate3Buttons",OPTV_BOOLEAN, {0}, FALSE }, 2469bd41f2cSmrg { OPTION_EMULATE_3_TIMEOUT, "Emulate3Timeout",OPTV_INTEGER, {0}, FALSE }, 2479bd41f2cSmrg { OPTION_CHORD_MIDDLE, "ChordMiddle", OPTV_BOOLEAN, {0}, FALSE }, 2489bd41f2cSmrg { OPTION_FLIP_XY, "FlipXY", OPTV_BOOLEAN, {0}, FALSE }, 2499bd41f2cSmrg { OPTION_INV_X, "InvX", OPTV_BOOLEAN, {0}, FALSE }, 2509bd41f2cSmrg { OPTION_INV_Y, "InvY", OPTV_BOOLEAN, {0}, FALSE }, 2519bd41f2cSmrg { OPTION_ANGLE_OFFSET, "AngleOffset", OPTV_INTEGER, {0}, FALSE }, 2529bd41f2cSmrg { OPTION_Z_AXIS_MAPPING, "ZAxisMapping", OPTV_STRING, {0}, FALSE }, 2539bd41f2cSmrg { OPTION_SAMPLE_RATE, "SampleRate", OPTV_INTEGER, {0}, FALSE }, 2549bd41f2cSmrg { OPTION_RESOLUTION, "Resolution", OPTV_INTEGER, {0}, FALSE }, 2559bd41f2cSmrg { OPTION_EMULATE_WHEEL, "EmulateWheel", OPTV_BOOLEAN, {0}, FALSE }, 2569bd41f2cSmrg { OPTION_EMU_WHEEL_BUTTON, "EmulateWheelButton", OPTV_INTEGER, {0}, FALSE }, 2579bd41f2cSmrg { OPTION_EMU_WHEEL_INERTIA, "EmulateWheelInertia", OPTV_INTEGER, {0}, FALSE }, 2589bd41f2cSmrg { OPTION_X_AXIS_MAPPING, "XAxisMapping", OPTV_STRING, {0}, FALSE }, 2599bd41f2cSmrg { OPTION_Y_AXIS_MAPPING, "YAxisMapping", OPTV_STRING, {0}, FALSE }, 2609bd41f2cSmrg { OPTION_AUTO_SOFT, "AutoSoft", OPTV_BOOLEAN, {0}, FALSE }, 2619bd41f2cSmrg { OPTION_DRAGLOCKBUTTONS, "DragLockButtons",OPTV_STRING, {0}, FALSE }, 2629bd41f2cSmrg { -1, NULL, OPTV_NONE, {0}, FALSE } 2639bd41f2cSmrg}; 2649bd41f2cSmrg 2659bd41f2cSmrgstatic char reverseMap[32] = { 0, 4, 2, 6, 1, 5, 3, 7, 2669bd41f2cSmrg 8, 12, 10, 14, 9, 13, 11, 15, 2679bd41f2cSmrg 16, 20, 18, 22, 17, 21, 19, 23, 2689bd41f2cSmrg 24, 28, 26, 30, 25, 29, 27, 31}; 2699bd41f2cSmrg 2709bd41f2cSmrg#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f]) 2719bd41f2cSmrg 2729bd41f2cSmrg 2739bd41f2cSmrg/* 2749bd41f2cSmrg *---------------------------------------------------------------------- 2759bd41f2cSmrg * 2769bd41f2cSmrg * VMMousePreInit -- 2779bd41f2cSmrg * This function collect all the information that is necessary to 2789bd41f2cSmrg * determine the configuration of the hardware and to prepare the 2799bd41f2cSmrg * device for being used 2809bd41f2cSmrg * 2819bd41f2cSmrg * Results: 2829bd41f2cSmrg * An InputInfoPtr object which points to vmmouse's information, 2839bd41f2cSmrg * if the absolute pointing device available 2849bd41f2cSmrg * Otherwise, an InputInfoPtr of regular mouse 2859bd41f2cSmrg * 2869bd41f2cSmrg * Side effects: 2879bd41f2cSmrg * VMMouse was initialized with necessary information 2889bd41f2cSmrg * 2899bd41f2cSmrg *---------------------------------------------------------------------- 2909bd41f2cSmrg */ 2919bd41f2cSmrg 2929bd41f2cSmrgstatic InputInfoPtr 2939bd41f2cSmrgVMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags) 2949bd41f2cSmrg{ 2959bd41f2cSmrg InputInfoPtr pInfo; 2969bd41f2cSmrg MouseDevPtr pMse; 2979bd41f2cSmrg VMMousePrivPtr mPriv; 2989bd41f2cSmrg OSMouseInfoPtr osInfo = NULL; 2999bd41f2cSmrg 3009bd41f2cSmrg /* 3019bd41f2cSmrg * let Xserver init the mouse first 3029bd41f2cSmrg */ 3039bd41f2cSmrg osInfo = xf86OSMouseInit(0); 3049bd41f2cSmrg if (!osInfo) 3059bd41f2cSmrg return FALSE; 3069bd41f2cSmrg 3079bd41f2cSmrg mPriv = xcalloc (1, sizeof (VMMousePrivRec)); 3089bd41f2cSmrg 3099bd41f2cSmrg 3109bd41f2cSmrg if (!mPriv) { 3119bd41f2cSmrg return NULL; 3129bd41f2cSmrg } 3139bd41f2cSmrg /* 3149bd41f2cSmrg * try to enable vmmouse here 3159bd41f2cSmrg */ 3169bd41f2cSmrg if (!VMMouseClient_Enable()) { 3179bd41f2cSmrg /* 3189bd41f2cSmrg * vmmouse failed 3199bd41f2cSmrg * Fall back to normal mouse module 3209bd41f2cSmrg */ 3219bd41f2cSmrg InputDriverRec *passthruMouse; 3229bd41f2cSmrg xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n"); 3239bd41f2cSmrg mPriv->vmmouseAvailable = FALSE; 3249bd41f2cSmrg passthruMouse = (InputDriverRec *)LoaderSymbol("MOUSE"); 3259bd41f2cSmrg xfree(mPriv); 3269bd41f2cSmrg if(passthruMouse != NULL){ 3279bd41f2cSmrg return (passthruMouse->PreInit)(drv, dev, flags); 3289bd41f2cSmrg } else { 3299bd41f2cSmrg return NULL; 3309bd41f2cSmrg } 3319bd41f2cSmrg 3329bd41f2cSmrg } else { 3339bd41f2cSmrg /* 3349bd41f2cSmrg * vmmouse is available 3359bd41f2cSmrg */ 3369bd41f2cSmrg mPriv->vmmouseAvailable = TRUE; 3379bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): vmmouse is available\n"); 3389bd41f2cSmrg /* 3399bd41f2cSmrg * Disable the absolute pointing device for now 3409bd41f2cSmrg * It will be enabled during DEVICE_ON phase 3419bd41f2cSmrg */ 3429bd41f2cSmrg VMMouseClient_Disable(); 3439bd41f2cSmrg } 3449bd41f2cSmrg 3459bd41f2cSmrg if (!(pInfo = xf86AllocateInput(drv, 0))) { 3469bd41f2cSmrg xfree(mPriv); 3479bd41f2cSmrg return NULL; 3489bd41f2cSmrg } 3499bd41f2cSmrg 3509bd41f2cSmrg /* Settup the pInfo */ 3519bd41f2cSmrg pInfo->name = dev->identifier; 3529bd41f2cSmrg pInfo->type_name = XI_MOUSE; 3539bd41f2cSmrg pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; 3549bd41f2cSmrg pInfo->device_control = VMMouseDeviceControl; 3559bd41f2cSmrg pInfo->read_input = VMMouseReadInput; 3569bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 3579bd41f2cSmrg pInfo->motion_history_proc = xf86GetMotionEvents; 3589bd41f2cSmrg#endif 3599bd41f2cSmrg pInfo->control_proc = VMMouseControlProc; 3609bd41f2cSmrg pInfo->close_proc = VMMouseCloseProc; 3619bd41f2cSmrg pInfo->switch_mode = VMMouseSwitchMode; 3629bd41f2cSmrg pInfo->conversion_proc = VMMouseConvertProc; 3639bd41f2cSmrg pInfo->reverse_conversion_proc = NULL; 3649bd41f2cSmrg pInfo->fd = -1; 3659bd41f2cSmrg pInfo->dev = NULL; 3669bd41f2cSmrg pInfo->private_flags = 0; 3679bd41f2cSmrg pInfo->always_core_feedback = 0; 3689bd41f2cSmrg pInfo->conf_idev = dev; 3699bd41f2cSmrg 3709bd41f2cSmrg /* Allocate the MouseDevRec and initialise it. */ 3719bd41f2cSmrg if (!(pMse = xcalloc(sizeof(MouseDevRec), 1))) { 3729bd41f2cSmrg xfree(mPriv); 3739bd41f2cSmrg return pInfo; 3749bd41f2cSmrg } 3759bd41f2cSmrg 3769bd41f2cSmrg pInfo->private = pMse; 3779bd41f2cSmrg pMse->Ctrl = MouseCtrl; 3789bd41f2cSmrg pMse->PostEvent = VMMousePostEvent; 3799bd41f2cSmrg pMse->CommonOptions = MouseCommonOptions; 3809bd41f2cSmrg pMse->mousePriv = mPriv; 3819bd41f2cSmrg 3829bd41f2cSmrg 3839bd41f2cSmrg /* Collect the options, and process the common options. */ 3849bd41f2cSmrg xf86CollectInputOptions(pInfo, NULL, NULL); 3859bd41f2cSmrg xf86ProcessCommonOptions(pInfo, pInfo->options); 3869bd41f2cSmrg 3879bd41f2cSmrg /* Check if the device can be opened. */ 3889bd41f2cSmrg pInfo->fd = xf86OpenSerial(pInfo->options); 3899bd41f2cSmrg if (pInfo->fd == -1) { 3909bd41f2cSmrg if (xf86GetAllowMouseOpenFail()) 3919bd41f2cSmrg xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 3929bd41f2cSmrg else { 3939bd41f2cSmrg xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); 3949bd41f2cSmrg if (pMse->mousePriv) 3959bd41f2cSmrg xfree(pMse->mousePriv); 3969bd41f2cSmrg xfree(pMse); 3979bd41f2cSmrg pInfo->private = NULL; 3989bd41f2cSmrg return pInfo; 3999bd41f2cSmrg } 4009bd41f2cSmrg } 4019bd41f2cSmrg xf86CloseSerial(pInfo->fd); 4029bd41f2cSmrg pInfo->fd = -1; 4039bd41f2cSmrg 4049bd41f2cSmrg /* Process the options */ 4059bd41f2cSmrg pMse->CommonOptions(pInfo); 4069bd41f2cSmrg 4079bd41f2cSmrg /* set up the current screen num */ 4089bd41f2cSmrg mPriv->screenNum = xf86SetIntOption(pInfo->options, "ScreenNumber", 0); 4099bd41f2cSmrg 4109bd41f2cSmrg pInfo->flags |= XI86_CONFIGURED; 4119bd41f2cSmrg return pInfo; 4129bd41f2cSmrg} 4139bd41f2cSmrg 4149bd41f2cSmrg#ifdef XFree86LOADER 4159bd41f2cSmrgstatic const OptionInfoRec * 4169bd41f2cSmrgVMMouseAvailableOptions(void *unused) 4179bd41f2cSmrg{ 4189bd41f2cSmrg return (mouseOptions); 4199bd41f2cSmrg} 4209bd41f2cSmrg#endif 4219bd41f2cSmrg 4229bd41f2cSmrg 4239bd41f2cSmrg/* 4249bd41f2cSmrg *---------------------------------------------------------------------- 4259bd41f2cSmrg * 4269bd41f2cSmrg * MouseCtrl -- 4279bd41f2cSmrg * Alter the control paramters for the mouse. 4289bd41f2cSmrg * 4299bd41f2cSmrg * Results: 4309bd41f2cSmrg * None 4319bd41f2cSmrg * 4329bd41f2cSmrg * Side effects: 4339bd41f2cSmrg * None 4349bd41f2cSmrg * 4359bd41f2cSmrg *---------------------------------------------------------------------- 4369bd41f2cSmrg */ 4379bd41f2cSmrg 4389bd41f2cSmrgstatic void 4399bd41f2cSmrgMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl) 4409bd41f2cSmrg{ 4419bd41f2cSmrg InputInfoPtr pInfo; 4429bd41f2cSmrg MouseDevPtr pMse; 4439bd41f2cSmrg 4449bd41f2cSmrg pInfo = device->public.devicePrivate; 4459bd41f2cSmrg pMse = pInfo->private; 4469bd41f2cSmrg 4479bd41f2cSmrg#ifdef EXTMOUSEDEBUG 4489bd41f2cSmrg xf86Msg(X_INFO, "VMMOUSE(0): MouseCtrl pMse=%p\n", pMse); 4499bd41f2cSmrg#endif 4509bd41f2cSmrg 4519bd41f2cSmrg pMse->num = ctrl->num; 4529bd41f2cSmrg pMse->den = ctrl->den; 4539bd41f2cSmrg pMse->threshold = ctrl->threshold; 4549bd41f2cSmrg} 4559bd41f2cSmrg 4569bd41f2cSmrg 4579bd41f2cSmrg/* 4589bd41f2cSmrg *---------------------------------------------------------------------- 4599bd41f2cSmrg * 4609bd41f2cSmrg * VMMouseDoPostEvent -- 4619bd41f2cSmrg * Post the mouse button event and mouse motion event to Xserver 4629bd41f2cSmrg * 4639bd41f2cSmrg * Results: 4649bd41f2cSmrg * None 4659bd41f2cSmrg * 4669bd41f2cSmrg * Side effects: 4679bd41f2cSmrg * Mouse location and button status was updated 4689bd41f2cSmrg * 4699bd41f2cSmrg *---------------------------------------------------------------------- 4709bd41f2cSmrg */ 4719bd41f2cSmrg 4729bd41f2cSmrgstatic void 4739bd41f2cSmrgVMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy) 4749bd41f2cSmrg{ 4759bd41f2cSmrg MouseDevPtr pMse; 4769bd41f2cSmrg VMMousePrivPtr mPriv; 4779bd41f2cSmrg int truebuttons; 4789bd41f2cSmrg int id, change; 4799bd41f2cSmrg 4809bd41f2cSmrg pMse = pInfo->private; 4819bd41f2cSmrg mPriv = (VMMousePrivPtr)pMse->mousePriv; 4829bd41f2cSmrg 4839bd41f2cSmrg /* 4849bd41f2cSmrg * The following truebuttons/reverseBits and lastButtons are 4859bd41f2cSmrg * used to compare the current buttons and the previous buttons 4869bd41f2cSmrg * to find the button changes during two mouse events 4879bd41f2cSmrg */ 4889bd41f2cSmrg truebuttons = buttons; 4899bd41f2cSmrg 4909bd41f2cSmrg buttons = reverseBits(reverseMap, buttons); 4919bd41f2cSmrg 4929bd41f2cSmrg if (dx || dy) { 4939bd41f2cSmrg 4949bd41f2cSmrg /* 4959bd41f2cSmrg * The Xserver no longer calls an input device's conversion_proc 4969bd41f2cSmrg * to convert x and y coordinates from device to screen space. 4979bd41f2cSmrg */ 4989bd41f2cSmrg VMMouseConvertProc(pInfo, 0, 2, dx, dy, 0, 0, 0, 0, &dx, &dy); 4999bd41f2cSmrg xf86PostMotionEvent(pInfo->dev, !mPriv->relative, 0, 2, dx, dy); 5009bd41f2cSmrg } 5019bd41f2cSmrg 5029bd41f2cSmrg if (truebuttons != pMse->lastButtons) { 5039bd41f2cSmrg change = buttons ^ reverseBits(reverseMap, pMse->lastButtons); 5049bd41f2cSmrg while (change) { 5059bd41f2cSmrg id = ffs(change); 5069bd41f2cSmrg change &= ~(1 << (id - 1)); 5079bd41f2cSmrg xf86PostButtonEvent(pInfo->dev, 0, id, 5089bd41f2cSmrg (buttons & (1 << (id - 1))), 0, 0); 5099bd41f2cSmrg } 5109bd41f2cSmrg pMse->lastButtons = truebuttons; 5119bd41f2cSmrg } 5129bd41f2cSmrg} 5139bd41f2cSmrg 5149bd41f2cSmrg 5159bd41f2cSmrg/* 5169bd41f2cSmrg *---------------------------------------------------------------------- 5179bd41f2cSmrg * 5189bd41f2cSmrg * VMMousePostEvent -- 5199bd41f2cSmrg * Prepare the mouse status according to the Z axis mapping 5209bd41f2cSmrg * before we post the event to Xserver 5219bd41f2cSmrg * 5229bd41f2cSmrg * Results: 5239bd41f2cSmrg * None 5249bd41f2cSmrg * 5259bd41f2cSmrg * Side effects: 5269bd41f2cSmrg * Buttons was updated according to Z axis mapping 5279bd41f2cSmrg * 5289bd41f2cSmrg *---------------------------------------------------------------------- 5299bd41f2cSmrg */ 5309bd41f2cSmrg 5319bd41f2cSmrgstatic void 5329bd41f2cSmrgVMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw) 5339bd41f2cSmrg{ 5349bd41f2cSmrg MouseDevPtr pMse; 5359bd41f2cSmrg int zbutton = 0; 5369bd41f2cSmrg VMMousePrivPtr mPriv; 5379bd41f2cSmrg 5389bd41f2cSmrg pMse = pInfo->private; 5399bd41f2cSmrg mPriv = (VMMousePrivPtr)pMse->mousePriv; 5409bd41f2cSmrg /* Map the Z axis movement. */ 5419bd41f2cSmrg /* XXX Could this go in the conversion_proc? */ 5429bd41f2cSmrg switch (pMse->negativeZ) { 5439bd41f2cSmrg case MSE_NOZMAP: /* do nothing */ 5449bd41f2cSmrg break; 5459bd41f2cSmrg case MSE_MAPTOX: 5469bd41f2cSmrg if (dz != 0) { 5479bd41f2cSmrg if(mPriv->relative) 5489bd41f2cSmrg dx = dz; 5499bd41f2cSmrg else 5509bd41f2cSmrg dx += dz; 5519bd41f2cSmrg dz = 0; 5529bd41f2cSmrg } 5539bd41f2cSmrg break; 5549bd41f2cSmrg case MSE_MAPTOY: 5559bd41f2cSmrg if (dz != 0) { 5569bd41f2cSmrg if(mPriv->relative) 5579bd41f2cSmrg dy = dz; 5589bd41f2cSmrg else 5599bd41f2cSmrg dy += dz; 5609bd41f2cSmrg dz = 0; 5619bd41f2cSmrg } 5629bd41f2cSmrg break; 5639bd41f2cSmrg default: /* buttons */ 5649bd41f2cSmrg buttons &= ~(pMse->negativeZ | pMse->positiveZ 5659bd41f2cSmrg | pMse->negativeW | pMse->positiveW); 5669bd41f2cSmrg if (dw < 0 || dz < -1) { 5679bd41f2cSmrg zbutton = pMse->negativeW; 5689bd41f2cSmrg } 5699bd41f2cSmrg else if (dz < 0) { 5709bd41f2cSmrg zbutton = pMse->negativeZ; 5719bd41f2cSmrg } 5729bd41f2cSmrg else if (dw > 0 || dz > 1) { 5739bd41f2cSmrg zbutton = pMse->positiveW; 5749bd41f2cSmrg } 5759bd41f2cSmrg else if (dz > 0) { 5769bd41f2cSmrg zbutton = pMse->positiveZ; 5779bd41f2cSmrg } 5789bd41f2cSmrg buttons |= zbutton; 5799bd41f2cSmrg dz = 0; 5809bd41f2cSmrg break; 5819bd41f2cSmrg } 5829bd41f2cSmrg 5839bd41f2cSmrg VMMouseDoPostEvent(pInfo, buttons, dx, dy); 5849bd41f2cSmrg 5859bd41f2cSmrg /* 5869bd41f2cSmrg * If dz has been mapped to a button `down' event, we need to cook up 5879bd41f2cSmrg * a corresponding button `up' event. 5889bd41f2cSmrg */ 5899bd41f2cSmrg if (zbutton) { 5909bd41f2cSmrg buttons &= ~zbutton; 5919bd41f2cSmrg if(mPriv->relative) 5929bd41f2cSmrg VMMouseDoPostEvent(pInfo, buttons, 0, 0); 5939bd41f2cSmrg else 5949bd41f2cSmrg VMMouseDoPostEvent(pInfo, buttons, dx, dy); 5959bd41f2cSmrg } 5969bd41f2cSmrg} 5979bd41f2cSmrg 5989bd41f2cSmrg 5999bd41f2cSmrg/* 6009bd41f2cSmrg *---------------------------------------------------------------------- 6019bd41f2cSmrg * 6029bd41f2cSmrg * FlushButtons -- 6039bd41f2cSmrg * 6049bd41f2cSmrg * FlushButtons -- send button up events for sanity. It is called 6059bd41f2cSmrg * during DEVICE_ON in VMMouseDeviceControl 6069bd41f2cSmrg * 6079bd41f2cSmrg * Results: 6089bd41f2cSmrg * None 6099bd41f2cSmrg * 6109bd41f2cSmrg * Side effects: 6119bd41f2cSmrg * None 6129bd41f2cSmrg * 6139bd41f2cSmrg *---------------------------------------------------------------------- 6149bd41f2cSmrg */ 6159bd41f2cSmrg 6169bd41f2cSmrgstatic void 6179bd41f2cSmrgFlushButtons(MouseDevPtr pMse) 6189bd41f2cSmrg{ 6199bd41f2cSmrg 6209bd41f2cSmrg /* If no button down is pending xf86PostButtonEvent() 6219bd41f2cSmrg * will discard them. So we are on the safe side. */ 6229bd41f2cSmrg 6239bd41f2cSmrg int i, blocked; 6249bd41f2cSmrg 6259bd41f2cSmrg pMse->lastButtons = 0; 6269bd41f2cSmrg 6279bd41f2cSmrg blocked = xf86BlockSIGIO (); 6289bd41f2cSmrg for (i = 1; i <= 5; i++) 6299bd41f2cSmrg xf86PostButtonEvent(pMse->device,0,i,0,0,0); 6309bd41f2cSmrg xf86UnblockSIGIO (blocked); 6319bd41f2cSmrg} 6329bd41f2cSmrg 6339bd41f2cSmrg 6349bd41f2cSmrg/* 6359bd41f2cSmrg *---------------------------------------------------------------------- 6369bd41f2cSmrg * 6379bd41f2cSmrg * MouseCommonOptions -- 6389bd41f2cSmrg * Process acceptable mouse options. Currently we only process 6399bd41f2cSmrg * "Buttons" and "ZAxisMapping" options. 6409bd41f2cSmrg * More options can be added later on 6419bd41f2cSmrg * 6429bd41f2cSmrg * Results: 6439bd41f2cSmrg * None 6449bd41f2cSmrg * 6459bd41f2cSmrg * Side effects: 6469bd41f2cSmrg * The buttons was setup according to the options 6479bd41f2cSmrg * 6489bd41f2cSmrg *---------------------------------------------------------------------- 6499bd41f2cSmrg */ 6509bd41f2cSmrg 6519bd41f2cSmrgstatic void 6529bd41f2cSmrgMouseCommonOptions(InputInfoPtr pInfo) 6539bd41f2cSmrg{ 6549bd41f2cSmrg MouseDevPtr pMse; 6559bd41f2cSmrg MessageType from = X_DEFAULT; 6569bd41f2cSmrg char *s; 6579bd41f2cSmrg int origButtons; 6589bd41f2cSmrg 6599bd41f2cSmrg pMse = pInfo->private; 6609bd41f2cSmrg 6619bd41f2cSmrg pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0); 6629bd41f2cSmrg from = X_CONFIG; 6639bd41f2cSmrg if (!pMse->buttons) { 6649bd41f2cSmrg pMse->buttons = MSE_DFLTBUTTONS; 6659bd41f2cSmrg from = X_DEFAULT; 6669bd41f2cSmrg } 6679bd41f2cSmrg origButtons = pMse->buttons; 6689bd41f2cSmrg 6699bd41f2cSmrg /* 6709bd41f2cSmrg * "emulate3Buttons" and "Drag Lock" is not supported 6719bd41f2cSmrg */ 6729bd41f2cSmrg 6739bd41f2cSmrg /* 6749bd41f2cSmrg * Process option for ZAxisMapping 6759bd41f2cSmrg */ 6769bd41f2cSmrg s = xf86SetStrOption(pInfo->options, "ZAxisMapping", NULL); 6779bd41f2cSmrg if (s) { 6789bd41f2cSmrg int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 6799bd41f2cSmrg char *msg = NULL; 6809bd41f2cSmrg 6819bd41f2cSmrg if (!xf86NameCmp(s, "x")) { 6829bd41f2cSmrg pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX; 6839bd41f2cSmrg pMse->negativeW = pMse->positiveW = MSE_MAPTOX; 6849bd41f2cSmrg msg = xstrdup("X axis"); 6859bd41f2cSmrg } else if (!xf86NameCmp(s, "y")) { 6869bd41f2cSmrg pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY; 6879bd41f2cSmrg pMse->negativeW = pMse->positiveW = MSE_MAPTOY; 6889bd41f2cSmrg msg = xstrdup("Y axis"); 6899bd41f2cSmrg } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 && 6909bd41f2cSmrg b1 > 0 && b1 <= MSE_MAXBUTTONS && 6919bd41f2cSmrg b2 > 0 && b2 <= MSE_MAXBUTTONS) { 6929bd41f2cSmrg msg = xstrdup("buttons XX and YY"); 6939bd41f2cSmrg if (msg) 6949bd41f2cSmrg sprintf(msg, "buttons %d and %d", b1, b2); 6959bd41f2cSmrg pMse->negativeZ = pMse->negativeW = 1 << (b1-1); 6969bd41f2cSmrg pMse->positiveZ = pMse->positiveW = 1 << (b2-1); 6979bd41f2cSmrg if (b1 > pMse->buttons) pMse->buttons = b1; 6989bd41f2cSmrg if (b2 > pMse->buttons) pMse->buttons = b2; 6999bd41f2cSmrg 7009bd41f2cSmrg /* 7019bd41f2cSmrg * Option "ZAxisMapping" "N1 N2 N3 N4" not supported 7029bd41f2cSmrg */ 7039bd41f2cSmrg pMse->negativeW = pMse->positiveW = MSE_NOZMAP; 7049bd41f2cSmrg } else { 7059bd41f2cSmrg pMse->negativeZ = pMse->positiveZ = MSE_NOZMAP; 7069bd41f2cSmrg pMse->negativeW = pMse->positiveW = MSE_NOZMAP; 7079bd41f2cSmrg } 7089bd41f2cSmrg if (msg) { 7099bd41f2cSmrg xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg); 7109bd41f2cSmrg xfree(msg); 7119bd41f2cSmrg } else { 7129bd41f2cSmrg xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n", 7139bd41f2cSmrg pInfo->name, s); 7149bd41f2cSmrg } 7159bd41f2cSmrg } 7169bd41f2cSmrg 7179bd41f2cSmrg /* 7189bd41f2cSmrg * Emulatewheel is not supported 7199bd41f2cSmrg */ 7209bd41f2cSmrg if (origButtons != pMse->buttons) 7219bd41f2cSmrg from = X_CONFIG; 7229bd41f2cSmrg 7239bd41f2cSmrg} 7249bd41f2cSmrg 7259bd41f2cSmrg 7269bd41f2cSmrg/* 7279bd41f2cSmrg *---------------------------------------------------------------------- 7289bd41f2cSmrg * 7299bd41f2cSmrg * VMMouseUnInit -- 7309bd41f2cSmrg * This function was supposed to be called by Xserver to do Un-Init. 7319bd41f2cSmrg * But it was unused now 7329bd41f2cSmrg * 7339bd41f2cSmrg * Results: 7349bd41f2cSmrg * None 7359bd41f2cSmrg * 7369bd41f2cSmrg * Side effects: 7379bd41f2cSmrg * None 7389bd41f2cSmrg * 7399bd41f2cSmrg *---------------------------------------------------------------------- 7409bd41f2cSmrg */ 7419bd41f2cSmrg 7429bd41f2cSmrgstatic void 7439bd41f2cSmrgVMMouseUnInit(InputDriverPtr drv, LocalDevicePtr local, int flags) 7449bd41f2cSmrg{ 7459bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMouseUnInit\n"); 7469bd41f2cSmrg} 7479bd41f2cSmrg 7489bd41f2cSmrg 7499bd41f2cSmrg/* 7509bd41f2cSmrg *---------------------------------------------------------------------- 7519bd41f2cSmrg * 7529bd41f2cSmrg * VMMouseDeviceControl -- 7539bd41f2cSmrg * This function was called by Xserver during DEVICE_INIT, DEVICE_ON, 7549bd41f2cSmrg * DEVICE_OFF and DEVICE_CLOSE phase 7559bd41f2cSmrg * 7569bd41f2cSmrg * Results: 7579bd41f2cSmrg * TRUE, if sucessful 7589bd41f2cSmrg * FALSE, if failed 7599bd41f2cSmrg * 7609bd41f2cSmrg * Side effects: 7619bd41f2cSmrg * Absolute pointing device is enabled during DEVICE_ON 7629bd41f2cSmrg * Absolute pointing device is disabled during DEVICE_OFF 7639bd41f2cSmrg * and DEVICE_CLOSE 7649bd41f2cSmrg * 7659bd41f2cSmrg *---------------------------------------------------------------------- 7669bd41f2cSmrg */ 7679bd41f2cSmrg 7689bd41f2cSmrgstatic Bool 7699bd41f2cSmrgVMMouseDeviceControl(DeviceIntPtr device, int mode) 7709bd41f2cSmrg{ 7719bd41f2cSmrg InputInfoPtr pInfo; 7729bd41f2cSmrg MouseDevPtr pMse; 7739bd41f2cSmrg VMMousePrivPtr mPriv; 7749bd41f2cSmrg unsigned char map[MSE_MAXBUTTONS + 1]; 7759bd41f2cSmrg int i; 7769bd41f2cSmrg 7779bd41f2cSmrg pInfo = device->public.devicePrivate; 7789bd41f2cSmrg pMse = pInfo->private; 7799bd41f2cSmrg pMse->device = device; 7809bd41f2cSmrg mPriv = (VMMousePrivPtr)pMse->mousePriv; 7819bd41f2cSmrg 7829bd41f2cSmrg switch (mode){ 7839bd41f2cSmrg case DEVICE_INIT: 7849bd41f2cSmrg device->public.on = FALSE; 7859bd41f2cSmrg /* 7869bd41f2cSmrg * [KAZU-241097] We don't know exactly how many buttons the 7879bd41f2cSmrg * device has, so setup the map with the maximum number. 7889bd41f2cSmrg */ 7899bd41f2cSmrg for (i = 0; i < MSE_MAXBUTTONS; i++) 7909bd41f2cSmrg map[i + 1] = i + 1; 7919bd41f2cSmrg 7929bd41f2cSmrg InitPointerDeviceStruct((DevicePtr)device, map, 7939bd41f2cSmrg min(pMse->buttons, MSE_MAXBUTTONS), 7949bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 7959bd41f2cSmrg miPointerGetMotionEvents, 7969bd41f2cSmrg#else 7979bd41f2cSmrg GetMotionHistory, 7989bd41f2cSmrg#endif 7999bd41f2cSmrg pMse->Ctrl, 8009bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 8019bd41f2cSmrg miPointerGetMotionBufferSize() 8029bd41f2cSmrg#else 8039bd41f2cSmrg GetMotionHistorySize(), 2 8049bd41f2cSmrg#endif 8059bd41f2cSmrg ); 8069bd41f2cSmrg 8079bd41f2cSmrg /* X valuator */ 8089bd41f2cSmrg xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1); 8099bd41f2cSmrg xf86InitValuatorDefaults(device, 0); 8109bd41f2cSmrg /* Y valuator */ 8119bd41f2cSmrg xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1); 8129bd41f2cSmrg xf86InitValuatorDefaults(device, 1); 8139bd41f2cSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 8149bd41f2cSmrg xf86MotionHistoryAllocate(pInfo); 8159bd41f2cSmrg#endif 8169bd41f2cSmrg 8179bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_INIT\n"); 8189bd41f2cSmrg#ifdef EXTMOUSEDEBUG 8199bd41f2cSmrg xf86Msg(X_INFO, "assigning %p atom=%d name=%s\n", device, pInfo->atom, 8209bd41f2cSmrg pInfo->name); 8219bd41f2cSmrg#endif 8229bd41f2cSmrg break; 8239bd41f2cSmrg 8249bd41f2cSmrg case DEVICE_ON: 8259bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_ON\n"); 8269bd41f2cSmrg pInfo->fd = xf86OpenSerial(pInfo->options); 8279bd41f2cSmrg if (pInfo->fd == -1) 8289bd41f2cSmrg xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 8299bd41f2cSmrg else { 8309bd41f2cSmrg pMse->buffer = XisbNew(pInfo->fd, 64); 8319bd41f2cSmrg if (!pMse->buffer) { 8329bd41f2cSmrg xf86CloseSerial(pInfo->fd); 8339bd41f2cSmrg pInfo->fd = -1; 8349bd41f2cSmrg } else { 8359bd41f2cSmrg VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv; 8369bd41f2cSmrg if (mPriv != NULL) { 8379bd41f2cSmrg /* 8389bd41f2cSmrg * enable absolute pointing device here 8399bd41f2cSmrg */ 8409bd41f2cSmrg if (!VMMouseClient_Enable()) { 8419bd41f2cSmrg xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n"); 8429bd41f2cSmrg mPriv->vmmouseAvailable = FALSE; 8439bd41f2cSmrg device->public.on = FALSE; 8449bd41f2cSmrg return FALSE; 8459bd41f2cSmrg } else { 8469bd41f2cSmrg mPriv->vmmouseAvailable = TRUE; 8479bd41f2cSmrg VMMouseClient_RequestAbsolute(); 8489bd41f2cSmrg mPriv->relative = FALSE; 8499bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): vmmouse enabled\n"); 8509bd41f2cSmrg } 8519bd41f2cSmrg } 8529bd41f2cSmrg xf86FlushInput(pInfo->fd); 8539bd41f2cSmrg xf86AddEnabledDevice(pInfo); 8549bd41f2cSmrg } 8559bd41f2cSmrg } 8569bd41f2cSmrg pMse->lastButtons = 0; 8579bd41f2cSmrg device->public.on = TRUE; 8589bd41f2cSmrg FlushButtons(pMse); 8599bd41f2cSmrg break; 8609bd41f2cSmrg case DEVICE_OFF: 8619bd41f2cSmrg case DEVICE_CLOSE: 8629bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_OFF/CLOSE\n"); 8639bd41f2cSmrg 8649bd41f2cSmrg if (pInfo->fd != -1) { 8659bd41f2cSmrg VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv; 8669bd41f2cSmrg if( mPriv->vmmouseAvailable ) { 8679bd41f2cSmrg VMMouseClient_Disable(); 8689bd41f2cSmrg mPriv->vmmouseAvailable = FALSE; 8699bd41f2cSmrg } 8709bd41f2cSmrg 8719bd41f2cSmrg xf86RemoveEnabledDevice(pInfo); 8729bd41f2cSmrg if (pMse->buffer) { 8739bd41f2cSmrg XisbFree(pMse->buffer); 8749bd41f2cSmrg pMse->buffer = NULL; 8759bd41f2cSmrg } 8769bd41f2cSmrg xf86CloseSerial(pInfo->fd); 8779bd41f2cSmrg pInfo->fd = -1; 8789bd41f2cSmrg } 8799bd41f2cSmrg device->public.on = FALSE; 8809bd41f2cSmrg usleep(300000); 8819bd41f2cSmrg break; 8829bd41f2cSmrg 8839bd41f2cSmrg } 8849bd41f2cSmrg 8859bd41f2cSmrg return Success; 8869bd41f2cSmrg} 8879bd41f2cSmrg 8889bd41f2cSmrg 8899bd41f2cSmrg/* 8909bd41f2cSmrg *---------------------------------------------------------------------- 8919bd41f2cSmrg * 8929bd41f2cSmrg * VMMouseReadInput -- 8939bd41f2cSmrg * This function was called by Xserver when there is data available 8949bd41f2cSmrg * in the input device 8959bd41f2cSmrg * 8969bd41f2cSmrg * Results: 8979bd41f2cSmrg * None 8989bd41f2cSmrg * 8999bd41f2cSmrg * Side effects: 9009bd41f2cSmrg * Input data in regular PS/2 fd was cleared 9019bd41f2cSmrg * Real mouse data was read from the absolute pointing device 9029bd41f2cSmrg * and posted to Xserver 9039bd41f2cSmrg * 9049bd41f2cSmrg *---------------------------------------------------------------------- 9059bd41f2cSmrg */ 9069bd41f2cSmrg 9079bd41f2cSmrgstatic void 9089bd41f2cSmrgVMMouseReadInput(InputInfoPtr pInfo) 9099bd41f2cSmrg{ 9109bd41f2cSmrg MouseDevPtr pMse; 9119bd41f2cSmrg VMMousePrivPtr mPriv; 9129bd41f2cSmrg int c; 9139bd41f2cSmrg int len = 0; 9149bd41f2cSmrg 9159bd41f2cSmrg pMse = pInfo->private; 9169bd41f2cSmrg mPriv = pMse->mousePriv; 9179bd41f2cSmrg 9189bd41f2cSmrg /* 9199bd41f2cSmrg * First read the bytes in input device to clear the regular PS/2 fd so 9209bd41f2cSmrg * we don't get called again. 9219bd41f2cSmrg */ 9229bd41f2cSmrg /* 9239bd41f2cSmrg * Set blocking to -1 on the first call because we know there is data to 9249bd41f2cSmrg * read. Xisb automatically clears it after one successful read so that 9259bd41f2cSmrg * succeeding reads are preceeded by a select with a 0 timeout to prevent 9269bd41f2cSmrg * read from blocking indefinitely. 9279bd41f2cSmrg */ 9289bd41f2cSmrg XisbBlockDuration(pMse->buffer, -1); 9299bd41f2cSmrg while ((c = XisbRead(pMse->buffer)) >= 0) { 9309bd41f2cSmrg len++; 9319bd41f2cSmrg /* 9329bd41f2cSmrg * regular PS packet consists of 3 bytes 9339bd41f2cSmrg * We read 3 bytes to drain the PS/2 packet 9349bd41f2cSmrg */ 9359bd41f2cSmrg if(len < 3) continue; 9369bd41f2cSmrg len = 0; 9379bd41f2cSmrg /* 9389bd41f2cSmrg * Now get the real data from absolute pointing device 9399bd41f2cSmrg */ 9409bd41f2cSmrg GetVMMouseMotionEvent(pInfo); 9419bd41f2cSmrg } 9429bd41f2cSmrg /* 9439bd41f2cSmrg * There maybe still vmmouse data available 9449bd41f2cSmrg */ 9459bd41f2cSmrg GetVMMouseMotionEvent(pInfo); 9469bd41f2cSmrg} 9479bd41f2cSmrg 9489bd41f2cSmrg 9499bd41f2cSmrg/* 9509bd41f2cSmrg *---------------------------------------------------------------------- 9519bd41f2cSmrg * 9529bd41f2cSmrg * GetVMMouseMotionEvent -- 9539bd41f2cSmrg * Read all the mouse data available from the absolute 9549bd41f2cSmrg * pointing device and post it to the Xserver 9559bd41f2cSmrg * 9569bd41f2cSmrg * Results: 9579bd41f2cSmrg * None 9589bd41f2cSmrg * 9599bd41f2cSmrg * Side effects: 9609bd41f2cSmrg * Real mouse data was read from the absolute pointing 9619bd41f2cSmrg * device and posted to Xserver 9629bd41f2cSmrg * 9639bd41f2cSmrg *---------------------------------------------------------------------- 9649bd41f2cSmrg */ 9659bd41f2cSmrg 9669bd41f2cSmrgstatic void 9679bd41f2cSmrgGetVMMouseMotionEvent(InputInfoPtr pInfo){ 9689bd41f2cSmrg MouseDevPtr pMse; 9699bd41f2cSmrg int buttons, dx, dy, dz, dw; 9709bd41f2cSmrg VMMOUSE_INPUT_DATA vmmouseInput; 9719bd41f2cSmrg int ps2Buttons = 0; 9729bd41f2cSmrg int numPackets; 9739bd41f2cSmrg 9749bd41f2cSmrg pMse = pInfo->private; 9759bd41f2cSmrg while((numPackets = VMMouseClient_GetInput(&vmmouseInput))){ 9769bd41f2cSmrg if (numPackets == VMMOUSE_ERROR) { 9779bd41f2cSmrg VMMouseClient_Disable(); 9789bd41f2cSmrg VMMouseClient_Enable(); 9799bd41f2cSmrg VMMouseClient_RequestAbsolute(); 9809bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): re-requesting absolute mode after reset\n"); 9819bd41f2cSmrg break; 9829bd41f2cSmrg } 9839bd41f2cSmrg 9849bd41f2cSmrg if(vmmouseInput.Buttons & VMMOUSE_MIDDLE_BUTTON) 9859bd41f2cSmrg ps2Buttons |= 0x04; /* Middle*/ 9869bd41f2cSmrg if(vmmouseInput.Buttons & VMMOUSE_RIGHT_BUTTON) 9879bd41f2cSmrg ps2Buttons |= 0x02; /* Right*/ 9889bd41f2cSmrg if(vmmouseInput.Buttons & VMMOUSE_LEFT_BUTTON) 9899bd41f2cSmrg ps2Buttons |= 0x01; /* Left*/ 9909bd41f2cSmrg 9919bd41f2cSmrg buttons = (ps2Buttons & 0x04) >> 1 | /* Middle */ 9929bd41f2cSmrg (ps2Buttons & 0x02) >> 1 | /* Right */ 9939bd41f2cSmrg (ps2Buttons & 0x01) << 2; /* Left */ 9949bd41f2cSmrg 9959bd41f2cSmrg dx = vmmouseInput.X; 9969bd41f2cSmrg dy = vmmouseInput.Y; 9979bd41f2cSmrg dz = (char)vmmouseInput.Z; 9989bd41f2cSmrg dw = 0; 9999bd41f2cSmrg /* post an event */ 10009bd41f2cSmrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 10019bd41f2cSmrg } 10029bd41f2cSmrg} 10039bd41f2cSmrg 10049bd41f2cSmrg 10059bd41f2cSmrg/* 10069bd41f2cSmrg *---------------------------------------------------------------------- 10079bd41f2cSmrg * 10089bd41f2cSmrg * VMMouseControlProc -- 10099bd41f2cSmrg * This function is unused 10109bd41f2cSmrg * 10119bd41f2cSmrg * Results: 10129bd41f2cSmrg * None 10139bd41f2cSmrg * 10149bd41f2cSmrg * Side effects: 10159bd41f2cSmrg * None 10169bd41f2cSmrg * 10179bd41f2cSmrg *---------------------------------------------------------------------- 10189bd41f2cSmrg */ 10199bd41f2cSmrg 10209bd41f2cSmrgstatic int 10219bd41f2cSmrgVMMouseControlProc(LocalDevicePtr local, xDeviceCtl * control) 10229bd41f2cSmrg{ 10239bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMouseControlProc\n"); 10249bd41f2cSmrg return (Success); 10259bd41f2cSmrg} 10269bd41f2cSmrg 10279bd41f2cSmrg 10289bd41f2cSmrg/* 10299bd41f2cSmrg *---------------------------------------------------------------------- 10309bd41f2cSmrg * 10319bd41f2cSmrg * VMMouseCloseProc -- 10329bd41f2cSmrg * This function is unused 10339bd41f2cSmrg * 10349bd41f2cSmrg * Results: 10359bd41f2cSmrg * None 10369bd41f2cSmrg * 10379bd41f2cSmrg * Side effects: 10389bd41f2cSmrg * None 10399bd41f2cSmrg * 10409bd41f2cSmrg *---------------------------------------------------------------------- 10419bd41f2cSmrg */ 10429bd41f2cSmrg 10439bd41f2cSmrgstatic void 10449bd41f2cSmrgVMMouseCloseProc(LocalDevicePtr local) 10459bd41f2cSmrg{ 10469bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMouseCloseProc\n"); 10479bd41f2cSmrg} 10489bd41f2cSmrg 10499bd41f2cSmrg 10509bd41f2cSmrg/* 10519bd41f2cSmrg *---------------------------------------------------------------------- 10529bd41f2cSmrg * 10539bd41f2cSmrg * VMMouseSwitchProc -- 10549bd41f2cSmrg * This function is unused 10559bd41f2cSmrg * 10569bd41f2cSmrg * Results: 10579bd41f2cSmrg * None 10589bd41f2cSmrg * 10599bd41f2cSmrg * Side effects: 10609bd41f2cSmrg * None 10619bd41f2cSmrg * 10629bd41f2cSmrg *---------------------------------------------------------------------- 10639bd41f2cSmrg */ 10649bd41f2cSmrg 10659bd41f2cSmrgstatic int 10669bd41f2cSmrgVMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode) 10679bd41f2cSmrg{ 10689bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMouseSwitchMode\n"); 10699bd41f2cSmrg return (Success); 10709bd41f2cSmrg} 10719bd41f2cSmrg 10729bd41f2cSmrg 10739bd41f2cSmrg/* 10749bd41f2cSmrg *---------------------------------------------------------------------- 10759bd41f2cSmrg * 10769bd41f2cSmrg * VMMouseConvertProc -- 10779bd41f2cSmrg * This function was called by Xserver to convert valuators to X and Y 10789bd41f2cSmrg * 10799bd41f2cSmrg * Results: 10809bd41f2cSmrg * TRUE 10819bd41f2cSmrg * 10829bd41f2cSmrg * Side effects: 10839bd41f2cSmrg * X and Y was converted according to current Screen dimension 10849bd41f2cSmrg * 10859bd41f2cSmrg *---------------------------------------------------------------------- 10869bd41f2cSmrg */ 10879bd41f2cSmrg 10889bd41f2cSmrgstatic Bool 10899bd41f2cSmrgVMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, 10909bd41f2cSmrg int v3, int v4, int v5, int *x, int *y) 10919bd41f2cSmrg{ 10929bd41f2cSmrg MouseDevPtr pMse; 10939bd41f2cSmrg VMMousePrivPtr mPriv; 10949bd41f2cSmrg double factorX, factorY; 10959bd41f2cSmrg 10969bd41f2cSmrg pMse = pInfo->private; 10979bd41f2cSmrg mPriv = pMse->mousePriv; 10989bd41f2cSmrg 10999bd41f2cSmrg if (first != 0 || num != 2) 11009bd41f2cSmrg return FALSE; 11019bd41f2cSmrg 11029bd41f2cSmrg if(mPriv->relative) { 11039bd41f2cSmrg *x = v0; 11049bd41f2cSmrg *y = v1; 11059bd41f2cSmrg } else { 11069bd41f2cSmrg factorX = ((double) screenInfo.screens[mPriv->screenNum]->width) / (double) 65535; 11079bd41f2cSmrg factorY = ((double) screenInfo.screens[mPriv->screenNum]->height) / (double) 65535; 11089bd41f2cSmrg 11099bd41f2cSmrg *x = v0 * factorX + 0.5; 11109bd41f2cSmrg *y = v1 * factorY + 0.5; 11119bd41f2cSmrg 11129bd41f2cSmrg if (mPriv->screenNum != -1) { 11139bd41f2cSmrg xf86XInputSetScreen(pInfo, mPriv->screenNum, *x, *y); 11149bd41f2cSmrg } 11159bd41f2cSmrg } 11169bd41f2cSmrg return TRUE; 11179bd41f2cSmrg} 11189bd41f2cSmrg 11199bd41f2cSmrg 11209bd41f2cSmrg#ifdef XFree86LOADER 11219bd41f2cSmrgModuleInfoRec VMMouseInfo = { 11229bd41f2cSmrg 1, 11239bd41f2cSmrg "VMMOUSE", 11249bd41f2cSmrg NULL, 11259bd41f2cSmrg 0, 11269bd41f2cSmrg VMMouseAvailableOptions, 11279bd41f2cSmrg}; 11289bd41f2cSmrg 11299bd41f2cSmrg 11309bd41f2cSmrg/* 11319bd41f2cSmrg *---------------------------------------------------------------------- 11329bd41f2cSmrg * 11339bd41f2cSmrg * VMMouseUnplug -- 11349bd41f2cSmrg * This function was called by Xserver when unplug 11359bd41f2cSmrg * 11369bd41f2cSmrg * Results: 11379bd41f2cSmrg * None 11389bd41f2cSmrg * 11399bd41f2cSmrg * Side effects: 11409bd41f2cSmrg * None 11419bd41f2cSmrg * 11429bd41f2cSmrg *---------------------------------------------------------------------- 11439bd41f2cSmrg */ 11449bd41f2cSmrg 11459bd41f2cSmrgstatic void 11469bd41f2cSmrgVMMouseUnplug(pointer p) 11479bd41f2cSmrg{ 11489bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMouseUnplug\n"); 11499bd41f2cSmrg} 11509bd41f2cSmrg 11519bd41f2cSmrg 11529bd41f2cSmrg/* 11539bd41f2cSmrg *---------------------------------------------------------------------- 11549bd41f2cSmrg * 11559bd41f2cSmrg * VMMousePlug -- 11569bd41f2cSmrg * This function was called when Xserver load vmmouse module. It will 11579bd41f2cSmrg * integrate the module infto the XFree86 loader architecutre. 11589bd41f2cSmrg * 11599bd41f2cSmrg * Results: 11609bd41f2cSmrg * TRUE 11619bd41f2cSmrg * 11629bd41f2cSmrg * Side effects: 11639bd41f2cSmrg * Regular mouse module was loaded as a submodule. In case 11649bd41f2cSmrg * absolute pointing device is not available, we can always fall back 11659bd41f2cSmrg * to the regular mouse module 11669bd41f2cSmrg * 11679bd41f2cSmrg *---------------------------------------------------------------------- 11689bd41f2cSmrg */ 11699bd41f2cSmrg 11709bd41f2cSmrgstatic pointer 11719bd41f2cSmrgVMMousePlug(pointer module, 11729bd41f2cSmrg pointer options, 11739bd41f2cSmrg int *errmaj, 11749bd41f2cSmrg int *errmin) 11759bd41f2cSmrg{ 11769bd41f2cSmrg static Bool Initialised = FALSE; 11779bd41f2cSmrg char *name; 11789bd41f2cSmrg 11799bd41f2cSmrg xf86LoaderReqSymLists(reqSymbols, NULL); 11809bd41f2cSmrg 11819bd41f2cSmrg if (!Initialised) { 11829bd41f2cSmrg Initialised = TRUE; 11839bd41f2cSmrg#ifndef REMOVE_LOADER_CHECK_MODULE_INFO 11849bd41f2cSmrg if (xf86LoaderCheckSymbol("xf86AddModuleInfo")) 11859bd41f2cSmrg#endif 11869bd41f2cSmrg xf86AddModuleInfo(&VMMouseInfo, module); 11879bd41f2cSmrg } 11889bd41f2cSmrg 11899bd41f2cSmrg xf86Msg(X_INFO, "VMWARE(0): VMMOUSE module was loaded\n"); 11909bd41f2cSmrg xf86AddInputDriver(&VMMOUSE, module, 0); 11919bd41f2cSmrg 11929bd41f2cSmrg /* 11939bd41f2cSmrg * Load the normal mouse module as submodule 11949bd41f2cSmrg * If we fail in PreInit later, this allows us to fall back to normal mouse module 11959bd41f2cSmrg */ 11969bd41f2cSmrg#ifndef NORMALISE_MODULE_NAME 11979bd41f2cSmrg name = xstrdup("mouse"); 11989bd41f2cSmrg#else 11999bd41f2cSmrg /* Normalise the module name */ 12009bd41f2cSmrg name = xf86NormalizeName("mouse"); 12019bd41f2cSmrg#endif 12029bd41f2cSmrg 12039bd41f2cSmrg if (!LoadSubModule(module, name, NULL, NULL, NULL, NULL, errmaj, errmin)) { 12049bd41f2cSmrg LoaderErrorMsg(NULL, name, *errmaj, *errmin); 12059bd41f2cSmrg } 12069bd41f2cSmrg xfree(name); 12079bd41f2cSmrg 12089bd41f2cSmrg return module; 12099bd41f2cSmrg} 12109bd41f2cSmrg 12119bd41f2cSmrgstatic XF86ModuleVersionInfo VMMouseVersionRec = { 12129bd41f2cSmrg "vmmouse", 12139bd41f2cSmrg MODULEVENDORSTRING, 12149bd41f2cSmrg MODINFOSTRING1, 12159bd41f2cSmrg MODINFOSTRING2, 12169bd41f2cSmrg XORG_VERSION_CURRENT, 12179bd41f2cSmrg VMMOUSE_MAJOR_VERSION, VMMOUSE_MINOR_VERSION, VMMOUSE_PATCHLEVEL, 12189bd41f2cSmrg ABI_CLASS_XINPUT, 12199bd41f2cSmrg ABI_XINPUT_VERSION, 12209bd41f2cSmrg MOD_CLASS_XINPUT, 12219bd41f2cSmrg {0, 0, 0, 0} /* signature, to be patched into the file by a tool */ 12229bd41f2cSmrg}; 12239bd41f2cSmrg 12249bd41f2cSmrg/* 12259bd41f2cSmrg * The variable contains the necessary information to load and initialize the module 12269bd41f2cSmrg */ 12279bd41f2cSmrgXF86ModuleData vmmouseModuleData = { 12289bd41f2cSmrg &VMMouseVersionRec, 12299bd41f2cSmrg VMMousePlug, 12309bd41f2cSmrg VMMouseUnplug 12319bd41f2cSmrg}; 12329bd41f2cSmrg#endif /* XFree86LOADER */ 1233