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