xf86Xinput.c revision 9ace9065
1/* 2 * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Frederic Lepied not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Frederic Lepied makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 */ 23/* 24 * Copyright (c) 2000-2002 by The XFree86 Project, Inc. 25 * 26 * Permission is hereby granted, free of charge, to any person obtaining a 27 * copy of this software and associated documentation files (the "Software"), 28 * to deal in the Software without restriction, including without limitation 29 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 30 * and/or sell copies of the Software, and to permit persons to whom the 31 * Software is furnished to do so, subject to the following conditions: 32 * 33 * The above copyright notice and this permission notice shall be included in 34 * all copies or substantial portions of the Software. 35 * 36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 39 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 40 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 41 * OTHER DEALINGS IN THE SOFTWARE. 42 * 43 * Except as contained in this notice, the name of the copyright holder(s) 44 * and author(s) shall not be used in advertising or otherwise to promote 45 * the sale, use or other dealings in this Software without prior written 46 * authorization from the copyright holder(s) and author(s). 47 */ 48 49#ifdef HAVE_XORG_CONFIG_H 50#include <xorg-config.h> 51#endif 52 53#include <X11/Xfuncproto.h> 54#include <X11/Xmd.h> 55#include <X11/extensions/XI.h> 56#include <X11/extensions/XIproto.h> 57#include <X11/Xatom.h> 58#include "xf86.h" 59#include "xf86Priv.h" 60#include "xf86Config.h" 61#include "xf86Xinput.h" 62#include "xf86Optrec.h" 63#include "mipointer.h" 64#include "extinit.h" 65#include "loaderProcs.h" 66 67#include "exevents.h" /* AddInputDevice */ 68#include "exglobals.h" 69#include "eventstr.h" 70#include "inpututils.h" 71 72#include <string.h> /* InputClassMatches */ 73#ifdef HAVE_FNMATCH_H 74#include <fnmatch.h> 75#endif 76#ifdef HAVE_SYS_UTSNAME_H 77#include <sys/utsname.h> 78#endif 79 80#include <stdarg.h> 81#include <stdint.h> /* for int64_t */ 82 83#include "mi.h" 84 85#include <ptrveloc.h> /* dix pointer acceleration */ 86#include <xserver-properties.h> 87 88#ifdef XFreeXDGA 89#include "dgaproc.h" 90#endif 91 92#include "xkbsrv.h" 93 94/* Valuator verification macro */ 95#define XI_VERIFY_VALUATORS(num_valuators) \ 96 if (num_valuators > MAX_VALUATORS) { \ 97 xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ 98 " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ 99 return; \ 100 } 101 102EventListPtr xf86Events = NULL; 103 104static int 105xf86InputDevicePostInit(DeviceIntPtr dev); 106 107/** 108 * Eval config and modify DeviceVelocityRec accordingly 109 */ 110static void 111ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, 112 DeviceVelocityPtr s) 113{ 114 int tempi; 115 float tempf; 116 Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); 117 Atom prop; 118 119 if(!s) 120 return; 121 122 /* common settings (available via device properties) */ 123 tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); 124 if (tempf > 1.0) { 125 xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", 126 devname, tempf); 127 prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); 128 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 129 PropModeReplace, 1, &tempf, FALSE); 130 } 131 132 tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); 133 if (tempf > 1.0) { 134 xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", 135 devname, tempf); 136 prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); 137 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 138 PropModeReplace, 1, &tempf, FALSE); 139 } 140 141 /* select profile by number */ 142 tempi = xf86SetIntOption(list, "AccelerationProfile", 143 s->statistics.profile_number); 144 145 prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); 146 if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, 147 PropModeReplace, 1, &tempi, FALSE) == Success) { 148 xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, 149 tempi); 150 } else { 151 xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", 152 devname, tempi); 153 } 154 155 /* set scaling */ 156 tempf = xf86SetRealOption(list, "ExpectedRate", 0); 157 prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); 158 if (tempf > 0) { 159 tempf = 1000.0 / tempf; 160 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 161 PropModeReplace, 1, &tempf, FALSE); 162 } else { 163 tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); 164 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 165 PropModeReplace, 1, &tempf, FALSE); 166 } 167 168 tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); 169 if (tempi > 1) 170 InitTrackers(s, tempi); 171 172 s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", 173 s->initial_range); 174 175 s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); 176 177 tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); 178 if (tempf >= 0) { 179 xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", 180 devname, tempf*100.0); 181 s->max_rel_diff = tempf; 182 } 183 184 /* Configure softening. If const deceleration is used, this is expected 185 * to provide better subpixel information so we enable 186 * softening by default only if ConstantDeceleration is not used 187 */ 188 s->use_softening = xf86SetBoolOption(list, "Softening", 189 s->const_acceleration == 1.0); 190 191 s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", 192 s->average_accel); 193 194 s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); 195} 196 197static void 198ApplyAccelerationSettings(DeviceIntPtr dev){ 199 int scheme, i; 200 DeviceVelocityPtr pVel; 201 InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; 202 char* schemeStr; 203 204 if (dev->valuator && dev->ptrfeed) { 205 schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); 206 207 scheme = dev->valuator->accelScheme.number; 208 209 if (!xf86NameCmp(schemeStr, "predictable")) 210 scheme = PtrAccelPredictable; 211 212 if (!xf86NameCmp(schemeStr, "lightweight")) 213 scheme = PtrAccelLightweight; 214 215 if (!xf86NameCmp(schemeStr, "none")) 216 scheme = PtrAccelNoOp; 217 218 /* reinit scheme if needed */ 219 if (dev->valuator->accelScheme.number != scheme) { 220 if (dev->valuator->accelScheme.AccelCleanupProc) { 221 dev->valuator->accelScheme.AccelCleanupProc(dev); 222 } 223 224 if (InitPointerAccelerationScheme(dev, scheme)) { 225 xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", 226 pInfo->name, schemeStr, scheme); 227 } else { 228 xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", 229 pInfo->name, schemeStr); 230 scheme = dev->valuator->accelScheme.number; 231 } 232 } else { 233 xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", 234 pInfo->name, scheme); 235 } 236 237 free(schemeStr); 238 239 /* process special configuration */ 240 switch (scheme) { 241 case PtrAccelPredictable: 242 pVel = GetDevicePredictableAccelData(dev); 243 ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, 244 pVel); 245 break; 246 } 247 248 i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", 249 dev->ptrfeed->ctrl.num); 250 if (i >= 0) 251 dev->ptrfeed->ctrl.num = i; 252 253 i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", 254 dev->ptrfeed->ctrl.den); 255 if (i > 0) 256 dev->ptrfeed->ctrl.den = i; 257 258 i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", 259 dev->ptrfeed->ctrl.threshold); 260 if (i >= 0) 261 dev->ptrfeed->ctrl.threshold = i; 262 263 xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", 264 pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ 265 ((float)dev->ptrfeed->ctrl.den)); 266 xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", 267 pInfo->name, dev->ptrfeed->ctrl.threshold); 268 } 269} 270 271/*********************************************************************** 272 * 273 * xf86ProcessCommonOptions -- 274 * 275 * Process global options. 276 * 277 *********************************************************************** 278 */ 279void 280xf86ProcessCommonOptions(InputInfoPtr pInfo, 281 pointer list) 282{ 283 if (xf86SetBoolOption(list, "Floating", 0) || 284 !xf86SetBoolOption(list, "AlwaysCore", 1) || 285 !xf86SetBoolOption(list, "SendCoreEvents", 1) || 286 !xf86SetBoolOption(list, "CorePointer", 1) || 287 !xf86SetBoolOption(list, "CoreKeyboard", 1)) { 288 xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); 289 } else { 290 pInfo->flags |= XI86_ALWAYS_CORE; 291 xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); 292 } 293} 294 295/*********************************************************************** 296 * 297 * xf86ActivateDevice -- 298 * 299 * Initialize an input device. 300 * 301 * Returns TRUE on success, or FALSE otherwise. 302 *********************************************************************** 303 */ 304static DeviceIntPtr 305xf86ActivateDevice(InputInfoPtr pInfo) 306{ 307 DeviceIntPtr dev; 308 Atom atom; 309 310 dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); 311 312 if (dev == NULL) 313 { 314 xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", 315 pInfo->name); 316 pInfo->dev = NULL; 317 return NULL; 318 } 319 320 atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); 321 AssignTypeAndName(dev, atom, pInfo->name); 322 dev->public.devicePrivate = pInfo; 323 pInfo->dev = dev; 324 325 dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; 326 dev->type = SLAVE; 327 dev->spriteInfo->spriteOwner = FALSE; 328 329 dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); 330 331 if (serverGeneration == 1) 332 xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", 333 pInfo->name, pInfo->type_name); 334 335 return dev; 336} 337 338/**************************************************************************** 339 * 340 * Caller: ProcXSetDeviceMode 341 * 342 * Change the mode of an extension device. 343 * This function is used to change the mode of a device from reporting 344 * relative motion to reporting absolute positional information, and 345 * vice versa. 346 * The default implementation below is that no such devices are supported. 347 * 348 *********************************************************************** 349 */ 350 351int 352SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) 353{ 354 InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; 355 356 if (pInfo->switch_mode) { 357 return (*pInfo->switch_mode)(client, dev, mode); 358 } 359 else 360 return BadMatch; 361} 362 363 364/*********************************************************************** 365 * 366 * Caller: ProcXSetDeviceValuators 367 * 368 * Set the value of valuators on an extension input device. 369 * This function is used to set the initial value of valuators on 370 * those input devices that are capable of reporting either relative 371 * motion or an absolute position, and allow an initial position to be set. 372 * The default implementation below is that no such devices are supported. 373 * 374 *********************************************************************** 375 */ 376 377int 378SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, 379 int first_valuator, int num_valuators) 380{ 381 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 382 383 if (pInfo->set_device_valuators) 384 return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, 385 num_valuators); 386 387 return BadMatch; 388} 389 390 391/*********************************************************************** 392 * 393 * Caller: ProcXChangeDeviceControl 394 * 395 * Change the specified device controls on an extension input device. 396 * 397 *********************************************************************** 398 */ 399 400int 401ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) 402{ 403 InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; 404 405 if (!pInfo->control_proc) { 406 switch (control->control) { 407 case DEVICE_CORE: 408 return BadMatch; 409 case DEVICE_RESOLUTION: 410 case DEVICE_ABS_CALIB: 411 case DEVICE_ABS_AREA: 412 case DEVICE_ENABLE: 413 return Success; 414 default: 415 return BadMatch; 416 } 417 } 418 else { 419 return (*pInfo->control_proc)(pInfo, control); 420 } 421} 422 423/* 424 * Get the operating system name from uname and store it statically to avoid 425 * repeating the system call each time MatchOS is checked. 426 */ 427static const char * 428HostOS(void) 429{ 430#ifdef HAVE_SYS_UTSNAME_H 431 struct utsname name; 432 static char host_os[sizeof(name.sysname)] = ""; 433 434 if (*host_os == '\0') { 435 if (uname(&name) >= 0) 436 strcpy(host_os, name.sysname); 437 else { 438 strncpy(host_os, "unknown", sizeof(host_os)); 439 host_os[sizeof(host_os)-1] = '\0'; 440 } 441 } 442 return host_os; 443#else 444 return ""; 445#endif 446} 447 448static int 449match_substring(const char *attr, const char *pattern) 450{ 451 return (strstr(attr, pattern)) ? 0 : -1; 452} 453 454#ifdef HAVE_FNMATCH_H 455static int 456match_pattern(const char *attr, const char *pattern) 457{ 458 return fnmatch(pattern, attr, 0); 459} 460#else 461#define match_pattern match_substring 462#endif 463 464#ifdef HAVE_FNMATCH_H 465static int 466match_path_pattern(const char *attr, const char *pattern) 467{ 468 return fnmatch(pattern, attr, FNM_PATHNAME); 469} 470#else 471#define match_path_pattern match_substring 472#endif 473 474/* 475 * Match an attribute against a list of NULL terminated arrays of patterns. 476 * If a pattern in each list entry is matched, return TRUE. 477 */ 478static Bool 479MatchAttrToken(const char *attr, struct list *patterns, 480 int (*compare)(const char *attr, const char *pattern)) 481{ 482 const xf86MatchGroup *group; 483 484 /* If there are no patterns, accept the match */ 485 if (list_is_empty(patterns)) 486 return TRUE; 487 488 /* If there are patterns but no attribute, reject the match */ 489 if (!attr) 490 return FALSE; 491 492 /* 493 * Otherwise, iterate the list of patterns ensuring each entry has a 494 * match. Each list entry is a separate Match line of the same type. 495 */ 496 list_for_each_entry(group, patterns, entry) { 497 char * const *cur; 498 Bool match = FALSE; 499 500 for (cur = group->values; *cur; cur++) 501 if ((*compare)(attr, *cur) == 0) { 502 match = TRUE; 503 break; 504 } 505 if (!match) 506 return FALSE; 507 } 508 509 /* All the entries in the list matched the attribute */ 510 return TRUE; 511} 512 513/* 514 * Classes without any Match statements match all devices. Otherwise, all 515 * statements must match. 516 */ 517static Bool 518InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, 519 const InputAttributes *attrs) 520{ 521 /* MatchProduct substring */ 522 if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) 523 return FALSE; 524 525 /* MatchVendor substring */ 526 if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) 527 return FALSE; 528 529 /* MatchDevicePath pattern */ 530 if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) 531 return FALSE; 532 533 /* MatchOS case-insensitive string */ 534 if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) 535 return FALSE; 536 537 /* MatchPnPID pattern */ 538 if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) 539 return FALSE; 540 541 /* MatchUSBID pattern */ 542 if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) 543 return FALSE; 544 545 /* MatchDriver string */ 546 if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) 547 return FALSE; 548 549 /* 550 * MatchTag string 551 * See if any of the device's tags match any of the MatchTag tokens. 552 */ 553 if (!list_is_empty(&iclass->match_tag)) { 554 char * const *tag; 555 Bool match; 556 557 if (!attrs->tags) 558 return FALSE; 559 for (tag = attrs->tags, match = FALSE; *tag; tag++) { 560 if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { 561 match = TRUE; 562 break; 563 } 564 } 565 if (!match) 566 return FALSE; 567 } 568 569 /* MatchIs* booleans */ 570 if (iclass->is_keyboard.set && 571 iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) 572 return FALSE; 573 if (iclass->is_pointer.set && 574 iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) 575 return FALSE; 576 if (iclass->is_joystick.set && 577 iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) 578 return FALSE; 579 if (iclass->is_tablet.set && 580 iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) 581 return FALSE; 582 if (iclass->is_touchpad.set && 583 iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) 584 return FALSE; 585 if (iclass->is_touchscreen.set && 586 iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) 587 return FALSE; 588 589 return TRUE; 590} 591 592/* 593 * Merge in any InputClass configurations. Options in each InputClass 594 * section have more priority than the original device configuration as 595 * well as any previous InputClass sections. 596 */ 597static int 598MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) 599{ 600 XF86ConfInputClassPtr cl; 601 XF86OptionPtr classopts; 602 603 for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 604 if (!InputClassMatches(cl, idev, attrs)) 605 continue; 606 607 /* Collect class options and driver settings */ 608 classopts = xf86optionListDup(cl->option_lst); 609 if (cl->driver) { 610 free(idev->driver); 611 idev->driver = xstrdup(cl->driver); 612 if (!idev->driver) { 613 xf86Msg(X_ERROR, "Failed to allocate memory while merging " 614 "InputClass configuration"); 615 return BadAlloc; 616 } 617 classopts = xf86ReplaceStrOption(classopts, "driver", 618 idev->driver); 619 } 620 621 /* Apply options to device with InputClass settings preferred. */ 622 xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", 623 idev->name, cl->identifier); 624 idev->options = xf86optionListMerge(idev->options, classopts); 625 } 626 627 return Success; 628} 629 630/* 631 * Iterate the list of classes and look for Option "Ignore". Return the 632 * value of the last matching class and holler when returning TRUE. 633 */ 634static Bool 635IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) 636{ 637 XF86ConfInputClassPtr cl; 638 Bool ignore = FALSE; 639 const char *ignore_class; 640 641 for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 642 if (!InputClassMatches(cl, idev, attrs)) 643 continue; 644 if (xf86findOption(cl->option_lst, "Ignore")) { 645 ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); 646 ignore_class = cl->identifier; 647 } 648 } 649 650 if (ignore) 651 xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", 652 idev->name, ignore_class); 653 return ignore; 654} 655 656InputInfoPtr 657xf86AllocateInput(void) 658{ 659 InputInfoPtr pInfo; 660 661 pInfo = calloc(sizeof(*pInfo), 1); 662 if (!pInfo) 663 return NULL; 664 665 pInfo->fd = -1; 666 pInfo->type_name = "UNKNOWN"; 667 668 return pInfo; 669} 670 671/* Append InputInfoRec to the tail of xf86InputDevs. */ 672static void 673xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) 674{ 675 InputInfoPtr *prev = NULL; 676 677 pInfo->drv = drv; 678 pInfo->module = DuplicateModule(drv->module, NULL); 679 680 for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) 681 ; 682 683 *prev = pInfo; 684 pInfo->next = NULL; 685 686 xf86CollectInputOptions(pInfo, (const char**)drv->default_options); 687 xf86OptionListReport(pInfo->options); 688 xf86ProcessCommonOptions(pInfo, pInfo->options); 689} 690 691/* 692 * Remove an entry from xf86InputDevs and free all the device's information. 693 */ 694void 695xf86DeleteInput(InputInfoPtr pInp, int flags) 696{ 697 /* First check if the inputdev is valid. */ 698 if (pInp == NULL) 699 return; 700 701 if (pInp->module) 702 UnloadModule(pInp->module); 703 704 /* This should *really* be handled in drv->UnInit(dev) call instead, but 705 * if the driver forgets about it make sure we free it or at least crash 706 * with flying colors */ 707 free(pInp->private); 708 709 FreeInputAttributes(pInp->attrs); 710 711 /* Remove the entry from the list. */ 712 if (pInp == xf86InputDevs) 713 xf86InputDevs = pInp->next; 714 else { 715 InputInfoPtr p = xf86InputDevs; 716 while (p && p->next != pInp) 717 p = p->next; 718 if (p) 719 p->next = pInp->next; 720 /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ 721 } 722 723 free(pInp->driver); 724 free(pInp->name); 725 xf86optionListFree(pInp->options); 726 free(pInp); 727} 728 729/* 730 * Apply backend-specific initialization. Invoked after ActiveteDevice(), 731 * i.e. after the driver successfully completed DEVICE_INIT and the device 732 * is advertised. 733 * @param dev the device 734 * @return Success or an error code 735 */ 736static int 737xf86InputDevicePostInit(DeviceIntPtr dev) { 738 ApplyAccelerationSettings(dev); 739 return Success; 740} 741 742/** 743 * Create a new input device, activate and enable it. 744 * 745 * Possible return codes: 746 * BadName .. a bad driver name was supplied. 747 * BadImplementation ... The driver does not have a PreInit function. This 748 * is a driver bug. 749 * BadMatch .. device initialization failed. 750 * BadAlloc .. too many input devices 751 * 752 * @param idev The device, already set up with identifier, driver, and the 753 * options. 754 * @param pdev Pointer to the new device, if Success was reported. 755 * @param enable Enable the device after activating it. 756 * 757 * @return Success or an error code 758 */ 759_X_INTERNAL int 760xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) 761{ 762 InputDriverPtr drv = NULL; 763 DeviceIntPtr dev = NULL; 764 int rval; 765 766 /* Memory leak for every attached device if we don't 767 * test if the module is already loaded first */ 768 drv = xf86LookupInputDriver(pInfo->driver); 769 if (!drv) 770 if (xf86LoadOneModule(pInfo->driver, NULL)) 771 drv = xf86LookupInputDriver(pInfo->driver); 772 if (!drv) { 773 xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); 774 rval = BadName; 775 goto unwind; 776 } 777 778 xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, pInfo->name); 779 780 if (!drv->PreInit) { 781 xf86Msg(X_ERROR, 782 "Input driver `%s' has no PreInit function (ignoring)\n", 783 drv->driverName); 784 rval = BadImplementation; 785 goto unwind; 786 } 787 788 xf86AddInput(drv, pInfo); 789 790 rval = drv->PreInit(drv, pInfo, 0); 791 792 if (rval != Success) { 793 xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); 794 goto unwind; 795 } 796 797 if (!(dev = xf86ActivateDevice(pInfo))) 798 { 799 rval = BadAlloc; 800 goto unwind; 801 } 802 803 rval = ActivateDevice(dev, TRUE); 804 if (rval != Success) 805 { 806 xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 807 RemoveDevice(dev, TRUE); 808 goto unwind; 809 } 810 811 rval = xf86InputDevicePostInit(dev); 812 if (rval != Success) 813 { 814 xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); 815 RemoveDevice(dev, TRUE); 816 goto unwind; 817 } 818 819 /* Enable it if it's properly initialised and we're currently in the VT */ 820 if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) 821 { 822 OsBlockSignals(); 823 EnableDevice(dev, TRUE); 824 if (!dev->enabled) 825 { 826 OsReleaseSignals(); 827 xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 828 rval = BadMatch; 829 goto unwind; 830 } 831 /* send enter/leave event, update sprite window */ 832 CheckMotion(NULL, dev); 833 OsReleaseSignals(); 834 } 835 836 *pdev = dev; 837 return Success; 838 839unwind: 840 if(pInfo) { 841 if(drv && drv->UnInit) 842 drv->UnInit(drv, pInfo, 0); 843 else 844 xf86DeleteInput(pInfo, 0); 845 } 846 return rval; 847} 848 849int 850NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, 851 DeviceIntPtr *pdev) 852{ 853 InputInfoPtr pInfo = NULL; 854 InputOption *option = NULL; 855 int rval = Success; 856 int is_auto = 0; 857 858 pInfo = xf86AllocateInput(); 859 if (!pInfo) 860 return BadAlloc; 861 862 for (option = options; option; option = option->next) { 863 if (strcasecmp(option->key, "driver") == 0) { 864 if (pInfo->driver) { 865 rval = BadRequest; 866 goto unwind; 867 } 868 pInfo->driver = xstrdup(option->value); 869 if (!pInfo->driver) { 870 rval = BadAlloc; 871 goto unwind; 872 } 873 } 874 875 if (strcasecmp(option->key, "name") == 0 || 876 strcasecmp(option->key, "identifier") == 0) { 877 if (pInfo->name) { 878 rval = BadRequest; 879 goto unwind; 880 } 881 pInfo->name = xstrdup(option->value); 882 if (!pInfo->name) { 883 rval = BadAlloc; 884 goto unwind; 885 } 886 } 887 888 if (strcmp(option->key, "_source") == 0 && 889 (strcmp(option->value, "server/hal") == 0 || 890 strcmp(option->value, "server/udev") == 0)) { 891 is_auto = 1; 892 if (!xf86Info.autoAddDevices) { 893 rval = BadMatch; 894 goto unwind; 895 } 896 } 897 } 898 899 for (option = options; option; option = option->next) { 900 /* Steal option key/value strings from the provided list. 901 * We need those strings, the InputOption list doesn't. */ 902 pInfo->options = xf86addNewOption(pInfo->options, 903 option->key, option->value); 904 option->key = NULL; 905 option->value = NULL; 906 } 907 908 /* Apply InputClass settings */ 909 if (attrs) { 910 if (IgnoreInputClass(pInfo, attrs)) { 911 rval = BadIDChoice; 912 goto unwind; 913 } 914 915 rval = MergeInputClasses(pInfo, attrs); 916 if (rval != Success) 917 goto unwind; 918 919 pInfo->attrs = DuplicateInputAttributes(attrs); 920 } 921 922 if (!pInfo->driver || !pInfo->name) { 923 xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); 924 rval = BadRequest; 925 goto unwind; 926 } 927 928 if (!pInfo->name) { 929 xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); 930 rval = BadMatch; 931 goto unwind; 932 } 933 934 rval = xf86NewInputDevice(pInfo, pdev, 935 (!is_auto || (is_auto && xf86Info.autoEnableDevices))); 936 937 return rval; 938 939unwind: 940 if (is_auto && !xf86Info.autoAddDevices) 941 xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); 942 xf86DeleteInput(pInfo, 0); 943 return rval; 944} 945 946void 947DeleteInputDeviceRequest(DeviceIntPtr pDev) 948{ 949 InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; 950 InputDriverPtr drv = NULL; 951 Bool isMaster = IsMaster(pDev); 952 953 if (pInfo) /* need to get these before RemoveDevice */ 954 drv = pInfo->drv; 955 956 OsBlockSignals(); 957 RemoveDevice(pDev, TRUE); 958 959 if (!isMaster && pInfo != NULL) 960 { 961 if(drv->UnInit) 962 drv->UnInit(drv, pInfo, 0); 963 else 964 xf86DeleteInput(pInfo, 0); 965 } 966 OsReleaseSignals(); 967} 968 969/* 970 * convenient functions to post events 971 */ 972 973void 974xf86PostMotionEvent(DeviceIntPtr device, 975 int is_absolute, 976 int first_valuator, 977 int num_valuators, 978 ...) 979{ 980 va_list var; 981 int i = 0; 982 ValuatorMask mask; 983 984 XI_VERIFY_VALUATORS(num_valuators); 985 986 valuator_mask_zero(&mask); 987 va_start(var, num_valuators); 988 for (i = 0; i < num_valuators; i++) 989 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 990 va_end(var); 991 992 xf86PostMotionEventM(device, is_absolute, &mask); 993} 994 995void 996xf86PostMotionEventP(DeviceIntPtr device, 997 int is_absolute, 998 int first_valuator, 999 int num_valuators, 1000 const int *valuators) 1001{ 1002 ValuatorMask mask; 1003 1004 XI_VERIFY_VALUATORS(num_valuators); 1005 1006 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1007 xf86PostMotionEventM(device, is_absolute, &mask); 1008} 1009 1010void 1011xf86PostMotionEventM(DeviceIntPtr device, 1012 int is_absolute, 1013 const ValuatorMask *mask) 1014{ 1015 int i = 0, nevents = 0; 1016 DeviceEvent *event; 1017 int flags = 0; 1018 1019 if (valuator_mask_num_valuators(mask) > 0) 1020 { 1021 if (is_absolute) 1022 flags = POINTER_ABSOLUTE; 1023 else 1024 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1025 } 1026 1027#if XFreeXDGA 1028 /* The evdev driver may not always send all axes across. */ 1029 if (valuator_mask_isset(mask, 0) || 1030 valuator_mask_isset(mask, 1)) 1031 if (miPointerGetScreen(device)) { 1032 int index = miPointerGetScreen(device)->myNum; 1033 int dx = 0, dy = 0; 1034 1035 if (valuator_mask_isset(mask, 0)) 1036 { 1037 dx = valuator_mask_get(mask, 0); 1038 if (is_absolute) 1039 dx -= device->last.valuators[0]; 1040 } 1041 1042 if (valuator_mask_isset(mask, 1)) 1043 { 1044 dy = valuator_mask_get(mask, 1); 1045 if (is_absolute) 1046 dy -= device->last.valuators[1]; 1047 } 1048 1049 if (DGAStealMotionEvent(device, index, dx, dy)) 1050 return; 1051 } 1052#endif 1053 1054 nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); 1055 1056 for (i = 0; i < nevents; i++) { 1057 event = (DeviceEvent*)((xf86Events + i)->event); 1058 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1059 } 1060} 1061 1062void 1063xf86PostProximityEvent(DeviceIntPtr device, 1064 int is_in, 1065 int first_valuator, 1066 int num_valuators, 1067 ...) 1068{ 1069 va_list var; 1070 int i; 1071 ValuatorMask mask; 1072 1073 XI_VERIFY_VALUATORS(num_valuators); 1074 1075 valuator_mask_zero(&mask); 1076 va_start(var, num_valuators); 1077 for (i = 0; i < num_valuators; i++) 1078 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1079 va_end(var); 1080 1081 xf86PostProximityEventM(device, is_in, &mask); 1082} 1083 1084void 1085xf86PostProximityEventP(DeviceIntPtr device, 1086 int is_in, 1087 int first_valuator, 1088 int num_valuators, 1089 const int *valuators) 1090{ 1091 ValuatorMask mask; 1092 1093 XI_VERIFY_VALUATORS(num_valuators); 1094 1095 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1096 xf86PostProximityEventM(device, is_in, &mask); 1097} 1098 1099void 1100xf86PostProximityEventM(DeviceIntPtr device, 1101 int is_in, 1102 const ValuatorMask *mask) 1103{ 1104 int i, nevents; 1105 1106 nevents = GetProximityEvents(xf86Events, device, 1107 is_in ? ProximityIn : ProximityOut, mask); 1108 for (i = 0; i < nevents; i++) 1109 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1110 1111} 1112 1113void 1114xf86PostButtonEvent(DeviceIntPtr device, 1115 int is_absolute, 1116 int button, 1117 int is_down, 1118 int first_valuator, 1119 int num_valuators, 1120 ...) 1121{ 1122 va_list var; 1123 ValuatorMask mask; 1124 int i = 0; 1125 1126 XI_VERIFY_VALUATORS(num_valuators); 1127 1128 valuator_mask_zero(&mask); 1129 1130 va_start(var, num_valuators); 1131 for (i = 0; i < num_valuators; i++) 1132 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1133 va_end(var); 1134 1135 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1136} 1137 1138void 1139xf86PostButtonEventP(DeviceIntPtr device, 1140 int is_absolute, 1141 int button, 1142 int is_down, 1143 int first_valuator, 1144 int num_valuators, 1145 const int *valuators) 1146{ 1147 ValuatorMask mask; 1148 1149 XI_VERIFY_VALUATORS(num_valuators); 1150 1151 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1152 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1153} 1154 1155void 1156xf86PostButtonEventM(DeviceIntPtr device, 1157 int is_absolute, 1158 int button, 1159 int is_down, 1160 const ValuatorMask *mask) 1161{ 1162 int i = 0, nevents = 0; 1163 int flags = 0; 1164 1165 if (valuator_mask_num_valuators(mask) > 0) 1166 { 1167 if (is_absolute) 1168 flags = POINTER_ABSOLUTE; 1169 else 1170 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1171 } 1172 1173#if XFreeXDGA 1174 if (miPointerGetScreen(device)) { 1175 int index = miPointerGetScreen(device)->myNum; 1176 1177 if (DGAStealButtonEvent(device, index, button, is_down)) 1178 return; 1179 } 1180#endif 1181 1182 nevents = GetPointerEvents(xf86Events, device, 1183 is_down ? ButtonPress : ButtonRelease, button, 1184 flags, mask); 1185 1186 for (i = 0; i < nevents; i++) 1187 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1188 1189} 1190 1191void 1192xf86PostKeyEvent(DeviceIntPtr device, 1193 unsigned int key_code, 1194 int is_down, 1195 int is_absolute, 1196 int first_valuator, 1197 int num_valuators, 1198 ...) 1199{ 1200 va_list var; 1201 int i = 0; 1202 ValuatorMask mask; 1203 1204 XI_VERIFY_VALUATORS(num_valuators); 1205 1206 valuator_mask_zero(&mask); 1207 1208 va_start(var, num_valuators); 1209 for (i = 0; i < num_valuators; i++) 1210 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1211 va_end(var); 1212 1213 xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); 1214} 1215 1216void 1217xf86PostKeyEventP(DeviceIntPtr device, 1218 unsigned int key_code, 1219 int is_down, 1220 int is_absolute, 1221 int first_valuator, 1222 int num_valuators, 1223 const int *valuators) 1224{ 1225 ValuatorMask mask; 1226 1227 XI_VERIFY_VALUATORS(num_valuators); 1228 1229 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1230 xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); 1231} 1232 1233void 1234xf86PostKeyEventM(DeviceIntPtr device, 1235 unsigned int key_code, 1236 int is_down, 1237 int is_absolute, 1238 const ValuatorMask *mask) 1239{ 1240 int i = 0, nevents = 0; 1241 1242#if XFreeXDGA 1243 DeviceIntPtr pointer; 1244 1245 /* Some pointers send key events, paired device is wrong then. */ 1246 pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); 1247 if (miPointerGetScreen(pointer)) { 1248 int index = miPointerGetScreen(pointer)->myNum; 1249 1250 if (DGAStealKeyEvent(device, index, key_code, is_down)) 1251 return; 1252 } 1253#endif 1254 1255 if (is_absolute) { 1256 nevents = GetKeyboardValuatorEvents(xf86Events, device, 1257 is_down ? KeyPress : KeyRelease, 1258 key_code, mask); 1259 } 1260 else { 1261 nevents = GetKeyboardEvents(xf86Events, device, 1262 is_down ? KeyPress : KeyRelease, 1263 key_code); 1264 } 1265 1266 for (i = 0; i < nevents; i++) 1267 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1268} 1269 1270void 1271xf86PostKeyboardEvent(DeviceIntPtr device, 1272 unsigned int key_code, 1273 int is_down) 1274{ 1275 ValuatorMask mask; 1276 1277 valuator_mask_zero(&mask); 1278 xf86PostKeyEventM(device, key_code, is_down, 0, &mask); 1279} 1280 1281InputInfoPtr 1282xf86FirstLocalDevice(void) 1283{ 1284 return xf86InputDevs; 1285} 1286 1287/* 1288 * Cx - raw data from touch screen 1289 * to_max - scaled highest dimension 1290 * (remember, this is of rows - 1 because of 0 origin) 1291 * to_min - scaled lowest dimension 1292 * from_max - highest raw value from touch screen calibration 1293 * from_min - lowest raw value from touch screen calibration 1294 * 1295 * This function is the same for X or Y coordinates. 1296 * You may have to reverse the high and low values to compensate for 1297 * different orgins on the touch screen vs X. 1298 * 1299 * e.g. to scale from device coordinates into screen coordinates, call 1300 * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); 1301 */ 1302 1303int 1304xf86ScaleAxis(int Cx, 1305 int to_max, 1306 int to_min, 1307 int from_max, 1308 int from_min ) 1309{ 1310 int X; 1311 int64_t to_width = to_max - to_min; 1312 int64_t from_width = from_max - from_min; 1313 1314 if (from_width) { 1315 X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); 1316 } 1317 else { 1318 X = 0; 1319 ErrorF ("Divide by Zero in xf86ScaleAxis\n"); 1320 } 1321 1322 if (X > to_max) 1323 X = to_max; 1324 if (X < to_min) 1325 X = to_min; 1326 1327 return X; 1328} 1329 1330/* 1331 * This function checks the given screen against the current screen and 1332 * makes changes if appropriate. It should be called from an XInput driver's 1333 * ReadInput function before any events are posted, if the device is screen 1334 * specific like a touch screen. 1335 */ 1336void 1337xf86XInputSetScreen(InputInfoPtr pInfo, 1338 int screen_number, 1339 int x, 1340 int y) 1341{ 1342 if (miPointerGetScreen(pInfo->dev) != 1343 screenInfo.screens[screen_number]) { 1344 miPointerSetScreen(pInfo->dev, screen_number, x, y); 1345 } 1346} 1347 1348 1349void 1350xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, 1351 int resolution, int min_res, int max_res, int mode) 1352{ 1353 if (!dev || !dev->valuator) 1354 return; 1355 1356 InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, 1357 max_res, mode); 1358} 1359 1360/* 1361 * Set the valuator values to be in synch with dix/event.c 1362 * DefineInitialRootWindow(). 1363 */ 1364void 1365xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) 1366{ 1367 if (axnum == 0) { 1368 dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 1369 dev->last.valuators[0] = dev->valuator->axisVal[0]; 1370 } 1371 else if (axnum == 1) { 1372 dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 1373 dev->last.valuators[1] = dev->valuator->axisVal[1]; 1374 } 1375} 1376 1377 1378/** 1379 * Deactivate a device. Call this function from the driver if you receive a 1380 * read error or something else that spoils your day. 1381 * Device will be moved to the off_devices list, but it will still be there 1382 * until you really clean up after it. 1383 * Notifies the client about an inactive device. 1384 * 1385 * @param panic True if device is unrecoverable and needs to be removed. 1386 */ 1387void 1388xf86DisableDevice(DeviceIntPtr dev, Bool panic) 1389{ 1390 if(!panic) 1391 { 1392 DisableDevice(dev, TRUE); 1393 } else 1394 { 1395 SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); 1396 DeleteInputDeviceRequest(dev); 1397 } 1398} 1399 1400/** 1401 * Reactivate a device. Call this function from the driver if you just found 1402 * out that the read error wasn't quite that bad after all. 1403 * Device will be re-activated, and an event sent to the client. 1404 */ 1405void 1406xf86EnableDevice(DeviceIntPtr dev) 1407{ 1408 EnableDevice(dev, TRUE); 1409} 1410 1411/* end of xf86Xinput.c */ 1412