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