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