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