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