vmmouse.c revision 9418810d
1/* 2 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 3 * Copyright 1993 by David Dawes <dawes@xfree86.org> 4 * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich 5 * Copyright 1994-2002 by The XFree86 Project, Inc. 6 * Copyright 2002 by Paul Elliott 7 * Copyright 2002-2006 by VMware, Inc. 8 * 9 * Permission to use, copy, modify, distribute, and sell this software and its 10 * documentation for any purpose is hereby granted without fee, provided that 11 * the above copyright notice appear in all copies and that both that 12 * copyright notice and this permission notice appear in supporting 13 * documentation, and that the names of copyright holders not be 14 * used in advertising or publicity pertaining to distribution of the 15 * software without specific, written prior permission. The copyright holders 16 * make no representations about the suitability of this 17 * software for any purpose. It is provided "as is" without express or 18 * implied warranty. 19 * 20 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 21 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 22 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 24 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 25 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27 * 28 */ 29 30/* 31 * vmmouse.c -- 32 * 33 * This is a modified version of the mouse input driver 34 * provided in Xserver/hw/xfree86/input/mouse/mouse.c 35 * 36 * Although all data is read using the vmmouse protocol, notification 37 * is still done through the PS/2 port, so all the basic code for 38 * interacting with the port is retained. 39 * 40 */ 41 42 43/***************************************************************************** 44 * Standard Headers 45 ****************************************************************************/ 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50#include <stdio.h> 51#define NEED_EVENTS 52#include <X11/X.h> 53#include <X11/Xproto.h> 54 55#include "xf86.h" 56 57#ifdef XINPUT 58#include <X11/extensions/XI.h> 59#include <X11/extensions/XIproto.h> 60#include "extnsionst.h" 61#include "extinit.h" 62#else 63#include "inputstr.h" 64#endif 65 66#include "xf86Xinput.h" 67#include "xf86_OSproc.h" 68#include "xf86OSmouse.h" 69#include "compiler.h" 70 71#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 72#include <xserver-properties.h> 73#endif 74 75#include "xisb.h" 76#include "mipointer.h" 77 78/***************************************************************************** 79 * Local Headers 80 ****************************************************************************/ 81#include "vmmouse_client.h" 82 83/* 84 * This is the only way I know to turn a #define of an integer constant into 85 * a constant string. 86 */ 87#define VMW_INNERSTRINGIFY(s) #s 88#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) 89 90/* 91 * So that the file compiles unmodified when dropped into an xfree source tree. 92 */ 93#ifndef XORG_VERSION_CURRENT 94#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT 95#endif 96 97/* 98 * Version constants 99 */ 100#define VMMOUSE_DRIVER_VERSION \ 101 (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) 102#define VMMOUSE_DRIVER_VERSION_STRING \ 103 VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ 104 "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) 105 106/* 107 * Standard four digit version string expected by VMware Tools installer. 108 * As the driver's version is only {major, minor, patchlevel}, simply append an 109 * extra zero for the fourth digit. 110 */ 111#ifdef __GNUC__ 112const char vm_mouse_version[] __attribute__((section(".modinfo"),unused)) = 113 "version=" VMMOUSE_DRIVER_VERSION_STRING ".0"; 114#endif 115 116 117/***************************************************************************** 118 * static function header 119 ****************************************************************************/ 120static InputInfoPtr VMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags); 121static void VMMouseUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags); 122static void MouseCommonOptions(InputInfoPtr pInfo); 123static void GetVMMouseMotionEvent(InputInfoPtr pInfo); 124static void VMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw); 125static void VMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy); 126static Bool VMMouseDeviceControl(DeviceIntPtr device, int mode); 127static void VMMouseCloseProc(LocalDevicePtr local); 128static int VMMouseControlProc(LocalDevicePtr local, xDeviceCtl * control); 129static void VMMouseReadInput(InputInfoPtr pInfo); 130static int VMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode); 131static Bool VMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, 132 int v3, int v4, int v5, int *x, int *y); 133static void MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl); 134 135/****************************************************************************** 136 * Definitions 137 *****************************************************************************/ 138typedef struct { 139 int screenNum; 140 Bool vmmouseAvailable; 141 VMMOUSE_INPUT_DATA vmmousePrevInput; 142 Bool isCurrRelative; 143 Bool absoluteRequested; 144} VMMousePrivRec, *VMMousePrivPtr; 145 146#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7 147static const char *reqSymbols[] = { 148 "InitPointerDeviceStruct", 149 "LoaderSymbol", 150 "LoadSubModule", 151 "miPointerGetMotionBufferSize", 152 "miPointerGetMotionEvents", 153 "screenInfo", 154 "Xcalloc", 155 "xf86AddEnabledDevice", 156 "xf86AddInputDriver", 157 "xf86AddModuleInfo", 158 "xf86AllocateInput", 159 "xf86BlockSIGIO", 160 "xf86CloseSerial", 161 "xf86CollectInputOptions", 162 "xf86ffs", 163 "xf86FlushInput", 164 "xf86GetAllowMouseOpenFail", 165 "xf86GetMotionEvents", 166 "xf86InitValuatorAxisStruct", 167 "xf86InitValuatorDefaults", 168 "xf86LoaderCheckSymbol", 169 "xf86MotionHistoryAllocate", 170 "xf86Msg", 171 "xf86NameCmp", 172 "xf86OpenSerial", 173 "xf86OSMouseInit", 174 "xf86PostButtonEvent", 175 "xf86PostMotionEvent", 176 "xf86ProcessCommonOptions", 177 "xf86RemoveEnabledDevice", 178 "xf86SetIntOption", 179 "xf86SetStrOption", 180 "xf86sprintf", 181 "xf86sscanf", 182 "xf86UnblockSIGIO", 183 "xf86usleep", 184 "xf86XInputSetScreen", 185 "Xfree", 186 "XisbBlockDuration", 187 "XisbFree", 188 "XisbNew", 189 "XisbRead", 190 "Xstrdup", 191 NULL 192}; 193#endif 194 195InputDriverRec VMMOUSE = { 196 1, 197 "vmmouse", 198 NULL, 199 VMMousePreInit, 200 VMMouseUnInit, 201 NULL, 202 0 203}; 204 205static char reverseMap[32] = { 0, 4, 2, 6, 1, 5, 3, 7, 206 8, 12, 10, 14, 9, 13, 11, 15, 207 16, 20, 18, 22, 17, 21, 19, 23, 208 24, 28, 26, 30, 25, 29, 27, 31}; 209 210#define reverseBits(map, b) (((b) & ~0x0f) | map[(b) & 0x0f]) 211 212 213/* 214 *---------------------------------------------------------------------- 215 * 216 * VMMousePreInit -- 217 * This function collect all the information that is necessary to 218 * determine the configuration of the hardware and to prepare the 219 * device for being used 220 * 221 * Results: 222 * An InputInfoPtr object which points to vmmouse's information, 223 * if the absolute pointing device available 224 * Otherwise, an InputInfoPtr of regular mouse 225 * 226 * Side effects: 227 * VMMouse was initialized with necessary information 228 * 229 *---------------------------------------------------------------------- 230 */ 231 232static InputInfoPtr 233VMMousePreInit(InputDriverPtr drv, IDevPtr dev, int flags) 234{ 235 InputInfoPtr pInfo; 236 MouseDevPtr pMse; 237 VMMousePrivPtr mPriv; 238 239#ifndef NO_MOUSE_MODULE 240{ 241 OSMouseInfoPtr osInfo = NULL; 242 243 /* 244 * let Xserver init the mouse first 245 */ 246 osInfo = xf86OSMouseInit(0); 247 if (!osInfo) 248 return FALSE; 249} 250#endif 251 252 mPriv = xcalloc (1, sizeof (VMMousePrivRec)); 253 254 255 if (!mPriv) { 256 return NULL; 257 } 258 259 mPriv->absoluteRequested = FALSE; 260 261 /* 262 * try to enable vmmouse here 263 */ 264 if (!VMMouseClient_Enable()) { 265 /* 266 * vmmouse failed 267 * Fall back to normal mouse module 268 */ 269 InputDriverRec *passthruMouse; 270 xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n"); 271 mPriv->vmmouseAvailable = FALSE; 272 passthruMouse = (InputDriverRec *)LoaderSymbol("MOUSE"); 273 xfree(mPriv); 274 if(passthruMouse != NULL){ 275 return (passthruMouse->PreInit)(drv, dev, flags); 276 } else { 277 return NULL; 278 } 279 280 } else { 281 /* 282 * vmmouse is available 283 */ 284 mPriv->vmmouseAvailable = TRUE; 285 xf86Msg(X_INFO, "VMWARE(0): vmmouse is available\n"); 286 /* 287 * Disable the absolute pointing device for now 288 * It will be enabled during DEVICE_ON phase 289 */ 290 VMMouseClient_Disable(); 291 } 292 293 if (!(pInfo = xf86AllocateInput(drv, 0))) { 294 xfree(mPriv); 295 return NULL; 296 } 297 298 /* Settup the pInfo */ 299 pInfo->name = dev->identifier; 300 pInfo->type_name = XI_MOUSE; 301 pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; 302 pInfo->device_control = VMMouseDeviceControl; 303 pInfo->read_input = VMMouseReadInput; 304#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 305 pInfo->motion_history_proc = xf86GetMotionEvents; 306#endif 307 pInfo->control_proc = VMMouseControlProc; 308 pInfo->close_proc = VMMouseCloseProc; 309 pInfo->switch_mode = VMMouseSwitchMode; 310 pInfo->conversion_proc = VMMouseConvertProc; 311 pInfo->reverse_conversion_proc = NULL; 312 pInfo->fd = -1; 313 pInfo->dev = NULL; 314 pInfo->private_flags = 0; 315 pInfo->always_core_feedback = 0; 316 pInfo->conf_idev = dev; 317 318 /* Allocate the MouseDevRec and initialise it. */ 319 if (!(pMse = xcalloc(sizeof(MouseDevRec), 1))) { 320 xfree(mPriv); 321 return pInfo; 322 } 323 324 pInfo->private = pMse; 325 pMse->Ctrl = MouseCtrl; 326 pMse->PostEvent = VMMousePostEvent; 327 pMse->CommonOptions = MouseCommonOptions; 328 pMse->mousePriv = mPriv; 329 330 331 /* Collect the options, and process the common options. */ 332 xf86CollectInputOptions(pInfo, NULL, NULL); 333 xf86ProcessCommonOptions(pInfo, pInfo->options); 334 335 /* Check if the device can be opened. */ 336 pInfo->fd = xf86OpenSerial(pInfo->options); 337 if (pInfo->fd == -1) { 338 if (xf86GetAllowMouseOpenFail()) 339 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 340 else { 341 xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); 342 if (pMse->mousePriv) 343 xfree(pMse->mousePriv); 344 xfree(pMse); 345 pInfo->private = NULL; 346 return pInfo; 347 } 348 } 349 xf86CloseSerial(pInfo->fd); 350 pInfo->fd = -1; 351 352 /* Process the options */ 353 pMse->CommonOptions(pInfo); 354 355 /* set up the current screen num */ 356 mPriv->screenNum = xf86SetIntOption(pInfo->options, "ScreenNumber", 0); 357 358 pInfo->flags |= XI86_CONFIGURED; 359 return pInfo; 360} 361 362 363/* 364 *---------------------------------------------------------------------- 365 * 366 * MouseCtrl -- 367 * Alter the control paramters for the mouse. 368 * 369 * Results: 370 * None 371 * 372 * Side effects: 373 * None 374 * 375 *---------------------------------------------------------------------- 376 */ 377 378static void 379MouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl) 380{ 381 InputInfoPtr pInfo; 382 MouseDevPtr pMse; 383 384 pInfo = device->public.devicePrivate; 385 pMse = pInfo->private; 386 387#ifdef EXTMOUSEDEBUG 388 xf86Msg(X_INFO, "VMMOUSE(0): MouseCtrl pMse=%p\n", pMse); 389#endif 390 391 pMse->num = ctrl->num; 392 pMse->den = ctrl->den; 393 pMse->threshold = ctrl->threshold; 394} 395 396 397/* 398 *---------------------------------------------------------------------- 399 * 400 * VMMouseDoPostEvent -- 401 * Post the mouse button event and mouse motion event to Xserver 402 * 403 * Results: 404 * None 405 * 406 * Side effects: 407 * Mouse location and button status was updated 408 * 409 *---------------------------------------------------------------------- 410 */ 411 412static void 413VMMouseDoPostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy) 414{ 415 MouseDevPtr pMse; 416 VMMousePrivPtr mPriv; 417 int truebuttons; 418 int id, change; 419 Bool mouseMoved = FALSE; 420 421 pMse = pInfo->private; 422 mPriv = (VMMousePrivPtr)pMse->mousePriv; 423 424 /* 425 * The following truebuttons/reverseBits and lastButtons are 426 * used to compare the current buttons and the previous buttons 427 * to find the button changes during two mouse events 428 */ 429 truebuttons = buttons; 430 431 buttons = reverseBits(reverseMap, buttons); 432 433 if (mPriv->isCurrRelative) { 434 mouseMoved = dx || dy; 435 } else { 436 mouseMoved = (dx != mPriv->vmmousePrevInput.X) || 437 (dy != mPriv->vmmousePrevInput.Y) || 438 (mPriv->vmmousePrevInput.Flags & VMMOUSE_MOVE_RELATIVE); 439 } 440 if (mouseMoved) { 441 442#ifdef CALL_CONVERSION_PROC 443 /* 444 * Xservers between 1.3.99.0 - 1.4.0.90 do not call conversion_proc, so 445 * we need to do the conversion from device to screen space. 446 */ 447 VMMouseConvertProc(pInfo, 0, 2, dx, dy, 0, 0, 0, 0, &dx, &dy); 448#endif 449 xf86PostMotionEvent(pInfo->dev, !mPriv->isCurrRelative, 0, 2, dx, dy); 450 } 451 452 if (truebuttons != pMse->lastButtons) { 453 change = buttons ^ reverseBits(reverseMap, pMse->lastButtons); 454 while (change) { 455 id = ffs(change); 456 change &= ~(1 << (id - 1)); 457 xf86PostButtonEvent(pInfo->dev, 0, id, 458 (buttons & (1 << (id - 1))), 0, 0); 459 } 460 pMse->lastButtons = truebuttons; 461 } 462} 463 464 465/* 466 *---------------------------------------------------------------------- 467 * 468 * VMMousePostEvent -- 469 * Prepare the mouse status according to the Z axis mapping 470 * before we post the event to Xserver 471 * 472 * Results: 473 * None 474 * 475 * Side effects: 476 * Buttons was updated according to Z axis mapping 477 * 478 *---------------------------------------------------------------------- 479 */ 480 481static void 482VMMousePostEvent(InputInfoPtr pInfo, int buttons, int dx, int dy, int dz, int dw) 483{ 484 MouseDevPtr pMse; 485 int zbutton = 0; 486 VMMousePrivPtr mPriv; 487 488 pMse = pInfo->private; 489 mPriv = (VMMousePrivPtr)pMse->mousePriv; 490 /* Map the Z axis movement. */ 491 /* XXX Could this go in the conversion_proc? */ 492 switch (pMse->negativeZ) { 493 case MSE_NOZMAP: /* do nothing */ 494 break; 495 case MSE_MAPTOX: 496 if (dz != 0) { 497 if(mPriv->isCurrRelative) 498 dx = dz; 499 else 500 dx += dz; 501 dz = 0; 502 } 503 break; 504 case MSE_MAPTOY: 505 if (dz != 0) { 506 if(mPriv->isCurrRelative) 507 dy = dz; 508 else 509 dy += dz; 510 dz = 0; 511 } 512 break; 513 default: /* buttons */ 514 buttons &= ~(pMse->negativeZ | pMse->positiveZ 515 | pMse->negativeW | pMse->positiveW); 516 if (dw < 0 || dz < -1) { 517 zbutton = pMse->negativeW; 518 } 519 else if (dz < 0) { 520 zbutton = pMse->negativeZ; 521 } 522 else if (dw > 0 || dz > 1) { 523 zbutton = pMse->positiveW; 524 } 525 else if (dz > 0) { 526 zbutton = pMse->positiveZ; 527 } 528 buttons |= zbutton; 529 dz = 0; 530 break; 531 } 532 533 VMMouseDoPostEvent(pInfo, buttons, dx, dy); 534 535 /* 536 * If dz has been mapped to a button `down' event, we need to cook up 537 * a corresponding button `up' event. 538 */ 539 if (zbutton) { 540 buttons &= ~zbutton; 541 if(mPriv->isCurrRelative) 542 VMMouseDoPostEvent(pInfo, buttons, 0, 0); 543 else 544 VMMouseDoPostEvent(pInfo, buttons, dx, dy); 545 } 546} 547 548 549/* 550 *---------------------------------------------------------------------- 551 * 552 * FlushButtons -- 553 * 554 * FlushButtons -- reset button states. 555 * 556 * Results: 557 * None 558 * 559 * Side effects: 560 * None 561 * 562 *---------------------------------------------------------------------- 563 */ 564 565static void 566FlushButtons(MouseDevPtr pMse) 567{ 568 pMse->lastButtons = 0; 569} 570 571 572/* 573 *---------------------------------------------------------------------- 574 * 575 * MouseCommonOptions -- 576 * Process acceptable mouse options. Currently we only process 577 * "Buttons" and "ZAxisMapping" options. 578 * More options can be added later on 579 * 580 * Results: 581 * None 582 * 583 * Side effects: 584 * The buttons was setup according to the options 585 * 586 *---------------------------------------------------------------------- 587 */ 588 589static void 590MouseCommonOptions(InputInfoPtr pInfo) 591{ 592 MouseDevPtr pMse; 593 MessageType from = X_DEFAULT; 594 char *s; 595 int origButtons; 596 597 pMse = pInfo->private; 598 599 pMse->buttons = xf86SetIntOption(pInfo->options, "Buttons", 0); 600 from = X_CONFIG; 601 if (!pMse->buttons) { 602 pMse->buttons = MSE_DFLTBUTTONS; 603 from = X_DEFAULT; 604 } 605 origButtons = pMse->buttons; 606 607 /* 608 * "emulate3Buttons" and "Drag Lock" is not supported 609 */ 610 611 /* 612 * Process option for ZAxisMapping 613 */ 614 s = xf86SetStrOption(pInfo->options, "ZAxisMapping", "4 5"); 615 if (s) { 616 int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 617 char *msg = NULL; 618 619 if (!xf86NameCmp(s, "x")) { 620 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOX; 621 pMse->negativeW = pMse->positiveW = MSE_MAPTOX; 622 msg = xstrdup("X axis"); 623 } else if (!xf86NameCmp(s, "y")) { 624 pMse->negativeZ = pMse->positiveZ = MSE_MAPTOY; 625 pMse->negativeW = pMse->positiveW = MSE_MAPTOY; 626 msg = xstrdup("Y axis"); 627 } else if (sscanf(s, "%d %d %d %d", &b1, &b2, &b3, &b4) >= 2 && 628 b1 > 0 && b1 <= MSE_MAXBUTTONS && 629 b2 > 0 && b2 <= MSE_MAXBUTTONS) { 630 msg = xstrdup("buttons XX and YY"); 631 if (msg) 632 sprintf(msg, "buttons %d and %d", b1, b2); 633 pMse->negativeZ = pMse->negativeW = 1 << (b1-1); 634 pMse->positiveZ = pMse->positiveW = 1 << (b2-1); 635 if (b1 > pMse->buttons) pMse->buttons = b1; 636 if (b2 > pMse->buttons) pMse->buttons = b2; 637 638 /* 639 * Option "ZAxisMapping" "N1 N2 N3 N4" not supported 640 */ 641 pMse->negativeW = pMse->positiveW = MSE_NOZMAP; 642 } else { 643 pMse->negativeZ = pMse->positiveZ = MSE_NOZMAP; 644 pMse->negativeW = pMse->positiveW = MSE_NOZMAP; 645 } 646 if (msg) { 647 xf86Msg(X_CONFIG, "%s: ZAxisMapping: %s\n", pInfo->name, msg); 648 xfree(msg); 649 } else { 650 xf86Msg(X_WARNING, "%s: Invalid ZAxisMapping value: \"%s\"\n", 651 pInfo->name, s); 652 } 653 } 654 655 /* 656 * Emulatewheel is not supported 657 */ 658 if (origButtons != pMse->buttons) 659 from = X_CONFIG; 660 661} 662 663 664/* 665 *---------------------------------------------------------------------- 666 * 667 * VMMouseUnInit -- 668 * This function was supposed to be called by Xserver to do Un-Init. 669 * But it was unused now 670 * 671 * Results: 672 * None 673 * 674 * Side effects: 675 * None 676 * 677 *---------------------------------------------------------------------- 678 */ 679 680static void 681VMMouseUnInit(InputDriverPtr drv, LocalDevicePtr local, int flags) 682{ 683 xf86Msg(X_INFO, "VMWARE(0): VMMouseUnInit\n"); 684} 685 686 687/* 688 *---------------------------------------------------------------------- 689 * 690 * VMMouseDeviceControl -- 691 * This function was called by Xserver during DEVICE_INIT, DEVICE_ON, 692 * DEVICE_OFF and DEVICE_CLOSE phase 693 * 694 * Results: 695 * TRUE, if sucessful 696 * FALSE, if failed 697 * 698 * Side effects: 699 * Absolute pointing device is enabled during DEVICE_ON 700 * Absolute pointing device is disabled during DEVICE_OFF 701 * and DEVICE_CLOSE 702 * 703 *---------------------------------------------------------------------- 704 */ 705 706static Bool 707VMMouseDeviceControl(DeviceIntPtr device, int mode) 708{ 709 InputInfoPtr pInfo; 710 MouseDevPtr pMse; 711 VMMousePrivPtr mPriv; 712 unsigned char map[MSE_MAXBUTTONS + 1]; 713 int i; 714#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 715 Atom btn_labels[MSE_MAXBUTTONS] = {0}; 716 Atom axes_labels[2] = { 0, 0 }; 717#endif 718 719 pInfo = device->public.devicePrivate; 720 pMse = pInfo->private; 721 pMse->device = device; 722 mPriv = (VMMousePrivPtr)pMse->mousePriv; 723 724 switch (mode){ 725 case DEVICE_INIT: 726 device->public.on = FALSE; 727 /* 728 * [KAZU-241097] We don't know exactly how many buttons the 729 * device has, so setup the map with the maximum number. 730 */ 731 for (i = 0; i < MSE_MAXBUTTONS; i++) 732 map[i + 1] = i + 1; 733#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 734 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 735 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 736 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 737 btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 738 btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 739 btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 740 btn_labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 741 /* other buttons are unknown */ 742 743#ifdef ABS_VALUATOR_AXES 744 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); 745 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); 746#else 747 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 748 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 749#endif /* ABS_VALUATOR_AXES */ 750#endif 751 752 InitPointerDeviceStruct((DevicePtr)device, map, 753 min(pMse->buttons, MSE_MAXBUTTONS), 754#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 755 btn_labels, 756#endif 757#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 758 miPointerGetMotionEvents, 759#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3 760 GetMotionHistory, 761#endif 762 pMse->Ctrl, 763#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 764 miPointerGetMotionBufferSize() 765#else 766 GetMotionHistorySize(), 2 767#endif 768#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 769 , axes_labels 770#endif 771 ); 772 773 /* X valuator */ 774#ifdef ABS_VALUATOR_AXES 775 xf86InitValuatorAxisStruct(device, 0, 776#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 777 axes_labels[0], 778#endif 779 0, 65535, 10000, 0, 10000); 780#else 781 xf86InitValuatorAxisStruct(device, 0, 782#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 783 axes_labels[0], 784#endif 785 0, -1, 1, 0, 1); 786#endif 787 xf86InitValuatorDefaults(device, 0); 788 /* Y valuator */ 789#ifdef ABS_VALUATOR_AXES 790 xf86InitValuatorAxisStruct(device, 1, 791#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 792 axes_labels[1], 793#endif 794 0, 65535, 10000, 0, 10000); 795#else 796 xf86InitValuatorAxisStruct(device, 1, 797#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 798 axes_labels[1], 799#endif 800 0, -1, 1, 0, 1); 801#endif 802 xf86InitValuatorDefaults(device, 1); 803#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0 804 xf86MotionHistoryAllocate(pInfo); 805#endif 806 807 xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_INIT\n"); 808#ifdef EXTMOUSEDEBUG 809 xf86Msg(X_INFO, "assigning %p atom=%d name=%s\n", device, pInfo->atom, 810 pInfo->name); 811#endif 812 break; 813 814 case DEVICE_ON: 815 xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_ON\n"); 816 pInfo->fd = xf86OpenSerial(pInfo->options); 817 if (pInfo->fd == -1) 818 xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name); 819 else { 820 pMse->buffer = XisbNew(pInfo->fd, 64); 821 if (!pMse->buffer) { 822 xf86CloseSerial(pInfo->fd); 823 pInfo->fd = -1; 824 } else { 825 VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv; 826 if (mPriv != NULL) { 827 /* 828 * enable absolute pointing device here 829 */ 830 if (!VMMouseClient_Enable()) { 831 xf86Msg(X_ERROR, "VMWARE(0): vmmouse enable failed\n"); 832 mPriv->vmmouseAvailable = FALSE; 833 device->public.on = FALSE; 834 return FALSE; 835 } else { 836 mPriv->vmmouseAvailable = TRUE; 837 xf86Msg(X_INFO, "VMWARE(0): vmmouse enabled\n"); 838 } 839 } 840 xf86FlushInput(pInfo->fd); 841 xf86AddEnabledDevice(pInfo); 842 } 843 } 844 pMse->lastButtons = 0; 845 device->public.on = TRUE; 846 FlushButtons(pMse); 847 break; 848 case DEVICE_OFF: 849 case DEVICE_CLOSE: 850 xf86Msg(X_INFO, "VMWARE(0): VMMOUSE DEVICE_OFF/CLOSE\n"); 851 852 if (pInfo->fd != -1) { 853 VMMousePrivPtr mPriv = (VMMousePrivPtr)pMse->mousePriv; 854 if( mPriv->vmmouseAvailable ) { 855 VMMouseClient_Disable(); 856 mPriv->vmmouseAvailable = FALSE; 857 mPriv->absoluteRequested = FALSE; 858 } 859 860 xf86RemoveEnabledDevice(pInfo); 861 if (pMse->buffer) { 862 XisbFree(pMse->buffer); 863 pMse->buffer = NULL; 864 } 865 xf86CloseSerial(pInfo->fd); 866 pInfo->fd = -1; 867 } 868 device->public.on = FALSE; 869 usleep(300000); 870 break; 871 872 } 873 874 return Success; 875} 876 877 878/* 879 *---------------------------------------------------------------------- 880 * 881 * VMMouseReadInput -- 882 * This function was called by Xserver when there is data available 883 * in the input device 884 * 885 * Results: 886 * None 887 * 888 * Side effects: 889 * Input data in regular PS/2 fd was cleared 890 * Real mouse data was read from the absolute pointing device 891 * and posted to Xserver 892 * 893 *---------------------------------------------------------------------- 894 */ 895 896static void 897VMMouseReadInput(InputInfoPtr pInfo) 898{ 899 MouseDevPtr pMse; 900 VMMousePrivPtr mPriv; 901 int c; 902 int len = 0; 903 904 pMse = pInfo->private; 905 mPriv = pMse->mousePriv; 906 907 if (!mPriv->absoluteRequested) { 908 /* 909 * We can request for absolute mode, but it depends on 910 * host whether it will send us absolute or relative 911 * position. 912 */ 913 VMMouseClient_RequestAbsolute(); 914 mPriv->absoluteRequested = TRUE; 915 xf86Msg(X_INFO, "VMWARE(0): vmmouse enable absolute mode\n"); 916 } 917 918 /* 919 * First read the bytes in input device to clear the regular PS/2 fd so 920 * we don't get called again. 921 */ 922 /* 923 * Set blocking to -1 on the first call because we know there is data to 924 * read. Xisb automatically clears it after one successful read so that 925 * succeeding reads are preceeded by a select with a 0 timeout to prevent 926 * read from blocking indefinitely. 927 */ 928 XisbBlockDuration(pMse->buffer, -1); 929 while ((c = XisbRead(pMse->buffer)) >= 0) { 930 len++; 931 /* 932 * regular PS packet consists of 3 bytes 933 * We read 3 bytes to drain the PS/2 packet 934 */ 935 if(len < 3) continue; 936 len = 0; 937 /* 938 * Now get the real data from absolute pointing device 939 */ 940 GetVMMouseMotionEvent(pInfo); 941 } 942 /* 943 * There maybe still vmmouse data available 944 */ 945 GetVMMouseMotionEvent(pInfo); 946} 947 948 949/* 950 *---------------------------------------------------------------------- 951 * 952 * GetVMMouseMotionEvent -- 953 * Read all the mouse data available from the absolute 954 * pointing device and post it to the Xserver 955 * 956 * Results: 957 * None 958 * 959 * Side effects: 960 * Real mouse data was read from the absolute pointing 961 * device and posted to Xserver 962 * 963 *---------------------------------------------------------------------- 964 */ 965 966static void 967GetVMMouseMotionEvent(InputInfoPtr pInfo){ 968 MouseDevPtr pMse; 969 VMMousePrivPtr mPriv; 970 int buttons, dx, dy, dz, dw; 971 VMMOUSE_INPUT_DATA vmmouseInput; 972 int ps2Buttons = 0; 973 int numPackets; 974 975 pMse = pInfo->private; 976 mPriv = (VMMousePrivPtr)pMse->mousePriv; 977 while((numPackets = VMMouseClient_GetInput(&vmmouseInput))){ 978 if (numPackets == VMMOUSE_ERROR) { 979 VMMouseClient_Disable(); 980 VMMouseClient_Enable(); 981 VMMouseClient_RequestAbsolute(); 982 xf86Msg(X_INFO, "VMWARE(0): re-requesting absolute mode after reset\n"); 983 break; 984 } 985 986 if(vmmouseInput.Buttons & VMMOUSE_MIDDLE_BUTTON) 987 ps2Buttons |= 0x04; /* Middle*/ 988 if(vmmouseInput.Buttons & VMMOUSE_RIGHT_BUTTON) 989 ps2Buttons |= 0x02; /* Right*/ 990 if(vmmouseInput.Buttons & VMMOUSE_LEFT_BUTTON) 991 ps2Buttons |= 0x01; /* Left*/ 992 993 buttons = (ps2Buttons & 0x04) >> 1 | /* Middle */ 994 (ps2Buttons & 0x02) >> 1 | /* Right */ 995 (ps2Buttons & 0x01) << 2; /* Left */ 996 997 dx = vmmouseInput.X; 998 dy = vmmouseInput.Y; 999 dz = (char)vmmouseInput.Z; 1000 dw = 0; 1001 /* 1002 * Get the per package relative or absolute information. 1003 */ 1004 mPriv->isCurrRelative = vmmouseInput.Flags & VMMOUSE_MOVE_RELATIVE; 1005 /* post an event */ 1006 pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw); 1007 mPriv->vmmousePrevInput = vmmouseInput; 1008 } 1009} 1010 1011 1012/* 1013 *---------------------------------------------------------------------- 1014 * 1015 * VMMouseControlProc -- 1016 * This function is unused 1017 * 1018 * Results: 1019 * None 1020 * 1021 * Side effects: 1022 * None 1023 * 1024 *---------------------------------------------------------------------- 1025 */ 1026 1027static int 1028VMMouseControlProc(LocalDevicePtr local, xDeviceCtl * control) 1029{ 1030 xf86Msg(X_INFO, "VMWARE(0): VMMouseControlProc\n"); 1031 return (Success); 1032} 1033 1034 1035/* 1036 *---------------------------------------------------------------------- 1037 * 1038 * VMMouseCloseProc -- 1039 * This function is unused 1040 * 1041 * Results: 1042 * None 1043 * 1044 * Side effects: 1045 * None 1046 * 1047 *---------------------------------------------------------------------- 1048 */ 1049 1050static void 1051VMMouseCloseProc(LocalDevicePtr local) 1052{ 1053 xf86Msg(X_INFO, "VMWARE(0): VMMouseCloseProc\n"); 1054} 1055 1056 1057/* 1058 *---------------------------------------------------------------------- 1059 * 1060 * VMMouseSwitchProc -- 1061 * This function is unused 1062 * 1063 * Results: 1064 * None 1065 * 1066 * Side effects: 1067 * None 1068 * 1069 *---------------------------------------------------------------------- 1070 */ 1071 1072static int 1073VMMouseSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode) 1074{ 1075 xf86Msg(X_INFO, "VMWARE(0): VMMouseSwitchMode\n"); 1076 return (Success); 1077} 1078 1079 1080/* 1081 *---------------------------------------------------------------------- 1082 * 1083 * VMMouseConvertProc -- 1084 * This function was called by Xserver to convert valuators to X and Y 1085 * 1086 * Results: 1087 * TRUE 1088 * 1089 * Side effects: 1090 * X and Y was converted according to current Screen dimension 1091 * 1092 *---------------------------------------------------------------------- 1093 */ 1094 1095static Bool 1096VMMouseConvertProc(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, 1097 int v3, int v4, int v5, int *x, int *y) 1098{ 1099 MouseDevPtr pMse; 1100 VMMousePrivPtr mPriv; 1101 double factorX, factorY; 1102 1103 pMse = pInfo->private; 1104 mPriv = pMse->mousePriv; 1105 1106 if (first != 0 || num != 2) 1107 return FALSE; 1108 1109 if(mPriv->isCurrRelative) { 1110 *x = v0; 1111 *y = v1; 1112 } else { 1113 factorX = ((double) screenInfo.screens[mPriv->screenNum]->width) / (double) 65535; 1114 factorY = ((double) screenInfo.screens[mPriv->screenNum]->height) / (double) 65535; 1115 1116 *x = v0 * factorX + 0.5; 1117 *y = v1 * factorY + 0.5; 1118 1119 if (mPriv->screenNum != -1) { 1120 xf86XInputSetScreen(pInfo, mPriv->screenNum, *x, *y); 1121 } 1122 } 1123 return TRUE; 1124} 1125 1126 1127#ifdef XFree86LOADER 1128 1129/* 1130 *---------------------------------------------------------------------- 1131 * 1132 * VMMouseUnplug -- 1133 * This function was called by Xserver when unplug 1134 * 1135 * Results: 1136 * None 1137 * 1138 * Side effects: 1139 * None 1140 * 1141 *---------------------------------------------------------------------- 1142 */ 1143 1144static void 1145VMMouseUnplug(pointer p) 1146{ 1147 xf86Msg(X_INFO, "VMWARE(0): VMMouseUnplug\n"); 1148} 1149 1150 1151/* 1152 *---------------------------------------------------------------------- 1153 * 1154 * VMMousePlug -- 1155 * This function was called when Xserver load vmmouse module. It will 1156 * integrate the module infto the XFree86 loader architecutre. 1157 * 1158 * Results: 1159 * TRUE 1160 * 1161 * Side effects: 1162 * Regular mouse module was loaded as a submodule. In case 1163 * absolute pointing device is not available, we can always fall back 1164 * to the regular mouse module 1165 * 1166 *---------------------------------------------------------------------- 1167 */ 1168 1169static pointer 1170VMMousePlug(pointer module, 1171 pointer options, 1172 int *errmaj, 1173 int *errmin) 1174{ 1175 static Bool Initialised = FALSE; 1176 1177#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7 1178 xf86LoaderReqSymLists(reqSymbols, NULL); 1179#endif 1180 1181 if (!Initialised) 1182 Initialised = TRUE; 1183 1184 xf86Msg(X_INFO, "VMWARE(0): VMMOUSE module was loaded\n"); 1185 xf86AddInputDriver(&VMMOUSE, module, 0); 1186 1187#ifndef NO_MOUSE_MODULE 1188{ 1189 char *name; 1190 /* 1191 * Load the normal mouse module as submodule 1192 * If we fail in PreInit later, this allows us to fall back to normal mouse module 1193 */ 1194#ifndef NORMALISE_MODULE_NAME 1195 name = xstrdup("mouse"); 1196#else 1197 /* Normalise the module name */ 1198 name = xf86NormalizeName("mouse"); 1199#endif 1200 1201 if (!LoadSubModule(module, name, NULL, NULL, NULL, NULL, errmaj, errmin)) { 1202 LoaderErrorMsg(NULL, name, *errmaj, *errmin); 1203 } 1204 xfree(name); 1205} 1206#endif 1207 1208 return module; 1209} 1210 1211static XF86ModuleVersionInfo VMMouseVersionRec = { 1212 "vmmouse", 1213 MODULEVENDORSTRING, 1214 MODINFOSTRING1, 1215 MODINFOSTRING2, 1216 XORG_VERSION_CURRENT, 1217 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, 1218 ABI_CLASS_XINPUT, 1219 ABI_XINPUT_VERSION, 1220 MOD_CLASS_XINPUT, 1221 {0, 0, 0, 0} /* signature, to be patched into the file by a tool */ 1222}; 1223 1224/* 1225 * The variable contains the necessary information to load and initialize the module 1226 */ 1227_X_EXPORT XF86ModuleData vmmouseModuleData = { 1228 &VMMouseVersionRec, 1229 VMMousePlug, 1230 VMMouseUnplug 1231}; 1232#endif /* XFree86LOADER */ 1233