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