bsd_mouse.c revision f3d19aa6
1 2/* 3 * Copyright (c) 1999-2003 by The XFree86 Project, Inc. 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 shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Except as contained in this notice, the name of the copyright holder(s) 24 * and author(s) shall not be used in advertising or otherwise to promote 25 * the sale, use or other dealings in this Software without prior written 26 * authorization from the copyright holder(s) and author(s). 27 */ 28 29#include <xorg-server.h> 30 31#include <X11/X.h> 32#include "xf86.h" 33#include "xf86Priv.h" 34#include "xf86_OSlib.h" 35#include "xf86Xinput.h" 36#include "mouse.h" 37#include "xisb.h" 38#include "mipointer.h" 39#ifdef WSCONS_SUPPORT 40#include <dev/wscons/wsconsio.h> 41#endif 42#ifdef USBMOUSE_SUPPORT 43#ifdef HAS_LIB_USB_HID 44#include <usbhid.h> 45#else 46#include "usb.h" 47#endif 48 49#include <dev/usb/usb.h> 50#ifdef USB_GET_REPORT_ID 51#define USB_NEW_HID 52#endif 53 54#define HUP_GENERIC_DESKTOP 0x0001 55#define HUP_BUTTON 0x0009 56 57#define HUG_X 0x0030 58#define HUG_Y 0x0031 59#define HUG_Z 0x0032 60#define HUG_WHEEL 0x0038 61 62#define HID_USAGE2(p,u) (((p) << 16) | u) 63 64/* The UMS mices have middle button as number 3 */ 65#define UMS_BUT(i) ((i) == 0 ? 2 : (i) == 1 ? 0 : (i) == 2 ? 1 : (i)) 66#endif /* USBMOUSE_SUPPORT */ 67 68#ifdef USBMOUSE_SUPPORT 69static void usbSigioReadInput (int fd, void *closure); 70#endif 71static const char *FindDevice(InputInfoPtr, const char *, int); 72 73#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 74/* These are for FreeBSD and DragonFly */ 75#define DEFAULT_MOUSE_DEV "/dev/mouse" 76#define DEFAULT_SYSMOUSE_DEV "/dev/sysmouse" 77#define DEFAULT_PS2_DEV "/dev/psm0" 78 79static const char *mouseDevs[] = { 80 DEFAULT_MOUSE_DEV, 81 DEFAULT_SYSMOUSE_DEV, 82 DEFAULT_PS2_DEV, 83 NULL 84}; 85#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 86/* Only wsmouse mices are autoconfigured for now on OpenBSD */ 87#define DEFAULT_WSMOUSE_DEV "/dev/wsmouse" 88#define DEFAULT_WSMOUSE0_DEV "/dev/wsmouse0" 89 90static const char *mouseDevs[] = { 91 DEFAULT_WSMOUSE_DEV, 92 DEFAULT_WSMOUSE0_DEV, 93 NULL 94}; 95#endif 96 97static int 98SupportedInterfaces(void) 99{ 100#if defined(__NetBSD__) 101 return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC; 102#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 103 return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC; 104#else 105 return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC; 106#endif 107} 108 109/* Names of protocols that are handled internally here. */ 110static const char *internalNames[] = { 111#if defined(WSCONS_SUPPORT) 112 "WSMouse", 113#endif 114#if defined(USBMOUSE_SUPPORT) 115 "usb", 116#endif 117 NULL 118}; 119 120/* 121 * Names of MSC_MISC protocols that the OS supports. These are decoded by 122 * main "mouse" driver. 123 */ 124static const char *miscNames[] = { 125#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 126 "SysMouse", 127#endif 128 NULL 129}; 130 131static const char ** 132BuiltinNames(void) 133{ 134 return internalNames; 135} 136 137static Bool 138CheckProtocol(const char *protocol) 139{ 140 int i; 141 142 for (i = 0; internalNames[i]; i++) 143 if (xf86NameCmp(protocol, internalNames[i]) == 0) 144 return TRUE; 145 for (i = 0; miscNames[i]; i++) 146 if (xf86NameCmp(protocol, miscNames[i]) == 0) 147 return TRUE; 148 return FALSE; 149} 150 151static const char * 152DefaultProtocol(void) 153{ 154#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 155 return "Auto"; 156#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 157 return "WSMouse"; 158#else 159 return NULL; 160#endif 161} 162 163#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE) 164static struct { 165 int dproto; 166 const char *name; 167} devproto[] = { 168 { MOUSE_PROTO_MS, "Microsoft" }, 169 { MOUSE_PROTO_MSC, "MouseSystems" }, 170 { MOUSE_PROTO_LOGI, "Logitech" }, 171 { MOUSE_PROTO_MM, "MMSeries" }, 172 { MOUSE_PROTO_LOGIMOUSEMAN, "MouseMan" }, 173 { MOUSE_PROTO_BUS, "BusMouse" }, 174 { MOUSE_PROTO_INPORT, "BusMouse" }, 175 { MOUSE_PROTO_PS2, "PS/2" }, 176 { MOUSE_PROTO_HITTAB, "MMHitTab" }, 177 { MOUSE_PROTO_GLIDEPOINT, "GlidePoint" }, 178 { MOUSE_PROTO_INTELLI, "Intellimouse" }, 179 { MOUSE_PROTO_THINK, "ThinkingMouse" }, 180 { MOUSE_PROTO_SYSMOUSE, "SysMouse" } 181}; 182 183static const char * 184SetupAuto(InputInfoPtr pInfo, int *protoPara) 185{ 186 int i; 187 mousehw_t hw; 188 mousemode_t mode; 189 190 if (pInfo->fd == -1) 191 return NULL; 192 193 /* set the driver operation level, if applicable */ 194 i = 1; 195 ioctl(pInfo->fd, MOUSE_SETLEVEL, &i); 196 197 /* interrogate the driver and get some intelligence on the device. */ 198 hw.iftype = MOUSE_IF_UNKNOWN; 199 hw.model = MOUSE_MODEL_GENERIC; 200 ioctl(pInfo->fd, MOUSE_GETHWINFO, &hw); 201 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: hw.iftype is %d, hw.model is %d\n", 202 pInfo->name, hw.iftype, hw.model); 203 if (ioctl(pInfo->fd, MOUSE_GETMODE, &mode) == 0) { 204 for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); ++i) { 205 if (mode.protocol == devproto[i].dproto) { 206 /* override some parameters */ 207 if (protoPara) { 208 protoPara[4] = mode.packetsize; 209 protoPara[0] = mode.syncmask[0]; 210 protoPara[1] = mode.syncmask[1]; 211 } 212 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n", 213 pInfo->name, devproto[i].name); 214 return devproto[i].name; 215 } 216 } 217 } 218 return NULL; 219} 220 221static void 222SetSysMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res) 223{ 224 mousemode_t mode; 225 MouseDevPtr pMse; 226 227 pMse = pInfo->private; 228 229 mode.rate = rate > 0 ? rate : -1; 230 mode.resolution = res > 0 ? res : -1; 231 mode.accelfactor = -1; 232#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 233 if (pMse->autoProbe || 234 (protocol && xf86NameCmp(protocol, "SysMouse") == 0)) { 235 /* 236 * As the FreeBSD sysmouse driver defaults to protocol level 0 237 * everytime it is opened we enforce protocol level 1 again at 238 * this point. 239 */ 240 mode.level = 1; 241 } else 242 mode.level = -1; 243#else 244 mode.level = -1; 245#endif 246 ioctl(pInfo->fd, MOUSE_SETMODE, &mode); 247} 248#endif 249 250#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 251 252#define MOUSED_PID_FILE "/var/run/moused.pid" 253 254/* 255 * Try to check if moused is running. DEFAULT_SYSMOUSE_DEV is useless without 256 * it. There doesn't seem to be a better way of checking. 257 */ 258static Bool 259MousedRunning(void) 260{ 261 FILE *f = NULL; 262 unsigned int pid; 263 264 if ((f = fopen(MOUSED_PID_FILE, "r")) != NULL) { 265 if (fscanf(f, "%u", &pid) == 1 && pid > 0) { 266 if (kill(pid, 0) == 0) { 267 fclose(f); 268 return TRUE; 269 } 270 } 271 fclose(f); 272 } 273 return FALSE; 274} 275 276static const char * 277FindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 278{ 279 int fd = -1; 280 const char **pdev, *dev = NULL; 281 Bool devMouse = FALSE; 282 struct stat devMouseStat; 283 struct stat sb; 284 285 for (pdev = mouseDevs; *pdev; pdev++) { 286 SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK)); 287 if (fd == -1) { 288#ifdef DEBUG 289 ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno)); 290#endif 291 } else { 292 /* 293 * /dev/mouse is held until checks for matches with other devices 294 * are done. This is so that when it points to /dev/sysmouse, 295 * the test for whether /dev/sysmouse is usable can be made. 296 */ 297 if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) { 298 if (fstat(fd, &devMouseStat) == 0) 299 devMouse = TRUE; 300 close(fd); 301 continue; 302 } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) { 303 /* Check if /dev/mouse is the same as /dev/sysmouse. */ 304 if (devMouse && fstat(fd, &sb) == 0 && 305 devMouseStat.st_dev == sb.st_dev && 306 devMouseStat.st_ino == sb.st_ino) { 307 /* If the same, use /dev/sysmouse. */ 308 devMouse = FALSE; 309 } 310 close(fd); 311 if (MousedRunning()) 312 break; 313 else { 314#ifdef DEBUG 315 ErrorF("moused isn't running\n"); 316#endif 317 } 318 } else { 319 close(fd); 320 break; 321 } 322 } 323 } 324 325 if (*pdev) 326 dev = *pdev; 327 else if (devMouse) 328 dev = DEFAULT_MOUSE_DEV; 329 330 if (dev) { 331 /* Set the Device option. */ 332 pInfo->options = 333 xf86AddNewOption(pInfo->options, "Device", dev); 334 xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n", 335 pInfo->name, dev); 336 } 337 338 return *pdev; 339} 340#endif 341 342#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 343 344/* Only support wsmouse configuration for now */ 345static const char * 346SetupAuto(InputInfoPtr pInfo, int *protoPara) 347{ 348 349 xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n", 350 pInfo->name, "wsmouse"); 351 return "wsmouse"; 352} 353 354static void 355SetMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res) 356{ 357 358 xf86MsgVerb(X_INFO, 3, "%s: SetMouseRes: protocol %s rate %d res %d\n", 359 pInfo->name, protocol, rate, res); 360} 361 362static const char * 363FindDevice(InputInfoPtr pInfo, const char *protocol, int flags) 364{ 365 int fd = -1; 366 const char **pdev; 367 368 for (pdev = mouseDevs; *pdev; pdev++) { 369 SYSCALL(fd = open(*pdev, O_RDWR | O_NONBLOCK)); 370 if (fd != -1) { 371 /* Set the Device option. */ 372 pInfo->options = 373 xf86AddNewOption(pInfo->options, 374 "Device", *pdev); 375 xf86Msg(X_INFO, "%s: found Device \"%s\"\n", 376 pInfo->name, *pdev); 377 close(fd); 378 break; 379 } 380 } 381 return *pdev; 382} 383#endif /* __OpenBSD__ || __NetBSD__ && WSCONS_SUPPORT */ 384 385#ifdef WSCONS_SUPPORT 386#define NUMEVENTS 64 387 388static void 389wsconsReadInput(InputInfoPtr pInfo) 390{ 391 MouseDevPtr pMse; 392 static struct wscons_event eventList[NUMEVENTS]; 393 int n, c; 394 struct wscons_event *event = eventList; 395 unsigned char *pBuf; 396 397 pMse = pInfo->private; 398 399 XisbBlockDuration(pMse->buffer, -1); 400 pBuf = (unsigned char *)eventList; 401 n = 0; 402 while (n < sizeof(eventList) && (c = XisbRead(pMse->buffer)) >= 0) { 403 pBuf[n++] = (unsigned char)c; 404 } 405 406 if (n == 0) 407 return; 408 409 n /= sizeof(struct wscons_event); 410 while( n-- ) { 411 int buttons = pMse->lastButtons; 412 int dx = 0, dy = 0, dz = 0, dw = 0, x, y; 413 switch (event->type) { 414 case WSCONS_EVENT_MOUSE_UP: 415#define BUTBIT (1 << (event->value <= 2 ? 2 - event->value : event->value)) 416 buttons &= ~BUTBIT; 417 break; 418 case WSCONS_EVENT_MOUSE_DOWN: 419 buttons |= BUTBIT; 420 break; 421 case WSCONS_EVENT_MOUSE_DELTA_X: 422 dx = event->value; 423 break; 424 case WSCONS_EVENT_MOUSE_DELTA_Y: 425 dy = -event->value; 426 break; 427#ifdef WSCONS_EVENT_MOUSE_DELTA_Z 428 case WSCONS_EVENT_MOUSE_DELTA_Z: 429 dz = event->value; 430 break; 431#endif 432#ifdef WSCONS_EVENT_MOUSE_DELTA_W 433 case WSCONS_EVENT_MOUSE_DELTA_W: 434 dw = event->value; 435 break; 436#endif 437 case WSCONS_EVENT_MOUSE_ABSOLUTE_X: 438 miPointerGetPosition (pInfo->dev, &x, &y); 439 x = event->value; 440 miPointerSetPosition (pInfo->dev, &x, &y); 441 xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, x, y); 442 ++event; 443 continue; 444 case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: 445 miPointerGetPosition (pInfo->dev, &x, &y); 446 y = event->value; 447 miPointerSetPosition (pInfo->dev, &x, &y); 448 xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, x, y); 449 ++event; 450 continue; 451#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_Z 452 case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: 453 ++event; 454 continue; 455#endif 456#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_W 457 case WSCONS_EVENT_MOUSE_ABSOLUTE_W: 458 ++event; 459 continue; 460#endif 461 default: 462 xf86Msg(X_WARNING, "%s: bad wsmouse event type=%d\n", pInfo->name, 463 event->type); 464 ++event; 465 continue; 466 } 467 468 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 469 ++event; 470 } 471 return; 472} 473 474 475/* This function is called when the protocol is "wsmouse". */ 476static Bool 477wsconsPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 478{ 479 MouseDevPtr pMse = pInfo->private; 480 481 /* Setup the local input proc. */ 482 pInfo->read_input = wsconsReadInput; 483 pMse->xisbscale = sizeof(struct wscons_event); 484 485#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 486 pInfo->flags |= XI86_CONFIGURED; 487#endif 488 return TRUE; 489} 490#endif 491 492#if defined(USBMOUSE_SUPPORT) 493 494typedef struct _UsbMseRec { 495 int packetSize; 496 int iid; 497 hid_item_t loc_x; /* x locator item */ 498 hid_item_t loc_y; /* y locator item */ 499 hid_item_t loc_z; /* z (wheel) locator item */ 500 hid_item_t loc_w; /* z (wheel) locator item */ 501 hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */ 502 unsigned char *buffer; 503} UsbMseRec, *UsbMsePtr; 504 505static int 506usbMouseProc(DeviceIntPtr pPointer, int what) 507{ 508 InputInfoPtr pInfo; 509 MouseDevPtr pMse; 510 UsbMsePtr pUsbMse; 511 unsigned char map[MSE_MAXBUTTONS + 1]; 512 int nbuttons; 513 514 pInfo = pPointer->public.devicePrivate; 515 pMse = pInfo->private; 516 pMse->device = pPointer; 517 pUsbMse = pMse->mousePriv; 518 519 switch (what) { 520 case DEVICE_INIT: 521 pPointer->public.on = FALSE; 522 523 for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons) 524 map[nbuttons + 1] = nbuttons + 1; 525 526 InitPointerDeviceStruct((DevicePtr)pPointer, 527 map, 528 min(pMse->buttons, MSE_MAXBUTTONS), 529 miPointerGetMotionEvents, 530 pMse->Ctrl, 531 miPointerGetMotionBufferSize()); 532 533 /* X valuator */ 534 xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1); 535 xf86InitValuatorDefaults(pPointer, 0); 536 /* Y valuator */ 537 xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1); 538 xf86InitValuatorDefaults(pPointer, 1); 539 xf86MotionHistoryAllocate(pInfo); 540 break; 541 542 case DEVICE_ON: 543 pInfo->fd = xf86OpenSerial(pInfo->options); 544 if (pInfo->fd == -1) 545 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 546 else { 547 pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize); 548 if (!pMse->buffer) { 549 free(pMse); 550 xf86CloseSerial(pInfo->fd); 551 pInfo->fd = -1; 552 } else { 553 xf86FlushInput(pInfo->fd); 554 if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput, 555 pInfo)) 556 AddEnabledDevice(pInfo->fd); 557 } 558 } 559 pMse->lastButtons = 0; 560 pMse->lastMappedButtons = 0; 561 pMse->emulateState = 0; 562 pPointer->public.on = TRUE; 563 break; 564 565 case DEVICE_OFF: 566 case DEVICE_CLOSE: 567 if (pInfo->fd != -1) { 568 RemoveEnabledDevice(pInfo->fd); 569 if (pUsbMse->packetSize > 8 && pUsbMse->buffer) { 570 free(pUsbMse->buffer); 571 } 572 if (pMse->buffer) { 573 XisbFree(pMse->buffer); 574 pMse->buffer = NULL; 575 } 576 xf86CloseSerial(pInfo->fd); 577 pInfo->fd = -1; 578 } 579 pPointer->public.on = FALSE; 580 usleep(300000); 581 break; 582 } 583 return Success; 584} 585 586static void 587usbReadInput(InputInfoPtr pInfo) 588{ 589 MouseDevPtr pMse; 590 UsbMsePtr pUsbMse; 591 int buttons = pMse->lastButtons; 592 int dx = 0, dy = 0, dz = 0, dw = 0; 593 int n, c; 594 unsigned char *pBuf; 595 596 pMse = pInfo->private; 597 pUsbMse = pMse->mousePriv; 598 599 XisbBlockDuration(pMse->buffer, -1); 600 pBuf = pUsbMse->buffer; 601 n = 0; 602 while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) { 603 pBuf[n++] = (unsigned char)c; 604 } 605 if (n == 0) 606 return; 607 if (n != pUsbMse->packetSize) { 608 xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", pInfo->name, 609 n); 610 } 611 /* discard packets with an id that don't match the mouse */ 612 /* XXX this is probably not the right thing */ 613 if (pUsbMse->iid != 0) { 614 if (*pBuf++ != pUsbMse->iid) 615 return; 616 } 617 dx = hid_get_data(pBuf, &pUsbMse->loc_x); 618 dy = hid_get_data(pBuf, &pUsbMse->loc_y); 619 dz = hid_get_data(pBuf, &pUsbMse->loc_z); 620 dw = hid_get_data(pBuf, &pUsbMse->loc_w); 621 622 buttons = 0; 623 for (n = 0; n < pMse->buttons; n++) { 624 if (hid_get_data(pBuf, &pUsbMse->loc_btn[n])) 625 buttons |= (1 << UMS_BUT(n)); 626 } 627 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 628 return; 629} 630 631static void 632usbSigioReadInput (int fd, void *closure) 633{ 634 usbReadInput ((InputInfoPtr) closure); 635} 636 637/* This function is called when the protocol is "usb". */ 638static Bool 639usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags) 640{ 641 MouseDevPtr pMse = pInfo->private; 642 UsbMsePtr pUsbMse; 643 report_desc_t reportDesc; 644 int i; 645 646 pUsbMse = malloc(sizeof(UsbMseRec)); 647 if (pUsbMse == NULL) { 648 xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name); 649 free(pMse); 650 return FALSE; 651 } 652 653 pMse->protocol = protocol; 654 xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol); 655 656 /* Collect the options, and process the common options. */ 657 COLLECT_INPUT_OPTIONS(pInfo, NULL); 658 xf86ProcessCommonOptions(pInfo, pInfo->options); 659 660 /* Check if the device can be opened. */ 661 pInfo->fd = xf86OpenSerial(pInfo->options); 662 if (pInfo->fd == -1) { 663 if (xf86GetAllowMouseOpenFail()) 664 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 665 else { 666 xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); 667 free(pUsbMse); 668 free(pMse); 669 return FALSE; 670 } 671 } 672 /* Get USB informations */ 673 reportDesc = hid_get_report_desc(pInfo->fd); 674 /* Get packet size & iid */ 675#ifdef USB_NEW_HID 676 if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) { 677 xf86Msg(X_ERROR, "Error ioctl USB_GET_REPORT_ID on %s : %s\n", 678 pInfo->name, strerror(errno)); 679 return FALSE; 680 } 681 pUsbMse->packetSize = hid_report_size(reportDesc, hid_input, 682 pUsbMse->iid); 683#else 684 pUsbMse->packetSize = hid_report_size(reportDesc, hid_input, 685 &pUsbMse->iid); 686#endif 687 /* Allocate buffer */ 688 if (pUsbMse->packetSize <= 8) { 689 pUsbMse->buffer = pMse->protoBuf; 690 } else { 691 pUsbMse->buffer = malloc(pUsbMse->packetSize); 692 } 693 if (pUsbMse->buffer == NULL) { 694 xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name); 695 free(pUsbMse); 696 free(pMse); 697 xf86CloseSerial(pInfo->fd); 698 return FALSE; 699 } 700#ifdef USB_NEW_HID 701 if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 702 hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) { 703 xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name); 704 } 705 if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 706 hid_input, &pUsbMse->loc_y, pUsbMse->iid) < 0) { 707 xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name); 708 } 709 if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), 710 hid_input, &pUsbMse->loc_z, pUsbMse->iid) < 0) { 711 } 712#else 713 if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 714 hid_input, &pUsbMse->loc_x) < 0) { 715 xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name); 716 } 717 if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), 718 hid_input, &pUsbMse->loc_y) < 0) { 719 xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name); 720 } 721 if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), 722 hid_input, &pUsbMse->loc_z) < 0) { 723 } 724#endif 725 /* Probe for number of buttons */ 726 for (i = 1; i <= MSE_MAXBUTTONS; i++) { 727 if (!hid_locate(reportDesc, HID_USAGE2(HUP_BUTTON, i), 728 hid_input, &pUsbMse->loc_btn[i-1] 729#ifdef USB_NEW_HID 730 , pUsbMse->iid 731#endif 732 )) 733 break; 734 } 735 pMse->buttons = i-1; 736 737 xf86CloseSerial(pInfo->fd); 738 pInfo->fd = -1; 739 740 /* Private structure */ 741 pMse->mousePriv = pUsbMse; 742 743 /* Process common mouse options (like Emulate3Buttons, etc). */ 744 pMse->CommonOptions(pInfo); 745 746 /* Setup the local procs. */ 747 pInfo->device_control = usbMouseProc; 748 pInfo->read_input = usbReadInput; 749 750#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 751 pInfo->flags |= XI86_CONFIGURED; 752#endif 753 return TRUE; 754} 755#endif /* USBMOUSE */ 756 757static Bool 758bsdMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags) 759{ 760 /* The protocol is guaranteed to be one of the internalNames[] */ 761#ifdef WSCONS_SUPPORT 762 if (xf86NameCmp(protocol, "WSMouse") == 0) { 763 return wsconsPreInit(pInfo, protocol, flags); 764 } 765#endif 766#ifdef USBMOUSE_SUPPORT 767 if (xf86NameCmp(protocol, "usb") == 0) { 768 return usbPreInit(pInfo, protocol, flags); 769 } 770#endif 771 return TRUE; 772} 773 774OSMouseInfoPtr 775OSMouseInit(int flags) 776{ 777 OSMouseInfoPtr p; 778 779 p = calloc(sizeof(OSMouseInfoRec), 1); 780 if (!p) 781 return NULL; 782 p->SupportedInterfaces = SupportedInterfaces; 783 p->BuiltinNames = BuiltinNames; 784 p->DefaultProtocol = DefaultProtocol; 785 p->CheckProtocol = CheckProtocol; 786#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE) 787 p->SetupAuto = SetupAuto; 788 p->SetPS2Res = SetSysMouseRes; 789 p->SetBMRes = SetSysMouseRes; 790 p->SetMiscRes = SetSysMouseRes; 791#endif 792#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT) 793 p->SetupAuto = SetupAuto; 794 p->SetMiscRes = SetMouseRes; 795#endif 796#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__) 797 p->FindDevice = FindDevice; 798#endif 799 p->PreInit = bsdMousePreInit; 800 return p; 801} 802