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