1b73be646Smrg/* 2ebac4eb7Smrg * Copyright (c) 2004, 2022, Oracle and/or its affiliates. 3b73be646Smrg * 4b73be646Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b73be646Smrg * copy of this software and associated documentation files (the "Software"), 6b73be646Smrg * to deal in the Software without restriction, including without limitation 7b73be646Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b73be646Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b73be646Smrg * Software is furnished to do so, subject to the following conditions: 10b73be646Smrg * 11b73be646Smrg * The above copyright notice and this permission notice (including the next 12b73be646Smrg * paragraph) shall be included in all copies or substantial portions of the 13b73be646Smrg * Software. 14b73be646Smrg * 15b73be646Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b73be646Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b73be646Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b73be646Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b73be646Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b73be646Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21b73be646Smrg * DEALINGS IN THE SOFTWARE. 22b73be646Smrg */ 236aab59a7Smrg/* 246aab59a7Smrg * Copyright 1999-2001 The XFree86 Project, Inc. All Rights Reserved. 256aab59a7Smrg * 266aab59a7Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy 276aab59a7Smrg * of this software and associated documentation files (the "Software"), to 286aab59a7Smrg * deal in the Software without restriction, including without limitation the 296aab59a7Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 306aab59a7Smrg * sell copies of the Software, and to permit persons to whom the Software is 316aab59a7Smrg * furnished to do so, subject to the following conditions: 326aab59a7Smrg * 336aab59a7Smrg * The above copyright notice and this permission notice shall be included in 346aab59a7Smrg * all copies or substantial portions of the Software. 356aab59a7Smrg * 366aab59a7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 376aab59a7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 386aab59a7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 396aab59a7Smrg * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 406aab59a7Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 416aab59a7Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 426aab59a7Smrg * 436aab59a7Smrg * Except as contained in this notice, the name of the XFree86 Project shall 446aab59a7Smrg * not be used in advertising or otherwise to promote the sale, use or other 456aab59a7Smrg * dealings in this Software without prior written authorization from the 466aab59a7Smrg * XFree86 Project. 476aab59a7Smrg */ 486aab59a7Smrg 49370b807fSmrg#ifdef HAVE_CONFIG_H 50370b807fSmrg#include "config.h" 51370b807fSmrg#endif 52370b807fSmrg 536aab59a7Smrg#ifdef HAVE_XORG_CONFIG_H 546aab59a7Smrg#include <xorg-config.h> 556aab59a7Smrg#endif 566aab59a7Smrg 57ebac4eb7Smrg#include <unistd.h> /* for ioctl(2) */ 58ebac4eb7Smrg#include <sys/stropts.h> 59ebac4eb7Smrg#include <sys/vuid_event.h> 60ebac4eb7Smrg#include <sys/msio.h> 61ebac4eb7Smrg#include <fcntl.h> 62ebac4eb7Smrg#include <errno.h> 636aab59a7Smrg#include "xorg-server.h" 646aab59a7Smrg#include "xf86.h" 656aab59a7Smrg#include "xf86_OSlib.h" 66bd3a1963Smrg#include "mouse.h" 676aab59a7Smrg#include "xisb.h" 686aab59a7Smrg#include "mipointer.h" 6984bf8334Smrg#include "xf86Crtc.h" 706aab59a7Smrg 716aab59a7Smrg/* Wheel mouse support in VUID drivers in Solaris 9 updates & Solaris 10 */ 726aab59a7Smrg#ifdef WHEEL_DEVID /* Defined in vuid_event.h if VUID wheel support present */ 736aab59a7Smrg# define HAVE_VUID_WHEEL 746aab59a7Smrg#endif 756aab59a7Smrg#ifdef HAVE_VUID_WHEEL 766aab59a7Smrg# include <sys/vuid_wheel.h> 776aab59a7Smrg#endif 786aab59a7Smrg 79ebac4eb7Smrg#include <libdevinfo.h> 80ebac4eb7Smrg 81a73597f9Smrg/* Support for scaling absolute coordinates to screen size in 826aab59a7Smrg * Solaris 10 updates and beyond */ 836aab59a7Smrg#if !defined(HAVE_ABSOLUTE_MOUSE_SCALING) 846aab59a7Smrg# ifdef MSIOSRESOLUTION /* Defined in msio.h if scaling support present */ 856aab59a7Smrg# define HAVE_ABSOLUTE_MOUSE_SCALING 866aab59a7Smrg# endif 876aab59a7Smrg#endif 886aab59a7Smrg 896aab59a7Smrg/* Names of protocols that are handled internally here. */ 906aab59a7Smrg 916aab59a7Smrgstatic const char *internalNames[] = { 92a73597f9Smrg "VUID", 93a73597f9Smrg NULL 946aab59a7Smrg}; 956aab59a7Smrg 966aab59a7Smrgstatic const char *solarisMouseDevs[] = { 97a73597f9Smrg /* Device file: Protocol: */ 98a73597f9Smrg "/dev/mouse", "VUID", /* USB or SPARC */ 996aab59a7Smrg#if defined(__i386) || defined(__x86) 100a73597f9Smrg "/dev/kdmouse", "PS/2", /* PS/2 */ 1016aab59a7Smrg#endif 1026aab59a7Smrg NULL 1036aab59a7Smrg}; 1046aab59a7Smrg 1056aab59a7Smrgtypedef struct _VuidMseRec { 106a73597f9Smrg struct _VuidMseRec *next; 107a73597f9Smrg InputInfoPtr pInfo; 108a73597f9Smrg Firm_event event; 109a73597f9Smrg unsigned char * buffer; 110a73597f9Smrg char * strmod; 1116aab59a7Smrg Bool(*wrapped_device_control)(DeviceIntPtr device, int what); 1126aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 113a73597f9Smrg Ms_screen_resolution absres; 1146aab59a7Smrg#endif 115a73597f9Smrg OsTimerPtr remove_timer; /* Callback for removal on ENODEV */ 116ebac4eb7Smrg int relToAbs; 117ebac4eb7Smrg int absX; 118ebac4eb7Smrg int absY; 1196aab59a7Smrg} VuidMseRec, *VuidMsePtr; 1206aab59a7Smrg 121a73597f9Smrgstatic VuidMsePtr vuidMouseList = NULL; 1226aab59a7Smrg 1236aab59a7Smrgstatic int vuidMouseProc(DeviceIntPtr pPointer, int what); 1246aab59a7Smrgstatic void vuidReadInput(InputInfoPtr pInfo); 1256aab59a7Smrg 126ebac4eb7Smrgstatic int CheckRelToAbs(InputInfoPtr pInfo); 127ebac4eb7Smrgstatic int CheckRelToAbsWalker(di_node_t node, void *arg); 128ebac4eb7Smrg 1296aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 130a73597f9Smrg# include "compat-api.h" 131a73597f9Smrg 1326aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse); 133a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL); 1346aab59a7Smrg 135370b807fSmrgstatic unsigned long vuidMouseGeneration = 0; 136b73be646Smrg 137b73be646Smrg#if HAS_DEVPRIVATEKEYREC 138b73be646Smrgstatic DevPrivateKeyRec vuidMouseScreenIndex; 139b73be646Smrg#else 1406aab59a7Smrgstatic int vuidMouseScreenIndex; 141b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 142b73be646Smrg 1436aab59a7Smrg#define vuidMouseGetScreenPrivate(s) ( \ 1446aab59a7Smrg dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex)) 1456aab59a7Smrg#define vuidMouseSetScreenPrivate(s,p) \ 1466aab59a7Smrg dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p) 1476aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 1486aab59a7Smrg 1496aab59a7Smrgstatic inline 1506aab59a7SmrgVuidMsePtr getVuidMsePriv(InputInfoPtr pInfo) 1516aab59a7Smrg{ 1526aab59a7Smrg VuidMsePtr m = vuidMouseList; 1536aab59a7Smrg 1546aab59a7Smrg while ((m != NULL) && (m->pInfo != pInfo)) { 155a73597f9Smrg m = m->next; 1566aab59a7Smrg } 1576aab59a7Smrg 1586aab59a7Smrg return m; 1596aab59a7Smrg} 1606aab59a7Smrg 161b73be646Smrg/* Called from OsTimer callback, since removing a device from the device 162b73be646Smrg list or changing pInfo->fd while xf86Wakeup is looping through the list 163b73be646Smrg causes server crashes */ 164b73be646Smrgstatic CARD32 165a73597f9SmrgvuidRemoveMouse(OsTimerPtr timer, CARD32 now, pointer arg) 166b73be646Smrg{ 167b73be646Smrg InputInfoPtr pInfo = (InputInfoPtr) arg; 168b73be646Smrg 169b73be646Smrg xf86DisableDevice(pInfo->dev, TRUE); 170b73be646Smrg 171b73be646Smrg return 0; /* All done, don't set to run again */ 172b73be646Smrg} 1736aab59a7Smrg 1746aab59a7Smrg/* 1756aab59a7Smrg * Initialize and enable the mouse wheel, if present. 1766aab59a7Smrg * 1776aab59a7Smrg * Returns 1 if mouse wheel was successfully enabled. 1786aab59a7Smrg * Returns 0 if an error occurred or if there is no mouse wheel. 1796aab59a7Smrg */ 1806aab59a7Smrgstatic int 1816aab59a7SmrgvuidMouseWheelInit(InputInfoPtr pInfo) 1826aab59a7Smrg{ 1836aab59a7Smrg#ifdef HAVE_VUID_WHEEL 1846aab59a7Smrg wheel_state wstate; 1856aab59a7Smrg int nwheel = -1; 1866aab59a7Smrg int i; 1876aab59a7Smrg 1886aab59a7Smrg wstate.vers = VUID_WHEEL_STATE_VERS; 1896aab59a7Smrg wstate.id = 0; 1906aab59a7Smrg wstate.stateflags = (uint32_t) -1; 1916aab59a7Smrg 1926aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel)); 1936aab59a7Smrg if (i != 0) 194a73597f9Smrg return (0); 1956aab59a7Smrg 1966aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate)); 1976aab59a7Smrg if (i != 0) { 198a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name); 199a73597f9Smrg return (0); 2006aab59a7Smrg } 2016aab59a7Smrg 2026aab59a7Smrg wstate.stateflags |= VUID_WHEEL_STATE_ENABLED; 2036aab59a7Smrg 2046aab59a7Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate)); 2056aab59a7Smrg if (i != 0) { 206a73597f9Smrg xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name); 207a73597f9Smrg return (0); 2086aab59a7Smrg } 2096aab59a7Smrg 2106aab59a7Smrg return (1); 2116aab59a7Smrg#else 2126aab59a7Smrg return (0); 2136aab59a7Smrg#endif 2146aab59a7Smrg} 2156aab59a7Smrg 2166aab59a7Smrg 2176aab59a7Smrg/* This function is called when the protocol is "VUID". */ 2186aab59a7Smrgstatic Bool 2196aab59a7SmrgvuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 2206aab59a7Smrg{ 2216aab59a7Smrg MouseDevPtr pMse = pInfo->private; 2226aab59a7Smrg VuidMsePtr pVuidMse; 223a73597f9Smrg 224a73597f9Smrg /* Ensure we don't add the same device twice */ 225a73597f9Smrg if (getVuidMsePriv(pInfo) != NULL) 226a73597f9Smrg return TRUE; 2276aab59a7Smrg 228bd3a1963Smrg pVuidMse = calloc(sizeof(VuidMseRec), 1); 2296aab59a7Smrg if (pVuidMse == NULL) { 230a73597f9Smrg xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); 231a73597f9Smrg free(pMse); 232a73597f9Smrg return FALSE; 2336aab59a7Smrg } 2346aab59a7Smrg 235fc27e79cSmrg pVuidMse->buffer = (unsigned char *)&pVuidMse->event; 236fc27e79cSmrg pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL); 237ebac4eb7Smrg pVuidMse->relToAbs = xf86SetIntOption(pInfo->options, "RelToAbs", -1); 238ebac4eb7Smrg if (pVuidMse->relToAbs == -1) 239ebac4eb7Smrg pVuidMse->relToAbs = CheckRelToAbs(pInfo); 240ebac4eb7Smrg pVuidMse->absX = 0; 241ebac4eb7Smrg pVuidMse->absY = 0; 242fc27e79cSmrg 2436aab59a7Smrg /* Setup the local procs. */ 2446aab59a7Smrg pVuidMse->wrapped_device_control = pInfo->device_control; 2456aab59a7Smrg pInfo->device_control = vuidMouseProc; 2466aab59a7Smrg pInfo->read_input = vuidReadInput; 2476aab59a7Smrg 2486aab59a7Smrg pMse->xisbscale = sizeof(Firm_event); 2496aab59a7Smrg 250a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 2516aab59a7Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 2526aab59a7Smrg#endif 2536aab59a7Smrg pVuidMse->pInfo = pInfo; 254a73597f9Smrg pVuidMse->next = vuidMouseList; 2556aab59a7Smrg vuidMouseList = pVuidMse; 2566aab59a7Smrg 257bd3a1963Smrg#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 2586aab59a7Smrg pInfo->flags |= XI86_CONFIGURED; 259bd3a1963Smrg#endif 2606aab59a7Smrg return TRUE; 2616aab59a7Smrg} 2626aab59a7Smrg 263ebac4eb7Smrg/* 264ebac4eb7Smrg * It seems that the mouse that is presented by the Emulex ILOM 265ebac4eb7Smrg * device (USB 0x430, 0xa101 and USB 0x430, 0xa102) sends relative 266ebac4eb7Smrg * mouse movements. But relative mouse movements are subject to 267ebac4eb7Smrg * acceleration. This causes the position indicated on the ILOM 268ebac4eb7Smrg * window to not match what the Xorg server actually has. This 269ebac4eb7Smrg * makes the mouse in this environment rather unusable. So, for the 270ebac4eb7Smrg * Emulex ILOM device, we will change all relative mouse movements 271ebac4eb7Smrg * into absolute mouse movements, making it appear more like a 272ebac4eb7Smrg * tablet. This will not be subject to acceleration, and this 273ebac4eb7Smrg * should keep the ILOM window and Xorg server with the same values 274ebac4eb7Smrg * for the coordinates of the mouse. 275ebac4eb7Smrg */ 276ebac4eb7Smrg 277ebac4eb7Smrgtypedef struct reltoabs_match { 278ebac4eb7Smrg int matched; 279ebac4eb7Smrg char const *matchname; 280ebac4eb7Smrg } reltoabs_match_t; 281ebac4eb7Smrg 282ebac4eb7Smrg/* Sun Microsystems, keyboard / mouse */ 283ebac4eb7Smrg#define RELTOABS_MATCH1 "usbif430,a101.config1.1" 284ebac4eb7Smrg/* Sun Microsystems, keyboard / mouse / storage */ 285ebac4eb7Smrg#define RELTOABS_MATCH2 "usbif430,a102.config1.1" 286ebac4eb7Smrg 287ebac4eb7Smrgstatic int 288ebac4eb7SmrgCheckRelToAbsWalker(di_node_t node, void *arg) 289ebac4eb7Smrg{ 290ebac4eb7Smrg di_minor_t minor; 291ebac4eb7Smrg char *path; 292ebac4eb7Smrg int numvalues; 293ebac4eb7Smrg int valueon; 294ebac4eb7Smrg char const *stringptr; 295ebac4eb7Smrg int status; 296ebac4eb7Smrg reltoabs_match_t *const matchptr = (reltoabs_match_t *)arg; 297ebac4eb7Smrg char *stringvalues; 298ebac4eb7Smrg 299ebac4eb7Smrg for (minor = di_minor_next(node, DI_MINOR_NIL); 300ebac4eb7Smrg minor != DI_MINOR_NIL; 301ebac4eb7Smrg minor = di_minor_next(node, minor)) { 302ebac4eb7Smrg path = di_devfs_minor_path(minor); 303ebac4eb7Smrg status = path != NULL && strcmp(path, matchptr -> matchname) == 0; 304ebac4eb7Smrg di_devfs_path_free(path); 305ebac4eb7Smrg if (status) 306ebac4eb7Smrg break; 307ebac4eb7Smrg } 308ebac4eb7Smrg 309ebac4eb7Smrg if (minor == DI_MINOR_NIL) 310ebac4eb7Smrg return (DI_WALK_CONTINUE); 311ebac4eb7Smrg 312ebac4eb7Smrg numvalues = di_prop_lookup_strings(DDI_DEV_T_ANY, node, 313ebac4eb7Smrg "compatible", &stringvalues); 314ebac4eb7Smrg if (numvalues <= 0) 315ebac4eb7Smrg return (DI_WALK_CONTINUE); 316ebac4eb7Smrg 317ebac4eb7Smrg for (valueon = 0, stringptr = stringvalues; valueon < numvalues; 318ebac4eb7Smrg valueon++, stringptr += strlen(stringptr) + 1) { 319ebac4eb7Smrg if (strcmp(stringptr, RELTOABS_MATCH1) == 0) { 320ebac4eb7Smrg matchptr -> matched = 1; 321ebac4eb7Smrg return (DI_WALK_TERMINATE); 322ebac4eb7Smrg } 323ebac4eb7Smrg if (strcmp(stringptr, RELTOABS_MATCH2) == 0) { 324ebac4eb7Smrg matchptr -> matched = 2; 325ebac4eb7Smrg return (DI_WALK_TERMINATE); 326ebac4eb7Smrg } 327ebac4eb7Smrg } 328ebac4eb7Smrg return (DI_WALK_CONTINUE); 329ebac4eb7Smrg} 330ebac4eb7Smrg 331ebac4eb7Smrgstatic int 332ebac4eb7SmrgCheckRelToAbs(InputInfoPtr pInfo) 333ebac4eb7Smrg{ 334ebac4eb7Smrg char const *device; 335ebac4eb7Smrg char const *matchname; 336ebac4eb7Smrg ssize_t readstatus; 337ebac4eb7Smrg di_node_t node; 338ebac4eb7Smrg struct stat statbuf; 339ebac4eb7Smrg char linkname[512]; 340ebac4eb7Smrg reltoabs_match_t reltoabs_match; 341ebac4eb7Smrg 342ebac4eb7Smrg device = xf86CheckStrOption(pInfo->options, "Device", NULL); 343ebac4eb7Smrg if (device == NULL) 344ebac4eb7Smrg return (0); 345ebac4eb7Smrg 346ebac4eb7Smrg matchname = device; 347ebac4eb7Smrg 348ebac4eb7Smrg if (lstat(device, &statbuf) == 0 && 349ebac4eb7Smrg (statbuf.st_mode & S_IFMT) == S_IFLNK) { 350ebac4eb7Smrg readstatus = readlink(device, linkname, sizeof(linkname)); 351ebac4eb7Smrg if (readstatus > 0 && readstatus < (ssize_t) sizeof(linkname)) { 352ebac4eb7Smrg linkname[readstatus] = 0; 353ebac4eb7Smrg matchname = linkname; 354ebac4eb7Smrg if (strncmp(matchname, "../..", sizeof("../..") - 1) == 0) 355ebac4eb7Smrg matchname += sizeof("../..") - 1; 356ebac4eb7Smrg } 357ebac4eb7Smrg } 358ebac4eb7Smrg 359ebac4eb7Smrg if (strncmp(matchname, "/devices", sizeof("/devices") - 1) == 0) 360ebac4eb7Smrg matchname += sizeof("/devices") - 1; 361ebac4eb7Smrg 362ebac4eb7Smrg reltoabs_match.matched = 0; 363ebac4eb7Smrg reltoabs_match.matchname = matchname; 364ebac4eb7Smrg 365ebac4eb7Smrg node = di_init("/", DINFOCPYALL); 366ebac4eb7Smrg if (node == DI_NODE_NIL) 367ebac4eb7Smrg return (0); 368ebac4eb7Smrg 369ebac4eb7Smrg di_walk_node(node, DI_WALK_CLDFIRST, (void *)&reltoabs_match, 370ebac4eb7Smrg CheckRelToAbsWalker); 371ebac4eb7Smrg 372ebac4eb7Smrg di_fini(node); 373ebac4eb7Smrg 374ebac4eb7Smrg return (reltoabs_match.matched != 0); 375ebac4eb7Smrg} 376ebac4eb7Smrg 3776aab59a7Smrgstatic void 378a73597f9SmrgvuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY, 379a73597f9Smrg Bool *absXset, Bool *absYset) 3806aab59a7Smrg{ 3816aab59a7Smrg#ifdef DEBUG 382a73597f9Smrg ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY, 383a73597f9Smrg *absXset, *absYset); 3846aab59a7Smrg#endif 3856aab59a7Smrg if ((*absXset) && (*absYset)) { 386a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 387a73597f9Smrg /* is_absolute: */ TRUE, 388a73597f9Smrg /* first_valuator: */ 0, 389a73597f9Smrg /* num_valuators: */ 2, 390a73597f9Smrg absX, absY); 3916aab59a7Smrg } else if (*absXset) { 392a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 393a73597f9Smrg /* is_absolute: */ TRUE, 394a73597f9Smrg /* first_valuator: */ 0, 395a73597f9Smrg /* num_valuators: */ 1, 396a73597f9Smrg absX); 3976aab59a7Smrg } else if (*absYset) { 398a73597f9Smrg xf86PostMotionEvent(pInfo->dev, 399a73597f9Smrg /* is_absolute: */ TRUE, 400a73597f9Smrg /* first_valuator: */ 1, 401a73597f9Smrg /* num_valuators: */ 1, 402a73597f9Smrg absY); 4036aab59a7Smrg } 4046aab59a7Smrg 4056aab59a7Smrg *absXset = FALSE; 4066aab59a7Smrg *absYset = FALSE; 4076aab59a7Smrg} 4086aab59a7Smrg 4096aab59a7Smrgstatic void 4106aab59a7SmrgvuidReadInput(InputInfoPtr pInfo) 4116aab59a7Smrg{ 4126aab59a7Smrg MouseDevPtr pMse; 4136aab59a7Smrg VuidMsePtr pVuidMse; 4146aab59a7Smrg int buttons; 4156aab59a7Smrg int dx = 0, dy = 0, dz = 0, dw = 0; 416370b807fSmrg ssize_t n; 4176aab59a7Smrg unsigned char *pBuf; 4186aab59a7Smrg int absX = 0, absY = 0; 419ebac4eb7Smrg int hdisplay = 0, vdisplay = 0; 4206aab59a7Smrg Bool absXset = FALSE, absYset = FALSE; 421ebac4eb7Smrg int relToAbs; 4226aab59a7Smrg 4236aab59a7Smrg pMse = pInfo->private; 4246aab59a7Smrg buttons = pMse->lastButtons; 425370b807fSmrg pVuidMse = getVuidMsePriv(pInfo); 426370b807fSmrg if (pVuidMse == NULL) { 427370b807fSmrg xf86Msg(X_ERROR, "%s: cannot locate VuidMsePtr\n", pInfo->name); 428370b807fSmrg return; 429370b807fSmrg } 4306aab59a7Smrg pBuf = pVuidMse->buffer; 431ebac4eb7Smrg relToAbs = pVuidMse->relToAbs; 432ebac4eb7Smrg if (relToAbs) { 433ebac4eb7Smrg ScreenPtr pScreen = miPointerGetScreen(pInfo->dev); 434ebac4eb7Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 435ebac4eb7Smrg 436ebac4eb7Smrg if (pScr->currentMode) { 437ebac4eb7Smrg hdisplay = pScr->currentMode->HDisplay; 438ebac4eb7Smrg vdisplay = pScr->currentMode->VDisplay; 439ebac4eb7Smrg } 440ebac4eb7Smrg absX = pVuidMse->absX; 441ebac4eb7Smrg absY = pVuidMse->absY; 442ebac4eb7Smrg } 4436aab59a7Smrg 4446aab59a7Smrg do { 445a73597f9Smrg n = read(pInfo->fd, pBuf, sizeof(Firm_event)); 446a73597f9Smrg 447a73597f9Smrg if (n == 0) { 448a73597f9Smrg break; 449a73597f9Smrg } else if (n == -1) { 450a73597f9Smrg switch (errno) { 451a73597f9Smrg case EAGAIN: /* Nothing to read now */ 452a73597f9Smrg n = 0; /* End loop, go on to flush events & return */ 453a73597f9Smrg continue; 454a73597f9Smrg case EINTR: /* Interrupted, try again */ 455a73597f9Smrg continue; 456a73597f9Smrg case ENODEV: /* May happen when USB mouse is unplugged */ 457a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 458a73597f9Smrg may be called from SIGIO handler. No longer true for 459a73597f9Smrg sigsafe logging, but matters for older servers */ 460a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, 461a73597f9Smrg "%s: Device no longer present - removing.\n", 462a73597f9Smrg pInfo->name); 463a73597f9Smrg xf86RemoveEnabledDevice(pInfo); 464a73597f9Smrg pVuidMse->remove_timer = 465a73597f9Smrg TimerSet(pVuidMse->remove_timer, 0, 1, 466a73597f9Smrg vuidRemoveMouse, pInfo); 467a73597f9Smrg return; 468a73597f9Smrg default: /* All other errors */ 469a73597f9Smrg /* We use X_NONE here because it didn't alloc since we 470a73597f9Smrg may be called from SIGIO handler. No longer true for 471a73597f9Smrg sigsafe logging, but matters for older servers */ 472a73597f9Smrg LogMessageVerbSigSafe(X_NONE, 0, "%s: Read error: %s\n", 473a73597f9Smrg pInfo->name, strerror(errno)); 474a73597f9Smrg return; 475a73597f9Smrg } 476a73597f9Smrg } else if (n != sizeof(Firm_event)) { 477370b807fSmrg xf86Msg(X_WARNING, "%s: incomplete packet, size %zd\n", 478a73597f9Smrg pInfo->name, n); 479a73597f9Smrg } 4806aab59a7Smrg 4816aab59a7Smrg#ifdef DEBUG 482a73597f9Smrg LogMessageVerbSigSafe("vuidReadInput: event type: %d value: %d\n", 483a73597f9Smrg pVuidMse->event.id, pVuidMse->event.value); 4846aab59a7Smrg#endif 4856aab59a7Smrg 486a73597f9Smrg if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { 487a73597f9Smrg /* button */ 488a73597f9Smrg int butnum = pVuidMse->event.id - BUT_FIRST; 489a73597f9Smrg 490a73597f9Smrg if (butnum < 3) 491a73597f9Smrg butnum = 2 - butnum; 492a73597f9Smrg if (!pVuidMse->event.value) 493a73597f9Smrg buttons &= ~(1 << butnum); 494a73597f9Smrg else 495a73597f9Smrg buttons |= (1 << butnum); 496a73597f9Smrg } else if (pVuidMse->event.id >= VLOC_FIRST && 497a73597f9Smrg pVuidMse->event.id <= VLOC_LAST) { 498a73597f9Smrg /* axis */ 499a73597f9Smrg int delta = pVuidMse->event.value; 500a73597f9Smrg switch(pVuidMse->event.id) { 501a73597f9Smrg case LOC_X_DELTA: 502ebac4eb7Smrg if (!relToAbs) 503ebac4eb7Smrg dx += delta; 504ebac4eb7Smrg else { 505ebac4eb7Smrg if (absXset) 506ebac4eb7Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 507ebac4eb7Smrg absX += delta; 508ebac4eb7Smrg if (absX < 0) 509ebac4eb7Smrg absX = 0; 510ebac4eb7Smrg else if (absX >= hdisplay && hdisplay > 0) 511ebac4eb7Smrg absX = hdisplay - 1; 512ebac4eb7Smrg pVuidMse->absX = absX; 513ebac4eb7Smrg absXset = TRUE; 514ebac4eb7Smrg } 515a73597f9Smrg break; 516a73597f9Smrg case LOC_Y_DELTA: 517ebac4eb7Smrg if (!relToAbs) 518ebac4eb7Smrg dy -= delta; 519ebac4eb7Smrg else { 520ebac4eb7Smrg if (absYset) 521ebac4eb7Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 522ebac4eb7Smrg absY -= delta; 523ebac4eb7Smrg if (absY < 0) 524ebac4eb7Smrg absY = 0; 525ebac4eb7Smrg else if (absY >= vdisplay && vdisplay > 0) 526ebac4eb7Smrg absY = vdisplay - 1; 527ebac4eb7Smrg pVuidMse->absY = absY; 528ebac4eb7Smrg absYset = TRUE; 529ebac4eb7Smrg } 530a73597f9Smrg break; 531a73597f9Smrg case LOC_X_ABSOLUTE: 532a73597f9Smrg if (absXset) { 533a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 534a73597f9Smrg } 535a73597f9Smrg absX = delta; 536a73597f9Smrg absXset = TRUE; 537a73597f9Smrg break; 538a73597f9Smrg case LOC_Y_ABSOLUTE: 539a73597f9Smrg if (absYset) { 540a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 541a73597f9Smrg } 542a73597f9Smrg absY = delta; 543a73597f9Smrg absYset = TRUE; 544a73597f9Smrg break; 545a73597f9Smrg } 546a73597f9Smrg } 5476aab59a7Smrg#ifdef HAVE_VUID_WHEEL 548a73597f9Smrg else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) { 549a73597f9Smrg if (vuid_id_offset(pVuidMse->event.id) == 0) 550a73597f9Smrg dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 551a73597f9Smrg else 552a73597f9Smrg dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 553a73597f9Smrg } 5546aab59a7Smrg#endif 5556aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 556a73597f9Smrg else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) { 557a73597f9Smrg ScreenPtr ptrCurScreen; 558a73597f9Smrg 559a73597f9Smrg /* force sending absolute resolution scaling ioctl */ 560a73597f9Smrg pVuidMse->absres.height = pVuidMse->absres.width = 0; 561a73597f9Smrg ptrCurScreen = miPointerGetScreen(pInfo->dev); 562a73597f9Smrg vuidMouseSendScreenSize(ptrCurScreen, pVuidMse); 563a73597f9Smrg } 5646aab59a7Smrg#endif 5656aab59a7Smrg 5666aab59a7Smrg } while (n != 0); 5676aab59a7Smrg 5686aab59a7Smrg if (absXset || absYset) { 569a73597f9Smrg vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 5706aab59a7Smrg } 5716aab59a7Smrg 5726aab59a7Smrg pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 5736aab59a7Smrg return; 5746aab59a7Smrg} 5756aab59a7Smrg 5766aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 5776aab59a7Smrgstatic void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse) 5786aab59a7Smrg{ 5796aab59a7Smrg InputInfoPtr pInfo = pVuidMse->pInfo; 5806aab59a7Smrg ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 5816aab59a7Smrg int result; 5826aab59a7Smrg 58384bf8334Smrg if ((pVuidMse->absres.width != pScr->virtualX) || 58484bf8334Smrg (pVuidMse->absres.height != pScr->virtualY)) 5856aab59a7Smrg { 58684bf8334Smrg pVuidMse->absres.width = pScr->virtualX; 58784bf8334Smrg pVuidMse->absres.height = pScr->virtualY; 5886aab59a7Smrg 589a73597f9Smrg do { 590a73597f9Smrg result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres)); 591a73597f9Smrg } while ( (result != 0) && (errno == EINTR) ); 5926aab59a7Smrg 593a73597f9Smrg if (result != 0) { 594a73597f9Smrg LogMessageVerbSigSafe(X_WARNING, -1, 595a73597f9Smrg "%s: couldn't set absolute mouse scaling resolution: %s\n", 596a73597f9Smrg pInfo->name, strerror(errno)); 5976aab59a7Smrg#ifdef DEBUG 598a73597f9Smrg } else { 599a73597f9Smrg LogMessageVerbSigSafe(X_INFO, 600a73597f9Smrg "%s: absolute mouse scaling resolution set to %d x %d\n", 601a73597f9Smrg pInfo->name, 602a73597f9Smrg pVuidMse->absres.width, 603a73597f9Smrg pVuidMse->absres.height); 6046aab59a7Smrg#endif 605a73597f9Smrg } 6066aab59a7Smrg } 6076aab59a7Smrg} 6086aab59a7Smrg 609a73597f9Smrgstatic void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL) 6106aab59a7Smrg{ 611a73597f9Smrg SCRN_INFO_PTR(arg); 612a73597f9Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 613a73597f9Smrg xf86AdjustFrameProc *wrappedAdjustFrame 614a73597f9Smrg = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen); 615a73597f9Smrg VuidMsePtr m; 616a73597f9Smrg ScreenPtr ptrCurScreen; 617a73597f9Smrg 618a73597f9Smrg if (wrappedAdjustFrame) { 619a73597f9Smrg pScrn->AdjustFrame = wrappedAdjustFrame; 620a73597f9Smrg (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 621a73597f9Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 6226aab59a7Smrg } 6236aab59a7Smrg 6246aab59a7Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 625a73597f9Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 626a73597f9Smrg if (ptrCurScreen == pScreen) 627a73597f9Smrg { 628a73597f9Smrg vuidMouseSendScreenSize(pScreen, m); 629a73597f9Smrg } 6306aab59a7Smrg } 6316aab59a7Smrg} 63284bf8334Smrg 63384bf8334Smrgstatic void vuidMouseCrtcNotify(ScreenPtr pScreen) 63484bf8334Smrg{ 63584bf8334Smrg xf86_crtc_notify_proc_ptr wrappedCrtcNotify 63684bf8334Smrg = (xf86_crtc_notify_proc_ptr) vuidMouseGetScreenPrivate(pScreen); 63784bf8334Smrg VuidMsePtr m; 63884bf8334Smrg ScreenPtr ptrCurScreen; 63984bf8334Smrg 64084bf8334Smrg if (wrappedCrtcNotify) 64184bf8334Smrg wrappedCrtcNotify(pScreen); 64284bf8334Smrg 64384bf8334Smrg for (m = vuidMouseList; m != NULL ; m = m->next) { 64484bf8334Smrg ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 64584bf8334Smrg if (ptrCurScreen == pScreen) { 64684bf8334Smrg vuidMouseSendScreenSize(pScreen, m); 64784bf8334Smrg } 64884bf8334Smrg } 64984bf8334Smrg} 6506aab59a7Smrg#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 6516aab59a7Smrg 6526aab59a7Smrg 6536aab59a7Smrgstatic int 6546aab59a7SmrgvuidMouseProc(DeviceIntPtr pPointer, int what) 6556aab59a7Smrg{ 6566aab59a7Smrg InputInfoPtr pInfo; 6576aab59a7Smrg MouseDevPtr pMse; 6586aab59a7Smrg VuidMsePtr pVuidMse; 6596aab59a7Smrg int ret = Success; 6606aab59a7Smrg int i; 6616aab59a7Smrg 6626aab59a7Smrg pInfo = pPointer->public.devicePrivate; 6636aab59a7Smrg pMse = pInfo->private; 6646aab59a7Smrg pMse->device = pPointer; 6656aab59a7Smrg 6666aab59a7Smrg pVuidMse = getVuidMsePriv(pInfo); 6676aab59a7Smrg if (pVuidMse == NULL) { 668a73597f9Smrg return BadImplementation; 6696aab59a7Smrg } 670a73597f9Smrg 6716aab59a7Smrg switch (what) { 6726aab59a7Smrg 6736aab59a7Smrg case DEVICE_INIT: 6746aab59a7Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 675b73be646Smrg 676b73be646Smrg#if HAS_DEVPRIVATEKEYREC 677a73597f9Smrg if (!dixRegisterPrivateKey(&vuidMouseScreenIndex, PRIVATE_SCREEN, 0)) 678a73597f9Smrg return BadAlloc; 679b73be646Smrg#endif /* HAS_DEVPRIVATEKEYREC */ 680b73be646Smrg 681a73597f9Smrg if (vuidMouseGeneration != serverGeneration) { 682a73597f9Smrg for (i = 0; i < screenInfo.numScreens; i++) { 683a73597f9Smrg ScreenPtr pScreen = screenInfo.screens[i]; 684a73597f9Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 68584bf8334Smrg if (xf86CrtcConfigPrivateIndex != -1) { 68684bf8334Smrg xf86_crtc_notify_proc_ptr pCrtcNotify 68784bf8334Smrg = xf86_wrap_crtc_notify(pScreen, 68884bf8334Smrg vuidMouseCrtcNotify); 68984bf8334Smrg vuidMouseSetScreenPrivate(pScreen, pCrtcNotify); 69084bf8334Smrg } else { 69184bf8334Smrg vuidMouseSetScreenPrivate(pScreen, 69284bf8334Smrg pScrn->AdjustFrame); 69384bf8334Smrg pScrn->AdjustFrame = vuidMouseAdjustFrame; 69484bf8334Smrg } 695a73597f9Smrg } 696a73597f9Smrg vuidMouseGeneration = serverGeneration; 697a73597f9Smrg } 698a73597f9Smrg#endif 699a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 700a73597f9Smrg break; 701a73597f9Smrg 7026aab59a7Smrg case DEVICE_ON: 703a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON); 704a73597f9Smrg 705a73597f9Smrg if ((ret == Success) && (pInfo->fd != -1)) { 706a73597f9Smrg int fmt = VUID_FIRM_EVENT; 707a73597f9Smrg 708a73597f9Smrg if (pVuidMse->strmod) { 709a73597f9Smrg /* Check to see if module is already pushed */ 710a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod)); 711a73597f9Smrg 712a73597f9Smrg if (i == 0) { /* Not already pushed */ 713a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod)); 714a73597f9Smrg if (i < 0) { 715a73597f9Smrg xf86Msg(X_WARNING, "%s: cannot push module '%s' " 716a73597f9Smrg "onto mouse device: %s\n", pInfo->name, 717a73597f9Smrg pVuidMse->strmod, strerror(errno)); 718a73597f9Smrg free(pVuidMse->strmod); 719a73597f9Smrg pVuidMse->strmod = NULL; 720a73597f9Smrg } 721a73597f9Smrg } 722a73597f9Smrg } 723a73597f9Smrg 724a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt)); 725a73597f9Smrg if (i < 0) { 726a73597f9Smrg xf86Msg(X_WARNING, 727a73597f9Smrg "%s: cannot set mouse device to VUID mode: %s\n", 728a73597f9Smrg pInfo->name, strerror(errno)); 729a73597f9Smrg } 730a73597f9Smrg vuidMouseWheelInit(pInfo); 731a73597f9Smrg#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 732a73597f9Smrg vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse); 733a73597f9Smrg#endif 734a73597f9Smrg xf86FlushInput(pInfo->fd); 735a73597f9Smrg 736a73597f9Smrg /* Allocate here so we don't alloc in ReadInput which may be called 737a73597f9Smrg from SIGIO handler. */ 738a73597f9Smrg if (pVuidMse->remove_timer == NULL) { 739a73597f9Smrg pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer, 740a73597f9Smrg 0, 0, NULL, NULL); 741a73597f9Smrg } 742a73597f9Smrg } 743a73597f9Smrg break; 7446aab59a7Smrg 7456aab59a7Smrg case DEVICE_CLOSE: 746ebac4eb7Smrg if (vuidMouseList == pVuidMse) 747ebac4eb7Smrg vuidMouseList = vuidMouseList->next; 748ebac4eb7Smrg else { 749ebac4eb7Smrg VuidMsePtr m = vuidMouseList; 750ebac4eb7Smrg 751ebac4eb7Smrg while ((m != NULL) && (m->next != pVuidMse)) { 752ebac4eb7Smrg m = m->next; 753ebac4eb7Smrg } 754ebac4eb7Smrg 755ebac4eb7Smrg if (m != NULL) 756ebac4eb7Smrg m->next = pVuidMse->next; 757ebac4eb7Smrg } 758ebac4eb7Smrg /* fallthrough */ 759ebac4eb7Smrg case DEVICE_OFF: 760a73597f9Smrg if (pInfo->fd != -1) { 761a73597f9Smrg if (pVuidMse->strmod) { 762a73597f9Smrg SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod)); 763a73597f9Smrg if (i == -1) { 764a73597f9Smrg xf86Msg(X_WARNING, 765a73597f9Smrg "%s: cannot pop module '%s' off mouse device: %s\n", 766a73597f9Smrg pInfo->name, pVuidMse->strmod, strerror(errno)); 767a73597f9Smrg } 768a73597f9Smrg } 769a73597f9Smrg } 770a73597f9Smrg if (pVuidMse->remove_timer) { 771a73597f9Smrg TimerFree(pVuidMse->remove_timer); 772a73597f9Smrg pVuidMse->remove_timer = NULL; 773a73597f9Smrg } 774a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 775a73597f9Smrg break; 7766aab59a7Smrg 7776aab59a7Smrg default: /* Should never be called, but just in case */ 778a73597f9Smrg ret = pVuidMse->wrapped_device_control(pPointer, what); 779a73597f9Smrg break; 7806aab59a7Smrg } 7816aab59a7Smrg return ret; 7826aab59a7Smrg} 7836aab59a7Smrg 7846aab59a7Smrgstatic Bool 7856aab59a7SmrgsunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 7866aab59a7Smrg{ 7876aab59a7Smrg /* The protocol is guaranteed to be one of the internalNames[] */ 7886aab59a7Smrg if (xf86NameCmp(protocol, "VUID") == 0) { 789a73597f9Smrg return vuidPreInit(pInfo, protocol, flags); 7906aab59a7Smrg } 7916aab59a7Smrg return TRUE; 792a73597f9Smrg} 7936aab59a7Smrg 7946aab59a7Smrgstatic const char ** 7956aab59a7SmrgBuiltinNames(void) 7966aab59a7Smrg{ 7976aab59a7Smrg return internalNames; 7986aab59a7Smrg} 7996aab59a7Smrg 8006aab59a7Smrgstatic Bool 8016aab59a7SmrgCheckProtocol(const char *protocol) 8026aab59a7Smrg{ 8036aab59a7Smrg int i; 8046aab59a7Smrg 8056aab59a7Smrg for (i = 0; internalNames[i]; i++) 806a73597f9Smrg if (xf86NameCmp(protocol, internalNames[i]) == 0) 807a73597f9Smrg return TRUE; 8086aab59a7Smrg 8096aab59a7Smrg return FALSE; 8106aab59a7Smrg} 8116aab59a7Smrg 8126aab59a7Smrgstatic const char * 8136aab59a7SmrgDefaultProtocol(void) 8146aab59a7Smrg{ 8156aab59a7Smrg return "Auto"; 8166aab59a7Smrg} 8176aab59a7Smrg 8186aab59a7Smrgstatic Bool 819a73597f9SmrgsolarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol, 820a73597f9Smrg const char **device) 8216aab59a7Smrg{ 8226aab59a7Smrg const char **pdev, **pproto; 8236aab59a7Smrg int fd = -1; 8246aab59a7Smrg Bool found; 8256aab59a7Smrg char *strmod; 8266aab59a7Smrg 8276aab59a7Smrg if (*device == NULL) { 828a73597f9Smrg /* Check to see if xorg.conf or HAL specified a device to use */ 829a73597f9Smrg *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 8306aab59a7Smrg } 8316aab59a7Smrg 8326aab59a7Smrg if (*device != NULL) { 833a73597f9Smrg strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 834a73597f9Smrg if (strmod) { 835a73597f9Smrg /* if a device name is already known, and a StreamsModule is 836a73597f9Smrg specified to convert events to VUID, then we don't need to 837a73597f9Smrg probe further */ 838a73597f9Smrg *protocol = "VUID"; 839a73597f9Smrg return TRUE; 840a73597f9Smrg } 8416aab59a7Smrg } 8426aab59a7Smrg 8436aab59a7Smrg 8446aab59a7Smrg for (pdev = solarisMouseDevs; *pdev; pdev += 2) { 845a73597f9Smrg pproto = pdev + 1; 846a73597f9Smrg if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) && 847a73597f9Smrg (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) { 848a73597f9Smrg continue; 849a73597f9Smrg } 850a73597f9Smrg if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) { 851a73597f9Smrg continue; 852a73597f9Smrg } 8536aab59a7Smrg SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 854a73597f9Smrg if (fd == -1) { 8556aab59a7Smrg#ifdef DEBUG 856a73597f9Smrg ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno)); 8576aab59a7Smrg#endif 858a73597f9Smrg } else { 859a73597f9Smrg found = TRUE; 860a73597f9Smrg if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) { 861a73597f9Smrg int i, r; 862a73597f9Smrg SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i)); 863a73597f9Smrg if (r < 0) { 864a73597f9Smrg found = FALSE; 865a73597f9Smrg } 866a73597f9Smrg } 867a73597f9Smrg close(fd); 868a73597f9Smrg if (found == TRUE) { 869a73597f9Smrg if (*pproto != NULL) { 870a73597f9Smrg *protocol = *pproto; 871a73597f9Smrg } 872a73597f9Smrg *device = *pdev; 873a73597f9Smrg return TRUE; 874a73597f9Smrg } 875a73597f9Smrg } 8766aab59a7Smrg } 8776aab59a7Smrg return FALSE; 8786aab59a7Smrg} 8796aab59a7Smrg 8806aab59a7Smrgstatic const char * 8816aab59a7SmrgSetupAuto(InputInfoPtr pInfo, int *protoPara) 8826aab59a7Smrg{ 8836aab59a7Smrg const char *pdev = NULL; 8846aab59a7Smrg const char *pproto = NULL; 8856aab59a7Smrg MouseDevPtr pMse = pInfo->private; 8866aab59a7Smrg 8876aab59a7Smrg if (pInfo->fd == -1) { 888a73597f9Smrg /* probe to find device/protocol to use */ 889a73597f9Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 890a73597f9Smrg /* Set the Device option. */ 891a73597f9Smrg pInfo->options = 892a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 893a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 894a73597f9Smrg pInfo->name, pdev); 895a73597f9Smrg } 8966aab59a7Smrg } else if (pMse->protocolID == PROT_AUTO) { 897a73597f9Smrg pdev = xf86CheckStrOption(pInfo->options, 898a73597f9Smrg "Device", NULL); 899a73597f9Smrg if ((solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) && 900a73597f9Smrg (pproto != NULL)) 901a73597f9Smrg sunMousePreInit(pInfo, pproto, 0); 9026aab59a7Smrg } 9036aab59a7Smrg return pproto; 9046aab59a7Smrg} 9056aab59a7Smrg 9066aab59a7Smrgstatic const char * 9076aab59a7SmrgFindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 9086aab59a7Smrg{ 9096aab59a7Smrg const char *pdev = NULL; 9106aab59a7Smrg const char *pproto = protocol; 9116aab59a7Smrg 9126aab59a7Smrg if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 913a73597f9Smrg /* Set the Device option. */ 914a73597f9Smrg pInfo->options = 915a73597f9Smrg xf86AddNewOption(pInfo->options, "Device", pdev); 916a73597f9Smrg xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 917a73597f9Smrg pInfo->name, pdev); 9186aab59a7Smrg } 9196aab59a7Smrg return pdev; 9206aab59a7Smrg} 9216aab59a7Smrg 9226aab59a7Smrgstatic int 9236aab59a7SmrgSupportedInterfaces(void) 9246aab59a7Smrg{ 9256aab59a7Smrg /* XXX This needs to be checked. */ 9266aab59a7Smrg return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; 9276aab59a7Smrg} 9286aab59a7Smrg 929bd3a1963SmrgOSMouseInfoPtr 930bd3a1963SmrgOSMouseInit(int flags) 9316aab59a7Smrg{ 9326aab59a7Smrg OSMouseInfoPtr p; 9336aab59a7Smrg 934bd3a1963Smrg p = calloc(sizeof(OSMouseInfoRec), 1); 9356aab59a7Smrg if (!p) 936a73597f9Smrg return NULL; 9376aab59a7Smrg p->SupportedInterfaces = SupportedInterfaces; 9386aab59a7Smrg p->BuiltinNames = BuiltinNames; 9396aab59a7Smrg p->CheckProtocol = CheckProtocol; 9406aab59a7Smrg p->PreInit = sunMousePreInit; 9416aab59a7Smrg p->DefaultProtocol = DefaultProtocol; 9426aab59a7Smrg p->SetupAuto = SetupAuto; 9436aab59a7Smrg p->FindDevice = FindDevice; 9446aab59a7Smrg 9456aab59a7Smrg return p; 9466aab59a7Smrg} 9476aab59a7Smrg 948