xf86Xinput.c revision 706f2543
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 RemoveDevice(dev, TRUE); 829 rval = BadMatch; 830 goto unwind; 831 } 832 /* send enter/leave event, update sprite window */ 833 CheckMotion(NULL, dev); 834 OsReleaseSignals(); 835 } 836 837 *pdev = dev; 838 return Success; 839 840unwind: 841 if(pInfo) { 842 if(drv && drv->UnInit) 843 drv->UnInit(drv, pInfo, 0); 844 else 845 xf86DeleteInput(pInfo, 0); 846 } 847 return rval; 848} 849 850int 851NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, 852 DeviceIntPtr *pdev) 853{ 854 InputInfoPtr pInfo = NULL; 855 InputOption *option = NULL; 856 int rval = Success; 857 int is_auto = 0; 858 859 pInfo = xf86AllocateInput(); 860 if (!pInfo) 861 return BadAlloc; 862 863 for (option = options; option; option = option->next) { 864 if (strcasecmp(option->key, "driver") == 0) { 865 if (pInfo->driver) { 866 rval = BadRequest; 867 goto unwind; 868 } 869 pInfo->driver = xstrdup(option->value); 870 if (!pInfo->driver) { 871 rval = BadAlloc; 872 goto unwind; 873 } 874 } 875 876 if (strcasecmp(option->key, "name") == 0 || 877 strcasecmp(option->key, "identifier") == 0) { 878 if (pInfo->name) { 879 rval = BadRequest; 880 goto unwind; 881 } 882 pInfo->name = xstrdup(option->value); 883 if (!pInfo->name) { 884 rval = BadAlloc; 885 goto unwind; 886 } 887 } 888 889 if (strcmp(option->key, "_source") == 0 && 890 (strcmp(option->value, "server/hal") == 0 || 891 strcmp(option->value, "server/udev") == 0)) { 892 is_auto = 1; 893 if (!xf86Info.autoAddDevices) { 894 rval = BadMatch; 895 goto unwind; 896 } 897 } 898 } 899 900 for (option = options; option; option = option->next) { 901 /* Steal option key/value strings from the provided list. 902 * We need those strings, the InputOption list doesn't. */ 903 pInfo->options = xf86addNewOption(pInfo->options, 904 option->key, option->value); 905 option->key = NULL; 906 option->value = NULL; 907 } 908 909 /* Apply InputClass settings */ 910 if (attrs) { 911 if (IgnoreInputClass(pInfo, attrs)) { 912 rval = BadIDChoice; 913 goto unwind; 914 } 915 916 rval = MergeInputClasses(pInfo, attrs); 917 if (rval != Success) 918 goto unwind; 919 920 pInfo->attrs = DuplicateInputAttributes(attrs); 921 } 922 923 if (!pInfo->name) { 924 xf86Msg(X_INFO, "No identifier specified, ignoring this device.\n"); 925 rval = BadRequest; 926 goto unwind; 927 } 928 929 if (!pInfo->driver) { 930 xf86Msg(X_INFO, "No input driver specified, ignoring this device.\n"); 931 xf86Msg(X_INFO, "This device may have been added with another device file.\n"); 932 rval = BadRequest; 933 goto unwind; 934 } 935 936 rval = xf86NewInputDevice(pInfo, pdev, 937 (!is_auto || (is_auto && xf86Info.autoEnableDevices))); 938 939 return rval; 940 941unwind: 942 if (is_auto && !xf86Info.autoAddDevices) 943 xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); 944 xf86DeleteInput(pInfo, 0); 945 return rval; 946} 947 948void 949DeleteInputDeviceRequest(DeviceIntPtr pDev) 950{ 951 InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; 952 InputDriverPtr drv = NULL; 953 Bool isMaster = IsMaster(pDev); 954 955 if (pInfo) /* need to get these before RemoveDevice */ 956 drv = pInfo->drv; 957 958 OsBlockSignals(); 959 RemoveDevice(pDev, TRUE); 960 961 if (!isMaster && pInfo != NULL) 962 { 963 if(drv->UnInit) 964 drv->UnInit(drv, pInfo, 0); 965 else 966 xf86DeleteInput(pInfo, 0); 967 } 968 OsReleaseSignals(); 969} 970 971/* 972 * convenient functions to post events 973 */ 974 975void 976xf86PostMotionEvent(DeviceIntPtr device, 977 int is_absolute, 978 int first_valuator, 979 int num_valuators, 980 ...) 981{ 982 va_list var; 983 int i = 0; 984 ValuatorMask mask; 985 986 XI_VERIFY_VALUATORS(num_valuators); 987 988 valuator_mask_zero(&mask); 989 va_start(var, num_valuators); 990 for (i = 0; i < num_valuators; i++) 991 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 992 va_end(var); 993 994 xf86PostMotionEventM(device, is_absolute, &mask); 995} 996 997void 998xf86PostMotionEventP(DeviceIntPtr device, 999 int is_absolute, 1000 int first_valuator, 1001 int num_valuators, 1002 const int *valuators) 1003{ 1004 ValuatorMask mask; 1005 1006 XI_VERIFY_VALUATORS(num_valuators); 1007 1008 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1009 xf86PostMotionEventM(device, is_absolute, &mask); 1010} 1011 1012void 1013xf86PostMotionEventM(DeviceIntPtr device, 1014 int is_absolute, 1015 const ValuatorMask *mask) 1016{ 1017 int i = 0, nevents = 0; 1018 DeviceEvent *event; 1019 int flags = 0; 1020 1021 if (valuator_mask_num_valuators(mask) > 0) 1022 { 1023 if (is_absolute) 1024 flags = POINTER_ABSOLUTE; 1025 else 1026 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1027 } 1028 1029#if XFreeXDGA 1030 /* The evdev driver may not always send all axes across. */ 1031 if (valuator_mask_isset(mask, 0) || 1032 valuator_mask_isset(mask, 1)) 1033 if (miPointerGetScreen(device)) { 1034 int index = miPointerGetScreen(device)->myNum; 1035 int dx = 0, dy = 0; 1036 1037 if (valuator_mask_isset(mask, 0)) 1038 { 1039 dx = valuator_mask_get(mask, 0); 1040 if (is_absolute) 1041 dx -= device->last.valuators[0]; 1042 } 1043 1044 if (valuator_mask_isset(mask, 1)) 1045 { 1046 dy = valuator_mask_get(mask, 1); 1047 if (is_absolute) 1048 dy -= device->last.valuators[1]; 1049 } 1050 1051 if (DGAStealMotionEvent(device, index, dx, dy)) 1052 return; 1053 } 1054#endif 1055 1056 nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); 1057 1058 for (i = 0; i < nevents; i++) { 1059 event = (DeviceEvent*)((xf86Events + i)->event); 1060 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1061 } 1062} 1063 1064void 1065xf86PostProximityEvent(DeviceIntPtr device, 1066 int is_in, 1067 int first_valuator, 1068 int num_valuators, 1069 ...) 1070{ 1071 va_list var; 1072 int i; 1073 ValuatorMask mask; 1074 1075 XI_VERIFY_VALUATORS(num_valuators); 1076 1077 valuator_mask_zero(&mask); 1078 va_start(var, num_valuators); 1079 for (i = 0; i < num_valuators; i++) 1080 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1081 va_end(var); 1082 1083 xf86PostProximityEventM(device, is_in, &mask); 1084} 1085 1086void 1087xf86PostProximityEventP(DeviceIntPtr device, 1088 int is_in, 1089 int first_valuator, 1090 int num_valuators, 1091 const int *valuators) 1092{ 1093 ValuatorMask mask; 1094 1095 XI_VERIFY_VALUATORS(num_valuators); 1096 1097 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1098 xf86PostProximityEventM(device, is_in, &mask); 1099} 1100 1101void 1102xf86PostProximityEventM(DeviceIntPtr device, 1103 int is_in, 1104 const ValuatorMask *mask) 1105{ 1106 int i, nevents; 1107 1108 nevents = GetProximityEvents(xf86Events, device, 1109 is_in ? ProximityIn : ProximityOut, mask); 1110 for (i = 0; i < nevents; i++) 1111 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1112 1113} 1114 1115void 1116xf86PostButtonEvent(DeviceIntPtr device, 1117 int is_absolute, 1118 int button, 1119 int is_down, 1120 int first_valuator, 1121 int num_valuators, 1122 ...) 1123{ 1124 va_list var; 1125 ValuatorMask mask; 1126 int i = 0; 1127 1128 XI_VERIFY_VALUATORS(num_valuators); 1129 1130 valuator_mask_zero(&mask); 1131 1132 va_start(var, num_valuators); 1133 for (i = 0; i < num_valuators; i++) 1134 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1135 va_end(var); 1136 1137 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1138} 1139 1140void 1141xf86PostButtonEventP(DeviceIntPtr device, 1142 int is_absolute, 1143 int button, 1144 int is_down, 1145 int first_valuator, 1146 int num_valuators, 1147 const int *valuators) 1148{ 1149 ValuatorMask mask; 1150 1151 XI_VERIFY_VALUATORS(num_valuators); 1152 1153 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1154 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1155} 1156 1157void 1158xf86PostButtonEventM(DeviceIntPtr device, 1159 int is_absolute, 1160 int button, 1161 int is_down, 1162 const ValuatorMask *mask) 1163{ 1164 int i = 0, nevents = 0; 1165 int flags = 0; 1166 1167 if (valuator_mask_num_valuators(mask) > 0) 1168 { 1169 if (is_absolute) 1170 flags = POINTER_ABSOLUTE; 1171 else 1172 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1173 } 1174 1175#if XFreeXDGA 1176 if (miPointerGetScreen(device)) { 1177 int index = miPointerGetScreen(device)->myNum; 1178 1179 if (DGAStealButtonEvent(device, index, button, is_down)) 1180 return; 1181 } 1182#endif 1183 1184 nevents = GetPointerEvents(xf86Events, device, 1185 is_down ? ButtonPress : ButtonRelease, button, 1186 flags, mask); 1187 1188 for (i = 0; i < nevents; i++) 1189 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1190 1191} 1192 1193void 1194xf86PostKeyEvent(DeviceIntPtr device, 1195 unsigned int key_code, 1196 int is_down, 1197 int is_absolute, 1198 int first_valuator, 1199 int num_valuators, 1200 ...) 1201{ 1202 va_list var; 1203 int i = 0; 1204 ValuatorMask mask; 1205 1206 XI_VERIFY_VALUATORS(num_valuators); 1207 1208 valuator_mask_zero(&mask); 1209 1210 va_start(var, num_valuators); 1211 for (i = 0; i < num_valuators; i++) 1212 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1213 va_end(var); 1214 1215 xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); 1216} 1217 1218void 1219xf86PostKeyEventP(DeviceIntPtr device, 1220 unsigned int key_code, 1221 int is_down, 1222 int is_absolute, 1223 int first_valuator, 1224 int num_valuators, 1225 const int *valuators) 1226{ 1227 ValuatorMask mask; 1228 1229 XI_VERIFY_VALUATORS(num_valuators); 1230 1231 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1232 xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); 1233} 1234 1235void 1236xf86PostKeyEventM(DeviceIntPtr device, 1237 unsigned int key_code, 1238 int is_down, 1239 int is_absolute, 1240 const ValuatorMask *mask) 1241{ 1242 int i = 0, nevents = 0; 1243 1244#if XFreeXDGA 1245 DeviceIntPtr pointer; 1246 1247 /* Some pointers send key events, paired device is wrong then. */ 1248 pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); 1249 if (miPointerGetScreen(pointer)) { 1250 int index = miPointerGetScreen(pointer)->myNum; 1251 1252 if (DGAStealKeyEvent(device, index, key_code, is_down)) 1253 return; 1254 } 1255#endif 1256 1257 if (is_absolute) { 1258 nevents = GetKeyboardValuatorEvents(xf86Events, device, 1259 is_down ? KeyPress : KeyRelease, 1260 key_code, mask); 1261 } 1262 else { 1263 nevents = GetKeyboardEvents(xf86Events, device, 1264 is_down ? KeyPress : KeyRelease, 1265 key_code); 1266 } 1267 1268 for (i = 0; i < nevents; i++) 1269 mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1270} 1271 1272void 1273xf86PostKeyboardEvent(DeviceIntPtr device, 1274 unsigned int key_code, 1275 int is_down) 1276{ 1277 ValuatorMask mask; 1278 1279 valuator_mask_zero(&mask); 1280 xf86PostKeyEventM(device, key_code, is_down, 0, &mask); 1281} 1282 1283InputInfoPtr 1284xf86FirstLocalDevice(void) 1285{ 1286 return xf86InputDevs; 1287} 1288 1289/* 1290 * Cx - raw data from touch screen 1291 * to_max - scaled highest dimension 1292 * (remember, this is of rows - 1 because of 0 origin) 1293 * to_min - scaled lowest dimension 1294 * from_max - highest raw value from touch screen calibration 1295 * from_min - lowest raw value from touch screen calibration 1296 * 1297 * This function is the same for X or Y coordinates. 1298 * You may have to reverse the high and low values to compensate for 1299 * different orgins on the touch screen vs X. 1300 * 1301 * e.g. to scale from device coordinates into screen coordinates, call 1302 * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); 1303 */ 1304 1305int 1306xf86ScaleAxis(int Cx, 1307 int to_max, 1308 int to_min, 1309 int from_max, 1310 int from_min ) 1311{ 1312 int X; 1313 int64_t to_width = to_max - to_min; 1314 int64_t from_width = from_max - from_min; 1315 1316 if (from_width) { 1317 X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); 1318 } 1319 else { 1320 X = 0; 1321 ErrorF ("Divide by Zero in xf86ScaleAxis\n"); 1322 } 1323 1324 if (X > to_max) 1325 X = to_max; 1326 if (X < to_min) 1327 X = to_min; 1328 1329 return X; 1330} 1331 1332/* 1333 * This function checks the given screen against the current screen and 1334 * makes changes if appropriate. It should be called from an XInput driver's 1335 * ReadInput function before any events are posted, if the device is screen 1336 * specific like a touch screen. 1337 */ 1338void 1339xf86XInputSetScreen(InputInfoPtr pInfo, 1340 int screen_number, 1341 int x, 1342 int y) 1343{ 1344 if (miPointerGetScreen(pInfo->dev) != 1345 screenInfo.screens[screen_number]) { 1346 miPointerSetScreen(pInfo->dev, screen_number, x, y); 1347 } 1348} 1349 1350 1351void 1352xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, 1353 int resolution, int min_res, int max_res, int mode) 1354{ 1355 if (!dev || !dev->valuator) 1356 return; 1357 1358 InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, 1359 max_res, mode); 1360} 1361 1362/* 1363 * Set the valuator values to be in synch with dix/event.c 1364 * DefineInitialRootWindow(). 1365 */ 1366void 1367xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) 1368{ 1369 if (axnum == 0) { 1370 dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 1371 dev->last.valuators[0] = dev->valuator->axisVal[0]; 1372 } 1373 else if (axnum == 1) { 1374 dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 1375 dev->last.valuators[1] = dev->valuator->axisVal[1]; 1376 } 1377} 1378 1379 1380/** 1381 * Deactivate a device. Call this function from the driver if you receive a 1382 * read error or something else that spoils your day. 1383 * Device will be moved to the off_devices list, but it will still be there 1384 * until you really clean up after it. 1385 * Notifies the client about an inactive device. 1386 * 1387 * @param panic True if device is unrecoverable and needs to be removed. 1388 */ 1389void 1390xf86DisableDevice(DeviceIntPtr dev, Bool panic) 1391{ 1392 if(!panic) 1393 { 1394 DisableDevice(dev, TRUE); 1395 } else 1396 { 1397 SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); 1398 DeleteInputDeviceRequest(dev); 1399 } 1400} 1401 1402/** 1403 * Reactivate a device. Call this function from the driver if you just found 1404 * out that the read error wasn't quite that bad after all. 1405 * Device will be re-activated, and an event sent to the client. 1406 */ 1407void 1408xf86EnableDevice(DeviceIntPtr dev) 1409{ 1410 EnableDevice(dev, TRUE); 1411} 1412 1413/* end of xf86Xinput.c */ 1414