sun_mouse.c revision a73597f9
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 72a73597f9Smrg/* 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[] = { 83a73597f9Smrg "VUID", 84a73597f9Smrg NULL 856aab59a7Smrg}; 866aab59a7Smrg 876aab59a7Smrgstatic const char *solarisMouseDevs[] = { 88a73597f9Smrg /* Device file: Protocol: */ 89a73597f9Smrg "/dev/mouse", "VUID", /* USB or SPARC */ 906aab59a7Smrg#if defined(__i386) || defined(__x86) 91a73597f9Smrg "/dev/kdmouse", "PS/2", /* PS/2 */ 926aab59a7Smrg#endif 936aab59a7Smrg NULL 946aab59a7Smrg}; 956aab59a7Smrg 966aab59a7Smrgtypedef struct _VuidMseRec { 97a73597f9Smrg struct _VuidMseRec *next; 98a73597f9Smrg InputInfoPtr pInfo; 99a73597f9Smrg Firm_event event; 100a73597f9Smrg unsigned char * buffer; 101a73597f9Smrg char * strmod; 1026aab59a7Smrg Bool(*wrapped_device_control)(DeviceIntPtr device, int what); 1036aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 104a73597f9Smrg Ms_screen_resolution absres; 1056aab59a7Smrg#endif 106a73597f9Smrg OsTimerPtr remove_timer; /* Callback for removal on ENODEV */ 1076aab59a7Smrg} VuidMseRec, *VuidMsePtr; 1086aab59a7Smrg 109a73597f9Smrgstatic VuidMsePtr vuidMouseList = NULL; 1106aab59a7Smrg 1116aab59a7Smrgstatic int vuidMouseProc(DeviceIntPtr pPointer, int what); 1126aab59a7Smrgstatic void vuidReadInput(InputInfoPtr pInfo); 1136aab59a7Smrg 1146aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 115a73597f9Smrg# include "compat-api.h" 116a73597f9Smrg 1176aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse); 118a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL); 1196aab59a7Smrg 1206aab59a7Smrgstatic int vuidMouseGeneration = 0; 121b73be646Smrg 122b73be646Smrg#if HAS_DEVPRIVATEKEYREC 123b73be646Smrgstatic DevPrivateKeyRec vuidMouseScreenIndex; 124b73be646Smrg#else 1256aab59a7Smrgstatic int vuidMouseScreenIndex; 126b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 127b73be646Smrg 1286aab59a7Smrg#define vuidMouseGetScreenPrivate(s) ( \ 1296aab59a7Smrg dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex)) 1306aab59a7Smrg#define vuidMouseSetScreenPrivate(s,p) \ 1316aab59a7Smrg dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p) 1326aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 1336aab59a7Smrg 1346aab59a7Smrgstatic inline 1356aab59a7SmrgVuidMsePtr getVuidMsePriv(InputInfoPtr pInfo) 1366aab59a7Smrg{ 1376aab59a7Smrg VuidMsePtr m = vuidMouseList; 1386aab59a7Smrg 1396aab59a7Smrg while ((m != NULL) && (m->pInfo != pInfo)) { 140a73597f9Smrg m = m->next; 1416aab59a7Smrg } 1426aab59a7Smrg 1436aab59a7Smrg return m; 1446aab59a7Smrg} 1456aab59a7Smrg 146b73be646Smrg/* Called from OsTimer callback, since removing a device from the device 147b73be646Smrg list or changing pInfo->fd while xf86Wakeup is looping through the list 148b73be646Smrg causes server crashes */ 149b73be646Smrgstatic CARD32 150a73597f9SmrgvuidRemoveMouse(OsTimerPtr timer, CARD32 now, pointer arg) 151b73be646Smrg{ 152b73be646Smrg InputInfoPtr pInfo = (InputInfoPtr) arg; 153b73be646Smrg 154b73be646Smrg xf86DisableDevice(pInfo->dev, TRUE); 155b73be646Smrg 156b73be646Smrg return 0; /* All done, don't set to run again */ 157b73be646Smrg} 1586aab59a7Smrg 1596aab59a7Smrg/* 1606aab59a7Smrg * Initialize and enable the mouse wheel, if present. 1616aab59a7Smrg * 1626aab59a7Smrg * Returns 1 if mouse wheel was successfully enabled. 1636aab59a7Smrg * Returns 0 if an error occurred or if there is no mouse wheel. 1646aab59a7Smrg */ 1656aab59a7Smrgstatic int 1666aab59a7SmrgvuidMouseWheelInit(InputInfoPtr pInfo) 1676aab59a7Smrg{ 1686aab59a7Smrg#ifdef HAVE_VUID_WHEEL 1696aab59a7Smrg wheel_state wstate; 1706aab59a7Smrg int nwheel = -1; 1716aab59a7Smrg int i; 1726aab59a7Smrg 1736aab59a7Smrg wstate.vers = VUID_WHEEL_STATE_VERS; 1746aab59a7Smrg wstate.id = 0; 1756aab59a7Smrg wstate.stateflags = (uint32_t) -1; 1766aab59a7Smrg 1776aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel)); 1786aab59a7Smrg if (i != 0) 179a73597f9Smrg return (0); 1806aab59a7Smrg 1816aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate)); 1826aab59a7Smrg if (i != 0) { 183a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name); 184a73597f9Smrg return (0); 1856aab59a7Smrg } 1866aab59a7Smrg 1876aab59a7Smrg wstate.stateflags |= VUID_WHEEL_STATE_ENABLED; 1886aab59a7Smrg 1896aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate)); 1906aab59a7Smrg if (i != 0) { 191a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name); 192a73597f9Smrg return (0); 1936aab59a7Smrg } 1946aab59a7Smrg 1956aab59a7Smrg return (1); 1966aab59a7Smrg#else 1976aab59a7Smrg return (0); 1986aab59a7Smrg#endif 1996aab59a7Smrg} 2006aab59a7Smrg 2016aab59a7Smrg 2026aab59a7Smrg/* This function is called when the protocol is "VUID". */ 2036aab59a7Smrgstatic Bool 2046aab59a7SmrgvuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 2056aab59a7Smrg{ 2066aab59a7Smrg MouseDevPtr pMse = pInfo->private; 2076aab59a7Smrg VuidMsePtr pVuidMse; 208a73597f9Smrg 209a73597f9Smrg /* Ensure we don't add the same device twice */ 210a73597f9Smrg if (getVuidMsePriv(pInfo) != NULL) 211a73597f9Smrg return TRUE; 2126aab59a7Smrg 213bd3a1963Smrg pVuidMse = calloc(sizeof(VuidMseRec), 1); 2146aab59a7Smrg if (pVuidMse == NULL) { 215a73597f9Smrg xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); 216a73597f9Smrg free(pMse); 217a73597f9Smrg return FALSE; 2186aab59a7Smrg } 2196aab59a7Smrg 220fc27e79cSmrg pVuidMse->buffer = (unsigned char *)&pVuidMse->event; 221fc27e79cSmrg pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL); 222fc27e79cSmrg 2236aab59a7Smrg /* Setup the local procs. */ 2246aab59a7Smrg pVuidMse->wrapped_device_control = pInfo->device_control; 2256aab59a7Smrg pInfo->device_control = vuidMouseProc; 2266aab59a7Smrg pInfo->read_input = vuidReadInput; 2276aab59a7Smrg 2286aab59a7Smrg pMse->xisbscale = sizeof(Firm_event); 2296aab59a7Smrg 230a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 2316aab59a7Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 2326aab59a7Smrg#endif 2336aab59a7Smrg pVuidMse->pInfo = pInfo; 234a73597f9Smrg pVuidMse->next = vuidMouseList; 2356aab59a7Smrg vuidMouseList = pVuidMse; 2366aab59a7Smrg 237bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 2386aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 239bd3a1963Smrg#endif 2406aab59a7Smrg return TRUE; 2416aab59a7Smrg} 2426aab59a7Smrg 2436aab59a7Smrgstatic void 244a73597f9SmrgvuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY, 245a73597f9Smrg Bool *absXset, Bool *absYset) 2466aab59a7Smrg{ 2476aab59a7Smrg#ifdef DEBUG 248a73597f9Smrg ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY, 249a73597f9Smrg *absXset, *absYset); 2506aab59a7Smrg#endif 2516aab59a7Smrg if ((*absXset) && (*absYset)) { 252a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 253a73597f9Smrg /* is_absolute: */ TRUE, 254a73597f9Smrg /* first_valuator: */ 0, 255a73597f9Smrg /* num_valuators: */ 2, 256a73597f9Smrg absX, absY); 2576aab59a7Smrg } else if (*absXset) { 258a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 259a73597f9Smrg /* is_absolute: */ TRUE, 260a73597f9Smrg /* first_valuator: */ 0, 261a73597f9Smrg /* num_valuators: */ 1, 262a73597f9Smrg absX); 2636aab59a7Smrg } else if (*absYset) { 264a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 265a73597f9Smrg /* is_absolute: */ TRUE, 266a73597f9Smrg /* first_valuator: */ 1, 267a73597f9Smrg /* num_valuators: */ 1, 268a73597f9Smrg absY); 2696aab59a7Smrg } 2706aab59a7Smrg 2716aab59a7Smrg *absXset = FALSE; 2726aab59a7Smrg *absYset = FALSE; 2736aab59a7Smrg} 2746aab59a7Smrg 2756aab59a7Smrgstatic void 2766aab59a7SmrgvuidReadInput(InputInfoPtr pInfo) 2776aab59a7Smrg{ 2786aab59a7Smrg MouseDevPtr pMse; 2796aab59a7Smrg VuidMsePtr pVuidMse; 2806aab59a7Smrg int buttons; 2816aab59a7Smrg int dx = 0, dy = 0, dz = 0, dw = 0; 2826aab59a7Smrg unsigned int n; 2836aab59a7Smrg unsigned char *pBuf; 2846aab59a7Smrg int absX = 0, absY = 0; 2856aab59a7Smrg Bool absXset = FALSE, absYset = FALSE; 2866aab59a7Smrg 2876aab59a7Smrg pMse = pInfo->private; 2886aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 2896aab59a7Smrg buttons = pMse->lastButtons; 2906aab59a7Smrg pBuf = pVuidMse->buffer; 2916aab59a7Smrg n = 0; 2926aab59a7Smrg 2936aab59a7Smrg do { 294a73597f9Smrg n = read(pInfo->fd, pBuf, sizeof(Firm_event)); 295a73597f9Smrg 296a73597f9Smrg if (n == 0) { 297a73597f9Smrg break; 298a73597f9Smrg } else if (n == -1) { 299a73597f9Smrg switch (errno) { 300a73597f9Smrg case EAGAIN: /* Nothing to read now */ 301a73597f9Smrg n = 0; /* End loop, go on to flush events & return */ 302a73597f9Smrg continue; 303a73597f9Smrg case EINTR: /* Interrupted, try again */ 304a73597f9Smrg continue; 305a73597f9Smrg case ENODEV: /* May happen when USB mouse is unplugged */ 306a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 307a73597f9Smrg may be called from SIGIO handler. No longer true for 308a73597f9Smrg sigsafe logging, but matters for older servers */ 309a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, 310a73597f9Smrg "%s: Device no longer present - removing.\n", 311a73597f9Smrg pInfo->name); 312a73597f9Smrg xf86RemoveEnabledDevice(pInfo); 313a73597f9Smrg pVuidMse->remove_timer = 314a73597f9Smrg TimerSet(pVuidMse->remove_timer, 0, 1, 315a73597f9Smrg vuidRemoveMouse, pInfo); 316a73597f9Smrg return; 317a73597f9Smrg default: /* All other errors */ 318a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 319a73597f9Smrg may be called from SIGIO handler. No longer true for 320a73597f9Smrg sigsafe logging, but matters for older servers */ 321a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, "%s: Read error: %s\n", 322a73597f9Smrg pInfo->name, strerror(errno)); 323a73597f9Smrg return; 324a73597f9Smrg } 325a73597f9Smrg } else if (n != sizeof(Firm_event)) { 326a73597f9Smrg xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", 327a73597f9Smrg pInfo->name, n); 328a73597f9Smrg } 3296aab59a7Smrg 3306aab59a7Smrg#ifdef DEBUG 331a73597f9Smrg LogMessageVerbSigSafe("vuidReadInput: event type: %d value: %d\n", 332a73597f9Smrg pVuidMse->event.id, pVuidMse->event.value); 3336aab59a7Smrg#endif 3346aab59a7Smrg 335a73597f9Smrg if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { 336a73597f9Smrg /* button */ 337a73597f9Smrg int butnum = pVuidMse->event.id - BUT_FIRST; 338a73597f9Smrg 339a73597f9Smrg if (butnum < 3) 340a73597f9Smrg butnum = 2 - butnum; 341a73597f9Smrg if (!pVuidMse->event.value) 342a73597f9Smrg buttons &= ~(1 << butnum); 343a73597f9Smrg else 344a73597f9Smrg buttons |= (1 << butnum); 345a73597f9Smrg } else if (pVuidMse->event.id >= VLOC_FIRST && 346a73597f9Smrg pVuidMse->event.id <= VLOC_LAST) { 347a73597f9Smrg /* axis */ 348a73597f9Smrg int delta = pVuidMse->event.value; 349a73597f9Smrg switch(pVuidMse->event.id) { 350a73597f9Smrg case LOC_X_DELTA: 351a73597f9Smrg dx += delta; 352a73597f9Smrg break; 353a73597f9Smrg case LOC_Y_DELTA: 354a73597f9Smrg dy -= delta; 355a73597f9Smrg break; 356a73597f9Smrg case LOC_X_ABSOLUTE: 357a73597f9Smrg if (absXset) { 358a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 359a73597f9Smrg } 360a73597f9Smrg absX = delta; 361a73597f9Smrg absXset = TRUE; 362a73597f9Smrg break; 363a73597f9Smrg case LOC_Y_ABSOLUTE: 364a73597f9Smrg if (absYset) { 365a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 366a73597f9Smrg } 367a73597f9Smrg absY = delta; 368a73597f9Smrg absYset = TRUE; 369a73597f9Smrg break; 370a73597f9Smrg } 371a73597f9Smrg } 3726aab59a7Smrg#ifdef HAVE_VUID_WHEEL 373a73597f9Smrg else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) { 374a73597f9Smrg if (vuid_id_offset(pVuidMse->event.id) == 0) 375a73597f9Smrg dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 376a73597f9Smrg else 377a73597f9Smrg dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 378a73597f9Smrg } 3796aab59a7Smrg#endif 3806aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 381a73597f9Smrg else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) { 382a73597f9Smrg ScreenPtr ptrCurScreen; 383a73597f9Smrg 384a73597f9Smrg /* force sending absolute resolution scaling ioctl */ 385a73597f9Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 386a73597f9Smrg ptrCurScreen = miPointerGetScreen(pInfo->dev); 387a73597f9Smrg vuidMouseSendScreenSize(ptrCurScreen, pVuidMse); 388a73597f9Smrg } 3896aab59a7Smrg#endif 3906aab59a7Smrg 3916aab59a7Smrg } while (n != 0); 3926aab59a7Smrg 3936aab59a7Smrg if (absXset || absYset) { 394a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 3956aab59a7Smrg } 3966aab59a7Smrg 3976aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 3986aab59a7Smrg return; 3996aab59a7Smrg} 4006aab59a7Smrg 4016aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 4026aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse) 4036aab59a7Smrg{ 4046aab59a7Smrg InputInfoPtr pInfo = pVuidMse->pInfo; 4056aab59a7Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 4066aab59a7Smrg int result; 4076aab59a7Smrg 408b73be646Smrg if (!pScr->currentMode) 409a73597f9Smrg return; 410b73be646Smrg 411a73597f9Smrg if ((pVuidMse->absres.width != pScr->currentMode->HDisplay) || 412a73597f9Smrg (pVuidMse->absres.height != pScr->currentMode->VDisplay)) 4136aab59a7Smrg { 414a73597f9Smrg pVuidMse->absres.width = pScr->currentMode->HDisplay; 415a73597f9Smrg pVuidMse->absres.height = pScr->currentMode->VDisplay; 4166aab59a7Smrg 417a73597f9Smrg do { 418a73597f9Smrg result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres)); 419a73597f9Smrg } while ( (result != 0) && (errno == EINTR) ); 4206aab59a7Smrg 421a73597f9Smrg if (result != 0) { 422a73597f9Smrg LogMessageVerbSigSafe(X_WARNING, -1, 423a73597f9Smrg "%s: couldn't set absolute mouse scaling resolution: %s\n", 424a73597f9Smrg pInfo->name, strerror(errno)); 4256aab59a7Smrg#ifdef DEBUG 426a73597f9Smrg } else { 427a73597f9Smrg LogMessageVerbSigSafe(X_INFO, 428a73597f9Smrg "%s: absolute mouse scaling resolution set to %d x %d\n", 429a73597f9Smrg pInfo->name, 430a73597f9Smrg pVuidMse->absres.width, 431a73597f9Smrg pVuidMse->absres.height); 4326aab59a7Smrg#endif 433a73597f9Smrg } 4346aab59a7Smrg } 4356aab59a7Smrg} 4366aab59a7Smrg 437a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL) 4386aab59a7Smrg{ 439a73597f9Smrg SCRN_INFO_PTR(arg); 440a73597f9Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 441a73597f9Smrg xf86AdjustFrameProc *wrappedAdjustFrame 442a73597f9Smrg = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen); 443a73597f9Smrg VuidMsePtr m; 444a73597f9Smrg ScreenPtr ptrCurScreen; 445a73597f9Smrg 446a73597f9Smrg if (wrappedAdjustFrame) { 447a73597f9Smrg pScrn->AdjustFrame = wrappedAdjustFrame; 448a73597f9Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 449a73597f9Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 4506aab59a7Smrg } 4516aab59a7Smrg 4526aab59a7Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 453a73597f9Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 454a73597f9Smrg if (ptrCurScreen == pScreen) 455a73597f9Smrg { 456a73597f9Smrg vuidMouseSendScreenSize(pScreen, m); 457a73597f9Smrg } 4586aab59a7Smrg } 4596aab59a7Smrg} 4606aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 4616aab59a7Smrg 4626aab59a7Smrg 4636aab59a7Smrgstatic int 4646aab59a7SmrgvuidMouseProc(DeviceIntPtr pPointer, int what) 4656aab59a7Smrg{ 4666aab59a7Smrg InputInfoPtr pInfo; 4676aab59a7Smrg MouseDevPtr pMse; 4686aab59a7Smrg VuidMsePtr pVuidMse; 4696aab59a7Smrg int ret = Success; 4706aab59a7Smrg int i; 4716aab59a7Smrg 4726aab59a7Smrg pInfo = pPointer->public.devicePrivate; 4736aab59a7Smrg pMse = pInfo->private; 4746aab59a7Smrg pMse->device = pPointer; 4756aab59a7Smrg 4766aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 4776aab59a7Smrg if (pVuidMse == NULL) { 478a73597f9Smrg return BadImplementation; 4796aab59a7Smrg } 480a73597f9Smrg 4816aab59a7Smrg switch (what) { 4826aab59a7Smrg 4836aab59a7Smrg case DEVICE_INIT: 4846aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 485b73be646Smrg 486b73be646Smrg#if HAS_DEVPRIVATEKEYREC 487a73597f9Smrg if (!dixRegisterPrivateKey(&vuidMouseScreenIndex, PRIVATE_SCREEN, 0)) 488a73597f9Smrg return BadAlloc; 489b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 490b73be646Smrg 491a73597f9Smrg if (vuidMouseGeneration != serverGeneration) { 492a73597f9Smrg for (i = 0; i < screenInfo.numScreens; i++) { 493a73597f9Smrg ScreenPtr pScreen = screenInfo.screens[i]; 494a73597f9Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 495a73597f9Smrg vuidMouseSetScreenPrivate(pScreen, pScrn->AdjustFrame); 496a73597f9Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 497a73597f9Smrg } 498a73597f9Smrg vuidMouseGeneration = serverGeneration; 499a73597f9Smrg } 500a73597f9Smrg#endif 501a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 502a73597f9Smrg break; 503a73597f9Smrg 5046aab59a7Smrg case DEVICE_ON: 505a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON); 506a73597f9Smrg 507a73597f9Smrg if ((ret == Success) && (pInfo->fd != -1)) { 508a73597f9Smrg int fmt = VUID_FIRM_EVENT; 509a73597f9Smrg 510a73597f9Smrg if (pVuidMse->strmod) { 511a73597f9Smrg /* Check to see if module is already pushed */ 512a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod)); 513a73597f9Smrg 514a73597f9Smrg if (i == 0) { /* Not already pushed */ 515a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod)); 516a73597f9Smrg if (i < 0) { 517a73597f9Smrg xf86Msg(X_WARNING, "%s: cannot push module '%s' " 518a73597f9Smrg "onto mouse device: %s\n", pInfo->name, 519a73597f9Smrg pVuidMse->strmod, strerror(errno)); 520a73597f9Smrg free(pVuidMse->strmod); 521a73597f9Smrg pVuidMse->strmod = NULL; 522a73597f9Smrg } 523a73597f9Smrg } 524a73597f9Smrg } 525a73597f9Smrg 526a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt)); 527a73597f9Smrg if (i < 0) { 528a73597f9Smrg xf86Msg(X_WARNING, 529a73597f9Smrg "%s: cannot set mouse device to VUID mode: %s\n", 530a73597f9Smrg pInfo->name, strerror(errno)); 531a73597f9Smrg } 532a73597f9Smrg vuidMouseWheelInit(pInfo); 533a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 534a73597f9Smrg vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse); 535a73597f9Smrg#endif 536a73597f9Smrg xf86FlushInput(pInfo->fd); 537a73597f9Smrg 538a73597f9Smrg /* Allocate here so we don't alloc in ReadInput which may be called 539a73597f9Smrg from SIGIO handler. */ 540a73597f9Smrg if (pVuidMse->remove_timer == NULL) { 541a73597f9Smrg pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer, 542a73597f9Smrg 0, 0, NULL, NULL); 543a73597f9Smrg } 544a73597f9Smrg } 545a73597f9Smrg break; 5466aab59a7Smrg 5476aab59a7Smrg case DEVICE_OFF: 5486aab59a7Smrg case DEVICE_CLOSE: 549a73597f9Smrg if (pInfo->fd != -1) { 550a73597f9Smrg if (pVuidMse->strmod) { 551a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod)); 552a73597f9Smrg if (i == -1) { 553a73597f9Smrg xf86Msg(X_WARNING, 554a73597f9Smrg "%s: cannot pop module '%s' off mouse device: %s\n", 555a73597f9Smrg pInfo->name, pVuidMse->strmod, strerror(errno)); 556a73597f9Smrg } 557a73597f9Smrg } 558a73597f9Smrg } 559a73597f9Smrg if (pVuidMse->remove_timer) { 560a73597f9Smrg TimerFree(pVuidMse->remove_timer); 561a73597f9Smrg pVuidMse->remove_timer = NULL; 562a73597f9Smrg } 563a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 564a73597f9Smrg break; 5656aab59a7Smrg 5666aab59a7Smrg default: /* Should never be called, but just in case */ 567a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 568a73597f9Smrg break; 5696aab59a7Smrg } 5706aab59a7Smrg return ret; 5716aab59a7Smrg} 5726aab59a7Smrg 5736aab59a7Smrgstatic Bool 5746aab59a7SmrgsunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 5756aab59a7Smrg{ 5766aab59a7Smrg /* The protocol is guaranteed to be one of the internalNames[] */ 5776aab59a7Smrg if (xf86NameCmp(protocol, "VUID") == 0) { 578a73597f9Smrg return vuidPreInit(pInfo, protocol, flags); 5796aab59a7Smrg } 5806aab59a7Smrg return TRUE; 581a73597f9Smrg} 5826aab59a7Smrg 5836aab59a7Smrgstatic const char ** 5846aab59a7SmrgBuiltinNames(void) 5856aab59a7Smrg{ 5866aab59a7Smrg return internalNames; 5876aab59a7Smrg} 5886aab59a7Smrg 5896aab59a7Smrgstatic Bool 5906aab59a7SmrgCheckProtocol(const char *protocol) 5916aab59a7Smrg{ 5926aab59a7Smrg int i; 5936aab59a7Smrg 5946aab59a7Smrg for (i = 0; internalNames[i]; i++) 595a73597f9Smrg if (xf86NameCmp(protocol, internalNames[i]) == 0) 596a73597f9Smrg return TRUE; 5976aab59a7Smrg 5986aab59a7Smrg return FALSE; 5996aab59a7Smrg} 6006aab59a7Smrg 6016aab59a7Smrgstatic const char * 6026aab59a7SmrgDefaultProtocol(void) 6036aab59a7Smrg{ 6046aab59a7Smrg return "Auto"; 6056aab59a7Smrg} 6066aab59a7Smrg 6076aab59a7Smrgstatic Bool 608a73597f9SmrgsolarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol, 609a73597f9Smrg const char **device) 6106aab59a7Smrg{ 6116aab59a7Smrg const char **pdev, **pproto; 6126aab59a7Smrg int fd = -1; 6136aab59a7Smrg Bool found; 6146aab59a7Smrg char *strmod; 6156aab59a7Smrg 6166aab59a7Smrg if (*device == NULL) { 617a73597f9Smrg /* Check to see if xorg.conf or HAL specified a device to use */ 618a73597f9Smrg *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 6196aab59a7Smrg } 6206aab59a7Smrg 6216aab59a7Smrg if (*device != NULL) { 622a73597f9Smrg strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 623a73597f9Smrg if (strmod) { 624a73597f9Smrg /* if a device name is already known, and a StreamsModule is 625a73597f9Smrg specified to convert events to VUID, then we don't need to 626a73597f9Smrg probe further */ 627a73597f9Smrg *protocol = "VUID"; 628a73597f9Smrg return TRUE; 629a73597f9Smrg } 6306aab59a7Smrg } 6316aab59a7Smrg 6326aab59a7Smrg 6336aab59a7Smrg for (pdev = solarisMouseDevs; *pdev; pdev += 2) { 634a73597f9Smrg pproto = pdev + 1; 635a73597f9Smrg if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) && 636a73597f9Smrg (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) { 637a73597f9Smrg continue; 638a73597f9Smrg } 639a73597f9Smrg if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) { 640a73597f9Smrg continue; 641a73597f9Smrg } 6426aab59a7Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 643a73597f9Smrg if (fd == -1) { 6446aab59a7Smrg#ifdef DEBUG 645a73597f9Smrg ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno)); 6466aab59a7Smrg#endif 647a73597f9Smrg } else { 648a73597f9Smrg found = TRUE; 649a73597f9Smrg if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) { 650a73597f9Smrg int i, r; 651a73597f9Smrg SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i)); 652a73597f9Smrg if (r < 0) { 653a73597f9Smrg found = FALSE; 654a73597f9Smrg } 655a73597f9Smrg } 656a73597f9Smrg close(fd); 657a73597f9Smrg if (found == TRUE) { 658a73597f9Smrg if (*pproto != NULL) { 659a73597f9Smrg *protocol = *pproto; 660a73597f9Smrg } 661a73597f9Smrg *device = *pdev; 662a73597f9Smrg return TRUE; 663a73597f9Smrg } 664a73597f9Smrg } 6656aab59a7Smrg } 6666aab59a7Smrg return FALSE; 6676aab59a7Smrg} 6686aab59a7Smrg 6696aab59a7Smrgstatic const char * 6706aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 6716aab59a7Smrg{ 6726aab59a7Smrg const char *pdev = NULL; 6736aab59a7Smrg const char *pproto = NULL; 6746aab59a7Smrg MouseDevPtr pMse = pInfo->private; 6756aab59a7Smrg 6766aab59a7Smrg if (pInfo->fd == -1) { 677a73597f9Smrg /* probe to find device/protocol to use */ 678a73597f9Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 679a73597f9Smrg /* Set the Device option. */ 680a73597f9Smrg pInfo->options = 681a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 682a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 683a73597f9Smrg pInfo->name, pdev); 684a73597f9Smrg } 6856aab59a7Smrg } else if (pMse->protocolID == PROT_AUTO) { 686a73597f9Smrg pdev = xf86CheckStrOption(pInfo->options, 687a73597f9Smrg "Device", NULL); 688a73597f9Smrg if ((solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) && 689a73597f9Smrg (pproto != NULL)) 690a73597f9Smrg sunMousePreInit(pInfo, pproto, 0); 6916aab59a7Smrg } 6926aab59a7Smrg return pproto; 6936aab59a7Smrg} 6946aab59a7Smrg 6956aab59a7Smrgstatic const char * 6966aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 6976aab59a7Smrg{ 6986aab59a7Smrg const char *pdev = NULL; 6996aab59a7Smrg const char *pproto = protocol; 7006aab59a7Smrg 7016aab59a7Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 702a73597f9Smrg /* Set the Device option. */ 703a73597f9Smrg pInfo->options = 704a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 705a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 706a73597f9Smrg pInfo->name, pdev); 7076aab59a7Smrg } 7086aab59a7Smrg return pdev; 7096aab59a7Smrg} 7106aab59a7Smrg 7116aab59a7Smrgstatic int 7126aab59a7SmrgSupportedInterfaces(void) 7136aab59a7Smrg{ 7146aab59a7Smrg /* XXX This needs to be checked. */ 7156aab59a7Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; 7166aab59a7Smrg} 7176aab59a7Smrg 718bd3a1963SmrgOSMouseInfoPtr 719bd3a1963SmrgOSMouseInit(int flags) 7206aab59a7Smrg{ 7216aab59a7Smrg OSMouseInfoPtr p; 7226aab59a7Smrg 723bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 7246aab59a7Smrg if (!p) 725a73597f9Smrg return NULL; 7266aab59a7Smrg p->SupportedInterfaces = SupportedInterfaces; 7276aab59a7Smrg p->BuiltinNames = BuiltinNames; 7286aab59a7Smrg p->CheckProtocol = CheckProtocol; 7296aab59a7Smrg p->PreInit = sunMousePreInit; 7306aab59a7Smrg p->DefaultProtocol = DefaultProtocol; 7316aab59a7Smrg p->SetupAuto = SetupAuto; 7326aab59a7Smrg p->FindDevice = FindDevice; 7336aab59a7Smrg 7346aab59a7Smrg return p; 7356aab59a7Smrg} 7366aab59a7Smrg 737