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