sun_mouse.c revision 84bf8334
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" 6084bf8334Smrg#include "xf86Crtc.h" 616aab59a7Smrg#include <sys/stropts.h> 626aab59a7Smrg#include <sys/vuid_event.h> 636aab59a7Smrg#include <sys/msio.h> 646aab59a7Smrg 656aab59a7Smrg/* Wheel mouse support in VUID drivers in Solaris 9 updates & Solaris 10 */ 666aab59a7Smrg#ifdef WHEEL_DEVID /* Defined in vuid_event.h if VUID wheel support present */ 676aab59a7Smrg# define HAVE_VUID_WHEEL 686aab59a7Smrg#endif 696aab59a7Smrg#ifdef HAVE_VUID_WHEEL 706aab59a7Smrg# include <sys/vuid_wheel.h> 716aab59a7Smrg#endif 726aab59a7Smrg 73a73597f9Smrg/* Support for scaling absolute coordinates to screen size in 746aab59a7Smrg * Solaris 10 updates and beyond */ 756aab59a7Smrg#if !defined(HAVE_ABSOLUTE_MOUSE_SCALING) 766aab59a7Smrg# ifdef MSIOSRESOLUTION /* Defined in msio.h if scaling support present */ 776aab59a7Smrg# define HAVE_ABSOLUTE_MOUSE_SCALING 786aab59a7Smrg# endif 796aab59a7Smrg#endif 806aab59a7Smrg 816aab59a7Smrg/* Names of protocols that are handled internally here. */ 826aab59a7Smrg 836aab59a7Smrgstatic const char *internalNames[] = { 84a73597f9Smrg "VUID", 85a73597f9Smrg NULL 866aab59a7Smrg}; 876aab59a7Smrg 886aab59a7Smrgstatic const char *solarisMouseDevs[] = { 89a73597f9Smrg /* Device file: Protocol: */ 90a73597f9Smrg "/dev/mouse", "VUID", /* USB or SPARC */ 916aab59a7Smrg#if defined(__i386) || defined(__x86) 92a73597f9Smrg "/dev/kdmouse", "PS/2", /* PS/2 */ 936aab59a7Smrg#endif 946aab59a7Smrg NULL 956aab59a7Smrg}; 966aab59a7Smrg 976aab59a7Smrgtypedef struct _VuidMseRec { 98a73597f9Smrg struct _VuidMseRec *next; 99a73597f9Smrg InputInfoPtr pInfo; 100a73597f9Smrg Firm_event event; 101a73597f9Smrg unsigned char * buffer; 102a73597f9Smrg char * strmod; 1036aab59a7Smrg Bool(*wrapped_device_control)(DeviceIntPtr device, int what); 1046aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 105a73597f9Smrg Ms_screen_resolution absres; 1066aab59a7Smrg#endif 107a73597f9Smrg OsTimerPtr remove_timer; /* Callback for removal on ENODEV */ 1086aab59a7Smrg} VuidMseRec, *VuidMsePtr; 1096aab59a7Smrg 110a73597f9Smrgstatic VuidMsePtr vuidMouseList = NULL; 1116aab59a7Smrg 1126aab59a7Smrgstatic int vuidMouseProc(DeviceIntPtr pPointer, int what); 1136aab59a7Smrgstatic void vuidReadInput(InputInfoPtr pInfo); 1146aab59a7Smrg 1156aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 116a73597f9Smrg# include "compat-api.h" 117a73597f9Smrg 1186aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse); 119a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL); 1206aab59a7Smrg 1216aab59a7Smrgstatic int vuidMouseGeneration = 0; 122b73be646Smrg 123b73be646Smrg#if HAS_DEVPRIVATEKEYREC 124b73be646Smrgstatic DevPrivateKeyRec vuidMouseScreenIndex; 125b73be646Smrg#else 1266aab59a7Smrgstatic int vuidMouseScreenIndex; 127b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 128b73be646Smrg 1296aab59a7Smrg#define vuidMouseGetScreenPrivate(s) ( \ 1306aab59a7Smrg dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex)) 1316aab59a7Smrg#define vuidMouseSetScreenPrivate(s,p) \ 1326aab59a7Smrg dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p) 1336aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 1346aab59a7Smrg 1356aab59a7Smrgstatic inline 1366aab59a7SmrgVuidMsePtr getVuidMsePriv(InputInfoPtr pInfo) 1376aab59a7Smrg{ 1386aab59a7Smrg VuidMsePtr m = vuidMouseList; 1396aab59a7Smrg 1406aab59a7Smrg while ((m != NULL) && (m->pInfo != pInfo)) { 141a73597f9Smrg m = m->next; 1426aab59a7Smrg } 1436aab59a7Smrg 1446aab59a7Smrg return m; 1456aab59a7Smrg} 1466aab59a7Smrg 147b73be646Smrg/* Called from OsTimer callback, since removing a device from the device 148b73be646Smrg list or changing pInfo->fd while xf86Wakeup is looping through the list 149b73be646Smrg causes server crashes */ 150b73be646Smrgstatic CARD32 151a73597f9SmrgvuidRemoveMouse(OsTimerPtr timer, CARD32 now, pointer arg) 152b73be646Smrg{ 153b73be646Smrg InputInfoPtr pInfo = (InputInfoPtr) arg; 154b73be646Smrg 155b73be646Smrg xf86DisableDevice(pInfo->dev, TRUE); 156b73be646Smrg 157b73be646Smrg return 0; /* All done, don't set to run again */ 158b73be646Smrg} 1596aab59a7Smrg 1606aab59a7Smrg/* 1616aab59a7Smrg * Initialize and enable the mouse wheel, if present. 1626aab59a7Smrg * 1636aab59a7Smrg * Returns 1 if mouse wheel was successfully enabled. 1646aab59a7Smrg * Returns 0 if an error occurred or if there is no mouse wheel. 1656aab59a7Smrg */ 1666aab59a7Smrgstatic int 1676aab59a7SmrgvuidMouseWheelInit(InputInfoPtr pInfo) 1686aab59a7Smrg{ 1696aab59a7Smrg#ifdef HAVE_VUID_WHEEL 1706aab59a7Smrg wheel_state wstate; 1716aab59a7Smrg int nwheel = -1; 1726aab59a7Smrg int i; 1736aab59a7Smrg 1746aab59a7Smrg wstate.vers = VUID_WHEEL_STATE_VERS; 1756aab59a7Smrg wstate.id = 0; 1766aab59a7Smrg wstate.stateflags = (uint32_t) -1; 1776aab59a7Smrg 1786aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel)); 1796aab59a7Smrg if (i != 0) 180a73597f9Smrg return (0); 1816aab59a7Smrg 1826aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate)); 1836aab59a7Smrg if (i != 0) { 184a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name); 185a73597f9Smrg return (0); 1866aab59a7Smrg } 1876aab59a7Smrg 1886aab59a7Smrg wstate.stateflags |= VUID_WHEEL_STATE_ENABLED; 1896aab59a7Smrg 1906aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate)); 1916aab59a7Smrg if (i != 0) { 192a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name); 193a73597f9Smrg return (0); 1946aab59a7Smrg } 1956aab59a7Smrg 1966aab59a7Smrg return (1); 1976aab59a7Smrg#else 1986aab59a7Smrg return (0); 1996aab59a7Smrg#endif 2006aab59a7Smrg} 2016aab59a7Smrg 2026aab59a7Smrg 2036aab59a7Smrg/* This function is called when the protocol is "VUID". */ 2046aab59a7Smrgstatic Bool 2056aab59a7SmrgvuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 2066aab59a7Smrg{ 2076aab59a7Smrg MouseDevPtr pMse = pInfo->private; 2086aab59a7Smrg VuidMsePtr pVuidMse; 209a73597f9Smrg 210a73597f9Smrg /* Ensure we don't add the same device twice */ 211a73597f9Smrg if (getVuidMsePriv(pInfo) != NULL) 212a73597f9Smrg return TRUE; 2136aab59a7Smrg 214bd3a1963Smrg pVuidMse = calloc(sizeof(VuidMseRec), 1); 2156aab59a7Smrg if (pVuidMse == NULL) { 216a73597f9Smrg xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); 217a73597f9Smrg free(pMse); 218a73597f9Smrg return FALSE; 2196aab59a7Smrg } 2206aab59a7Smrg 221fc27e79cSmrg pVuidMse->buffer = (unsigned char *)&pVuidMse->event; 222fc27e79cSmrg pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL); 223fc27e79cSmrg 2246aab59a7Smrg /* Setup the local procs. */ 2256aab59a7Smrg pVuidMse->wrapped_device_control = pInfo->device_control; 2266aab59a7Smrg pInfo->device_control = vuidMouseProc; 2276aab59a7Smrg pInfo->read_input = vuidReadInput; 2286aab59a7Smrg 2296aab59a7Smrg pMse->xisbscale = sizeof(Firm_event); 2306aab59a7Smrg 231a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 2326aab59a7Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 2336aab59a7Smrg#endif 2346aab59a7Smrg pVuidMse->pInfo = pInfo; 235a73597f9Smrg pVuidMse->next = vuidMouseList; 2366aab59a7Smrg vuidMouseList = pVuidMse; 2376aab59a7Smrg 238bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 2396aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 240bd3a1963Smrg#endif 2416aab59a7Smrg return TRUE; 2426aab59a7Smrg} 2436aab59a7Smrg 2446aab59a7Smrgstatic void 245a73597f9SmrgvuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY, 246a73597f9Smrg Bool *absXset, Bool *absYset) 2476aab59a7Smrg{ 2486aab59a7Smrg#ifdef DEBUG 249a73597f9Smrg ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY, 250a73597f9Smrg *absXset, *absYset); 2516aab59a7Smrg#endif 2526aab59a7Smrg if ((*absXset) && (*absYset)) { 253a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 254a73597f9Smrg /* is_absolute: */ TRUE, 255a73597f9Smrg /* first_valuator: */ 0, 256a73597f9Smrg /* num_valuators: */ 2, 257a73597f9Smrg absX, absY); 2586aab59a7Smrg } else if (*absXset) { 259a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 260a73597f9Smrg /* is_absolute: */ TRUE, 261a73597f9Smrg /* first_valuator: */ 0, 262a73597f9Smrg /* num_valuators: */ 1, 263a73597f9Smrg absX); 2646aab59a7Smrg } else if (*absYset) { 265a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 266a73597f9Smrg /* is_absolute: */ TRUE, 267a73597f9Smrg /* first_valuator: */ 1, 268a73597f9Smrg /* num_valuators: */ 1, 269a73597f9Smrg absY); 2706aab59a7Smrg } 2716aab59a7Smrg 2726aab59a7Smrg *absXset = FALSE; 2736aab59a7Smrg *absYset = FALSE; 2746aab59a7Smrg} 2756aab59a7Smrg 2766aab59a7Smrgstatic void 2776aab59a7SmrgvuidReadInput(InputInfoPtr pInfo) 2786aab59a7Smrg{ 2796aab59a7Smrg MouseDevPtr pMse; 2806aab59a7Smrg VuidMsePtr pVuidMse; 2816aab59a7Smrg int buttons; 2826aab59a7Smrg int dx = 0, dy = 0, dz = 0, dw = 0; 2836aab59a7Smrg unsigned int n; 2846aab59a7Smrg unsigned char *pBuf; 2856aab59a7Smrg int absX = 0, absY = 0; 2866aab59a7Smrg Bool absXset = FALSE, absYset = FALSE; 2876aab59a7Smrg 2886aab59a7Smrg pMse = pInfo->private; 2896aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 2906aab59a7Smrg buttons = pMse->lastButtons; 2916aab59a7Smrg pBuf = pVuidMse->buffer; 2926aab59a7Smrg n = 0; 2936aab59a7Smrg 2946aab59a7Smrg do { 295a73597f9Smrg n = read(pInfo->fd, pBuf, sizeof(Firm_event)); 296a73597f9Smrg 297a73597f9Smrg if (n == 0) { 298a73597f9Smrg break; 299a73597f9Smrg } else if (n == -1) { 300a73597f9Smrg switch (errno) { 301a73597f9Smrg case EAGAIN: /* Nothing to read now */ 302a73597f9Smrg n = 0; /* End loop, go on to flush events & return */ 303a73597f9Smrg continue; 304a73597f9Smrg case EINTR: /* Interrupted, try again */ 305a73597f9Smrg continue; 306a73597f9Smrg case ENODEV: /* May happen when USB mouse is unplugged */ 307a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 308a73597f9Smrg may be called from SIGIO handler. No longer true for 309a73597f9Smrg sigsafe logging, but matters for older servers */ 310a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, 311a73597f9Smrg "%s: Device no longer present - removing.\n", 312a73597f9Smrg pInfo->name); 313a73597f9Smrg xf86RemoveEnabledDevice(pInfo); 314a73597f9Smrg pVuidMse->remove_timer = 315a73597f9Smrg TimerSet(pVuidMse->remove_timer, 0, 1, 316a73597f9Smrg vuidRemoveMouse, pInfo); 317a73597f9Smrg return; 318a73597f9Smrg default: /* All other errors */ 319a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 320a73597f9Smrg may be called from SIGIO handler. No longer true for 321a73597f9Smrg sigsafe logging, but matters for older servers */ 322a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, "%s: Read error: %s\n", 323a73597f9Smrg pInfo->name, strerror(errno)); 324a73597f9Smrg return; 325a73597f9Smrg } 326a73597f9Smrg } else if (n != sizeof(Firm_event)) { 327a73597f9Smrg xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", 328a73597f9Smrg pInfo->name, n); 329a73597f9Smrg } 3306aab59a7Smrg 3316aab59a7Smrg#ifdef DEBUG 332a73597f9Smrg LogMessageVerbSigSafe("vuidReadInput: event type: %d value: %d\n", 333a73597f9Smrg pVuidMse->event.id, pVuidMse->event.value); 3346aab59a7Smrg#endif 3356aab59a7Smrg 336a73597f9Smrg if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { 337a73597f9Smrg /* button */ 338a73597f9Smrg int butnum = pVuidMse->event.id - BUT_FIRST; 339a73597f9Smrg 340a73597f9Smrg if (butnum < 3) 341a73597f9Smrg butnum = 2 - butnum; 342a73597f9Smrg if (!pVuidMse->event.value) 343a73597f9Smrg buttons &= ~(1 << butnum); 344a73597f9Smrg else 345a73597f9Smrg buttons |= (1 << butnum); 346a73597f9Smrg } else if (pVuidMse->event.id >= VLOC_FIRST && 347a73597f9Smrg pVuidMse->event.id <= VLOC_LAST) { 348a73597f9Smrg /* axis */ 349a73597f9Smrg int delta = pVuidMse->event.value; 350a73597f9Smrg switch(pVuidMse->event.id) { 351a73597f9Smrg case LOC_X_DELTA: 352a73597f9Smrg dx += delta; 353a73597f9Smrg break; 354a73597f9Smrg case LOC_Y_DELTA: 355a73597f9Smrg dy -= delta; 356a73597f9Smrg break; 357a73597f9Smrg case LOC_X_ABSOLUTE: 358a73597f9Smrg if (absXset) { 359a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 360a73597f9Smrg } 361a73597f9Smrg absX = delta; 362a73597f9Smrg absXset = TRUE; 363a73597f9Smrg break; 364a73597f9Smrg case LOC_Y_ABSOLUTE: 365a73597f9Smrg if (absYset) { 366a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 367a73597f9Smrg } 368a73597f9Smrg absY = delta; 369a73597f9Smrg absYset = TRUE; 370a73597f9Smrg break; 371a73597f9Smrg } 372a73597f9Smrg } 3736aab59a7Smrg#ifdef HAVE_VUID_WHEEL 374a73597f9Smrg else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) { 375a73597f9Smrg if (vuid_id_offset(pVuidMse->event.id) == 0) 376a73597f9Smrg dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 377a73597f9Smrg else 378a73597f9Smrg dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 379a73597f9Smrg } 3806aab59a7Smrg#endif 3816aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 382a73597f9Smrg else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) { 383a73597f9Smrg ScreenPtr ptrCurScreen; 384a73597f9Smrg 385a73597f9Smrg /* force sending absolute resolution scaling ioctl */ 386a73597f9Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 387a73597f9Smrg ptrCurScreen = miPointerGetScreen(pInfo->dev); 388a73597f9Smrg vuidMouseSendScreenSize(ptrCurScreen, pVuidMse); 389a73597f9Smrg } 3906aab59a7Smrg#endif 3916aab59a7Smrg 3926aab59a7Smrg } while (n != 0); 3936aab59a7Smrg 3946aab59a7Smrg if (absXset || absYset) { 395a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 3966aab59a7Smrg } 3976aab59a7Smrg 3986aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 3996aab59a7Smrg return; 4006aab59a7Smrg} 4016aab59a7Smrg 4026aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 4036aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse) 4046aab59a7Smrg{ 4056aab59a7Smrg InputInfoPtr pInfo = pVuidMse->pInfo; 4066aab59a7Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 4076aab59a7Smrg int result; 4086aab59a7Smrg 40984bf8334Smrg if ((pVuidMse->absres.width != pScr->virtualX) || 41084bf8334Smrg (pVuidMse->absres.height != pScr->virtualY)) 4116aab59a7Smrg { 41284bf8334Smrg pVuidMse->absres.width = pScr->virtualX; 41384bf8334Smrg pVuidMse->absres.height = pScr->virtualY; 4146aab59a7Smrg 415a73597f9Smrg do { 416a73597f9Smrg result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres)); 417a73597f9Smrg } while ( (result != 0) && (errno == EINTR) ); 4186aab59a7Smrg 419a73597f9Smrg if (result != 0) { 420a73597f9Smrg LogMessageVerbSigSafe(X_WARNING, -1, 421a73597f9Smrg "%s: couldn't set absolute mouse scaling resolution: %s\n", 422a73597f9Smrg pInfo->name, strerror(errno)); 4236aab59a7Smrg#ifdef DEBUG 424a73597f9Smrg } else { 425a73597f9Smrg LogMessageVerbSigSafe(X_INFO, 426a73597f9Smrg "%s: absolute mouse scaling resolution set to %d x %d\n", 427a73597f9Smrg pInfo->name, 428a73597f9Smrg pVuidMse->absres.width, 429a73597f9Smrg pVuidMse->absres.height); 4306aab59a7Smrg#endif 431a73597f9Smrg } 4326aab59a7Smrg } 4336aab59a7Smrg} 4346aab59a7Smrg 435a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL) 4366aab59a7Smrg{ 437a73597f9Smrg SCRN_INFO_PTR(arg); 438a73597f9Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 439a73597f9Smrg xf86AdjustFrameProc *wrappedAdjustFrame 440a73597f9Smrg = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen); 441a73597f9Smrg VuidMsePtr m; 442a73597f9Smrg ScreenPtr ptrCurScreen; 443a73597f9Smrg 444a73597f9Smrg if (wrappedAdjustFrame) { 445a73597f9Smrg pScrn->AdjustFrame = wrappedAdjustFrame; 446a73597f9Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 447a73597f9Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 4486aab59a7Smrg } 4496aab59a7Smrg 4506aab59a7Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 451a73597f9Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 452a73597f9Smrg if (ptrCurScreen == pScreen) 453a73597f9Smrg { 454a73597f9Smrg vuidMouseSendScreenSize(pScreen, m); 455a73597f9Smrg } 4566aab59a7Smrg } 4576aab59a7Smrg} 45884bf8334Smrg 45984bf8334Smrgstatic void vuidMouseCrtcNotify(ScreenPtr pScreen) 46084bf8334Smrg{ 46184bf8334Smrg xf86_crtc_notify_proc_ptr wrappedCrtcNotify 46284bf8334Smrg = (xf86_crtc_notify_proc_ptr) vuidMouseGetScreenPrivate(pScreen); 46384bf8334Smrg VuidMsePtr m; 46484bf8334Smrg ScreenPtr ptrCurScreen; 46584bf8334Smrg 46684bf8334Smrg if (wrappedCrtcNotify) 46784bf8334Smrg wrappedCrtcNotify(pScreen); 46884bf8334Smrg 46984bf8334Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 47084bf8334Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 47184bf8334Smrg if (ptrCurScreen == pScreen) { 47284bf8334Smrg vuidMouseSendScreenSize(pScreen, m); 47384bf8334Smrg } 47484bf8334Smrg } 47584bf8334Smrg} 4766aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 4776aab59a7Smrg 4786aab59a7Smrg 4796aab59a7Smrgstatic int 4806aab59a7SmrgvuidMouseProc(DeviceIntPtr pPointer, int what) 4816aab59a7Smrg{ 4826aab59a7Smrg InputInfoPtr pInfo; 4836aab59a7Smrg MouseDevPtr pMse; 4846aab59a7Smrg VuidMsePtr pVuidMse; 4856aab59a7Smrg int ret = Success; 4866aab59a7Smrg int i; 4876aab59a7Smrg 4886aab59a7Smrg pInfo = pPointer->public.devicePrivate; 4896aab59a7Smrg pMse = pInfo->private; 4906aab59a7Smrg pMse->device = pPointer; 4916aab59a7Smrg 4926aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 4936aab59a7Smrg if (pVuidMse == NULL) { 494a73597f9Smrg return BadImplementation; 4956aab59a7Smrg } 496a73597f9Smrg 4976aab59a7Smrg switch (what) { 4986aab59a7Smrg 4996aab59a7Smrg case DEVICE_INIT: 5006aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 501b73be646Smrg 502b73be646Smrg#if HAS_DEVPRIVATEKEYREC 503a73597f9Smrg if (!dixRegisterPrivateKey(&vuidMouseScreenIndex, PRIVATE_SCREEN, 0)) 504a73597f9Smrg return BadAlloc; 505b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 506b73be646Smrg 507a73597f9Smrg if (vuidMouseGeneration != serverGeneration) { 508a73597f9Smrg for (i = 0; i < screenInfo.numScreens; i++) { 509a73597f9Smrg ScreenPtr pScreen = screenInfo.screens[i]; 510a73597f9Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 51184bf8334Smrg if (xf86CrtcConfigPrivateIndex != -1) { 51284bf8334Smrg xf86_crtc_notify_proc_ptr pCrtcNotify 51384bf8334Smrg = xf86_wrap_crtc_notify(pScreen, 51484bf8334Smrg vuidMouseCrtcNotify); 51584bf8334Smrg vuidMouseSetScreenPrivate(pScreen, pCrtcNotify); 51684bf8334Smrg } else { 51784bf8334Smrg vuidMouseSetScreenPrivate(pScreen, 51884bf8334Smrg pScrn->AdjustFrame); 51984bf8334Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 52084bf8334Smrg } 521a73597f9Smrg } 522a73597f9Smrg vuidMouseGeneration = serverGeneration; 523a73597f9Smrg } 524a73597f9Smrg#endif 525a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 526a73597f9Smrg break; 527a73597f9Smrg 5286aab59a7Smrg case DEVICE_ON: 529a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON); 530a73597f9Smrg 531a73597f9Smrg if ((ret == Success) && (pInfo->fd != -1)) { 532a73597f9Smrg int fmt = VUID_FIRM_EVENT; 533a73597f9Smrg 534a73597f9Smrg if (pVuidMse->strmod) { 535a73597f9Smrg /* Check to see if module is already pushed */ 536a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod)); 537a73597f9Smrg 538a73597f9Smrg if (i == 0) { /* Not already pushed */ 539a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod)); 540a73597f9Smrg if (i < 0) { 541a73597f9Smrg xf86Msg(X_WARNING, "%s: cannot push module '%s' " 542a73597f9Smrg "onto mouse device: %s\n", pInfo->name, 543a73597f9Smrg pVuidMse->strmod, strerror(errno)); 544a73597f9Smrg free(pVuidMse->strmod); 545a73597f9Smrg pVuidMse->strmod = NULL; 546a73597f9Smrg } 547a73597f9Smrg } 548a73597f9Smrg } 549a73597f9Smrg 550a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt)); 551a73597f9Smrg if (i < 0) { 552a73597f9Smrg xf86Msg(X_WARNING, 553a73597f9Smrg "%s: cannot set mouse device to VUID mode: %s\n", 554a73597f9Smrg pInfo->name, strerror(errno)); 555a73597f9Smrg } 556a73597f9Smrg vuidMouseWheelInit(pInfo); 557a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 558a73597f9Smrg vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse); 559a73597f9Smrg#endif 560a73597f9Smrg xf86FlushInput(pInfo->fd); 561a73597f9Smrg 562a73597f9Smrg /* Allocate here so we don't alloc in ReadInput which may be called 563a73597f9Smrg from SIGIO handler. */ 564a73597f9Smrg if (pVuidMse->remove_timer == NULL) { 565a73597f9Smrg pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer, 566a73597f9Smrg 0, 0, NULL, NULL); 567a73597f9Smrg } 568a73597f9Smrg } 569a73597f9Smrg break; 5706aab59a7Smrg 5716aab59a7Smrg case DEVICE_OFF: 5726aab59a7Smrg case DEVICE_CLOSE: 573a73597f9Smrg if (pInfo->fd != -1) { 574a73597f9Smrg if (pVuidMse->strmod) { 575a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod)); 576a73597f9Smrg if (i == -1) { 577a73597f9Smrg xf86Msg(X_WARNING, 578a73597f9Smrg "%s: cannot pop module '%s' off mouse device: %s\n", 579a73597f9Smrg pInfo->name, pVuidMse->strmod, strerror(errno)); 580a73597f9Smrg } 581a73597f9Smrg } 582a73597f9Smrg } 583a73597f9Smrg if (pVuidMse->remove_timer) { 584a73597f9Smrg TimerFree(pVuidMse->remove_timer); 585a73597f9Smrg pVuidMse->remove_timer = NULL; 586a73597f9Smrg } 587a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 588a73597f9Smrg break; 5896aab59a7Smrg 5906aab59a7Smrg default: /* Should never be called, but just in case */ 591a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 592a73597f9Smrg break; 5936aab59a7Smrg } 5946aab59a7Smrg return ret; 5956aab59a7Smrg} 5966aab59a7Smrg 5976aab59a7Smrgstatic Bool 5986aab59a7SmrgsunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 5996aab59a7Smrg{ 6006aab59a7Smrg /* The protocol is guaranteed to be one of the internalNames[] */ 6016aab59a7Smrg if (xf86NameCmp(protocol, "VUID") == 0) { 602a73597f9Smrg return vuidPreInit(pInfo, protocol, flags); 6036aab59a7Smrg } 6046aab59a7Smrg return TRUE; 605a73597f9Smrg} 6066aab59a7Smrg 6076aab59a7Smrgstatic const char ** 6086aab59a7SmrgBuiltinNames(void) 6096aab59a7Smrg{ 6106aab59a7Smrg return internalNames; 6116aab59a7Smrg} 6126aab59a7Smrg 6136aab59a7Smrgstatic Bool 6146aab59a7SmrgCheckProtocol(const char *protocol) 6156aab59a7Smrg{ 6166aab59a7Smrg int i; 6176aab59a7Smrg 6186aab59a7Smrg for (i = 0; internalNames[i]; i++) 619a73597f9Smrg if (xf86NameCmp(protocol, internalNames[i]) == 0) 620a73597f9Smrg return TRUE; 6216aab59a7Smrg 6226aab59a7Smrg return FALSE; 6236aab59a7Smrg} 6246aab59a7Smrg 6256aab59a7Smrgstatic const char * 6266aab59a7SmrgDefaultProtocol(void) 6276aab59a7Smrg{ 6286aab59a7Smrg return "Auto"; 6296aab59a7Smrg} 6306aab59a7Smrg 6316aab59a7Smrgstatic Bool 632a73597f9SmrgsolarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol, 633a73597f9Smrg const char **device) 6346aab59a7Smrg{ 6356aab59a7Smrg const char **pdev, **pproto; 6366aab59a7Smrg int fd = -1; 6376aab59a7Smrg Bool found; 6386aab59a7Smrg char *strmod; 6396aab59a7Smrg 6406aab59a7Smrg if (*device == NULL) { 641a73597f9Smrg /* Check to see if xorg.conf or HAL specified a device to use */ 642a73597f9Smrg *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 6436aab59a7Smrg } 6446aab59a7Smrg 6456aab59a7Smrg if (*device != NULL) { 646a73597f9Smrg strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 647a73597f9Smrg if (strmod) { 648a73597f9Smrg /* if a device name is already known, and a StreamsModule is 649a73597f9Smrg specified to convert events to VUID, then we don't need to 650a73597f9Smrg probe further */ 651a73597f9Smrg *protocol = "VUID"; 652a73597f9Smrg return TRUE; 653a73597f9Smrg } 6546aab59a7Smrg } 6556aab59a7Smrg 6566aab59a7Smrg 6576aab59a7Smrg for (pdev = solarisMouseDevs; *pdev; pdev += 2) { 658a73597f9Smrg pproto = pdev + 1; 659a73597f9Smrg if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) && 660a73597f9Smrg (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) { 661a73597f9Smrg continue; 662a73597f9Smrg } 663a73597f9Smrg if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) { 664a73597f9Smrg continue; 665a73597f9Smrg } 6666aab59a7Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 667a73597f9Smrg if (fd == -1) { 6686aab59a7Smrg#ifdef DEBUG 669a73597f9Smrg ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno)); 6706aab59a7Smrg#endif 671a73597f9Smrg } else { 672a73597f9Smrg found = TRUE; 673a73597f9Smrg if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) { 674a73597f9Smrg int i, r; 675a73597f9Smrg SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i)); 676a73597f9Smrg if (r < 0) { 677a73597f9Smrg found = FALSE; 678a73597f9Smrg } 679a73597f9Smrg } 680a73597f9Smrg close(fd); 681a73597f9Smrg if (found == TRUE) { 682a73597f9Smrg if (*pproto != NULL) { 683a73597f9Smrg *protocol = *pproto; 684a73597f9Smrg } 685a73597f9Smrg *device = *pdev; 686a73597f9Smrg return TRUE; 687a73597f9Smrg } 688a73597f9Smrg } 6896aab59a7Smrg } 6906aab59a7Smrg return FALSE; 6916aab59a7Smrg} 6926aab59a7Smrg 6936aab59a7Smrgstatic const char * 6946aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 6956aab59a7Smrg{ 6966aab59a7Smrg const char *pdev = NULL; 6976aab59a7Smrg const char *pproto = NULL; 6986aab59a7Smrg MouseDevPtr pMse = pInfo->private; 6996aab59a7Smrg 7006aab59a7Smrg if (pInfo->fd == -1) { 701a73597f9Smrg /* probe to find device/protocol to use */ 702a73597f9Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 703a73597f9Smrg /* Set the Device option. */ 704a73597f9Smrg pInfo->options = 705a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 706a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 707a73597f9Smrg pInfo->name, pdev); 708a73597f9Smrg } 7096aab59a7Smrg } else if (pMse->protocolID == PROT_AUTO) { 710a73597f9Smrg pdev = xf86CheckStrOption(pInfo->options, 711a73597f9Smrg "Device", NULL); 712a73597f9Smrg if ((solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) && 713a73597f9Smrg (pproto != NULL)) 714a73597f9Smrg sunMousePreInit(pInfo, pproto, 0); 7156aab59a7Smrg } 7166aab59a7Smrg return pproto; 7176aab59a7Smrg} 7186aab59a7Smrg 7196aab59a7Smrgstatic const char * 7206aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 7216aab59a7Smrg{ 7226aab59a7Smrg const char *pdev = NULL; 7236aab59a7Smrg const char *pproto = protocol; 7246aab59a7Smrg 7256aab59a7Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 726a73597f9Smrg /* Set the Device option. */ 727a73597f9Smrg pInfo->options = 728a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 729a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 730a73597f9Smrg pInfo->name, pdev); 7316aab59a7Smrg } 7326aab59a7Smrg return pdev; 7336aab59a7Smrg} 7346aab59a7Smrg 7356aab59a7Smrgstatic int 7366aab59a7SmrgSupportedInterfaces(void) 7376aab59a7Smrg{ 7386aab59a7Smrg /* XXX This needs to be checked. */ 7396aab59a7Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; 7406aab59a7Smrg} 7416aab59a7Smrg 742bd3a1963SmrgOSMouseInfoPtr 743bd3a1963SmrgOSMouseInit(int flags) 7446aab59a7Smrg{ 7456aab59a7Smrg OSMouseInfoPtr p; 7466aab59a7Smrg 747bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 7486aab59a7Smrg if (!p) 749a73597f9Smrg return NULL; 7506aab59a7Smrg p->SupportedInterfaces = SupportedInterfaces; 7516aab59a7Smrg p->BuiltinNames = BuiltinNames; 7526aab59a7Smrg p->CheckProtocol = CheckProtocol; 7536aab59a7Smrg p->PreInit = sunMousePreInit; 7546aab59a7Smrg p->DefaultProtocol = DefaultProtocol; 7556aab59a7Smrg p->SetupAuto = SetupAuto; 7566aab59a7Smrg p->FindDevice = FindDevice; 7576aab59a7Smrg 7586aab59a7Smrg return p; 7596aab59a7Smrg} 7606aab59a7Smrg 761