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#include "systemd-logind.h" 67 68#include "exevents.h" /* AddInputDevice */ 69#include "exglobals.h" 70#include "eventstr.h" 71#include "inpututils.h" 72#include "optionstr.h" 73 74#include <string.h> /* InputClassMatches */ 75#ifdef HAVE_FNMATCH_H 76#include <fnmatch.h> 77#endif 78#ifdef HAVE_SYS_UTSNAME_H 79#include <sys/utsname.h> 80#endif 81 82#include <stdarg.h> 83#include <stdint.h> /* for int64_t */ 84#include <sys/types.h> 85#include <sys/stat.h> 86#include <unistd.h> 87#ifdef HAVE_SYS_SYSMACROS_H 88#include <sys/sysmacros.h> 89#endif 90#ifdef HAVE_SYS_MKDEV_H 91#include <sys/mkdev.h> /* for major() & minor() on Solaris */ 92#endif 93 94#include "mi.h" 95 96#include <ptrveloc.h> /* dix pointer acceleration */ 97#include <xserver-properties.h> 98 99#ifdef XFreeXDGA 100#include "dgaproc.h" 101#endif 102 103#include "xkbsrv.h" 104 105/* Valuator verification macro */ 106#define XI_VERIFY_VALUATORS(num_valuators) \ 107 if (num_valuators > MAX_VALUATORS) { \ 108 xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ 109 " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ 110 return; \ 111 } 112 113static int 114 xf86InputDevicePostInit(DeviceIntPtr dev); 115 116typedef struct { 117 struct xorg_list node; 118 InputInfoPtr pInfo; 119} PausedInputDeviceRec; 120typedef PausedInputDeviceRec *PausedInputDevicePtr; 121 122static struct xorg_list new_input_devices_list = { 123 .next = &new_input_devices_list, 124 .prev = &new_input_devices_list, 125}; 126 127/** 128 * Eval config and modify DeviceVelocityRec accordingly 129 */ 130static void 131ProcessVelocityConfiguration(DeviceIntPtr pDev, const char *devname, void *list, 132 DeviceVelocityPtr s) 133{ 134 int tempi; 135 float tempf; 136 Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); 137 Atom prop; 138 139 if (!s) 140 return; 141 142 /* common settings (available via device properties) */ 143 tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); 144 if (tempf != 1.0) { 145 xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", 146 devname, tempf); 147 prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); 148 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 149 PropModeReplace, 1, &tempf, FALSE); 150 } 151 152 tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); 153 if (tempf > 1.0) { 154 xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", 155 devname, tempf); 156 prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); 157 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 158 PropModeReplace, 1, &tempf, FALSE); 159 } 160 161 /* select profile by number */ 162 tempi = xf86SetIntOption(list, "AccelerationProfile", 163 s->statistics.profile_number); 164 165 prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); 166 if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, 167 PropModeReplace, 1, &tempi, FALSE) == Success) { 168 xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, 169 tempi); 170 } 171 else { 172 xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", 173 devname, tempi); 174 } 175 176 /* set scaling */ 177 tempf = xf86SetRealOption(list, "ExpectedRate", 0); 178 prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); 179 if (tempf > 0) { 180 tempf = 1000.0 / tempf; 181 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 182 PropModeReplace, 1, &tempf, FALSE); 183 } 184 else { 185 tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); 186 XIChangeDeviceProperty(pDev, prop, float_prop, 32, 187 PropModeReplace, 1, &tempf, FALSE); 188 } 189 190 tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); 191 if (tempi > 1) 192 InitTrackers(s, tempi); 193 194 s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", 195 s->initial_range); 196 197 s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); 198 199 tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); 200 if (tempf >= 0) { 201 xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", 202 devname, tempf * 100.0); 203 s->max_rel_diff = tempf; 204 } 205 206 /* Configure softening. If const deceleration is used, this is expected 207 * to provide better subpixel information so we enable 208 * softening by default only if ConstantDeceleration is not used 209 */ 210 s->use_softening = xf86SetBoolOption(list, "Softening", 211 s->const_acceleration == 1.0); 212 213 s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", 214 s->average_accel); 215 216 s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); 217} 218 219static void 220ApplyAccelerationSettings(DeviceIntPtr dev) 221{ 222 int scheme, i; 223 DeviceVelocityPtr pVel; 224 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 225 char *schemeStr; 226 227 if (dev->valuator && dev->ptrfeed) { 228 schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); 229 230 scheme = dev->valuator->accelScheme.number; 231 232 if (!xf86NameCmp(schemeStr, "predictable")) 233 scheme = PtrAccelPredictable; 234 235 if (!xf86NameCmp(schemeStr, "lightweight")) 236 scheme = PtrAccelLightweight; 237 238 if (!xf86NameCmp(schemeStr, "none")) 239 scheme = PtrAccelNoOp; 240 241 /* reinit scheme if needed */ 242 if (dev->valuator->accelScheme.number != scheme) { 243 if (dev->valuator->accelScheme.AccelCleanupProc) { 244 dev->valuator->accelScheme.AccelCleanupProc(dev); 245 } 246 247 if (InitPointerAccelerationScheme(dev, scheme)) { 248 xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", 249 pInfo->name, schemeStr, scheme); 250 } 251 else { 252 xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", 253 pInfo->name, schemeStr); 254 scheme = dev->valuator->accelScheme.number; 255 } 256 } 257 else { 258 xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", 259 pInfo->name, scheme); 260 } 261 262 free(schemeStr); 263 264 /* process special configuration */ 265 switch (scheme) { 266 case PtrAccelPredictable: 267 pVel = GetDevicePredictableAccelData(dev); 268 ProcessVelocityConfiguration(dev, pInfo->name, pInfo->options, 269 pVel); 270 break; 271 } 272 273 i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", 274 dev->ptrfeed->ctrl.num); 275 if (i >= 0) 276 dev->ptrfeed->ctrl.num = i; 277 278 i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", 279 dev->ptrfeed->ctrl.den); 280 if (i > 0) 281 dev->ptrfeed->ctrl.den = i; 282 283 i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", 284 dev->ptrfeed->ctrl.threshold); 285 if (i >= 0) 286 dev->ptrfeed->ctrl.threshold = i; 287 288 xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", 289 pInfo->name, ((float) dev->ptrfeed->ctrl.num) / 290 ((float) dev->ptrfeed->ctrl.den)); 291 xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", 292 pInfo->name, dev->ptrfeed->ctrl.threshold); 293 } 294} 295 296static void 297ApplyTransformationMatrix(DeviceIntPtr dev) 298{ 299 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 300 char *str; 301 int rc; 302 float matrix[9] = { 0 }; 303 304 if (!dev->valuator) 305 return; 306 307 str = xf86SetStrOption(pInfo->options, "TransformationMatrix", NULL); 308 if (!str) 309 return; 310 311 rc = sscanf(str, "%f %f %f %f %f %f %f %f %f", &matrix[0], &matrix[1], 312 &matrix[2], &matrix[3], &matrix[4], &matrix[5], &matrix[6], 313 &matrix[7], &matrix[8]); 314 if (rc != 9) { 315 xf86Msg(X_ERROR, 316 "%s: invalid format for transformation matrix. Ignoring configuration.\n", 317 pInfo->name); 318 return; 319 } 320 321 XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), 322 XIGetKnownProperty(XATOM_FLOAT), 32, 323 PropModeReplace, 9, matrix, FALSE); 324} 325 326static void 327ApplyAutoRepeat(DeviceIntPtr dev) 328{ 329 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 330 XkbSrvInfoPtr xkbi; 331 char *repeatStr; 332 long delay, rate; 333 334 if (!dev->key) 335 return; 336 337 xkbi = dev->key->xkbInfo; 338 339 repeatStr = xf86SetStrOption(pInfo->options, "AutoRepeat", NULL); 340 if (!repeatStr) 341 return; 342 343 if (sscanf(repeatStr, "%ld %ld", &delay, &rate) != 2) { 344 xf86Msg(X_ERROR, "\"%s\" is not a valid AutoRepeat value\n", repeatStr); 345 return; 346 } 347 348 xf86Msg(X_CONFIG, "AutoRepeat: %ld %ld\n", delay, rate); 349 xkbi->desc->ctrls->repeat_delay = delay; 350 xkbi->desc->ctrls->repeat_interval = rate; 351} 352 353/*********************************************************************** 354 * 355 * xf86ProcessCommonOptions -- 356 * 357 * Process global options. 358 * 359 *********************************************************************** 360 */ 361void 362xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr list) 363{ 364 if (xf86SetBoolOption(list, "Floating", 0) || 365 !xf86SetBoolOption(list, "AlwaysCore", 1) || 366 !xf86SetBoolOption(list, "SendCoreEvents", 1) || 367 !xf86SetBoolOption(list, "CorePointer", 1) || 368 !xf86SetBoolOption(list, "CoreKeyboard", 1)) { 369 xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); 370 } 371 else { 372 pInfo->flags |= XI86_ALWAYS_CORE; 373 xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); 374 } 375} 376 377/*********************************************************************** 378 * 379 * xf86ActivateDevice -- 380 * 381 * Initialize an input device. 382 * 383 * Returns TRUE on success, or FALSE otherwise. 384 *********************************************************************** 385 */ 386static DeviceIntPtr 387xf86ActivateDevice(InputInfoPtr pInfo) 388{ 389 DeviceIntPtr dev; 390 Atom atom; 391 392 dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); 393 394 if (dev == NULL) { 395 xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", pInfo->name); 396 pInfo->dev = NULL; 397 return NULL; 398 } 399 400 atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); 401 AssignTypeAndName(dev, atom, pInfo->name); 402 dev->public.devicePrivate = pInfo; 403 pInfo->dev = dev; 404 405 dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; 406 dev->type = SLAVE; 407 dev->spriteInfo->spriteOwner = FALSE; 408 409 dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); 410 411 if (serverGeneration == 1) 412 xf86Msg(X_INFO, 413 "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n", 414 pInfo->name, pInfo->type_name, dev->id); 415 416 return dev; 417} 418 419/**************************************************************************** 420 * 421 * Caller: ProcXSetDeviceMode 422 * 423 * Change the mode of an extension device. 424 * This function is used to change the mode of a device from reporting 425 * relative motion to reporting absolute positional information, and 426 * vice versa. 427 * The default implementation below is that no such devices are supported. 428 * 429 *********************************************************************** 430 */ 431 432int 433SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode) 434{ 435 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 436 437 if (pInfo->switch_mode) { 438 return (*pInfo->switch_mode) (client, dev, mode); 439 } 440 else 441 return BadMatch; 442} 443 444/*********************************************************************** 445 * 446 * Caller: ProcXSetDeviceValuators 447 * 448 * Set the value of valuators on an extension input device. 449 * This function is used to set the initial value of valuators on 450 * those input devices that are capable of reporting either relative 451 * motion or an absolute position, and allow an initial position to be set. 452 * The default implementation below is that no such devices are supported. 453 * 454 *********************************************************************** 455 */ 456 457int 458SetDeviceValuators(ClientPtr client, DeviceIntPtr dev, int *valuators, 459 int first_valuator, int num_valuators) 460{ 461 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 462 463 if (pInfo->set_device_valuators) 464 return (*pInfo->set_device_valuators) (pInfo, valuators, first_valuator, 465 num_valuators); 466 467 return BadMatch; 468} 469 470/*********************************************************************** 471 * 472 * Caller: ProcXChangeDeviceControl 473 * 474 * Change the specified device controls on an extension input device. 475 * 476 *********************************************************************** 477 */ 478 479int 480ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev, xDeviceCtl * control) 481{ 482 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 483 484 if (!pInfo->control_proc) { 485 switch (control->control) { 486 case DEVICE_CORE: 487 case DEVICE_ABS_CALIB: 488 case DEVICE_ABS_AREA: 489 return BadMatch; 490 case DEVICE_RESOLUTION: 491 case DEVICE_ENABLE: 492 return Success; 493 default: 494 return BadMatch; 495 } 496 } 497 else { 498 return (*pInfo->control_proc) (pInfo, control); 499 } 500} 501 502/* 503 * Get the operating system name from uname and store it statically to avoid 504 * repeating the system call each time MatchOS is checked. 505 */ 506static const char * 507HostOS(void) 508{ 509#ifdef HAVE_SYS_UTSNAME_H 510 struct utsname name; 511 static char host_os[sizeof(name.sysname)] = ""; 512 513 if (*host_os == '\0') { 514 if (uname(&name) >= 0) 515 strlcpy(host_os, name.sysname, sizeof(host_os)); 516 else { 517 strlcpy(host_os, "unknown", sizeof(host_os)); 518 } 519 } 520 return host_os; 521#else 522 return ""; 523#endif 524} 525 526static int 527match_substring(const char *attr, const char *pattern) 528{ 529 return (strstr(attr, pattern)) ? 0 : -1; 530} 531 532#ifdef HAVE_FNMATCH_H 533static int 534match_pattern(const char *attr, const char *pattern) 535{ 536 return fnmatch(pattern, attr, 0); 537} 538#else 539#define match_pattern match_substring 540#endif 541 542#ifdef HAVE_FNMATCH_H 543static int 544match_path_pattern(const char *attr, const char *pattern) 545{ 546 return fnmatch(pattern, attr, FNM_PATHNAME); 547} 548#else 549#define match_path_pattern match_substring 550#endif 551 552/* 553 * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" 554 * It is convenient that "" in patterns means "no explicit layout" 555 */ 556static int 557match_string_implicit(const char *attr, const char *pattern) 558{ 559 if (strlen(pattern)) { 560 return strcmp(attr, pattern); 561 } 562 else { 563 return strcmp(attr, "(implicit)"); 564 } 565} 566 567/* 568 * Match an attribute against a list of NULL terminated arrays of patterns. 569 * If a pattern in each list entry is matched, return TRUE. 570 */ 571static Bool 572MatchAttrToken(const char *attr, struct xorg_list *patterns, 573 int (*compare) (const char *attr, const char *pattern)) 574{ 575 const xf86MatchGroup *group; 576 577 /* If there are no patterns, accept the match */ 578 if (xorg_list_is_empty(patterns)) 579 return TRUE; 580 581 /* 582 * Iterate the list of patterns ensuring each entry has a 583 * match. Each list entry is a separate Match line of the same type. 584 */ 585 xorg_list_for_each_entry(group, patterns, entry) { 586 char *const *cur; 587 Bool is_negated = group->is_negated; 588 Bool match = is_negated; 589 590 /* If there's a pattern but no attribute, we reject the match for a 591 * MatchFoo directive, and accept it for a NoMatchFoo directive 592 */ 593 if (!attr) 594 return is_negated; 595 596 for (cur = group->values; *cur; cur++) 597 if ((*compare) (attr, *cur) == 0) { 598 match = !is_negated; 599 break; 600 } 601 if (!match) 602 return FALSE; 603 } 604 605 /* All the entries in the list matched the attribute */ 606 return TRUE; 607} 608 609/* 610 * Classes without any Match statements match all devices. Otherwise, all 611 * statements must match. 612 */ 613static Bool 614InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, 615 const InputAttributes * attrs) 616{ 617 /* MatchProduct substring */ 618 if (!MatchAttrToken 619 (attrs->product, &iclass->match_product, match_substring)) 620 return FALSE; 621 622 /* MatchVendor substring */ 623 if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) 624 return FALSE; 625 626 /* MatchDevicePath pattern */ 627 if (!MatchAttrToken 628 (attrs->device, &iclass->match_device, match_path_pattern)) 629 return FALSE; 630 631 /* MatchOS case-insensitive string */ 632 if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) 633 return FALSE; 634 635 /* MatchPnPID pattern */ 636 if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) 637 return FALSE; 638 639 /* MatchUSBID pattern */ 640 if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) 641 return FALSE; 642 643 /* MatchDriver string */ 644 if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) 645 return FALSE; 646 647 /* 648 * MatchTag string 649 * See if any of the device's tags match any of the MatchTag tokens. 650 */ 651 if (!xorg_list_is_empty(&iclass->match_tag)) { 652 char *const *tag; 653 Bool match; 654 655 if (!attrs->tags) 656 return FALSE; 657 for (tag = attrs->tags, match = FALSE; *tag; tag++) { 658 if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { 659 match = TRUE; 660 break; 661 } 662 } 663 if (!match) 664 return FALSE; 665 } 666 667 /* MatchLayout string */ 668 if (!xorg_list_is_empty(&iclass->match_layout)) { 669 if (!MatchAttrToken(xf86ConfigLayout.id, 670 &iclass->match_layout, match_string_implicit)) 671 return FALSE; 672 } 673 674 /* MatchIs* booleans */ 675 if (iclass->is_keyboard.set && 676 iclass->is_keyboard.val != ! !(attrs->flags & (ATTR_KEY|ATTR_KEYBOARD))) 677 return FALSE; 678 if (iclass->is_pointer.set && 679 iclass->is_pointer.val != ! !(attrs->flags & ATTR_POINTER)) 680 return FALSE; 681 if (iclass->is_joystick.set && 682 iclass->is_joystick.val != ! !(attrs->flags & ATTR_JOYSTICK)) 683 return FALSE; 684 if (iclass->is_tablet.set && 685 iclass->is_tablet.val != ! !(attrs->flags & ATTR_TABLET)) 686 return FALSE; 687 if (iclass->is_tablet_pad.set && 688 iclass->is_tablet_pad.val != ! !(attrs->flags & ATTR_TABLET_PAD)) 689 return FALSE; 690 if (iclass->is_touchpad.set && 691 iclass->is_touchpad.val != ! !(attrs->flags & ATTR_TOUCHPAD)) 692 return FALSE; 693 if (iclass->is_touchscreen.set && 694 iclass->is_touchscreen.val != ! !(attrs->flags & ATTR_TOUCHSCREEN)) 695 return FALSE; 696 697 return TRUE; 698} 699 700/* 701 * Merge in any InputClass configurations. Options in each InputClass 702 * section have more priority than the original device configuration as 703 * well as any previous InputClass sections. 704 */ 705static int 706MergeInputClasses(const InputInfoPtr idev, const InputAttributes * attrs) 707{ 708 XF86ConfInputClassPtr cl; 709 XF86OptionPtr classopts; 710 711 for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 712 if (!InputClassMatches(cl, idev, attrs)) 713 continue; 714 715 /* Collect class options and driver settings */ 716 classopts = xf86optionListDup(cl->option_lst); 717 if (cl->driver) { 718 free((void *) idev->driver); 719 idev->driver = xstrdup(cl->driver); 720 if (!idev->driver) { 721 xf86Msg(X_ERROR, "Failed to allocate memory while merging " 722 "InputClass configuration"); 723 return BadAlloc; 724 } 725 classopts = xf86ReplaceStrOption(classopts, "driver", idev->driver); 726 } 727 728 /* Apply options to device with InputClass settings preferred. */ 729 xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", 730 idev->name, cl->identifier); 731 idev->options = xf86optionListMerge(idev->options, classopts); 732 } 733 734 return Success; 735} 736 737/* 738 * Iterate the list of classes and look for Option "Ignore". Return the 739 * value of the last matching class and holler when returning TRUE. 740 */ 741static Bool 742IgnoreInputClass(const InputInfoPtr idev, const InputAttributes * attrs) 743{ 744 XF86ConfInputClassPtr cl; 745 Bool ignore = FALSE; 746 const char *ignore_class; 747 748 for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 749 if (!InputClassMatches(cl, idev, attrs)) 750 continue; 751 if (xf86findOption(cl->option_lst, "Ignore")) { 752 ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); 753 ignore_class = cl->identifier; 754 } 755 } 756 757 if (ignore) 758 xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", 759 idev->name, ignore_class); 760 return ignore; 761} 762 763InputInfoPtr 764xf86AllocateInput(void) 765{ 766 InputInfoPtr pInfo; 767 768 pInfo = calloc(sizeof(*pInfo), 1); 769 if (!pInfo) 770 return NULL; 771 772 pInfo->fd = -1; 773 pInfo->type_name = "UNKNOWN"; 774 775 return pInfo; 776} 777 778/* Append InputInfoRec to the tail of xf86InputDevs. */ 779static void 780xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) 781{ 782 InputInfoPtr *prev = NULL; 783 784 pInfo->drv = drv; 785 pInfo->module = DuplicateModule(drv->module, NULL); 786 787 for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next); 788 789 *prev = pInfo; 790 pInfo->next = NULL; 791 792 xf86CollectInputOptions(pInfo, (const char **) drv->default_options); 793 xf86OptionListReport(pInfo->options); 794 xf86ProcessCommonOptions(pInfo, pInfo->options); 795} 796 797/* 798 * Remove an entry from xf86InputDevs and free all the device's information. 799 */ 800void 801xf86DeleteInput(InputInfoPtr pInp, int flags) 802{ 803 /* First check if the inputdev is valid. */ 804 if (pInp == NULL) 805 return; 806 807 if (pInp->module) 808 UnloadModule(pInp->module); 809 810 /* This should *really* be handled in drv->UnInit(dev) call instead, but 811 * if the driver forgets about it make sure we free it or at least crash 812 * with flying colors */ 813 free(pInp->private); 814 815 FreeInputAttributes(pInp->attrs); 816 817 if (pInp->flags & XI86_SERVER_FD) 818 systemd_logind_release_fd(pInp->major, pInp->minor, pInp->fd); 819 820 /* Remove the entry from the list. */ 821 if (pInp == xf86InputDevs) 822 xf86InputDevs = pInp->next; 823 else { 824 InputInfoPtr p = xf86InputDevs; 825 826 while (p && p->next != pInp) 827 p = p->next; 828 if (p) 829 p->next = pInp->next; 830 /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ 831 } 832 833 free((void *) pInp->driver); 834 free((void *) pInp->name); 835 xf86optionListFree(pInp->options); 836 free(pInp); 837} 838 839/* 840 * Apply backend-specific initialization. Invoked after ActivateDevice(), 841 * i.e. after the driver successfully completed DEVICE_INIT and the device 842 * is advertised. 843 * @param dev the device 844 * @return Success or an error code 845 */ 846static int 847xf86InputDevicePostInit(DeviceIntPtr dev) 848{ 849 ApplyAccelerationSettings(dev); 850 ApplyTransformationMatrix(dev); 851 ApplyAutoRepeat(dev); 852 return Success; 853} 854 855static void 856xf86stat(const char *path, int *maj, int *min) 857{ 858 struct stat st; 859 860 if (stat(path, &st) == -1) 861 return; 862 863 *maj = major(st.st_rdev); 864 *min = minor(st.st_rdev); 865} 866 867static inline InputDriverPtr 868xf86LoadInputDriver(const char *driver_name) 869{ 870 InputDriverPtr drv = NULL; 871 872 /* Memory leak for every attached device if we don't 873 * test if the module is already loaded first */ 874 drv = xf86LookupInputDriver(driver_name); 875 if (!drv) { 876 if (xf86LoadOneModule(driver_name, NULL)) 877 drv = xf86LookupInputDriver(driver_name); 878 } 879 880 return drv; 881} 882 883/** 884 * Create a new input device, activate and enable it. 885 * 886 * Possible return codes: 887 * BadName .. a bad driver name was supplied. 888 * BadImplementation ... The driver does not have a PreInit function. This 889 * is a driver bug. 890 * BadMatch .. device initialization failed. 891 * BadAlloc .. too many input devices 892 * 893 * @param idev The device, already set up with identifier, driver, and the 894 * options. 895 * @param pdev Pointer to the new device, if Success was reported. 896 * @param enable Enable the device after activating it. 897 * 898 * @return Success or an error code 899 */ 900_X_INTERNAL int 901xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) 902{ 903 InputDriverPtr drv = NULL; 904 DeviceIntPtr dev = NULL; 905 Bool paused = FALSE; 906 int rval; 907 char *path = NULL; 908 909 drv = xf86LoadInputDriver(pInfo->driver); 910 if (!drv) { 911 xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); 912 913 if (strlen(FALLBACK_INPUT_DRIVER) > 0) { 914 xf86Msg(X_INFO, "Falling back to input driver `%s'\n", 915 FALLBACK_INPUT_DRIVER); 916 drv = xf86LoadInputDriver(FALLBACK_INPUT_DRIVER); 917 if (drv) { 918 free(pInfo->driver); 919 pInfo->driver = strdup(FALLBACK_INPUT_DRIVER); 920 } 921 } 922 if (!drv) { 923 rval = BadName; 924 goto unwind; 925 } 926 } 927 928 xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, 929 pInfo->name); 930 931 if (!drv->PreInit) { 932 xf86Msg(X_ERROR, 933 "Input driver `%s' has no PreInit function (ignoring)\n", 934 drv->driverName); 935 rval = BadImplementation; 936 goto unwind; 937 } 938 939 path = xf86CheckStrOption(pInfo->options, "Device", NULL); 940 if (path && pInfo->major == 0 && pInfo->minor == 0) 941 xf86stat(path, &pInfo->major, &pInfo->minor); 942 943 if (path && (drv->capabilities & XI86_DRV_CAP_SERVER_FD)){ 944 int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor, 945 path, &paused); 946 if (fd != -1) { 947 if (paused) { 948 /* Put on new_input_devices list for delayed probe */ 949 PausedInputDevicePtr new_device = xnfalloc(sizeof *new_device); 950 new_device->pInfo = pInfo; 951 952 xorg_list_append(&new_device->node, &new_input_devices_list); 953 systemd_logind_release_fd(pInfo->major, pInfo->minor, fd); 954 free(path); 955 return BadMatch; 956 } 957 pInfo->fd = fd; 958 pInfo->flags |= XI86_SERVER_FD; 959 pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd); 960 } 961 } 962 963 free(path); 964 965 xf86AddInput(drv, pInfo); 966 967 input_lock(); 968 rval = drv->PreInit(drv, pInfo, 0); 969 input_unlock(); 970 971 if (rval != Success) { 972 xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); 973 goto unwind; 974 } 975 976 if (!(dev = xf86ActivateDevice(pInfo))) { 977 rval = BadAlloc; 978 goto unwind; 979 } 980 981 rval = ActivateDevice(dev, TRUE); 982 if (rval != Success) { 983 xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 984 RemoveDevice(dev, TRUE); 985 goto unwind; 986 } 987 988 rval = xf86InputDevicePostInit(dev); 989 if (rval != Success) { 990 xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); 991 RemoveDevice(dev, TRUE); 992 goto unwind; 993 } 994 995 /* Enable it if it's properly initialised and we're currently in the VT */ 996 if (enable && dev->inited && dev->startup && xf86VTOwner()) { 997 input_lock(); 998 EnableDevice(dev, TRUE); 999 if (!dev->enabled) { 1000 xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 1001 RemoveDevice(dev, TRUE); 1002 rval = BadMatch; 1003 input_unlock(); 1004 goto unwind; 1005 } 1006 /* send enter/leave event, update sprite window */ 1007 CheckMotion(NULL, dev); 1008 input_unlock(); 1009 } 1010 1011 *pdev = dev; 1012 return Success; 1013 1014 unwind: 1015 if (pInfo) { 1016 if (drv && drv->UnInit) 1017 drv->UnInit(drv, pInfo, 0); 1018 else 1019 xf86DeleteInput(pInfo, 0); 1020 } 1021 return rval; 1022} 1023 1024int 1025NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, 1026 DeviceIntPtr *pdev) 1027{ 1028 InputInfoPtr pInfo = NULL; 1029 InputOption *option = NULL; 1030 int rval = Success; 1031 int is_auto = 0; 1032 1033 pInfo = xf86AllocateInput(); 1034 if (!pInfo) 1035 return BadAlloc; 1036 1037 nt_list_for_each_entry(option, options, list.next) { 1038 const char *key = input_option_get_key(option); 1039 const char *value = input_option_get_value(option); 1040 1041 if (strcasecmp(key, "driver") == 0) { 1042 if (pInfo->driver) { 1043 rval = BadRequest; 1044 goto unwind; 1045 } 1046 pInfo->driver = xstrdup(value); 1047 if (!pInfo->driver) { 1048 rval = BadAlloc; 1049 goto unwind; 1050 } 1051 } 1052 1053 if (strcasecmp(key, "name") == 0 || strcasecmp(key, "identifier") == 0) { 1054 if (pInfo->name) { 1055 rval = BadRequest; 1056 goto unwind; 1057 } 1058 pInfo->name = xstrdup(value); 1059 if (!pInfo->name) { 1060 rval = BadAlloc; 1061 goto unwind; 1062 } 1063 } 1064 1065 if (strcmp(key, "_source") == 0 && 1066 (strcmp(value, "server/hal") == 0 || 1067 strcmp(value, "server/udev") == 0 || 1068 strcmp(value, "server/wscons") == 0)) { 1069 is_auto = 1; 1070 if (!xf86Info.autoAddDevices) { 1071 rval = BadMatch; 1072 goto unwind; 1073 } 1074 } 1075 1076 if (strcmp(key, "major") == 0) 1077 pInfo->major = atoi(value); 1078 1079 if (strcmp(key, "minor") == 0) 1080 pInfo->minor = atoi(value); 1081 } 1082 1083 nt_list_for_each_entry(option, options, list.next) { 1084 /* Copy option key/value strings from the provided list */ 1085 pInfo->options = xf86AddNewOption(pInfo->options, 1086 input_option_get_key(option), 1087 input_option_get_value(option)); 1088 } 1089 1090 /* Apply InputClass settings */ 1091 if (attrs) { 1092 if (IgnoreInputClass(pInfo, attrs)) { 1093 rval = BadIDChoice; 1094 goto unwind; 1095 } 1096 1097 rval = MergeInputClasses(pInfo, attrs); 1098 if (rval != Success) 1099 goto unwind; 1100 1101 pInfo->attrs = DuplicateInputAttributes(attrs); 1102 } 1103 1104 if (!pInfo->name) { 1105 xf86Msg(X_INFO, "No identifier specified, ignoring this device.\n"); 1106 rval = BadRequest; 1107 goto unwind; 1108 } 1109 1110 if (!pInfo->driver) { 1111 xf86Msg(X_INFO, "No input driver specified, ignoring this device.\n"); 1112 xf86Msg(X_INFO, 1113 "This device may have been added with another device file.\n"); 1114 rval = BadRequest; 1115 goto unwind; 1116 } 1117 1118 rval = xf86NewInputDevice(pInfo, pdev, 1119 (!is_auto || 1120 (is_auto && xf86Info.autoEnableDevices))); 1121 1122 return rval; 1123 1124 unwind: 1125 if (is_auto && !xf86Info.autoAddDevices) 1126 xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); 1127 xf86DeleteInput(pInfo, 0); 1128 return rval; 1129} 1130 1131void 1132DeleteInputDeviceRequest(DeviceIntPtr pDev) 1133{ 1134 InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; 1135 InputDriverPtr drv = NULL; 1136 Bool isMaster = IsMaster(pDev); 1137 1138 if (pInfo) /* need to get these before RemoveDevice */ 1139 drv = pInfo->drv; 1140 1141 input_lock(); 1142 RemoveDevice(pDev, TRUE); 1143 1144 if (!isMaster && pInfo != NULL) { 1145 if (drv->UnInit) 1146 drv->UnInit(drv, pInfo, 0); 1147 else 1148 xf86DeleteInput(pInfo, 0); 1149 } 1150 input_unlock(); 1151} 1152 1153void 1154RemoveInputDeviceTraces(const char *config_info) 1155{ 1156 PausedInputDevicePtr d, tmp; 1157 1158 xorg_list_for_each_entry_safe(d, tmp, &new_input_devices_list, node) { 1159 const char *ci = xf86findOptionValue(d->pInfo->options, "config_info"); 1160 if (!ci || strcmp(ci, config_info) != 0) 1161 continue; 1162 1163 xorg_list_del(&d->node); 1164 free(d); 1165 } 1166} 1167 1168/* 1169 * convenient functions to post events 1170 */ 1171 1172void 1173xf86PostMotionEvent(DeviceIntPtr device, 1174 int is_absolute, int first_valuator, int num_valuators, ...) 1175{ 1176 va_list var; 1177 int i = 0; 1178 ValuatorMask mask; 1179 1180 XI_VERIFY_VALUATORS(num_valuators); 1181 1182 valuator_mask_zero(&mask); 1183 va_start(var, num_valuators); 1184 for (i = 0; i < num_valuators; i++) 1185 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1186 1187 va_end(var); 1188 1189 xf86PostMotionEventM(device, is_absolute, &mask); 1190} 1191 1192void 1193xf86PostMotionEventP(DeviceIntPtr device, 1194 int is_absolute, 1195 int first_valuator, 1196 int num_valuators, const int *valuators) 1197{ 1198 ValuatorMask mask; 1199 1200 XI_VERIFY_VALUATORS(num_valuators); 1201 1202 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1203 xf86PostMotionEventM(device, is_absolute, &mask); 1204} 1205 1206static int 1207xf86CheckMotionEvent4DGA(DeviceIntPtr device, int is_absolute, 1208 const ValuatorMask *mask) 1209{ 1210 int stolen = 0; 1211 1212#ifdef XFreeXDGA 1213 ScreenPtr scr = NULL; 1214 int idx = 0, i; 1215 1216 /* The evdev driver may not always send all axes across. */ 1217 if (valuator_mask_isset(mask, 0) || valuator_mask_isset(mask, 1)) { 1218 scr = miPointerGetScreen(device); 1219 if (scr) { 1220 int dx = 0, dy = 0; 1221 1222 idx = scr->myNum; 1223 1224 if (valuator_mask_isset(mask, 0)) { 1225 dx = valuator_mask_get(mask, 0); 1226 if (is_absolute) 1227 dx -= device->last.valuators[0]; 1228 else if (valuator_mask_has_unaccelerated(mask)) 1229 dx = valuator_mask_get_unaccelerated(mask, 0); 1230 } 1231 1232 if (valuator_mask_isset(mask, 1)) { 1233 dy = valuator_mask_get(mask, 1); 1234 if (is_absolute) 1235 dy -= device->last.valuators[1]; 1236 else if (valuator_mask_has_unaccelerated(mask)) 1237 dy = valuator_mask_get_unaccelerated(mask, 1); 1238 } 1239 1240 if (DGAStealMotionEvent(device, idx, dx, dy)) 1241 stolen = 1; 1242 } 1243 } 1244 1245 for (i = 2; i < valuator_mask_size(mask); i++) { 1246 AxisInfoPtr ax; 1247 double incr; 1248 int val, button; 1249 1250 if (i >= device->valuator->numAxes) 1251 break; 1252 1253 if (!valuator_mask_isset(mask, i)) 1254 continue; 1255 1256 ax = &device->valuator->axes[i]; 1257 1258 if (ax->scroll.type == SCROLL_TYPE_NONE) 1259 continue; 1260 1261 if (!scr) { 1262 scr = miPointerGetScreen(device); 1263 if (!scr) 1264 break; 1265 idx = scr->myNum; 1266 } 1267 1268 incr = ax->scroll.increment; 1269 val = valuator_mask_get(mask, i); 1270 1271 if (ax->scroll.type == SCROLL_TYPE_VERTICAL) { 1272 if (incr * val < 0) 1273 button = 4; /* up */ 1274 else 1275 button = 5; /* down */ 1276 } else { /* SCROLL_TYPE_HORIZONTAL */ 1277 if (incr * val < 0) 1278 button = 6; /* left */ 1279 else 1280 button = 7; /* right */ 1281 } 1282 1283 if (DGAStealButtonEvent(device, idx, button, 1) && 1284 DGAStealButtonEvent(device, idx, button, 0)) 1285 stolen = 1; 1286 } 1287 1288#endif 1289 1290 return stolen; 1291} 1292 1293void 1294xf86PostMotionEventM(DeviceIntPtr device, 1295 int is_absolute, const ValuatorMask *mask) 1296{ 1297 int flags = 0; 1298 1299 if (xf86CheckMotionEvent4DGA(device, is_absolute, mask)) 1300 return; 1301 1302 if (valuator_mask_num_valuators(mask) > 0) { 1303 if (is_absolute) 1304 flags = POINTER_ABSOLUTE; 1305 else 1306 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1307 } 1308 1309 QueuePointerEvents(device, MotionNotify, 0, flags, mask); 1310} 1311 1312void 1313xf86PostProximityEvent(DeviceIntPtr device, 1314 int is_in, int first_valuator, int num_valuators, ...) 1315{ 1316 va_list var; 1317 int i; 1318 ValuatorMask mask; 1319 1320 XI_VERIFY_VALUATORS(num_valuators); 1321 1322 valuator_mask_zero(&mask); 1323 va_start(var, num_valuators); 1324 for (i = 0; i < num_valuators; i++) 1325 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1326 1327 va_end(var); 1328 1329 xf86PostProximityEventM(device, is_in, &mask); 1330} 1331 1332void 1333xf86PostProximityEventP(DeviceIntPtr device, 1334 int is_in, 1335 int first_valuator, 1336 int num_valuators, const int *valuators) 1337{ 1338 ValuatorMask mask; 1339 1340 XI_VERIFY_VALUATORS(num_valuators); 1341 1342 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1343 xf86PostProximityEventM(device, is_in, &mask); 1344} 1345 1346void 1347xf86PostProximityEventM(DeviceIntPtr device, 1348 int is_in, const ValuatorMask *mask) 1349{ 1350 QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask); 1351} 1352 1353void 1354xf86PostButtonEvent(DeviceIntPtr device, 1355 int is_absolute, 1356 int button, 1357 int is_down, int first_valuator, int num_valuators, ...) 1358{ 1359 va_list var; 1360 ValuatorMask mask; 1361 int i = 0; 1362 1363 XI_VERIFY_VALUATORS(num_valuators); 1364 1365 valuator_mask_zero(&mask); 1366 1367 va_start(var, num_valuators); 1368 for (i = 0; i < num_valuators; i++) 1369 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1370 1371 va_end(var); 1372 1373 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1374} 1375 1376void 1377xf86PostButtonEventP(DeviceIntPtr device, 1378 int is_absolute, 1379 int button, 1380 int is_down, 1381 int first_valuator, 1382 int num_valuators, const int *valuators) 1383{ 1384 ValuatorMask mask; 1385 1386 XI_VERIFY_VALUATORS(num_valuators); 1387 1388 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1389 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1390} 1391 1392void 1393xf86PostButtonEventM(DeviceIntPtr device, 1394 int is_absolute, 1395 int button, int is_down, const ValuatorMask *mask) 1396{ 1397 int flags = 0; 1398 1399 if (valuator_mask_num_valuators(mask) > 0) { 1400 if (is_absolute) 1401 flags = POINTER_ABSOLUTE; 1402 else 1403 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1404 } 1405 1406#ifdef XFreeXDGA 1407 if (miPointerGetScreen(device)) { 1408 int index = miPointerGetScreen(device)->myNum; 1409 1410 if (DGAStealButtonEvent(device, index, button, is_down)) 1411 return; 1412 } 1413#endif 1414 1415 QueuePointerEvents(device, 1416 is_down ? ButtonPress : ButtonRelease, button, 1417 flags, mask); 1418} 1419 1420void 1421xf86PostKeyEvent(DeviceIntPtr device, unsigned int key_code, int is_down) 1422{ 1423 xf86PostKeyEventM(device, key_code, is_down); 1424} 1425 1426void 1427xf86PostKeyEventP(DeviceIntPtr device, 1428 unsigned int key_code, 1429 int is_down) 1430{ 1431 xf86PostKeyEventM(device, key_code, is_down); 1432} 1433 1434void 1435xf86PostKeyEventM(DeviceIntPtr device, unsigned int key_code, int is_down) 1436{ 1437#ifdef XFreeXDGA 1438 DeviceIntPtr pointer; 1439 1440 /* Some pointers send key events, paired device is wrong then. */ 1441 pointer = GetMaster(device, POINTER_OR_FLOAT); 1442 1443 if (miPointerGetScreen(pointer)) { 1444 int index = miPointerGetScreen(pointer)->myNum; 1445 1446 if (DGAStealKeyEvent(device, index, key_code, is_down)) 1447 return; 1448 } 1449#endif 1450 1451 QueueKeyboardEvents(device, is_down ? KeyPress : KeyRelease, key_code); 1452} 1453 1454void 1455xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code, int is_down) 1456{ 1457 ValuatorMask mask; 1458 1459 valuator_mask_zero(&mask); 1460 xf86PostKeyEventM(device, key_code, is_down); 1461} 1462 1463InputInfoPtr 1464xf86FirstLocalDevice(void) 1465{ 1466 return xf86InputDevs; 1467} 1468 1469/* 1470 * Cx - raw data from touch screen 1471 * to_max - scaled highest dimension 1472 * (remember, this is of rows - 1 because of 0 origin) 1473 * to_min - scaled lowest dimension 1474 * from_max - highest raw value from touch screen calibration 1475 * from_min - lowest raw value from touch screen calibration 1476 * 1477 * This function is the same for X or Y coordinates. 1478 * You may have to reverse the high and low values to compensate for 1479 * different origins on the touch screen vs X. 1480 * 1481 * e.g. to scale from device coordinates into screen coordinates, call 1482 * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); 1483 */ 1484 1485int 1486xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min) 1487{ 1488 int X; 1489 int64_t to_width = to_max - to_min; 1490 int64_t from_width = from_max - from_min; 1491 1492 if (from_width) { 1493 X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min); 1494 } 1495 else { 1496 X = 0; 1497 ErrorF("Divide by Zero in xf86ScaleAxis\n"); 1498 } 1499 1500 if (X > to_max) 1501 X = to_max; 1502 if (X < to_min) 1503 X = to_min; 1504 1505 return X; 1506} 1507 1508Bool 1509xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 1510 int maxval, int resolution, int min_res, int max_res, 1511 int mode) 1512{ 1513 if (!dev || !dev->valuator) 1514 return FALSE; 1515 1516 return InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, 1517 min_res, max_res, mode); 1518} 1519 1520/* 1521 * Set the valuator values to be in sync with dix/event.c 1522 * DefineInitialRootWindow(). 1523 */ 1524void 1525xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) 1526{ 1527 if (axnum == 0) { 1528 dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 1529 dev->last.valuators[0] = dev->valuator->axisVal[0]; 1530 } 1531 else if (axnum == 1) { 1532 dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 1533 dev->last.valuators[1] = dev->valuator->axisVal[1]; 1534 } 1535} 1536 1537/** 1538 * Deactivate a device. Call this function from the driver if you receive a 1539 * read error or something else that spoils your day. 1540 * Device will be moved to the off_devices list, but it will still be there 1541 * until you really clean up after it. 1542 * Notifies the client about an inactive device. 1543 * 1544 * @param panic True if device is unrecoverable and needs to be removed. 1545 */ 1546void 1547xf86DisableDevice(DeviceIntPtr dev, Bool panic) 1548{ 1549 if (!panic) { 1550 DisableDevice(dev, TRUE); 1551 } 1552 else { 1553 SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); 1554 DeleteInputDeviceRequest(dev); 1555 } 1556} 1557 1558/** 1559 * Reactivate a device. Call this function from the driver if you just found 1560 * out that the read error wasn't quite that bad after all. 1561 * Device will be re-activated, and an event sent to the client. 1562 */ 1563void 1564xf86EnableDevice(DeviceIntPtr dev) 1565{ 1566 EnableDevice(dev, TRUE); 1567} 1568 1569/** 1570 * Post a touch event with optional valuators. If this is the first touch in 1571 * the sequence, at least x & y valuators must be provided. The driver is 1572 * responsible for maintaining the correct event sequence (TouchBegin, TouchUpdate, 1573 * TouchEnd). Submitting an update or end event for a unregistered touchid will 1574 * result in errors. 1575 * Touch IDs may be reused by the driver but only after a TouchEnd has been 1576 * submitted for that touch ID. 1577 * 1578 * @param dev The device to post the event for 1579 * @param touchid The touchid of the current touch event. Must be an 1580 * existing ID for TouchUpdate or TouchEnd events 1581 * @param type One of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd 1582 * @param flags Flags for this event 1583 * @param The valuator mask with all valuators set for this event. 1584 */ 1585void 1586xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type, 1587 uint32_t flags, const ValuatorMask *mask) 1588{ 1589 1590 QueueTouchEvents(dev, type, touchid, flags, mask); 1591} 1592 1593/** 1594 * Post a gesture pinch event. The driver is responsible for maintaining the 1595 * correct event sequence (GesturePinchBegin, GesturePinchUpdate, 1596 * GesturePinchEnd). 1597 * 1598 * @param dev The device to post the event for 1599 * @param type One of XI_GesturePinchBegin, XI_GesturePinchUpdate, 1600 * XI_GesturePinchEnd 1601 * @param num_touches The number of touches in the gesture 1602 * @param flags Flags for this event 1603 * @param delta_x,delta_y accelerated relative motion delta 1604 * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta 1605 * @param scale absolute scale of a pinch gesture 1606 * @param delta_angle the ange delta in degrees between the last and the current pinch event. 1607 */ 1608void 1609xf86PostGesturePinchEvent(DeviceIntPtr dev, uint16_t type, 1610 uint16_t num_touches, uint32_t flags, 1611 double delta_x, double delta_y, 1612 double delta_unaccel_x, 1613 double delta_unaccel_y, 1614 double scale, double delta_angle) 1615{ 1616 QueueGesturePinchEvents(dev, type, num_touches, flags, delta_x, delta_y, 1617 delta_unaccel_x, delta_unaccel_y, 1618 scale, delta_angle); 1619} 1620 1621/** 1622 * Post a gesture swipe event. The driver is responsible for maintaining the 1623 * correct event sequence (GestureSwipeBegin, GestureSwipeUpdate, 1624 * GestureSwipeEnd). 1625 * 1626 * @param dev The device to post the event for 1627 * @param type One of XI_GestureSwipeBegin, XI_GestureSwipeUpdate, 1628 * XI_GestureSwipeEnd 1629 * @param num_touches The number of touches in the gesture 1630 * @param flags Flags for this event 1631 * @param delta_x,delta_y accelerated relative motion delta 1632 * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta 1633 */ 1634void 1635xf86PostGestureSwipeEvent(DeviceIntPtr dev, uint16_t type, 1636 uint16_t num_touches, uint32_t flags, 1637 double delta_x, double delta_y, 1638 double delta_unaccel_x, 1639 double delta_unaccel_y) 1640{ 1641 QueueGestureSwipeEvents(dev, type, num_touches, flags, delta_x, delta_y, 1642 delta_unaccel_x, delta_unaccel_y); 1643} 1644 1645void 1646xf86InputEnableVTProbe(void) 1647{ 1648 int is_auto = 0; 1649 DeviceIntPtr pdev; 1650 PausedInputDevicePtr d, tmp; 1651 1652 xorg_list_for_each_entry_safe(d, tmp, &new_input_devices_list, node) { 1653 InputInfoPtr pInfo = d->pInfo; 1654 const char *value = xf86findOptionValue(pInfo->options, "_source"); 1655 1656 is_auto = 0; 1657 if (value && 1658 (strcmp(value, "server/hal") == 0 || 1659 strcmp(value, "server/udev") == 0 || 1660 strcmp(value, "server/wscons") == 0)) 1661 is_auto = 1; 1662 1663 xf86NewInputDevice(pInfo, &pdev, 1664 (!is_auto || 1665 (is_auto && xf86Info.autoEnableDevices))); 1666 xorg_list_del(&d->node); 1667 free(d); 1668 } 1669} 1670 1671/* end of xf86Xinput.c */ 1672