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