sun_mouse.c revision fc27e79c
16aab59a7Smrg/*
26aab59a7Smrg * Copyright 1999-2001 The XFree86 Project, Inc.  All Rights Reserved.
36aab59a7Smrg *
46aab59a7Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
56aab59a7Smrg * of this software and associated documentation files (the "Software"), to
66aab59a7Smrg * deal in the Software without restriction, including without limitation the
76aab59a7Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
86aab59a7Smrg * sell copies of the Software, and to permit persons to whom the Software is
96aab59a7Smrg * furnished to do so, subject to the following conditions:
106aab59a7Smrg *
116aab59a7Smrg * The above copyright notice and this permission notice shall be included in
126aab59a7Smrg * all copies or substantial portions of the Software.
136aab59a7Smrg *
146aab59a7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156aab59a7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166aab59a7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
176aab59a7Smrg * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
186aab59a7Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
196aab59a7Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
206aab59a7Smrg *
216aab59a7Smrg * Except as contained in this notice, the name of the XFree86 Project shall
226aab59a7Smrg * not be used in advertising or otherwise to promote the sale, use or other
236aab59a7Smrg * dealings in this Software without prior written authorization from the
246aab59a7Smrg * XFree86 Project.
256aab59a7Smrg */
26fc27e79cSmrg/* Copyright 2004-2005, 2008-2009 Sun Microsystems, Inc.  All rights reserved.
276aab59a7Smrg *
286aab59a7Smrg * Permission is hereby granted, free of charge, to any person obtaining a
296aab59a7Smrg * copy of this software and associated documentation files (the
306aab59a7Smrg * "Software"), to deal in the Software without restriction, including
316aab59a7Smrg * without limitation the rights to use, copy, modify, merge, publish,
326aab59a7Smrg * distribute, and/or sell copies of the Software, and to permit persons
336aab59a7Smrg * to whom the Software is furnished to do so, provided that the above
346aab59a7Smrg * copyright notice(s) and this permission notice appear in all copies of
356aab59a7Smrg * the Software and that both the above copyright notice(s) and this
366aab59a7Smrg * permission notice appear in supporting documentation.
376aab59a7Smrg *
386aab59a7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
396aab59a7Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
406aab59a7Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
416aab59a7Smrg * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
426aab59a7Smrg * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
436aab59a7Smrg * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
446aab59a7Smrg * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
456aab59a7Smrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
466aab59a7Smrg * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
476aab59a7Smrg *
486aab59a7Smrg * Except as contained in this notice, the name of a copyright holder
496aab59a7Smrg * shall not be used in advertising or otherwise to promote the sale, use
506aab59a7Smrg * or other dealings in this Software without prior written authorization
516aab59a7Smrg * of the copyright holder.
526aab59a7Smrg */
536aab59a7Smrg
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"
616aab59a7Smrg#include "xf86OSmouse.h"
626aab59a7Smrg#include "xisb.h"
636aab59a7Smrg#include "mipointer.h"
646aab59a7Smrg#include <sys/stropts.h>
656aab59a7Smrg#include <sys/vuid_event.h>
666aab59a7Smrg#include <sys/msio.h>
676aab59a7Smrg
686aab59a7Smrg/* Wheel mouse support in VUID drivers in Solaris 9 updates & Solaris 10 */
696aab59a7Smrg#ifdef WHEEL_DEVID /* Defined in vuid_event.h if VUID wheel support present */
706aab59a7Smrg# define HAVE_VUID_WHEEL
716aab59a7Smrg#endif
726aab59a7Smrg#ifdef HAVE_VUID_WHEEL
736aab59a7Smrg# include <sys/vuid_wheel.h>
746aab59a7Smrg#endif
756aab59a7Smrg
766aab59a7Smrg/* Support for scaling absolute coordinates to screen size in
776aab59a7Smrg * Solaris 10 updates and beyond */
786aab59a7Smrg#if !defined(HAVE_ABSOLUTE_MOUSE_SCALING)
796aab59a7Smrg# ifdef MSIOSRESOLUTION /* Defined in msio.h if scaling support present */
806aab59a7Smrg#  define HAVE_ABSOLUTE_MOUSE_SCALING
816aab59a7Smrg# endif
826aab59a7Smrg#endif
836aab59a7Smrg
846aab59a7Smrg/* Names of protocols that are handled internally here. */
856aab59a7Smrg
866aab59a7Smrgstatic const char *internalNames[] = {
876aab59a7Smrg	"VUID",
886aab59a7Smrg	NULL
896aab59a7Smrg};
906aab59a7Smrg
916aab59a7Smrgstatic const char *solarisMouseDevs[] = {
926aab59a7Smrg    /* Device file:	Protocol: 			*/
936aab59a7Smrg    "/dev/mouse",	"VUID",		/* USB or SPARC */
946aab59a7Smrg#if defined(__i386) || defined(__x86)
956aab59a7Smrg    "/dev/kdmouse",	"PS/2",		/* PS/2 */
966aab59a7Smrg#endif
976aab59a7Smrg    NULL
986aab59a7Smrg};
996aab59a7Smrg
1006aab59a7Smrgtypedef struct _VuidMseRec {
1016aab59a7Smrg    struct _VuidMseRec *next;
1026aab59a7Smrg    InputInfoPtr	pInfo;
1036aab59a7Smrg    Firm_event 		event;
1046aab59a7Smrg    unsigned char *	buffer;
1056aab59a7Smrg    char *		strmod;
1066aab59a7Smrg    Bool(*wrapped_device_control)(DeviceIntPtr device, int what);
1076aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
1086aab59a7Smrg    Ms_screen_resolution	 absres;
1096aab59a7Smrg#endif
1106aab59a7Smrg} VuidMseRec, *VuidMsePtr;
1116aab59a7Smrg
1126aab59a7Smrgstatic VuidMsePtr	vuidMouseList = NULL;
1136aab59a7Smrg
1146aab59a7Smrgstatic int  vuidMouseProc(DeviceIntPtr pPointer, int what);
1156aab59a7Smrgstatic void vuidReadInput(InputInfoPtr pInfo);
1166aab59a7Smrg
1176aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
1186aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse);
1196aab59a7Smrgstatic void vuidMouseAdjustFrame(int index, int x, int y, int flags);
1206aab59a7Smrg
1216aab59a7Smrgstatic int vuidMouseGeneration = 0;
1226aab59a7Smrgstatic int vuidMouseScreenIndex;
1236aab59a7Smrg#define vuidMouseGetScreenPrivate(s) ( \
1246aab59a7Smrg    dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex))
1256aab59a7Smrg#define vuidMouseSetScreenPrivate(s,p) \
1266aab59a7Smrg    dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p)
1276aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */
1286aab59a7Smrg
1296aab59a7Smrgstatic inline
1306aab59a7SmrgVuidMsePtr getVuidMsePriv(InputInfoPtr pInfo)
1316aab59a7Smrg{
1326aab59a7Smrg    VuidMsePtr m = vuidMouseList;
1336aab59a7Smrg
1346aab59a7Smrg    while ((m != NULL) && (m->pInfo != pInfo)) {
1356aab59a7Smrg	m = m->next;
1366aab59a7Smrg    }
1376aab59a7Smrg
1386aab59a7Smrg    return m;
1396aab59a7Smrg}
1406aab59a7Smrg
1416aab59a7Smrg
1426aab59a7Smrg/*
1436aab59a7Smrg * Initialize and enable the mouse wheel, if present.
1446aab59a7Smrg *
1456aab59a7Smrg * Returns 1 if mouse wheel was successfully enabled.
1466aab59a7Smrg * Returns 0 if an error occurred or if there is no mouse wheel.
1476aab59a7Smrg */
1486aab59a7Smrgstatic int
1496aab59a7SmrgvuidMouseWheelInit(InputInfoPtr pInfo)
1506aab59a7Smrg{
1516aab59a7Smrg#ifdef HAVE_VUID_WHEEL
1526aab59a7Smrg    wheel_state wstate;
1536aab59a7Smrg    int nwheel = -1;
1546aab59a7Smrg    int i;
1556aab59a7Smrg
1566aab59a7Smrg    wstate.vers = VUID_WHEEL_STATE_VERS;
1576aab59a7Smrg    wstate.id = 0;
1586aab59a7Smrg    wstate.stateflags = (uint32_t) -1;
1596aab59a7Smrg
1606aab59a7Smrg    SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel));
1616aab59a7Smrg    if (i != 0)
1626aab59a7Smrg	return (0);
1636aab59a7Smrg
1646aab59a7Smrg    SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate));
1656aab59a7Smrg    if (i != 0) {
1666aab59a7Smrg	xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name);
1676aab59a7Smrg	return (0);
1686aab59a7Smrg    }
1696aab59a7Smrg
1706aab59a7Smrg    wstate.stateflags |= VUID_WHEEL_STATE_ENABLED;
1716aab59a7Smrg
1726aab59a7Smrg    SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate));
1736aab59a7Smrg    if (i != 0) {
1746aab59a7Smrg	xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name);
1756aab59a7Smrg	return (0);
1766aab59a7Smrg    }
1776aab59a7Smrg
1786aab59a7Smrg    return (1);
1796aab59a7Smrg#else
1806aab59a7Smrg    return (0);
1816aab59a7Smrg#endif
1826aab59a7Smrg}
1836aab59a7Smrg
1846aab59a7Smrg
1856aab59a7Smrg/* This function is called when the protocol is "VUID". */
1866aab59a7Smrgstatic Bool
1876aab59a7SmrgvuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
1886aab59a7Smrg{
1896aab59a7Smrg    MouseDevPtr pMse = pInfo->private;
1906aab59a7Smrg    VuidMsePtr pVuidMse;
1916aab59a7Smrg    int buttons, i;
1926aab59a7Smrg
1936aab59a7Smrg    pVuidMse = xcalloc(sizeof(VuidMseRec), 1);
1946aab59a7Smrg    if (pVuidMse == NULL) {
1956aab59a7Smrg	xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name);
1966aab59a7Smrg	xfree(pMse);
1976aab59a7Smrg	return FALSE;
1986aab59a7Smrg    }
1996aab59a7Smrg
2006aab59a7Smrg    pMse->protocol = protocol;
2016aab59a7Smrg    xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
2026aab59a7Smrg
2036aab59a7Smrg    /* Collect the options, and process the common options. */
2046aab59a7Smrg    xf86CollectInputOptions(pInfo, NULL, NULL);
2056aab59a7Smrg    xf86ProcessCommonOptions(pInfo, pInfo->options);
2066aab59a7Smrg
207fc27e79cSmrg    pVuidMse->buffer = (unsigned char *)&pVuidMse->event;
208fc27e79cSmrg    pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL);
209fc27e79cSmrg
2106aab59a7Smrg    /* Check if the device can be opened. */
2116aab59a7Smrg    pInfo->fd = xf86OpenSerial(pInfo->options);
2126aab59a7Smrg    if (pInfo->fd == -1) {
213fc27e79cSmrg	if (xf86GetAllowMouseOpenFail()) {
2146aab59a7Smrg	    xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
215fc27e79cSmrg	} else {
2166aab59a7Smrg	    xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
217fc27e79cSmrg	    xfree(pVuidMse->strmod);
2186aab59a7Smrg	    xfree(pVuidMse);
2196aab59a7Smrg	    xfree(pMse);
2206aab59a7Smrg	    return FALSE;
2216aab59a7Smrg	}
222fc27e79cSmrg    } else {
223fc27e79cSmrg	if (pVuidMse->strmod) {
224fc27e79cSmrg	    /* Check to see if module is already pushed */
225fc27e79cSmrg	    SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod));
2266aab59a7Smrg
227fc27e79cSmrg	    if (i == 0) { /* Not already pushed */
228fc27e79cSmrg		SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod));
229fc27e79cSmrg		if (i < 0) {
230fc27e79cSmrg		    xf86Msg(X_ERROR,
231fc27e79cSmrg			"%s: cannot push module '%s' onto mouse device: %s\n",
232fc27e79cSmrg			pInfo->name, pVuidMse->strmod, strerror(errno));
233fc27e79cSmrg		    xf86CloseSerial(pInfo->fd);
234fc27e79cSmrg		    pInfo->fd = -1;
235fc27e79cSmrg		    xfree(pVuidMse->strmod);
236fc27e79cSmrg		    xfree(pVuidMse);
237fc27e79cSmrg		    xfree(pMse);
238fc27e79cSmrg		    return FALSE;
239fc27e79cSmrg		}
240fc27e79cSmrg	    }
2416aab59a7Smrg	}
2426aab59a7Smrg
243fc27e79cSmrg	buttons = xf86SetIntOption(pInfo->options, "Buttons", 0);
244fc27e79cSmrg	if (buttons == 0) {
245fc27e79cSmrg	    SYSCALL(i = ioctl(pInfo->fd, MSIOBUTTONS, &buttons));
246fc27e79cSmrg	    if (i == 0) {
247fc27e79cSmrg		pInfo->conf_idev->commonOptions =
248fc27e79cSmrg		    xf86ReplaceIntOption(pInfo->conf_idev->commonOptions,
249fc27e79cSmrg					 "Buttons", buttons);
250fc27e79cSmrg		xf86Msg(X_INFO, "%s: Setting Buttons option to \"%d\"\n",
251fc27e79cSmrg			pInfo->name, buttons);
252fc27e79cSmrg	    }
2536aab59a7Smrg	}
2546aab59a7Smrg
255fc27e79cSmrg	if (pVuidMse->strmod) {
256fc27e79cSmrg	    SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod));
257fc27e79cSmrg	    if (i == -1) {
258fc27e79cSmrg		xf86Msg(X_WARNING,
259fc27e79cSmrg			"%s: cannot pop module '%s' off mouse device: %s\n",
260fc27e79cSmrg			pInfo->name, pVuidMse->strmod, strerror(errno));
261fc27e79cSmrg	    }
2626aab59a7Smrg	}
2636aab59a7Smrg
264fc27e79cSmrg	xf86CloseSerial(pInfo->fd);
265fc27e79cSmrg	pInfo->fd = -1;
266fc27e79cSmrg    }
2676aab59a7Smrg
2686aab59a7Smrg    /* Process common mouse options (like Emulate3Buttons, etc). */
2696aab59a7Smrg    pMse->CommonOptions(pInfo);
2706aab59a7Smrg
2716aab59a7Smrg    /* Setup the local procs. */
2726aab59a7Smrg    pVuidMse->wrapped_device_control = pInfo->device_control;
2736aab59a7Smrg    pInfo->device_control = vuidMouseProc;
2746aab59a7Smrg    pInfo->read_input = vuidReadInput;
2756aab59a7Smrg
2766aab59a7Smrg    pMse->xisbscale = sizeof(Firm_event);
2776aab59a7Smrg
2786aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
2796aab59a7Smrg    pVuidMse->absres.height = pVuidMse->absres.width = 0;
2806aab59a7Smrg#endif
2816aab59a7Smrg    pVuidMse->pInfo = pInfo;
2826aab59a7Smrg    pVuidMse->next = vuidMouseList;
2836aab59a7Smrg    vuidMouseList = pVuidMse;
2846aab59a7Smrg
2856aab59a7Smrg    pInfo->flags |= XI86_CONFIGURED;
2866aab59a7Smrg    return TRUE;
2876aab59a7Smrg}
2886aab59a7Smrg
2896aab59a7Smrgstatic void
2906aab59a7SmrgvuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY,
2916aab59a7Smrg		   Bool *absXset, Bool *absYset)
2926aab59a7Smrg{
2936aab59a7Smrg#ifdef DEBUG
2946aab59a7Smrg    ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY,
2956aab59a7Smrg	   *absXset, *absYset);
2966aab59a7Smrg#endif
2976aab59a7Smrg    if ((*absXset) && (*absYset)) {
2986aab59a7Smrg	xf86PostMotionEvent(pInfo->dev,
2996aab59a7Smrg			    /* is_absolute: */    TRUE,
3006aab59a7Smrg			    /* first_valuator: */ 0,
3016aab59a7Smrg			    /* num_valuators: */  2,
3026aab59a7Smrg			    absX, absY);
3036aab59a7Smrg    } else if (*absXset) {
3046aab59a7Smrg	xf86PostMotionEvent(pInfo->dev,
3056aab59a7Smrg			    /* is_absolute: */    TRUE,
3066aab59a7Smrg			    /* first_valuator: */ 0,
3076aab59a7Smrg			    /* num_valuators: */  1,
3086aab59a7Smrg			    absX);
3096aab59a7Smrg    } else if (*absYset) {
3106aab59a7Smrg	xf86PostMotionEvent(pInfo->dev,
3116aab59a7Smrg			    /* is_absolute: */    TRUE,
3126aab59a7Smrg			    /* first_valuator: */ 1,
3136aab59a7Smrg			    /* num_valuators: */  1,
3146aab59a7Smrg			    absY);
3156aab59a7Smrg    }
3166aab59a7Smrg
3176aab59a7Smrg    *absXset = FALSE;
3186aab59a7Smrg    *absYset = FALSE;
3196aab59a7Smrg}
3206aab59a7Smrg
3216aab59a7Smrgstatic void
3226aab59a7SmrgvuidReadInput(InputInfoPtr pInfo)
3236aab59a7Smrg{
3246aab59a7Smrg    MouseDevPtr pMse;
3256aab59a7Smrg    VuidMsePtr pVuidMse;
3266aab59a7Smrg    int buttons;
3276aab59a7Smrg    int dx = 0, dy = 0, dz = 0, dw = 0;
3286aab59a7Smrg    unsigned int n;
3296aab59a7Smrg    int c;
3306aab59a7Smrg    unsigned char *pBuf;
3316aab59a7Smrg    int absX = 0, absY = 0;
3326aab59a7Smrg    Bool absXset = FALSE, absYset = FALSE;
3336aab59a7Smrg
3346aab59a7Smrg    pMse = pInfo->private;
3356aab59a7Smrg    pVuidMse = getVuidMsePriv(pInfo);
3366aab59a7Smrg    buttons = pMse->lastButtons;
3376aab59a7Smrg    XisbBlockDuration(pMse->buffer, -1);
3386aab59a7Smrg    pBuf = pVuidMse->buffer;
3396aab59a7Smrg    n = 0;
3406aab59a7Smrg
3416aab59a7Smrg    do {
3426aab59a7Smrg	while (n < sizeof(Firm_event) && (c = XisbRead(pMse->buffer)) >= 0) {
3436aab59a7Smrg	    pBuf[n++] = (unsigned char)c;
3446aab59a7Smrg	}
3456aab59a7Smrg
3466aab59a7Smrg	if (n == 0)
3476aab59a7Smrg	    return;
3486aab59a7Smrg
3496aab59a7Smrg	if (n != sizeof(Firm_event)) {
3506aab59a7Smrg	    xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n",
3516aab59a7Smrg			pInfo->name, n);
3526aab59a7Smrg	}
3536aab59a7Smrg
3546aab59a7Smrg#ifdef DEBUG
3556aab59a7Smrg	ErrorF("vuidReadInput: event type: %3d value: %5d\n",
3566aab59a7Smrg	       pVuidMse->event.id, pVuidMse->event.value);
3576aab59a7Smrg#endif
3586aab59a7Smrg
3596aab59a7Smrg	if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) {
3606aab59a7Smrg	    /* button */
3616aab59a7Smrg	    int butnum = pVuidMse->event.id - BUT_FIRST;
3626aab59a7Smrg
3636aab59a7Smrg	    if (butnum < 3)
3646aab59a7Smrg		butnum = 2 - butnum;
3656aab59a7Smrg	    if (!pVuidMse->event.value)
3666aab59a7Smrg		buttons &= ~(1 << butnum);
3676aab59a7Smrg	    else
3686aab59a7Smrg		buttons |= (1 << butnum);
3696aab59a7Smrg	} else if (pVuidMse->event.id >= VLOC_FIRST &&
3706aab59a7Smrg		   pVuidMse->event.id <= VLOC_LAST) {
3716aab59a7Smrg	    /* axis */
3726aab59a7Smrg	    int delta = pVuidMse->event.value;
3736aab59a7Smrg	    switch(pVuidMse->event.id) {
3746aab59a7Smrg	    case LOC_X_DELTA:
3756aab59a7Smrg		dx += delta;
3766aab59a7Smrg		break;
3776aab59a7Smrg	    case LOC_Y_DELTA:
3786aab59a7Smrg		dy -= delta;
3796aab59a7Smrg		break;
3806aab59a7Smrg	    case LOC_X_ABSOLUTE:
3816aab59a7Smrg		if (absXset) {
3826aab59a7Smrg		    vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset);
3836aab59a7Smrg		}
3846aab59a7Smrg		absX = delta;
3856aab59a7Smrg		absXset = TRUE;
3866aab59a7Smrg		break;
3876aab59a7Smrg	    case LOC_Y_ABSOLUTE:
3886aab59a7Smrg		if (absYset) {
3896aab59a7Smrg		    vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset);
3906aab59a7Smrg		}
3916aab59a7Smrg		absY = delta;
3926aab59a7Smrg		absYset = TRUE;
3936aab59a7Smrg		break;
3946aab59a7Smrg	    }
3956aab59a7Smrg	}
3966aab59a7Smrg#ifdef HAVE_VUID_WHEEL
3976aab59a7Smrg	else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) {
3986aab59a7Smrg	    if (vuid_id_offset(pVuidMse->event.id) == 0)
3996aab59a7Smrg		dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value);
4006aab59a7Smrg	    else
4016aab59a7Smrg		dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value);
4026aab59a7Smrg	}
4036aab59a7Smrg#endif
4046aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
4056aab59a7Smrg	else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) {
4066aab59a7Smrg	    ScreenPtr 	ptrCurScreen;
4076aab59a7Smrg
4086aab59a7Smrg	    /* force sending absolute resolution scaling ioctl */
4096aab59a7Smrg	    pVuidMse->absres.height = pVuidMse->absres.width = 0;
4106aab59a7Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
4116aab59a7Smrg	    ptrCurScreen = miPointerCurrentScreen();
4126aab59a7Smrg#else
4136aab59a7Smrg	    ptrCurScreen = miPointerGetScreen(pInfo->dev);
4146aab59a7Smrg#endif
4156aab59a7Smrg	    vuidMouseSendScreenSize(ptrCurScreen, pVuidMse);
4166aab59a7Smrg	}
4176aab59a7Smrg#endif
4186aab59a7Smrg
4196aab59a7Smrg	n = 0;
4206aab59a7Smrg	if ((c = XisbRead(pMse->buffer)) >= 0) {
4216aab59a7Smrg	    /* Another packet.  Handle it right away. */
4226aab59a7Smrg	    pBuf[n++] = c;
4236aab59a7Smrg	}
4246aab59a7Smrg    } while (n != 0);
4256aab59a7Smrg
4266aab59a7Smrg    if (absXset || absYset) {
4276aab59a7Smrg	vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset);
4286aab59a7Smrg    }
4296aab59a7Smrg
4306aab59a7Smrg    pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
4316aab59a7Smrg    return;
4326aab59a7Smrg}
4336aab59a7Smrg
4346aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
4356aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse)
4366aab59a7Smrg{
4376aab59a7Smrg    InputInfoPtr pInfo = pVuidMse->pInfo;
4386aab59a7Smrg    ScrnInfoPtr pScr = XF86SCRNINFO(pScreen);
4396aab59a7Smrg    int result;
4406aab59a7Smrg
4416aab59a7Smrg    if ((pVuidMse->absres.width != pScr->currentMode->HDisplay) ||
4426aab59a7Smrg	(pVuidMse->absres.height != pScr->currentMode->VDisplay))
4436aab59a7Smrg    {
4446aab59a7Smrg	pVuidMse->absres.width = pScr->currentMode->HDisplay;
4456aab59a7Smrg	pVuidMse->absres.height = pScr->currentMode->VDisplay;
4466aab59a7Smrg
4476aab59a7Smrg	do {
4486aab59a7Smrg	    result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres));
4496aab59a7Smrg	} while ( (result != 0) && (errno == EINTR) );
4506aab59a7Smrg
4516aab59a7Smrg	if (result != 0) {
4526aab59a7Smrg	    xf86Msg(X_WARNING,
4536aab59a7Smrg		    "%s: couldn't set absolute mouse scaling resolution: %s\n",
4546aab59a7Smrg		    pInfo->name, strerror(errno));
4556aab59a7Smrg#ifdef DEBUG
4566aab59a7Smrg	} else {
4576aab59a7Smrg	    xf86Msg(X_INFO,
4586aab59a7Smrg		    "%s: absolute mouse scaling resolution set to %d x %d\n",
4596aab59a7Smrg		    pInfo->name,
4606aab59a7Smrg		    pVuidMse->absres.width, pVuidMse->absres.height);
4616aab59a7Smrg#endif
4626aab59a7Smrg	}
4636aab59a7Smrg    }
4646aab59a7Smrg}
4656aab59a7Smrg
4666aab59a7Smrgstatic void vuidMouseAdjustFrame(int index, int x, int y, int flags)
4676aab59a7Smrg{
4686aab59a7Smrg      ScrnInfoPtr	pScrn = xf86Screens[index];
4696aab59a7Smrg      ScreenPtr		pScreen = pScrn->pScreen;
4706aab59a7Smrg      xf86AdjustFrameProc *wrappedAdjustFrame
4716aab59a7Smrg	  = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen);
4726aab59a7Smrg      VuidMsePtr	m;
4736aab59a7Smrg      ScreenPtr 	ptrCurScreen;
4746aab59a7Smrg
4756aab59a7Smrg      if(wrappedAdjustFrame) {
4766aab59a7Smrg        pScrn->AdjustFrame = wrappedAdjustFrame;
4776aab59a7Smrg        (*pScrn->AdjustFrame)(index, x, y, flags);
4786aab59a7Smrg        pScrn->AdjustFrame = vuidMouseAdjustFrame;
4796aab59a7Smrg      }
4806aab59a7Smrg
4816aab59a7Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
4826aab59a7Smrg      ptrCurScreen = miPointerCurrentScreen();
4836aab59a7Smrg#endif
4846aab59a7Smrg
4856aab59a7Smrg      for (m = vuidMouseList; m != NULL ; m = m->next) {
4866aab59a7Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 0
4876aab59a7Smrg	  ptrCurScreen = miPointerGetScreen(m->pInfo->dev);
4886aab59a7Smrg#endif
4896aab59a7Smrg	  if (ptrCurScreen == pScreen)
4906aab59a7Smrg	  {
4916aab59a7Smrg	      vuidMouseSendScreenSize(pScreen, m);
4926aab59a7Smrg	  }
4936aab59a7Smrg      }
4946aab59a7Smrg}
4956aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */
4966aab59a7Smrg
4976aab59a7Smrg
4986aab59a7Smrgstatic int
4996aab59a7SmrgvuidMouseProc(DeviceIntPtr pPointer, int what)
5006aab59a7Smrg{
5016aab59a7Smrg    InputInfoPtr pInfo;
5026aab59a7Smrg    MouseDevPtr pMse;
5036aab59a7Smrg    VuidMsePtr pVuidMse;
5046aab59a7Smrg    int ret = Success;
5056aab59a7Smrg    int i;
5066aab59a7Smrg
5076aab59a7Smrg    pInfo = pPointer->public.devicePrivate;
5086aab59a7Smrg    pMse = pInfo->private;
5096aab59a7Smrg    pMse->device = pPointer;
5106aab59a7Smrg
5116aab59a7Smrg    pVuidMse = getVuidMsePriv(pInfo);
5126aab59a7Smrg    if (pVuidMse == NULL) {
5136aab59a7Smrg	return BadImplementation;
5146aab59a7Smrg    }
5156aab59a7Smrg
5166aab59a7Smrg    switch (what) {
5176aab59a7Smrg
5186aab59a7Smrg    case DEVICE_INIT:
5196aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
5206aab59a7Smrg	if (vuidMouseGeneration != serverGeneration) {
5216aab59a7Smrg		for (i = 0; i < screenInfo.numScreens; i++) {
5226aab59a7Smrg		    ScreenPtr pScreen = screenInfo.screens[i];
5236aab59a7Smrg		    ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
5246aab59a7Smrg		    vuidMouseSetScreenPrivate(pScreen, pScrn->AdjustFrame);
5256aab59a7Smrg		    pScrn->AdjustFrame = vuidMouseAdjustFrame;
5266aab59a7Smrg		}
5276aab59a7Smrg	    vuidMouseGeneration = serverGeneration;
5286aab59a7Smrg	}
5296aab59a7Smrg#endif
5306aab59a7Smrg	ret = pVuidMse->wrapped_device_control(pPointer, what);
5316aab59a7Smrg	break;
5326aab59a7Smrg
5336aab59a7Smrg    case DEVICE_ON:
5346aab59a7Smrg	ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON);
5356aab59a7Smrg
5366aab59a7Smrg	if ((ret == Success) && (pInfo->fd != -1)) {
5376aab59a7Smrg	    int fmt = VUID_FIRM_EVENT;
5386aab59a7Smrg
5396aab59a7Smrg	    if (pVuidMse->strmod) {
540fc27e79cSmrg		/* Check to see if module is already pushed */
541fc27e79cSmrg		SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod));
542fc27e79cSmrg
543fc27e79cSmrg		if (i == 0) { /* Not already pushed */
544fc27e79cSmrg		    SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod));
545fc27e79cSmrg		    if (i < 0) {
546fc27e79cSmrg			xf86Msg(X_WARNING, "%s: cannot push module '%s' "
547fc27e79cSmrg				"onto mouse device: %s\n", pInfo->name,
548fc27e79cSmrg				pVuidMse->strmod, strerror(errno));
549fc27e79cSmrg			xfree(pVuidMse->strmod);
550fc27e79cSmrg			pVuidMse->strmod = NULL;
551fc27e79cSmrg		    }
5526aab59a7Smrg		}
5536aab59a7Smrg	    }
554fc27e79cSmrg
5556aab59a7Smrg	    SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt));
5566aab59a7Smrg	    if (i < 0) {
5576aab59a7Smrg		xf86Msg(X_WARNING,
5586aab59a7Smrg			"%s: cannot set mouse device to VUID mode: %s\n",
5596aab59a7Smrg			pInfo->name, strerror(errno));
5606aab59a7Smrg	    }
5616aab59a7Smrg	    vuidMouseWheelInit(pInfo);
5626aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING
5636aab59a7Smrg	    vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse);
5646aab59a7Smrg#endif
5656aab59a7Smrg	    xf86FlushInput(pInfo->fd);
5666aab59a7Smrg	}
5676aab59a7Smrg	break;
5686aab59a7Smrg
5696aab59a7Smrg    case DEVICE_OFF:
5706aab59a7Smrg    case DEVICE_CLOSE:
5716aab59a7Smrg	if (pInfo->fd != -1) {
5726aab59a7Smrg	    if (pVuidMse->strmod) {
5736aab59a7Smrg		SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod));
5746aab59a7Smrg		if (i == -1) {
5756aab59a7Smrg		    xf86Msg(X_WARNING,
5766aab59a7Smrg		      "%s: cannot pop module '%s' off mouse device: %s\n",
5776aab59a7Smrg		      pInfo->name, pVuidMse->strmod, strerror(errno));
5786aab59a7Smrg		}
5796aab59a7Smrg	    }
5806aab59a7Smrg	}
5816aab59a7Smrg	ret = pVuidMse->wrapped_device_control(pPointer, what);
5826aab59a7Smrg	break;
5836aab59a7Smrg
5846aab59a7Smrg    default: /* Should never be called, but just in case */
5856aab59a7Smrg	ret = pVuidMse->wrapped_device_control(pPointer, what);
5866aab59a7Smrg	break;
5876aab59a7Smrg    }
5886aab59a7Smrg    return ret;
5896aab59a7Smrg}
5906aab59a7Smrg
5916aab59a7Smrgstatic Bool
5926aab59a7SmrgsunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags)
5936aab59a7Smrg{
5946aab59a7Smrg    /* The protocol is guaranteed to be one of the internalNames[] */
5956aab59a7Smrg    if (xf86NameCmp(protocol, "VUID") == 0) {
5966aab59a7Smrg	return vuidPreInit(pInfo, protocol, flags);
5976aab59a7Smrg    }
5986aab59a7Smrg    return TRUE;
5996aab59a7Smrg}
6006aab59a7Smrg
6016aab59a7Smrgstatic const char **
6026aab59a7SmrgBuiltinNames(void)
6036aab59a7Smrg{
6046aab59a7Smrg    return internalNames;
6056aab59a7Smrg}
6066aab59a7Smrg
6076aab59a7Smrgstatic Bool
6086aab59a7SmrgCheckProtocol(const char *protocol)
6096aab59a7Smrg{
6106aab59a7Smrg    int i;
6116aab59a7Smrg
6126aab59a7Smrg    for (i = 0; internalNames[i]; i++)
6136aab59a7Smrg	if (xf86NameCmp(protocol, internalNames[i]) == 0)
6146aab59a7Smrg	    return TRUE;
6156aab59a7Smrg
6166aab59a7Smrg    return FALSE;
6176aab59a7Smrg}
6186aab59a7Smrg
6196aab59a7Smrgstatic const char *
6206aab59a7SmrgDefaultProtocol(void)
6216aab59a7Smrg{
6226aab59a7Smrg    return "Auto";
6236aab59a7Smrg}
6246aab59a7Smrg
6256aab59a7Smrgstatic Bool
6266aab59a7SmrgsolarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol,
6276aab59a7Smrg	const char **device)
6286aab59a7Smrg{
6296aab59a7Smrg    const char **pdev, **pproto;
6306aab59a7Smrg    int fd = -1;
6316aab59a7Smrg    Bool found;
6326aab59a7Smrg    char *strmod;
6336aab59a7Smrg
6346aab59a7Smrg    if (*device == NULL) {
6356aab59a7Smrg	/* Check to see if xorg.conf or HAL specified a device to use */
6366aab59a7Smrg	*device = xf86CheckStrOption(pInfo->options, "Device", NULL);
6376aab59a7Smrg	if (*device == NULL) {
6386aab59a7Smrg	    *device = xf86CheckStrOption(pInfo->conf_idev->commonOptions,
6396aab59a7Smrg					 "Device", NULL);
6406aab59a7Smrg	}
6416aab59a7Smrg    }
6426aab59a7Smrg
6436aab59a7Smrg    if (*device != NULL) {
6446aab59a7Smrg	strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL);
6456aab59a7Smrg	if (strmod == NULL) {
6466aab59a7Smrg	    strmod = xf86CheckStrOption(pInfo->conf_idev->commonOptions,
6476aab59a7Smrg					"StreamsModule", NULL);
6486aab59a7Smrg	}
6496aab59a7Smrg	if (strmod) {
6506aab59a7Smrg	    /* if a device name is already known, and a StreamsModule is
6516aab59a7Smrg	       specified to convert events to VUID, then we don't need to
6526aab59a7Smrg	       probe further */
6536aab59a7Smrg	    *protocol = "VUID";
6546aab59a7Smrg	    return TRUE;
6556aab59a7Smrg	}
6566aab59a7Smrg    }
6576aab59a7Smrg
6586aab59a7Smrg
6596aab59a7Smrg    for (pdev = solarisMouseDevs; *pdev; pdev += 2) {
6606aab59a7Smrg	pproto = pdev + 1;
6616aab59a7Smrg	if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) &&
6626aab59a7Smrg	  (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) {
6636aab59a7Smrg	    continue;
6646aab59a7Smrg	}
6656aab59a7Smrg	if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) {
6666aab59a7Smrg	    continue;
6676aab59a7Smrg	}
6686aab59a7Smrg        SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK));
6696aab59a7Smrg	if (fd == -1) {
6706aab59a7Smrg#ifdef DEBUG
6716aab59a7Smrg	    ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno));
6726aab59a7Smrg#endif
6736aab59a7Smrg	} else {
6746aab59a7Smrg	    found = TRUE;
6756aab59a7Smrg	    if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) {
6766aab59a7Smrg		int i, r;
6776aab59a7Smrg		SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i));
6786aab59a7Smrg    		if (r < 0) {
6796aab59a7Smrg		    found = FALSE;
6806aab59a7Smrg		}
6816aab59a7Smrg	    }
6826aab59a7Smrg	    close(fd);
6836aab59a7Smrg	    if (found == TRUE) {
6846aab59a7Smrg		if (*pproto != NULL) {
6856aab59a7Smrg		    *protocol = *pproto;
6866aab59a7Smrg		}
6876aab59a7Smrg		*device = *pdev;
6886aab59a7Smrg		return TRUE;
6896aab59a7Smrg	    }
6906aab59a7Smrg	}
6916aab59a7Smrg    }
6926aab59a7Smrg    return FALSE;
6936aab59a7Smrg}
6946aab59a7Smrg
6956aab59a7Smrgstatic const char *
6966aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara)
6976aab59a7Smrg{
6986aab59a7Smrg    const char *pdev = NULL;
6996aab59a7Smrg    const char *pproto = NULL;
7006aab59a7Smrg    MouseDevPtr pMse = pInfo->private;
7016aab59a7Smrg
7026aab59a7Smrg    if (pInfo->fd == -1) {
7036aab59a7Smrg	/* probe to find device/protocol to use */
7046aab59a7Smrg	if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) {
7056aab59a7Smrg	    /* Set the Device option. */
7066aab59a7Smrg	    pInfo->conf_idev->commonOptions =
7076aab59a7Smrg	     xf86AddNewOption(pInfo->conf_idev->commonOptions, "Device", pdev);
7086aab59a7Smrg	    xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
7096aab59a7Smrg	      pInfo->name, pdev);
7106aab59a7Smrg	}
7116aab59a7Smrg    } else if (pMse->protocolID == PROT_AUTO) {
7126aab59a7Smrg	pdev = xf86CheckStrOption(pInfo->conf_idev->commonOptions,
7136aab59a7Smrg		"Device", NULL);
7146aab59a7Smrg	solarisMouseAutoProbe(pInfo, &pproto, &pdev);
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) {
7266aab59a7Smrg	/* Set the Device option. */
7276aab59a7Smrg	pInfo->conf_idev->commonOptions =
7286aab59a7Smrg	  xf86AddNewOption(pInfo->conf_idev->commonOptions, "Device", pdev);
7296aab59a7Smrg	xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
7306aab59a7Smrg	  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
7426aab59a7Smrg_X_EXPORT OSMouseInfoPtr
7436aab59a7Smrgxf86OSMouseInit(int flags)
7446aab59a7Smrg{
7456aab59a7Smrg    OSMouseInfoPtr p;
7466aab59a7Smrg
7476aab59a7Smrg    p = xcalloc(sizeof(OSMouseInfoRec), 1);
7486aab59a7Smrg    if (!p)
7496aab59a7Smrg	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