sun_mouse.c revision bd3a1963
1b73be646Smrg/* 2b73be646Smrg * Copyright (c) 2004-2005, 2008-2010, Oracle and/or its affiliates. 3b73be646Smrg * All rights reserved. 4b73be646Smrg * 5b73be646Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6b73be646Smrg * copy of this software and associated documentation files (the "Software"), 7b73be646Smrg * to deal in the Software without restriction, including without limitation 8b73be646Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b73be646Smrg * and/or sell copies of the Software, and to permit persons to whom the 10b73be646Smrg * Software is furnished to do so, subject to the following conditions: 11b73be646Smrg * 12b73be646Smrg * The above copyright notice and this permission notice (including the next 13b73be646Smrg * paragraph) shall be included in all copies or substantial portions of the 14b73be646Smrg * Software. 15b73be646Smrg * 16b73be646Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b73be646Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b73be646Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b73be646Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20b73be646Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21b73be646Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22b73be646Smrg * DEALINGS IN THE SOFTWARE. 23b73be646Smrg */ 246aab59a7Smrg/* 256aab59a7Smrg * Copyright 1999-2001 The XFree86 Project, Inc. All Rights Reserved. 266aab59a7Smrg * 276aab59a7Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 286aab59a7Smrg * of this software and associated documentation files (the "Software"), to 296aab59a7Smrg * deal in the Software without restriction, including without limitation the 306aab59a7Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 316aab59a7Smrg * sell copies of the Software, and to permit persons to whom the Software is 326aab59a7Smrg * furnished to do so, subject to the following conditions: 336aab59a7Smrg * 346aab59a7Smrg * The above copyright notice and this permission notice shall be included in 356aab59a7Smrg * all copies or substantial portions of the Software. 366aab59a7Smrg * 376aab59a7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 386aab59a7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 396aab59a7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 406aab59a7Smrg * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 416aab59a7Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 426aab59a7Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 436aab59a7Smrg * 446aab59a7Smrg * Except as contained in this notice, the name of the XFree86 Project shall 456aab59a7Smrg * not be used in advertising or otherwise to promote the sale, use or other 466aab59a7Smrg * dealings in this Software without prior written authorization from the 476aab59a7Smrg * XFree86 Project. 486aab59a7Smrg */ 496aab59a7Smrg 506aab59a7Smrg#ifdef HAVE_XORG_CONFIG_H 516aab59a7Smrg#include <xorg-config.h> 526aab59a7Smrg#endif 536aab59a7Smrg 546aab59a7Smrg#include "xorg-server.h" 556aab59a7Smrg#include "xf86.h" 566aab59a7Smrg#include "xf86_OSlib.h" 57bd3a1963Smrg#include "mouse.h" 586aab59a7Smrg#include "xisb.h" 596aab59a7Smrg#include "mipointer.h" 606aab59a7Smrg#include <sys/stropts.h> 616aab59a7Smrg#include <sys/vuid_event.h> 626aab59a7Smrg#include <sys/msio.h> 636aab59a7Smrg 646aab59a7Smrg/* Wheel mouse support in VUID drivers in Solaris 9 updates & Solaris 10 */ 656aab59a7Smrg#ifdef WHEEL_DEVID /* Defined in vuid_event.h if VUID wheel support present */ 666aab59a7Smrg# define HAVE_VUID_WHEEL 676aab59a7Smrg#endif 686aab59a7Smrg#ifdef HAVE_VUID_WHEEL 696aab59a7Smrg# include <sys/vuid_wheel.h> 706aab59a7Smrg#endif 716aab59a7Smrg 726aab59a7Smrg/* Support for scaling absolute coordinates to screen size in 736aab59a7Smrg * Solaris 10 updates and beyond */ 746aab59a7Smrg#if !defined(HAVE_ABSOLUTE_MOUSE_SCALING) 756aab59a7Smrg# ifdef MSIOSRESOLUTION /* Defined in msio.h if scaling support present */ 766aab59a7Smrg# define HAVE_ABSOLUTE_MOUSE_SCALING 776aab59a7Smrg# endif 786aab59a7Smrg#endif 796aab59a7Smrg 806aab59a7Smrg/* Names of protocols that are handled internally here. */ 816aab59a7Smrg 826aab59a7Smrgstatic const char *internalNames[] = { 836aab59a7Smrg "VUID", 846aab59a7Smrg NULL 856aab59a7Smrg}; 866aab59a7Smrg 876aab59a7Smrgstatic const char *solarisMouseDevs[] = { 886aab59a7Smrg /* Device file: Protocol: */ 896aab59a7Smrg "/dev/mouse", "VUID", /* USB or SPARC */ 906aab59a7Smrg#if defined(__i386) || defined(__x86) 916aab59a7Smrg "/dev/kdmouse", "PS/2", /* PS/2 */ 926aab59a7Smrg#endif 936aab59a7Smrg NULL 946aab59a7Smrg}; 956aab59a7Smrg 966aab59a7Smrgtypedef struct _VuidMseRec { 976aab59a7Smrg struct _VuidMseRec *next; 986aab59a7Smrg InputInfoPtr pInfo; 996aab59a7Smrg Firm_event event; 1006aab59a7Smrg unsigned char * buffer; 1016aab59a7Smrg char * strmod; 1026aab59a7Smrg Bool(*wrapped_device_control)(DeviceIntPtr device, int what); 1036aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 1046aab59a7Smrg Ms_screen_resolution absres; 1056aab59a7Smrg#endif 106b73be646Smrg OsTimerPtr remove_timer; /* Callback for removal on ENODEV */ 1076aab59a7Smrg} VuidMseRec, *VuidMsePtr; 1086aab59a7Smrg 1096aab59a7Smrgstatic VuidMsePtr vuidMouseList = NULL; 1106aab59a7Smrg 1116aab59a7Smrgstatic int vuidMouseProc(DeviceIntPtr pPointer, int what); 1126aab59a7Smrgstatic void vuidReadInput(InputInfoPtr pInfo); 1136aab59a7Smrg 1146aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 1156aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse); 1166aab59a7Smrgstatic void vuidMouseAdjustFrame(int index, int x, int y, int flags); 1176aab59a7Smrg 1186aab59a7Smrgstatic int vuidMouseGeneration = 0; 119b73be646Smrg 120b73be646Smrg#if HAS_DEVPRIVATEKEYREC 121b73be646Smrgstatic DevPrivateKeyRec vuidMouseScreenIndex; 122b73be646Smrg#else 1236aab59a7Smrgstatic int vuidMouseScreenIndex; 124b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 125b73be646Smrg 1266aab59a7Smrg#define vuidMouseGetScreenPrivate(s) ( \ 1276aab59a7Smrg dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex)) 1286aab59a7Smrg#define vuidMouseSetScreenPrivate(s,p) \ 1296aab59a7Smrg dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p) 1306aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 1316aab59a7Smrg 1326aab59a7Smrgstatic inline 1336aab59a7SmrgVuidMsePtr getVuidMsePriv(InputInfoPtr pInfo) 1346aab59a7Smrg{ 1356aab59a7Smrg VuidMsePtr m = vuidMouseList; 1366aab59a7Smrg 1376aab59a7Smrg while ((m != NULL) && (m->pInfo != pInfo)) { 1386aab59a7Smrg m = m->next; 1396aab59a7Smrg } 1406aab59a7Smrg 1416aab59a7Smrg return m; 1426aab59a7Smrg} 1436aab59a7Smrg 144b73be646Smrg/* Called from OsTimer callback, since removing a device from the device 145b73be646Smrg list or changing pInfo->fd while xf86Wakeup is looping through the list 146b73be646Smrg causes server crashes */ 147b73be646Smrgstatic CARD32 148b73be646SmrgvuidRemoveMouse(OsTimerPtr timer, CARD32 time, pointer arg) 149b73be646Smrg{ 150b73be646Smrg InputInfoPtr pInfo = (InputInfoPtr) arg; 151b73be646Smrg 152b73be646Smrg xf86DisableDevice(pInfo->dev, TRUE); 153b73be646Smrg 154b73be646Smrg return 0; /* All done, don't set to run again */ 155b73be646Smrg} 1566aab59a7Smrg 1576aab59a7Smrg/* 1586aab59a7Smrg * Initialize and enable the mouse wheel, if present. 1596aab59a7Smrg * 1606aab59a7Smrg * Returns 1 if mouse wheel was successfully enabled. 1616aab59a7Smrg * Returns 0 if an error occurred or if there is no mouse wheel. 1626aab59a7Smrg */ 1636aab59a7Smrgstatic int 1646aab59a7SmrgvuidMouseWheelInit(InputInfoPtr pInfo) 1656aab59a7Smrg{ 1666aab59a7Smrg#ifdef HAVE_VUID_WHEEL 1676aab59a7Smrg wheel_state wstate; 1686aab59a7Smrg int nwheel = -1; 1696aab59a7Smrg int i; 1706aab59a7Smrg 1716aab59a7Smrg wstate.vers = VUID_WHEEL_STATE_VERS; 1726aab59a7Smrg wstate.id = 0; 1736aab59a7Smrg wstate.stateflags = (uint32_t) -1; 1746aab59a7Smrg 1756aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel)); 1766aab59a7Smrg if (i != 0) 1776aab59a7Smrg return (0); 1786aab59a7Smrg 1796aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate)); 1806aab59a7Smrg if (i != 0) { 1816aab59a7Smrg xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name); 1826aab59a7Smrg return (0); 1836aab59a7Smrg } 1846aab59a7Smrg 1856aab59a7Smrg wstate.stateflags |= VUID_WHEEL_STATE_ENABLED; 1866aab59a7Smrg 1876aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate)); 1886aab59a7Smrg if (i != 0) { 1896aab59a7Smrg xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name); 1906aab59a7Smrg return (0); 1916aab59a7Smrg } 1926aab59a7Smrg 1936aab59a7Smrg return (1); 1946aab59a7Smrg#else 1956aab59a7Smrg return (0); 1966aab59a7Smrg#endif 1976aab59a7Smrg} 1986aab59a7Smrg 1996aab59a7Smrg 2006aab59a7Smrg/* This function is called when the protocol is "VUID". */ 2016aab59a7Smrgstatic Bool 2026aab59a7SmrgvuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 2036aab59a7Smrg{ 2046aab59a7Smrg MouseDevPtr pMse = pInfo->private; 2056aab59a7Smrg VuidMsePtr pVuidMse; 2066aab59a7Smrg int buttons, i; 2076aab59a7Smrg 208bd3a1963Smrg pVuidMse = calloc(sizeof(VuidMseRec), 1); 2096aab59a7Smrg if (pVuidMse == NULL) { 2106aab59a7Smrg xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); 211bd3a1963Smrg free(pMse); 2126aab59a7Smrg return FALSE; 2136aab59a7Smrg } 2146aab59a7Smrg 215fc27e79cSmrg pVuidMse->buffer = (unsigned char *)&pVuidMse->event; 216fc27e79cSmrg pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL); 217fc27e79cSmrg 2186aab59a7Smrg /* Setup the local procs. */ 2196aab59a7Smrg pVuidMse->wrapped_device_control = pInfo->device_control; 2206aab59a7Smrg pInfo->device_control = vuidMouseProc; 2216aab59a7Smrg pInfo->read_input = vuidReadInput; 2226aab59a7Smrg 2236aab59a7Smrg pMse->xisbscale = sizeof(Firm_event); 2246aab59a7Smrg 2256aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 2266aab59a7Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 2276aab59a7Smrg#endif 2286aab59a7Smrg pVuidMse->pInfo = pInfo; 2296aab59a7Smrg pVuidMse->next = vuidMouseList; 2306aab59a7Smrg vuidMouseList = pVuidMse; 2316aab59a7Smrg 232bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 2336aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 234bd3a1963Smrg#endif 2356aab59a7Smrg return TRUE; 2366aab59a7Smrg} 2376aab59a7Smrg 2386aab59a7Smrgstatic void 2396aab59a7SmrgvuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY, 2406aab59a7Smrg Bool *absXset, Bool *absYset) 2416aab59a7Smrg{ 2426aab59a7Smrg#ifdef DEBUG 2436aab59a7Smrg ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY, 2446aab59a7Smrg *absXset, *absYset); 2456aab59a7Smrg#endif 2466aab59a7Smrg if ((*absXset) && (*absYset)) { 2476aab59a7Smrg xf86PostMotionEvent(pInfo->dev, 2486aab59a7Smrg /* is_absolute: */ TRUE, 2496aab59a7Smrg /* first_valuator: */ 0, 2506aab59a7Smrg /* num_valuators: */ 2, 2516aab59a7Smrg absX, absY); 2526aab59a7Smrg } else if (*absXset) { 2536aab59a7Smrg xf86PostMotionEvent(pInfo->dev, 2546aab59a7Smrg /* is_absolute: */ TRUE, 2556aab59a7Smrg /* first_valuator: */ 0, 2566aab59a7Smrg /* num_valuators: */ 1, 2576aab59a7Smrg absX); 2586aab59a7Smrg } else if (*absYset) { 2596aab59a7Smrg xf86PostMotionEvent(pInfo->dev, 2606aab59a7Smrg /* is_absolute: */ TRUE, 2616aab59a7Smrg /* first_valuator: */ 1, 2626aab59a7Smrg /* num_valuators: */ 1, 2636aab59a7Smrg absY); 2646aab59a7Smrg } 2656aab59a7Smrg 2666aab59a7Smrg *absXset = FALSE; 2676aab59a7Smrg *absYset = FALSE; 2686aab59a7Smrg} 2696aab59a7Smrg 2706aab59a7Smrgstatic void 2716aab59a7SmrgvuidReadInput(InputInfoPtr pInfo) 2726aab59a7Smrg{ 2736aab59a7Smrg MouseDevPtr pMse; 2746aab59a7Smrg VuidMsePtr pVuidMse; 2756aab59a7Smrg int buttons; 2766aab59a7Smrg int dx = 0, dy = 0, dz = 0, dw = 0; 2776aab59a7Smrg unsigned int n; 2786aab59a7Smrg int c; 2796aab59a7Smrg unsigned char *pBuf; 2806aab59a7Smrg int absX = 0, absY = 0; 2816aab59a7Smrg Bool absXset = FALSE, absYset = FALSE; 2826aab59a7Smrg 2836aab59a7Smrg pMse = pInfo->private; 2846aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 2856aab59a7Smrg buttons = pMse->lastButtons; 2866aab59a7Smrg pBuf = pVuidMse->buffer; 2876aab59a7Smrg n = 0; 2886aab59a7Smrg 2896aab59a7Smrg do { 290b73be646Smrg n = read(pInfo->fd, pBuf, sizeof(Firm_event)); 291b73be646Smrg 292b73be646Smrg if (n == 0) { 293b73be646Smrg break; 294b73be646Smrg } else if (n == -1) { 295b73be646Smrg switch (errno) { 296b73be646Smrg case EAGAIN: /* Nothing to read now */ 297b73be646Smrg n = 0; /* End loop, go on to flush events & return */ 298b73be646Smrg continue; 299b73be646Smrg case EINTR: /* Interrupted, try again */ 300b73be646Smrg continue; 301b73be646Smrg case ENODEV: /* May happen when USB mouse is unplugged */ 302b73be646Smrg /* We use X_NONE here because it doesn't alloc since we 303b73be646Smrg may be called from SIGIO handler */ 304b73be646Smrg xf86MsgVerb(X_NONE, 0, 305b73be646Smrg "%s: Device no longer present - removing.\n", 306b73be646Smrg pInfo->name); 307b73be646Smrg xf86RemoveEnabledDevice(pInfo); 308b73be646Smrg pVuidMse->remove_timer = 309b73be646Smrg TimerSet(pVuidMse->remove_timer, 0, 1, 310b73be646Smrg vuidRemoveMouse, pInfo); 311b73be646Smrg return; 312b73be646Smrg default: /* All other errors */ 313b73be646Smrg /* We use X_NONE here because it doesn't alloc since we 314b73be646Smrg may be called from SIGIO handler */ 315b73be646Smrg xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, 316b73be646Smrg strerror(errno)); 317b73be646Smrg return; 318b73be646Smrg } 319b73be646Smrg } else if (n != sizeof(Firm_event)) { 3206aab59a7Smrg xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", 3216aab59a7Smrg pInfo->name, n); 3226aab59a7Smrg } 3236aab59a7Smrg 3246aab59a7Smrg#ifdef DEBUG 3256aab59a7Smrg ErrorF("vuidReadInput: event type: %3d value: %5d\n", 3266aab59a7Smrg pVuidMse->event.id, pVuidMse->event.value); 3276aab59a7Smrg#endif 3286aab59a7Smrg 3296aab59a7Smrg if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { 3306aab59a7Smrg /* button */ 3316aab59a7Smrg int butnum = pVuidMse->event.id - BUT_FIRST; 3326aab59a7Smrg 3336aab59a7Smrg if (butnum < 3) 3346aab59a7Smrg butnum = 2 - butnum; 3356aab59a7Smrg if (!pVuidMse->event.value) 3366aab59a7Smrg buttons &= ~(1 << butnum); 3376aab59a7Smrg else 3386aab59a7Smrg buttons |= (1 << butnum); 3396aab59a7Smrg } else if (pVuidMse->event.id >= VLOC_FIRST && 3406aab59a7Smrg pVuidMse->event.id <= VLOC_LAST) { 3416aab59a7Smrg /* axis */ 3426aab59a7Smrg int delta = pVuidMse->event.value; 3436aab59a7Smrg switch(pVuidMse->event.id) { 3446aab59a7Smrg case LOC_X_DELTA: 3456aab59a7Smrg dx += delta; 3466aab59a7Smrg break; 3476aab59a7Smrg case LOC_Y_DELTA: 3486aab59a7Smrg dy -= delta; 3496aab59a7Smrg break; 3506aab59a7Smrg case LOC_X_ABSOLUTE: 3516aab59a7Smrg if (absXset) { 3526aab59a7Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 3536aab59a7Smrg } 3546aab59a7Smrg absX = delta; 3556aab59a7Smrg absXset = TRUE; 3566aab59a7Smrg break; 3576aab59a7Smrg case LOC_Y_ABSOLUTE: 3586aab59a7Smrg if (absYset) { 3596aab59a7Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 3606aab59a7Smrg } 3616aab59a7Smrg absY = delta; 3626aab59a7Smrg absYset = TRUE; 3636aab59a7Smrg break; 3646aab59a7Smrg } 3656aab59a7Smrg } 3666aab59a7Smrg#ifdef HAVE_VUID_WHEEL 3676aab59a7Smrg else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) { 3686aab59a7Smrg if (vuid_id_offset(pVuidMse->event.id) == 0) 3696aab59a7Smrg dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 3706aab59a7Smrg else 3716aab59a7Smrg dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 3726aab59a7Smrg } 3736aab59a7Smrg#endif 3746aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 3756aab59a7Smrg else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) { 3766aab59a7Smrg ScreenPtr ptrCurScreen; 3776aab59a7Smrg 3786aab59a7Smrg /* force sending absolute resolution scaling ioctl */ 3796aab59a7Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 3806aab59a7Smrg ptrCurScreen = miPointerGetScreen(pInfo->dev); 3816aab59a7Smrg vuidMouseSendScreenSize(ptrCurScreen, pVuidMse); 3826aab59a7Smrg } 3836aab59a7Smrg#endif 3846aab59a7Smrg 3856aab59a7Smrg } while (n != 0); 3866aab59a7Smrg 3876aab59a7Smrg if (absXset || absYset) { 3886aab59a7Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 3896aab59a7Smrg } 3906aab59a7Smrg 3916aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 3926aab59a7Smrg return; 3936aab59a7Smrg} 3946aab59a7Smrg 3956aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 3966aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse) 3976aab59a7Smrg{ 3986aab59a7Smrg InputInfoPtr pInfo = pVuidMse->pInfo; 3996aab59a7Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 4006aab59a7Smrg int result; 4016aab59a7Smrg 402b73be646Smrg if (!pScr->currentMode) 403b73be646Smrg return; 404b73be646Smrg 4056aab59a7Smrg if ((pVuidMse->absres.width != pScr->currentMode->HDisplay) || 4066aab59a7Smrg (pVuidMse->absres.height != pScr->currentMode->VDisplay)) 4076aab59a7Smrg { 4086aab59a7Smrg pVuidMse->absres.width = pScr->currentMode->HDisplay; 4096aab59a7Smrg pVuidMse->absres.height = pScr->currentMode->VDisplay; 4106aab59a7Smrg 4116aab59a7Smrg do { 4126aab59a7Smrg result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres)); 4136aab59a7Smrg } while ( (result != 0) && (errno == EINTR) ); 4146aab59a7Smrg 4156aab59a7Smrg if (result != 0) { 4166aab59a7Smrg xf86Msg(X_WARNING, 4176aab59a7Smrg "%s: couldn't set absolute mouse scaling resolution: %s\n", 4186aab59a7Smrg pInfo->name, strerror(errno)); 4196aab59a7Smrg#ifdef DEBUG 4206aab59a7Smrg } else { 4216aab59a7Smrg xf86Msg(X_INFO, 4226aab59a7Smrg "%s: absolute mouse scaling resolution set to %d x %d\n", 4236aab59a7Smrg pInfo->name, 4246aab59a7Smrg pVuidMse->absres.width, pVuidMse->absres.height); 4256aab59a7Smrg#endif 4266aab59a7Smrg } 4276aab59a7Smrg } 4286aab59a7Smrg} 4296aab59a7Smrg 4306aab59a7Smrgstatic void vuidMouseAdjustFrame(int index, int x, int y, int flags) 4316aab59a7Smrg{ 4326aab59a7Smrg ScrnInfoPtr pScrn = xf86Screens[index]; 4336aab59a7Smrg ScreenPtr pScreen = pScrn->pScreen; 4346aab59a7Smrg xf86AdjustFrameProc *wrappedAdjustFrame 4356aab59a7Smrg = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen); 4366aab59a7Smrg VuidMsePtr m; 4376aab59a7Smrg ScreenPtr ptrCurScreen; 4386aab59a7Smrg 4396aab59a7Smrg if(wrappedAdjustFrame) { 4406aab59a7Smrg pScrn->AdjustFrame = wrappedAdjustFrame; 4416aab59a7Smrg (*pScrn->AdjustFrame)(index, x, y, flags); 4426aab59a7Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 4436aab59a7Smrg } 4446aab59a7Smrg 4456aab59a7Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 4466aab59a7Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 4476aab59a7Smrg if (ptrCurScreen == pScreen) 4486aab59a7Smrg { 4496aab59a7Smrg vuidMouseSendScreenSize(pScreen, m); 4506aab59a7Smrg } 4516aab59a7Smrg } 4526aab59a7Smrg} 4536aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 4546aab59a7Smrg 4556aab59a7Smrg 4566aab59a7Smrgstatic int 4576aab59a7SmrgvuidMouseProc(DeviceIntPtr pPointer, int what) 4586aab59a7Smrg{ 4596aab59a7Smrg InputInfoPtr pInfo; 4606aab59a7Smrg MouseDevPtr pMse; 4616aab59a7Smrg VuidMsePtr pVuidMse; 4626aab59a7Smrg int ret = Success; 4636aab59a7Smrg int i; 4646aab59a7Smrg 4656aab59a7Smrg pInfo = pPointer->public.devicePrivate; 4666aab59a7Smrg pMse = pInfo->private; 4676aab59a7Smrg pMse->device = pPointer; 4686aab59a7Smrg 4696aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 4706aab59a7Smrg if (pVuidMse == NULL) { 4716aab59a7Smrg return BadImplementation; 4726aab59a7Smrg } 4736aab59a7Smrg 4746aab59a7Smrg switch (what) { 4756aab59a7Smrg 4766aab59a7Smrg case DEVICE_INIT: 4776aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 478b73be646Smrg 479b73be646Smrg#if HAS_DEVPRIVATEKEYREC 480b73be646Smrg if (!dixRegisterPrivateKey(&vuidMouseScreenIndex, PRIVATE_SCREEN, 0)) 481b73be646Smrg return BadAlloc; 482b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 483b73be646Smrg 4846aab59a7Smrg if (vuidMouseGeneration != serverGeneration) { 4856aab59a7Smrg for (i = 0; i < screenInfo.numScreens; i++) { 4866aab59a7Smrg ScreenPtr pScreen = screenInfo.screens[i]; 4876aab59a7Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 4886aab59a7Smrg vuidMouseSetScreenPrivate(pScreen, pScrn->AdjustFrame); 4896aab59a7Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 4906aab59a7Smrg } 4916aab59a7Smrg vuidMouseGeneration = serverGeneration; 4926aab59a7Smrg } 4936aab59a7Smrg#endif 4946aab59a7Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 4956aab59a7Smrg break; 4966aab59a7Smrg 4976aab59a7Smrg case DEVICE_ON: 4986aab59a7Smrg ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON); 4996aab59a7Smrg 5006aab59a7Smrg if ((ret == Success) && (pInfo->fd != -1)) { 5016aab59a7Smrg int fmt = VUID_FIRM_EVENT; 5026aab59a7Smrg 5036aab59a7Smrg if (pVuidMse->strmod) { 504fc27e79cSmrg /* Check to see if module is already pushed */ 505fc27e79cSmrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod)); 506fc27e79cSmrg 507fc27e79cSmrg if (i == 0) { /* Not already pushed */ 508fc27e79cSmrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod)); 509fc27e79cSmrg if (i < 0) { 510fc27e79cSmrg xf86Msg(X_WARNING, "%s: cannot push module '%s' " 511fc27e79cSmrg "onto mouse device: %s\n", pInfo->name, 512fc27e79cSmrg pVuidMse->strmod, strerror(errno)); 513bd3a1963Smrg free(pVuidMse->strmod); 514fc27e79cSmrg pVuidMse->strmod = NULL; 515fc27e79cSmrg } 5166aab59a7Smrg } 5176aab59a7Smrg } 518fc27e79cSmrg 5196aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt)); 5206aab59a7Smrg if (i < 0) { 5216aab59a7Smrg xf86Msg(X_WARNING, 5226aab59a7Smrg "%s: cannot set mouse device to VUID mode: %s\n", 5236aab59a7Smrg pInfo->name, strerror(errno)); 5246aab59a7Smrg } 5256aab59a7Smrg vuidMouseWheelInit(pInfo); 5266aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 5276aab59a7Smrg vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse); 5286aab59a7Smrg#endif 5296aab59a7Smrg xf86FlushInput(pInfo->fd); 530b73be646Smrg 531b73be646Smrg /* Allocate here so we don't alloc in ReadInput which may be called 532b73be646Smrg from SIGIO handler. */ 533b73be646Smrg if (pVuidMse->remove_timer == NULL) { 534b73be646Smrg pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer, 535b73be646Smrg 0, 0, NULL, NULL); 536b73be646Smrg } 5376aab59a7Smrg } 5386aab59a7Smrg break; 5396aab59a7Smrg 5406aab59a7Smrg case DEVICE_OFF: 5416aab59a7Smrg case DEVICE_CLOSE: 5426aab59a7Smrg if (pInfo->fd != -1) { 5436aab59a7Smrg if (pVuidMse->strmod) { 5446aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod)); 5456aab59a7Smrg if (i == -1) { 5466aab59a7Smrg xf86Msg(X_WARNING, 5476aab59a7Smrg "%s: cannot pop module '%s' off mouse device: %s\n", 5486aab59a7Smrg pInfo->name, pVuidMse->strmod, strerror(errno)); 5496aab59a7Smrg } 5506aab59a7Smrg } 5516aab59a7Smrg } 552b73be646Smrg if (pVuidMse->remove_timer) { 553b73be646Smrg TimerFree(pVuidMse->remove_timer); 554b73be646Smrg pVuidMse->remove_timer = NULL; 555b73be646Smrg } 5566aab59a7Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 5576aab59a7Smrg break; 5586aab59a7Smrg 5596aab59a7Smrg default: /* Should never be called, but just in case */ 5606aab59a7Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 5616aab59a7Smrg break; 5626aab59a7Smrg } 5636aab59a7Smrg return ret; 5646aab59a7Smrg} 5656aab59a7Smrg 5666aab59a7Smrgstatic Bool 5676aab59a7SmrgsunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 5686aab59a7Smrg{ 5696aab59a7Smrg /* The protocol is guaranteed to be one of the internalNames[] */ 5706aab59a7Smrg if (xf86NameCmp(protocol, "VUID") == 0) { 5716aab59a7Smrg return vuidPreInit(pInfo, protocol, flags); 5726aab59a7Smrg } 5736aab59a7Smrg return TRUE; 5746aab59a7Smrg} 5756aab59a7Smrg 5766aab59a7Smrgstatic const char ** 5776aab59a7SmrgBuiltinNames(void) 5786aab59a7Smrg{ 5796aab59a7Smrg return internalNames; 5806aab59a7Smrg} 5816aab59a7Smrg 5826aab59a7Smrgstatic Bool 5836aab59a7SmrgCheckProtocol(const char *protocol) 5846aab59a7Smrg{ 5856aab59a7Smrg int i; 5866aab59a7Smrg 5876aab59a7Smrg for (i = 0; internalNames[i]; i++) 5886aab59a7Smrg if (xf86NameCmp(protocol, internalNames[i]) == 0) 5896aab59a7Smrg return TRUE; 5906aab59a7Smrg 5916aab59a7Smrg return FALSE; 5926aab59a7Smrg} 5936aab59a7Smrg 5946aab59a7Smrgstatic const char * 5956aab59a7SmrgDefaultProtocol(void) 5966aab59a7Smrg{ 5976aab59a7Smrg return "Auto"; 5986aab59a7Smrg} 5996aab59a7Smrg 6006aab59a7Smrgstatic Bool 6016aab59a7SmrgsolarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol, 6026aab59a7Smrg const char **device) 6036aab59a7Smrg{ 6046aab59a7Smrg const char **pdev, **pproto; 6056aab59a7Smrg int fd = -1; 6066aab59a7Smrg Bool found; 6076aab59a7Smrg char *strmod; 6086aab59a7Smrg 6096aab59a7Smrg if (*device == NULL) { 6106aab59a7Smrg /* Check to see if xorg.conf or HAL specified a device to use */ 6116aab59a7Smrg *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 6126aab59a7Smrg if (*device == NULL) { 613bd3a1963Smrg *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 6146aab59a7Smrg } 6156aab59a7Smrg } 6166aab59a7Smrg 6176aab59a7Smrg if (*device != NULL) { 6186aab59a7Smrg strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 6196aab59a7Smrg if (strmod == NULL) { 620bd3a1963Smrg strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 6216aab59a7Smrg } 6226aab59a7Smrg if (strmod) { 6236aab59a7Smrg /* if a device name is already known, and a StreamsModule is 6246aab59a7Smrg specified to convert events to VUID, then we don't need to 6256aab59a7Smrg probe further */ 6266aab59a7Smrg *protocol = "VUID"; 6276aab59a7Smrg return TRUE; 6286aab59a7Smrg } 6296aab59a7Smrg } 6306aab59a7Smrg 6316aab59a7Smrg 6326aab59a7Smrg for (pdev = solarisMouseDevs; *pdev; pdev += 2) { 6336aab59a7Smrg pproto = pdev + 1; 6346aab59a7Smrg if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) && 6356aab59a7Smrg (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) { 6366aab59a7Smrg continue; 6376aab59a7Smrg } 6386aab59a7Smrg if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) { 6396aab59a7Smrg continue; 6406aab59a7Smrg } 6416aab59a7Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 6426aab59a7Smrg if (fd == -1) { 6436aab59a7Smrg#ifdef DEBUG 6446aab59a7Smrg ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno)); 6456aab59a7Smrg#endif 6466aab59a7Smrg } else { 6476aab59a7Smrg found = TRUE; 6486aab59a7Smrg if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) { 6496aab59a7Smrg int i, r; 6506aab59a7Smrg SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i)); 6516aab59a7Smrg if (r < 0) { 6526aab59a7Smrg found = FALSE; 6536aab59a7Smrg } 6546aab59a7Smrg } 6556aab59a7Smrg close(fd); 6566aab59a7Smrg if (found == TRUE) { 6576aab59a7Smrg if (*pproto != NULL) { 6586aab59a7Smrg *protocol = *pproto; 6596aab59a7Smrg } 6606aab59a7Smrg *device = *pdev; 6616aab59a7Smrg return TRUE; 6626aab59a7Smrg } 6636aab59a7Smrg } 6646aab59a7Smrg } 6656aab59a7Smrg return FALSE; 6666aab59a7Smrg} 6676aab59a7Smrg 6686aab59a7Smrgstatic const char * 6696aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 6706aab59a7Smrg{ 6716aab59a7Smrg const char *pdev = NULL; 6726aab59a7Smrg const char *pproto = NULL; 6736aab59a7Smrg MouseDevPtr pMse = pInfo->private; 6746aab59a7Smrg 6756aab59a7Smrg if (pInfo->fd == -1) { 6766aab59a7Smrg /* probe to find device/protocol to use */ 6776aab59a7Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 6786aab59a7Smrg /* Set the Device option. */ 679bd3a1963Smrg pInfo->options = 680bd3a1963Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 6816aab59a7Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 6826aab59a7Smrg pInfo->name, pdev); 6836aab59a7Smrg } 6846aab59a7Smrg } else if (pMse->protocolID == PROT_AUTO) { 685bd3a1963Smrg pdev = xf86CheckStrOption(pInfo->options, 6866aab59a7Smrg "Device", NULL); 6876aab59a7Smrg solarisMouseAutoProbe(pInfo, &pproto, &pdev); 6886aab59a7Smrg } 6896aab59a7Smrg return pproto; 6906aab59a7Smrg} 6916aab59a7Smrg 6926aab59a7Smrgstatic const char * 6936aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 6946aab59a7Smrg{ 6956aab59a7Smrg const char *pdev = NULL; 6966aab59a7Smrg const char *pproto = protocol; 6976aab59a7Smrg 6986aab59a7Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 6996aab59a7Smrg /* Set the Device option. */ 700bd3a1963Smrg pInfo->options = 701bd3a1963Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 7026aab59a7Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 7036aab59a7Smrg pInfo->name, pdev); 7046aab59a7Smrg } 7056aab59a7Smrg return pdev; 7066aab59a7Smrg} 7076aab59a7Smrg 7086aab59a7Smrgstatic int 7096aab59a7SmrgSupportedInterfaces(void) 7106aab59a7Smrg{ 7116aab59a7Smrg /* XXX This needs to be checked. */ 7126aab59a7Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; 7136aab59a7Smrg} 7146aab59a7Smrg 715bd3a1963SmrgOSMouseInfoPtr 716bd3a1963SmrgOSMouseInit(int flags) 7176aab59a7Smrg{ 7186aab59a7Smrg OSMouseInfoPtr p; 7196aab59a7Smrg 720bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 7216aab59a7Smrg if (!p) 7226aab59a7Smrg return NULL; 7236aab59a7Smrg p->SupportedInterfaces = SupportedInterfaces; 7246aab59a7Smrg p->BuiltinNames = BuiltinNames; 7256aab59a7Smrg p->CheckProtocol = CheckProtocol; 7266aab59a7Smrg p->PreInit = sunMousePreInit; 7276aab59a7Smrg p->DefaultProtocol = DefaultProtocol; 7286aab59a7Smrg p->SetupAuto = SetupAuto; 7296aab59a7Smrg p->FindDevice = FindDevice; 7306aab59a7Smrg 7316aab59a7Smrg return p; 7326aab59a7Smrg} 7336aab59a7Smrg 734