xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86Xinput.c (49967B)


      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 
    113 static int
    114  xf86InputDevicePostInit(DeviceIntPtr dev);
    115 
    116 typedef struct {
    117     struct xorg_list node;
    118     InputInfoPtr pInfo;
    119 } PausedInputDeviceRec;
    120 typedef PausedInputDeviceRec *PausedInputDevicePtr;
    121 
    122 static 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  */
    130 static void
    131 ProcessVelocityConfiguration(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 
    219 static void
    220 ApplyAccelerationSettings(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 
    296 static void
    297 ApplyTransformationMatrix(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 static void
    327 ApplyAutoRepeat(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  */
    361 void
    362 xf86ProcessCommonOptions(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  */
    386 static DeviceIntPtr
    387 xf86ActivateDevice(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 
    432 int
    433 SetDeviceMode(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 
    457 int
    458 SetDeviceValuators(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 
    479 int
    480 ChangeDeviceControl(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  */
    506 static const char *
    507 HostOS(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 
    526 static int
    527 match_substring(const char *attr, const char *pattern)
    528 {
    529     return (strstr(attr, pattern)) ? 0 : -1;
    530 }
    531 
    532 #ifdef HAVE_FNMATCH_H
    533 static int
    534 match_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
    543 static int
    544 match_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  */
    556 static int
    557 match_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  */
    571 static Bool
    572 MatchAttrToken(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  */
    613 static Bool
    614 InputClassMatches(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  */
    705 static int
    706 MergeInputClasses(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  */
    741 static Bool
    742 IgnoreInputClass(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 
    763 InputInfoPtr
    764 xf86AllocateInput(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. */
    779 static void
    780 xf86AddInput(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  */
    800 void
    801 xf86DeleteInput(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  */
    846 static int
    847 xf86InputDevicePostInit(DeviceIntPtr dev)
    848 {
    849     ApplyAccelerationSettings(dev);
    850     ApplyTransformationMatrix(dev);
    851     ApplyAutoRepeat(dev);
    852     return Success;
    853 }
    854 
    855 static void
    856 xf86stat(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 
    867 static inline InputDriverPtr
    868 xf86LoadInputDriver(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
    901 xf86NewInputDevice(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 
   1024 int
   1025 NewInputDeviceRequest(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 
   1131 void
   1132 DeleteInputDeviceRequest(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 
   1153 void
   1154 RemoveInputDeviceTraces(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 
   1172 void
   1173 xf86PostMotionEvent(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 
   1192 void
   1193 xf86PostMotionEventP(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 
   1206 static int
   1207 xf86CheckMotionEvent4DGA(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 
   1293 void
   1294 xf86PostMotionEventM(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 
   1312 void
   1313 xf86PostProximityEvent(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 
   1332 void
   1333 xf86PostProximityEventP(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 
   1346 void
   1347 xf86PostProximityEventM(DeviceIntPtr device,
   1348                         int is_in, const ValuatorMask *mask)
   1349 {
   1350     QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask);
   1351 }
   1352 
   1353 void
   1354 xf86PostButtonEvent(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 
   1376 void
   1377 xf86PostButtonEventP(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 
   1392 void
   1393 xf86PostButtonEventM(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 
   1420 void
   1421 xf86PostKeyEvent(DeviceIntPtr device, unsigned int key_code, int is_down)
   1422 {
   1423     xf86PostKeyEventM(device, key_code, is_down);
   1424 }
   1425 
   1426 void
   1427 xf86PostKeyEventP(DeviceIntPtr device,
   1428                   unsigned int key_code,
   1429                   int is_down)
   1430 {
   1431     xf86PostKeyEventM(device, key_code, is_down);
   1432 }
   1433 
   1434 void
   1435 xf86PostKeyEventM(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 
   1454 void
   1455 xf86PostKeyboardEvent(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 
   1463 InputInfoPtr
   1464 xf86FirstLocalDevice(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 
   1485 int
   1486 xf86ScaleAxis(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 
   1508 Bool
   1509 xf86InitValuatorAxisStruct(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  */
   1524 void
   1525 xf86InitValuatorDefaults(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  */
   1546 void
   1547 xf86DisableDevice(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  */
   1563 void
   1564 xf86EnableDevice(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  */
   1585 void
   1586 xf86PostTouchEvent(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  */
   1608 void
   1609 xf86PostGesturePinchEvent(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  */
   1634 void
   1635 xf86PostGestureSwipeEvent(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 
   1645 void
   1646 xf86InputEnableVTProbe(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 */