sun_mouse.c revision 370b807f
1/* 2 * Copyright (c) 2004-2005, 2008-2010, Oracle and/or its affiliates. 3 * All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24/* 25 * Copyright 1999-2001 The XFree86 Project, Inc. All Rights Reserved. 26 * 27 * Permission is hereby granted, free of charge, to any person obtaining a copy 28 * of this software and associated documentation files (the "Software"), to 29 * deal in the Software without restriction, including without limitation the 30 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 31 * sell copies of the Software, and to permit persons to whom the Software is 32 * furnished to do so, subject to the following conditions: 33 * 34 * The above copyright notice and this permission notice shall be included in 35 * all copies or substantial portions of the Software. 36 * 37 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 41 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 42 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 43 * 44 * Except as contained in this notice, the name of the XFree86 Project shall 45 * not be used in advertising or otherwise to promote the sale, use or other 46 * dealings in this Software without prior written authorization from the 47 * XFree86 Project. 48 */ 49 50#ifdef HAVE_CONFIG_H 51#include "config.h" 52#endif 53 54#ifdef HAVE_XORG_CONFIG_H 55#include <xorg-config.h> 56#endif 57 58#include "xorg-server.h" 59#include "xf86.h" 60#include "xf86_OSlib.h" 61#include "mouse.h" 62#include "xisb.h" 63#include "mipointer.h" 64#include "xf86Crtc.h" 65#include <sys/stropts.h> 66#include <sys/vuid_event.h> 67#include <sys/msio.h> 68 69/* Wheel mouse support in VUID drivers in Solaris 9 updates & Solaris 10 */ 70#ifdef WHEEL_DEVID /* Defined in vuid_event.h if VUID wheel support present */ 71# define HAVE_VUID_WHEEL 72#endif 73#ifdef HAVE_VUID_WHEEL 74# include <sys/vuid_wheel.h> 75#endif 76 77/* Support for scaling absolute coordinates to screen size in 78 * Solaris 10 updates and beyond */ 79#if !defined(HAVE_ABSOLUTE_MOUSE_SCALING) 80# ifdef MSIOSRESOLUTION /* Defined in msio.h if scaling support present */ 81# define HAVE_ABSOLUTE_MOUSE_SCALING 82# endif 83#endif 84 85/* Names of protocols that are handled internally here. */ 86 87static const char *internalNames[] = { 88 "VUID", 89 NULL 90}; 91 92static const char *solarisMouseDevs[] = { 93 /* Device file: Protocol: */ 94 "/dev/mouse", "VUID", /* USB or SPARC */ 95#if defined(__i386) || defined(__x86) 96 "/dev/kdmouse", "PS/2", /* PS/2 */ 97#endif 98 NULL 99}; 100 101typedef struct _VuidMseRec { 102 struct _VuidMseRec *next; 103 InputInfoPtr pInfo; 104 Firm_event event; 105 unsigned char * buffer; 106 char * strmod; 107 Bool(*wrapped_device_control)(DeviceIntPtr device, int what); 108#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 109 Ms_screen_resolution absres; 110#endif 111 OsTimerPtr remove_timer; /* Callback for removal on ENODEV */ 112} VuidMseRec, *VuidMsePtr; 113 114static VuidMsePtr vuidMouseList = NULL; 115 116static int vuidMouseProc(DeviceIntPtr pPointer, int what); 117static void vuidReadInput(InputInfoPtr pInfo); 118 119#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 120# include "compat-api.h" 121 122static void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse); 123static void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL); 124 125static unsigned long vuidMouseGeneration = 0; 126 127#if HAS_DEVPRIVATEKEYREC 128static DevPrivateKeyRec vuidMouseScreenIndex; 129#else 130static int vuidMouseScreenIndex; 131#endif /* HAS_DEVPRIVATEKEYREC */ 132 133#define vuidMouseGetScreenPrivate(s) ( \ 134 dixLookupPrivate(&(s)->devPrivates, &vuidMouseScreenIndex)) 135#define vuidMouseSetScreenPrivate(s,p) \ 136 dixSetPrivate(&(s)->devPrivates, &vuidMouseScreenIndex, (void *) p) 137#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 138 139static inline 140VuidMsePtr getVuidMsePriv(InputInfoPtr pInfo) 141{ 142 VuidMsePtr m = vuidMouseList; 143 144 while ((m != NULL) && (m->pInfo != pInfo)) { 145 m = m->next; 146 } 147 148 return m; 149} 150 151/* Called from OsTimer callback, since removing a device from the device 152 list or changing pInfo->fd while xf86Wakeup is looping through the list 153 causes server crashes */ 154static CARD32 155vuidRemoveMouse(OsTimerPtr timer, CARD32 now, pointer arg) 156{ 157 InputInfoPtr pInfo = (InputInfoPtr) arg; 158 159 xf86DisableDevice(pInfo->dev, TRUE); 160 161 return 0; /* All done, don't set to run again */ 162} 163 164/* 165 * Initialize and enable the mouse wheel, if present. 166 * 167 * Returns 1 if mouse wheel was successfully enabled. 168 * Returns 0 if an error occurred or if there is no mouse wheel. 169 */ 170static int 171vuidMouseWheelInit(InputInfoPtr pInfo) 172{ 173#ifdef HAVE_VUID_WHEEL 174 wheel_state wstate; 175 int nwheel = -1; 176 int i; 177 178 wstate.vers = VUID_WHEEL_STATE_VERS; 179 wstate.id = 0; 180 wstate.stateflags = (uint32_t) -1; 181 182 SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELCOUNT, &nwheel)); 183 if (i != 0) 184 return (0); 185 186 SYSCALL(i = ioctl(pInfo->fd, VUIDGWHEELSTATE, &wstate)); 187 if (i != 0) { 188 xf86Msg(X_WARNING, "%s: couldn't get wheel state\n", pInfo->name); 189 return (0); 190 } 191 192 wstate.stateflags |= VUID_WHEEL_STATE_ENABLED; 193 194 SYSCALL(i = ioctl(pInfo->fd, VUIDSWHEELSTATE, &wstate)); 195 if (i != 0) { 196 xf86Msg(X_WARNING, "%s: couldn't enable wheel\n", pInfo->name); 197 return (0); 198 } 199 200 return (1); 201#else 202 return (0); 203#endif 204} 205 206 207/* This function is called when the protocol is "VUID". */ 208static Bool 209vuidPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 210{ 211 MouseDevPtr pMse = pInfo->private; 212 VuidMsePtr pVuidMse; 213 214 /* Ensure we don't add the same device twice */ 215 if (getVuidMsePriv(pInfo) != NULL) 216 return TRUE; 217 218 pVuidMse = calloc(sizeof(VuidMseRec), 1); 219 if (pVuidMse == NULL) { 220 xf86Msg(X_ERROR, "%s: cannot allocate VuidMouseRec\n", pInfo->name); 221 free(pMse); 222 return FALSE; 223 } 224 225 pVuidMse->buffer = (unsigned char *)&pVuidMse->event; 226 pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL); 227 228 /* Setup the local procs. */ 229 pVuidMse->wrapped_device_control = pInfo->device_control; 230 pInfo->device_control = vuidMouseProc; 231 pInfo->read_input = vuidReadInput; 232 233 pMse->xisbscale = sizeof(Firm_event); 234 235#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 236 pVuidMse->absres.height = pVuidMse->absres.width = 0; 237#endif 238 pVuidMse->pInfo = pInfo; 239 pVuidMse->next = vuidMouseList; 240 vuidMouseList = pVuidMse; 241 242#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 243 pInfo->flags |= XI86_CONFIGURED; 244#endif 245 return TRUE; 246} 247 248static void 249vuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY, 250 Bool *absXset, Bool *absYset) 251{ 252#ifdef DEBUG 253 ErrorF("vuidFlushAbsEvents: %d,%d (set: %d, %d)\n", absX, absY, 254 *absXset, *absYset); 255#endif 256 if ((*absXset) && (*absYset)) { 257 xf86PostMotionEvent(pInfo->dev, 258 /* is_absolute: */ TRUE, 259 /* first_valuator: */ 0, 260 /* num_valuators: */ 2, 261 absX, absY); 262 } else if (*absXset) { 263 xf86PostMotionEvent(pInfo->dev, 264 /* is_absolute: */ TRUE, 265 /* first_valuator: */ 0, 266 /* num_valuators: */ 1, 267 absX); 268 } else if (*absYset) { 269 xf86PostMotionEvent(pInfo->dev, 270 /* is_absolute: */ TRUE, 271 /* first_valuator: */ 1, 272 /* num_valuators: */ 1, 273 absY); 274 } 275 276 *absXset = FALSE; 277 *absYset = FALSE; 278} 279 280static void 281vuidReadInput(InputInfoPtr pInfo) 282{ 283 MouseDevPtr pMse; 284 VuidMsePtr pVuidMse; 285 int buttons; 286 int dx = 0, dy = 0, dz = 0, dw = 0; 287 ssize_t n; 288 unsigned char *pBuf; 289 int absX = 0, absY = 0; 290 Bool absXset = FALSE, absYset = FALSE; 291 292 pMse = pInfo->private; 293 buttons = pMse->lastButtons; 294 pVuidMse = getVuidMsePriv(pInfo); 295 if (pVuidMse == NULL) { 296 xf86Msg(X_ERROR, "%s: cannot locate VuidMsePtr\n", pInfo->name); 297 return; 298 } 299 pBuf = pVuidMse->buffer; 300 301 do { 302 n = read(pInfo->fd, pBuf, sizeof(Firm_event)); 303 304 if (n == 0) { 305 break; 306 } else if (n == -1) { 307 switch (errno) { 308 case EAGAIN: /* Nothing to read now */ 309 n = 0; /* End loop, go on to flush events & return */ 310 continue; 311 case EINTR: /* Interrupted, try again */ 312 continue; 313 case ENODEV: /* May happen when USB mouse is unplugged */ 314 /* We use X_NONE here because it didn't alloc since we 315 may be called from SIGIO handler. No longer true for 316 sigsafe logging, but matters for older servers */ 317 LogMessageVerbSigSafe(X_NONE, 0, 318 "%s: Device no longer present - removing.\n", 319 pInfo->name); 320 xf86RemoveEnabledDevice(pInfo); 321 pVuidMse->remove_timer = 322 TimerSet(pVuidMse->remove_timer, 0, 1, 323 vuidRemoveMouse, pInfo); 324 return; 325 default: /* All other errors */ 326 /* We use X_NONE here because it didn't alloc since we 327 may be called from SIGIO handler. No longer true for 328 sigsafe logging, but matters for older servers */ 329 LogMessageVerbSigSafe(X_NONE, 0, "%s: Read error: %s\n", 330 pInfo->name, strerror(errno)); 331 return; 332 } 333 } else if (n != sizeof(Firm_event)) { 334 xf86Msg(X_WARNING, "%s: incomplete packet, size %zd\n", 335 pInfo->name, n); 336 } 337 338#ifdef DEBUG 339 LogMessageVerbSigSafe("vuidReadInput: event type: %d value: %d\n", 340 pVuidMse->event.id, pVuidMse->event.value); 341#endif 342 343 if (pVuidMse->event.id >= BUT_FIRST && pVuidMse->event.id <= BUT_LAST) { 344 /* button */ 345 int butnum = pVuidMse->event.id - BUT_FIRST; 346 347 if (butnum < 3) 348 butnum = 2 - butnum; 349 if (!pVuidMse->event.value) 350 buttons &= ~(1 << butnum); 351 else 352 buttons |= (1 << butnum); 353 } else if (pVuidMse->event.id >= VLOC_FIRST && 354 pVuidMse->event.id <= VLOC_LAST) { 355 /* axis */ 356 int delta = pVuidMse->event.value; 357 switch(pVuidMse->event.id) { 358 case LOC_X_DELTA: 359 dx += delta; 360 break; 361 case LOC_Y_DELTA: 362 dy -= delta; 363 break; 364 case LOC_X_ABSOLUTE: 365 if (absXset) { 366 vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 367 } 368 absX = delta; 369 absXset = TRUE; 370 break; 371 case LOC_Y_ABSOLUTE: 372 if (absYset) { 373 vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 374 } 375 absY = delta; 376 absYset = TRUE; 377 break; 378 } 379 } 380#ifdef HAVE_VUID_WHEEL 381 else if (vuid_in_range(VUID_WHEEL, pVuidMse->event.id)) { 382 if (vuid_id_offset(pVuidMse->event.id) == 0) 383 dz -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 384 else 385 dw -= VUID_WHEEL_GETDELTA(pVuidMse->event.value); 386 } 387#endif 388#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 389 else if (pVuidMse->event.id == MOUSE_TYPE_ABSOLUTE) { 390 ScreenPtr ptrCurScreen; 391 392 /* force sending absolute resolution scaling ioctl */ 393 pVuidMse->absres.height = pVuidMse->absres.width = 0; 394 ptrCurScreen = miPointerGetScreen(pInfo->dev); 395 vuidMouseSendScreenSize(ptrCurScreen, pVuidMse); 396 } 397#endif 398 399 } while (n != 0); 400 401 if (absXset || absYset) { 402 vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset); 403 } 404 405 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 406 return; 407} 408 409#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 410static void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse) 411{ 412 InputInfoPtr pInfo = pVuidMse->pInfo; 413 ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); 414 int result; 415 416 if ((pVuidMse->absres.width != pScr->virtualX) || 417 (pVuidMse->absres.height != pScr->virtualY)) 418 { 419 pVuidMse->absres.width = pScr->virtualX; 420 pVuidMse->absres.height = pScr->virtualY; 421 422 do { 423 result = ioctl(pInfo->fd, MSIOSRESOLUTION, &(pVuidMse->absres)); 424 } while ( (result != 0) && (errno == EINTR) ); 425 426 if (result != 0) { 427 LogMessageVerbSigSafe(X_WARNING, -1, 428 "%s: couldn't set absolute mouse scaling resolution: %s\n", 429 pInfo->name, strerror(errno)); 430#ifdef DEBUG 431 } else { 432 LogMessageVerbSigSafe(X_INFO, 433 "%s: absolute mouse scaling resolution set to %d x %d\n", 434 pInfo->name, 435 pVuidMse->absres.width, 436 pVuidMse->absres.height); 437#endif 438 } 439 } 440} 441 442static void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL) 443{ 444 SCRN_INFO_PTR(arg); 445 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 446 xf86AdjustFrameProc *wrappedAdjustFrame 447 = (xf86AdjustFrameProc *) vuidMouseGetScreenPrivate(pScreen); 448 VuidMsePtr m; 449 ScreenPtr ptrCurScreen; 450 451 if (wrappedAdjustFrame) { 452 pScrn->AdjustFrame = wrappedAdjustFrame; 453 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 454 pScrn->AdjustFrame = vuidMouseAdjustFrame; 455 } 456 457 for (m = vuidMouseList; m != NULL ; m = m->next) { 458 ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 459 if (ptrCurScreen == pScreen) 460 { 461 vuidMouseSendScreenSize(pScreen, m); 462 } 463 } 464} 465 466static void vuidMouseCrtcNotify(ScreenPtr pScreen) 467{ 468 xf86_crtc_notify_proc_ptr wrappedCrtcNotify 469 = (xf86_crtc_notify_proc_ptr) vuidMouseGetScreenPrivate(pScreen); 470 VuidMsePtr m; 471 ScreenPtr ptrCurScreen; 472 473 if (wrappedCrtcNotify) 474 wrappedCrtcNotify(pScreen); 475 476 for (m = vuidMouseList; m != NULL ; m = m->next) { 477 ptrCurScreen = miPointerGetScreen(m->pInfo->dev); 478 if (ptrCurScreen == pScreen) { 479 vuidMouseSendScreenSize(pScreen, m); 480 } 481 } 482} 483#endif /* HAVE_ABSOLUTE_MOUSE_SCALING */ 484 485 486static int 487vuidMouseProc(DeviceIntPtr pPointer, int what) 488{ 489 InputInfoPtr pInfo; 490 MouseDevPtr pMse; 491 VuidMsePtr pVuidMse; 492 int ret = Success; 493 int i; 494 495 pInfo = pPointer->public.devicePrivate; 496 pMse = pInfo->private; 497 pMse->device = pPointer; 498 499 pVuidMse = getVuidMsePriv(pInfo); 500 if (pVuidMse == NULL) { 501 return BadImplementation; 502 } 503 504 switch (what) { 505 506 case DEVICE_INIT: 507#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 508 509#if HAS_DEVPRIVATEKEYREC 510 if (!dixRegisterPrivateKey(&vuidMouseScreenIndex, PRIVATE_SCREEN, 0)) 511 return BadAlloc; 512#endif /* HAS_DEVPRIVATEKEYREC */ 513 514 if (vuidMouseGeneration != serverGeneration) { 515 for (i = 0; i < screenInfo.numScreens; i++) { 516 ScreenPtr pScreen = screenInfo.screens[i]; 517 ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 518 if (xf86CrtcConfigPrivateIndex != -1) { 519 xf86_crtc_notify_proc_ptr pCrtcNotify 520 = xf86_wrap_crtc_notify(pScreen, 521 vuidMouseCrtcNotify); 522 vuidMouseSetScreenPrivate(pScreen, pCrtcNotify); 523 } else { 524 vuidMouseSetScreenPrivate(pScreen, 525 pScrn->AdjustFrame); 526 pScrn->AdjustFrame = vuidMouseAdjustFrame; 527 } 528 } 529 vuidMouseGeneration = serverGeneration; 530 } 531#endif 532 ret = pVuidMse->wrapped_device_control(pPointer, what); 533 break; 534 535 case DEVICE_ON: 536 ret = pVuidMse->wrapped_device_control(pPointer, DEVICE_ON); 537 538 if ((ret == Success) && (pInfo->fd != -1)) { 539 int fmt = VUID_FIRM_EVENT; 540 541 if (pVuidMse->strmod) { 542 /* Check to see if module is already pushed */ 543 SYSCALL(i = ioctl(pInfo->fd, I_FIND, pVuidMse->strmod)); 544 545 if (i == 0) { /* Not already pushed */ 546 SYSCALL(i = ioctl(pInfo->fd, I_PUSH, pVuidMse->strmod)); 547 if (i < 0) { 548 xf86Msg(X_WARNING, "%s: cannot push module '%s' " 549 "onto mouse device: %s\n", pInfo->name, 550 pVuidMse->strmod, strerror(errno)); 551 free(pVuidMse->strmod); 552 pVuidMse->strmod = NULL; 553 } 554 } 555 } 556 557 SYSCALL(i = ioctl(pInfo->fd, VUIDSFORMAT, &fmt)); 558 if (i < 0) { 559 xf86Msg(X_WARNING, 560 "%s: cannot set mouse device to VUID mode: %s\n", 561 pInfo->name, strerror(errno)); 562 } 563 vuidMouseWheelInit(pInfo); 564#ifdef HAVE_ABSOLUTE_MOUSE_SCALING 565 vuidMouseSendScreenSize(screenInfo.screens[0], pVuidMse); 566#endif 567 xf86FlushInput(pInfo->fd); 568 569 /* Allocate here so we don't alloc in ReadInput which may be called 570 from SIGIO handler. */ 571 if (pVuidMse->remove_timer == NULL) { 572 pVuidMse->remove_timer = TimerSet(pVuidMse->remove_timer, 573 0, 0, NULL, NULL); 574 } 575 } 576 break; 577 578 case DEVICE_OFF: 579 case DEVICE_CLOSE: 580 if (pInfo->fd != -1) { 581 if (pVuidMse->strmod) { 582 SYSCALL(i = ioctl(pInfo->fd, I_POP, pVuidMse->strmod)); 583 if (i == -1) { 584 xf86Msg(X_WARNING, 585 "%s: cannot pop module '%s' off mouse device: %s\n", 586 pInfo->name, pVuidMse->strmod, strerror(errno)); 587 } 588 } 589 } 590 if (pVuidMse->remove_timer) { 591 TimerFree(pVuidMse->remove_timer); 592 pVuidMse->remove_timer = NULL; 593 } 594 ret = pVuidMse->wrapped_device_control(pPointer, what); 595 break; 596 597 default: /* Should never be called, but just in case */ 598 ret = pVuidMse->wrapped_device_control(pPointer, what); 599 break; 600 } 601 return ret; 602} 603 604static Bool 605sunMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 606{ 607 /* The protocol is guaranteed to be one of the internalNames[] */ 608 if (xf86NameCmp(protocol, "VUID") == 0) { 609 return vuidPreInit(pInfo, protocol, flags); 610 } 611 return TRUE; 612} 613 614static const char ** 615BuiltinNames(void) 616{ 617 return internalNames; 618} 619 620static Bool 621CheckProtocol(const char *protocol) 622{ 623 int i; 624 625 for (i = 0; internalNames[i]; i++) 626 if (xf86NameCmp(protocol, internalNames[i]) == 0) 627 return TRUE; 628 629 return FALSE; 630} 631 632static const char * 633DefaultProtocol(void) 634{ 635 return "Auto"; 636} 637 638static Bool 639solarisMouseAutoProbe(InputInfoPtr pInfo, const char **protocol, 640 const char **device) 641{ 642 const char **pdev, **pproto; 643 int fd = -1; 644 Bool found; 645 char *strmod; 646 647 if (*device == NULL) { 648 /* Check to see if xorg.conf or HAL specified a device to use */ 649 *device = xf86CheckStrOption(pInfo->options, "Device", NULL); 650 } 651 652 if (*device != NULL) { 653 strmod = xf86CheckStrOption(pInfo->options, "StreamsModule", NULL); 654 if (strmod) { 655 /* if a device name is already known, and a StreamsModule is 656 specified to convert events to VUID, then we don't need to 657 probe further */ 658 *protocol = "VUID"; 659 return TRUE; 660 } 661 } 662 663 664 for (pdev = solarisMouseDevs; *pdev; pdev += 2) { 665 pproto = pdev + 1; 666 if ((*protocol != NULL) && (strcmp(*protocol, "Auto") != 0) && 667 (*pproto != NULL) && (strcmp(*pproto, *protocol) != 0)) { 668 continue; 669 } 670 if ((*device != NULL) && (strcmp(*device, *pdev) != 0)) { 671 continue; 672 } 673 SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 674 if (fd == -1) { 675#ifdef DEBUG 676 ErrorF("Cannot open %s (%s)\n", pdev, strerror(errno)); 677#endif 678 } else { 679 found = TRUE; 680 if ((*pproto != NULL) && (strcmp(*pproto, "VUID") == 0)) { 681 int i, r; 682 SYSCALL(r = ioctl(fd, VUIDGFORMAT, &i)); 683 if (r < 0) { 684 found = FALSE; 685 } 686 } 687 close(fd); 688 if (found == TRUE) { 689 if (*pproto != NULL) { 690 *protocol = *pproto; 691 } 692 *device = *pdev; 693 return TRUE; 694 } 695 } 696 } 697 return FALSE; 698} 699 700static const char * 701SetupAuto(InputInfoPtr pInfo, int *protoPara) 702{ 703 const char *pdev = NULL; 704 const char *pproto = NULL; 705 MouseDevPtr pMse = pInfo->private; 706 707 if (pInfo->fd == -1) { 708 /* probe to find device/protocol to use */ 709 if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 710 /* Set the Device option. */ 711 pInfo->options = 712 xf86AddNewOption(pInfo->options, "Device", pdev); 713 xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 714 pInfo->name, pdev); 715 } 716 } else if (pMse->protocolID == PROT_AUTO) { 717 pdev = xf86CheckStrOption(pInfo->options, 718 "Device", NULL); 719 if ((solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) && 720 (pproto != NULL)) 721 sunMousePreInit(pInfo, pproto, 0); 722 } 723 return pproto; 724} 725 726static const char * 727FindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 728{ 729 const char *pdev = NULL; 730 const char *pproto = protocol; 731 732 if (solarisMouseAutoProbe(pInfo, &pproto, &pdev) != FALSE) { 733 /* Set the Device option. */ 734 pInfo->options = 735 xf86AddNewOption(pInfo->options, "Device", pdev); 736 xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 737 pInfo->name, pdev); 738 } 739 return pdev; 740} 741 742static int 743SupportedInterfaces(void) 744{ 745 /* XXX This needs to be checked. */ 746 return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_XPS2 | MSE_MISC; 747} 748 749OSMouseInfoPtr 750OSMouseInit(int flags) 751{ 752 OSMouseInfoPtr p; 753 754 p = calloc(sizeof(OSMouseInfoRec), 1); 755 if (!p) 756 return NULL; 757 p->SupportedInterfaces = SupportedInterfaces; 758 p->BuiltinNames = BuiltinNames; 759 p->CheckProtocol = CheckProtocol; 760 p->PreInit = sunMousePreInit; 761 p->DefaultProtocol = DefaultProtocol; 762 p->SetupAuto = SetupAuto; 763 p->FindDevice = FindDevice; 764 765 return p; 766} 767 768