xf86Xinput.c revision 1b5d61b8
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 326/*********************************************************************** 327 * 328 * xf86ProcessCommonOptions -- 329 * 330 * Process global options. 331 * 332 *********************************************************************** 333 */ 334void 335xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr list) 336{ 337 if (xf86SetBoolOption(list, "Floating", 0) || 338 !xf86SetBoolOption(list, "AlwaysCore", 1) || 339 !xf86SetBoolOption(list, "SendCoreEvents", 1) || 340 !xf86SetBoolOption(list, "CorePointer", 1) || 341 !xf86SetBoolOption(list, "CoreKeyboard", 1)) { 342 xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); 343 } 344 else { 345 pInfo->flags |= XI86_ALWAYS_CORE; 346 xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); 347 } 348} 349 350/*********************************************************************** 351 * 352 * xf86ActivateDevice -- 353 * 354 * Initialize an input device. 355 * 356 * Returns TRUE on success, or FALSE otherwise. 357 *********************************************************************** 358 */ 359static DeviceIntPtr 360xf86ActivateDevice(InputInfoPtr pInfo) 361{ 362 DeviceIntPtr dev; 363 Atom atom; 364 365 dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); 366 367 if (dev == NULL) { 368 xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", pInfo->name); 369 pInfo->dev = NULL; 370 return NULL; 371 } 372 373 atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); 374 AssignTypeAndName(dev, atom, pInfo->name); 375 dev->public.devicePrivate = pInfo; 376 pInfo->dev = dev; 377 378 dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; 379 dev->type = SLAVE; 380 dev->spriteInfo->spriteOwner = FALSE; 381 382 dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); 383 384 if (serverGeneration == 1) 385 xf86Msg(X_INFO, 386 "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n", 387 pInfo->name, pInfo->type_name, dev->id); 388 389 return dev; 390} 391 392/**************************************************************************** 393 * 394 * Caller: ProcXSetDeviceMode 395 * 396 * Change the mode of an extension device. 397 * This function is used to change the mode of a device from reporting 398 * relative motion to reporting absolute positional information, and 399 * vice versa. 400 * The default implementation below is that no such devices are supported. 401 * 402 *********************************************************************** 403 */ 404 405int 406SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode) 407{ 408 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 409 410 if (pInfo->switch_mode) { 411 return (*pInfo->switch_mode) (client, dev, mode); 412 } 413 else 414 return BadMatch; 415} 416 417/*********************************************************************** 418 * 419 * Caller: ProcXSetDeviceValuators 420 * 421 * Set the value of valuators on an extension input device. 422 * This function is used to set the initial value of valuators on 423 * those input devices that are capable of reporting either relative 424 * motion or an absolute position, and allow an initial position to be set. 425 * The default implementation below is that no such devices are supported. 426 * 427 *********************************************************************** 428 */ 429 430int 431SetDeviceValuators(ClientPtr client, DeviceIntPtr dev, int *valuators, 432 int first_valuator, int num_valuators) 433{ 434 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 435 436 if (pInfo->set_device_valuators) 437 return (*pInfo->set_device_valuators) (pInfo, valuators, first_valuator, 438 num_valuators); 439 440 return BadMatch; 441} 442 443/*********************************************************************** 444 * 445 * Caller: ProcXChangeDeviceControl 446 * 447 * Change the specified device controls on an extension input device. 448 * 449 *********************************************************************** 450 */ 451 452int 453ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev, xDeviceCtl * control) 454{ 455 InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 456 457 if (!pInfo->control_proc) { 458 switch (control->control) { 459 case DEVICE_CORE: 460 case DEVICE_ABS_CALIB: 461 case DEVICE_ABS_AREA: 462 return BadMatch; 463 case DEVICE_RESOLUTION: 464 case DEVICE_ENABLE: 465 return Success; 466 default: 467 return BadMatch; 468 } 469 } 470 else { 471 return (*pInfo->control_proc) (pInfo, control); 472 } 473} 474 475/* 476 * Get the operating system name from uname and store it statically to avoid 477 * repeating the system call each time MatchOS is checked. 478 */ 479static const char * 480HostOS(void) 481{ 482#ifdef HAVE_SYS_UTSNAME_H 483 struct utsname name; 484 static char host_os[sizeof(name.sysname)] = ""; 485 486 if (*host_os == '\0') { 487 if (uname(&name) >= 0) 488 strlcpy(host_os, name.sysname, sizeof(host_os)); 489 else { 490 strlcpy(host_os, "unknown", sizeof(host_os)); 491 } 492 } 493 return host_os; 494#else 495 return ""; 496#endif 497} 498 499static int 500match_substring(const char *attr, const char *pattern) 501{ 502 return (strstr(attr, pattern)) ? 0 : -1; 503} 504 505#ifdef HAVE_FNMATCH_H 506static int 507match_pattern(const char *attr, const char *pattern) 508{ 509 return fnmatch(pattern, attr, 0); 510} 511#else 512#define match_pattern match_substring 513#endif 514 515#ifdef HAVE_FNMATCH_H 516static int 517match_path_pattern(const char *attr, const char *pattern) 518{ 519 return fnmatch(pattern, attr, FNM_PATHNAME); 520} 521#else 522#define match_path_pattern match_substring 523#endif 524 525/* 526 * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" 527 * It is convenient that "" in patterns means "no explicit layout" 528 */ 529static int 530match_string_implicit(const char *attr, const char *pattern) 531{ 532 if (strlen(pattern)) { 533 return strcmp(attr, pattern); 534 } 535 else { 536 return strcmp(attr, "(implicit)"); 537 } 538} 539 540/* 541 * Match an attribute against a list of NULL terminated arrays of patterns. 542 * If a pattern in each list entry is matched, return TRUE. 543 */ 544static Bool 545MatchAttrToken(const char *attr, struct xorg_list *patterns, 546 int (*compare) (const char *attr, const char *pattern)) 547{ 548 const xf86MatchGroup *group; 549 550 /* If there are no patterns, accept the match */ 551 if (xorg_list_is_empty(patterns)) 552 return TRUE; 553 554 /* 555 * Iterate the list of patterns ensuring each entry has a 556 * match. Each list entry is a separate Match line of the same type. 557 */ 558 xorg_list_for_each_entry(group, patterns, entry) { 559 char *const *cur; 560 Bool is_negated = group->is_negated; 561 Bool match = is_negated; 562 563 /* If there's a pattern but no attribute, we reject the match for a 564 * MatchFoo directive, and accept it for a NoMatchFoo directive 565 */ 566 if (!attr) 567 return is_negated; 568 569 for (cur = group->values; *cur; cur++) 570 if ((*compare) (attr, *cur) == 0) { 571 match = !is_negated; 572 break; 573 } 574 if (!match) 575 return FALSE; 576 } 577 578 /* All the entries in the list matched the attribute */ 579 return TRUE; 580} 581 582/* 583 * Classes without any Match statements match all devices. Otherwise, all 584 * statements must match. 585 */ 586static Bool 587InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, 588 const InputAttributes * attrs) 589{ 590 /* MatchProduct substring */ 591 if (!MatchAttrToken 592 (attrs->product, &iclass->match_product, match_substring)) 593 return FALSE; 594 595 /* MatchVendor substring */ 596 if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) 597 return FALSE; 598 599 /* MatchDevicePath pattern */ 600 if (!MatchAttrToken 601 (attrs->device, &iclass->match_device, match_path_pattern)) 602 return FALSE; 603 604 /* MatchOS case-insensitive string */ 605 if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) 606 return FALSE; 607 608 /* MatchPnPID pattern */ 609 if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) 610 return FALSE; 611 612 /* MatchUSBID pattern */ 613 if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) 614 return FALSE; 615 616 /* MatchDriver string */ 617 if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) 618 return FALSE; 619 620 /* 621 * MatchTag string 622 * See if any of the device's tags match any of the MatchTag tokens. 623 */ 624 if (!xorg_list_is_empty(&iclass->match_tag)) { 625 char *const *tag; 626 Bool match; 627 628 if (!attrs->tags) 629 return FALSE; 630 for (tag = attrs->tags, match = FALSE; *tag; tag++) { 631 if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { 632 match = TRUE; 633 break; 634 } 635 } 636 if (!match) 637 return FALSE; 638 } 639 640 /* MatchLayout string */ 641 if (!xorg_list_is_empty(&iclass->match_layout)) { 642 if (!MatchAttrToken(xf86ConfigLayout.id, 643 &iclass->match_layout, match_string_implicit)) 644 return FALSE; 645 } 646 647 /* MatchIs* booleans */ 648 if (iclass->is_keyboard.set && 649 iclass->is_keyboard.val != ! !(attrs->flags & (ATTR_KEY|ATTR_KEYBOARD))) 650 return FALSE; 651 if (iclass->is_pointer.set && 652 iclass->is_pointer.val != ! !(attrs->flags & ATTR_POINTER)) 653 return FALSE; 654 if (iclass->is_joystick.set && 655 iclass->is_joystick.val != ! !(attrs->flags & ATTR_JOYSTICK)) 656 return FALSE; 657 if (iclass->is_tablet.set && 658 iclass->is_tablet.val != ! !(attrs->flags & ATTR_TABLET)) 659 return FALSE; 660 if (iclass->is_tablet_pad.set && 661 iclass->is_tablet_pad.val != ! !(attrs->flags & ATTR_TABLET_PAD)) 662 return FALSE; 663 if (iclass->is_touchpad.set && 664 iclass->is_touchpad.val != ! !(attrs->flags & ATTR_TOUCHPAD)) 665 return FALSE; 666 if (iclass->is_touchscreen.set && 667 iclass->is_touchscreen.val != ! !(attrs->flags & ATTR_TOUCHSCREEN)) 668 return FALSE; 669 670 return TRUE; 671} 672 673/* 674 * Merge in any InputClass configurations. Options in each InputClass 675 * section have more priority than the original device configuration as 676 * well as any previous InputClass sections. 677 */ 678static int 679MergeInputClasses(const InputInfoPtr idev, const InputAttributes * attrs) 680{ 681 XF86ConfInputClassPtr cl; 682 XF86OptionPtr classopts; 683 684 for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 685 if (!InputClassMatches(cl, idev, attrs)) 686 continue; 687 688 /* Collect class options and driver settings */ 689 classopts = xf86optionListDup(cl->option_lst); 690 if (cl->driver) { 691 free((void *) idev->driver); 692 idev->driver = xstrdup(cl->driver); 693 if (!idev->driver) { 694 xf86Msg(X_ERROR, "Failed to allocate memory while merging " 695 "InputClass configuration"); 696 return BadAlloc; 697 } 698 classopts = xf86ReplaceStrOption(classopts, "driver", idev->driver); 699 } 700 701 /* Apply options to device with InputClass settings preferred. */ 702 xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", 703 idev->name, cl->identifier); 704 idev->options = xf86optionListMerge(idev->options, classopts); 705 } 706 707 return Success; 708} 709 710/* 711 * Iterate the list of classes and look for Option "Ignore". Return the 712 * value of the last matching class and holler when returning TRUE. 713 */ 714static Bool 715IgnoreInputClass(const InputInfoPtr idev, const InputAttributes * attrs) 716{ 717 XF86ConfInputClassPtr cl; 718 Bool ignore = FALSE; 719 const char *ignore_class; 720 721 for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 722 if (!InputClassMatches(cl, idev, attrs)) 723 continue; 724 if (xf86findOption(cl->option_lst, "Ignore")) { 725 ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); 726 ignore_class = cl->identifier; 727 } 728 } 729 730 if (ignore) 731 xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", 732 idev->name, ignore_class); 733 return ignore; 734} 735 736InputInfoPtr 737xf86AllocateInput(void) 738{ 739 InputInfoPtr pInfo; 740 741 pInfo = calloc(sizeof(*pInfo), 1); 742 if (!pInfo) 743 return NULL; 744 745 pInfo->fd = -1; 746 pInfo->type_name = "UNKNOWN"; 747 748 return pInfo; 749} 750 751/* Append InputInfoRec to the tail of xf86InputDevs. */ 752static void 753xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) 754{ 755 InputInfoPtr *prev = NULL; 756 757 pInfo->drv = drv; 758 pInfo->module = DuplicateModule(drv->module, NULL); 759 760 for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next); 761 762 *prev = pInfo; 763 pInfo->next = NULL; 764 765 xf86CollectInputOptions(pInfo, (const char **) drv->default_options); 766 xf86OptionListReport(pInfo->options); 767 xf86ProcessCommonOptions(pInfo, pInfo->options); 768} 769 770/* 771 * Remove an entry from xf86InputDevs and free all the device's information. 772 */ 773void 774xf86DeleteInput(InputInfoPtr pInp, int flags) 775{ 776 /* First check if the inputdev is valid. */ 777 if (pInp == NULL) 778 return; 779 780 if (pInp->module) 781 UnloadModule(pInp->module); 782 783 /* This should *really* be handled in drv->UnInit(dev) call instead, but 784 * if the driver forgets about it make sure we free it or at least crash 785 * with flying colors */ 786 free(pInp->private); 787 788 FreeInputAttributes(pInp->attrs); 789 790 if (pInp->flags & XI86_SERVER_FD) 791 systemd_logind_release_fd(pInp->major, pInp->minor, pInp->fd); 792 793 /* Remove the entry from the list. */ 794 if (pInp == xf86InputDevs) 795 xf86InputDevs = pInp->next; 796 else { 797 InputInfoPtr p = xf86InputDevs; 798 799 while (p && p->next != pInp) 800 p = p->next; 801 if (p) 802 p->next = pInp->next; 803 /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ 804 } 805 806 free((void *) pInp->driver); 807 free((void *) pInp->name); 808 xf86optionListFree(pInp->options); 809 free(pInp); 810} 811 812/* 813 * Apply backend-specific initialization. Invoked after ActivateDevice(), 814 * i.e. after the driver successfully completed DEVICE_INIT and the device 815 * is advertised. 816 * @param dev the device 817 * @return Success or an error code 818 */ 819static int 820xf86InputDevicePostInit(DeviceIntPtr dev) 821{ 822 ApplyAccelerationSettings(dev); 823 ApplyTransformationMatrix(dev); 824 return Success; 825} 826 827static void 828xf86stat(const char *path, int *maj, int *min) 829{ 830 struct stat st; 831 832 if (stat(path, &st) == -1) 833 return; 834 835 *maj = major(st.st_rdev); 836 *min = minor(st.st_rdev); 837} 838 839static inline InputDriverPtr 840xf86LoadInputDriver(const char *driver_name) 841{ 842 InputDriverPtr drv = NULL; 843 844 /* Memory leak for every attached device if we don't 845 * test if the module is already loaded first */ 846 drv = xf86LookupInputDriver(driver_name); 847 if (!drv) { 848 if (xf86LoadOneModule(driver_name, NULL)) 849 drv = xf86LookupInputDriver(driver_name); 850 } 851 852 return drv; 853} 854 855/** 856 * Create a new input device, activate and enable it. 857 * 858 * Possible return codes: 859 * BadName .. a bad driver name was supplied. 860 * BadImplementation ... The driver does not have a PreInit function. This 861 * is a driver bug. 862 * BadMatch .. device initialization failed. 863 * BadAlloc .. too many input devices 864 * 865 * @param idev The device, already set up with identifier, driver, and the 866 * options. 867 * @param pdev Pointer to the new device, if Success was reported. 868 * @param enable Enable the device after activating it. 869 * 870 * @return Success or an error code 871 */ 872_X_INTERNAL int 873xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) 874{ 875 InputDriverPtr drv = NULL; 876 DeviceIntPtr dev = NULL; 877 Bool paused; 878 int rval; 879 char *path = NULL; 880 881 drv = xf86LoadInputDriver(pInfo->driver); 882 if (!drv) { 883 xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); 884 885 if (strlen(FALLBACK_INPUT_DRIVER) > 0) { 886 xf86Msg(X_INFO, "Falling back to input driver `%s'\n", 887 FALLBACK_INPUT_DRIVER); 888 drv = xf86LoadInputDriver(FALLBACK_INPUT_DRIVER); 889 if (drv) { 890 free(pInfo->driver); 891 pInfo->driver = strdup(FALLBACK_INPUT_DRIVER); 892 } 893 } 894 if (!drv) { 895 rval = BadName; 896 goto unwind; 897 } 898 } 899 900 xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, 901 pInfo->name); 902 903 if (!drv->PreInit) { 904 xf86Msg(X_ERROR, 905 "Input driver `%s' has no PreInit function (ignoring)\n", 906 drv->driverName); 907 rval = BadImplementation; 908 goto unwind; 909 } 910 911 path = xf86CheckStrOption(pInfo->options, "Device", NULL); 912 if (path && pInfo->major == 0 && pInfo->minor == 0) 913 xf86stat(path, &pInfo->major, &pInfo->minor); 914 915 if (path && (drv->capabilities & XI86_DRV_CAP_SERVER_FD)){ 916 int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor, 917 path, &paused); 918 if (fd != -1) { 919 if (paused) { 920 /* Put on new_input_devices list for delayed probe */ 921 PausedInputDevicePtr new_device = xnfalloc(sizeof *new_device); 922 new_device->pInfo = pInfo; 923 924 xorg_list_append(&new_device->node, &new_input_devices_list); 925 systemd_logind_release_fd(pInfo->major, pInfo->minor, fd); 926 free(path); 927 return BadMatch; 928 } 929 pInfo->fd = fd; 930 pInfo->flags |= XI86_SERVER_FD; 931 pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd); 932 } 933 } 934 935 free(path); 936 937 xf86AddInput(drv, pInfo); 938 939 input_lock(); 940 rval = drv->PreInit(drv, pInfo, 0); 941 input_unlock(); 942 943 if (rval != Success) { 944 xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); 945 goto unwind; 946 } 947 948 if (!(dev = xf86ActivateDevice(pInfo))) { 949 rval = BadAlloc; 950 goto unwind; 951 } 952 953 rval = ActivateDevice(dev, TRUE); 954 if (rval != Success) { 955 xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 956 RemoveDevice(dev, TRUE); 957 goto unwind; 958 } 959 960 rval = xf86InputDevicePostInit(dev); 961 if (rval != Success) { 962 xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); 963 RemoveDevice(dev, TRUE); 964 goto unwind; 965 } 966 967 /* Enable it if it's properly initialised and we're currently in the VT */ 968 if (enable && dev->inited && dev->startup && xf86VTOwner()) { 969 input_lock(); 970 EnableDevice(dev, TRUE); 971 if (!dev->enabled) { 972 xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 973 RemoveDevice(dev, TRUE); 974 rval = BadMatch; 975 input_unlock(); 976 goto unwind; 977 } 978 /* send enter/leave event, update sprite window */ 979 CheckMotion(NULL, dev); 980 input_unlock(); 981 } 982 983 *pdev = dev; 984 return Success; 985 986 unwind: 987 if (pInfo) { 988 if (drv && drv->UnInit) 989 drv->UnInit(drv, pInfo, 0); 990 else 991 xf86DeleteInput(pInfo, 0); 992 } 993 return rval; 994} 995 996int 997NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, 998 DeviceIntPtr *pdev) 999{ 1000 InputInfoPtr pInfo = NULL; 1001 InputOption *option = NULL; 1002 int rval = Success; 1003 int is_auto = 0; 1004 1005 pInfo = xf86AllocateInput(); 1006 if (!pInfo) 1007 return BadAlloc; 1008 1009 nt_list_for_each_entry(option, options, list.next) { 1010 const char *key = input_option_get_key(option); 1011 const char *value = input_option_get_value(option); 1012 1013 if (strcasecmp(key, "driver") == 0) { 1014 if (pInfo->driver) { 1015 rval = BadRequest; 1016 goto unwind; 1017 } 1018 pInfo->driver = xstrdup(value); 1019 if (!pInfo->driver) { 1020 rval = BadAlloc; 1021 goto unwind; 1022 } 1023 } 1024 1025 if (strcasecmp(key, "name") == 0 || strcasecmp(key, "identifier") == 0) { 1026 if (pInfo->name) { 1027 rval = BadRequest; 1028 goto unwind; 1029 } 1030 pInfo->name = xstrdup(value); 1031 if (!pInfo->name) { 1032 rval = BadAlloc; 1033 goto unwind; 1034 } 1035 } 1036 1037 if (strcmp(key, "_source") == 0 && 1038 (strcmp(value, "server/hal") == 0 || 1039 strcmp(value, "server/udev") == 0 || 1040 strcmp(value, "server/wscons") == 0)) { 1041 is_auto = 1; 1042 if (!xf86Info.autoAddDevices) { 1043 rval = BadMatch; 1044 goto unwind; 1045 } 1046 } 1047 1048 if (strcmp(key, "major") == 0) 1049 pInfo->major = atoi(value); 1050 1051 if (strcmp(key, "minor") == 0) 1052 pInfo->minor = atoi(value); 1053 } 1054 1055 nt_list_for_each_entry(option, options, list.next) { 1056 /* Copy option key/value strings from the provided list */ 1057 pInfo->options = xf86AddNewOption(pInfo->options, 1058 input_option_get_key(option), 1059 input_option_get_value(option)); 1060 } 1061 1062 /* Apply InputClass settings */ 1063 if (attrs) { 1064 if (IgnoreInputClass(pInfo, attrs)) { 1065 rval = BadIDChoice; 1066 goto unwind; 1067 } 1068 1069 rval = MergeInputClasses(pInfo, attrs); 1070 if (rval != Success) 1071 goto unwind; 1072 1073 pInfo->attrs = DuplicateInputAttributes(attrs); 1074 } 1075 1076 if (!pInfo->name) { 1077 xf86Msg(X_INFO, "No identifier specified, ignoring this device.\n"); 1078 rval = BadRequest; 1079 goto unwind; 1080 } 1081 1082 if (!pInfo->driver) { 1083 xf86Msg(X_INFO, "No input driver specified, ignoring this device.\n"); 1084 xf86Msg(X_INFO, 1085 "This device may have been added with another device file.\n"); 1086 rval = BadRequest; 1087 goto unwind; 1088 } 1089 1090 rval = xf86NewInputDevice(pInfo, pdev, 1091 (!is_auto || 1092 (is_auto && xf86Info.autoEnableDevices))); 1093 1094 return rval; 1095 1096 unwind: 1097 if (is_auto && !xf86Info.autoAddDevices) 1098 xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); 1099 xf86DeleteInput(pInfo, 0); 1100 return rval; 1101} 1102 1103void 1104DeleteInputDeviceRequest(DeviceIntPtr pDev) 1105{ 1106 InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; 1107 InputDriverPtr drv = NULL; 1108 Bool isMaster = IsMaster(pDev); 1109 1110 if (pInfo) /* need to get these before RemoveDevice */ 1111 drv = pInfo->drv; 1112 1113 input_lock(); 1114 RemoveDevice(pDev, TRUE); 1115 1116 if (!isMaster && pInfo != NULL) { 1117 if (drv->UnInit) 1118 drv->UnInit(drv, pInfo, 0); 1119 else 1120 xf86DeleteInput(pInfo, 0); 1121 } 1122 input_unlock(); 1123} 1124 1125void 1126RemoveInputDeviceTraces(const char *config_info) 1127{ 1128 PausedInputDevicePtr d, tmp; 1129 1130 xorg_list_for_each_entry_safe(d, tmp, &new_input_devices_list, node) { 1131 const char *ci = xf86findOptionValue(d->pInfo->options, "config_info"); 1132 if (!ci || strcmp(ci, config_info) != 0) 1133 continue; 1134 1135 xorg_list_del(&d->node); 1136 free(d); 1137 } 1138} 1139 1140/* 1141 * convenient functions to post events 1142 */ 1143 1144void 1145xf86PostMotionEvent(DeviceIntPtr device, 1146 int is_absolute, int first_valuator, int num_valuators, ...) 1147{ 1148 va_list var; 1149 int i = 0; 1150 ValuatorMask mask; 1151 1152 XI_VERIFY_VALUATORS(num_valuators); 1153 1154 valuator_mask_zero(&mask); 1155 va_start(var, num_valuators); 1156 for (i = 0; i < num_valuators; i++) 1157 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1158 1159 va_end(var); 1160 1161 xf86PostMotionEventM(device, is_absolute, &mask); 1162} 1163 1164void 1165xf86PostMotionEventP(DeviceIntPtr device, 1166 int is_absolute, 1167 int first_valuator, 1168 int num_valuators, const int *valuators) 1169{ 1170 ValuatorMask mask; 1171 1172 XI_VERIFY_VALUATORS(num_valuators); 1173 1174 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1175 xf86PostMotionEventM(device, is_absolute, &mask); 1176} 1177 1178static int 1179xf86CheckMotionEvent4DGA(DeviceIntPtr device, int is_absolute, 1180 const ValuatorMask *mask) 1181{ 1182 int stolen = 0; 1183 1184#ifdef XFreeXDGA 1185 ScreenPtr scr = NULL; 1186 int idx = 0, i; 1187 1188 /* The evdev driver may not always send all axes across. */ 1189 if (valuator_mask_isset(mask, 0) || valuator_mask_isset(mask, 1)) { 1190 scr = miPointerGetScreen(device); 1191 if (scr) { 1192 int dx = 0, dy = 0; 1193 1194 idx = scr->myNum; 1195 1196 if (valuator_mask_isset(mask, 0)) { 1197 dx = valuator_mask_get(mask, 0); 1198 if (is_absolute) 1199 dx -= device->last.valuators[0]; 1200 else if (valuator_mask_has_unaccelerated(mask)) 1201 dx = valuator_mask_get_unaccelerated(mask, 0); 1202 } 1203 1204 if (valuator_mask_isset(mask, 1)) { 1205 dy = valuator_mask_get(mask, 1); 1206 if (is_absolute) 1207 dy -= device->last.valuators[1]; 1208 else if (valuator_mask_has_unaccelerated(mask)) 1209 dy = valuator_mask_get_unaccelerated(mask, 1); 1210 } 1211 1212 if (DGAStealMotionEvent(device, idx, dx, dy)) 1213 stolen = 1; 1214 } 1215 } 1216 1217 for (i = 2; i < valuator_mask_size(mask); i++) { 1218 AxisInfoPtr ax; 1219 double incr; 1220 int val, button; 1221 1222 if (i >= device->valuator->numAxes) 1223 break; 1224 1225 if (!valuator_mask_isset(mask, i)) 1226 continue; 1227 1228 ax = &device->valuator->axes[i]; 1229 1230 if (ax->scroll.type == SCROLL_TYPE_NONE) 1231 continue; 1232 1233 if (!scr) { 1234 scr = miPointerGetScreen(device); 1235 if (!scr) 1236 break; 1237 idx = scr->myNum; 1238 } 1239 1240 incr = ax->scroll.increment; 1241 val = valuator_mask_get(mask, i); 1242 1243 if (ax->scroll.type == SCROLL_TYPE_VERTICAL) { 1244 if (incr * val < 0) 1245 button = 4; /* up */ 1246 else 1247 button = 5; /* down */ 1248 } else { /* SCROLL_TYPE_HORIZONTAL */ 1249 if (incr * val < 0) 1250 button = 6; /* left */ 1251 else 1252 button = 7; /* right */ 1253 } 1254 1255 if (DGAStealButtonEvent(device, idx, button, 1) && 1256 DGAStealButtonEvent(device, idx, button, 0)) 1257 stolen = 1; 1258 } 1259 1260#endif 1261 1262 return stolen; 1263} 1264 1265void 1266xf86PostMotionEventM(DeviceIntPtr device, 1267 int is_absolute, const ValuatorMask *mask) 1268{ 1269 int flags = 0; 1270 1271 if (xf86CheckMotionEvent4DGA(device, is_absolute, mask)) 1272 return; 1273 1274 if (valuator_mask_num_valuators(mask) > 0) { 1275 if (is_absolute) 1276 flags = POINTER_ABSOLUTE; 1277 else 1278 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1279 } 1280 1281 QueuePointerEvents(device, MotionNotify, 0, flags, mask); 1282} 1283 1284void 1285xf86PostProximityEvent(DeviceIntPtr device, 1286 int is_in, int first_valuator, int num_valuators, ...) 1287{ 1288 va_list var; 1289 int i; 1290 ValuatorMask mask; 1291 1292 XI_VERIFY_VALUATORS(num_valuators); 1293 1294 valuator_mask_zero(&mask); 1295 va_start(var, num_valuators); 1296 for (i = 0; i < num_valuators; i++) 1297 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1298 1299 va_end(var); 1300 1301 xf86PostProximityEventM(device, is_in, &mask); 1302} 1303 1304void 1305xf86PostProximityEventP(DeviceIntPtr device, 1306 int is_in, 1307 int first_valuator, 1308 int num_valuators, const int *valuators) 1309{ 1310 ValuatorMask mask; 1311 1312 XI_VERIFY_VALUATORS(num_valuators); 1313 1314 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1315 xf86PostProximityEventM(device, is_in, &mask); 1316} 1317 1318void 1319xf86PostProximityEventM(DeviceIntPtr device, 1320 int is_in, const ValuatorMask *mask) 1321{ 1322 QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask); 1323} 1324 1325void 1326xf86PostButtonEvent(DeviceIntPtr device, 1327 int is_absolute, 1328 int button, 1329 int is_down, int first_valuator, int num_valuators, ...) 1330{ 1331 va_list var; 1332 ValuatorMask mask; 1333 int i = 0; 1334 1335 XI_VERIFY_VALUATORS(num_valuators); 1336 1337 valuator_mask_zero(&mask); 1338 1339 va_start(var, num_valuators); 1340 for (i = 0; i < num_valuators; i++) 1341 valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1342 1343 va_end(var); 1344 1345 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1346} 1347 1348void 1349xf86PostButtonEventP(DeviceIntPtr device, 1350 int is_absolute, 1351 int button, 1352 int is_down, 1353 int first_valuator, 1354 int num_valuators, const int *valuators) 1355{ 1356 ValuatorMask mask; 1357 1358 XI_VERIFY_VALUATORS(num_valuators); 1359 1360 valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1361 xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1362} 1363 1364void 1365xf86PostButtonEventM(DeviceIntPtr device, 1366 int is_absolute, 1367 int button, int is_down, const ValuatorMask *mask) 1368{ 1369 int flags = 0; 1370 1371 if (valuator_mask_num_valuators(mask) > 0) { 1372 if (is_absolute) 1373 flags = POINTER_ABSOLUTE; 1374 else 1375 flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1376 } 1377 1378#ifdef XFreeXDGA 1379 if (miPointerGetScreen(device)) { 1380 int index = miPointerGetScreen(device)->myNum; 1381 1382 if (DGAStealButtonEvent(device, index, button, is_down)) 1383 return; 1384 } 1385#endif 1386 1387 QueuePointerEvents(device, 1388 is_down ? ButtonPress : ButtonRelease, button, 1389 flags, mask); 1390} 1391 1392void 1393xf86PostKeyEvent(DeviceIntPtr device, unsigned int key_code, int is_down) 1394{ 1395 xf86PostKeyEventM(device, key_code, is_down); 1396} 1397 1398void 1399xf86PostKeyEventP(DeviceIntPtr device, 1400 unsigned int key_code, 1401 int is_down) 1402{ 1403 xf86PostKeyEventM(device, key_code, is_down); 1404} 1405 1406void 1407xf86PostKeyEventM(DeviceIntPtr device, unsigned int key_code, int is_down) 1408{ 1409#ifdef XFreeXDGA 1410 DeviceIntPtr pointer; 1411 1412 /* Some pointers send key events, paired device is wrong then. */ 1413 pointer = GetMaster(device, POINTER_OR_FLOAT); 1414 1415 if (miPointerGetScreen(pointer)) { 1416 int index = miPointerGetScreen(pointer)->myNum; 1417 1418 if (DGAStealKeyEvent(device, index, key_code, is_down)) 1419 return; 1420 } 1421#endif 1422 1423 QueueKeyboardEvents(device, is_down ? KeyPress : KeyRelease, key_code); 1424} 1425 1426void 1427xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code, int is_down) 1428{ 1429 ValuatorMask mask; 1430 1431 valuator_mask_zero(&mask); 1432 xf86PostKeyEventM(device, key_code, is_down); 1433} 1434 1435InputInfoPtr 1436xf86FirstLocalDevice(void) 1437{ 1438 return xf86InputDevs; 1439} 1440 1441/* 1442 * Cx - raw data from touch screen 1443 * to_max - scaled highest dimension 1444 * (remember, this is of rows - 1 because of 0 origin) 1445 * to_min - scaled lowest dimension 1446 * from_max - highest raw value from touch screen calibration 1447 * from_min - lowest raw value from touch screen calibration 1448 * 1449 * This function is the same for X or Y coordinates. 1450 * You may have to reverse the high and low values to compensate for 1451 * different orgins on the touch screen vs X. 1452 * 1453 * e.g. to scale from device coordinates into screen coordinates, call 1454 * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); 1455 */ 1456 1457int 1458xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min) 1459{ 1460 int X; 1461 int64_t to_width = to_max - to_min; 1462 int64_t from_width = from_max - from_min; 1463 1464 if (from_width) { 1465 X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min); 1466 } 1467 else { 1468 X = 0; 1469 ErrorF("Divide by Zero in xf86ScaleAxis\n"); 1470 } 1471 1472 if (X > to_max) 1473 X = to_max; 1474 if (X < to_min) 1475 X = to_min; 1476 1477 return X; 1478} 1479 1480Bool 1481xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 1482 int maxval, int resolution, int min_res, int max_res, 1483 int mode) 1484{ 1485 if (!dev || !dev->valuator) 1486 return FALSE; 1487 1488 return InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, 1489 min_res, max_res, mode); 1490} 1491 1492/* 1493 * Set the valuator values to be in sync with dix/event.c 1494 * DefineInitialRootWindow(). 1495 */ 1496void 1497xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) 1498{ 1499 if (axnum == 0) { 1500 dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 1501 dev->last.valuators[0] = dev->valuator->axisVal[0]; 1502 } 1503 else if (axnum == 1) { 1504 dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 1505 dev->last.valuators[1] = dev->valuator->axisVal[1]; 1506 } 1507} 1508 1509/** 1510 * Deactivate a device. Call this function from the driver if you receive a 1511 * read error or something else that spoils your day. 1512 * Device will be moved to the off_devices list, but it will still be there 1513 * until you really clean up after it. 1514 * Notifies the client about an inactive device. 1515 * 1516 * @param panic True if device is unrecoverable and needs to be removed. 1517 */ 1518void 1519xf86DisableDevice(DeviceIntPtr dev, Bool panic) 1520{ 1521 if (!panic) { 1522 DisableDevice(dev, TRUE); 1523 } 1524 else { 1525 SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); 1526 DeleteInputDeviceRequest(dev); 1527 } 1528} 1529 1530/** 1531 * Reactivate a device. Call this function from the driver if you just found 1532 * out that the read error wasn't quite that bad after all. 1533 * Device will be re-activated, and an event sent to the client. 1534 */ 1535void 1536xf86EnableDevice(DeviceIntPtr dev) 1537{ 1538 EnableDevice(dev, TRUE); 1539} 1540 1541/** 1542 * Post a touch event with optional valuators. If this is the first touch in 1543 * the sequence, at least x & y valuators must be provided. The driver is 1544 * responsible for maintaining the correct event sequence (TouchBegin, TouchUpdate, 1545 * TouchEnd). Submitting an update or end event for a unregistered touchid will 1546 * result in errors. 1547 * Touch IDs may be reused by the driver but only after a TouchEnd has been 1548 * submitted for that touch ID. 1549 * 1550 * @param dev The device to post the event for 1551 * @param touchid The touchid of the current touch event. Must be an 1552 * existing ID for TouchUpdate or TouchEnd events 1553 * @param type One of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd 1554 * @param flags Flags for this event 1555 * @param The valuator mask with all valuators set for this event. 1556 */ 1557void 1558xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type, 1559 uint32_t flags, const ValuatorMask *mask) 1560{ 1561 1562 QueueTouchEvents(dev, type, touchid, flags, mask); 1563} 1564 1565void 1566xf86InputEnableVTProbe(void) 1567{ 1568 int is_auto = 0; 1569 DeviceIntPtr pdev; 1570 PausedInputDevicePtr d, tmp; 1571 1572 xorg_list_for_each_entry_safe(d, tmp, &new_input_devices_list, node) { 1573 InputInfoPtr pInfo = d->pInfo; 1574 const char *value = xf86findOptionValue(pInfo->options, "_source"); 1575 1576 is_auto = 0; 1577 if (value && 1578 (strcmp(value, "server/hal") == 0 || 1579 strcmp(value, "server/udev") == 0 || 1580 strcmp(value, "server/wscons") == 0)) 1581 is_auto = 1; 1582 1583 xf86NewInputDevice(pInfo, &pdev, 1584 (!is_auto || 1585 (is_auto && xf86Info.autoEnableDevices))); 1586 xorg_list_del(&d->node); 1587 free(d); 1588 } 1589} 1590 1591/* end of xf86Xinput.c */ 1592