sun_mouse.c revision 370b807f
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 50370b807fSmrg#ifdef HAVE_CONFIG_H 51370b807fSmrg#include "config.h" 52370b807fSmrg#endif 53370b807fSmrg 546aab59a7Smrg#ifdef HAVE_XORG_CONFIG_H 556aab59a7Smrg#include <xorg-config.h> 566aab59a7Smrg#endif 576aab59a7Smrg 586aab59a7Smrg#include "xorg-server.h" 596aab59a7Smrg#include "xf86.h" 606aab59a7Smrg#include "xf86_OSlib.h" 61bd3a1963Smrg#include "mouse.h" 626aab59a7Smrg#include "xisb.h" 636aab59a7Smrg#include "mipointer.h" 6484bf8334Smrg#include "xf86Crtc.h" 656aab59a7Smrg#include <sys/stropts.h> 666aab59a7Smrg#include <sys/vuid_event.h> 676aab59a7Smrg#include <sys/msio.h> 686aab59a7Smrg 696aab59a7Smrg/* Wheel mouse support in VUID drivers in Solaris 9 updates & Solaris 10 */ 706aab59a7Smrg#ifdef WHEEL_DEVID /* Defined in vuid_event.h if VUID wheel support present */ 716aab59a7Smrg# define HAVE_VUID_WHEEL 726aab59a7Smrg#endif 736aab59a7Smrg#ifdef HAVE_VUID_WHEEL 746aab59a7Smrg# include <sys/vuid_wheel.h> 756aab59a7Smrg#endif 766aab59a7Smrg 77a73597f9Smrg/* Support for scaling absolute coordinates to screen size in 786aab59a7Smrg * Solaris 10 updates and beyond */ 796aab59a7Smrg#if !defined(HAVE_ABSOLUTE_MOUSE_SCALING) 806aab59a7Smrg# ifdef MSIOSRESOLUTION /* Defined in msio.h if scaling support present */ 816aab59a7Smrg# define HAVE_ABSOLUTE_MOUSE_SCALING 826aab59a7Smrg# endif 836aab59a7Smrg#endif 846aab59a7Smrg 856aab59a7Smrg/* Names of protocols that are handled internally here. */ 866aab59a7Smrg 876aab59a7Smrgstatic const char *internalNames[] = { 88a73597f9Smrg "VUID", 89a73597f9Smrg NULL 906aab59a7Smrg}; 916aab59a7Smrg 926aab59a7Smrgstatic const char *solarisMouseDevs[] = { 93a73597f9Smrg /* Device file: Protocol: */ 94a73597f9Smrg "/dev/mouse", "VUID", /* USB or SPARC */ 956aab59a7Smrg#if defined(__i386) || defined(__x86) 96a73597f9Smrg "/dev/kdmouse", "PS/2", /* PS/2 */ 976aab59a7Smrg#endif 986aab59a7Smrg NULL 996aab59a7Smrg}; 1006aab59a7Smrg 1016aab59a7Smrgtypedef struct _VuidMseRec { 102a73597f9Smrg struct _VuidMseRec *next; 103a73597f9Smrg InputInfoPtr pInfo; 104a73597f9Smrg Firm_event event; 105a73597f9Smrg unsigned char * buffer; 106a73597f9Smrg char * strmod; 1076aab59a7Smrg Bool(*wrapped_device_control)(DeviceIntPtr device, int what); 1086aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 109a73597f9Smrg Ms_screen_resolution absres; 1106aab59a7Smrg#endif 111a73597f9Smrg OsTimerPtr remove_timer; /* Callback for removal on ENODEV */ 1126aab59a7Smrg} VuidMseRec, *VuidMsePtr; 1136aab59a7Smrg 114a73597f9Smrgstatic VuidMsePtr vuidMouseList = NULL; 1156aab59a7Smrg 1166aab59a7Smrgstatic int vuidMouseProc(DeviceIntPtr pPointer, int what); 1176aab59a7Smrgstatic void vuidReadInput(InputInfoPtr pInfo); 1186aab59a7Smrg 1196aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 120a73597f9Smrg# include "compat-api.h" 121a73597f9Smrg 1226aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse); 123a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL); 1246aab59a7Smrg 125370b807fSmrgstatic unsigned long vuidMouseGeneration = 0; 126b73be646Smrg 127b73be646Smrg#if HAS_DEVPRIVATEKEYREC 128b73be646Smrgstatic DevPrivateKeyRec vuidMouseScreenIndex; 129b73be646Smrg#else 1306aab59a7Smrgstatic int vuidMouseScreenIndex; 131b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 132b73be646Smrg 1336aab59a7Smrg#define vuidMouseGetScreenPrivate(s) ( \ 1346aab59a7Smrg dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex)) 1356aab59a7Smrg#define vuidMouseSetScreenPrivate(s,p) \ 1366aab59a7Smrg dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p) 1376aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 1386aab59a7Smrg 1396aab59a7Smrgstatic inline 1406aab59a7SmrgVuidMsePtr getVuidMsePriv(InputInfoPtr pInfo) 1416aab59a7Smrg{ 1426aab59a7Smrg VuidMsePtr m = vuidMouseList; 1436aab59a7Smrg 1446aab59a7Smrg while ((m != NULL) && (m->pInfo != pInfo)) { 145a73597f9Smrg m = m->next; 1466aab59a7Smrg } 1476aab59a7Smrg 1486aab59a7Smrg return m; 1496aab59a7Smrg} 1506aab59a7Smrg 151b73be646Smrg/* Called from OsTimer callback, since removing a device from the device 152b73be646Smrg list or changing pInfo->fd while xf86Wakeup is looping through the list 153b73be646Smrg causes server crashes */ 154b73be646Smrgstatic CARD32 155a73597f9SmrgvuidRemoveMouse(OsTimerPtr timer, CARD32 now, pointer arg) 156b73be646Smrg{ 157b73be646Smrg InputInfoPtr pInfo = (InputInfoPtr) arg; 158b73be646Smrg 159b73be646Smrg xf86DisableDevice(pInfo->dev, TRUE); 160b73be646Smrg 161b73be646Smrg return 0; /* All done, don't set to run again */ 162b73be646Smrg} 1636aab59a7Smrg 1646aab59a7Smrg/* 1656aab59a7Smrg * Initialize and enable the mouse wheel, if present. 1666aab59a7Smrg * 1676aab59a7Smrg * Returns 1 if mouse wheel was successfully enabled. 1686aab59a7Smrg * Returns 0 if an error occurred or if there is no mouse wheel. 1696aab59a7Smrg */ 1706aab59a7Smrgstatic int 1716aab59a7SmrgvuidMouseWheelInit(InputInfoPtr pInfo) 1726aab59a7Smrg{ 1736aab59a7Smrg#ifdef HAVE_VUID_WHEEL 1746aab59a7Smrg wheel_state wstate; 1756aab59a7Smrg int nwheel = -1; 1766aab59a7Smrg int i; 1776aab59a7Smrg 1786aab59a7Smrg wstate.vers = VUID_WHEEL_STATE_VERS; 1796aab59a7Smrg wstate.id = 0; 1806aab59a7Smrg wstate.stateflags = (uint32_t) -1; 1816aab59a7Smrg 1826aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel)); 1836aab59a7Smrg if (i != 0) 184a73597f9Smrg return (0); 1856aab59a7Smrg 1866aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate)); 1876aab59a7Smrg if (i != 0) { 188a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name); 189a73597f9Smrg return (0); 1906aab59a7Smrg } 1916aab59a7Smrg 1926aab59a7Smrg wstate.stateflags |= VUID_WHEEL_STATE_ENABLED; 1936aab59a7Smrg 1946aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate)); 1956aab59a7Smrg if (i != 0) { 196a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name); 197a73597f9Smrg return (0); 1986aab59a7Smrg } 1996aab59a7Smrg 2006aab59a7Smrg return (1); 2016aab59a7Smrg#else 2026aab59a7Smrg return (0); 2036aab59a7Smrg#endif 2046aab59a7Smrg} 2056aab59a7Smrg 2066aab59a7Smrg 2076aab59a7Smrg/* This function is called when the protocol is "VUID". */ 2086aab59a7Smrgstatic Bool 2096aab59a7SmrgvuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 2106aab59a7Smrg{ 2116aab59a7Smrg MouseDevPtr pMse = pInfo->private; 2126aab59a7Smrg VuidMsePtr pVuidMse; 213a73597f9Smrg 214a73597f9Smrg /* Ensure we don't add the same device twice */ 215a73597f9Smrg if (getVuidMsePriv(pInfo) != NULL) 216a73597f9Smrg return TRUE; 2176aab59a7Smrg 218bd3a1963Smrg pVuidMse = calloc(sizeof(VuidMseRec), 1); 2196aab59a7Smrg if (pVuidMse == NULL) { 220a73597f9Smrg xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); 221a73597f9Smrg free(pMse); 222a73597f9Smrg return FALSE; 2236aab59a7Smrg } 2246aab59a7Smrg 225fc27e79cSmrg pVuidMse->buffer = (unsigned char *)&pVuidMse->event; 226fc27e79cSmrg pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL); 227fc27e79cSmrg 2286aab59a7Smrg /* Setup the local procs. */ 2296aab59a7Smrg pVuidMse->wrapped_device_control = pInfo->device_control; 2306aab59a7Smrg pInfo->device_control = vuidMouseProc; 2316aab59a7Smrg pInfo->read_input = vuidReadInput; 2326aab59a7Smrg 2336aab59a7Smrg pMse->xisbscale = sizeof(Firm_event); 2346aab59a7Smrg 235a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 2366aab59a7Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 2376aab59a7Smrg#endif 2386aab59a7Smrg pVuidMse->pInfo = pInfo; 239a73597f9Smrg pVuidMse->next = vuidMouseList; 2406aab59a7Smrg vuidMouseList = pVuidMse; 2416aab59a7Smrg 242bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 2436aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 244bd3a1963Smrg#endif 2456aab59a7Smrg return TRUE; 2466aab59a7Smrg} 2476aab59a7Smrg 2486aab59a7Smrgstatic void 249a73597f9SmrgvuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY, 250a73597f9Smrg Bool *absXset, Bool *absYset) 2516aab59a7Smrg{ 2526aab59a7Smrg#ifdef DEBUG 253a73597f9Smrg ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY, 254a73597f9Smrg *absXset, *absYset); 2556aab59a7Smrg#endif 2566aab59a7Smrg if ((*absXset) && (*absYset)) { 257a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 258a73597f9Smrg /* is_absolute: */ TRUE, 259a73597f9Smrg /* first_valuator: */ 0, 260a73597f9Smrg /* num_valuators: */ 2, 261a73597f9Smrg absX, absY); 2626aab59a7Smrg } else if (*absXset) { 263a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 264a73597f9Smrg /* is_absolute: */ TRUE, 265a73597f9Smrg /* first_valuator: */ 0, 266a73597f9Smrg /* num_valuators: */ 1, 267a73597f9Smrg absX); 2686aab59a7Smrg } else if (*absYset) { 269a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 270a73597f9Smrg /* is_absolute: */ TRUE, 271a73597f9Smrg /* first_valuator: */ 1, 272a73597f9Smrg /* num_valuators: */ 1, 273a73597f9Smrg absY); 2746aab59a7Smrg } 2756aab59a7Smrg 2766aab59a7Smrg *absXset = FALSE; 2776aab59a7Smrg *absYset = FALSE; 2786aab59a7Smrg} 2796aab59a7Smrg 2806aab59a7Smrgstatic void 2816aab59a7SmrgvuidReadInput(InputInfoPtr pInfo) 2826aab59a7Smrg{ 2836aab59a7Smrg MouseDevPtr pMse; 2846aab59a7Smrg VuidMsePtr pVuidMse; 2856aab59a7Smrg int buttons; 2866aab59a7Smrg int dx = 0, dy = 0, dz = 0, dw = 0; 287370b807fSmrg ssize_t n; 2886aab59a7Smrg unsigned char *pBuf; 2896aab59a7Smrg int absX = 0, absY = 0; 2906aab59a7Smrg Bool absXset = FALSE, absYset = FALSE; 2916aab59a7Smrg 2926aab59a7Smrg pMse = pInfo->private; 2936aab59a7Smrg buttons = pMse->lastButtons; 294370b807fSmrg pVuidMse = getVuidMsePriv(pInfo); 295370b807fSmrg if (pVuidMse == NULL) { 296370b807fSmrg xf86Msg(X_ERROR, "%s: cannot locate VuidMsePtr\n", pInfo->name); 297370b807fSmrg return; 298370b807fSmrg } 2996aab59a7Smrg pBuf = pVuidMse->buffer; 3006aab59a7Smrg 3016aab59a7Smrg do { 302a73597f9Smrg n = read(pInfo->fd, pBuf, sizeof(Firm_event)); 303a73597f9Smrg 304a73597f9Smrg if (n == 0) { 305a73597f9Smrg break; 306a73597f9Smrg } else if (n == -1) { 307a73597f9Smrg switch (errno) { 308a73597f9Smrg case EAGAIN: /* Nothing to read now */ 309a73597f9Smrg n = 0; /* End loop, go on to flush events & return */ 310a73597f9Smrg continue; 311a73597f9Smrg case EINTR: /* Interrupted, try again */ 312a73597f9Smrg continue; 313a73597f9Smrg case ENODEV: /* May happen when USB mouse is unplugged */ 314a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 315a73597f9Smrg may be called from SIGIO handler. No longer true for 316a73597f9Smrg sigsafe logging, but matters for older servers */ 317a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, 318a73597f9Smrg "%s: Device no longer present - removing.\n", 319a73597f9Smrg pInfo->name); 320a73597f9Smrg xf86RemoveEnabledDevice(pInfo); 321a73597f9Smrg pVuidMse->remove_timer = 322a73597f9Smrg TimerSet(pVuidMse->remove_timer, 0, 1, 323a73597f9Smrg vuidRemoveMouse, pInfo); 324a73597f9Smrg return; 325a73597f9Smrg default: /* All other errors */ 326a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 327a73597f9Smrg may be called from SIGIO handler. No longer true for 328a73597f9Smrg sigsafe logging, but matters for older servers */ 329a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, "%s: Read error: %s\n", 330a73597f9Smrg pInfo->name, strerror(errno)); 331a73597f9Smrg return; 332a73597f9Smrg } 333a73597f9Smrg } else if (n != sizeof(Firm_event)) { 334370b807fSmrg xf86Msg(X_WARNING, "%s: incomplete packet, size %zd\n", 335a73597f9Smrg pInfo->name, n); 336a73597f9Smrg } 3376aab59a7Smrg 3386aab59a7Smrg#ifdef DEBUG 339a73597f9Smrg LogMessageVerbSigSafe("vuidReadInput: event type: %d value: %d\n", 340a73597f9Smrg pVuidMse->event.id, pVuidMse->event.value); 3416aab59a7Smrg#endif 3426aab59a7Smrg 343a73597f9Smrg if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { 344a73597f9Smrg /* button */ 345a73597f9Smrg int butnum = pVuidMse->event.id - BUT_FIRST; 346a73597f9Smrg 347a73597f9Smrg if (butnum < 3) 348a73597f9Smrg butnum = 2 - butnum; 349a73597f9Smrg if (!pVuidMse->event.value) 350a73597f9Smrg buttons &= ~(1 << butnum); 351a73597f9Smrg else 352a73597f9Smrg buttons |= (1 << butnum); 353a73597f9Smrg } else if (pVuidMse->event.id >= VLOC_FIRST && 354a73597f9Smrg pVuidMse->event.id <= VLOC_LAST) { 355a73597f9Smrg /* axis */ 356a73597f9Smrg int delta = pVuidMse->event.value; 357a73597f9Smrg switch(pVuidMse->event.id) { 358a73597f9Smrg case LOC_X_DELTA: 359a73597f9Smrg dx += delta; 360a73597f9Smrg break; 361a73597f9Smrg case LOC_Y_DELTA: 362a73597f9Smrg dy -= delta; 363a73597f9Smrg break; 364a73597f9Smrg case LOC_X_ABSOLUTE: 365a73597f9Smrg if (absXset) { 366a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 367a73597f9Smrg } 368a73597f9Smrg absX = delta; 369a73597f9Smrg absXset = TRUE; 370a73597f9Smrg break; 371a73597f9Smrg case LOC_Y_ABSOLUTE: 372a73597f9Smrg if (absYset) { 373a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 374a73597f9Smrg } 375a73597f9Smrg absY = delta; 376a73597f9Smrg absYset = TRUE; 377a73597f9Smrg break; 378a73597f9Smrg } 379a73597f9Smrg } 3806aab59a7Smrg#ifdef HAVE_VUID_WHEEL 381a73597f9Smrg else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) { 382a73597f9Smrg if (vuid_id_offset(pVuidMse->event.id) == 0) 383a73597f9Smrg dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 384a73597f9Smrg else 385a73597f9Smrg dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 386a73597f9Smrg } 3876aab59a7Smrg#endif 3886aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 389a73597f9Smrg else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) { 390a73597f9Smrg ScreenPtr ptrCurScreen; 391a73597f9Smrg 392a73597f9Smrg /* force sending absolute resolution scaling ioctl */ 393a73597f9Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 394a73597f9Smrg ptrCurScreen = miPointerGetScreen(pInfo->dev); 395a73597f9Smrg vuidMouseSendScreenSize(ptrCurScreen, pVuidMse); 396a73597f9Smrg } 3976aab59a7Smrg#endif 3986aab59a7Smrg 3996aab59a7Smrg } while (n != 0); 4006aab59a7Smrg 4016aab59a7Smrg if (absXset || absYset) { 402a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 4036aab59a7Smrg } 4046aab59a7Smrg 4056aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 4066aab59a7Smrg return; 4076aab59a7Smrg} 4086aab59a7Smrg 4096aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 4106aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse) 4116aab59a7Smrg{ 4126aab59a7Smrg InputInfoPtr pInfo = pVuidMse->pInfo; 4136aab59a7Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 4146aab59a7Smrg int result; 4156aab59a7Smrg 41684bf8334Smrg if ((pVuidMse->absres.width != pScr->virtualX) || 41784bf8334Smrg (pVuidMse->absres.height != pScr->virtualY)) 4186aab59a7Smrg { 41984bf8334Smrg pVuidMse->absres.width = pScr->virtualX; 42084bf8334Smrg pVuidMse->absres.height = pScr->virtualY; 4216aab59a7Smrg 422a73597f9Smrg do { 423a73597f9Smrg result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres)); 424a73597f9Smrg } while ( (result != 0) && (errno == EINTR) ); 4256aab59a7Smrg 426a73597f9Smrg if (result != 0) { 427a73597f9Smrg LogMessageVerbSigSafe(X_WARNING, -1, 428a73597f9Smrg "%s: couldn't set absolute mouse scaling resolution: %s\n", 429a73597f9Smrg pInfo->name, strerror(errno)); 4306aab59a7Smrg#ifdef DEBUG 431a73597f9Smrg } else { 432a73597f9Smrg LogMessageVerbSigSafe(X_INFO, 433a73597f9Smrg "%s: absolute mouse scaling resolution set to %d x %d\n", 434a73597f9Smrg pInfo->name, 435a73597f9Smrg pVuidMse->absres.width, 436a73597f9Smrg pVuidMse->absres.height); 4376aab59a7Smrg#endif 438a73597f9Smrg } 4396aab59a7Smrg } 4406aab59a7Smrg} 4416aab59a7Smrg 442a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL) 4436aab59a7Smrg{ 444a73597f9Smrg SCRN_INFO_PTR(arg); 445a73597f9Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 446a73597f9Smrg xf86AdjustFrameProc *wrappedAdjustFrame 447a73597f9Smrg = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen); 448a73597f9Smrg VuidMsePtr m; 449a73597f9Smrg ScreenPtr ptrCurScreen; 450a73597f9Smrg 451a73597f9Smrg if (wrappedAdjustFrame) { 452a73597f9Smrg pScrn->AdjustFrame = wrappedAdjustFrame; 453a73597f9Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 454a73597f9Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 4556aab59a7Smrg } 4566aab59a7Smrg 4576aab59a7Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 458a73597f9Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 459a73597f9Smrg if (ptrCurScreen == pScreen) 460a73597f9Smrg { 461a73597f9Smrg vuidMouseSendScreenSize(pScreen, m); 462a73597f9Smrg } 4636aab59a7Smrg } 4646aab59a7Smrg} 46584bf8334Smrg 46684bf8334Smrgstatic void vuidMouseCrtcNotify(ScreenPtr pScreen) 46784bf8334Smrg{ 46884bf8334Smrg xf86_crtc_notify_proc_ptr wrappedCrtcNotify 46984bf8334Smrg = (xf86_crtc_notify_proc_ptr) vuidMouseGetScreenPrivate(pScreen); 47084bf8334Smrg VuidMsePtr m; 47184bf8334Smrg ScreenPtr ptrCurScreen; 47284bf8334Smrg 47384bf8334Smrg if (wrappedCrtcNotify) 47484bf8334Smrg wrappedCrtcNotify(pScreen); 47584bf8334Smrg 47684bf8334Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 47784bf8334Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 47884bf8334Smrg if (ptrCurScreen == pScreen) { 47984bf8334Smrg vuidMouseSendScreenSize(pScreen, m); 48084bf8334Smrg } 48184bf8334Smrg } 48284bf8334Smrg} 4836aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 4846aab59a7Smrg 4856aab59a7Smrg 4866aab59a7Smrgstatic int 4876aab59a7SmrgvuidMouseProc(DeviceIntPtr pPointer, int what) 4886aab59a7Smrg{ 4896aab59a7Smrg InputInfoPtr pInfo; 4906aab59a7Smrg MouseDevPtr pMse; 4916aab59a7Smrg VuidMsePtr pVuidMse; 4926aab59a7Smrg int ret = Success; 4936aab59a7Smrg int i; 4946aab59a7Smrg 4956aab59a7Smrg pInfo = pPointer->public.devicePrivate; 4966aab59a7Smrg pMse = pInfo->private; 4976aab59a7Smrg pMse->device = pPointer; 4986aab59a7Smrg 4996aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 5006aab59a7Smrg if (pVuidMse == NULL) { 501a73597f9Smrg return BadImplementation; 5026aab59a7Smrg } 503a73597f9Smrg 5046aab59a7Smrg switch (what) { 5056aab59a7Smrg 5066aab59a7Smrg case DEVICE_INIT: 5076aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 508b73be646Smrg 509b73be646Smrg#if HAS_DEVPRIVATEKEYREC 510a73597f9Smrg if (!dixRegisterPrivateKey(&vuidMouseScreenIndex, PRIVATE_SCREEN, 0)) 511a73597f9Smrg return BadAlloc; 512b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 513b73be646Smrg 514a73597f9Smrg if (vuidMouseGeneration != serverGeneration) { 515a73597f9Smrg for (i = 0; i < screenInfo.numScreens; i++) { 516a73597f9Smrg ScreenPtr pScreen = screenInfo.screens[i]; 517a73597f9Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 51884bf8334Smrg if (xf86CrtcConfigPrivateIndex != -1) { 51984bf8334Smrg xf86_crtc_notify_proc_ptr pCrtcNotify 52084bf8334Smrg = xf86_wrap_crtc_notify(pScreen, 52184bf8334Smrg vuidMouseCrtcNotify); 52284bf8334Smrg vuidMouseSetScreenPrivate(pScreen, pCrtcNotify); 52384bf8334Smrg } else { 52484bf8334Smrg vuidMouseSetScreenPrivate(pScreen, 52584bf8334Smrg pScrn->AdjustFrame); 52684bf8334Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 52784bf8334Smrg } 528a73597f9Smrg } 529a73597f9Smrg vuidMouseGeneration = serverGeneration; 530a73597f9Smrg } 531a73597f9Smrg#endif 532a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 533a73597f9Smrg break; 534a73597f9Smrg 5356aab59a7Smrg case DEVICE_ON: 536a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON); 537a73597f9Smrg 538a73597f9Smrg if ((ret == Success) && (pInfo->fd != -1)) { 539a73597f9Smrg int fmt = VUID_FIRM_EVENT; 540a73597f9Smrg 541a73597f9Smrg if (pVuidMse->strmod) { 542a73597f9Smrg /* Check to see if module is already pushed */ 543a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod)); 544a73597f9Smrg 545a73597f9Smrg if (i == 0) { /* Not already pushed */ 546a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod)); 547a73597f9Smrg if (i < 0) { 548a73597f9Smrg xf86Msg(X_WARNING, "%s: cannot push module '%s' " 549a73597f9Smrg "onto mouse device: %s\n", pInfo->name, 550a73597f9Smrg pVuidMse->strmod, strerror(errno)); 551a73597f9Smrg free(pVuidMse->strmod); 552a73597f9Smrg pVuidMse->strmod = NULL; 553a73597f9Smrg } 554a73597f9Smrg } 555a73597f9Smrg } 556a73597f9Smrg 557a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt)); 558a73597f9Smrg if (i < 0) { 559a73597f9Smrg xf86Msg(X_WARNING, 560a73597f9Smrg "%s: cannot set mouse device to VUID mode: %s\n", 561a73597f9Smrg pInfo->name, strerror(errno)); 562a73597f9Smrg } 563a73597f9Smrg vuidMouseWheelInit(pInfo); 564a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 565a73597f9Smrg vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse); 566a73597f9Smrg#endif 567a73597f9Smrg xf86FlushInput(pInfo->fd); 568a73597f9Smrg 569a73597f9Smrg /* Allocate here so we don't alloc in ReadInput which may be called 570a73597f9Smrg from SIGIO handler. */ 571a73597f9Smrg if (pVuidMse->remove_timer == NULL) { 572a73597f9Smrg pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer, 573a73597f9Smrg 0, 0, NULL, NULL); 574a73597f9Smrg } 575a73597f9Smrg } 576a73597f9Smrg break; 5776aab59a7Smrg 5786aab59a7Smrg case DEVICE_OFF: 5796aab59a7Smrg case DEVICE_CLOSE: 580a73597f9Smrg if (pInfo->fd != -1) { 581a73597f9Smrg if (pVuidMse->strmod) { 582a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod)); 583a73597f9Smrg if (i == -1) { 584a73597f9Smrg xf86Msg(X_WARNING, 585a73597f9Smrg "%s: cannot pop module '%s' off mouse device: %s\n", 586a73597f9Smrg pInfo->name, pVuidMse->strmod, strerror(errno)); 587a73597f9Smrg } 588a73597f9Smrg } 589a73597f9Smrg } 590a73597f9Smrg if (pVuidMse->remove_timer) { 591a73597f9Smrg TimerFree(pVuidMse->remove_timer); 592a73597f9Smrg pVuidMse->remove_timer = NULL; 593a73597f9Smrg } 594a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 595a73597f9Smrg break; 5966aab59a7Smrg 5976aab59a7Smrg default: /* Should never be called, but just in case */ 598a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 599a73597f9Smrg break; 6006aab59a7Smrg } 6016aab59a7Smrg return ret; 6026aab59a7Smrg} 6036aab59a7Smrg 6046aab59a7Smrgstatic Bool 6056aab59a7SmrgsunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 6066aab59a7Smrg{ 6076aab59a7Smrg /* The protocol is guaranteed to be one of the internalNames[] */ 6086aab59a7Smrg if (xf86NameCmp(protocol, "VUID") == 0) { 609a73597f9Smrg return vuidPreInit(pInfo, protocol, flags); 6106aab59a7Smrg } 6116aab59a7Smrg return TRUE; 612a73597f9Smrg} 6136aab59a7Smrg 6146aab59a7Smrgstatic const char ** 6156aab59a7SmrgBuiltinNames(void) 6166aab59a7Smrg{ 6176aab59a7Smrg return internalNames; 6186aab59a7Smrg} 6196aab59a7Smrg 6206aab59a7Smrgstatic Bool 6216aab59a7SmrgCheckProtocol(const char *protocol) 6226aab59a7Smrg{ 6236aab59a7Smrg int i; 6246aab59a7Smrg 6256aab59a7Smrg for (i = 0; internalNames[i]; i++) 626a73597f9Smrg if (xf86NameCmp(protocol, internalNames[i]) == 0) 627a73597f9Smrg return TRUE; 6286aab59a7Smrg 6296aab59a7Smrg return FALSE; 6306aab59a7Smrg} 6316aab59a7Smrg 6326aab59a7Smrgstatic const char * 6336aab59a7SmrgDefaultProtocol(void) 6346aab59a7Smrg{ 6356aab59a7Smrg return "Auto"; 6366aab59a7Smrg} 6376aab59a7Smrg 6386aab59a7Smrgstatic Bool 639a73597f9SmrgsolarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol, 640a73597f9Smrg const char **device) 6416aab59a7Smrg{ 6426aab59a7Smrg const char **pdev, **pproto; 6436aab59a7Smrg int fd = -1; 6446aab59a7Smrg Bool found; 6456aab59a7Smrg char *strmod; 6466aab59a7Smrg 6476aab59a7Smrg if (*device == NULL) { 648a73597f9Smrg /* Check to see if xorg.conf or HAL specified a device to use */ 649a73597f9Smrg *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 6506aab59a7Smrg } 6516aab59a7Smrg 6526aab59a7Smrg if (*device != NULL) { 653a73597f9Smrg strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 654a73597f9Smrg if (strmod) { 655a73597f9Smrg /* if a device name is already known, and a StreamsModule is 656a73597f9Smrg specified to convert events to VUID, then we don't need to 657a73597f9Smrg probe further */ 658a73597f9Smrg *protocol = "VUID"; 659a73597f9Smrg return TRUE; 660a73597f9Smrg } 6616aab59a7Smrg } 6626aab59a7Smrg 6636aab59a7Smrg 6646aab59a7Smrg for (pdev = solarisMouseDevs; *pdev; pdev += 2) { 665a73597f9Smrg pproto = pdev + 1; 666a73597f9Smrg if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) && 667a73597f9Smrg (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) { 668a73597f9Smrg continue; 669a73597f9Smrg } 670a73597f9Smrg if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) { 671a73597f9Smrg continue; 672a73597f9Smrg } 6736aab59a7Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 674a73597f9Smrg if (fd == -1) { 6756aab59a7Smrg#ifdef DEBUG 676a73597f9Smrg ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno)); 6776aab59a7Smrg#endif 678a73597f9Smrg } else { 679a73597f9Smrg found = TRUE; 680a73597f9Smrg if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) { 681a73597f9Smrg int i, r; 682a73597f9Smrg SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i)); 683a73597f9Smrg if (r < 0) { 684a73597f9Smrg found = FALSE; 685a73597f9Smrg } 686a73597f9Smrg } 687a73597f9Smrg close(fd); 688a73597f9Smrg if (found == TRUE) { 689a73597f9Smrg if (*pproto != NULL) { 690a73597f9Smrg *protocol = *pproto; 691a73597f9Smrg } 692a73597f9Smrg *device = *pdev; 693a73597f9Smrg return TRUE; 694a73597f9Smrg } 695a73597f9Smrg } 6966aab59a7Smrg } 6976aab59a7Smrg return FALSE; 6986aab59a7Smrg} 6996aab59a7Smrg 7006aab59a7Smrgstatic const char * 7016aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 7026aab59a7Smrg{ 7036aab59a7Smrg const char *pdev = NULL; 7046aab59a7Smrg const char *pproto = NULL; 7056aab59a7Smrg MouseDevPtr pMse = pInfo->private; 7066aab59a7Smrg 7076aab59a7Smrg if (pInfo->fd == -1) { 708a73597f9Smrg /* probe to find device/protocol to use */ 709a73597f9Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 710a73597f9Smrg /* Set the Device option. */ 711a73597f9Smrg pInfo->options = 712a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 713a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 714a73597f9Smrg pInfo->name, pdev); 715a73597f9Smrg } 7166aab59a7Smrg } else if (pMse->protocolID == PROT_AUTO) { 717a73597f9Smrg pdev = xf86CheckStrOption(pInfo->options, 718a73597f9Smrg "Device", NULL); 719a73597f9Smrg if ((solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) && 720a73597f9Smrg (pproto != NULL)) 721a73597f9Smrg sunMousePreInit(pInfo, pproto, 0); 7226aab59a7Smrg } 7236aab59a7Smrg return pproto; 7246aab59a7Smrg} 7256aab59a7Smrg 7266aab59a7Smrgstatic const char * 7276aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 7286aab59a7Smrg{ 7296aab59a7Smrg const char *pdev = NULL; 7306aab59a7Smrg const char *pproto = protocol; 7316aab59a7Smrg 7326aab59a7Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 733a73597f9Smrg /* Set the Device option. */ 734a73597f9Smrg pInfo->options = 735a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 736a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 737a73597f9Smrg pInfo->name, pdev); 7386aab59a7Smrg } 7396aab59a7Smrg return pdev; 7406aab59a7Smrg} 7416aab59a7Smrg 7426aab59a7Smrgstatic int 7436aab59a7SmrgSupportedInterfaces(void) 7446aab59a7Smrg{ 7456aab59a7Smrg /* XXX This needs to be checked. */ 7466aab59a7Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; 7476aab59a7Smrg} 7486aab59a7Smrg 749bd3a1963SmrgOSMouseInfoPtr 750bd3a1963SmrgOSMouseInit(int flags) 7516aab59a7Smrg{ 7526aab59a7Smrg OSMouseInfoPtr p; 7536aab59a7Smrg 754bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 7556aab59a7Smrg if (!p) 756a73597f9Smrg return NULL; 7576aab59a7Smrg p->SupportedInterfaces = SupportedInterfaces; 7586aab59a7Smrg p->BuiltinNames = BuiltinNames; 7596aab59a7Smrg p->CheckProtocol = CheckProtocol; 7606aab59a7Smrg p->PreInit = sunMousePreInit; 7616aab59a7Smrg p->DefaultProtocol = DefaultProtocol; 7626aab59a7Smrg p->SetupAuto = SetupAuto; 7636aab59a7Smrg p->FindDevice = FindDevice; 7646aab59a7Smrg 7656aab59a7Smrg return p; 7666aab59a7Smrg} 7676aab59a7Smrg 768