2 * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org>
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.
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.
24 * Copyright (c) 2000-2002 by The XFree86 Project, Inc.
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:
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
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.
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).
49 #ifdef HAVE_XORG_CONFIG_H
50 #include <xorg-config.h>
53 #include <X11/Xfuncproto.h>
55 #include <X11/extensions/XI.h>
56 #include <X11/extensions/XIproto.h>
57 #include <X11/Xatom.h>
60 #include "xf86Config.h"
61 #include "xf86Xinput.h"
62 #include "xf86Optrec.h"
63 #include "mipointer.h"
65 #include "loaderProcs.h"
67 #include "exevents.h" /* AddInputDevice */
68 #include "exglobals.h"
70 #include "inpututils.h"
71 #include "optionstr.h"
73 #include <string.h> /* InputClassMatches */
77 #ifdef HAVE_SYS_UTSNAME_H
78 #include <sys/utsname.h>
82 #include <stdint.h> /* for int64_t */
86 #include <ptrveloc.h> /* dix pointer acceleration */
87 #include <xserver-properties.h>
95 /* Valuator verification macro */
96 #define XI_VERIFY_VALUATORS(num_valuators) \
97 if (num_valuators > MAX_VALUATORS) { \
98 xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \
99 " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \
104 xf86InputDevicePostInit(DeviceIntPtr dev
);
107 * Eval config and modify DeviceVelocityRec accordingly
110 ProcessVelocityConfiguration(DeviceIntPtr pDev
, char *devname
, pointer list
,
115 Atom float_prop
= XIGetKnownProperty(XATOM_FLOAT
);
121 /* common settings (available via device properties) */
122 tempf
= xf86SetRealOption(list
, "ConstantDeceleration", 1.0);
124 xf86Msg(X_CONFIG
, "%s: (accel) constant deceleration by %.1f\n",
126 prop
= XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION
);
127 XIChangeDeviceProperty(pDev
, prop
, float_prop
, 32,
128 PropModeReplace
, 1, &tempf
, FALSE
);
131 tempf
= xf86SetRealOption(list
, "AdaptiveDeceleration", 1.0);
133 xf86Msg(X_CONFIG
, "%s: (accel) adaptive deceleration by %.1f\n",
135 prop
= XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION
);
136 XIChangeDeviceProperty(pDev
, prop
, float_prop
, 32,
137 PropModeReplace
, 1, &tempf
, FALSE
);
140 /* select profile by number */
141 tempi
= xf86SetIntOption(list
, "AccelerationProfile",
142 s
->statistics
.profile_number
);
144 prop
= XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER
);
145 if (XIChangeDeviceProperty(pDev
, prop
, XA_INTEGER
, 32,
146 PropModeReplace
, 1, &tempi
, FALSE
) == Success
) {
147 xf86Msg(X_CONFIG
, "%s: (accel) acceleration profile %i\n", devname
,
151 xf86Msg(X_CONFIG
, "%s: (accel) acceleration profile %i is unknown\n",
156 tempf
= xf86SetRealOption(list
, "ExpectedRate", 0);
157 prop
= XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING
);
159 tempf
= 1000.0 / tempf
;
160 XIChangeDeviceProperty(pDev
, prop
, float_prop
, 32,
161 PropModeReplace
, 1, &tempf
, FALSE
);
164 tempf
= xf86SetRealOption(list
, "VelocityScale", s
->corr_mul
);
165 XIChangeDeviceProperty(pDev
, prop
, float_prop
, 32,
166 PropModeReplace
, 1, &tempf
, FALSE
);
169 tempi
= xf86SetIntOption(list
, "VelocityTrackerCount", -1);
171 InitTrackers(s
, tempi
);
173 s
->initial_range
= xf86SetIntOption(list
, "VelocityInitialRange",
176 s
->max_diff
= xf86SetRealOption(list
, "VelocityAbsDiff", s
->max_diff
);
178 tempf
= xf86SetRealOption(list
, "VelocityRelDiff", -1);
180 xf86Msg(X_CONFIG
, "%s: (accel) max rel. velocity difference: %.1f%%\n",
181 devname
, tempf
* 100.0);
182 s
->max_rel_diff
= tempf
;
185 /* Configure softening. If const deceleration is used, this is expected
186 * to provide better subpixel information so we enable
187 * softening by default only if ConstantDeceleration is not used
189 s
->use_softening
= xf86SetBoolOption(list
, "Softening",
190 s
->const_acceleration
== 1.0);
192 s
->average_accel
= xf86SetBoolOption(list
, "AccelerationProfileAveraging",
195 s
->reset_time
= xf86SetIntOption(list
, "VelocityReset", s
->reset_time
);
199 ApplyAccelerationSettings(DeviceIntPtr dev
)
202 DeviceVelocityPtr pVel
;
203 InputInfoPtr pInfo
= (InputInfoPtr
) dev
->public.devicePrivate
;
206 if (dev
->valuator
&& dev
->ptrfeed
) {
207 schemeStr
= xf86SetStrOption(pInfo
->options
, "AccelerationScheme", "");
209 scheme
= dev
->valuator
->accelScheme
.number
;
211 if (!xf86NameCmp(schemeStr
, "predictable"))
212 scheme
= PtrAccelPredictable
;
214 if (!xf86NameCmp(schemeStr
, "lightweight"))
215 scheme
= PtrAccelLightweight
;
217 if (!xf86NameCmp(schemeStr
, "none"))
218 scheme
= PtrAccelNoOp
;
220 /* reinit scheme if needed */
221 if (dev
->valuator
->accelScheme
.number
!= scheme
) {
222 if (dev
->valuator
->accelScheme
.AccelCleanupProc
) {
223 dev
->valuator
->accelScheme
.AccelCleanupProc(dev
);
226 if (InitPointerAccelerationScheme(dev
, scheme
)) {
227 xf86Msg(X_CONFIG
, "%s: (accel) selected scheme %s/%i\n",
228 pInfo
->name
, schemeStr
, scheme
);
231 xf86Msg(X_CONFIG
, "%s: (accel) could not init scheme %s\n",
232 pInfo
->name
, schemeStr
);
233 scheme
= dev
->valuator
->accelScheme
.number
;
237 xf86Msg(X_CONFIG
, "%s: (accel) keeping acceleration scheme %i\n",
238 pInfo
->name
, scheme
);
243 /* process special configuration */
245 case PtrAccelPredictable
:
246 pVel
= GetDevicePredictableAccelData(dev
);
247 ProcessVelocityConfiguration(dev
, pInfo
->name
, pInfo
->options
,
252 i
= xf86SetIntOption(pInfo
->options
, "AccelerationNumerator",
253 dev
->ptrfeed
->ctrl
.num
);
255 dev
->ptrfeed
->ctrl
.num
= i
;
257 i
= xf86SetIntOption(pInfo
->options
, "AccelerationDenominator",
258 dev
->ptrfeed
->ctrl
.den
);
260 dev
->ptrfeed
->ctrl
.den
= i
;
262 i
= xf86SetIntOption(pInfo
->options
, "AccelerationThreshold",
263 dev
->ptrfeed
->ctrl
.threshold
);
265 dev
->ptrfeed
->ctrl
.threshold
= i
;
267 xf86Msg(X_CONFIG
, "%s: (accel) acceleration factor: %.3f\n",
268 pInfo
->name
, ((float) dev
->ptrfeed
->ctrl
.num
) /
269 ((float) dev
->ptrfeed
->ctrl
.den
));
270 xf86Msg(X_CONFIG
, "%s: (accel) acceleration threshold: %i\n",
271 pInfo
->name
, dev
->ptrfeed
->ctrl
.threshold
);
276 ApplyTransformationMatrix(DeviceIntPtr dev
)
278 InputInfoPtr pInfo
= (InputInfoPtr
) dev
->public.devicePrivate
;
281 float matrix
[9] = { 0 };
286 str
= xf86SetStrOption(pInfo
->options
, "TransformationMatrix", NULL
);
290 rc
= sscanf(str
, "%f %f %f %f %f %f %f %f %f", &matrix
[0], &matrix
[1],
291 &matrix
[2], &matrix
[3], &matrix
[4], &matrix
[5], &matrix
[6],
292 &matrix
[7], &matrix
[8]);
295 "%s: invalid format for transformation matrix. Ignoring configuration.\n",
300 XIChangeDeviceProperty(dev
, XIGetKnownProperty(XI_PROP_TRANSFORM
),
301 XIGetKnownProperty(XATOM_FLOAT
), 32,
302 PropModeReplace
, 9, matrix
, FALSE
);
305 /***********************************************************************
307 * xf86ProcessCommonOptions --
309 * Process global options.
311 ***********************************************************************
314 xf86ProcessCommonOptions(InputInfoPtr pInfo
, XF86OptionPtr list
)
316 if (xf86SetBoolOption(list
, "Floating", 0) ||
317 !xf86SetBoolOption(list
, "AlwaysCore", 1) ||
318 !xf86SetBoolOption(list
, "SendCoreEvents", 1) ||
319 !xf86SetBoolOption(list
, "CorePointer", 1) ||
320 !xf86SetBoolOption(list
, "CoreKeyboard", 1)) {
321 xf86Msg(X_CONFIG
, "%s: doesn't report core events\n", pInfo
->name
);
324 pInfo
->flags
|= XI86_ALWAYS_CORE
;
325 xf86Msg(X_CONFIG
, "%s: always reports core events\n", pInfo
->name
);
329 /***********************************************************************
331 * xf86ActivateDevice --
333 * Initialize an input device.
335 * Returns TRUE on success, or FALSE otherwise.
336 ***********************************************************************
339 xf86ActivateDevice(InputInfoPtr pInfo
)
344 dev
= AddInputDevice(serverClient
, pInfo
->device_control
, TRUE
);
347 xf86Msg(X_ERROR
, "Too many input devices. Ignoring %s\n", pInfo
->name
);
352 atom
= MakeAtom(pInfo
->type_name
, strlen(pInfo
->type_name
), TRUE
);
353 AssignTypeAndName(dev
, atom
, pInfo
->name
);
354 dev
->public.devicePrivate
= pInfo
;
357 dev
->coreEvents
= pInfo
->flags
& XI86_ALWAYS_CORE
;
359 dev
->spriteInfo
->spriteOwner
= FALSE
;
361 dev
->config_info
= xf86SetStrOption(pInfo
->options
, "config_info", NULL
);
363 if (serverGeneration
== 1)
365 "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n",
366 pInfo
->name
, pInfo
->type_name
, dev
->id
);
371 /****************************************************************************
373 * Caller: ProcXSetDeviceMode
375 * Change the mode of an extension device.
376 * This function is used to change the mode of a device from reporting
377 * relative motion to reporting absolute positional information, and
379 * The default implementation below is that no such devices are supported.
381 ***********************************************************************
385 SetDeviceMode(ClientPtr client
, DeviceIntPtr dev
, int mode
)
387 InputInfoPtr pInfo
= (InputInfoPtr
) dev
->public.devicePrivate
;
389 if (pInfo
->switch_mode
) {
390 return (*pInfo
->switch_mode
) (client
, dev
, mode
);
396 /***********************************************************************
398 * Caller: ProcXSetDeviceValuators
400 * Set the value of valuators on an extension input device.
401 * This function is used to set the initial value of valuators on
402 * those input devices that are capable of reporting either relative
403 * motion or an absolute position, and allow an initial position to be set.
404 * The default implementation below is that no such devices are supported.
406 ***********************************************************************
410 SetDeviceValuators(ClientPtr client
, DeviceIntPtr dev
, int *valuators
,
411 int first_valuator
, int num_valuators
)
413 InputInfoPtr pInfo
= (InputInfoPtr
) dev
->public.devicePrivate
;
415 if (pInfo
->set_device_valuators
)
416 return (*pInfo
->set_device_valuators
) (pInfo
, valuators
, first_valuator
,
422 /***********************************************************************
424 * Caller: ProcXChangeDeviceControl
426 * Change the specified device controls on an extension input device.
428 ***********************************************************************
432 ChangeDeviceControl(ClientPtr client
, DeviceIntPtr dev
, xDeviceCtl
* control
)
434 InputInfoPtr pInfo
= (InputInfoPtr
) dev
->public.devicePrivate
;
436 if (!pInfo
->control_proc
) {
437 switch (control
->control
) {
439 case DEVICE_ABS_CALIB
:
440 case DEVICE_ABS_AREA
:
442 case DEVICE_RESOLUTION
:
450 return (*pInfo
->control_proc
) (pInfo
, control
);
455 * Get the operating system name from uname and store it statically to avoid
456 * repeating the system call each time MatchOS is checked.
461 #ifdef HAVE_SYS_UTSNAME_H
463 static char host_os
[sizeof(name
.sysname
)] = "";
465 if (*host_os
== '\0') {
466 if (uname(&name
) >= 0)
467 strlcpy(host_os
, name
.sysname
, sizeof(host_os
));
469 strlcpy(host_os
, "unknown", sizeof(host_os
));
479 match_substring(const char *attr
, const char *pattern
)
481 return (strstr(attr
, pattern
)) ? 0 : -1;
484 #ifdef HAVE_FNMATCH_H
486 match_pattern(const char *attr
, const char *pattern
)
488 return fnmatch(pattern
, attr
, 0);
491 #define match_pattern match_substring
494 #ifdef HAVE_FNMATCH_H
496 match_path_pattern(const char *attr
, const char *pattern
)
498 return fnmatch(pattern
, attr
, FNM_PATHNAME
);
501 #define match_path_pattern match_substring
505 * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)"
506 * It is convenient that "" in patterns means "no explicit layout"
509 match_string_implicit(const char *attr
, const char *pattern
)
511 if (strlen(pattern
)) {
512 return strcmp(attr
, pattern
);
515 return strcmp(attr
, "(implicit)");
520 * Match an attribute against a list of NULL terminated arrays of patterns.
521 * If a pattern in each list entry is matched, return TRUE.
524 MatchAttrToken(const char *attr
, struct xorg_list
*patterns
,
525 int (*compare
) (const char *attr
, const char *pattern
))
527 const xf86MatchGroup
*group
;
529 /* If there are no patterns, accept the match */
530 if (xorg_list_is_empty(patterns
))
533 /* If there are patterns but no attribute, reject the match */
538 * Otherwise, iterate the list of patterns ensuring each entry has a
539 * match. Each list entry is a separate Match line of the same type.
541 xorg_list_for_each_entry(group
, patterns
, entry
) {
545 for (cur
= group
->values
; *cur
; cur
++)
546 if ((*compare
) (attr
, *cur
) == 0) {
554 /* All the entries in the list matched the attribute */
559 * Classes without any Match statements match all devices. Otherwise, all
560 * statements must match.
563 InputClassMatches(const XF86ConfInputClassPtr iclass
, const InputInfoPtr idev
,
564 const InputAttributes
* attrs
)
566 /* MatchProduct substring */
568 (attrs
->product
, &iclass
->match_product
, match_substring
))
571 /* MatchVendor substring */
572 if (!MatchAttrToken(attrs
->vendor
, &iclass
->match_vendor
, match_substring
))
575 /* MatchDevicePath pattern */
577 (attrs
->device
, &iclass
->match_device
, match_path_pattern
))
580 /* MatchOS case-insensitive string */
581 if (!MatchAttrToken(HostOS(), &iclass
->match_os
, strcasecmp
))
584 /* MatchPnPID pattern */
585 if (!MatchAttrToken(attrs
->pnp_id
, &iclass
->match_pnpid
, match_pattern
))
588 /* MatchUSBID pattern */
589 if (!MatchAttrToken(attrs
->usb_id
, &iclass
->match_usbid
, match_pattern
))
592 /* MatchDriver string */
593 if (!MatchAttrToken(idev
->driver
, &iclass
->match_driver
, strcmp
))
598 * See if any of the device's tags match any of the MatchTag tokens.
600 if (!xorg_list_is_empty(&iclass
->match_tag
)) {
606 for (tag
= attrs
->tags
, match
= FALSE
; *tag
; tag
++) {
607 if (MatchAttrToken(*tag
, &iclass
->match_tag
, strcmp
)) {
616 /* MatchLayout string */
617 if (!xorg_list_is_empty(&iclass
->match_layout
)) {
618 if (!MatchAttrToken(xf86ConfigLayout
.id
,
619 &iclass
->match_layout
, match_string_implicit
))
623 /* MatchIs* booleans */
624 if (iclass
->is_keyboard
.set
&&
625 iclass
->is_keyboard
.val
!= ! !(attrs
->flags
& ATTR_KEYBOARD
))
627 if (iclass
->is_pointer
.set
&&
628 iclass
->is_pointer
.val
!= ! !(attrs
->flags
& ATTR_POINTER
))
630 if (iclass
->is_joystick
.set
&&
631 iclass
->is_joystick
.val
!= ! !(attrs
->flags
& ATTR_JOYSTICK
))
633 if (iclass
->is_tablet
.set
&&
634 iclass
->is_tablet
.val
!= ! !(attrs
->flags
& ATTR_TABLET
))
636 if (iclass
->is_touchpad
.set
&&
637 iclass
->is_touchpad
.val
!= ! !(attrs
->flags
& ATTR_TOUCHPAD
))
639 if (iclass
->is_touchscreen
.set
&&
640 iclass
->is_touchscreen
.val
!= ! !(attrs
->flags
& ATTR_TOUCHSCREEN
))
647 * Merge in any InputClass configurations. Options in each InputClass
648 * section have more priority than the original device configuration as
649 * well as any previous InputClass sections.
652 MergeInputClasses(const InputInfoPtr idev
, const InputAttributes
* attrs
)
654 XF86ConfInputClassPtr cl
;
655 XF86OptionPtr classopts
;
657 for (cl
= xf86configptr
->conf_inputclass_lst
; cl
; cl
= cl
->list
.next
) {
658 if (!InputClassMatches(cl
, idev
, attrs
))
661 /* Collect class options and driver settings */
662 classopts
= xf86optionListDup(cl
->option_lst
);
665 idev
->driver
= xstrdup(cl
->driver
);
667 xf86Msg(X_ERROR
, "Failed to allocate memory while merging "
668 "InputClass configuration");
671 classopts
= xf86ReplaceStrOption(classopts
, "driver", idev
->driver
);
674 /* Apply options to device with InputClass settings preferred. */
675 xf86Msg(X_CONFIG
, "%s: Applying InputClass \"%s\"\n",
676 idev
->name
, cl
->identifier
);
677 idev
->options
= xf86optionListMerge(idev
->options
, classopts
);
684 * Iterate the list of classes and look for Option "Ignore". Return the
685 * value of the last matching class and holler when returning TRUE.
688 IgnoreInputClass(const InputInfoPtr idev
, const InputAttributes
* attrs
)
690 XF86ConfInputClassPtr cl
;
692 const char *ignore_class
;
694 for (cl
= xf86configptr
->conf_inputclass_lst
; cl
; cl
= cl
->list
.next
) {
695 if (!InputClassMatches(cl
, idev
, attrs
))
697 if (xf86findOption(cl
->option_lst
, "Ignore")) {
698 ignore
= xf86CheckBoolOption(cl
->option_lst
, "Ignore", FALSE
);
699 ignore_class
= cl
->identifier
;
704 xf86Msg(X_CONFIG
, "%s: Ignoring device from InputClass \"%s\"\n",
705 idev
->name
, ignore_class
);
710 xf86AllocateInput(void)
714 pInfo
= calloc(sizeof(*pInfo
), 1);
719 pInfo
->type_name
= "UNKNOWN";
724 /* Append InputInfoRec to the tail of xf86InputDevs. */
726 xf86AddInput(InputDriverPtr drv
, InputInfoPtr pInfo
)
728 InputInfoPtr
*prev
= NULL
;
731 pInfo
->module
= DuplicateModule(drv
->module
, NULL
);
733 for (prev
= &xf86InputDevs
; *prev
; prev
= &(*prev
)->next
);
738 xf86CollectInputOptions(pInfo
, (const char **) drv
->default_options
);
739 xf86OptionListReport(pInfo
->options
);
740 xf86ProcessCommonOptions(pInfo
, pInfo
->options
);
744 * Remove an entry from xf86InputDevs and free all the device's information.
747 xf86DeleteInput(InputInfoPtr pInp
, int flags
)
749 /* First check if the inputdev is valid. */
754 UnloadModule(pInp
->module
);
756 /* This should *really* be handled in drv->UnInit(dev) call instead, but
757 * if the driver forgets about it make sure we free it or at least crash
758 * with flying colors */
761 FreeInputAttributes(pInp
->attrs
);
763 /* Remove the entry from the list. */
764 if (pInp
== xf86InputDevs
)
765 xf86InputDevs
= pInp
->next
;
767 InputInfoPtr p
= xf86InputDevs
;
769 while (p
&& p
->next
!= pInp
)
772 p
->next
= pInp
->next
;
773 /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
778 xf86optionListFree(pInp
->options
);
783 * Apply backend-specific initialization. Invoked after ActivateDevice(),
784 * i.e. after the driver successfully completed DEVICE_INIT and the device
786 * @param dev the device
787 * @return Success or an error code
790 xf86InputDevicePostInit(DeviceIntPtr dev
)
792 ApplyAccelerationSettings(dev
);
793 ApplyTransformationMatrix(dev
);
798 * Create a new input device, activate and enable it.
800 * Possible return codes:
801 * BadName .. a bad driver name was supplied.
802 * BadImplementation ... The driver does not have a PreInit function. This
804 * BadMatch .. device initialization failed.
805 * BadAlloc .. too many input devices
807 * @param idev The device, already set up with identifier, driver, and the
809 * @param pdev Pointer to the new device, if Success was reported.
810 * @param enable Enable the device after activating it.
812 * @return Success or an error code
815 xf86NewInputDevice(InputInfoPtr pInfo
, DeviceIntPtr
*pdev
, BOOL enable
)
817 InputDriverPtr drv
= NULL
;
818 DeviceIntPtr dev
= NULL
;
821 /* Memory leak for every attached device if we don't
822 * test if the module is already loaded first */
823 drv
= xf86LookupInputDriver(pInfo
->driver
);
825 if (xf86LoadOneModule(pInfo
->driver
, NULL
))
826 drv
= xf86LookupInputDriver(pInfo
->driver
);
828 xf86Msg(X_ERROR
, "No input driver matching `%s'\n", pInfo
->driver
);
833 xf86Msg(X_INFO
, "Using input driver '%s' for '%s'\n", drv
->driverName
,
838 "Input driver `%s' has no PreInit function (ignoring)\n",
840 rval
= BadImplementation
;
844 xf86AddInput(drv
, pInfo
);
846 rval
= drv
->PreInit(drv
, pInfo
, 0);
848 if (rval
!= Success
) {
849 xf86Msg(X_ERROR
, "PreInit returned %d for \"%s\"\n", rval
, pInfo
->name
);
853 if (!(dev
= xf86ActivateDevice(pInfo
))) {
858 rval
= ActivateDevice(dev
, TRUE
);
859 if (rval
!= Success
) {
860 xf86Msg(X_ERROR
, "Couldn't init device \"%s\"\n", pInfo
->name
);
861 RemoveDevice(dev
, TRUE
);
865 rval
= xf86InputDevicePostInit(dev
);
866 if (rval
!= Success
) {
867 xf86Msg(X_ERROR
, "Couldn't post-init device \"%s\"\n", pInfo
->name
);
868 RemoveDevice(dev
, TRUE
);
872 /* Enable it if it's properly initialised and we're currently in the VT */
873 if (enable
&& dev
->inited
&& dev
->startup
&& xf86VTOwner()) {
875 EnableDevice(dev
, TRUE
);
878 xf86Msg(X_ERROR
, "Couldn't init device \"%s\"\n", pInfo
->name
);
879 RemoveDevice(dev
, TRUE
);
883 /* send enter/leave event, update sprite window */
884 CheckMotion(NULL
, dev
);
893 if (drv
&& drv
->UnInit
)
894 drv
->UnInit(drv
, pInfo
, 0);
896 xf86DeleteInput(pInfo
, 0);
902 NewInputDeviceRequest(InputOption
*options
, InputAttributes
* attrs
,
905 InputInfoPtr pInfo
= NULL
;
906 InputOption
*option
= NULL
;
910 pInfo
= xf86AllocateInput();
914 nt_list_for_each_entry(option
, options
, list
.next
) {
915 const char *key
= input_option_get_key(option
);
916 const char *value
= input_option_get_value(option
);
918 if (strcasecmp(key
, "driver") == 0) {
923 pInfo
->driver
= xstrdup(value
);
924 if (!pInfo
->driver
) {
930 if (strcasecmp(key
, "name") == 0 || strcasecmp(key
, "identifier") == 0) {
935 pInfo
->name
= xstrdup(value
);
942 if (strcmp(key
, "_source") == 0 &&
943 (strcmp(value
, "server/hal") == 0 ||
944 strcmp(value
, "server/udev") == 0 ||
945 strcmp(value
, "server/wscons") == 0)) {
947 if (!xf86Info
.autoAddDevices
) {
954 nt_list_for_each_entry(option
, options
, list
.next
) {
955 /* Copy option key/value strings from the provided list */
956 pInfo
->options
= xf86AddNewOption(pInfo
->options
,
957 input_option_get_key(option
),
958 input_option_get_value(option
));
961 /* Apply InputClass settings */
963 if (IgnoreInputClass(pInfo
, attrs
)) {
968 rval
= MergeInputClasses(pInfo
, attrs
);
972 pInfo
->attrs
= DuplicateInputAttributes(attrs
);
976 xf86Msg(X_INFO
, "No identifier specified, ignoring this device.\n");
981 if (!pInfo
->driver
) {
982 xf86Msg(X_INFO
, "No input driver specified, ignoring this device.\n");
984 "This device may have been added with another device file.\n");
989 rval
= xf86NewInputDevice(pInfo
, pdev
,
991 (is_auto
&& xf86Info
.autoEnableDevices
)));
996 if (is_auto
&& !xf86Info
.autoAddDevices
)
997 xf86Msg(X_INFO
, "AutoAddDevices is off - not adding device.\n");
998 xf86DeleteInput(pInfo
, 0);
1003 DeleteInputDeviceRequest(DeviceIntPtr pDev
)
1005 InputInfoPtr pInfo
= (InputInfoPtr
) pDev
->public.devicePrivate
;
1006 InputDriverPtr drv
= NULL
;
1007 Bool isMaster
= IsMaster(pDev
);
1009 if (pInfo
) /* need to get these before RemoveDevice */
1013 RemoveDevice(pDev
, TRUE
);
1015 if (!isMaster
&& pInfo
!= NULL
) {
1017 drv
->UnInit(drv
, pInfo
, 0);
1019 xf86DeleteInput(pInfo
, 0);
1025 * convenient functions to post events
1029 xf86PostMotionEvent(DeviceIntPtr device
,
1030 int is_absolute
, int first_valuator
, int num_valuators
, ...)
1036 XI_VERIFY_VALUATORS(num_valuators
);
1038 valuator_mask_zero(&mask
);
1039 va_start(var
, num_valuators
);
1040 for (i
= 0; i
< num_valuators
; i
++)
1041 valuator_mask_set(&mask
, first_valuator
+ i
, va_arg(var
, int));
1045 xf86PostMotionEventM(device
, is_absolute
, &mask
);
1049 xf86PostMotionEventP(DeviceIntPtr device
,
1052 int num_valuators
, const int *valuators
)
1056 XI_VERIFY_VALUATORS(num_valuators
);
1058 valuator_mask_set_range(&mask
, first_valuator
, num_valuators
, valuators
);
1059 xf86PostMotionEventM(device
, is_absolute
, &mask
);
1063 xf86CheckMotionEvent4DGA(DeviceIntPtr device
, int is_absolute
,
1064 const ValuatorMask
*mask
)
1069 ScreenPtr scr
= NULL
;
1072 /* The evdev driver may not always send all axes across. */
1073 if (valuator_mask_isset(mask
, 0) || valuator_mask_isset(mask
, 1)) {
1074 scr
= miPointerGetScreen(device
);
1080 if (valuator_mask_isset(mask
, 0)) {
1081 dx
= valuator_mask_get(mask
, 0);
1083 dx
-= device
->last
.valuators
[0];
1086 if (valuator_mask_isset(mask
, 1)) {
1087 dy
= valuator_mask_get(mask
, 1);
1089 dy
-= device
->last
.valuators
[1];
1092 if (DGAStealMotionEvent(device
, idx
, dx
, dy
))
1097 for (i
= 2; i
< valuator_mask_size(mask
); i
++) {
1102 if (i
>= device
->valuator
->numAxes
)
1105 if (!valuator_mask_isset(mask
, i
))
1108 ax
= &device
->valuator
->axes
[i
];
1110 if (ax
->scroll
.type
== SCROLL_TYPE_NONE
)
1114 scr
= miPointerGetScreen(device
);
1120 incr
= ax
->scroll
.increment
;
1121 val
= valuator_mask_get(mask
, i
);
1123 if (ax
->scroll
.type
== SCROLL_TYPE_VERTICAL
) {
1125 button
= 4; /* up */
1127 button
= 5; /* down */
1128 } else { /* SCROLL_TYPE_HORIZONTAL */
1130 button
= 6; /* left */
1132 button
= 7; /* right */
1135 if (DGAStealButtonEvent(device
, idx
, button
, 1) &&
1136 DGAStealButtonEvent(device
, idx
, button
, 0))
1146 xf86PostMotionEventM(DeviceIntPtr device
,
1147 int is_absolute
, const ValuatorMask
*mask
)
1151 if (xf86CheckMotionEvent4DGA(device
, is_absolute
, mask
))
1154 if (valuator_mask_num_valuators(mask
) > 0) {
1156 flags
= POINTER_ABSOLUTE
;
1158 flags
= POINTER_RELATIVE
| POINTER_ACCELERATE
;
1161 QueuePointerEvents(device
, MotionNotify
, 0, flags
, mask
);
1165 xf86PostProximityEvent(DeviceIntPtr device
,
1166 int is_in
, int first_valuator
, int num_valuators
, ...)
1172 XI_VERIFY_VALUATORS(num_valuators
);
1174 valuator_mask_zero(&mask
);
1175 va_start(var
, num_valuators
);
1176 for (i
= 0; i
< num_valuators
; i
++)
1177 valuator_mask_set(&mask
, first_valuator
+ i
, va_arg(var
, int));
1181 xf86PostProximityEventM(device
, is_in
, &mask
);
1185 xf86PostProximityEventP(DeviceIntPtr device
,
1188 int num_valuators
, const int *valuators
)
1192 XI_VERIFY_VALUATORS(num_valuators
);
1194 valuator_mask_set_range(&mask
, first_valuator
, num_valuators
, valuators
);
1195 xf86PostProximityEventM(device
, is_in
, &mask
);
1199 xf86PostProximityEventM(DeviceIntPtr device
,
1200 int is_in
, const ValuatorMask
*mask
)
1202 QueueProximityEvents(device
, is_in
? ProximityIn
: ProximityOut
, mask
);
1206 xf86PostButtonEvent(DeviceIntPtr device
,
1209 int is_down
, int first_valuator
, int num_valuators
, ...)
1215 XI_VERIFY_VALUATORS(num_valuators
);
1217 valuator_mask_zero(&mask
);
1219 va_start(var
, num_valuators
);
1220 for (i
= 0; i
< num_valuators
; i
++)
1221 valuator_mask_set(&mask
, first_valuator
+ i
, va_arg(var
, int));
1225 xf86PostButtonEventM(device
, is_absolute
, button
, is_down
, &mask
);
1229 xf86PostButtonEventP(DeviceIntPtr device
,
1234 int num_valuators
, const int *valuators
)
1238 XI_VERIFY_VALUATORS(num_valuators
);
1240 valuator_mask_set_range(&mask
, first_valuator
, num_valuators
, valuators
);
1241 xf86PostButtonEventM(device
, is_absolute
, button
, is_down
, &mask
);
1245 xf86PostButtonEventM(DeviceIntPtr device
,
1247 int button
, int is_down
, const ValuatorMask
*mask
)
1251 if (valuator_mask_num_valuators(mask
) > 0) {
1253 flags
= POINTER_ABSOLUTE
;
1255 flags
= POINTER_RELATIVE
| POINTER_ACCELERATE
;
1259 if (miPointerGetScreen(device
)) {
1260 int index
= miPointerGetScreen(device
)->myNum
;
1262 if (DGAStealButtonEvent(device
, index
, button
, is_down
))
1267 QueuePointerEvents(device
,
1268 is_down
? ButtonPress
: ButtonRelease
, button
,
1273 xf86PostKeyEvent(DeviceIntPtr device
,
1274 unsigned int key_code
,
1276 int is_absolute
, int first_valuator
, int num_valuators
, ...)
1282 XI_VERIFY_VALUATORS(num_valuators
);
1284 valuator_mask_zero(&mask
);
1286 va_start(var
, num_valuators
);
1287 for (i
= 0; i
< num_valuators
; i
++)
1288 valuator_mask_set(&mask
, first_valuator
+ i
, va_arg(var
, int));
1292 xf86PostKeyEventM(device
, key_code
, is_down
, is_absolute
, &mask
);
1296 xf86PostKeyEventP(DeviceIntPtr device
,
1297 unsigned int key_code
,
1300 int first_valuator
, int num_valuators
, const int *valuators
)
1304 XI_VERIFY_VALUATORS(num_valuators
);
1306 valuator_mask_set_range(&mask
, first_valuator
, num_valuators
, valuators
);
1307 xf86PostKeyEventM(device
, key_code
, is_down
, is_absolute
, &mask
);
1311 xf86PostKeyEventM(DeviceIntPtr device
,
1312 unsigned int key_code
,
1313 int is_down
, int is_absolute
, const ValuatorMask
*mask
)
1316 DeviceIntPtr pointer
;
1318 /* Some pointers send key events, paired device is wrong then. */
1319 pointer
= GetMaster(device
, POINTER_OR_FLOAT
);
1321 if (miPointerGetScreen(pointer
)) {
1322 int index
= miPointerGetScreen(pointer
)->myNum
;
1324 if (DGAStealKeyEvent(device
, index
, key_code
, is_down
))
1329 QueueKeyboardEvents(device
,
1330 is_down
? KeyPress
: KeyRelease
, key_code
, mask
);
1334 xf86PostKeyboardEvent(DeviceIntPtr device
, unsigned int key_code
, int is_down
)
1338 valuator_mask_zero(&mask
);
1339 xf86PostKeyEventM(device
, key_code
, is_down
, 0, &mask
);
1343 xf86FirstLocalDevice(void)
1345 return xf86InputDevs
;
1349 * Cx - raw data from touch screen
1350 * to_max - scaled highest dimension
1351 * (remember, this is of rows - 1 because of 0 origin)
1352 * to_min - scaled lowest dimension
1353 * from_max - highest raw value from touch screen calibration
1354 * from_min - lowest raw value from touch screen calibration
1356 * This function is the same for X or Y coordinates.
1357 * You may have to reverse the high and low values to compensate for
1358 * different orgins on the touch screen vs X.
1360 * e.g. to scale from device coordinates into screen coordinates, call
1361 * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max);
1365 xf86ScaleAxis(int Cx
, int to_max
, int to_min
, int from_max
, int from_min
)
1368 int64_t to_width
= to_max
- to_min
;
1369 int64_t from_width
= from_max
- from_min
;
1372 X
= (int) (((to_width
* (Cx
- from_min
)) / from_width
) + to_min
);
1376 ErrorF("Divide by Zero in xf86ScaleAxis\n");
1388 xf86InitValuatorAxisStruct(DeviceIntPtr dev
, int axnum
, Atom label
, int minval
,
1389 int maxval
, int resolution
, int min_res
, int max_res
,
1392 if (!dev
|| !dev
->valuator
)
1395 return InitValuatorAxisStruct(dev
, axnum
, label
, minval
, maxval
, resolution
,
1396 min_res
, max_res
, mode
);
1400 * Set the valuator values to be in sync with dix/event.c
1401 * DefineInitialRootWindow().
1404 xf86InitValuatorDefaults(DeviceIntPtr dev
, int axnum
)
1407 dev
->valuator
->axisVal
[0] = screenInfo
.screens
[0]->width
/ 2;
1408 dev
->last
.valuators
[0] = dev
->valuator
->axisVal
[0];
1410 else if (axnum
== 1) {
1411 dev
->valuator
->axisVal
[1] = screenInfo
.screens
[0]->height
/ 2;
1412 dev
->last
.valuators
[1] = dev
->valuator
->axisVal
[1];
1417 * Deactivate a device. Call this function from the driver if you receive a
1418 * read error or something else that spoils your day.
1419 * Device will be moved to the off_devices list, but it will still be there
1420 * until you really clean up after it.
1421 * Notifies the client about an inactive device.
1423 * @param panic True if device is unrecoverable and needs to be removed.
1426 xf86DisableDevice(DeviceIntPtr dev
, Bool panic
)
1429 DisableDevice(dev
, TRUE
);
1432 SendDevicePresenceEvent(dev
->id
, DeviceUnrecoverable
);
1433 DeleteInputDeviceRequest(dev
);
1438 * Reactivate a device. Call this function from the driver if you just found
1439 * out that the read error wasn't quite that bad after all.
1440 * Device will be re-activated, and an event sent to the client.
1443 xf86EnableDevice(DeviceIntPtr dev
)
1445 EnableDevice(dev
, TRUE
);
1449 * Post a touch event with optional valuators. If this is the first touch in
1450 * the sequence, at least x & y valuators must be provided. The driver is
1451 * responsible for maintaining the correct event sequence (TouchBegin, TouchUpdate,
1452 * TouchEnd). Submitting an update or end event for a unregistered touchid will
1454 * Touch IDs may be reused by the driver but only after a TouchEnd has been
1455 * submitted for that touch ID.
1457 * @param dev The device to post the event for
1458 * @param touchid The touchid of the current touch event. Must be an
1459 * existing ID for TouchUpdate or TouchEnd events
1460 * @param type One of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd
1461 * @param flags Flags for this event
1462 * @param The valuator mask with all valuators set for this event.
1465 xf86PostTouchEvent(DeviceIntPtr dev
, uint32_t touchid
, uint16_t type
,
1466 uint32_t flags
, const ValuatorMask
*mask
)
1469 QueueTouchEvents(dev
, type
, touchid
, flags
, mask
);
1472 /* end of xf86Xinput.c */