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