1659607e0Smrg/* 2659607e0Smrg * 3659607e0Smrg * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 4659607e0Smrg * Copyright 1993 by David Dawes <dawes@xfree86.org> 5659607e0Smrg * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich 6659607e0Smrg * Copyright 1994-2002 by The XFree86 Project, Inc. 7659607e0Smrg * Copyright 2002 by Paul Elliott 8659607e0Smrg * 9659607e0Smrg * Permission to use, copy, modify, distribute, and sell this software and its 10659607e0Smrg * documentation for any purpose is hereby granted without fee, provided that 11659607e0Smrg * the above copyright notice appear in all copies and that both that 12659607e0Smrg * copyright notice and this permission notice appear in supporting 13659607e0Smrg * documentation, and that the names of copyright holders not be 14659607e0Smrg * used in advertising or publicity pertaining to distribution of the 15659607e0Smrg * software without specific, written prior permission. The copyright holders 16659607e0Smrg * make no representations about the suitability of this 17659607e0Smrg * software for any purpose. It is provided "as is" without express or 18659607e0Smrg * implied warranty. 19659607e0Smrg * 20659607e0Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 21659607e0Smrg * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 22659607e0Smrg * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 23659607e0Smrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 24659607e0Smrg * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 25659607e0Smrg * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 26659607e0Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27659607e0Smrg * 28659607e0Smrg */ 29659607e0Smrg/* Patch for PS/2 Intellimouse - Tim Goodwin 1997-11-06. */ 30659607e0Smrg 31659607e0Smrg/* 32659607e0Smrg * [JCH-96/01/21] Added fourth button support for PROT_GLIDEPOINT mouse 33659607e0Smrg * protocol. 34659607e0Smrg */ 35659607e0Smrg 36659607e0Smrg/* 37659607e0Smrg * [TVO-97/03/05] Added microsoft IntelliMouse support 38659607e0Smrg */ 39659607e0Smrg 40659607e0Smrg/* 414d6d3f96Smrg * [PME-02/08/11] Added support for drag lock buttons 42659607e0Smrg * for use with 4 button trackballs for convenience 43659607e0Smrg * and to help limited dexterity persons 44659607e0Smrg */ 45659607e0Smrg 46659607e0Smrg#ifdef HAVE_CONFIG_H 47659607e0Smrg#include "config.h" 48659607e0Smrg#endif 49659607e0Smrg 50f5c3fc63Smrg#include <xorg-server.h> 51659607e0Smrg#include <math.h> 52659607e0Smrg#include <string.h> 53659607e0Smrg#include <stdio.h> 54659607e0Smrg#include <stdlib.h> 55659607e0Smrg#include <X11/X.h> 56659607e0Smrg 57659607e0Smrg#include "xf86.h" 58659607e0Smrg 59659607e0Smrg#include <X11/extensions/XI.h> 60659607e0Smrg#include "extnsionst.h" 61659607e0Smrg#include "extinit.h" 62659607e0Smrg 63659607e0Smrg#include "xf86Xinput.h" 64659607e0Smrg#include "xf86_OSproc.h" 651450c749Smrg#include "exevents.h" 661450c749Smrg#include <X11/Xatom.h> 671450c749Smrg#include "xserver-properties.h" 681450c749Smrg#include "xf86-mouse-properties.h" 69659607e0Smrg 705ddc3750Smrg#ifdef __NetBSD__ 715ddc3750Smrg#include <time.h> 725ddc3750Smrg#include <dev/wscons/wsconsio.h> 733e41e457Schristos#include <sys/ioctl.h> 745ddc3750Smrg#endif 755ddc3750Smrg 76659607e0Smrg#include "compiler.h" 77659607e0Smrg 78659607e0Smrg#include "xisb.h" 79659607e0Smrg#include "mouse.h" 80659607e0Smrg#include "mousePriv.h" 81659607e0Smrg#include "mipointer.h" 82659607e0Smrg 83352aa7aeSmrg/* Xorg >= 1.10 provides an asprintf() implementation even if libc doesn't */ 84352aa7aeSmrg#include "xorgVersion.h" 85352aa7aeSmrg#if defined(HAVE_ASPRINTF) || \ 86352aa7aeSmrg (XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,10,0,0,0)) 87352aa7aeSmrg# define USE_ASPRINTF 88352aa7aeSmrg#endif 89352aa7aeSmrg 90659607e0Smrgenum { 91659607e0Smrg /* number of bits in mapped nibble */ 92659607e0Smrg NIB_BITS=4, 93659607e0Smrg /* size of map of nibbles to bitmask */ 94659607e0Smrg NIB_SIZE= (1 << NIB_BITS), 95659607e0Smrg /* mask for map */ 96659607e0Smrg NIB_MASK= (NIB_SIZE -1), 97659607e0Smrg /* number of maps to map all the buttons */ 98659607e0Smrg NIB_COUNT = ((MSE_MAXBUTTONS+NIB_BITS-1)/NIB_BITS) 99659607e0Smrg}; 100659607e0Smrg 101659607e0Smrg/*data to be used in implementing trackball drag locks.*/ 102659607e0Smrgtypedef struct _DragLockRec { 103659607e0Smrg 104659607e0Smrg /* Fields used to implement trackball drag locks. */ 105659607e0Smrg /* mask for those buttons that are ordinary drag lock buttons */ 106659607e0Smrg int lockButtonsM; 107659607e0Smrg 108659607e0Smrg /* mask for the master drag lock button if any */ 109659607e0Smrg int masterLockM; 110659607e0Smrg 111659607e0Smrg /* button state up/down from last time adjusted for drag locks */ 112659607e0Smrg int lockLastButtons; 113659607e0Smrg 114659607e0Smrg /* 115659607e0Smrg * true if master lock state i.e. master drag lock 116659607e0Smrg * button has just been pressed 117659607e0Smrg */ 118659607e0Smrg int masterTS; 119659607e0Smrg 120659607e0Smrg /* simulate these buttons being down although they are not */ 121659607e0Smrg int simulatedDown; 122659607e0Smrg 123659607e0Smrg /* 124659607e0Smrg * data to map bits for drag lock buttons to corresponding 125659607e0Smrg * bits for the target buttons 126659607e0Smrg */ 127659607e0Smrg int nib_table[NIB_COUNT][NIB_SIZE]; 128659607e0Smrg 129659607e0Smrg} DragLockRec, *DragLockPtr; 130659607e0Smrg 131659607e0Smrg 1321468c73eSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 23 1331468c73eSmrg#define HAVE_THREADED_INPUT 1 1341468c73eSmrg#endif 1351468c73eSmrg 1361468c73eSmrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 24 1371468c73eSmrg#define BLOCK_HANDLER_ARGS void *data, void *waitTime 1381468c73eSmrg#define WAKEUP_HANDLER_ARGS void *data, int i 1391468c73eSmrg#else 1401468c73eSmrg#define BLOCK_HANDLER_ARGS pointer data, struct timeval **waitTime, pointer LastSelectMask 1411468c73eSmrg#define WAKEUP_HANDLER_ARGS void *data, int i, pointer LastSelectMask 1421468c73eSmrg#endif 1431468c73eSmrg 144dd4cbfe8Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 145659607e0Smrgstatic InputInfoPtr MousePreInit(InputDriverPtr drv, IDevPtr dev, int flags); 146dd4cbfe8Smrg#else 147dd4cbfe8Smrgstatic int MousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 148659607e0Smrg#endif 149659607e0Smrg 150659607e0Smrgstatic int MouseProc(DeviceIntPtr device, int what); 151659607e0Smrgstatic void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl); 152659607e0Smrgstatic void MousePostEvent(InputInfoPtr pInfo, int buttons, 1531450c749Smrg int dx, int dy, int dz, int dw); 154659607e0Smrgstatic void MouseReadInput(InputInfoPtr pInfo); 1551468c73eSmrgstatic void MouseBlockHandler(BLOCK_HANDLER_ARGS); 1561468c73eSmrgstatic void MouseWakeupHandler(WAKEUP_HANDLER_ARGS); 157659607e0Smrgstatic void FlushButtons(MouseDevPtr pMse); 158659607e0Smrg 159659607e0Smrgstatic Bool SetupMouse(InputInfoPtr pInfo); 160659607e0Smrgstatic Bool initMouseHW(InputInfoPtr pInfo); 161659607e0Smrg#ifdef SUPPORT_MOUSE_RESET 162659607e0Smrgstatic Bool mouseReset(InputInfoPtr pInfo, unsigned char val); 163659607e0Smrgstatic void ps2WakeupHandler(pointer data, int i, pointer LastSelectMask); 164659607e0Smrgstatic void ps2BlockHandler(pointer data, struct timeval **waitTime, 1651450c749Smrg pointer LastSelectMask); 166659607e0Smrg#endif 1671450c749Smrgstatic void Emulate3ButtonsSetEnabled(InputInfoPtr pInfo, Bool enable); 168659607e0Smrg 169659607e0Smrg/* mouse autoprobe stuff */ 170659607e0Smrgstatic const char *autoOSProtocol(InputInfoPtr pInfo, int *protoPara); 171659607e0Smrgstatic void autoProbeMouse(InputInfoPtr pInfo, Bool inSync, Bool lostSync); 172659607e0Smrgstatic void checkForErraticMovements(InputInfoPtr pInfo, int dx, int dy); 173659607e0Smrgstatic Bool collectData(MouseDevPtr pMse, unsigned char u); 174659607e0Smrgstatic void SetMouseProto(MouseDevPtr pMse, MouseProtocolID protocolID); 175659607e0Smrgstatic Bool autoGood(MouseDevPtr pMse); 176659607e0Smrg 177659607e0Smrg#undef MOUSE 178659607e0Smrg_X_EXPORT InputDriverRec MOUSE = { 1794d6d3f96Smrg .driverVersion = 1, 1804d6d3f96Smrg .driverName = "mouse", 1814d6d3f96Smrg .Identify = NULL, 1824d6d3f96Smrg .PreInit = MousePreInit, 1834d6d3f96Smrg .UnInit = NULL, 1844d6d3f96Smrg .module = NULL, 1854d6d3f96Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 1864d6d3f96Smrg .default_options = NULL, 1874d6d3f96Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 21 1884d6d3f96Smrg .capabilities = 0 1894d6d3f96Smrg#endif 1904d6d3f96Smrg#endif 191659607e0Smrg}; 192659607e0Smrg 193659607e0Smrg#define RETRY_COUNT 4 194659607e0Smrg 1951450c749Smrg/* Properties that can be set at runtime via xinput */ 1961450c749Smrgstatic Atom prop_mbemu = 0; /* Middle button emulation on/off property */ 1971450c749Smrgstatic Atom prop_mbtimeout = 0; /* Middle button timeout property */ 1981450c749Smrg 199659607e0Smrg/* 200659607e0Smrg * Microsoft (all serial models), Logitech MouseMan, First Mouse, etc, 201659607e0Smrg * ALPS GlidePoint, Thinking Mouse. 202659607e0Smrg */ 203659607e0Smrgstatic const char *msDefaults[] = { 2041450c749Smrg "BaudRate", "1200", 2051450c749Smrg "DataBits", "7", 2061450c749Smrg "StopBits", "1", 2071450c749Smrg "Parity", "None", 2081450c749Smrg "FlowControl", "None", 2091450c749Smrg "VTime", "0", 2101450c749Smrg "VMin", "1", 2111450c749Smrg NULL 212659607e0Smrg}; 213659607e0Smrg/* MouseSystems */ 214659607e0Smrgstatic const char *mlDefaults[] = { 2151450c749Smrg "BaudRate", "1200", 2161450c749Smrg "DataBits", "8", 2171450c749Smrg "StopBits", "2", 2181450c749Smrg "Parity", "None", 2191450c749Smrg "FlowControl", "None", 2201450c749Smrg "VTime", "0", 2211450c749Smrg "VMin", "1", 2221450c749Smrg NULL 223659607e0Smrg}; 224659607e0Smrg/* MMSeries */ 225659607e0Smrgstatic const char *mmDefaults[] = { 2261450c749Smrg "BaudRate", "1200", 2271450c749Smrg "DataBits", "8", 2281450c749Smrg "StopBits", "1", 2291450c749Smrg "Parity", "Odd", 2301450c749Smrg "FlowControl", "None", 2311450c749Smrg "VTime", "0", 2321450c749Smrg "VMin", "1", 2331450c749Smrg NULL 234659607e0Smrg}; 235659607e0Smrg/* Hitachi Tablet */ 236659607e0Smrgstatic const char *mmhitDefaults[] = { 2371450c749Smrg "BaudRate", "1200", 2381450c749Smrg "DataBits", "8", 2391450c749Smrg "StopBits", "1", 2401450c749Smrg "Parity", "None", 2411450c749Smrg "FlowControl", "None", 2421450c749Smrg "VTime", "0", 2431450c749Smrg "VMin", "1", 2441450c749Smrg NULL 245659607e0Smrg}; 246659607e0Smrg/* AceCad Tablet */ 247659607e0Smrgstatic const char *acecadDefaults[] = { 2481450c749Smrg "BaudRate", "9600", 2491450c749Smrg "DataBits", "8", 2501450c749Smrg "StopBits", "1", 2511450c749Smrg "Parity", "Odd", 2521450c749Smrg "FlowControl", "None", 2531450c749Smrg "VTime", "0", 2541450c749Smrg "VMin", "1", 2551450c749Smrg NULL 256659607e0Smrg}; 257659607e0Smrg 258659607e0Smrgstatic MouseProtocolRec mouseProtocols[] = { 259659607e0Smrg 260659607e0Smrg /* Serial protocols */ 2611450c749Smrg { "Microsoft", MSE_SERIAL, msDefaults, PROT_MS }, 2621450c749Smrg { "MouseSystems", MSE_SERIAL, mlDefaults, PROT_MSC }, 2631450c749Smrg { "MMSeries", MSE_SERIAL, mmDefaults, PROT_MM }, 2641450c749Smrg { "Logitech", MSE_SERIAL, mlDefaults, PROT_LOGI }, 2651450c749Smrg { "MouseMan", MSE_SERIAL, msDefaults, PROT_LOGIMAN }, 2661450c749Smrg { "MMHitTab", MSE_SERIAL, mmhitDefaults, PROT_MMHIT }, 2671450c749Smrg { "GlidePoint", MSE_SERIAL, msDefaults, PROT_GLIDE }, 2681450c749Smrg { "IntelliMouse", MSE_SERIAL, msDefaults, PROT_IMSERIAL }, 2691450c749Smrg { "ThinkingMouse", MSE_SERIAL, msDefaults, PROT_THINKING }, 2701450c749Smrg { "AceCad", MSE_SERIAL, acecadDefaults, PROT_ACECAD }, 2711450c749Smrg { "ValuMouseScroll", MSE_SERIAL, msDefaults, PROT_VALUMOUSESCROLL }, 272659607e0Smrg 273659607e0Smrg /* Standard PS/2 */ 2741450c749Smrg { "PS/2", MSE_PS2, NULL, PROT_PS2 }, 2751450c749Smrg { "GenericPS/2", MSE_PS2, NULL, PROT_GENPS2 }, 276659607e0Smrg 277659607e0Smrg /* Extended PS/2 */ 2781450c749Smrg { "ImPS/2", MSE_XPS2, NULL, PROT_IMPS2 }, 2791450c749Smrg { "ExplorerPS/2", MSE_XPS2, NULL, PROT_EXPPS2 }, 2801450c749Smrg { "ThinkingMousePS/2", MSE_XPS2, NULL, PROT_THINKPS2 }, 2811450c749Smrg { "MouseManPlusPS/2", MSE_XPS2, NULL, PROT_MMPS2 }, 2821450c749Smrg { "GlidePointPS/2", MSE_XPS2, NULL, PROT_GLIDEPS2 }, 2831450c749Smrg { "NetMousePS/2", MSE_XPS2, NULL, PROT_NETPS2 }, 2841450c749Smrg { "NetScrollPS/2", MSE_XPS2, NULL, PROT_NETSCPS2 }, 285659607e0Smrg 286659607e0Smrg /* Bus Mouse */ 2871450c749Smrg { "BusMouse", MSE_BUS, NULL, PROT_BM }, 288659607e0Smrg 289659607e0Smrg /* Auto-detect (PnP) */ 2901450c749Smrg { "Auto", MSE_AUTO, NULL, PROT_AUTO }, 291659607e0Smrg 292659607e0Smrg /* Misc (usually OS-specific) */ 2931450c749Smrg { "SysMouse", MSE_MISC, mlDefaults, PROT_SYSMOUSE }, 2941450c749Smrg { "WSMouse", MSE_MISC, NULL, PROT_WSMOUSE }, 2951450c749Smrg { "VUID", MSE_MISC, NULL, PROT_VUID }, 296659607e0Smrg 297659607e0Smrg /* end of list */ 2981450c749Smrg { NULL, MSE_NONE, NULL, PROT_UNKNOWN } 299659607e0Smrg}; 300659607e0Smrg 301659607e0Smrg/* Process options common to all mouse types. */ 302659607e0Smrgstatic void 303659607e0SmrgMouseCommonOptions(InputInfoPtr pInfo) 304659607e0Smrg{ 305659607e0Smrg MouseDevPtr pMse; 306659607e0Smrg MessageType buttons_from = X_CONFIG; 307659607e0Smrg char *s; 308659607e0Smrg int origButtons; 309c508c3daSmrg int i; 310659607e0Smrg 311659607e0Smrg pMse = pInfo->private; 312659607e0Smrg 313659607e0Smrg pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0); 314659607e0Smrg if (!pMse->buttons) { 3151450c749Smrg pMse->buttons = MSE_DFLTBUTTONS; 3161450c749Smrg buttons_from = X_DEFAULT; 317659607e0Smrg } 318659607e0Smrg origButtons = pMse->buttons; 319659607e0Smrg 320659607e0Smrg pMse->emulate3Buttons = xf86SetBoolOption(pInfo->options, 3211450c749Smrg "Emulate3Buttons", FALSE); 322659607e0Smrg if (!xf86FindOptionValue(pInfo->options,"Emulate3Buttons")) { 3231450c749Smrg pMse->emulate3ButtonsSoft = TRUE; 3241450c749Smrg pMse->emulate3Buttons = TRUE; 325659607e0Smrg } 3261450c749Smrg 327659607e0Smrg pMse->emulate3Timeout = xf86SetIntOption(pInfo->options, 3281450c749Smrg "Emulate3Timeout", 50); 329659607e0Smrg if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) { 3301450c749Smrg MessageType from = X_CONFIG; 3311450c749Smrg if (pMse->emulate3ButtonsSoft) 3321450c749Smrg from = X_DEFAULT; 3331450c749Smrg xf86Msg(from, "%s: Emulate3Buttons, Emulate3Timeout: %d\n", 3341450c749Smrg pInfo->name, pMse->emulate3Timeout); 335659607e0Smrg } 336659607e0Smrg 337659607e0Smrg pMse->chordMiddle = xf86SetBoolOption(pInfo->options, "ChordMiddle", FALSE); 338659607e0Smrg pMse->flipXY = xf86SetBoolOption(pInfo->options, "FlipXY", FALSE); 339659607e0Smrg if (xf86SetBoolOption(pInfo->options, "InvX", FALSE)) { 3401450c749Smrg pMse->invX = -1; 341659607e0Smrg } else 3421450c749Smrg pMse->invX = 1; 343659607e0Smrg if (xf86SetBoolOption(pInfo->options, "InvY", FALSE)) { 3441450c749Smrg pMse->invY = -1; 345659607e0Smrg } else 3461450c749Smrg pMse->invY = 1; 347659607e0Smrg pMse->angleOffset = xf86SetIntOption(pInfo->options, "AngleOffset", 0); 3481450c749Smrg 349659607e0Smrg 350659607e0Smrg if (pMse->pDragLock) 3511450c749Smrg free(pMse->pDragLock); 352659607e0Smrg pMse->pDragLock = NULL; 3531450c749Smrg 354659607e0Smrg s = xf86SetStrOption(pInfo->options, "DragLockButtons", NULL); 355659607e0Smrg 356659607e0Smrg if (s) { 3571450c749Smrg int lock; /* lock button */ 3581450c749Smrg int target; /* target button */ 3591450c749Smrg int lockM,targetM; /* bitmasks for drag lock, target */ 3601450c749Smrg int j; /* indexes */ 3611450c749Smrg char *s1; /* parse input string */ 3621450c749Smrg DragLockPtr pLock; 3631450c749Smrg 3641450c749Smrg pLock = pMse->pDragLock = calloc(1, sizeof(DragLockRec)); 3651450c749Smrg /* init code */ 3661450c749Smrg 3671450c749Smrg /* initial string to be taken apart */ 3681450c749Smrg s1 = s; 3691450c749Smrg 3701450c749Smrg /* keep getting numbers which are buttons */ 3711450c749Smrg while ((s1 != NULL) && (lock = strtol(s1, &s1, 10)) != 0) { 3721450c749Smrg 3731450c749Smrg /* check sanity for a button */ 3741450c749Smrg if ((lock < 0) || (lock > MSE_MAXBUTTONS)) { 3751450c749Smrg xf86Msg(X_WARNING, "DragLock: Invalid button number = %d\n", 3761450c749Smrg lock); 3771450c749Smrg break; 3781450c749Smrg }; 3791450c749Smrg /* turn into a button mask */ 3801450c749Smrg lockM = 1 << (lock - 1); 3811450c749Smrg 3821450c749Smrg /* try to get drag lock button */ 3831450c749Smrg if ((s1 == NULL) || ((target=strtol(s1, &s1, 10)) == 0)) { 3841450c749Smrg /*if no target, must be a master drag lock button */ 3851450c749Smrg /* save master drag lock mask */ 3861450c749Smrg pLock->masterLockM = lockM; 3871450c749Smrg xf86Msg(X_CONFIG, 3881450c749Smrg "DragLock button %d is master drag lock", 3891450c749Smrg lock); 3901450c749Smrg } else { 3911450c749Smrg /* have target button number*/ 3921450c749Smrg /* check target button number for sanity */ 3931450c749Smrg if ((target < 0) || (target > MSE_MAXBUTTONS)) { 3941450c749Smrg xf86Msg(X_WARNING, 3951450c749Smrg "DragLock: Invalid button number for target=%d\n", 3961450c749Smrg target); 3971450c749Smrg break; 3981450c749Smrg } 399659607e0Smrg 4001450c749Smrg /* target button mask */ 4011450c749Smrg targetM = 1 << (target - 1); 402659607e0Smrg 4031450c749Smrg xf86Msg(X_CONFIG, 4041450c749Smrg "DragLock: button %d is drag lock for button %d\n", 4051450c749Smrg lock,target); 4061450c749Smrg lock--; 407659607e0Smrg 4081450c749Smrg /* initialize table that maps drag lock mask to target mask */ 4091450c749Smrg pLock->nib_table[lock / NIB_BITS][1 << (lock % NIB_BITS)] = 4101450c749Smrg targetM; 411659607e0Smrg 4121450c749Smrg /* add new drag lock to mask of drag locks */ 4131450c749Smrg pLock->lockButtonsM |= lockM; 4141450c749Smrg } 415659607e0Smrg 4161450c749Smrg } 417659607e0Smrg 4181450c749Smrg /* 4191450c749Smrg * fill out rest of map that maps sets of drag lock buttons 4201450c749Smrg * to sets of target buttons, in the form of masks 4211450c749Smrg */ 4221450c749Smrg 4231450c749Smrg /* for each nibble */ 4241450c749Smrg for (i = 0; i < NIB_COUNT; i++) { 4251450c749Smrg /* for each possible set of bits for that nibble */ 4261450c749Smrg for (j = 0; j < NIB_SIZE; j++) { 4271450c749Smrg int ff, fM, otherbits; 4281450c749Smrg 4291450c749Smrg /* get first bit set in j*/ 4301450c749Smrg ff = ffs(j) - 1; 4311450c749Smrg /* if 0 bits set nothing to do */ 4321450c749Smrg if (ff >= 0) { 4331450c749Smrg /* form mask for fist bit set */ 4341450c749Smrg fM = 1 << ff; 4351450c749Smrg /* mask off first bit set to get remaining bits set*/ 4361450c749Smrg otherbits = j & ~fM; 4371450c749Smrg /* 4381450c749Smrg * if otherbits =0 then only 1 bit set 4391450c749Smrg * so j=fM 4401450c749Smrg * nib_table[i][fM] already calculated if fM has 4411450c749Smrg * only 1 bit set. 4421450c749Smrg * nib_table[i][j] has already been filled in 4431450c749Smrg * by previous loop. otherwise 4441450c749Smrg * otherbits < j so nibtable[i][otherbits] 4451450c749Smrg * has already been calculated. 4461450c749Smrg */ 4471450c749Smrg if (otherbits) 4481450c749Smrg pLock->nib_table[i][j] = 4491450c749Smrg pLock->nib_table[i][fM] | 4501450c749Smrg pLock->nib_table[i][otherbits]; 4511450c749Smrg 4521450c749Smrg } 4531450c749Smrg } 4541450c749Smrg } 4551450c749Smrg free(s); 456659607e0Smrg } 457659607e0Smrg 458659607e0Smrg s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5"); 459659607e0Smrg if (s) { 4601450c749Smrg int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 4611450c749Smrg char *msg = NULL; 4621450c749Smrg 4631450c749Smrg pMse->negativeZ = pMse->positiveZ = MSE_NOAXISMAP; 4641450c749Smrg pMse->negativeW = pMse->positiveW = MSE_NOAXISMAP; 4651450c749Smrg if (!xf86NameCmp(s, "x")) { 4661450c749Smrg pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX; 4671450c749Smrg msg = xstrdup("X axis"); 4681450c749Smrg } else if (!xf86NameCmp(s, "y")) { 4691450c749Smrg pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY; 4701450c749Smrg msg = xstrdup("Y axis"); 4711450c749Smrg } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 && 4721450c749Smrg b1 > 0 && b1 <= MSE_MAXBUTTONS && 4731450c749Smrg b2 > 0 && b2 <= MSE_MAXBUTTONS) { 4741450c749Smrg pMse->negativeZ = 1 << (b1-1); 4751450c749Smrg pMse->positiveZ = 1 << (b2-1); 4761450c749Smrg if (b3 > 0 && b3 <= MSE_MAXBUTTONS && 4771450c749Smrg b4 > 0 && b4 <= MSE_MAXBUTTONS) { 4781450c749Smrg pMse->negativeW = 1 << (b3-1); 4791450c749Smrg pMse->positiveW = 1 << (b4-1); 480352aa7aeSmrg#ifdef USE_ASPRINTF 481352aa7aeSmrg if (asprintf(&msg, "buttons %d, %d, %d and %d", 482352aa7aeSmrg b1, b2, b3, b4) == -1) 483352aa7aeSmrg msg = NULL; 484352aa7aeSmrg#else 485352aa7aeSmrg msg = Xprintf("buttons %d, %d, %d and %d", b1, b2, b3, b4); 486352aa7aeSmrg#endif 487352aa7aeSmrg } 488352aa7aeSmrg else { 489352aa7aeSmrg#ifdef USE_ASPRINTF 490352aa7aeSmrg if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 491352aa7aeSmrg msg = NULL; 492352aa7aeSmrg#else 493352aa7aeSmrg msg = Xprintf("buttons %d and %d", b1, b2); 494352aa7aeSmrg#endif 4951450c749Smrg } 4961450c749Smrg if (b1 > pMse->buttons) pMse->buttons = b1; 4971450c749Smrg if (b2 > pMse->buttons) pMse->buttons = b2; 4981450c749Smrg if (b3 > pMse->buttons) pMse->buttons = b3; 4991450c749Smrg if (b4 > pMse->buttons) pMse->buttons = b4; 5001450c749Smrg } 5011450c749Smrg if (msg) { 5021450c749Smrg xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg); 5031450c749Smrg free(msg); 5041450c749Smrg } else { 5051450c749Smrg xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n", 5061450c749Smrg pInfo->name, s); 5071450c749Smrg } 5081450c749Smrg free(s); 509659607e0Smrg } 510659607e0Smrg if (xf86SetBoolOption(pInfo->options, "EmulateWheel", FALSE)) { 5111450c749Smrg Bool yFromConfig = FALSE; 5121450c749Smrg int wheelButton; 5131450c749Smrg 5141450c749Smrg pMse->emulateWheel = TRUE; 5151450c749Smrg wheelButton = xf86SetIntOption(pInfo->options, 5161450c749Smrg "EmulateWheelButton", 4); 5171450c749Smrg if (wheelButton < 0 || wheelButton > MSE_MAXBUTTONS) { 5181450c749Smrg xf86Msg(X_WARNING, "%s: Invalid EmulateWheelButton value: %d\n", 5191450c749Smrg pInfo->name, wheelButton); 5201450c749Smrg wheelButton = 4; 5211450c749Smrg } 5221450c749Smrg pMse->wheelButton = wheelButton; 5231450c749Smrg 5241450c749Smrg pMse->wheelInertia = xf86SetIntOption(pInfo->options, 5251450c749Smrg "EmulateWheelInertia", 10); 5261450c749Smrg if (pMse->wheelInertia <= 0) { 5271450c749Smrg xf86Msg(X_WARNING, "%s: Invalid EmulateWheelInertia value: %d\n", 5281450c749Smrg pInfo->name, pMse->wheelInertia); 5291450c749Smrg pMse->wheelInertia = 10; 5301450c749Smrg } 5311450c749Smrg pMse->wheelButtonTimeout = xf86SetIntOption(pInfo->options, 5321450c749Smrg "EmulateWheelTimeout", 200); 5331450c749Smrg if (pMse->wheelButtonTimeout <= 0) { 5341450c749Smrg xf86Msg(X_WARNING, "%s: Invalid EmulateWheelTimeout value: %d\n", 5351450c749Smrg pInfo->name, pMse->wheelButtonTimeout); 5361450c749Smrg pMse->wheelButtonTimeout = 200; 5371450c749Smrg } 538659607e0Smrg 5391450c749Smrg pMse->negativeX = MSE_NOAXISMAP; 5401450c749Smrg pMse->positiveX = MSE_NOAXISMAP; 5411450c749Smrg s = xf86SetStrOption(pInfo->options, "XAxisMapping", NULL); 5421450c749Smrg if (s) { 5431450c749Smrg int b1 = 0, b2 = 0; 5441450c749Smrg char *msg = NULL; 5451450c749Smrg 5461450c749Smrg if ((sscanf(s, "%d %d", &b1, &b2) == 2) && 5471450c749Smrg b1 > 0 && b1 <= MSE_MAXBUTTONS && 5481450c749Smrg b2 > 0 && b2 <= MSE_MAXBUTTONS) { 549352aa7aeSmrg#ifdef USE_ASPRINTF 550352aa7aeSmrg if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 551352aa7aeSmrg msg = NULL; 552352aa7aeSmrg#else 553352aa7aeSmrg msg = Xprintf("buttons %d and %d", b1, b2); 554352aa7aeSmrg#endif 5551450c749Smrg pMse->negativeX = b1; 5561450c749Smrg pMse->positiveX = b2; 5571450c749Smrg if (b1 > pMse->buttons) pMse->buttons = b1; 5581450c749Smrg if (b2 > pMse->buttons) pMse->buttons = b2; 5591450c749Smrg } else { 5601450c749Smrg xf86Msg(X_WARNING, "%s: Invalid XAxisMapping value: \"%s\"\n", 5611450c749Smrg pInfo->name, s); 5621450c749Smrg } 5631450c749Smrg if (msg) { 5641450c749Smrg xf86Msg(X_CONFIG, "%s: XAxisMapping: %s\n", pInfo->name, msg); 5651450c749Smrg free(msg); 5661450c749Smrg } 5671450c749Smrg free(s); 5681450c749Smrg } 5691450c749Smrg s = xf86SetStrOption(pInfo->options, "YAxisMapping", NULL); 5701450c749Smrg if (s) { 5711450c749Smrg int b1 = 0, b2 = 0; 5721450c749Smrg char *msg = NULL; 5731450c749Smrg 5741450c749Smrg if ((sscanf(s, "%d %d", &b1, &b2) == 2) && 5751450c749Smrg b1 > 0 && b1 <= MSE_MAXBUTTONS && 5761450c749Smrg b2 > 0 && b2 <= MSE_MAXBUTTONS) { 577352aa7aeSmrg#ifdef USE_ASPRINTF 578352aa7aeSmrg if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 579352aa7aeSmrg msg = NULL; 580352aa7aeSmrg#else 581352aa7aeSmrg msg = Xprintf("buttons %d and %d", b1, b2); 582352aa7aeSmrg#endif 5831450c749Smrg pMse->negativeY = b1; 5841450c749Smrg pMse->positiveY = b2; 5851450c749Smrg if (b1 > pMse->buttons) pMse->buttons = b1; 5861450c749Smrg if (b2 > pMse->buttons) pMse->buttons = b2; 5871450c749Smrg yFromConfig = TRUE; 5881450c749Smrg } else { 5891450c749Smrg xf86Msg(X_WARNING, "%s: Invalid YAxisMapping value: \"%s\"\n", 5901450c749Smrg pInfo->name, s); 5911450c749Smrg } 5921450c749Smrg if (msg) { 5931450c749Smrg xf86Msg(X_CONFIG, "%s: YAxisMapping: %s\n", pInfo->name, msg); 5941450c749Smrg free(msg); 5951450c749Smrg } 5961450c749Smrg free(s); 5971450c749Smrg } 5981450c749Smrg if (!yFromConfig) { 5991450c749Smrg pMse->negativeY = 4; 6001450c749Smrg pMse->positiveY = 5; 6011450c749Smrg if (pMse->negativeY > pMse->buttons) 6021450c749Smrg pMse->buttons = pMse->negativeY; 6031450c749Smrg if (pMse->positiveY > pMse->buttons) 6041450c749Smrg pMse->buttons = pMse->positiveY; 6051450c749Smrg xf86Msg(X_DEFAULT, "%s: YAxisMapping: buttons %d and %d\n", 6061450c749Smrg pInfo->name, pMse->negativeY, pMse->positiveY); 6071450c749Smrg } 6081450c749Smrg xf86Msg(X_CONFIG, "%s: EmulateWheel, EmulateWheelButton: %d, " 6091450c749Smrg "EmulateWheelInertia: %d, " 6101450c749Smrg "EmulateWheelTimeout: %d\n", 6111450c749Smrg pInfo->name, wheelButton, pMse->wheelInertia, 6121450c749Smrg pMse->wheelButtonTimeout); 613659607e0Smrg } 614659607e0Smrg s = xf86SetStrOption(pInfo->options, "ButtonMapping", NULL); 615659607e0Smrg if (s) { 616659607e0Smrg int b, n = 0; 617659607e0Smrg char *s1 = s; 618659607e0Smrg /* keep getting numbers which are buttons */ 619659607e0Smrg while (s1 && n < MSE_MAXBUTTONS && (b = strtol(s1, &s1, 10)) != 0) { 6201450c749Smrg /* check sanity for a button */ 6211450c749Smrg if (b < 0 || b > MSE_MAXBUTTONS) { 6221450c749Smrg xf86Msg(X_WARNING, 6231450c749Smrg "ButtonMapping: Invalid button number = %d\n", b); 6241450c749Smrg break; 6251450c749Smrg }; 6261450c749Smrg pMse->buttonMap[n++] = 1 << (b-1); 6271450c749Smrg if (b > pMse->buttons) pMse->buttons = b; 628659607e0Smrg } 629dd4cbfe8Smrg free(s); 630659607e0Smrg } 631659607e0Smrg /* get maximum of mapped buttons */ 6321450c749Smrg for (i = pMse->buttons-1; i >= 0; i--) { 6331450c749Smrg int f = ffs (pMse->buttonMap[i]); 6341450c749Smrg if (f > pMse->buttons) 6351450c749Smrg pMse->buttons = f; 636659607e0Smrg } 637659607e0Smrg if (origButtons != pMse->buttons) 6381450c749Smrg buttons_from = X_CONFIG; 639659607e0Smrg xf86Msg(buttons_from, "%s: Buttons: %d\n", pInfo->name, pMse->buttons); 640659607e0Smrg 641659607e0Smrg pMse->doubleClickSourceButtonMask = 0; 642659607e0Smrg pMse->doubleClickTargetButtonMask = 0; 643659607e0Smrg pMse->doubleClickTargetButton = 0; 644659607e0Smrg s = xf86SetStrOption(pInfo->options, "DoubleClickButtons", NULL); 645659607e0Smrg if (s) { 646659607e0Smrg int b1 = 0, b2 = 0; 647659607e0Smrg char *msg = NULL; 648659607e0Smrg 649659607e0Smrg if ((sscanf(s, "%d %d", &b1, &b2) == 2) && 650352aa7aeSmrg (b1 > 0) && (b1 <= MSE_MAXBUTTONS) && 651352aa7aeSmrg (b2 > 0) && (b2 <= MSE_MAXBUTTONS)) { 652352aa7aeSmrg#ifdef USE_ASPRINTF 653352aa7aeSmrg if (asprintf(&msg, "buttons %d and %d", b1, b2) == -1) 654352aa7aeSmrg msg = NULL; 655352aa7aeSmrg#else 656352aa7aeSmrg msg = Xprintf("buttons %d and %d", b1, b2); 657352aa7aeSmrg#endif 658659607e0Smrg pMse->doubleClickTargetButton = b1; 659659607e0Smrg pMse->doubleClickTargetButtonMask = 1 << (b1 - 1); 660659607e0Smrg pMse->doubleClickSourceButtonMask = 1 << (b2 - 1); 661659607e0Smrg if (b1 > pMse->buttons) pMse->buttons = b1; 662659607e0Smrg if (b2 > pMse->buttons) pMse->buttons = b2; 663659607e0Smrg } else { 664659607e0Smrg xf86Msg(X_WARNING, "%s: Invalid DoubleClickButtons value: \"%s\"\n", 665659607e0Smrg pInfo->name, s); 666659607e0Smrg } 667659607e0Smrg if (msg) { 668659607e0Smrg xf86Msg(X_CONFIG, "%s: DoubleClickButtons: %s\n", pInfo->name, msg); 669dd4cbfe8Smrg free(msg); 670659607e0Smrg } 6711450c749Smrg free(s); 672659607e0Smrg } 673659607e0Smrg} 674659607e0Smrg/* 675659607e0Smrg * map bits corresponding to lock buttons. 676659607e0Smrg * for each bit for a lock button, 677659607e0Smrg * turn on bit corresponding to button button that the lock 678659607e0Smrg * button services. 679659607e0Smrg */ 680659607e0Smrg 681659607e0Smrgstatic int 682659607e0Smrglock2targetMap(DragLockPtr pLock, int lockMask) 683659607e0Smrg{ 684659607e0Smrg int result,i; 685659607e0Smrg result = 0; 686659607e0Smrg 687659607e0Smrg /* 688659607e0Smrg * for each nibble group of bits, use 689659607e0Smrg * map for that group to get corresponding 690659607e0Smrg * bits, turn them on. 691659607e0Smrg * if 4 or less buttons only first map will 692659607e0Smrg * need to be used. 693659607e0Smrg */ 694659607e0Smrg for (i = 0; (i < NIB_COUNT) && lockMask; i++) { 6951450c749Smrg result |= pLock->nib_table[i][lockMask& NIB_MASK]; 696659607e0Smrg 6971450c749Smrg lockMask &= ~NIB_MASK; 6981450c749Smrg lockMask >>= NIB_BITS; 699659607e0Smrg } 700659607e0Smrg return result; 701659607e0Smrg} 702659607e0Smrg 703659607e0Smrgstatic void 704659607e0SmrgMouseHWOptions(InputInfoPtr pInfo) 705659607e0Smrg{ 706659607e0Smrg MouseDevPtr pMse = pInfo->private; 707659607e0Smrg mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 7081450c749Smrg 7091450c749Smrg if (mPriv == NULL) 7101450c749Smrg return; 711659607e0Smrg 712659607e0Smrg if ((mPriv->soft 7131450c749Smrg = xf86SetBoolOption(pInfo->options, "AutoSoft", FALSE))) { 7141450c749Smrg xf86Msg(X_CONFIG, "Don't initialize mouse when auto-probing\n"); 715659607e0Smrg } 716659607e0Smrg pMse->sampleRate = xf86SetIntOption(pInfo->options, "SampleRate", 0); 717659607e0Smrg pMse->resolution = xf86SetIntOption(pInfo->options, "Resolution", 0); 718dd4cbfe8Smrg mPriv->sensitivity = xf86SetRealOption(pInfo->options, "Sensitivity", 1.0); 719659607e0Smrg} 720659607e0Smrg 721659607e0Smrgstatic void 722659607e0SmrgMouseSerialOptions(InputInfoPtr pInfo) 723659607e0Smrg{ 724659607e0Smrg MouseDevPtr pMse = pInfo->private; 725659607e0Smrg 726dd4cbfe8Smrg pMse->baudRate = xf86SetIntOption(pInfo->options, "BaudRate", 0); 727659607e0Smrg} 728659607e0Smrg 729659607e0Smrgstatic MouseProtocolID 730659607e0SmrgProtocolNameToID(const char *name) 731659607e0Smrg{ 732659607e0Smrg int i; 733659607e0Smrg 734659607e0Smrg for (i = 0; mouseProtocols[i].name; i++) 7351450c749Smrg if (xf86NameCmp(name, mouseProtocols[i].name) == 0) 7361450c749Smrg return mouseProtocols[i].id; 737659607e0Smrg return PROT_UNKNOWN; 738659607e0Smrg} 739659607e0Smrg 740659607e0Smrgstatic const char * 741659607e0SmrgProtocolIDToName(MouseProtocolID id) 742659607e0Smrg{ 743659607e0Smrg int i; 744659607e0Smrg 745659607e0Smrg switch (id) { 746659607e0Smrg case PROT_UNKNOWN: 7471450c749Smrg return "Unknown"; 7481450c749Smrg break; 749659607e0Smrg case PROT_UNSUP: 7501450c749Smrg return "Unsupported"; 7511450c749Smrg break; 752659607e0Smrg default: 7531450c749Smrg for (i = 0; mouseProtocols[i].name; i++) 7541450c749Smrg if (id == mouseProtocols[i].id) 7551450c749Smrg return mouseProtocols[i].name; 7561450c749Smrg return "Invalid"; 757659607e0Smrg } 758659607e0Smrg} 759659607e0Smrg 760659607e0Smrgstatic int 761659607e0SmrgProtocolIDToClass(MouseProtocolID id) 762659607e0Smrg{ 763659607e0Smrg int i; 764659607e0Smrg 765659607e0Smrg switch (id) { 766659607e0Smrg case PROT_UNKNOWN: 767659607e0Smrg case PROT_UNSUP: 7681450c749Smrg return MSE_NONE; 7691450c749Smrg break; 770659607e0Smrg default: 7711450c749Smrg for (i = 0; mouseProtocols[i].name; i++) 7721450c749Smrg if (id == mouseProtocols[i].id) 7731450c749Smrg return mouseProtocols[i].class; 7741450c749Smrg return MSE_NONE; 775659607e0Smrg } 776659607e0Smrg} 777659607e0Smrg 778659607e0Smrgstatic MouseProtocolPtr 779659607e0SmrgGetProtocol(MouseProtocolID id) { 780659607e0Smrg int i; 781659607e0Smrg 782659607e0Smrg switch (id) { 783659607e0Smrg case PROT_UNKNOWN: 784659607e0Smrg case PROT_UNSUP: 7851450c749Smrg return NULL; 7861450c749Smrg break; 787659607e0Smrg default: 7881450c749Smrg for (i = 0; mouseProtocols[i].name; i++) 7891450c749Smrg if (id == mouseProtocols[i].id) { 7901450c749Smrg return &mouseProtocols[i]; 7911450c749Smrg } 7921450c749Smrg return NULL; 793659607e0Smrg } 794659607e0Smrg} 795659607e0Smrg 796659607e0Smrgstatic OSMouseInfoPtr osInfo = NULL; 797659607e0Smrg 798659607e0Smrgstatic Bool 799659607e0SmrgInitProtocols(void) 800659607e0Smrg{ 801659607e0Smrg int classes; 802659607e0Smrg int i; 803659607e0Smrg 804659607e0Smrg if (osInfo) 8051450c749Smrg return TRUE; 806659607e0Smrg 807dd4cbfe8Smrg osInfo = OSMouseInit(0); 808659607e0Smrg if (!osInfo) 8091450c749Smrg return FALSE; 810659607e0Smrg if (!osInfo->SupportedInterfaces) 8111450c749Smrg return FALSE; 812659607e0Smrg 813659607e0Smrg classes = osInfo->SupportedInterfaces(); 814659607e0Smrg if (!classes) 8151450c749Smrg return FALSE; 8161450c749Smrg 817659607e0Smrg /* Mark unsupported interface classes. */ 818659607e0Smrg for (i = 0; mouseProtocols[i].name; i++) 8191450c749Smrg if (!(mouseProtocols[i].class & classes)) 8201450c749Smrg mouseProtocols[i].id = PROT_UNSUP; 821659607e0Smrg 822659607e0Smrg for (i = 0; mouseProtocols[i].name; i++) 8231450c749Smrg if (mouseProtocols[i].class & MSE_MISC) 8241450c749Smrg if (!osInfo->CheckProtocol || 8251450c749Smrg !osInfo->CheckProtocol(mouseProtocols[i].name)) 8261450c749Smrg mouseProtocols[i].id = PROT_UNSUP; 827659607e0Smrg 828659607e0Smrg /* NetBSD uses PROT_BM for "PS/2". */ 8294d6d3f96Smrg#if defined(__NetBSD__) 83072ee27a2Smrg for (i = 0; mouseProtocols[i].name; i++) 83172ee27a2Smrg if (mouseProtocols[i].id == PROT_PS2) 83272ee27a2Smrg mouseProtocols[i].id = PROT_BM; 83372ee27a2Smrg#endif 834659607e0Smrg 835659607e0Smrg return TRUE; 836659607e0Smrg} 837659607e0Smrg 838dd4cbfe8Smrgstatic const char* 839dd4cbfe8SmrgMouseFindDevice(InputInfoPtr pInfo, const char* protocol) 840dd4cbfe8Smrg{ 841dd4cbfe8Smrg const char *device; 842dd4cbfe8Smrg 843dd4cbfe8Smrg if (!osInfo->FindDevice) 844dd4cbfe8Smrg return NULL; 845dd4cbfe8Smrg 846dd4cbfe8Smrg xf86Msg(X_WARNING, "%s: No Device specified, looking for one...\n", pInfo->name); 847dd4cbfe8Smrg device = osInfo->FindDevice(pInfo, protocol, 0); 848dd4cbfe8Smrg if (!device) 8491450c749Smrg xf86Msg(X_ERROR, "%s: Cannot find which device to use.\n", pInfo->name); 850dd4cbfe8Smrg else 8511450c749Smrg xf86Msg(X_PROBED, "%s: Device: \"%s\"\n", pInfo->name, device); 852dd4cbfe8Smrg 853dd4cbfe8Smrg return device; 854dd4cbfe8Smrg} 855dd4cbfe8Smrg 856dd4cbfe8Smrgstatic const char* 857dd4cbfe8SmrgMousePickProtocol(InputInfoPtr pInfo, const char* device, 8581450c749Smrg const char *protocol, MouseProtocolID *protocolID_out) 859dd4cbfe8Smrg{ 860dd4cbfe8Smrg MouseProtocolID protocolID = *protocolID_out; 861dd4cbfe8Smrg 862dd4cbfe8Smrg protocolID = ProtocolNameToID(protocol); 863dd4cbfe8Smrg 864dd4cbfe8Smrg if (protocolID == PROT_AUTO) 865dd4cbfe8Smrg { 8661450c749Smrg const char *osProt; 8671450c749Smrg if (osInfo->SetupAuto && (osProt = osInfo->SetupAuto(pInfo,NULL))) { 868352aa7aeSmrg protocolID = ProtocolNameToID(osProt); 869352aa7aeSmrg protocol = osProt; 8701450c749Smrg } 871dd4cbfe8Smrg } 872dd4cbfe8Smrg 873dd4cbfe8Smrg switch (protocolID) { 874dd4cbfe8Smrg case PROT_WSMOUSE: 875dd4cbfe8Smrg case PROT_VUID: 876dd4cbfe8Smrg if (osInfo->PreInit) 877dd4cbfe8Smrg osInfo->PreInit(pInfo, protocol, 0); 878dd4cbfe8Smrg break; 8791450c749Smrg case PROT_UNKNOWN: 8801450c749Smrg /* Check for a builtin OS-specific protocol, 8811450c749Smrg * and call its PreInit. */ 8821450c749Smrg if (osInfo->CheckProtocol 8831450c749Smrg && osInfo->CheckProtocol(protocol)) { 8841450c749Smrg if (!device) 8851450c749Smrg MouseFindDevice(pInfo, protocol); 8861450c749Smrg if (osInfo->PreInit) { 8871450c749Smrg osInfo->PreInit(pInfo, protocol, 0); 8881450c749Smrg } 8891450c749Smrg break; 8901450c749Smrg } 8911450c749Smrg xf86Msg(X_ERROR, "%s: Unknown protocol \"%s\"\n", 8921450c749Smrg pInfo->name, protocol); 8931450c749Smrg break; 8941450c749Smrg case PROT_UNSUP: 8951450c749Smrg xf86Msg(X_ERROR, 8961450c749Smrg "%s: Protocol \"%s\" is not supported on this " 8971450c749Smrg "platform\n", pInfo->name, protocol); 8981450c749Smrg break; 8991450c749Smrg default: 9001450c749Smrg break; 901dd4cbfe8Smrg } 902dd4cbfe8Smrg 903dd4cbfe8Smrg *protocolID_out = protocolID; 904dd4cbfe8Smrg 905dd4cbfe8Smrg return protocol; 906dd4cbfe8Smrg} 907dd4cbfe8Smrg 908dd4cbfe8Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 909dd4cbfe8Smrgstatic int NewMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, 910dd4cbfe8Smrg int flags); 911dd4cbfe8Smrg 912659607e0Smrgstatic InputInfoPtr 913659607e0SmrgMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags) 914659607e0Smrg{ 915659607e0Smrg InputInfoPtr pInfo; 916dd4cbfe8Smrg 917dd4cbfe8Smrg if (!(pInfo = xf86AllocateInput(drv, 0))) 9181450c749Smrg return NULL; 919dd4cbfe8Smrg 920dd4cbfe8Smrg pInfo->name = dev->identifier; 921dd4cbfe8Smrg pInfo->flags = XI86_SEND_DRAG_EVENTS; 922dd4cbfe8Smrg pInfo->conf_idev = dev; 923dd4cbfe8Smrg pInfo->close_proc = NULL; 924dd4cbfe8Smrg pInfo->private_flags = 0; 925dd4cbfe8Smrg pInfo->always_core_feedback = NULL; 926dd4cbfe8Smrg 9271450c749Smrg COLLECT_INPUT_OPTIONS(pInfo, NULL); 9281450c749Smrg 929dd4cbfe8Smrg if (NewMousePreInit(drv, pInfo, flags) == Success) 930dd4cbfe8Smrg { 931dd4cbfe8Smrg /* Check if SendDragEvents has been disabled. */ 932dd4cbfe8Smrg if (!xf86SetBoolOption(dev->commonOptions, "SendDragEvents", TRUE)) 933dd4cbfe8Smrg pInfo->flags &= ~XI86_SEND_DRAG_EVENTS; 934dd4cbfe8Smrg 935dd4cbfe8Smrg pInfo->flags |= XI86_CONFIGURED; 936dd4cbfe8Smrg 937dd4cbfe8Smrg return pInfo; 938dd4cbfe8Smrg } 939dd4cbfe8Smrg 940dd4cbfe8Smrg xf86DeleteInput(pInfo, 0); 941dd4cbfe8Smrg 942dd4cbfe8Smrg return NULL; 943dd4cbfe8Smrg} 944dd4cbfe8Smrg 945dd4cbfe8Smrgstatic int 946dd4cbfe8SmrgNewMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 947dd4cbfe8Smrg#else 948dd4cbfe8Smrgstatic int 949dd4cbfe8SmrgMousePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) 950dd4cbfe8Smrg#endif 951dd4cbfe8Smrg{ 952659607e0Smrg MouseDevPtr pMse; 953659607e0Smrg mousePrivPtr mPriv; 954dd4cbfe8Smrg MessageType protocolFrom = X_DEFAULT; 955dd4cbfe8Smrg const char *protocol; 956659607e0Smrg const char *device; 957659607e0Smrg MouseProtocolID protocolID; 958659607e0Smrg MouseProtocolPtr pProto; 959659607e0Smrg int i; 960dd4cbfe8Smrg int rc = Success; 961659607e0Smrg 962dd4cbfe8Smrg if (!InitProtocols()) 9631450c749Smrg return BadAlloc; 964659607e0Smrg 965659607e0Smrg /* Initialise the InputInfoRec. */ 966659607e0Smrg pInfo->type_name = XI_MOUSE; 967659607e0Smrg pInfo->device_control = MouseProc; 968659607e0Smrg pInfo->read_input = MouseReadInput; 969659607e0Smrg pInfo->control_proc = NULL; 970659607e0Smrg pInfo->switch_mode = NULL; 971659607e0Smrg pInfo->fd = -1; 972659607e0Smrg pInfo->dev = NULL; 973659607e0Smrg 974dd4cbfe8Smrg /* Allocate the MouseDevRec and initialise it. */ 975dd4cbfe8Smrg if (!(pMse = calloc(sizeof(MouseDevRec), 1))) 976dd4cbfe8Smrg { 9771450c749Smrg rc = BadAlloc; 9781450c749Smrg goto out; 979659607e0Smrg } 980659607e0Smrg 981659607e0Smrg pInfo->private = pMse; 982659607e0Smrg pMse->Ctrl = MouseCtrl; 983659607e0Smrg pMse->PostEvent = MousePostEvent; 984659607e0Smrg pMse->CommonOptions = MouseCommonOptions; 985dd4cbfe8Smrg 986659607e0Smrg /* Find the protocol type. */ 987dd4cbfe8Smrg protocol = xf86SetStrOption(pInfo->options, "Protocol", NULL); 988659607e0Smrg if (protocol) { 9891450c749Smrg protocolFrom = X_CONFIG; 990659607e0Smrg } else if (osInfo->DefaultProtocol) { 9911450c749Smrg protocol = osInfo->DefaultProtocol(); 9921450c749Smrg protocolFrom = X_DEFAULT; 993659607e0Smrg } 994659607e0Smrg if (!protocol) { 9951450c749Smrg xf86Msg(X_ERROR, "%s: No Protocol specified\n", pInfo->name); 9961450c749Smrg rc = BadValue; 9971450c749Smrg goto out; 998659607e0Smrg } 999659607e0Smrg 1000dd4cbfe8Smrg device = xf86SetStrOption(pInfo->options, "Device", NULL); 1001dd4cbfe8Smrg 1002659607e0Smrg /* Default Mapping: 1 2 3 8 9 10 11 ... */ 1003659607e0Smrg for (i = 0; i < MSE_MAXBUTTONS; i++) 10041450c749Smrg pMse->buttonMap[i] = 1 << (i > 2 && i < MSE_MAXBUTTONS-4 ? i+4 : i); 1005659607e0Smrg 1006dd4cbfe8Smrg protocol = MousePickProtocol(pInfo, device, protocol, &protocolID); 1007dd4cbfe8Smrg 1008dd4cbfe8Smrg if (!device) 1009dd4cbfe8Smrg MouseFindDevice(pInfo, protocol); 1010659607e0Smrg 1011659607e0Smrg xf86Msg(protocolFrom, "%s: Protocol: \"%s\"\n", pInfo->name, protocol); 1012dd4cbfe8Smrg if (protocolID == PROT_UNKNOWN) 1013dd4cbfe8Smrg goto out; 1014659607e0Smrg if (!(pProto = GetProtocol(protocolID))) 1015dd4cbfe8Smrg { 10161450c749Smrg rc = BadValue; 10171450c749Smrg goto out; 1018dd4cbfe8Smrg } 1019659607e0Smrg 1020659607e0Smrg pMse->protocolID = protocolID; 1021659607e0Smrg pMse->oldProtocolID = protocolID; /* hack */ 1022659607e0Smrg 1023659607e0Smrg pMse->autoProbe = FALSE; 1024659607e0Smrg /* Collect the options, and process the common options. */ 1025dd4cbfe8Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 1026dd4cbfe8Smrg /* need some special handling here. xf86CollectInputOptions will reset 1027dd4cbfe8Smrg * pInfo->options if the second argument is not-null. To re-merge the 1028dd4cbfe8Smrg * previously set arguments, pass the original pInfo->options in. 1029dd4cbfe8Smrg */ 1030dd4cbfe8Smrg xf86CollectInputOptions(pInfo, pProto->defaults, pInfo->options); 1031dd4cbfe8Smrg#else 1032dd4cbfe8Smrg COLLECT_INPUT_OPTIONS(pInfo, pProto->defaults); 1033dd4cbfe8Smrg#endif 1034659607e0Smrg xf86ProcessCommonOptions(pInfo, pInfo->options); 1035659607e0Smrg 1036659607e0Smrg /* Check if the device can be opened. */ 1037659607e0Smrg pInfo->fd = xf86OpenSerial(pInfo->options); 1038659607e0Smrg if (pInfo->fd == -1) { 10391450c749Smrg if (xf86GetAllowMouseOpenFail()) 10401450c749Smrg xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 10411450c749Smrg else { 10421450c749Smrg xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); 10431450c749Smrg if (pMse->mousePriv) 10441450c749Smrg free(pMse->mousePriv); 10451450c749Smrg free(pMse); 10461450c749Smrg pInfo->private = NULL; 10471450c749Smrg rc = BadValue; 10481450c749Smrg goto out; 10491450c749Smrg } 1050659607e0Smrg } 1051659607e0Smrg xf86CloseSerial(pInfo->fd); 1052659607e0Smrg pInfo->fd = -1; 1053659607e0Smrg 1054dd4cbfe8Smrg if (!(mPriv = (pointer) calloc(sizeof(mousePrivRec), 1))) 1055dd4cbfe8Smrg { 10561450c749Smrg rc = BadAlloc; 10571450c749Smrg goto out; 1058dd4cbfe8Smrg } 1059dd4cbfe8Smrg 1060659607e0Smrg pMse->mousePriv = mPriv; 1061659607e0Smrg pMse->CommonOptions(pInfo); 1062659607e0Smrg pMse->checkMovements = checkForErraticMovements; 1063659607e0Smrg pMse->autoProbeMouse = autoProbeMouse; 1064659607e0Smrg pMse->collectData = collectData; 1065659607e0Smrg pMse->dataGood = autoGood; 10661450c749Smrg 1067659607e0Smrg MouseHWOptions(pInfo); 1068659607e0Smrg MouseSerialOptions(pInfo); 1069dd4cbfe8Smrg 1070dd4cbfe8Smrgout: 1071dd4cbfe8Smrg return rc; 1072659607e0Smrg} 1073659607e0Smrg 10741450c749Smrgstatic void MouseInitButtonLabels(Atom *btn_labels) 10751450c749Smrg{ 10761450c749Smrg int i; 10771450c749Smrg Atom unknown_btn; 10781450c749Smrg 10791450c749Smrg btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 10801450c749Smrg btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 10811450c749Smrg btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 10821450c749Smrg btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 10831450c749Smrg btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 10841450c749Smrg btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 10851450c749Smrg btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 10861450c749Smrg 10871450c749Smrg unknown_btn = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN); 10881450c749Smrg for (i = 7; i < MSE_MAXBUTTONS; i++) 10891450c749Smrg btn_labels[i] = unknown_btn; 10901450c749Smrg} 10911450c749Smrg 10921450c749Smrgstatic int 10931450c749SmrgMouseSetProperty(DeviceIntPtr device, Atom atom, 10941450c749Smrg XIPropertyValuePtr val, BOOL checkonly) 10951450c749Smrg{ 10961450c749Smrg InputInfoPtr pInfo = device->public.devicePrivate; 10971450c749Smrg MouseDevPtr pMse = pInfo->private; 10981450c749Smrg 10991450c749Smrg if (atom == prop_mbemu) 11001450c749Smrg { 11011450c749Smrg if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER) 11021450c749Smrg return BadMatch; 11031450c749Smrg 11041450c749Smrg if (!checkonly) 11051450c749Smrg Emulate3ButtonsSetEnabled(pInfo, *((BOOL*)val->data)); 11061450c749Smrg } 11071450c749Smrg else if (atom == prop_mbtimeout) 11081450c749Smrg { 11091450c749Smrg if (val->format != 32 || val->size != 1 || val->type != XA_INTEGER) 11101450c749Smrg return BadMatch; 11111450c749Smrg 11121450c749Smrg if (!checkonly) 11131450c749Smrg pMse->emulate3Timeout = *((CARD32*)val->data); 11141450c749Smrg } 11151450c749Smrg 11161450c749Smrg return Success; 11171450c749Smrg} 11181450c749Smrg 11191450c749Smrgstatic void 11201450c749SmrgMouseInitProperties(DeviceIntPtr device) 11211450c749Smrg{ 11221450c749Smrg InputInfoPtr pInfo = device->public.devicePrivate; 11231450c749Smrg MouseDevPtr pMse = pInfo->private; 11241450c749Smrg int rc; 11251450c749Smrg 11261450c749Smrg#ifdef XI_PROP_DEVICE_NODE 11271450c749Smrg const char *device_node = 11281450c749Smrg xf86CheckStrOption(pInfo->options, "Device", NULL); 11291450c749Smrg 11301450c749Smrg if (device_node) 11311450c749Smrg { 11321450c749Smrg Atom prop_device = MakeAtom(XI_PROP_DEVICE_NODE, 11331450c749Smrg strlen(XI_PROP_DEVICE_NODE), TRUE); 11341450c749Smrg XIChangeDeviceProperty(device, prop_device, XA_STRING, 8, 11351450c749Smrg PropModeReplace, 11361450c749Smrg strlen(device_node), device_node, FALSE); 11371450c749Smrg } 11381450c749Smrg#endif /* XI_PROP_DEVICE_NODE */ 11391450c749Smrg 11401450c749Smrg /* Button labels */ 11411450c749Smrg if (pMse->buttons > 0) 11421450c749Smrg { 11431450c749Smrg Atom prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP); 11441450c749Smrg 11451450c749Smrg if (prop_btn_label) 11461450c749Smrg { 11471450c749Smrg Atom btn_labels[MSE_MAXBUTTONS]; 11481450c749Smrg MouseInitButtonLabels(btn_labels); 11491450c749Smrg 11501450c749Smrg XIChangeDeviceProperty(device, prop_btn_label, XA_ATOM, 32, 11511450c749Smrg PropModeReplace, pMse->buttons, 11521450c749Smrg btn_labels, FALSE); 11531450c749Smrg XISetDevicePropertyDeletable(device, prop_btn_label, FALSE); 11541450c749Smrg } 11551450c749Smrg } 11561450c749Smrg 11571450c749Smrg /* Middle button emulation - which this driver calls 3rd button emulation, 11581450c749Smrg * but evdev's properties considers that to be simulating right button 11591450c749Smrg * clicks from a one button mouse, which this driver does not currently 11601450c749Smrg * support, so we use this name for better consistency. 11611450c749Smrg */ 11621450c749Smrg prop_mbemu = MakeAtom(MOUSE_PROP_MIDBUTTON, strlen(MOUSE_PROP_MIDBUTTON), 11631450c749Smrg TRUE); 11641450c749Smrg rc = XIChangeDeviceProperty(device, prop_mbemu, XA_INTEGER, 8, 11651450c749Smrg PropModeReplace, 1, 11661450c749Smrg &pMse->emulate3Buttons, FALSE); 11671450c749Smrg if (rc != Success) 11681450c749Smrg return; 11691450c749Smrg XISetDevicePropertyDeletable(device, prop_mbemu, FALSE); 11701450c749Smrg 11711450c749Smrg prop_mbtimeout = MakeAtom(MOUSE_PROP_MIDBUTTON_TIMEOUT, 11721450c749Smrg strlen(MOUSE_PROP_MIDBUTTON_TIMEOUT), TRUE); 11731450c749Smrg rc = XIChangeDeviceProperty(device, prop_mbtimeout, XA_INTEGER, 32, 11741450c749Smrg PropModeReplace, 1, 11751450c749Smrg &pMse->emulate3Timeout, FALSE); 11761450c749Smrg 11771450c749Smrg if (rc != Success) 11781450c749Smrg return; 11791450c749Smrg XISetDevicePropertyDeletable(device, prop_mbtimeout, FALSE); 11801450c749Smrg 11811450c749Smrg XIRegisterPropertyHandler(device, MouseSetProperty, NULL, NULL); 11821450c749Smrg} 1183659607e0Smrg 1184659607e0Smrgstatic void 1185659607e0SmrgMouseReadInput(InputInfoPtr pInfo) 1186659607e0Smrg{ 1187659607e0Smrg MouseDevPtr pMse; 1188659607e0Smrg int j, buttons, dx, dy, dz, dw, baddata; 1189659607e0Smrg int pBufP; 1190659607e0Smrg int c; 1191659607e0Smrg unsigned char *pBuf, u; 1192659607e0Smrg 1193659607e0Smrg 1194659607e0Smrg pMse = pInfo->private; 1195659607e0Smrg pBufP = pMse->protoBufTail; 1196659607e0Smrg pBuf = pMse->protoBuf; 1197659607e0Smrg 1198659607e0Smrg if (pInfo->fd == -1) 11991450c749Smrg return; 1200659607e0Smrg 1201659607e0Smrg /* 1202659607e0Smrg * Set blocking to -1 on the first call because we know there is data to 1203659607e0Smrg * read. Xisb automatically clears it after one successful read so that 12044d6d3f96Smrg * succeeding reads are preceded by a select with a 0 timeout to prevent 1205659607e0Smrg * read from blocking indefinitely. 1206659607e0Smrg */ 1207659607e0Smrg XisbBlockDuration(pMse->buffer, -1); 1208659607e0Smrg 1209659607e0Smrg while ((c = XisbRead(pMse->buffer)) >= 0) { 12101450c749Smrg u = (unsigned char)c; 1211659607e0Smrg 1212659607e0Smrg#if defined (EXTMOUSEDEBUG) || defined (MOUSEDATADEBUG) 12131450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "mouse byte: %x\n",u); 1214659607e0Smrg#endif 1215659607e0Smrg 12161450c749Smrg /* if we do autoprobing collect the data */ 12171450c749Smrg if (pMse->collectData && pMse->autoProbe) 12181450c749Smrg if (pMse->collectData(pMse,u)) 12191450c749Smrg continue; 1220eeaac534Smrg 1221659607e0Smrg#ifdef SUPPORT_MOUSE_RESET 12221450c749Smrg if (mouseReset(pInfo,u)) { 12231450c749Smrg pBufP = 0; 12241450c749Smrg continue; 12251450c749Smrg } 1226659607e0Smrg#endif 12271450c749Smrg if (pBufP >= pMse->protoPara[4]) { 12281450c749Smrg /* 12291450c749Smrg * Buffer contains a full packet, which has already been processed: 12301450c749Smrg * Empty the buffer and check for optional 4th byte, which will be 12311450c749Smrg * processed directly, without being put into the buffer first. 12321450c749Smrg */ 12331450c749Smrg pBufP = 0; 12341450c749Smrg if ((u & pMse->protoPara[0]) != pMse->protoPara[1] && 12351450c749Smrg (u & pMse->protoPara[5]) == pMse->protoPara[6]) { 12361450c749Smrg /* 12371450c749Smrg * Hack for Logitech MouseMan Mouse - Middle button 12381450c749Smrg * 12391450c749Smrg * Unfortunately this mouse has variable length packets: the 12401450c749Smrg * standard Microsoft 3 byte packet plus an optional 4th byte 12411450c749Smrg * whenever the middle button status changes. 12421450c749Smrg * 12431450c749Smrg * We have already processed the standard packet with the 12441450c749Smrg * movement and button info. Now post an event message with 12451450c749Smrg * the old status of the left and right buttons and the 12461450c749Smrg * updated middle button. 12471450c749Smrg */ 12481450c749Smrg /* 12491450c749Smrg * Even worse, different MouseMen and TrackMen differ in the 12501450c749Smrg * 4th byte: some will send 0x00/0x20, others 0x01/0x21, or 12511450c749Smrg * even 0x02/0x22, so I have to strip off the lower bits. 12521450c749Smrg * [CHRIS-211092] 12531450c749Smrg * 12541450c749Smrg * [JCH-96/01/21] 12551450c749Smrg * HACK for ALPS "fourth button". (It's bit 0x10 of the 12561450c749Smrg * "fourth byte" and it is activated by tapping the glidepad 12571450c749Smrg * with the finger! 8^) We map it to bit bit3, and the 12581450c749Smrg * reverse map in xf86Events just has to be extended so that 12591450c749Smrg * it is identified as Button 4. The lower half of the 12601450c749Smrg * reverse-map may remain unchanged. 12611450c749Smrg */ 12621450c749Smrg /* 12631450c749Smrg * [KAZU-030897] 12644d6d3f96Smrg * Receive the fourth byte only when preceding three bytes 12651450c749Smrg * have been detected (pBufP >= pMse->protoPara[4]). In the 12661450c749Smrg * previous versions, the test was pBufP == 0; we may have 12671450c749Smrg * mistakingly received a byte even if we didn't see anything 12684d6d3f96Smrg * preceding the byte. 12691450c749Smrg */ 1270659607e0Smrg#ifdef EXTMOUSEDEBUG 12711450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "mouse 4th byte %x\n",u); 1272659607e0Smrg#endif 12731450c749Smrg dx = dy = dz = dw = 0; 12741450c749Smrg buttons = 0; 12751450c749Smrg switch (pMse->protocolID) { 12761450c749Smrg 12771450c749Smrg /* 12781450c749Smrg * [KAZU-221197] 12791450c749Smrg * IntelliMouse, NetMouse (including NetMouse Pro) and Mie 12801450c749Smrg * Mouse always send the fourth byte, whereas the fourth byte 12811450c749Smrg * is optional for GlidePoint and ThinkingMouse. The fourth 12821450c749Smrg * byte is also optional for MouseMan+ and FirstMouse+ in 12831450c749Smrg * their native mode. It is always sent if they are in the 12841450c749Smrg * IntelliMouse compatible mode. 12851450c749Smrg */ 12861450c749Smrg case PROT_IMSERIAL: /* IntelliMouse, NetMouse, Mie Mouse, 12871450c749Smrg MouseMan+ */ 12881450c749Smrg dz = (u & 0x08) ? 12891450c749Smrg (u & 0x0f) - 16 : (u & 0x0f); 12901450c749Smrg if ((dz >= 7) || (dz <= -7)) 12911450c749Smrg dz = 0; 12921450c749Smrg buttons |= ((int)(u & 0x10) >> 3) 12931450c749Smrg | ((int)(u & 0x20) >> 2) 12941450c749Smrg | (pMse->lastButtons & 0x05); 12951450c749Smrg break; 12961450c749Smrg 12971450c749Smrg case PROT_GLIDE: 12981450c749Smrg case PROT_THINKING: 12991450c749Smrg buttons |= ((int)(u & 0x10) >> 1); 13001450c749Smrg /* fall through */ 13011450c749Smrg 13021450c749Smrg default: 13031450c749Smrg buttons |= ((int)(u & 0x20) >> 4) | 13041450c749Smrg (pMse->lastButtons & 0x05); 13051450c749Smrg break; 13061450c749Smrg } 13071450c749Smrg goto post_event; 13081450c749Smrg } 13091450c749Smrg } 13101450c749Smrg /* End of packet buffer flush and 4th byte hack. */ 13111450c749Smrg 13121450c749Smrg /* 13131450c749Smrg * Append next byte to buffer (which is empty or contains an 13141450c749Smrg * incomplete packet); iterate if packet (still) not complete. 13151450c749Smrg */ 13161450c749Smrg pBuf[pBufP++] = u; 13171450c749Smrg if (pBufP != pMse->protoPara[4]) continue; 1318659607e0Smrg#ifdef EXTMOUSEDEBUG2 13191450c749Smrg { 13201450c749Smrg int i; 13211450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "received %d bytes",pBufP); 13221450c749Smrg for ( i=0; i < pBufP; i++) 13231450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, " %x",pBuf[i]); 13241450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "\n"); 13251450c749Smrg } 1326659607e0Smrg#endif 1327659607e0Smrg 13281450c749Smrg /* 13291450c749Smrg * Hack for resyncing: We check here for a package that is: 13301450c749Smrg * a) illegal (detected by wrong data-package header) 13311450c749Smrg * b) invalid (0x80 == -128 and that might be wrong for MouseSystems) 13321450c749Smrg * c) bad header-package 13331450c749Smrg * 13341450c749Smrg * NOTE: b) is a violation of the MouseSystems-Protocol, since values 13351450c749Smrg * of -128 are allowed, but since they are very seldom we can 13361450c749Smrg * easily use them as package-header with no button pressed. 13371450c749Smrg * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. 13381450c749Smrg * Furthermore, 0x80 is not valid as a header byte. For a PS/2 13391450c749Smrg * mouse we skip checking data bytes. For resyncing a PS/2 13401450c749Smrg * mouse we require the two most significant bits in the header 13411450c749Smrg * byte to be 0. These are the overflow bits, and in case of 13421450c749Smrg * an overflow we actually lose sync. Overflows are very rare, 13431450c749Smrg * however, and we quickly gain sync again after an overflow 13441450c749Smrg * condition. This is the best we can do. (Actually, we could 13451450c749Smrg * use bit 0x08 in the header byte for resyncing, since that 13461450c749Smrg * bit is supposed to be always on, but nobody told Microsoft...) 13471450c749Smrg */ 13481450c749Smrg 13491450c749Smrg /* 13501450c749Smrg * [KAZU,OYVIND-120398] 13511450c749Smrg * The above hack is wrong! Because of b) above, we shall see 13521450c749Smrg * erroneous mouse events so often when the MouseSystem mouse is 13531450c749Smrg * moved quickly. As for the PS/2 and its variants, we don't need 13541450c749Smrg * to treat them as special cases, because protoPara[2] and 13551450c749Smrg * protoPara[3] are both 0x00 for them, thus, any data bytes will 13561450c749Smrg * never be discarded. 0x80 is rejected for MMSeries, Logitech 13571450c749Smrg * and MMHittab protocols, because protoPara[2] and protoPara[3] 13581450c749Smrg * are 0x80 and 0x00 respectively. The other protocols are 7-bit 13591450c749Smrg * protocols; there is no use checking 0x80. 13601450c749Smrg * 13611450c749Smrg * All in all we should check the condition a) only. 13621450c749Smrg */ 13631450c749Smrg 13641450c749Smrg /* 13651450c749Smrg * [OYVIND-120498] 13661450c749Smrg * Check packet for valid data: 13671450c749Smrg * If driver is in sync with datastream, the packet is considered 13681450c749Smrg * bad if any byte (header and/or data) contains an invalid value. 13691450c749Smrg * 13701450c749Smrg * If packet is bad, we discard the first byte and shift the buffer. 13711450c749Smrg * Next iteration will then check the new situation for validity. 13721450c749Smrg * 13731450c749Smrg * If flag MF_SAFE is set in proto[7] and the driver 13741450c749Smrg * is out of sync, the packet is also considered bad if 13751450c749Smrg * any of the data bytes contains a valid header byte value. 13761450c749Smrg * This situation could occur if the buffer contains 13771450c749Smrg * the tail of one packet and the header of the next. 13781450c749Smrg * 13791450c749Smrg * Note: The driver starts in out-of-sync mode (pMse->inSync = 0). 13801450c749Smrg */ 13811450c749Smrg 13821450c749Smrg baddata = 0; 13831450c749Smrg 13841450c749Smrg /* All databytes must be valid. */ 13851450c749Smrg for (j = 1; j < pBufP; j++ ) 13861450c749Smrg if ((pBuf[j] & pMse->protoPara[2]) != pMse->protoPara[3]) 13871450c749Smrg baddata = 1; 13881450c749Smrg 13891450c749Smrg /* If out of sync, don't mistake a header byte for data. */ 13901450c749Smrg if ((pMse->protoPara[7] & MPF_SAFE) && !pMse->inSync) 13911450c749Smrg for (j = 1; j < pBufP; j++ ) 13921450c749Smrg if ((pBuf[j] & pMse->protoPara[0]) == pMse->protoPara[1]) 13931450c749Smrg baddata = 1; 13941450c749Smrg 13951450c749Smrg /* Accept or reject the packet ? */ 13961450c749Smrg if ((pBuf[0] & pMse->protoPara[0]) != pMse->protoPara[1] || baddata) { 13971450c749Smrg if (pMse->inSync) { 1398659607e0Smrg#ifdef EXTMOUSEDEBUG 13991450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "mouse driver lost sync\n"); 1400659607e0Smrg#endif 14011450c749Smrg } 1402659607e0Smrg#ifdef EXTMOUSEDEBUG 14031450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "skipping byte %x\n",*pBuf); 1404659607e0Smrg#endif 14051450c749Smrg /* Tell auto probe that we are out of sync */ 14061450c749Smrg if (pMse->autoProbeMouse && pMse->autoProbe) 14071450c749Smrg pMse->autoProbeMouse(pInfo, FALSE, pMse->inSync); 14081450c749Smrg pMse->protoBufTail = --pBufP; 14091450c749Smrg for (j = 0; j < pBufP; j++) 14101450c749Smrg pBuf[j] = pBuf[j+1]; 14111450c749Smrg pMse->inSync = 0; 14121450c749Smrg continue; 14131450c749Smrg } 14141450c749Smrg /* Tell auto probe that we were successful */ 14151450c749Smrg if (pMse->autoProbeMouse && pMse->autoProbe) 14161450c749Smrg pMse->autoProbeMouse(pInfo, TRUE, FALSE); 14171450c749Smrg 14181450c749Smrg if (!pMse->inSync) { 1419659607e0Smrg#ifdef EXTMOUSEDEBUG 14201450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "mouse driver back in sync\n"); 1421659607e0Smrg#endif 14221450c749Smrg pMse->inSync = 1; 14231450c749Smrg } 1424659607e0Smrg 14251450c749Smrg if (!pMse->dataGood(pMse)) 14261450c749Smrg continue; 14271450c749Smrg 14281450c749Smrg /* 14291450c749Smrg * Packet complete and verified, now process it ... 14301450c749Smrg */ 1431659607e0Smrg REDO_INTERPRET: 14321450c749Smrg dz = dw = 0; 14331450c749Smrg switch (pMse->protocolID) { 14341450c749Smrg case PROT_LOGIMAN: /* MouseMan / TrackMan [CHRIS-211092] */ 14351450c749Smrg case PROT_MS: /* Microsoft */ 14361450c749Smrg if (pMse->chordMiddle) 14371450c749Smrg buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 : 14381450c749Smrg ((int)(pBuf[0] & 0x20) >> 3) 14391450c749Smrg | ((int)(pBuf[0] & 0x10) >> 4); 14401450c749Smrg else 14411450c749Smrg buttons = (pMse->lastButtons & 2) 14421450c749Smrg | ((int)(pBuf[0] & 0x20) >> 3) 14431450c749Smrg | ((int)(pBuf[0] & 0x10) >> 4); 14441450c749Smrg dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 14451450c749Smrg dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 14461450c749Smrg break; 14471450c749Smrg 14481450c749Smrg case PROT_GLIDE: /* ALPS GlidePoint */ 14491450c749Smrg case PROT_THINKING: /* ThinkingMouse */ 14501450c749Smrg case PROT_IMSERIAL: /* IntelliMouse, NetMouse, Mie Mouse, MouseMan+ */ 14511450c749Smrg buttons = (pMse->lastButtons & (8 + 2)) 14521450c749Smrg | ((int)(pBuf[0] & 0x20) >> 3) 14531450c749Smrg | ((int)(pBuf[0] & 0x10) >> 4); 14541450c749Smrg dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 14551450c749Smrg dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 14561450c749Smrg break; 14571450c749Smrg 14581450c749Smrg case PROT_MSC: /* Mouse Systems Corp */ 14591450c749Smrg buttons = (~pBuf[0]) & 0x07; 14601450c749Smrg dx = (signed char)(pBuf[1]) + (char)(pBuf[3]); 14611450c749Smrg dy = - ((signed char)(pBuf[2]) + (char)(pBuf[4])); 14621450c749Smrg break; 14631450c749Smrg 14641450c749Smrg case PROT_MMHIT: /* MM_HitTablet */ 14651450c749Smrg buttons = pBuf[0] & 0x07; 14661450c749Smrg if (buttons != 0) 14671450c749Smrg buttons = 1 << (buttons - 1); 14681450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 14691450c749Smrg dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 14701450c749Smrg break; 14711450c749Smrg 14721450c749Smrg case PROT_ACECAD: /* ACECAD */ 14731450c749Smrg /* ACECAD is almost exactly like MM but the buttons are different */ 14741450c749Smrg buttons = (pBuf[0] & 0x02) | ((pBuf[0] & 0x04) >> 2) | 14751450c749Smrg ((pBuf[0] & 1) << 2); 14761450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 14771450c749Smrg dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 14781450c749Smrg break; 14791450c749Smrg 14801450c749Smrg case PROT_MM: /* MM Series */ 14811450c749Smrg case PROT_LOGI: /* Logitech Mice */ 14821450c749Smrg buttons = pBuf[0] & 0x07; 14831450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 14841450c749Smrg dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 14851450c749Smrg break; 14861450c749Smrg 14871450c749Smrg case PROT_BM: /* BusMouse */ 14881450c749Smrg buttons = (~pBuf[0]) & 0x07; 14891450c749Smrg dx = (signed char)pBuf[1]; 14901450c749Smrg dy = - (signed char)pBuf[2]; 14911450c749Smrg break; 14921450c749Smrg 14931450c749Smrg case PROT_PS2: /* PS/2 mouse */ 14941450c749Smrg case PROT_GENPS2: /* generic PS/2 mouse */ 14951450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 14961450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 14971450c749Smrg (pBuf[0] & 0x01) << 2; /* Left */ 14981450c749Smrg dx = (pBuf[0] & 0x10) ? (int)pBuf[1]-256 : (int)pBuf[1]; 14991450c749Smrg dy = (pBuf[0] & 0x20) ? -((int)pBuf[2]-256) : -(int)pBuf[2]; 15001450c749Smrg break; 15011450c749Smrg 15021450c749Smrg /* PS/2 mouse variants */ 15031450c749Smrg case PROT_IMPS2: /* IntelliMouse PS/2 */ 15041450c749Smrg case PROT_NETPS2: /* NetMouse PS/2 */ 15051450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 15061450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 15071450c749Smrg (pBuf[0] & 0x01) << 2 | /* Left */ 15081450c749Smrg (pBuf[0] & 0x40) >> 3 | /* button 4 */ 15091450c749Smrg (pBuf[0] & 0x80) >> 3; /* button 5 */ 15101450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 15111450c749Smrg dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 15121450c749Smrg /* 15131450c749Smrg * The next cast must be 'signed char' for platforms (like PPC) 15141450c749Smrg * where char defaults to unsigned. 15151450c749Smrg */ 15161450c749Smrg dz = (signed char)(pBuf[3] | ((pBuf[3] & 0x08) ? 0xf8 : 0)); 15171450c749Smrg if ((pBuf[3] & 0xf8) && ((pBuf[3] & 0xf8) != 0xf8)) { 15181450c749Smrg if (pMse->autoProbe) { 15191450c749Smrg SetMouseProto(pMse, PROT_EXPPS2); 15201450c749Smrg xf86Msg(X_INFO, 15211450c749Smrg "Mouse autoprobe: Changing protocol to %s\n", 15221450c749Smrg pMse->protocol); 15231450c749Smrg 15241450c749Smrg goto REDO_INTERPRET; 15251450c749Smrg } else 15261450c749Smrg dz = 0; 15271450c749Smrg } 15281450c749Smrg break; 15291450c749Smrg 15301450c749Smrg case PROT_EXPPS2: /* IntelliMouse Explorer PS/2 */ 15311450c749Smrg if (pMse->autoProbe && (pBuf[3] & 0xC0)) { 15321450c749Smrg SetMouseProto(pMse, PROT_IMPS2); 15331450c749Smrg xf86Msg(X_INFO,"Mouse autoprobe: Changing protocol to %s\n", 15341450c749Smrg pMse->protocol); 15351450c749Smrg goto REDO_INTERPRET; 15361450c749Smrg } 15371450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 15381450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 15391450c749Smrg (pBuf[0] & 0x01) << 2 | /* Left */ 15401450c749Smrg (pBuf[3] & 0x10) >> 1 | /* button 4 */ 15411450c749Smrg (pBuf[3] & 0x20) >> 1; /* button 5 */ 15421450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 15431450c749Smrg dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 15441450c749Smrg if (pMse->negativeW != MSE_NOAXISMAP) { 15451450c749Smrg switch (pBuf[3] & 0x0f) { 15461450c749Smrg case 0x00: break; 15471450c749Smrg case 0x01: dz = 1; break; 15481450c749Smrg case 0x02: dw = 1; break; 15491450c749Smrg case 0x0e: dw = -1; break; 15501450c749Smrg case 0x0f: dz = -1; break; 15511450c749Smrg default: 15521450c749Smrg xf86Msg(X_INFO, 15531450c749Smrg "Mouse autoprobe: Disabling secondary wheel\n"); 15541450c749Smrg pMse->negativeW = pMse->positiveW = MSE_NOAXISMAP; 15551450c749Smrg } 15561450c749Smrg } 15571450c749Smrg if (pMse->negativeW == MSE_NOAXISMAP) 15581450c749Smrg dz = (pBuf[3]&0x08) ? (pBuf[3]&0x0f) - 16 : (pBuf[3]&0x0f); 15591450c749Smrg break; 15601450c749Smrg 15611450c749Smrg case PROT_MMPS2: /* MouseMan+ PS/2 */ 15621450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 15631450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 15641450c749Smrg (pBuf[0] & 0x01) << 2; /* Left */ 15651450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1] - 256 : pBuf[1]; 15661450c749Smrg if (((pBuf[0] & 0x48) == 0x48) && 15671450c749Smrg (abs(dx) > 191) && 15681450c749Smrg ((((pBuf[2] & 0x03) << 2) | 0x02) == (pBuf[1] & 0x0f))) { 15691450c749Smrg /* extended data packet */ 15701450c749Smrg switch ((((pBuf[0] & 0x30) >> 2) | ((pBuf[1] & 0x30) >> 4))) { 15711450c749Smrg case 1: /* wheel data packet */ 15721450c749Smrg buttons |= ((pBuf[2] & 0x10) ? 0x08 : 0) | /* 4th button */ 15731450c749Smrg ((pBuf[2] & 0x20) ? 0x10 : 0); /* 5th button */ 15741450c749Smrg dx = dy = 0; 15751450c749Smrg dz = (pBuf[2] & 0x08) ? (pBuf[2] & 0x0f) - 16 : 15761450c749Smrg (pBuf[2] & 0x0f); 15771450c749Smrg break; 15781450c749Smrg case 2: /* Logitech reserves this packet type */ 15791450c749Smrg /* 15801450c749Smrg * IBM ScrollPoint uses this packet to encode its 15811450c749Smrg * stick movement. 15821450c749Smrg */ 15831450c749Smrg buttons |= (pMse->lastButtons & ~0x07); 15841450c749Smrg dx = dy = 0; 15851450c749Smrg dz = (pBuf[2] & 0x80) ? ((pBuf[2] >> 4) & 0x0f) - 16 : 15861450c749Smrg ((pBuf[2] >> 4) & 0x0f); 15871450c749Smrg dw = (pBuf[2] & 0x08) ? (pBuf[2] & 0x0f) - 16 : 15881450c749Smrg (pBuf[2] & 0x0f); 15891450c749Smrg break; 15901450c749Smrg case 0: /* device type packet - shouldn't happen */ 15911450c749Smrg default: 15921450c749Smrg buttons |= (pMse->lastButtons & ~0x07); 15931450c749Smrg dx = dy = 0; 15941450c749Smrg dz = 0; 15951450c749Smrg break; 15961450c749Smrg } 15971450c749Smrg } else { 15981450c749Smrg buttons |= (pMse->lastButtons & ~0x07); 15991450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 16001450c749Smrg dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 16011450c749Smrg } 16021450c749Smrg break; 16031450c749Smrg 16041450c749Smrg case PROT_GLIDEPS2: /* GlidePoint PS/2 */ 16051450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 16061450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 16071450c749Smrg (pBuf[0] & 0x01) << 2 | /* Left */ 16081450c749Smrg ((pBuf[0] & 0x08) ? 0 : 0x08);/* fourth button */ 16091450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 16101450c749Smrg dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 16111450c749Smrg break; 16121450c749Smrg 16131450c749Smrg case PROT_NETSCPS2: /* NetScroll PS/2 */ 16141450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 16151450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 16161450c749Smrg (pBuf[0] & 0x01) << 2 | /* Left */ 16171450c749Smrg ((pBuf[3] & 0x02) ? 0x08 : 0) | /* button 4 */ 16181450c749Smrg ((pBuf[3] & 0x01) ? 0x10 : 0); /* button 5 */ 16191450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 16201450c749Smrg dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 16211450c749Smrg dz = (pBuf[3] & 0x10) ? pBuf[4] - 256 : pBuf[4]; 16221450c749Smrg break; 16231450c749Smrg 16241450c749Smrg case PROT_THINKPS2: /* ThinkingMouse PS/2 */ 16251450c749Smrg buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 16261450c749Smrg (pBuf[0] & 0x02) >> 1 | /* Right */ 16271450c749Smrg (pBuf[0] & 0x01) << 2 | /* Left */ 16281450c749Smrg ((pBuf[0] & 0x08) ? 0x08 : 0);/* fourth button */ 16291450c749Smrg pBuf[1] |= (pBuf[0] & 0x40) ? 0x80 : 0x00; 16301450c749Smrg dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 16311450c749Smrg dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 16321450c749Smrg break; 16331450c749Smrg 16341450c749Smrg case PROT_SYSMOUSE: /* sysmouse */ 16351450c749Smrg buttons = (~pBuf[0]) & 0x07; 16361450c749Smrg dx = (signed char)(pBuf[1]) + (signed char)(pBuf[3]); 16371450c749Smrg dy = - ((signed char)(pBuf[2]) + (signed char)(pBuf[4])); 16381450c749Smrg /* FreeBSD sysmouse sends additional data bytes */ 16391450c749Smrg if (pMse->protoPara[4] >= 8) { 16401450c749Smrg /* 16411450c749Smrg * These casts must be 'signed char' for platforms (like PPC) 16421450c749Smrg * where char defaults to unsigned. 16431450c749Smrg */ 16441450c749Smrg dz = ((signed char)(pBuf[5] << 1) + 16451450c749Smrg (signed char)(pBuf[6] << 1)) >> 1; 16461450c749Smrg buttons |= (int)(~pBuf[7] & 0x7f) << 3; 16471450c749Smrg } 16481450c749Smrg break; 1649659607e0Smrg 16501450c749Smrg case PROT_VALUMOUSESCROLL: /* Kensington ValuMouseScroll */ 1651659607e0Smrg buttons = ((int)(pBuf[0] & 0x20) >> 3) 1652659607e0Smrg | ((int)(pBuf[0] & 0x10) >> 4) 1653659607e0Smrg | ((int)(pBuf[3] & 0x10) >> 3); 1654fecac299Smrg dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 1655fecac299Smrg dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 16561450c749Smrg dz = (pBuf[3] & 0x08) ? ((int)(pBuf[3] & 0x0F) - 0x10) : 1657659607e0Smrg ((int)(pBuf[3] & 0x0F)); 16581450c749Smrg break; 1659659607e0Smrg 16601450c749Smrg default: /* There's a table error */ 1661659607e0Smrg#ifdef EXTMOUSEDEBUG 16621450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "mouse table error\n"); 1663659607e0Smrg#endif 16641450c749Smrg continue; 16651450c749Smrg } 1666659607e0Smrg#ifdef EXTMOUSEDEBUG 16671450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "packet"); 16681450c749Smrg for ( j=0; j < pBufP; j++) 16691450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, " %x",pBuf[j]); 16701450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "\n"); 1671659607e0Smrg#endif 1672659607e0Smrg 1673659607e0Smrgpost_event: 1674659607e0Smrg#ifdef EXTMOUSEDEBUG 16751450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "dx=%i dy=%i dz=%i dw=%i buttons=%x\n",dx,dy,dz,dw,buttons); 1676659607e0Smrg#endif 16771450c749Smrg /* When auto-probing check if data makes sense */ 16781450c749Smrg if (pMse->checkMovements && pMse->autoProbe) 16791450c749Smrg pMse->checkMovements(pInfo,dx,dy); 16801450c749Smrg /* post an event */ 16811450c749Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 16821450c749Smrg 16831450c749Smrg /* 16841450c749Smrg * We don't reset pBufP here yet, as there may be an additional data 16851450c749Smrg * byte in some protocols. See above. 16861450c749Smrg */ 1687659607e0Smrg } 1688659607e0Smrg pMse->protoBufTail = pBufP; 1689659607e0Smrg} 1690659607e0Smrg 1691659607e0Smrg/* 1692659607e0Smrg * MouseCtrl -- 1693f5c3fc63Smrg * Alter the control parameters for the mouse. Note that all 1694f5c3fc63Smrg * settings are now handled by dix. 1695659607e0Smrg */ 1696659607e0Smrg 1697659607e0Smrgstatic void 1698659607e0SmrgMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl) 1699659607e0Smrg{ 1700f5c3fc63Smrg /* This function intentionally left blank */ 1701659607e0Smrg} 1702659607e0Smrg 1703659607e0Smrg/* 1704659607e0Smrg *************************************************************************** 1705659607e0Smrg * 1706659607e0Smrg * MouseProc -- 1707659607e0Smrg * 1708659607e0Smrg *************************************************************************** 1709659607e0Smrg */ 1710659607e0Smrg 1711659607e0Smrgstatic int 1712659607e0SmrgMouseProc(DeviceIntPtr device, int what) 1713659607e0Smrg{ 1714659607e0Smrg InputInfoPtr pInfo; 1715659607e0Smrg MouseDevPtr pMse; 1716659607e0Smrg mousePrivPtr mPriv; 1717659607e0Smrg unsigned char map[MSE_MAXBUTTONS + 1]; 1718659607e0Smrg int i; 1719fecac299Smrg Atom btn_labels[MSE_MAXBUTTONS] = {0}; 1720fecac299Smrg Atom axes_labels[2] = { 0, 0 }; 1721fecac299Smrg 1722659607e0Smrg pInfo = device->public.devicePrivate; 1723659607e0Smrg pMse = pInfo->private; 1724659607e0Smrg pMse->device = device; 1725659607e0Smrg 1726659607e0Smrg switch (what) 1727659607e0Smrg { 1728659607e0Smrg case DEVICE_INIT: 17291450c749Smrg device->public.on = FALSE; 17301450c749Smrg /* 17311450c749Smrg * [KAZU-241097] We don't know exactly how many buttons the 17321450c749Smrg * device has, so setup the map with the maximum number. 17331450c749Smrg */ 17341450c749Smrg for (i = 0; i < MSE_MAXBUTTONS; i++) 17351450c749Smrg map[i + 1] = i + 1; 17361450c749Smrg 17371450c749Smrg MouseInitButtonLabels(btn_labels); 17381450c749Smrg axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 17391450c749Smrg axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 17401450c749Smrg 17411450c749Smrg InitPointerDeviceStruct((DevicePtr)device, map, 17421450c749Smrg min(pMse->buttons, MSE_MAXBUTTONS), 1743fecac299Smrg btn_labels, 1744659607e0Smrg pMse->Ctrl, 17451450c749Smrg GetMotionHistorySize(), 2, 17461450c749Smrg axes_labels 1747659607e0Smrg ); 1748659607e0Smrg 17491450c749Smrg /* X valuator */ 17501450c749Smrg xf86InitValuatorAxisStruct(device, 0, 1751fecac299Smrg axes_labels[0], 1752dd4cbfe8Smrg -1, -1, 1, 0, 1 1753dd4cbfe8Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 1754dd4cbfe8Smrg , Relative 1755dd4cbfe8Smrg#endif 1756dd4cbfe8Smrg ); 17571450c749Smrg xf86InitValuatorDefaults(device, 0); 17581450c749Smrg /* Y valuator */ 17591450c749Smrg xf86InitValuatorAxisStruct(device, 1, 1760fecac299Smrg axes_labels[1], 1761dd4cbfe8Smrg -1, -1, 1, 0, 1 1762dd4cbfe8Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 1763dd4cbfe8Smrg , Relative 1764659607e0Smrg#endif 1765dd4cbfe8Smrg ); 17661450c749Smrg xf86InitValuatorDefaults(device, 1); 1767659607e0Smrg 1768659607e0Smrg#ifdef EXTMOUSEDEBUG 17691450c749Smrg ErrorF("assigning %p name=%s\n", device, pInfo->name); 1770659607e0Smrg#endif 17711450c749Smrg MouseInitProperties(device); 17721450c749Smrg break; 1773659607e0Smrg 1774659607e0Smrg case DEVICE_ON: 1775352aa7aeSmrg pInfo->fd = xf86OpenSerial(pInfo->options); 1776352aa7aeSmrg if (pInfo->fd == -1) 1777352aa7aeSmrg xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 1778352aa7aeSmrg else { 17795ddc3750Smrg#if defined(__NetBSD__) && defined(WSCONS_SUPPORT) && defined(WSMOUSEIO_SETVERSION) 1780352aa7aeSmrg int version = WSMOUSE_EVENT_VERSION; 1781352aa7aeSmrg if (ioctl(pInfo->fd, WSMOUSEIO_SETVERSION, &version) == -1) 1782352aa7aeSmrg xf86Msg(X_WARNING, "%s: cannot set version\n", pInfo->name); 17835ddc3750Smrg#endif 1784352aa7aeSmrg if (pMse->xisbscale) 1785352aa7aeSmrg pMse->buffer = XisbNew(pInfo->fd, pMse->xisbscale * 4); 1786352aa7aeSmrg else 1787352aa7aeSmrg pMse->buffer = XisbNew(pInfo->fd, 64); 1788352aa7aeSmrg if (!pMse->buffer) { 1789352aa7aeSmrg xf86CloseSerial(pInfo->fd); 1790352aa7aeSmrg pInfo->fd = -1; 1791352aa7aeSmrg } else { 1792352aa7aeSmrg if (!SetupMouse(pInfo)) { 1793352aa7aeSmrg xf86CloseSerial(pInfo->fd); 1794352aa7aeSmrg pInfo->fd = -1; 1795352aa7aeSmrg XisbFree(pMse->buffer); 1796352aa7aeSmrg pMse->buffer = NULL; 1797352aa7aeSmrg } else { 1798352aa7aeSmrg mPriv = (mousePrivPtr)pMse->mousePriv; 1799352aa7aeSmrg if (mPriv != NULL) { 1800352aa7aeSmrg if ( pMse->protocolID != PROT_AUTO) { 1801352aa7aeSmrg pMse->inSync = TRUE; /* @@@ */ 1802352aa7aeSmrg if (mPriv->soft) 1803352aa7aeSmrg mPriv->autoState = AUTOPROBE_GOOD; 1804352aa7aeSmrg else 1805352aa7aeSmrg mPriv->autoState = AUTOPROBE_H_GOOD; 1806352aa7aeSmrg } else { 1807352aa7aeSmrg if (mPriv->soft) 1808352aa7aeSmrg mPriv->autoState = AUTOPROBE_NOPROTO; 1809352aa7aeSmrg else 1810352aa7aeSmrg mPriv->autoState = AUTOPROBE_H_NOPROTO; 1811352aa7aeSmrg } 1812352aa7aeSmrg } 1813352aa7aeSmrg xf86FlushInput(pInfo->fd); 1814352aa7aeSmrg xf86AddEnabledDevice(pInfo); 1815352aa7aeSmrg if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) { 1816352aa7aeSmrg RegisterBlockAndWakeupHandlers (MouseBlockHandler, 1817352aa7aeSmrg MouseWakeupHandler, 1818352aa7aeSmrg (pointer) pInfo); 1819352aa7aeSmrg } 1820352aa7aeSmrg } 1821352aa7aeSmrg } 1822352aa7aeSmrg } 1823352aa7aeSmrg pMse->lastButtons = 0; 1824352aa7aeSmrg pMse->lastMappedButtons = 0; 1825352aa7aeSmrg pMse->emulateState = 0; 1826352aa7aeSmrg pMse->emulate3Pending = FALSE; 1827352aa7aeSmrg pMse->wheelButtonExpires = GetTimeInMillis (); 1828352aa7aeSmrg device->public.on = TRUE; 1829352aa7aeSmrg FlushButtons(pMse); 1830352aa7aeSmrg break; 18311450c749Smrg 1832659607e0Smrg case DEVICE_OFF: 18331450c749Smrg if (pInfo->fd != -1) { 18341450c749Smrg xf86RemoveEnabledDevice(pInfo); 18351450c749Smrg if (pMse->buffer) { 18361450c749Smrg XisbFree(pMse->buffer); 18371450c749Smrg pMse->buffer = NULL; 18381450c749Smrg } 18391450c749Smrg xf86CloseSerial(pInfo->fd); 18401450c749Smrg pInfo->fd = -1; 18411450c749Smrg if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) 18421450c749Smrg { 18431450c749Smrg RemoveBlockAndWakeupHandlers (MouseBlockHandler, 18441450c749Smrg MouseWakeupHandler, 18451450c749Smrg (pointer) pInfo); 18461450c749Smrg } 18471450c749Smrg } 18481450c749Smrg device->public.on = FALSE; 18491450c749Smrg break; 1850f5c3fc63Smrg case DEVICE_CLOSE: 18511450c749Smrg free(pMse->mousePriv); 18521450c749Smrg pMse->mousePriv = NULL; 18531450c749Smrg break; 18541450c749Smrg 18551450c749Smrg default: 18561450c749Smrg return BadValue; 1857659607e0Smrg } 1858659607e0Smrg return Success; 1859659607e0Smrg} 1860659607e0Smrg 1861659607e0Smrg/********************************************************************** 1862659607e0Smrg * 1863659607e0Smrg * FlushButtons -- reset button states. 1864659607e0Smrg * 1865659607e0Smrg **********************************************************************/ 1866659607e0Smrg 1867659607e0Smrgstatic void 1868659607e0SmrgFlushButtons(MouseDevPtr pMse) 1869659607e0Smrg{ 1870659607e0Smrg pMse->lastButtons = 0; 1871659607e0Smrg pMse->lastMappedButtons = 0; 1872659607e0Smrg} 1873659607e0Smrg 1874659607e0Smrg/********************************************************************** 1875659607e0Smrg * 1876659607e0Smrg * Emulate3Button support code 1877659607e0Smrg * 1878659607e0Smrg **********************************************************************/ 1879659607e0Smrg 1880659607e0Smrg 1881659607e0Smrg/* 1882659607e0Smrg * Lets create a simple finite-state machine for 3 button emulation: 1883659607e0Smrg * 1884659607e0Smrg * We track buttons 1 and 3 (left and right). There are 11 states: 1885659607e0Smrg * 0 ground - initial state 1886659607e0Smrg * 1 delayed left - left pressed, waiting for right 1887659607e0Smrg * 2 delayed right - right pressed, waiting for left 1888659607e0Smrg * 3 pressed middle - right and left pressed, emulated middle sent 1889659607e0Smrg * 4 pressed left - left pressed and sent 1890659607e0Smrg * 5 pressed right - right pressed and sent 1891659607e0Smrg * 6 released left - left released after emulated middle 1892659607e0Smrg * 7 released right - right released after emulated middle 1893659607e0Smrg * 8 repressed left - left pressed after released left 1894659607e0Smrg * 9 repressed right - right pressed after released right 1895659607e0Smrg * 10 pressed both - both pressed, not emulating middle 1896659607e0Smrg * 1897659607e0Smrg * At each state, we need handlers for the following events 1898659607e0Smrg * 0: no buttons down 1899659607e0Smrg * 1: left button down 1900659607e0Smrg * 2: right button down 1901659607e0Smrg * 3: both buttons down 1902659607e0Smrg * 4: emulate3Timeout passed without a button change 1903659607e0Smrg * Note that button events are not deltas, they are the set of buttons being 1904659607e0Smrg * pressed now. It's possible (ie, mouse hardware does it) to go from (eg) 1905659607e0Smrg * left down to right down without anything in between, so all cases must be 1906659607e0Smrg * handled. 1907659607e0Smrg * 1908659607e0Smrg * a handler consists of three values: 1909659607e0Smrg * 0: action1 1910659607e0Smrg * 1: action2 1911659607e0Smrg * 2: new emulation state 1912659607e0Smrg * 1913659607e0Smrg * action > 0: ButtonPress 1914659607e0Smrg * action = 0: nothing 1915659607e0Smrg * action < 0: ButtonRelease 1916659607e0Smrg * 19174d6d3f96Smrg * The comment preceding each section is the current emulation state. 1918659607e0Smrg * The comments to the right are of the form 1919659607e0Smrg * <button state> (<events>) -> <new emulation state> 1920659607e0Smrg * which should be read as 1921659607e0Smrg * If the buttons are in <button state>, generate <events> then go to 1922659607e0Smrg * <new emulation state>. 1923659607e0Smrg */ 1924659607e0Smrgstatic signed char stateTab[11][5][3] = { 1925659607e0Smrg/* 0 ground */ 1926659607e0Smrg { 1927659607e0Smrg { 0, 0, 0 }, /* nothing -> ground (no change) */ 1928659607e0Smrg { 0, 0, 1 }, /* left -> delayed left */ 1929659607e0Smrg { 0, 0, 2 }, /* right -> delayed right */ 1930659607e0Smrg { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ 1931659607e0Smrg { 0, 0, -1 } /* timeout N/A */ 1932659607e0Smrg }, 1933659607e0Smrg/* 1 delayed left */ 1934659607e0Smrg { 1935659607e0Smrg { 1, -1, 0 }, /* nothing (left event) -> ground */ 1936659607e0Smrg { 0, 0, 1 }, /* left -> delayed left (no change) */ 1937659607e0Smrg { 1, -1, 2 }, /* right (left event) -> delayed right */ 1938659607e0Smrg { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ 1939659607e0Smrg { 1, 0, 4 }, /* timeout (left press) -> pressed left */ 1940659607e0Smrg }, 1941659607e0Smrg/* 2 delayed right */ 1942659607e0Smrg { 1943659607e0Smrg { 3, -3, 0 }, /* nothing (right event) -> ground */ 1944659607e0Smrg { 3, -3, 1 }, /* left (right event) -> delayed left (no change) */ 1945659607e0Smrg { 0, 0, 2 }, /* right -> delayed right (no change) */ 1946659607e0Smrg { 2, 0, 3 }, /* left & right (middle press) -> pressed middle */ 1947659607e0Smrg { 3, 0, 5 }, /* timeout (right press) -> pressed right */ 1948659607e0Smrg }, 1949659607e0Smrg/* 3 pressed middle */ 1950659607e0Smrg { 1951659607e0Smrg { -2, 0, 0 }, /* nothing (middle release) -> ground */ 1952659607e0Smrg { 0, 0, 7 }, /* left -> released right */ 1953659607e0Smrg { 0, 0, 6 }, /* right -> released left */ 1954659607e0Smrg { 0, 0, 3 }, /* left & right -> pressed middle (no change) */ 1955659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 1956659607e0Smrg }, 1957659607e0Smrg/* 4 pressed left */ 1958659607e0Smrg { 1959659607e0Smrg { -1, 0, 0 }, /* nothing (left release) -> ground */ 1960659607e0Smrg { 0, 0, 4 }, /* left -> pressed left (no change) */ 1961659607e0Smrg { -1, 0, 2 }, /* right (left release) -> delayed right */ 1962659607e0Smrg { 3, 0, 10 }, /* left & right (right press) -> pressed both */ 1963659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 1964659607e0Smrg }, 1965659607e0Smrg/* 5 pressed right */ 1966659607e0Smrg { 1967659607e0Smrg { -3, 0, 0 }, /* nothing (right release) -> ground */ 1968659607e0Smrg { -3, 0, 1 }, /* left (right release) -> delayed left */ 1969659607e0Smrg { 0, 0, 5 }, /* right -> pressed right (no change) */ 1970659607e0Smrg { 1, 0, 10 }, /* left & right (left press) -> pressed both */ 1971659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 1972659607e0Smrg }, 1973659607e0Smrg/* 6 released left */ 1974659607e0Smrg { 1975659607e0Smrg { -2, 0, 0 }, /* nothing (middle release) -> ground */ 1976659607e0Smrg { -2, 0, 1 }, /* left (middle release) -> delayed left */ 1977659607e0Smrg { 0, 0, 6 }, /* right -> released left (no change) */ 1978659607e0Smrg { 1, 0, 8 }, /* left & right (left press) -> repressed left */ 1979659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 1980659607e0Smrg }, 1981659607e0Smrg/* 7 released right */ 1982659607e0Smrg { 1983659607e0Smrg { -2, 0, 0 }, /* nothing (middle release) -> ground */ 1984659607e0Smrg { 0, 0, 7 }, /* left -> released right (no change) */ 1985659607e0Smrg { -2, 0, 2 }, /* right (middle release) -> delayed right */ 1986659607e0Smrg { 3, 0, 9 }, /* left & right (right press) -> repressed right */ 1987659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 1988659607e0Smrg }, 1989659607e0Smrg/* 8 repressed left */ 1990659607e0Smrg { 1991659607e0Smrg { -2, -1, 0 }, /* nothing (middle release, left release) -> ground */ 1992659607e0Smrg { -2, 0, 4 }, /* left (middle release) -> pressed left */ 1993659607e0Smrg { -1, 0, 6 }, /* right (left release) -> released left */ 1994659607e0Smrg { 0, 0, 8 }, /* left & right -> repressed left (no change) */ 1995659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 1996659607e0Smrg }, 1997659607e0Smrg/* 9 repressed right */ 1998659607e0Smrg { 1999659607e0Smrg { -2, -3, 0 }, /* nothing (middle release, right release) -> ground */ 2000659607e0Smrg { -3, 0, 7 }, /* left (right release) -> released right */ 2001659607e0Smrg { -2, 0, 5 }, /* right (middle release) -> pressed right */ 2002659607e0Smrg { 0, 0, 9 }, /* left & right -> repressed right (no change) */ 2003659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 2004659607e0Smrg }, 2005659607e0Smrg/* 10 pressed both */ 2006659607e0Smrg { 2007659607e0Smrg { -1, -3, 0 }, /* nothing (left release, right release) -> ground */ 2008659607e0Smrg { -3, 0, 4 }, /* left (right release) -> pressed left */ 2009659607e0Smrg { -1, 0, 5 }, /* right (left release) -> pressed right */ 2010659607e0Smrg { 0, 0, 10 }, /* left & right -> pressed both (no change) */ 2011659607e0Smrg { 0, 0, -1 }, /* timeout N/A */ 2012659607e0Smrg }, 2013659607e0Smrg}; 2014659607e0Smrg 2015659607e0Smrg/* 2016659607e0Smrg * Table to allow quick reversal of natural button mapping to correct mapping 2017659607e0Smrg */ 2018659607e0Smrg 2019659607e0Smrg/* 2020659607e0Smrg * [JCH-96/01/21] The ALPS GlidePoint pad extends the MS protocol 2021659607e0Smrg * with a fourth button activated by tapping the PAD. 2022659607e0Smrg * The 2nd line corresponds to 4th button on; the drv sends 2023659607e0Smrg * the buttons in the following map (MSBit described first) : 2024659607e0Smrg * 0 | 4th | 1st | 2nd | 3rd 2025659607e0Smrg * And we remap them (MSBit described first) : 2026659607e0Smrg * 0 | 4th | 3rd | 2nd | 1st 2027659607e0Smrg */ 2028659607e0Smrgstatic char reverseMap[16] = { 0, 4, 2, 6, 20291450c749Smrg 1, 5, 3, 7, 20301450c749Smrg 8, 12, 10, 14, 20311450c749Smrg 9, 13, 11, 15 }; 2032659607e0Smrg 20331450c749Smrgstatic char hitachMap[16] = { 0, 2, 1, 3, 20341450c749Smrg 8, 10, 9, 11, 20351450c749Smrg 4, 6, 5, 7, 20361450c749Smrg 12, 14, 13, 15 }; 2037659607e0Smrg 20381450c749Smrg#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f]) 2039659607e0Smrg 2040659607e0Smrgstatic CARD32 2041659607e0SmrgbuttonTimer(InputInfoPtr pInfo) 2042659607e0Smrg{ 2043659607e0Smrg MouseDevPtr pMse; 20441468c73eSmrg#if !HAVE_THREADED_INPUT 20451450c749Smrg int sigstate; 20461468c73eSmrg#endif 2047659607e0Smrg int id; 2048659607e0Smrg 2049659607e0Smrg pMse = pInfo->private; 2050659607e0Smrg 20511468c73eSmrg#if HAVE_THREADED_INPUT 20521468c73eSmrg input_lock(); 20531468c73eSmrg#else 2054659607e0Smrg sigstate = xf86BlockSIGIO (); 20551468c73eSmrg#endif 2056659607e0Smrg 2057659607e0Smrg pMse->emulate3Pending = FALSE; 2058659607e0Smrg if ((id = stateTab[pMse->emulateState][4][0]) != 0) { 2059659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0); 2060659607e0Smrg pMse->emulateState = stateTab[pMse->emulateState][4][2]; 2061659607e0Smrg } else { 2062352aa7aeSmrg LogMessageVerbSigSafe(X_WARNING, -1, 2063352aa7aeSmrg "Got unexpected buttonTimer in state %d\n", pMse->emulateState); 2064659607e0Smrg } 2065659607e0Smrg 20661468c73eSmrg#if HAVE_THREADED_INPUT 20671468c73eSmrg input_unlock(); 20681468c73eSmrg#else 2069659607e0Smrg xf86UnblockSIGIO (sigstate); 20701468c73eSmrg#endif 2071659607e0Smrg return 0; 2072659607e0Smrg} 2073659607e0Smrg 20741450c749Smrgstatic void 20751450c749SmrgEmulate3ButtonsSetEnabled(InputInfoPtr pInfo, Bool enable) 20761450c749Smrg{ 20771450c749Smrg MouseDevPtr pMse = pInfo->private; 20781450c749Smrg 20791450c749Smrg if (pMse->emulate3Buttons == enable) 20801450c749Smrg return; 20811450c749Smrg 20821450c749Smrg pMse->emulate3Buttons = enable; 20831450c749Smrg 20841450c749Smrg if (enable) { 20851450c749Smrg pMse->emulateState = 0; 20861450c749Smrg pMse->emulate3Pending = FALSE; 20871450c749Smrg pMse->emulate3ButtonsSoft = FALSE; /* specifically requested now */ 20881450c749Smrg 20891450c749Smrg RegisterBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler, 20901450c749Smrg (pointer) pInfo); 20911450c749Smrg } else { 20921450c749Smrg if (pMse->emulate3Pending) 20931450c749Smrg buttonTimer(pInfo); 20941450c749Smrg 20951450c749Smrg RemoveBlockAndWakeupHandlers (MouseBlockHandler, MouseWakeupHandler, 20961450c749Smrg (pointer) pInfo); 20971450c749Smrg } 20981450c749Smrg} 20991450c749Smrg 2100659607e0Smrgstatic Bool 2101659607e0SmrgEmulate3ButtonsSoft(InputInfoPtr pInfo) 2102659607e0Smrg{ 2103659607e0Smrg MouseDevPtr pMse = pInfo->private; 2104659607e0Smrg 2105659607e0Smrg if (!pMse->emulate3ButtonsSoft) 21061450c749Smrg return TRUE; 2107659607e0Smrg 21087022890bSmartin#if defined(__NetBSD__) && defined(WSCONS_SUPPORT) 2109352aa7aeSmrg /* 2110352aa7aeSmrg * On NetBSD a wsmouse is a multiplexed device. Imagine a notebook 2111352aa7aeSmrg * with two-button mousepad, and an external USB mouse plugged in 2112352aa7aeSmrg * temporarily. After using button 3 on the external mouse and 2113352aa7aeSmrg * unplugging it again, the mousepad will still need to emulate 2114352aa7aeSmrg * 3 buttons. 2115352aa7aeSmrg */ 2116352aa7aeSmrg return TRUE; 2117352aa7aeSmrg#else 2118352aa7aeSmrg LogMessageVerbSigSafe(X_INFO, 4, 2119352aa7aeSmrg "mouse: 3rd Button detected: disabling emulate3Button\n"); 2120fecac299Smrg 21211450c749Smrg Emulate3ButtonsSetEnabled(pInfo, FALSE); 2122fecac299Smrg 2123659607e0Smrg return FALSE; 2124352aa7aeSmrg#endif 2125659607e0Smrg} 2126659607e0Smrg 21271468c73eSmrgstatic void MouseBlockHandler(BLOCK_HANDLER_ARGS) 2128659607e0Smrg{ 2129659607e0Smrg InputInfoPtr pInfo = (InputInfoPtr) data; 21301450c749Smrg MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 21311450c749Smrg int ms; 2132659607e0Smrg 2133659607e0Smrg if (pMse->emulate3Pending) 2134659607e0Smrg { 21351450c749Smrg ms = pMse->emulate3Expires - GetTimeInMillis (); 21361450c749Smrg if (ms <= 0) 21371450c749Smrg ms = 0; 21381450c749Smrg AdjustWaitForDelay (waitTime, ms); 2139659607e0Smrg } 2140659607e0Smrg} 2141659607e0Smrg 21421468c73eSmrgstatic void MouseWakeupHandler(WAKEUP_HANDLER_ARGS) 2143659607e0Smrg{ 2144659607e0Smrg InputInfoPtr pInfo = (InputInfoPtr) data; 21451450c749Smrg MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 21461450c749Smrg int ms; 21471450c749Smrg 2148659607e0Smrg if (pMse->emulate3Pending) 2149659607e0Smrg { 21501450c749Smrg ms = pMse->emulate3Expires - GetTimeInMillis (); 21511450c749Smrg if (ms <= 0) 21521450c749Smrg buttonTimer (pInfo); 2153659607e0Smrg } 2154659607e0Smrg} 2155659607e0Smrg 2156659607e0Smrg/******************************************************************* 2157659607e0Smrg * 2158659607e0Smrg * Post mouse events 2159659607e0Smrg * 2160659607e0Smrg *******************************************************************/ 2161659607e0Smrg 2162659607e0Smrgstatic void 2163659607e0SmrgMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy) 2164659607e0Smrg{ 2165659607e0Smrg MouseDevPtr pMse; 2166659607e0Smrg int emulateButtons; 2167659607e0Smrg int id, change; 2168659607e0Smrg int emuWheelDelta, emuWheelButton, emuWheelButtonMask; 2169659607e0Smrg int wheelButtonMask; 2170659607e0Smrg int ms; 2171659607e0Smrg 2172659607e0Smrg pMse = pInfo->private; 2173659607e0Smrg 2174659607e0Smrg change = buttons ^ pMse->lastMappedButtons; 2175659607e0Smrg pMse->lastMappedButtons = buttons; 2176659607e0Smrg 2177659607e0Smrg /* Do single button double click */ 2178659607e0Smrg if (pMse->doubleClickSourceButtonMask) { 2179659607e0Smrg if (buttons & pMse->doubleClickSourceButtonMask) { 2180659607e0Smrg if (!(pMse->doubleClickOldSourceState)) { 2181352aa7aeSmrg /* double-click button has just been pressed. 2182352aa7aeSmrg * Ignore it if target button is already down. 2183659607e0Smrg */ 2184659607e0Smrg if (!(buttons & pMse->doubleClickTargetButtonMask)) { 2185659607e0Smrg /* Target button isn't down, so send a double-click */ 2186659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 1, 0, 0); 2187659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 0, 0, 0); 2188659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 1, 0, 0); 2189659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, pMse->doubleClickTargetButton, 0, 0, 0); 2190659607e0Smrg } 2191659607e0Smrg } 2192659607e0Smrg pMse->doubleClickOldSourceState = 1; 2193659607e0Smrg } 2194659607e0Smrg else 2195659607e0Smrg pMse->doubleClickOldSourceState = 0; 2196659607e0Smrg 2197659607e0Smrg /* Whatever happened, mask the double-click button so it doesn't get 2198659607e0Smrg * processed as a normal button as well. 2199659607e0Smrg */ 2200659607e0Smrg buttons &= ~(pMse->doubleClickSourceButtonMask); 2201659607e0Smrg change &= ~(pMse->doubleClickSourceButtonMask); 2202659607e0Smrg } 2203659607e0Smrg 2204659607e0Smrg if (pMse->emulateWheel) { 22051450c749Smrg /* Emulate wheel button handling */ 22061450c749Smrg if(pMse->wheelButton == 0) 22071450c749Smrg wheelButtonMask = 0; 22081450c749Smrg else 22091450c749Smrg wheelButtonMask = 1 << (pMse->wheelButton - 1); 2210659607e0Smrg 22111450c749Smrg if (change & wheelButtonMask) { 22121450c749Smrg if (buttons & wheelButtonMask) { 22131450c749Smrg /* Start timeout handling */ 22141450c749Smrg pMse->wheelButtonExpires = GetTimeInMillis () + pMse->wheelButtonTimeout; 22151450c749Smrg ms = - pMse->wheelButtonTimeout; 22161450c749Smrg } else { 22171450c749Smrg ms = pMse->wheelButtonExpires - GetTimeInMillis (); 22181450c749Smrg 22191450c749Smrg if (0 < ms) { 22201450c749Smrg /* 22211450c749Smrg * If the button is released early enough emit the button 22221450c749Smrg * press/release events 22231450c749Smrg */ 2224352aa7aeSmrg xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 2225352aa7aeSmrg 1, 0, 0); 2226352aa7aeSmrg xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 2227352aa7aeSmrg 0, 0, 0); 22281450c749Smrg } 22291450c749Smrg } 22301450c749Smrg } else 22311450c749Smrg ms = pMse->wheelButtonExpires - GetTimeInMillis (); 22321450c749Smrg 22331450c749Smrg /* Intercept wheel emulation if the necessary button is depressed or 2234fecac299Smrg if no button is necessary */ 22351450c749Smrg if ((buttons & wheelButtonMask) || wheelButtonMask==0) { 22361450c749Smrg if (ms <= 0 || wheelButtonMask==0) { 22371450c749Smrg /* Y axis movement */ 22381450c749Smrg if (pMse->negativeY != MSE_NOAXISMAP) { 22391450c749Smrg pMse->wheelYDistance += dy; 22401450c749Smrg if (pMse->wheelYDistance < 0) { 22411450c749Smrg emuWheelDelta = -pMse->wheelInertia; 22421450c749Smrg emuWheelButton = pMse->negativeY; 22431450c749Smrg } else { 22441450c749Smrg emuWheelDelta = pMse->wheelInertia; 22451450c749Smrg emuWheelButton = pMse->positiveY; 22461450c749Smrg } 22471450c749Smrg emuWheelButtonMask = 1 << (emuWheelButton - 1); 22481450c749Smrg while (abs(pMse->wheelYDistance) > pMse->wheelInertia) { 22491450c749Smrg pMse->wheelYDistance -= emuWheelDelta; 22501450c749Smrg 22511450c749Smrg pMse->wheelXDistance = 0; 22521450c749Smrg /* 22531450c749Smrg * Synthesize the press and release, but not when 22541450c749Smrg * the button to be synthesized is already pressed 22551450c749Smrg * "for real". 22561450c749Smrg */ 22571450c749Smrg if (!(emuWheelButtonMask & buttons) || 22581450c749Smrg (emuWheelButtonMask & wheelButtonMask)) { 2259352aa7aeSmrg xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2260352aa7aeSmrg 1, 0, 0); 2261352aa7aeSmrg xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2262352aa7aeSmrg 0, 0, 0); 22631450c749Smrg } 22641450c749Smrg } 22651450c749Smrg } 2266659607e0Smrg 22671450c749Smrg /* X axis movement */ 22681450c749Smrg if (pMse->negativeX != MSE_NOAXISMAP) { 22691450c749Smrg pMse->wheelXDistance += dx; 22701450c749Smrg if (pMse->wheelXDistance < 0) { 22711450c749Smrg emuWheelDelta = -pMse->wheelInertia; 22721450c749Smrg emuWheelButton = pMse->negativeX; 22731450c749Smrg } else { 22741450c749Smrg emuWheelDelta = pMse->wheelInertia; 22751450c749Smrg emuWheelButton = pMse->positiveX; 22761450c749Smrg } 22771450c749Smrg emuWheelButtonMask = 1 << (emuWheelButton - 1); 22781450c749Smrg while (abs(pMse->wheelXDistance) > pMse->wheelInertia) { 22791450c749Smrg pMse->wheelXDistance -= emuWheelDelta; 22801450c749Smrg 22811450c749Smrg pMse->wheelYDistance = 0; 22821450c749Smrg /* 22831450c749Smrg * Synthesize the press and release, but not when 22841450c749Smrg * the button to be synthesized is already pressed 22851450c749Smrg * "for real". 22861450c749Smrg */ 22871450c749Smrg if (!(emuWheelButtonMask & buttons) || 22881450c749Smrg (emuWheelButtonMask & wheelButtonMask)) { 2289352aa7aeSmrg xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2290352aa7aeSmrg 1, 0, 0); 2291352aa7aeSmrg xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 2292352aa7aeSmrg 0, 0, 0); 22931450c749Smrg } 22941450c749Smrg } 22951450c749Smrg } 22961450c749Smrg } 2297659607e0Smrg 22981450c749Smrg /* Absorb the mouse movement while the wheel button is pressed. */ 22991450c749Smrg dx = 0; 23001450c749Smrg dy = 0; 23011450c749Smrg } 23021450c749Smrg /* 23031450c749Smrg * Button events for the wheel button are only emitted through 23041450c749Smrg * the timeout code. 23051450c749Smrg */ 23061450c749Smrg buttons &= ~wheelButtonMask; 23071450c749Smrg change &= ~wheelButtonMask; 2308659607e0Smrg } 2309659607e0Smrg 2310659607e0Smrg if (pMse->emulate3ButtonsSoft && pMse->emulate3Pending && (dx || dy)) 23111450c749Smrg buttonTimer(pInfo); 2312659607e0Smrg 2313659607e0Smrg if (dx || dy) 23141450c749Smrg xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy); 2315659607e0Smrg 2316659607e0Smrg if (change) { 2317659607e0Smrg 23181450c749Smrg /* 23191450c749Smrg * adjust buttons state for drag locks! 23201450c749Smrg * if there is drag locks 23211450c749Smrg */ 23221450c749Smrg if (pMse->pDragLock) { 23231450c749Smrg DragLockPtr pLock; 23241450c749Smrg int tarOfGoingDown, tarOfDown; 23251450c749Smrg int realbuttons; 23261450c749Smrg 23271450c749Smrg /* get drag lock block */ 23281450c749Smrg pLock = pMse->pDragLock; 23291450c749Smrg /* save real buttons */ 23301450c749Smrg realbuttons = buttons; 23311450c749Smrg 23321450c749Smrg /* if drag lock used */ 23331450c749Smrg 23341450c749Smrg /* state of drag lock buttons not seen always up */ 23351450c749Smrg 23361450c749Smrg buttons &= ~pLock->lockButtonsM; 23371450c749Smrg 23381450c749Smrg /* 23391450c749Smrg * if lock buttons being depressed changes state of 23401450c749Smrg * targets simulatedDown. 23411450c749Smrg */ 23421450c749Smrg tarOfGoingDown = lock2targetMap(pLock, 23431450c749Smrg realbuttons & change & pLock->lockButtonsM); 23441450c749Smrg pLock->simulatedDown ^= tarOfGoingDown; 23451450c749Smrg 23461450c749Smrg /* targets of drag locks down */ 23471450c749Smrg tarOfDown = lock2targetMap(pLock, 23481450c749Smrg realbuttons & pLock->lockButtonsM); 23491450c749Smrg 23501450c749Smrg /* 23511450c749Smrg * when simulatedDown set and target pressed, 23521450c749Smrg * simulatedDown goes false 23531450c749Smrg */ 23541450c749Smrg pLock->simulatedDown &= ~(realbuttons & change); 23551450c749Smrg 23561450c749Smrg /* 23571450c749Smrg * if master drag lock released 23581450c749Smrg * then master drag lock state on 23591450c749Smrg */ 23601450c749Smrg pLock->masterTS |= (~realbuttons & change) & pLock->masterLockM; 23611450c749Smrg 23621450c749Smrg /* if master state, buttons going down are simulatedDown */ 23631450c749Smrg if (pLock->masterTS) 23641450c749Smrg pLock->simulatedDown |= (realbuttons & change); 23651450c749Smrg 23661450c749Smrg /* if any button pressed, no longer in master drag lock state */ 23671450c749Smrg if (realbuttons & change) 23681450c749Smrg pLock->masterTS = 0; 23691450c749Smrg 23701450c749Smrg /* if simulatedDown or drag lock down, simulate down */ 23711450c749Smrg buttons |= (pLock->simulatedDown | tarOfDown); 23721450c749Smrg 23731450c749Smrg /* master button not seen */ 23741450c749Smrg buttons &= ~(pLock->masterLockM); 23751450c749Smrg 23761450c749Smrg /* buttons changed since last time */ 23771450c749Smrg change = buttons ^ pLock->lockLastButtons; 23781450c749Smrg 23791450c749Smrg /* save this time for next last time. */ 23801450c749Smrg pLock->lockLastButtons = buttons; 23811450c749Smrg } 2382659607e0Smrg 2383659607e0Smrg if (pMse->emulate3Buttons 23841450c749Smrg && (!(buttons & 0x02) || Emulate3ButtonsSoft(pInfo))) { 2385659607e0Smrg 2386659607e0Smrg /* handle all but buttons 1 & 3 normally */ 2387659607e0Smrg 2388659607e0Smrg change &= ~05; 2389659607e0Smrg 2390659607e0Smrg /* emulate the third button by the other two */ 2391659607e0Smrg 2392659607e0Smrg emulateButtons = (buttons & 01) | ((buttons &04) >> 1); 2393659607e0Smrg 2394659607e0Smrg if ((id = stateTab[pMse->emulateState][emulateButtons][0]) != 0) 2395659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0); 2396659607e0Smrg if ((id = stateTab[pMse->emulateState][emulateButtons][1]) != 0) 2397659607e0Smrg xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0); 2398659607e0Smrg 2399659607e0Smrg pMse->emulateState = 2400659607e0Smrg stateTab[pMse->emulateState][emulateButtons][2]; 2401659607e0Smrg 2402659607e0Smrg if (stateTab[pMse->emulateState][4][0] != 0) { 2403352aa7aeSmrg pMse->emulate3Expires = 2404352aa7aeSmrg GetTimeInMillis() + pMse->emulate3Timeout; 24051450c749Smrg pMse->emulate3Pending = TRUE; 2406659607e0Smrg } else { 24071450c749Smrg pMse->emulate3Pending = FALSE; 2408659607e0Smrg } 2409659607e0Smrg } 2410659607e0Smrg 24111450c749Smrg while (change) { 24121450c749Smrg id = ffs(change); 24131450c749Smrg change &= ~(1 << (id - 1)); 24141450c749Smrg xf86PostButtonEvent(pInfo->dev, 0, id, 24151450c749Smrg (buttons & (1 << (id - 1))), 0, 0); 24161450c749Smrg } 2417659607e0Smrg 2418659607e0Smrg } 2419659607e0Smrg} 2420659607e0Smrg 2421659607e0Smrgstatic void 2422659607e0SmrgMousePostEvent(InputInfoPtr pInfo, int truebuttons, 24231450c749Smrg int dx, int dy, int dz, int dw) 2424659607e0Smrg{ 2425659607e0Smrg MouseDevPtr pMse; 2426659607e0Smrg mousePrivPtr mousepriv; 2427659607e0Smrg int zbutton = 0, wbutton = 0, zbuttoncount = 0, wbuttoncount = 0; 2428659607e0Smrg int i, b, buttons = 0; 2429659607e0Smrg 2430659607e0Smrg pMse = pInfo->private; 2431659607e0Smrg mousepriv = (mousePrivPtr)pMse->mousePriv; 24321450c749Smrg 2433659607e0Smrg if (pMse->protocolID == PROT_MMHIT) 24341450c749Smrg b = reverseBits(hitachMap, truebuttons); 2435659607e0Smrg else 24361450c749Smrg b = reverseBits(reverseMap, truebuttons); 2437659607e0Smrg 2438659607e0Smrg /* Remap mouse buttons */ 2439659607e0Smrg b &= (1<<MSE_MAXBUTTONS)-1; 2440659607e0Smrg for (i = 0; b; i++) { 2441659607e0Smrg if (b & 1) 24421450c749Smrg buttons |= pMse->buttonMap[i]; 2443659607e0Smrg b >>= 1; 2444659607e0Smrg } 2445659607e0Smrg 2446659607e0Smrg /* Map the Z axis movement. */ 2447659607e0Smrg /* XXX Could this go in the conversion_proc? */ 2448659607e0Smrg switch (pMse->negativeZ) { 24491450c749Smrg case MSE_NOZMAP: /* do nothing */ 24501450c749Smrg dz = 0; 24511450c749Smrg break; 2452659607e0Smrg case MSE_MAPTOX: 24531450c749Smrg if (dz != 0) { 24541450c749Smrg dx = dz; 24551450c749Smrg dz = 0; 24561450c749Smrg } 24571450c749Smrg break; 2458659607e0Smrg case MSE_MAPTOY: 24591450c749Smrg if (dz != 0) { 24601450c749Smrg dy = dz; 24611450c749Smrg dz = 0; 24621450c749Smrg } 24631450c749Smrg break; 24641450c749Smrg default: /* buttons */ 24651450c749Smrg buttons &= ~(pMse->negativeZ | pMse->positiveZ); 24661450c749Smrg if (dz < 0) { 24671450c749Smrg zbutton = pMse->negativeZ; 24681450c749Smrg zbuttoncount = -dz; 24691450c749Smrg } else if (dz > 0) { 24701450c749Smrg zbutton = pMse->positiveZ; 24711450c749Smrg zbuttoncount = dz; 24721450c749Smrg } 24731450c749Smrg dz = 0; 24741450c749Smrg break; 2475659607e0Smrg } 2476659607e0Smrg switch (pMse->negativeW) { 24771450c749Smrg case MSE_NOZMAP: /* do nothing */ 24781450c749Smrg dw = 0; 24791450c749Smrg break; 2480659607e0Smrg case MSE_MAPTOX: 24811450c749Smrg if (dw != 0) { 24821450c749Smrg dx = dw; 24831450c749Smrg dw = 0; 24841450c749Smrg } 24851450c749Smrg break; 2486659607e0Smrg case MSE_MAPTOY: 24871450c749Smrg if (dw != 0) { 24881450c749Smrg dy = dw; 24891450c749Smrg dw = 0; 24901450c749Smrg } 24911450c749Smrg break; 24921450c749Smrg default: /* buttons */ 24931450c749Smrg buttons &= ~(pMse->negativeW | pMse->positiveW); 24941450c749Smrg if (dw < 0) { 24951450c749Smrg wbutton = pMse->negativeW; 24961450c749Smrg wbuttoncount = -dw; 24971450c749Smrg } else if (dw > 0) { 24981450c749Smrg wbutton = pMse->positiveW; 24991450c749Smrg wbuttoncount = dw; 25001450c749Smrg } 25011450c749Smrg dw = 0; 25021450c749Smrg break; 2503659607e0Smrg } 2504659607e0Smrg 2505659607e0Smrg 2506659607e0Smrg /* Apply angle offset */ 2507659607e0Smrg if (pMse->angleOffset != 0) { 25081450c749Smrg double rad = 3.141592653 * pMse->angleOffset / 180.0; 25091450c749Smrg int ndx = dx; 25101450c749Smrg dx = (int)((dx * cos(rad)) + (dy * sin(rad)) + 0.5); 25111450c749Smrg dy = (int)((dy * cos(rad)) - (ndx * sin(rad)) + 0.5); 2512659607e0Smrg } 2513659607e0Smrg 2514659607e0Smrg dx = pMse->invX * dx; 2515659607e0Smrg dy = pMse->invY * dy; 2516659607e0Smrg if (pMse->flipXY) { 25171450c749Smrg int tmp = dx; 25181450c749Smrg dx = dy; 25191450c749Smrg dy = tmp; 2520659607e0Smrg } 2521659607e0Smrg 25221450c749Smrg /* Accumulate the scaled dx, dy in the private variables 2523659607e0Smrg fracdx,fracdy and return the integer number part */ 2524659607e0Smrg if (mousepriv) { 25251450c749Smrg mousepriv->fracdx += mousepriv->sensitivity*dx; 25261450c749Smrg mousepriv->fracdy += mousepriv->sensitivity*dy; 25271450c749Smrg mousepriv->fracdx -= ( dx=(int)(mousepriv->fracdx) ); 25281450c749Smrg mousepriv->fracdy -= ( dy=(int)(mousepriv->fracdy) ); 2529659607e0Smrg } 25301450c749Smrg 2531659607e0Smrg /* If mouse wheel movement has to be mapped on a button, we need to 2532659607e0Smrg * loop for button press and release events. */ 2533659607e0Smrg do { 2534659607e0Smrg MouseDoPostEvent(pInfo, buttons | zbutton | wbutton, dx, dy); 25351450c749Smrg dx = dy = 0; 25361450c749Smrg if (zbutton || wbutton) 25371450c749Smrg MouseDoPostEvent(pInfo, buttons, 0, 0); 25381450c749Smrg if (--zbuttoncount <= 0) 25391450c749Smrg zbutton = 0; 25401450c749Smrg if (--wbuttoncount <= 0) 25411450c749Smrg wbutton = 0; 2542659607e0Smrg } while (zbutton || wbutton); 2543659607e0Smrg 2544659607e0Smrg pMse->lastButtons = truebuttons; 2545659607e0Smrg} 2546659607e0Smrg/****************************************************************** 2547659607e0Smrg * 2548659607e0Smrg * Mouse Setup Code 2549659607e0Smrg * 2550659607e0Smrg ******************************************************************/ 2551659607e0Smrg/* 2552659607e0Smrg * This array is indexed by the MouseProtocolID values, so the order of the 2553dd4cbfe8Smrg * entries must match that of the MouseProtocolID enum in mouse.h. 2554659607e0Smrg */ 2555659607e0Smrgstatic unsigned char proto[PROT_NUMPROTOS][8] = { 2556659607e0Smrg /* --header-- ---data--- packet -4th-byte- mouse */ 2557659607e0Smrg /* mask id mask id bytes mask id flags */ 25581450c749Smrg /* Serial mice */ 2559659607e0Smrg { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00, MPF_NONE }, /* MicroSoft */ 2560659607e0Smrg { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_SAFE }, /* MouseSystems */ 2561659607e0Smrg { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MMSeries */ 2562659607e0Smrg { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* Logitech */ 2563659607e0Smrg { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00, MPF_NONE }, /* MouseMan */ 2564659607e0Smrg { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MM_HitTablet */ 2565659607e0Smrg { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00, MPF_NONE }, /* GlidePoint */ 2566659607e0Smrg { 0x40, 0x40, 0x40, 0x00, 3, ~0x3f, 0x00, MPF_NONE }, /* IntelliMouse */ 2567659607e0Smrg { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00, MPF_NONE }, /* ThinkingMouse */ 2568659607e0Smrg { 0x80, 0x80, 0x80, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* ACECAD */ 2569659607e0Smrg { 0x40, 0x40, 0x40, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* ValuMouseScroll */ 25701450c749Smrg /* PS/2 variants */ 2571659607e0Smrg { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* PS/2 mouse */ 2572659607e0Smrg { 0xc8, 0x08, 0x00, 0x00, 3, 0x00, 0x00, MPF_NONE }, /* genericPS/2 mouse*/ 2573659607e0Smrg { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* IntelliMouse */ 2574659607e0Smrg { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* Explorer */ 2575659607e0Smrg { 0x80, 0x80, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* ThinkingMouse */ 2576659607e0Smrg { 0x08, 0x08, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* MouseMan+ */ 2577659607e0Smrg { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff, MPF_NONE }, /* GlidePoint */ 2578659607e0Smrg { 0x08, 0x08, 0x00, 0x00, 4, 0x00, 0xff, MPF_NONE }, /* NetMouse */ 2579659607e0Smrg { 0xc0, 0x00, 0x00, 0x00, 6, 0x00, 0xff, MPF_NONE }, /* NetScroll */ 25801450c749Smrg /* Bus Mouse */ 2581659607e0Smrg { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_NONE }, /* BusMouse */ 2582659607e0Smrg { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff, MPF_NONE }, /* Auto (dummy) */ 2583659607e0Smrg { 0xf8, 0x80, 0x00, 0x00, 8, 0x00, 0xff, MPF_NONE }, /* SysMouse */ 2584659607e0Smrg}; 2585659607e0Smrg 2586659607e0Smrg 2587659607e0Smrg/* 2588659607e0Smrg * SetupMouse -- 25891450c749Smrg * Sets up the mouse parameters 2590659607e0Smrg */ 2591659607e0Smrgstatic Bool 2592659607e0SmrgSetupMouse(InputInfoPtr pInfo) 2593659607e0Smrg{ 2594659607e0Smrg MouseDevPtr pMse; 2595659607e0Smrg int protoPara[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; 2596659607e0Smrg const char *name = NULL; 2597659607e0Smrg Bool automatic = FALSE; 2598659607e0Smrg 2599659607e0Smrg pMse = pInfo->private; 26001450c749Smrg 2601659607e0Smrg /* Handle the "Auto" protocol. */ 2602659607e0Smrg if (pMse->protocolID == PROT_AUTO) { 26031450c749Smrg /* 26041450c749Smrg * We come here when user specifies protocol "auto" in 26054d6d3f96Smrg * the configuration file or through the xf86misc extensions. 26061450c749Smrg * So we initialize autoprobing here. 26071450c749Smrg * Probe for PnP/OS mouse first. If unsuccessful 26081450c749Smrg * try to guess protocol from incoming data. 26091450c749Smrg */ 26101450c749Smrg automatic = TRUE; 26111450c749Smrg pMse->autoProbe = TRUE; 26121450c749Smrg name = autoOSProtocol(pInfo,protoPara); 26131450c749Smrg if (name) { 2614659607e0Smrg#ifdef EXTMOUSEDEBUG 26151450c749Smrg ErrorF("PnP/OS Mouse detected: %s\n",name); 26161450c749Smrg#endif 26171450c749Smrg } 2618659607e0Smrg } 2619659607e0Smrg 2620659607e0Smrg SetMouseProto(pMse, pMse->protocolID); 2621659607e0Smrg 2622659607e0Smrg if (automatic) { 26231450c749Smrg if (name) { 26241450c749Smrg /* Possible protoPara overrides from SetupAuto. */ 26254d6d3f96Smrg for (size_t i = 0; i < sizeof(pMse->protoPara); i++) 26261450c749Smrg if (protoPara[i] != -1) 26271450c749Smrg pMse->protoPara[i] = protoPara[i]; 26281450c749Smrg /* if we come here PnP/OS mouse probing was successful */ 26291450c749Smrg } else { 26301450c749Smrg /* PnP/OS mouse probing wasn't successful; we look at data */ 26311450c749Smrg } 2632659607e0Smrg } 2633659607e0Smrg 2634659607e0Smrg /* 2635659607e0Smrg * If protocol has changed fetch the default options 2636659607e0Smrg * for the new protocol. 2637659607e0Smrg */ 2638659607e0Smrg if (pMse->oldProtocolID != pMse->protocolID) { 26391450c749Smrg if ((pMse->protocolID >= 0) 26401450c749Smrg && (pMse->protocolID < PROT_NUMPROTOS) 26411450c749Smrg && mouseProtocols[pMse->protocolID].defaults) { 26421450c749Smrg pointer tmp = xf86OptionListCreate( 26431450c749Smrg mouseProtocols[pMse->protocolID].defaults, -1, 0); 26441450c749Smrg pInfo->options = xf86OptionListMerge(pInfo->options, tmp); 26451450c749Smrg } 26461450c749Smrg /* 26471450c749Smrg * If baudrate is set write it back to the option 26481450c749Smrg * list so that the serial interface code can access 26491450c749Smrg * the new value. Not set means default. 26501450c749Smrg */ 26511450c749Smrg if (pMse->baudRate) 26521450c749Smrg xf86ReplaceIntOption(pInfo->options, "BaudRate", pMse->baudRate); 26531450c749Smrg pMse->oldProtocolID = pMse->protocolID; /* hack */ 2654659607e0Smrg } 2655659607e0Smrg 2656659607e0Smrg 2657659607e0Smrg /* Set the port parameters. */ 2658659607e0Smrg if (!automatic) 26591450c749Smrg xf86SetSerial(pInfo->fd, pInfo->options); 2660659607e0Smrg 2661659607e0Smrg if (!initMouseHW(pInfo)) 26621450c749Smrg return FALSE; 2663659607e0Smrg 2664659607e0Smrg pMse->protoBufTail = 0; 2665659607e0Smrg pMse->inSync = 0; 2666659607e0Smrg 2667659607e0Smrg return TRUE; 2668659607e0Smrg} 2669659607e0Smrg 2670659607e0Smrg/******************************************************************** 2671659607e0Smrg * 2672659607e0Smrg * Mouse HW setup code 2673659607e0Smrg * 2674659607e0Smrg ********************************************************************/ 2675659607e0Smrg 2676659607e0Smrg/* 2677659607e0Smrg** The following lines take care of the Logitech MouseMan protocols. 2678659607e0Smrg** The "Logitech" protocol is for the old "series 9" Logitech products. 2679659607e0Smrg** All products since then use the "MouseMan" protocol. Some models 2680659607e0Smrg** were programmable, but most (all?) of the current models are not. 2681659607e0Smrg** 2682659607e0Smrg** NOTE: There are different versions of both MouseMan and TrackMan! 2683659607e0Smrg** Hence I add another protocol PROT_LOGIMAN, which the user can 2684352aa7aeSmrg** specify as MouseMan in an xorg.conf file. This entry was 2685659607e0Smrg** formerly handled as a special case of PROT_MS. However, people 2686659607e0Smrg** who don't have the middle button problem, can still specify 2687659607e0Smrg** Microsoft and use PROT_MS. 2688659607e0Smrg** 2689659607e0Smrg** By default, these mice should use a 3 byte Microsoft protocol 2690659607e0Smrg** plus a 4th byte for the middle button. However, the mouse might 2691659607e0Smrg** have switched to a different protocol before we use it, so I send 2692659607e0Smrg** the proper sequence just in case. 2693659607e0Smrg** 2694659607e0Smrg** NOTE: - all commands to (at least the European) MouseMan have to 2695659607e0Smrg** be sent at 1200 Baud. 2696659607e0Smrg** - each command starts with a '*'. 2697659607e0Smrg** - whenever the MouseMan receives a '*', it will switch back 26981450c749Smrg** to 1200 Baud. Hence I have to select the desired protocol 26991450c749Smrg** first, then select the baud rate. 2700659607e0Smrg** 2701659607e0Smrg** The protocols supported by the (European) MouseMan are: 2702659607e0Smrg** - 5 byte packed binary protocol, as with the Mouse Systems 2703659607e0Smrg** mouse. Selected by sequence "*U". 2704659607e0Smrg** - 2 button 3 byte MicroSoft compatible protocol. Selected 2705659607e0Smrg** by sequence "*V". 2706659607e0Smrg** - 3 button 3+1 byte MicroSoft compatible protocol (default). 2707659607e0Smrg** Selected by sequence "*X". 2708659607e0Smrg** 2709659607e0Smrg** The following baud rates are supported: 2710659607e0Smrg** - 1200 Baud (default). Selected by sequence "*n". 2711659607e0Smrg** - 9600 Baud. Selected by sequence "*q". 2712659607e0Smrg** 2713659607e0Smrg** Selecting a sample rate is no longer supported with the MouseMan! 2714659607e0Smrg** [CHRIS-211092] 2715659607e0Smrg*/ 2716659607e0Smrg 2717659607e0Smrg/* 2718659607e0Smrg * Do a reset wrap mode before reset. 2719659607e0Smrg */ 2720659607e0Smrg#define do_ps2Reset(x) { \ 2721659607e0Smrg int i = RETRY_COUNT;\ 2722659607e0Smrg while (i-- > 0) { \ 2723659607e0Smrg xf86FlushInput(x->fd); \ 2724659607e0Smrg if (ps2Reset(x)) break; \ 2725659607e0Smrg } \ 2726659607e0Smrg } 2727659607e0Smrg 27281450c749Smrg 2729659607e0Smrgstatic Bool 2730659607e0SmrginitMouseHW(InputInfoPtr pInfo) 2731659607e0Smrg{ 2732659607e0Smrg MouseDevPtr pMse = pInfo->private; 2733659607e0Smrg const char *s; 2734659607e0Smrg unsigned char c; 2735659607e0Smrg int speed; 2736659607e0Smrg pointer options; 2737659607e0Smrg unsigned char *param = NULL; 2738659607e0Smrg int paramlen = 0; 2739659607e0Smrg int count = RETRY_COUNT; 2740659607e0Smrg Bool ps2Init = TRUE; 27411450c749Smrg 2742659607e0Smrg switch (pMse->protocolID) { 27431450c749Smrg case PROT_LOGI: /* Logitech Mice */ 27441450c749Smrg /* 27451450c749Smrg * The baud rate selection command must be sent at the current 27461450c749Smrg * baud rate; try all likely settings. 27471450c749Smrg */ 27481450c749Smrg speed = pMse->baudRate; 27491450c749Smrg switch (speed) { 27501450c749Smrg case 9600: 27511450c749Smrg s = "*q"; 27521450c749Smrg break; 27531450c749Smrg case 4800: 27541450c749Smrg s = "*p"; 27551450c749Smrg break; 27561450c749Smrg case 2400: 27571450c749Smrg s = "*o"; 27581450c749Smrg break; 27591450c749Smrg case 1200: 27601450c749Smrg s = "*n"; 27611450c749Smrg break; 27621450c749Smrg default: 27631450c749Smrg /* Fallback value */ 27641450c749Smrg speed = 1200; 27651450c749Smrg s = "*n"; 27661450c749Smrg } 27671450c749Smrg xf86SetSerialSpeed(pInfo->fd, 9600); 27681450c749Smrg xf86WriteSerial(pInfo->fd, s, 2); 27691450c749Smrg usleep(100000); 27701450c749Smrg xf86SetSerialSpeed(pInfo->fd, 4800); 27711450c749Smrg xf86WriteSerial(pInfo->fd, s, 2); 27721450c749Smrg usleep(100000); 27731450c749Smrg xf86SetSerialSpeed(pInfo->fd, 2400); 27741450c749Smrg xf86WriteSerial(pInfo->fd, s, 2); 27751450c749Smrg usleep(100000); 27761450c749Smrg xf86SetSerialSpeed(pInfo->fd, 1200); 27771450c749Smrg xf86WriteSerial(pInfo->fd, s, 2); 27781450c749Smrg usleep(100000); 27791450c749Smrg xf86SetSerialSpeed(pInfo->fd, speed); 27801450c749Smrg 27811450c749Smrg /* Select MM series data format. */ 27821450c749Smrg xf86WriteSerial(pInfo->fd, "S", 1); 27831450c749Smrg usleep(100000); 27841450c749Smrg /* Set the parameters up for the MM series protocol. */ 27851450c749Smrg options = pInfo->options; 27861450c749Smrg COLLECT_INPUT_OPTIONS(pInfo, mmDefaults); 27871450c749Smrg xf86SetSerial(pInfo->fd, pInfo->options); 27881450c749Smrg pInfo->options = options; 27891450c749Smrg 27901450c749Smrg /* Select report rate/frequency. */ 27911450c749Smrg if (pMse->sampleRate <= 0) c = 'O'; /* 100 */ 27921450c749Smrg else if (pMse->sampleRate <= 15) c = 'J'; /* 10 */ 27931450c749Smrg else if (pMse->sampleRate <= 27) c = 'K'; /* 20 */ 27941450c749Smrg else if (pMse->sampleRate <= 42) c = 'L'; /* 35 */ 27951450c749Smrg else if (pMse->sampleRate <= 60) c = 'R'; /* 50 */ 27961450c749Smrg else if (pMse->sampleRate <= 85) c = 'M'; /* 67 */ 27971450c749Smrg else if (pMse->sampleRate <= 125) c = 'Q'; /* 100 */ 27981450c749Smrg else c = 'N'; /* 150 */ 27991450c749Smrg xf86WriteSerial(pInfo->fd, &c, 1); 28001450c749Smrg break; 2801659607e0Smrg 28021450c749Smrg case PROT_LOGIMAN: 28031450c749Smrg speed = pMse->baudRate; 28041450c749Smrg switch (speed) { 28051450c749Smrg case 9600: 28061450c749Smrg s = "*q"; 28071450c749Smrg break; 28081450c749Smrg case 1200: 28091450c749Smrg s = "*n"; 28101450c749Smrg break; 28111450c749Smrg default: 28121450c749Smrg /* Fallback value */ 28131450c749Smrg speed = 1200; 28141450c749Smrg s = "*n"; 28151450c749Smrg } 28161450c749Smrg xf86SetSerialSpeed(pInfo->fd, 1200); 28171450c749Smrg xf86WriteSerial(pInfo->fd, "*n", 2); 28181450c749Smrg xf86WriteSerial(pInfo->fd, "*X", 2); 28191450c749Smrg xf86WriteSerial(pInfo->fd, s, 2); 28201450c749Smrg usleep(100000); 28211450c749Smrg xf86SetSerialSpeed(pInfo->fd, speed); 28221450c749Smrg break; 2823659607e0Smrg 28241450c749Smrg case PROT_MMHIT: /* MM_HitTablet */ 28251450c749Smrg /* 28261450c749Smrg * Initialize Hitachi PUMA Plus - Model 1212E to desired settings. 28271450c749Smrg * The tablet must be configured to be in MM mode, NO parity, 28281450c749Smrg * Binary Format. pMse->sampleRate controls the sensitivity 28291450c749Smrg * of the tablet. We only use this tablet for it's 4-button puck 28301450c749Smrg * so we don't run in "Absolute Mode". 28311450c749Smrg */ 28321450c749Smrg xf86WriteSerial(pInfo->fd, "z8", 2); /* Set Parity = "NONE" */ 28331450c749Smrg usleep(50000); 28341450c749Smrg xf86WriteSerial(pInfo->fd, "zb", 2); /* Set Format = "Binary" */ 28351450c749Smrg usleep(50000); 28361450c749Smrg xf86WriteSerial(pInfo->fd, "@", 1); /* Set Report Mode = "Stream" */ 28371450c749Smrg usleep(50000); 28381450c749Smrg xf86WriteSerial(pInfo->fd, "R", 1); /* Set Output Rate = "45 rps" */ 28391450c749Smrg usleep(50000); 28401450c749Smrg xf86WriteSerial(pInfo->fd, "I\x20", 2); /* Set Incrememtal Mode "20" */ 28411450c749Smrg usleep(50000); 28421450c749Smrg xf86WriteSerial(pInfo->fd, "E", 1); /* Set Data Type = "Relative */ 28431450c749Smrg usleep(50000); 28441450c749Smrg /* 28451450c749Smrg * These sample rates translate to 'lines per inch' on the Hitachi 28461450c749Smrg * tablet. 28471450c749Smrg */ 28481450c749Smrg if (pMse->sampleRate <= 40) c = 'g'; 28491450c749Smrg else if (pMse->sampleRate <= 100) c = 'd'; 28501450c749Smrg else if (pMse->sampleRate <= 200) c = 'e'; 28511450c749Smrg else if (pMse->sampleRate <= 500) c = 'h'; 28521450c749Smrg else if (pMse->sampleRate <= 1000) c = 'j'; 28531450c749Smrg else c = 'd'; 28541450c749Smrg xf86WriteSerial(pInfo->fd, &c, 1); 28551450c749Smrg usleep(50000); 28561450c749Smrg xf86WriteSerial(pInfo->fd, "\021", 1); /* Resume DATA output */ 28571450c749Smrg break; 28581450c749Smrg 28591450c749Smrg case PROT_THINKING: /* ThinkingMouse */ 28601450c749Smrg /* This mouse may send a PnP ID string, ignore it. */ 28611450c749Smrg usleep(200000); 28621450c749Smrg xf86FlushInput(pInfo->fd); 28631450c749Smrg /* Send the command to initialize the beast. */ 28641450c749Smrg for (s = "E5E5"; *s; ++s) { 28651450c749Smrg xf86WriteSerial(pInfo->fd, s, 1); 28661450c749Smrg if ((xf86WaitForInput(pInfo->fd, 1000000) <= 0)) 28671450c749Smrg break; 28681450c749Smrg xf86ReadSerial(pInfo->fd, &c, 1); 28691450c749Smrg if (c != *s) 28701450c749Smrg break; 28711450c749Smrg } 28721450c749Smrg break; 28731450c749Smrg 28741450c749Smrg case PROT_MSC: /* MouseSystems Corp */ 28751450c749Smrg usleep(100000); 28761450c749Smrg xf86FlushInput(pInfo->fd); 28771450c749Smrg break; 28781450c749Smrg 28791450c749Smrg case PROT_ACECAD: 28801450c749Smrg /* initialize */ 28811450c749Smrg /* A nul character resets. */ 28821450c749Smrg xf86WriteSerial(pInfo->fd, "", 1); 28831450c749Smrg usleep(50000); 28841450c749Smrg /* Stream out relative mode high resolution increments of 1. */ 28851450c749Smrg xf86WriteSerial(pInfo->fd, "@EeI!", 5); 28861450c749Smrg break; 28871450c749Smrg 28881450c749Smrg case PROT_BM: /* bus/InPort mouse */ 28891450c749Smrg if (osInfo->SetBMRes) 28901450c749Smrg osInfo->SetBMRes(pInfo, pMse->protocol, pMse->sampleRate, 28911450c749Smrg pMse->resolution); 28921450c749Smrg break; 28931450c749Smrg 28941450c749Smrg case PROT_GENPS2: 28951450c749Smrg ps2Init = FALSE; 28961450c749Smrg break; 28971450c749Smrg 28981450c749Smrg case PROT_PS2: 28991450c749Smrg case PROT_GLIDEPS2: 29001450c749Smrg break; 29011450c749Smrg 29021450c749Smrg case PROT_IMPS2: /* IntelliMouse */ 29031450c749Smrg { 29041450c749Smrg static unsigned char seq[] = { 243, 200, 243, 100, 243, 80 }; 29051450c749Smrg param = seq; 29061450c749Smrg paramlen = sizeof(seq); 29071450c749Smrg } 29081450c749Smrg break; 29091450c749Smrg 29101450c749Smrg case PROT_EXPPS2: /* IntelliMouse Explorer */ 29111450c749Smrg { 29121450c749Smrg static unsigned char seq[] = { 243, 200, 243, 100, 243, 80, 29131450c749Smrg 243, 200, 243, 200, 243, 80 }; 29141450c749Smrg 29151450c749Smrg param = seq; 29161450c749Smrg paramlen = sizeof(seq); 29171450c749Smrg } 29181450c749Smrg break; 29191450c749Smrg 29201450c749Smrg case PROT_NETPS2: /* NetMouse, NetMouse Pro, Mie Mouse */ 29211450c749Smrg case PROT_NETSCPS2: /* NetScroll */ 29221450c749Smrg { 29231450c749Smrg static unsigned char seq[] = { 232, 3, 230, 230, 230, 233 }; 29241450c749Smrg 29251450c749Smrg param = seq; 29261450c749Smrg paramlen = sizeof(seq); 29271450c749Smrg } 29281450c749Smrg break; 29291450c749Smrg 29301450c749Smrg case PROT_MMPS2: /* MouseMan+, FirstMouse+ */ 29311450c749Smrg { 29321450c749Smrg static unsigned char seq[] = { 230, 232, 0, 232, 3, 232, 2, 232, 1, 29331450c749Smrg 230, 232, 3, 232, 1, 232, 2, 232, 3 }; 29341450c749Smrg param = seq; 29351450c749Smrg paramlen = sizeof(seq); 29361450c749Smrg } 29371450c749Smrg break; 29381450c749Smrg 29391450c749Smrg case PROT_THINKPS2: /* ThinkingMouse */ 29401450c749Smrg { 29411450c749Smrg static unsigned char seq[] = { 243, 10, 232, 0, 243, 20, 243, 60, 29421450c749Smrg 243, 40, 243, 20, 243, 20, 243, 60, 29431450c749Smrg 243, 40, 243, 20, 243, 20 }; 29441450c749Smrg param = seq; 29451450c749Smrg paramlen = sizeof(seq); 29461450c749Smrg } 29471450c749Smrg break; 29481450c749Smrg case PROT_SYSMOUSE: 29491450c749Smrg if (osInfo->SetMiscRes) 29501450c749Smrg osInfo->SetMiscRes(pInfo, pMse->protocol, pMse->sampleRate, 29511450c749Smrg pMse->resolution); 29521450c749Smrg break; 29531450c749Smrg 29541450c749Smrg default: 29551450c749Smrg /* Nothing to do. */ 29561450c749Smrg break; 2957659607e0Smrg } 2958659607e0Smrg 2959659607e0Smrg if (pMse->class & (MSE_PS2 | MSE_XPS2)) { 29601450c749Smrg /* 29611450c749Smrg * If one part of the PS/2 mouse initialization fails 29621450c749Smrg * redo complete initialization. There are mice which 29631450c749Smrg * have occasional problems with initialization and 29641450c749Smrg * are in an unknown state. 29651450c749Smrg */ 29661450c749Smrg if (ps2Init) { 29671450c749Smrg REDO: 29681450c749Smrg do_ps2Reset(pInfo); 29691450c749Smrg if (paramlen > 0) { 29701450c749Smrg if (!ps2SendPacket(pInfo,param,paramlen)) { 29711450c749Smrg usleep(30000); 29721450c749Smrg xf86FlushInput(pInfo->fd); 29731450c749Smrg if (!count--) 29741450c749Smrg return TRUE; 29751450c749Smrg goto REDO; 29761450c749Smrg } 29771450c749Smrg ps2GetDeviceID(pInfo); 29781450c749Smrg usleep(30000); 29791450c749Smrg xf86FlushInput(pInfo->fd); 29801450c749Smrg } 29811450c749Smrg 29821450c749Smrg if (osInfo->SetPS2Res) { 29831450c749Smrg osInfo->SetPS2Res(pInfo, pMse->protocol, pMse->sampleRate, 29841450c749Smrg pMse->resolution); 29851450c749Smrg } else { 29861450c749Smrg unsigned char c2[2]; 29871450c749Smrg 29881450c749Smrg c = 0xE6; /*230*/ /* 1:1 scaling */ 29891450c749Smrg if (!ps2SendPacket(pInfo,&c,1)) { 29901450c749Smrg if (!count--) 29911450c749Smrg return TRUE; 29921450c749Smrg goto REDO; 29931450c749Smrg } 29941450c749Smrg c2[0] = 0xF3; /*243*/ /* set sampling rate */ 29951450c749Smrg if (pMse->sampleRate > 0) { 29961450c749Smrg if (pMse->sampleRate >= 200) 29971450c749Smrg c2[1] = 200; 29981450c749Smrg else if (pMse->sampleRate >= 100) 29991450c749Smrg c2[1] = 100; 30001450c749Smrg else if (pMse->sampleRate >= 80) 30011450c749Smrg c2[1] = 80; 30021450c749Smrg else if (pMse->sampleRate >= 60) 30031450c749Smrg c2[1] = 60; 30041450c749Smrg else if (pMse->sampleRate >= 40) 30051450c749Smrg c2[1] = 40; 30061450c749Smrg else 30071450c749Smrg c2[1] = 20; 30081450c749Smrg } else { 30091450c749Smrg c2[1] = 100; 30101450c749Smrg } 30111450c749Smrg if (!ps2SendPacket(pInfo,c2,2)) { 30121450c749Smrg if (!count--) 30131450c749Smrg return TRUE; 30141450c749Smrg goto REDO; 30151450c749Smrg } 30161450c749Smrg c2[0] = 0xE8; /*232*/ /* set device resolution */ 30171450c749Smrg if (pMse->resolution > 0) { 30181450c749Smrg if (pMse->resolution >= 200) 30191450c749Smrg c2[1] = 3; 30201450c749Smrg else if (pMse->resolution >= 100) 30211450c749Smrg c2[1] = 2; 30221450c749Smrg else if (pMse->resolution >= 50) 30231450c749Smrg c2[1] = 1; 30241450c749Smrg else 30251450c749Smrg c2[1] = 0; 30261450c749Smrg } else { 30271450c749Smrg c2[1] = 3; /* used to be 2, W. uses 3 */ 30281450c749Smrg } 30291450c749Smrg if (!ps2SendPacket(pInfo,c2,2)) { 30301450c749Smrg if (!count--) 30311450c749Smrg return TRUE; 30321450c749Smrg goto REDO; 30331450c749Smrg } 30341450c749Smrg usleep(30000); 30351450c749Smrg xf86FlushInput(pInfo->fd); 30361450c749Smrg if (!ps2EnableDataReporting(pInfo)) { 30371450c749Smrg xf86Msg(X_INFO, "%s: ps2EnableDataReporting: failed\n", 30381450c749Smrg pInfo->name); 30391450c749Smrg xf86FlushInput(pInfo->fd); 30401450c749Smrg if (!count--) 30411450c749Smrg return TRUE; 30421450c749Smrg goto REDO; 30431450c749Smrg } else { 30441450c749Smrg xf86Msg(X_INFO, "%s: ps2EnableDataReporting: succeeded\n", 30451450c749Smrg pInfo->name); 30461450c749Smrg } 30471450c749Smrg } 30481450c749Smrg /* 30491450c749Smrg * The PS/2 reset handling needs to be rechecked. 30501450c749Smrg * We need to wait until after the 4.3 release. 30511450c749Smrg */ 30521450c749Smrg } 3053659607e0Smrg } else { 30541450c749Smrg if (paramlen > 0) { 30551450c749Smrg if (xf86WriteSerial(pInfo->fd, param, paramlen) != paramlen) 30561450c749Smrg xf86Msg(X_ERROR, "%s: Mouse initialization failed\n", 30571450c749Smrg pInfo->name); 30581450c749Smrg usleep(30000); 30591450c749Smrg xf86FlushInput(pInfo->fd); 30601450c749Smrg } 3061659607e0Smrg } 3062659607e0Smrg 3063659607e0Smrg return TRUE; 3064659607e0Smrg} 3065659607e0Smrg 3066659607e0Smrg#ifdef SUPPORT_MOUSE_RESET 3067659607e0Smrgstatic Bool 30681450c749SmrgmouseReset(InputInfoPtr pInfo, unsigned char val) 3069659607e0Smrg{ 3070659607e0Smrg MouseDevPtr pMse = pInfo->private; 3071659607e0Smrg mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv; 3072659607e0Smrg CARD32 prevEvent = mousepriv->lastEvent; 3073659607e0Smrg Bool expectReset = FALSE; 3074659607e0Smrg Bool ret = FALSE; 3075659607e0Smrg 3076659607e0Smrg mousepriv->lastEvent = GetTimeInMillis(); 3077659607e0Smrg 3078659607e0Smrg#ifdef EXTMOUSEDEBUG 30791450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "byte: 0x%x time: %li\n",val,mousepriv->lastEvent); 3080659607e0Smrg#endif 3081659607e0Smrg /* 3082659607e0Smrg * We believe that the following is true: 3083659607e0Smrg * When the mouse is replugged it will send a reset package 3084659607e0Smrg * It takes several seconds to replug a mouse: We don't see 3085659607e0Smrg * events for several seconds before we see the replug event package. 3086659607e0Smrg * There is no significant delay between consecutive bytes 3087659607e0Smrg * of a replug event package. 3088659607e0Smrg * There are no bytes sent after the replug event package until 3089659607e0Smrg * the mouse is reset. 3090659607e0Smrg */ 30911450c749Smrg 3092659607e0Smrg if (mousepriv->current == 0 30931450c749Smrg && (mousepriv->lastEvent - prevEvent) < 4000) 30941450c749Smrg return FALSE; 3095659607e0Smrg 3096659607e0Smrg if (mousepriv->current > 0 30971450c749Smrg && (mousepriv->lastEvent - prevEvent) >= 1000) { 30981450c749Smrg mousepriv->inReset = FALSE; 30991450c749Smrg mousepriv->current = 0; 31001450c749Smrg return FALSE; 3101659607e0Smrg } 3102659607e0Smrg 3103659607e0Smrg if (mousepriv->inReset) 31041450c749Smrg mousepriv->inReset = FALSE; 3105659607e0Smrg 3106659607e0Smrg#ifdef EXTMOUSEDEBUG 31071450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "Mouse Current: %i 0x%x\n",mousepriv->current, val); 3108659607e0Smrg#endif 31091450c749Smrg 3110eeaac534Smrg /* here we put the mouse specific reset detection */ 3111659607e0Smrg /* They need to do three things: */ 3112659607e0Smrg /* Check if byte may be a reset byte */ 3113659607e0Smrg /* If so: Set expectReset TRUE */ 3114659607e0Smrg /* If convinced: Set inReset TRUE */ 3115659607e0Smrg /* Register BlockAndWakeupHandler */ 3116659607e0Smrg 3117659607e0Smrg /* PS/2 */ 3118659607e0Smrg { 31191450c749Smrg unsigned char seq[] = { 0xaa, 0x00 }; 31201450c749Smrg int len = sizeof(seq); 3121659607e0Smrg 31221450c749Smrg if (seq[mousepriv->current] == val) 31231450c749Smrg expectReset = TRUE; 3124659607e0Smrg 31251450c749Smrg if (len == mousepriv->current + 1) { 31261450c749Smrg mousepriv->inReset = TRUE; 31271450c749Smrg mousepriv->expires = GetTimeInMillis() + 1000; 3128659607e0Smrg 3129659607e0Smrg#ifdef EXTMOUSEDEBUG 31301450c749Smrg LogMessageVerbSigSafe(X_INFO, -1, "Found PS/2 Reset string\n"); 3131659607e0Smrg#endif 31321450c749Smrg RegisterBlockAndWakeupHandlers (ps2BlockHandler, 31331450c749Smrg ps2WakeupHandler, (pointer) pInfo); 31341450c749Smrg ret = TRUE; 31351450c749Smrg } 3136659607e0Smrg } 31371450c749Smrg 31381450c749Smrg if (!expectReset) 31391450c749Smrg mousepriv->current = 0; 31401450c749Smrg else 31411450c749Smrg mousepriv->current++; 31421450c749Smrg return ret; 3143659607e0Smrg} 3144659607e0Smrg 3145659607e0Smrgstatic void 3146659607e0Smrgps2BlockHandler(pointer data, struct timeval **waitTime, 31471450c749Smrg pointer LastSelectMask) 3148659607e0Smrg{ 3149659607e0Smrg InputInfoPtr pInfo = (InputInfoPtr) data; 31501450c749Smrg MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 3151659607e0Smrg mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv; 31521450c749Smrg int ms; 3153659607e0Smrg 3154659607e0Smrg if (mousepriv->inReset) { 31551450c749Smrg ms = mousepriv->expires - GetTimeInMillis (); 31561450c749Smrg if (ms <= 0) 31571450c749Smrg ms = 0; 31581450c749Smrg AdjustWaitForDelay (waitTime, ms); 3159659607e0Smrg } else 31601450c749Smrg RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler, 31611450c749Smrg (pointer) pInfo); 3162659607e0Smrg} 3163659607e0Smrg 3164659607e0Smrgstatic void 3165659607e0Smrgps2WakeupHandler(pointer data, int i, pointer LastSelectMask) 3166659607e0Smrg{ 3167659607e0Smrg InputInfoPtr pInfo = (InputInfoPtr) data; 31681450c749Smrg MouseDevPtr pMse = (MouseDevPtr) pInfo->private; 3169659607e0Smrg mousePrivPtr mousepriv = (mousePrivPtr)pMse->mousePriv; 31701450c749Smrg int ms; 3171659607e0Smrg 31721450c749Smrg if (mousepriv->inReset) { 31731450c749Smrg unsigned char val; 31741450c749Smrg int blocked; 31751450c749Smrg 31761450c749Smrg ms = mousepriv->expires - GetTimeInMillis(); 31771450c749Smrg if (ms > 0) 31781450c749Smrg return; 31791450c749Smrg 31801450c749Smrg blocked = xf86BlockSIGIO (); 31811450c749Smrg 31821450c749Smrg xf86MsgVerb(X_INFO,3, 31831450c749Smrg "Got reinsert event: reinitializing PS/2 mouse\n"); 31841450c749Smrg val = 0xf4; 31851450c749Smrg if (xf86WriteSerial(pInfo->fd, &val, 1) != 1) 31861450c749Smrg xf86Msg(X_ERROR, "%s: Write to mouse failed\n", 31871450c749Smrg pInfo->name); 31881450c749Smrg xf86UnblockSIGIO(blocked); 3189659607e0Smrg } 3190659607e0Smrg RemoveBlockAndWakeupHandlers (ps2BlockHandler, ps2WakeupHandler, 31911450c749Smrg (pointer) pInfo); 3192659607e0Smrg} 3193659607e0Smrg#endif /* SUPPORT_MOUSE_RESET */ 3194659607e0Smrg 3195659607e0Smrg/************************************************************ 3196659607e0Smrg * 3197659607e0Smrg * Autoprobe stuff 3198659607e0Smrg * 3199659607e0Smrg ************************************************************/ 3200659607e0Smrg#ifdef EXTMOUSEDEBUG 3201659607e0Smrg# define AP_DBG(x) { ErrorF("Autoprobe: "); ErrorF x; } 3202659607e0Smrg# define AP_DBGC(x) ErrorF x ; 3203659607e0Smrg# else 3204659607e0Smrg# define AP_DBG(x) 3205659607e0Smrg# define AP_DBGC(x) 3206659607e0Smrg#endif 3207659607e0Smrg 3208eeaac534Smrgstatic 32091450c749SmrgMouseProtocolID hardProtocolList[] = { PROT_MSC, PROT_MM, PROT_LOGI, 32101450c749Smrg PROT_LOGIMAN, PROT_MMHIT, 32111450c749Smrg PROT_GLIDE, PROT_IMSERIAL, 32121450c749Smrg PROT_THINKING, PROT_ACECAD, 32131450c749Smrg PROT_THINKPS2, PROT_MMPS2, 32141450c749Smrg PROT_GLIDEPS2, 32151450c749Smrg PROT_NETSCPS2, PROT_EXPPS2,PROT_IMPS2, 32161450c749Smrg PROT_GENPS2, PROT_NETPS2, 32171450c749Smrg PROT_MS, 32181450c749Smrg PROT_UNKNOWN 3219659607e0Smrg}; 3220659607e0Smrg 3221eeaac534Smrgstatic 32221450c749SmrgMouseProtocolID softProtocolList[] = { PROT_MSC, PROT_MM, PROT_LOGI, 32231450c749Smrg PROT_LOGIMAN, PROT_MMHIT, 32241450c749Smrg PROT_GLIDE, PROT_IMSERIAL, 32251450c749Smrg PROT_THINKING, PROT_ACECAD, 32261450c749Smrg PROT_THINKPS2, PROT_MMPS2, 32271450c749Smrg PROT_GLIDEPS2, 32281450c749Smrg PROT_NETSCPS2 ,PROT_IMPS2, 32291450c749Smrg PROT_GENPS2, 32301450c749Smrg PROT_MS, 32311450c749Smrg PROT_UNKNOWN 3232659607e0Smrg}; 3233659607e0Smrg 3234659607e0Smrgstatic const char * 3235659607e0SmrgautoOSProtocol(InputInfoPtr pInfo, int *protoPara) 3236659607e0Smrg{ 3237659607e0Smrg MouseDevPtr pMse = pInfo->private; 3238659607e0Smrg const char *name = NULL; 3239659607e0Smrg MouseProtocolID protocolID = PROT_UNKNOWN; 3240659607e0Smrg 3241659607e0Smrg /* Check if the OS has a detection mechanism. */ 3242659607e0Smrg if (osInfo->SetupAuto) { 32431450c749Smrg name = osInfo->SetupAuto(pInfo, protoPara); 32441450c749Smrg if (name) { 32451450c749Smrg protocolID = ProtocolNameToID(name); 32461450c749Smrg switch (protocolID) { 32471450c749Smrg case PROT_UNKNOWN: 32481450c749Smrg /* Check for a builtin OS-specific protocol. */ 32491450c749Smrg if (osInfo->CheckProtocol && osInfo->CheckProtocol(name)) { 32501450c749Smrg /* We can only come here if the protocol has been 32514d6d3f96Smrg * changed to auto through the xf86misc extension 32521450c749Smrg * and we have detected an OS specific builtin 32531450c749Smrg * protocol. Currently we cannot handle this */ 32541450c749Smrg name = NULL; 32551450c749Smrg } else 32561450c749Smrg name = NULL; 32571450c749Smrg break; 32581450c749Smrg case PROT_UNSUP: 32591450c749Smrg name = NULL; 32601450c749Smrg break; 32611450c749Smrg default: 32621450c749Smrg break; 32631450c749Smrg } 32641450c749Smrg } 3265659607e0Smrg } 3266659607e0Smrg if (!name) { 32671450c749Smrg /* A PnP serial mouse? */ 32681450c749Smrg protocolID = MouseGetPnpProtocol(pInfo); 32691450c749Smrg if (protocolID >= 0 && protocolID < PROT_NUMPROTOS) { 32701450c749Smrg name = ProtocolIDToName(protocolID); 32711450c749Smrg xf86Msg(X_PROBED, "%s: PnP-detected protocol: \"%s\"\n", 32721450c749Smrg pInfo->name, name); 32731450c749Smrg } 3274659607e0Smrg } 3275eeaac534Smrg if (!name && osInfo->GuessProtocol) { 32761450c749Smrg name = osInfo->GuessProtocol(pInfo, 0); 32771450c749Smrg if (name) 32781450c749Smrg protocolID = ProtocolNameToID(name); 3279659607e0Smrg } 3280659607e0Smrg 3281659607e0Smrg if (name) { 32821450c749Smrg pMse->protocolID = protocolID; 3283659607e0Smrg } 32841450c749Smrg 3285659607e0Smrg return name; 3286659607e0Smrg} 3287659607e0Smrg 3288659607e0Smrg/* 3289659607e0Smrg * createProtocolList() -- create a list of protocols which may 3290659607e0Smrg * match on the incoming data stream. 3291659607e0Smrg */ 3292659607e0Smrgstatic void 3293659607e0SmrgcreateProtoList(MouseDevPtr pMse, MouseProtocolID *protoList) 3294659607e0Smrg{ 3295659607e0Smrg int i, j, k = 0; 3296659607e0Smrg MouseProtocolID prot; 3297659607e0Smrg unsigned char *para; 3298659607e0Smrg mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3299659607e0Smrg MouseProtocolID *tmplist = NULL; 33001468c73eSmrg#if !HAVE_THREADED_INPUT 3301659607e0Smrg int blocked; 33021468c73eSmrg#endif 33031450c749Smrg 3304659607e0Smrg AP_DBGC(("Autoprobe: ")); 3305659607e0Smrg for (i = 0; i < mPriv->count; i++) 33061450c749Smrg AP_DBGC(("%2.2x ", (unsigned char) mPriv->data[i])); 3307659607e0Smrg AP_DBGC(("\n")); 3308659607e0Smrg 33091468c73eSmrg#if HAVE_THREADED_INPUT 33101468c73eSmrg input_lock(); 33111468c73eSmrg#else 3312659607e0Smrg blocked = xf86BlockSIGIO (); 33131468c73eSmrg#endif 3314659607e0Smrg 3315659607e0Smrg /* create a private copy first so we can write in the old list */ 3316dd4cbfe8Smrg if ((tmplist = malloc(sizeof(MouseProtocolID) * NUM_AUTOPROBE_PROTOS))){ 33171450c749Smrg for (i = 0; protoList[i] != PROT_UNKNOWN; i++) { 33181450c749Smrg tmplist[i] = protoList[i]; 33191450c749Smrg } 33201450c749Smrg tmplist[i] = PROT_UNKNOWN; 33211450c749Smrg protoList = tmplist; 3322659607e0Smrg } else 33231450c749Smrg return; 33241450c749Smrg 33251450c749Smrg for (i = 0; ((prot = protoList[i]) != PROT_UNKNOWN 33261450c749Smrg && (k < NUM_AUTOPROBE_PROTOS - 1)) ; i++) { 33271450c749Smrg Bool bad = TRUE; 33281450c749Smrg unsigned char byte = 0; 33291450c749Smrg int count = 0; 33301450c749Smrg int next_header_candidate = 0; 33311450c749Smrg int header_count = 0; 33321450c749Smrg 33331450c749Smrg if (!GetProtocol(prot)) 33341450c749Smrg continue; 33351450c749Smrg para = proto[prot]; 33361450c749Smrg 33371450c749Smrg AP_DBG(("Protocol: %s ", ProtocolIDToName(prot))); 3338659607e0Smrg 3339659607e0Smrg#ifdef EXTMOUSEDEBUG 33401450c749Smrg for (j = 0; j < 7; j++) 33411450c749Smrg AP_DBGC(("%2.2x ", (unsigned char) para[j])); 33421450c749Smrg AP_DBGC(("\n")); 33431450c749Smrg#endif 33441450c749Smrg j = 0; 33451450c749Smrg while (1) { 33461450c749Smrg /* look for header */ 33471450c749Smrg while (j < mPriv->count) { 33481450c749Smrg if (((byte = mPriv->data[j++]) & para[0]) == para[1]){ 33491450c749Smrg AP_DBG(("found header %2.2x\n",byte)); 33501450c749Smrg next_header_candidate = j; 33511450c749Smrg count = 1; 33521450c749Smrg break; 33531450c749Smrg } else { 33541450c749Smrg /* 33551450c749Smrg * Bail out if number of bytes per package have 33561450c749Smrg * been tested for header. 33571450c749Smrg * Take bytes per package of leading garbage into 33581450c749Smrg * account. 33591450c749Smrg */ 33601450c749Smrg if (j > para[4] && ++header_count > para[4]) { 33611450c749Smrg j = mPriv->count; 33621450c749Smrg break; 33631450c749Smrg } 33641450c749Smrg } 33651450c749Smrg } 33661450c749Smrg /* check if remaining data matches protocol */ 33671450c749Smrg while (j < mPriv->count) { 33681450c749Smrg byte = mPriv->data[j++]; 33691450c749Smrg if (count == para[4]) { 33701450c749Smrg count = 0; 33711450c749Smrg /* check and eat excess byte */ 33721450c749Smrg if (((byte & para[0]) != para[1]) 33731450c749Smrg && ((byte & para[5]) == para[6])) { 33741450c749Smrg AP_DBG(("excess byte found\n")); 33751450c749Smrg continue; 33761450c749Smrg } 33771450c749Smrg } 33781450c749Smrg if (count == 0) { 33791450c749Smrg /* validate next header */ 33801450c749Smrg bad = FALSE; 33811450c749Smrg AP_DBG(("Complete set found\n")); 33821450c749Smrg if ((byte & para[0]) != para[1]) { 33831450c749Smrg AP_DBG(("Autoprobe: header bad\n")); 33841450c749Smrg bad = TRUE; 33851450c749Smrg break; 33861450c749Smrg } else { 33871450c749Smrg count++; 33881450c749Smrg continue; 33891450c749Smrg } 33901450c749Smrg } 33911450c749Smrg /* validate data */ 33921450c749Smrg else if (((byte & para[2]) != para[3]) 33931450c749Smrg || ((para[7] & MPF_SAFE) 33941450c749Smrg && ((byte & para[0]) == para[1]))) { 33951450c749Smrg AP_DBG(("data bad\n")); 33961450c749Smrg bad = TRUE; 33971450c749Smrg break; 33981450c749Smrg } else { 33991450c749Smrg count ++; 34001450c749Smrg continue; 34011450c749Smrg } 34021450c749Smrg } 34031450c749Smrg if (!bad) { 34041450c749Smrg /* this is a matching protocol */ 34051450c749Smrg mPriv->protoList[k++] = prot; 34061450c749Smrg AP_DBG(("Autoprobe: Adding protocol %s to list (entry %i)\n", 34071450c749Smrg ProtocolIDToName(prot),k-1)); 34081450c749Smrg break; 34091450c749Smrg } 34101450c749Smrg j = next_header_candidate; 34111450c749Smrg next_header_candidate = 0; 34121450c749Smrg /* we have tested number of bytes per package for header */ 34131450c749Smrg if (j > para[4] && ++header_count > para[4]) 34141450c749Smrg break; 34151450c749Smrg /* we have not found anything that looks like a header */ 34161450c749Smrg if (!next_header_candidate) 34171450c749Smrg break; 34181450c749Smrg AP_DBG(("Looking for new header\n")); 34191450c749Smrg } 3420659607e0Smrg } 3421659607e0Smrg 34221468c73eSmrg#if HAVE_THREADED_INPUT 34231468c73eSmrg input_unlock(); 34241468c73eSmrg#else 3425659607e0Smrg xf86UnblockSIGIO(blocked); 34261468c73eSmrg#endif 34271450c749Smrg 3428659607e0Smrg mPriv->protoList[k] = PROT_UNKNOWN; 3429659607e0Smrg 3430dd4cbfe8Smrg free(tmplist); 3431659607e0Smrg} 3432659607e0Smrg 3433659607e0Smrg 3434659607e0Smrg/* This only needs to be done once */ 3435eeaac534Smrgstatic void **serialDefaultsList = NULL; 3436659607e0Smrg 3437659607e0Smrg/* 3438659607e0Smrg * createSerialDefaultsLists() - create a list of the different default 3439659607e0Smrg * settings for the serial interface of the known protocols. 3440659607e0Smrg */ 3441659607e0Smrgstatic void 3442659607e0SmrgcreateSerialDefaultsList(void) 3443659607e0Smrg{ 3444659607e0Smrg int i = 0, j, k; 3445659607e0Smrg 3446659607e0Smrg serialDefaultsList = (void **)xnfalloc(sizeof(void*)); 3447659607e0Smrg serialDefaultsList[0] = NULL; 3448659607e0Smrg 3449659607e0Smrg for (j = 0; mouseProtocols[j].name; j++) { 34501450c749Smrg if (!mouseProtocols[j].defaults) 34511450c749Smrg continue; 34521450c749Smrg for (k = 0; k < i; k++) 34531450c749Smrg if (mouseProtocols[j].defaults == serialDefaultsList[k]) 34541450c749Smrg continue; 34551450c749Smrg i++; 34561450c749Smrg serialDefaultsList = (void**)xnfrealloc(serialDefaultsList, 34571450c749Smrg sizeof(void*)*(i+1)); 34581450c749Smrg serialDefaultsList[i-1] = mouseProtocols[j].defaults; 34591450c749Smrg serialDefaultsList[i] = NULL; 3460659607e0Smrg } 3461659607e0Smrg} 3462659607e0Smrg 3463659607e0Smrgtypedef enum { 3464659607e0Smrg STATE_INVALID, 3465659607e0Smrg STATE_UNCERTAIN, 3466659607e0Smrg STATE_VALID 3467659607e0Smrg} validState; 3468659607e0Smrg 3469659607e0Smrg/* Probing threshold values */ 3470659607e0Smrg#define PROBE_UNCERTAINTY 50 3471659607e0Smrg#define BAD_CERTAINTY 6 3472659607e0Smrg#define BAD_INC_CERTAINTY 1 3473659607e0Smrg#define BAD_INC_CERTAINTY_WHEN_SYNC_LOST 2 3474659607e0Smrg 3475659607e0Smrgstatic validState 34761450c749SmrgvalidCount(mousePrivPtr mPriv, Bool inSync, Bool lostSync) 3477659607e0Smrg{ 3478659607e0Smrg if (inSync) { 34791450c749Smrg if (!--mPriv->goodCount) { 34801450c749Smrg /* we are sure to have found the correct protocol */ 34811450c749Smrg mPriv->badCount = 0; 34821450c749Smrg return STATE_VALID; 34831450c749Smrg } 34841450c749Smrg AP_DBG(("%i successful rounds to go\n", 34851450c749Smrg mPriv->goodCount)); 34861450c749Smrg return STATE_UNCERTAIN; 3487659607e0Smrg } 3488659607e0Smrg 3489659607e0Smrg 3490659607e0Smrg /* We are out of sync again */ 3491659607e0Smrg mPriv->goodCount = PROBE_UNCERTAINTY; 3492659607e0Smrg /* We increase uncertainty of having the correct protocol */ 34931450c749Smrg mPriv->badCount+= lostSync ? BAD_INC_CERTAINTY_WHEN_SYNC_LOST 34941450c749Smrg : BAD_INC_CERTAINTY; 3495659607e0Smrg 3496659607e0Smrg if (mPriv->badCount < BAD_CERTAINTY) { 34971450c749Smrg /* We are not convinced yet to have the wrong protocol */ 34981450c749Smrg AP_DBG(("Changing protocol after: %i rounds\n", 34991450c749Smrg BAD_CERTAINTY - mPriv->badCount)); 35001450c749Smrg return STATE_UNCERTAIN; 3501659607e0Smrg } 3502659607e0Smrg return STATE_INVALID; 3503659607e0Smrg} 3504659607e0Smrg 35051450c749Smrg#define RESET_VALIDATION mPriv->goodCount = PROBE_UNCERTAINTY;\ 35061450c749Smrg mPriv->badCount = 0;\ 35071450c749Smrg mPriv->prevDx = 0;\ 35081450c749Smrg mPriv->prevDy = 0;\ 35091450c749Smrg mPriv->accDx = 0;\ 35101450c749Smrg mPriv->accDy = 0;\ 35111450c749Smrg mPriv->acc = 0; 3512659607e0Smrg 3513659607e0Smrgstatic void 35141450c749SmrgautoProbeMouse(InputInfoPtr pInfo, Bool inSync, Bool lostSync) 3515659607e0Smrg{ 3516659607e0Smrg MouseDevPtr pMse = pInfo->private; 3517659607e0Smrg mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3518659607e0Smrg 3519659607e0Smrg MouseProtocolID *protocolList = NULL; 35201450c749Smrg 3521659607e0Smrg while (1) { 35221450c749Smrg switch (mPriv->autoState) { 35231450c749Smrg case AUTOPROBE_GOOD: 35241450c749Smrg if (inSync) 35251450c749Smrg return; 35261450c749Smrg AP_DBG(("State GOOD\n")); 35271450c749Smrg RESET_VALIDATION; 35281450c749Smrg mPriv->autoState = AUTOPROBE_VALIDATE1; 35291450c749Smrg return; 35301450c749Smrg case AUTOPROBE_H_GOOD: 35311450c749Smrg if (inSync) 35321450c749Smrg return; 35331450c749Smrg AP_DBG(("State H_GOOD\n")); 35341450c749Smrg RESET_VALIDATION; 35351450c749Smrg mPriv->autoState = AUTOPROBE_H_VALIDATE2; 35361450c749Smrg return; 35371450c749Smrg case AUTOPROBE_H_NOPROTO: 35381450c749Smrg AP_DBG(("State H_NOPROTO\n")); 35391450c749Smrg mPriv->protocolID = 0; 35401450c749Smrg mPriv->autoState = AUTOPROBE_H_SETPROTO; 35411450c749Smrg break; 35421450c749Smrg case AUTOPROBE_H_SETPROTO: 35431450c749Smrg AP_DBG(("State H_SETPROTO\n")); 35441450c749Smrg if ((pMse->protocolID = hardProtocolList[mPriv->protocolID++]) 35451450c749Smrg == PROT_UNKNOWN) { 35461450c749Smrg mPriv->protocolID = 0; 35471450c749Smrg break; 35481450c749Smrg } else if (GetProtocol(pMse->protocolID) && SetupMouse(pInfo)) { 35491450c749Smrg FlushButtons(pMse); 35501450c749Smrg RESET_VALIDATION; 35511450c749Smrg AP_DBG(("Autoprobe: Trying Protocol: %s\n", 35521450c749Smrg ProtocolIDToName(pMse->protocolID))); 35531450c749Smrg mPriv->autoState = AUTOPROBE_H_VALIDATE1; 35541450c749Smrg return; 35551450c749Smrg } 35561450c749Smrg break; 35571450c749Smrg case AUTOPROBE_H_VALIDATE1: 35581450c749Smrg AP_DBG(("State H_VALIDATE1\n")); 35591450c749Smrg switch (validCount(mPriv,inSync,lostSync)) { 35601450c749Smrg case STATE_INVALID: 35611450c749Smrg mPriv->autoState = AUTOPROBE_H_SETPROTO; 35621450c749Smrg break; 35631450c749Smrg case STATE_VALID: 35641450c749Smrg xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 35651450c749Smrg ProtocolIDToName(pMse->protocolID)); 35661450c749Smrg mPriv->autoState = AUTOPROBE_H_GOOD; 35671450c749Smrg return; 35681450c749Smrg case STATE_UNCERTAIN: 35691450c749Smrg return; 35701450c749Smrg default: 35711450c749Smrg break; 35721450c749Smrg } 35731450c749Smrg break; 35741450c749Smrg case AUTOPROBE_H_VALIDATE2: 35751450c749Smrg AP_DBG(("State H_VALIDATE2\n")); 35761450c749Smrg switch (validCount(mPriv,inSync,lostSync)) { 35771450c749Smrg case STATE_INVALID: 35781450c749Smrg mPriv->autoState = AUTOPROBE_H_AUTODETECT; 35791450c749Smrg break; 35801450c749Smrg case STATE_VALID: 35811450c749Smrg xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 35821450c749Smrg ProtocolIDToName(pMse->protocolID)); 35831450c749Smrg mPriv->autoState = AUTOPROBE_H_GOOD; 35841450c749Smrg return; 35851450c749Smrg case STATE_UNCERTAIN: 35861450c749Smrg return; 35871450c749Smrg } 35881450c749Smrg break; 35891450c749Smrg case AUTOPROBE_H_AUTODETECT: 35901450c749Smrg AP_DBG(("State H_AUTODETECT\n")); 35911450c749Smrg pMse->protocolID = PROT_AUTO; 35921450c749Smrg AP_DBG(("Looking for PnP/OS mouse\n")); 35931450c749Smrg mPriv->count = 0; 35941450c749Smrg SetupMouse(pInfo); 35951450c749Smrg if (pMse->protocolID != PROT_AUTO) 35961450c749Smrg mPriv->autoState = AUTOPROBE_H_GOOD; 35971450c749Smrg else 35981450c749Smrg mPriv->autoState = AUTOPROBE_H_NOPROTO; 35991450c749Smrg break; 36001450c749Smrg case AUTOPROBE_NOPROTO: 36011450c749Smrg AP_DBG(("State NOPROTO\n")); 36021450c749Smrg mPriv->count = 0; 36031450c749Smrg mPriv->serialDefaultsNum = -1; 36041450c749Smrg mPriv->autoState = AUTOPROBE_COLLECT; 36051450c749Smrg break; 36061450c749Smrg case AUTOPROBE_COLLECT: 36071450c749Smrg AP_DBG(("State COLLECT\n")); 36081450c749Smrg if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES) 36091450c749Smrg return; 36101450c749Smrg protocolList = softProtocolList; 36111450c749Smrg mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST; 36121450c749Smrg break; 36131450c749Smrg case AUTOPROBE_CREATE_PROTOLIST: 36141450c749Smrg AP_DBG(("State CREATE_PROTOLIST\n")); 36151450c749Smrg createProtoList(pMse, protocolList); 36161450c749Smrg mPriv->protocolID = 0; 36171450c749Smrg mPriv->autoState = AUTOPROBE_SWITCH_PROTOCOL; 36181450c749Smrg break; 36191450c749Smrg case AUTOPROBE_AUTODETECT: 36201450c749Smrg AP_DBG(("State AUTODETECT\n")); 36211450c749Smrg pMse->protocolID = PROT_AUTO; 36221450c749Smrg AP_DBG(("Looking for PnP/OS mouse\n")); 36231450c749Smrg mPriv->count = 0; 36241450c749Smrg SetupMouse(pInfo); 36251450c749Smrg if (pMse->protocolID != PROT_AUTO) 36261450c749Smrg mPriv->autoState = AUTOPROBE_GOOD; 36271450c749Smrg else 36281450c749Smrg mPriv->autoState = AUTOPROBE_NOPROTO; 36291450c749Smrg break; 36301450c749Smrg case AUTOPROBE_VALIDATE1: 36311450c749Smrg AP_DBG(("State VALIDATE1\n")); 36321450c749Smrg switch (validCount(mPriv,inSync,lostSync)) { 36331450c749Smrg case STATE_INVALID: 36341450c749Smrg mPriv->autoState = AUTOPROBE_AUTODETECT; 36351450c749Smrg break; 36361450c749Smrg case STATE_VALID: 36371450c749Smrg xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 36381450c749Smrg ProtocolIDToName(pMse->protocolID)); 36391450c749Smrg mPriv->autoState = AUTOPROBE_GOOD; 36401450c749Smrg break; 36411450c749Smrg case STATE_UNCERTAIN: 36421450c749Smrg return; 36431450c749Smrg } 36441450c749Smrg break; 36451450c749Smrg case AUTOPROBE_VALIDATE2: 36461450c749Smrg AP_DBG(("State VALIDATE2\n")); 36471450c749Smrg switch (validCount(mPriv,inSync,lostSync)) { 36481450c749Smrg case STATE_INVALID: 36491450c749Smrg protocolList = &mPriv->protoList[mPriv->protocolID]; 36501450c749Smrg mPriv->autoState = AUTOPROBE_CREATE_PROTOLIST; 36511450c749Smrg break; 36521450c749Smrg case STATE_VALID: 36531450c749Smrg xf86Msg(X_INFO,"Mouse autoprobe: selecting %s protocol\n", 36541450c749Smrg ProtocolIDToName(pMse->protocolID)); 36551450c749Smrg mPriv->autoState = AUTOPROBE_GOOD; 36561450c749Smrg break; 36571450c749Smrg case STATE_UNCERTAIN: 36581450c749Smrg return; 36591450c749Smrg } 36601450c749Smrg break; 36611450c749Smrg case AUTOPROBE_SWITCHSERIAL: 36621450c749Smrg { 36631450c749Smrg pointer serialDefaults; 36641450c749Smrg AP_DBG(("State SWITCHSERIAL\n")); 36651450c749Smrg 36661450c749Smrg if (!serialDefaultsList) 36671450c749Smrg createSerialDefaultsList(); 36681450c749Smrg 36691450c749Smrg AP_DBG(("Switching serial params\n")); 36701450c749Smrg if ((serialDefaults = 36711450c749Smrg serialDefaultsList[++mPriv->serialDefaultsNum]) == NULL) { 36721450c749Smrg mPriv->serialDefaultsNum = 0; 36731450c749Smrg } else { 36741450c749Smrg pointer tmp = xf86OptionListCreate(serialDefaults, -1, 0); 36751450c749Smrg xf86SetSerial(pInfo->fd, tmp); 36761450c749Smrg xf86OptionListFree(tmp); 36771450c749Smrg mPriv->count = 0; 36781450c749Smrg mPriv->autoState = AUTOPROBE_COLLECT; 36791450c749Smrg } 36801450c749Smrg break; 36811450c749Smrg } 36821450c749Smrg case AUTOPROBE_SWITCH_PROTOCOL: 36831450c749Smrg { 36841450c749Smrg MouseProtocolID prot; 36851450c749Smrg MouseProtocolPtr pProto; 36861450c749Smrg void *defaults; 36871450c749Smrg AP_DBG(("State SWITCH_PROTOCOL\n")); 36881450c749Smrg prot = mPriv->protoList[mPriv->protocolID++]; 36891450c749Smrg if (prot == PROT_UNKNOWN) 36901450c749Smrg mPriv->autoState = AUTOPROBE_SWITCHSERIAL; 36911450c749Smrg else if (!((pProto = GetProtocol(prot)) && 36921450c749Smrg ((defaults = pProto->defaults))) 36931450c749Smrg || (mPriv->serialDefaultsNum == -1 36941450c749Smrg && (defaults == msDefaults)) 36951450c749Smrg || (mPriv->serialDefaultsNum != -1 36961450c749Smrg && serialDefaultsList[mPriv->serialDefaultsNum] 36971450c749Smrg == defaults)) { 36981450c749Smrg AP_DBG(("Changing Protocol to %s\n", 36991450c749Smrg ProtocolIDToName(prot))); 37001450c749Smrg SetMouseProto(pMse,prot); 37011450c749Smrg FlushButtons(pMse); 37021450c749Smrg RESET_VALIDATION; 37031450c749Smrg mPriv->autoState = AUTOPROBE_VALIDATE2; 37041450c749Smrg return; 37051450c749Smrg } 37061450c749Smrg break; 37071450c749Smrg } 37081450c749Smrg } 3709659607e0Smrg } 3710659607e0Smrg} 3711659607e0Smrg 3712659607e0Smrgstatic Bool 3713659607e0SmrgautoGood(MouseDevPtr pMse) 3714659607e0Smrg{ 3715659607e0Smrg mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 37161450c749Smrg 3717659607e0Smrg if (!pMse->autoProbe) 37181450c749Smrg return TRUE; 3719659607e0Smrg 3720659607e0Smrg switch (mPriv->autoState) { 3721659607e0Smrg case AUTOPROBE_GOOD: 3722659607e0Smrg case AUTOPROBE_H_GOOD: 37231450c749Smrg return TRUE; 3724659607e0Smrg case AUTOPROBE_VALIDATE1: /* @@@ */ 3725659607e0Smrg case AUTOPROBE_H_VALIDATE1: /* @@@ */ 3726659607e0Smrg case AUTOPROBE_VALIDATE2: 3727659607e0Smrg case AUTOPROBE_H_VALIDATE2: 37281450c749Smrg if (mPriv->goodCount < PROBE_UNCERTAINTY/2) 37291450c749Smrg return TRUE; 37304d6d3f96Smrg /* FALLTHROUGH */ 3731659607e0Smrg default: 37321450c749Smrg return FALSE; 3733659607e0Smrg } 3734659607e0Smrg} 3735659607e0Smrg 3736659607e0Smrg 3737659607e0Smrg#define TOT_THRESHOLD 3000 3738659607e0Smrg#define VAL_THRESHOLD 40 3739659607e0Smrg 3740659607e0Smrg/* 3741659607e0Smrg * checkForErraticMovements() -- check if mouse 'jumps around'. 3742659607e0Smrg */ 3743659607e0Smrgstatic void 3744659607e0SmrgcheckForErraticMovements(InputInfoPtr pInfo, int dx, int dy) 3745659607e0Smrg{ 3746659607e0Smrg MouseDevPtr pMse = pInfo->private; 3747659607e0Smrg mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3748eeaac534Smrg 3749659607e0Smrg if (!mPriv->goodCount) 37501450c749Smrg return; 3751eeaac534Smrg 3752659607e0Smrg#if 0 37531450c749Smrg if (abs(dx - mPriv->prevDx) > 300 37541450c749Smrg || abs(dy - mPriv->prevDy) > 300) 37551450c749Smrg AP_DBG(("erratic1 behaviour\n")); 3756659607e0Smrg#endif 3757659607e0Smrg if (abs(dx) > VAL_THRESHOLD) { 37581450c749Smrg if (sign(dx) == sign(mPriv->prevDx)) { 37591450c749Smrg mPriv->accDx += dx; 37601450c749Smrg if (abs(mPriv->accDx) > mPriv->acc) { 37611450c749Smrg mPriv->acc = abs(mPriv->accDx); 37621450c749Smrg AP_DBG(("acc=%i\n",mPriv->acc)); 37631450c749Smrg } 37644d6d3f96Smrg else { 37651450c749Smrg AP_DBG(("accDx=%i\n",mPriv->accDx)); 37664d6d3f96Smrg } 37671450c749Smrg } else { 37681450c749Smrg mPriv->accDx = 0; 37691450c749Smrg } 3770659607e0Smrg } 3771659607e0Smrg 3772659607e0Smrg if (abs(dy) > VAL_THRESHOLD) { 37731450c749Smrg if (sign(dy) == sign(mPriv->prevDy)) { 37741450c749Smrg mPriv->accDy += dy; 37751450c749Smrg if (abs(mPriv->accDy) > mPriv->acc) { 37761450c749Smrg mPriv->acc = abs(mPriv->accDy); 37771450c749Smrg AP_DBG(("acc: %i\n",mPriv->acc)); 37784d6d3f96Smrg } else { 37791450c749Smrg AP_DBG(("accDy=%i\n",mPriv->accDy)); 37804d6d3f96Smrg } 37811450c749Smrg } else { 37821450c749Smrg mPriv->accDy = 0; 37831450c749Smrg } 3784659607e0Smrg } 3785659607e0Smrg mPriv->prevDx = dx; 3786659607e0Smrg mPriv->prevDy = dy; 3787659607e0Smrg if (mPriv->acc > TOT_THRESHOLD) { 37881450c749Smrg mPriv->goodCount = PROBE_UNCERTAINTY; 37891450c749Smrg mPriv->prevDx = 0; 37901450c749Smrg mPriv->prevDy = 0; 37911450c749Smrg mPriv->accDx = 0; 37921450c749Smrg mPriv->accDy = 0; 37931450c749Smrg mPriv->acc = 0; 37941450c749Smrg AP_DBG(("erratic2 behaviour\n")); 37951450c749Smrg autoProbeMouse(pInfo, FALSE,TRUE); 3796659607e0Smrg } 3797659607e0Smrg} 3798659607e0Smrg 3799659607e0Smrgstatic void 3800659607e0SmrgSetMouseProto(MouseDevPtr pMse, MouseProtocolID protocolID) 3801659607e0Smrg{ 3802659607e0Smrg pMse->protocolID = protocolID; 3803659607e0Smrg pMse->protocol = ProtocolIDToName(pMse->protocolID); 3804659607e0Smrg pMse->class = ProtocolIDToClass(pMse->protocolID); 3805659607e0Smrg if ((pMse->protocolID >= 0) && (pMse->protocolID < PROT_NUMPROTOS)) 38061450c749Smrg memcpy(pMse->protoPara, proto[pMse->protocolID], 38071450c749Smrg sizeof(pMse->protoPara)); 38081450c749Smrg 3809659607e0Smrg if (pMse->emulate3ButtonsSoft) 38101450c749Smrg pMse->emulate3Buttons = TRUE; 3811659607e0Smrg} 3812659607e0Smrg 3813659607e0Smrg/* 3814659607e0Smrg * collectData() -- collect data bytes sent by mouse. 3815659607e0Smrg */ 3816659607e0Smrgstatic Bool 3817659607e0SmrgcollectData(MouseDevPtr pMse, unsigned char u) 3818659607e0Smrg{ 3819659607e0Smrg mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv; 3820659607e0Smrg if (mPriv->count < NUM_MSE_AUTOPROBE_TOTAL) { 38211450c749Smrg mPriv->data[mPriv->count++] = u; 38221450c749Smrg if (mPriv->count <= NUM_MSE_AUTOPROBE_BYTES) { 38231450c749Smrg return TRUE; 38241450c749Smrg } 3825659607e0Smrg } 3826659607e0Smrg return FALSE; 3827659607e0Smrg} 3828659607e0Smrg 3829659607e0Smrg/**************** end of autoprobe stuff *****************/ 3830659607e0Smrg 3831659607e0Smrg 3832659607e0Smrgstatic void 38331450c749Smrgxf86MouseUnplug(pointer p) 3834659607e0Smrg{ 3835659607e0Smrg} 3836659607e0Smrgstatic pointer 38371450c749Smrgxf86MousePlug(pointer module, 38381450c749Smrg pointer options, 38391450c749Smrg int *errmaj, 38401450c749Smrg int *errmin) 3841659607e0Smrg{ 3842659607e0Smrg static Bool Initialised = FALSE; 3843659607e0Smrg 3844eeaac534Smrg if (!Initialised) 38451450c749Smrg Initialised = TRUE; 3846659607e0Smrg 3847659607e0Smrg xf86AddInputDriver(&MOUSE, module, 0); 3848659607e0Smrg 3849659607e0Smrg return module; 3850659607e0Smrg} 3851659607e0Smrg 3852659607e0Smrgstatic XF86ModuleVersionInfo xf86MouseVersionRec = 3853659607e0Smrg{ 3854659607e0Smrg "mouse", 3855659607e0Smrg MODULEVENDORSTRING, 3856659607e0Smrg MODINFOSTRING1, 3857659607e0Smrg MODINFOSTRING2, 3858659607e0Smrg XORG_VERSION_CURRENT, 3859659607e0Smrg PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 3860659607e0Smrg ABI_CLASS_XINPUT, 3861659607e0Smrg ABI_XINPUT_VERSION, 3862659607e0Smrg MOD_CLASS_XINPUT, 38631450c749Smrg {0, 0, 0, 0} /* signature, to be patched into the file by */ 38641450c749Smrg /* a tool */ 3865659607e0Smrg}; 3866659607e0Smrg 3867659607e0Smrg_X_EXPORT XF86ModuleData mouseModuleData = { 3868659607e0Smrg &xf86MouseVersionRec, 3869659607e0Smrg xf86MousePlug, 3870659607e0Smrg xf86MouseUnplug 3871659607e0Smrg}; 3872659607e0Smrg 3873659607e0Smrg/* 3874659607e0Smrg Look at hitachi device stuff. 3875659607e0Smrg*/ 3876