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