diff options
Diffstat (limited to 'xorg-server/hw/xfree86/common/xf86Xinput.c')
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86Xinput.c | 2802 |
1 files changed, 1401 insertions, 1401 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index a53531cc1..d22fdc8b9 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -1,1401 +1,1401 @@ -/*
- * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Frederic Lepied not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Frederic Lepied makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-/*
- * Copyright (c) 2000-2002 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/Xfuncproto.h>
-#include <X11/Xmd.h>
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include <X11/Xatom.h>
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86Config.h"
-#include "xf86Xinput.h"
-#include "xf86Optrec.h"
-#include "mipointer.h"
-#include "extinit.h"
-#include "loaderProcs.h"
-
-#include "exevents.h" /* AddInputDevice */
-#include "exglobals.h"
-#include "eventstr.h"
-#include "inpututils.h"
-
-#include <string.h> /* InputClassMatches */
-#ifdef HAVE_FNMATCH_H
-#include <fnmatch.h>
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-
-#include <stdarg.h>
-#include <stdint.h> /* for int64_t */
-
-#include "mi.h"
-
-#include <ptrveloc.h> /* dix pointer acceleration */
-#include <xserver-properties.h>
-
-#ifdef XFreeXDGA
-#include "dgaproc.h"
-#endif
-
-#include "xkbsrv.h"
-
-/* Valuator verification macro */
-#define XI_VERIFY_VALUATORS(num_valuators) \
- if (num_valuators > MAX_VALUATORS) { \
- xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \
- " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \
- return; \
- }
-
-static int
-xf86InputDevicePostInit(DeviceIntPtr dev);
-
-/**
- * Eval config and modify DeviceVelocityRec accordingly
- */
-static void
-ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list,
- DeviceVelocityPtr s)
-{
- int tempi;
- float tempf;
- Atom float_prop = XIGetKnownProperty(XATOM_FLOAT);
- Atom prop;
-
- if(!s)
- return;
-
- /* common settings (available via device properties) */
- tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0);
- if (tempf > 1.0) {
- xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n",
- devname, tempf);
- prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- }
-
- tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0);
- if (tempf > 1.0) {
- xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n",
- devname, tempf);
- prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- }
-
- /* select profile by number */
- tempi = xf86SetIntOption(list, "AccelerationProfile",
- s->statistics.profile_number);
-
- prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
- if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32,
- PropModeReplace, 1, &tempi, FALSE) == Success) {
- xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname,
- tempi);
- } else {
- xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n",
- devname, tempi);
- }
-
- /* set scaling */
- tempf = xf86SetRealOption(list, "ExpectedRate", 0);
- prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
- if (tempf > 0) {
- tempf = 1000.0 / tempf;
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- } else {
- tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul);
- XIChangeDeviceProperty(pDev, prop, float_prop, 32,
- PropModeReplace, 1, &tempf, FALSE);
- }
-
- tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1);
- if (tempi > 1)
- InitTrackers(s, tempi);
-
- s->initial_range = xf86SetIntOption(list, "VelocityInitialRange",
- s->initial_range);
-
- s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff);
-
- tempf = xf86SetRealOption(list, "VelocityRelDiff", -1);
- if (tempf >= 0) {
- xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n",
- devname, tempf*100.0);
- s->max_rel_diff = tempf;
- }
-
- /* Configure softening. If const deceleration is used, this is expected
- * to provide better subpixel information so we enable
- * softening by default only if ConstantDeceleration is not used
- */
- s->use_softening = xf86SetBoolOption(list, "Softening",
- s->const_acceleration == 1.0);
-
- s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging",
- s->average_accel);
-
- s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time);
-}
-
-static void
-ApplyAccelerationSettings(DeviceIntPtr dev){
- int scheme, i;
- DeviceVelocityPtr pVel;
- InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
- char* schemeStr;
-
- if (dev->valuator && dev->ptrfeed) {
- schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", "");
-
- scheme = dev->valuator->accelScheme.number;
-
- if (!xf86NameCmp(schemeStr, "predictable"))
- scheme = PtrAccelPredictable;
-
- if (!xf86NameCmp(schemeStr, "lightweight"))
- scheme = PtrAccelLightweight;
-
- if (!xf86NameCmp(schemeStr, "none"))
- scheme = PtrAccelNoOp;
-
- /* reinit scheme if needed */
- if (dev->valuator->accelScheme.number != scheme) {
- if (dev->valuator->accelScheme.AccelCleanupProc) {
- dev->valuator->accelScheme.AccelCleanupProc(dev);
- }
-
- if (InitPointerAccelerationScheme(dev, scheme)) {
- xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n",
- pInfo->name, schemeStr, scheme);
- } else {
- xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n",
- pInfo->name, schemeStr);
- scheme = dev->valuator->accelScheme.number;
- }
- } else {
- xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n",
- pInfo->name, scheme);
- }
-
- free(schemeStr);
-
- /* process special configuration */
- switch (scheme) {
- case PtrAccelPredictable:
- pVel = GetDevicePredictableAccelData(dev);
- ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options,
- pVel);
- break;
- }
-
- i = xf86SetIntOption(pInfo->options, "AccelerationNumerator",
- dev->ptrfeed->ctrl.num);
- if (i >= 0)
- dev->ptrfeed->ctrl.num = i;
-
- i = xf86SetIntOption(pInfo->options, "AccelerationDenominator",
- dev->ptrfeed->ctrl.den);
- if (i > 0)
- dev->ptrfeed->ctrl.den = i;
-
- i = xf86SetIntOption(pInfo->options, "AccelerationThreshold",
- dev->ptrfeed->ctrl.threshold);
- if (i >= 0)
- dev->ptrfeed->ctrl.threshold = i;
-
- xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n",
- pInfo->name, ((float)dev->ptrfeed->ctrl.num)/
- ((float)dev->ptrfeed->ctrl.den));
- xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n",
- pInfo->name, dev->ptrfeed->ctrl.threshold);
- }
-}
-
-/***********************************************************************
- *
- * xf86ProcessCommonOptions --
- *
- * Process global options.
- *
- ***********************************************************************
- */
-void
-xf86ProcessCommonOptions(InputInfoPtr pInfo,
- pointer list)
-{
- if (xf86SetBoolOption(list, "Floating", 0) ||
- !xf86SetBoolOption(list, "AlwaysCore", 1) ||
- !xf86SetBoolOption(list, "SendCoreEvents", 1) ||
- !xf86SetBoolOption(list, "CorePointer", 1) ||
- !xf86SetBoolOption(list, "CoreKeyboard", 1)) {
- xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name);
- } else {
- pInfo->flags |= XI86_ALWAYS_CORE;
- xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name);
- }
-}
-
-/***********************************************************************
- *
- * xf86ActivateDevice --
- *
- * Initialize an input device.
- *
- * Returns TRUE on success, or FALSE otherwise.
- ***********************************************************************
- */
-static DeviceIntPtr
-xf86ActivateDevice(InputInfoPtr pInfo)
-{
- DeviceIntPtr dev;
- Atom atom;
-
- dev = AddInputDevice(serverClient, pInfo->device_control, TRUE);
-
- if (dev == NULL)
- {
- xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n",
- pInfo->name);
- pInfo->dev = NULL;
- return NULL;
- }
-
- atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE);
- AssignTypeAndName(dev, atom, pInfo->name);
- dev->public.devicePrivate = pInfo;
- pInfo->dev = dev;
-
- dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE;
- dev->type = SLAVE;
- dev->spriteInfo->spriteOwner = FALSE;
-
- dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL);
-
- if (serverGeneration == 1)
- xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n",
- pInfo->name, pInfo->type_name, dev->id);
-
- return dev;
-}
-
-/****************************************************************************
- *
- * Caller: ProcXSetDeviceMode
- *
- * Change the mode of an extension device.
- * This function is used to change the mode of a device from reporting
- * relative motion to reporting absolute positional information, and
- * vice versa.
- * The default implementation below is that no such devices are supported.
- *
- ***********************************************************************
- */
-
-int
-SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode)
-{
- InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-
- if (pInfo->switch_mode) {
- return (*pInfo->switch_mode)(client, dev, mode);
- }
- else
- return BadMatch;
-}
-
-
-/***********************************************************************
- *
- * Caller: ProcXSetDeviceValuators
- *
- * Set the value of valuators on an extension input device.
- * This function is used to set the initial value of valuators on
- * those input devices that are capable of reporting either relative
- * motion or an absolute position, and allow an initial position to be set.
- * The default implementation below is that no such devices are supported.
- *
- ***********************************************************************
- */
-
-int
-SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators,
- int first_valuator, int num_valuators)
-{
- InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate;
-
- if (pInfo->set_device_valuators)
- return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator,
- num_valuators);
-
- return BadMatch;
-}
-
-
-/***********************************************************************
- *
- * Caller: ProcXChangeDeviceControl
- *
- * Change the specified device controls on an extension input device.
- *
- ***********************************************************************
- */
-
-int
-ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control)
-{
- InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate;
-
- if (!pInfo->control_proc) {
- switch (control->control) {
- case DEVICE_CORE:
- case DEVICE_ABS_CALIB:
- case DEVICE_ABS_AREA:
- return BadMatch;
- case DEVICE_RESOLUTION:
- case DEVICE_ENABLE:
- return Success;
- default:
- return BadMatch;
- }
- }
- else {
- return (*pInfo->control_proc)(pInfo, control);
- }
-}
-
-/*
- * Get the operating system name from uname and store it statically to avoid
- * repeating the system call each time MatchOS is checked.
- */
-static const char *
-HostOS(void)
-{
-#ifdef HAVE_SYS_UTSNAME_H
- struct utsname name;
- static char host_os[sizeof(name.sysname)] = "";
-
- if (*host_os == '\0') {
- if (uname(&name) >= 0)
- strcpy(host_os, name.sysname);
- else {
- strncpy(host_os, "unknown", sizeof(host_os));
- host_os[sizeof(host_os)-1] = '\0';
- }
- }
- return host_os;
-#else
- return "";
-#endif
-}
-
-static int
-match_substring(const char *attr, const char *pattern)
-{
- return (strstr(attr, pattern)) ? 0 : -1;
-}
-
-#ifdef HAVE_FNMATCH_H
-static int
-match_pattern(const char *attr, const char *pattern)
-{
- return fnmatch(pattern, attr, 0);
-}
-#else
-#define match_pattern match_substring
-#endif
-
-#ifdef HAVE_FNMATCH_H
-static int
-match_path_pattern(const char *attr, const char *pattern)
-{
- return fnmatch(pattern, attr, FNM_PATHNAME);
-}
-#else
-#define match_path_pattern match_substring
-#endif
-
-/*
- * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)"
- * It is convenient that "" in patterns means "no explicit layout"
- */
-static int
-match_string_implicit(const char *attr, const char *pattern)
-{
- if (strlen(pattern)) {
- return strcmp(attr, pattern);
- } else {
- return strcmp(attr,"(implicit)");
- }
-}
-
-/*
- * Match an attribute against a list of NULL terminated arrays of patterns.
- * If a pattern in each list entry is matched, return TRUE.
- */
-static Bool
-MatchAttrToken(const char *attr, struct list *patterns,
- int (*compare)(const char *attr, const char *pattern))
-{
- const xf86MatchGroup *group;
-
- /* If there are no patterns, accept the match */
- if (list_is_empty(patterns))
- return TRUE;
-
- /* If there are patterns but no attribute, reject the match */
- if (!attr)
- return FALSE;
-
- /*
- * Otherwise, iterate the list of patterns ensuring each entry has a
- * match. Each list entry is a separate Match line of the same type.
- */
- list_for_each_entry(group, patterns, entry) {
- char * const *cur;
- Bool match = FALSE;
-
- for (cur = group->values; *cur; cur++)
- if ((*compare)(attr, *cur) == 0) {
- match = TRUE;
- break;
- }
- if (!match)
- return FALSE;
- }
-
- /* All the entries in the list matched the attribute */
- return TRUE;
-}
-
-/*
- * Classes without any Match statements match all devices. Otherwise, all
- * statements must match.
- */
-static Bool
-InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev,
- const InputAttributes *attrs)
-{
- /* MatchProduct substring */
- if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring))
- return FALSE;
-
- /* MatchVendor substring */
- if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring))
- return FALSE;
-
- /* MatchDevicePath pattern */
- if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern))
- return FALSE;
-
- /* MatchOS case-insensitive string */
- if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp))
- return FALSE;
-
- /* MatchPnPID pattern */
- if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern))
- return FALSE;
-
- /* MatchUSBID pattern */
- if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern))
- return FALSE;
-
- /* MatchDriver string */
- if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp))
- return FALSE;
-
- /*
- * MatchTag string
- * See if any of the device's tags match any of the MatchTag tokens.
- */
- if (!list_is_empty(&iclass->match_tag)) {
- char * const *tag;
- Bool match;
-
- if (!attrs->tags)
- return FALSE;
- for (tag = attrs->tags, match = FALSE; *tag; tag++) {
- if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) {
- match = TRUE;
- break;
- }
- }
- if (!match)
- return FALSE;
- }
-
- /* MatchLayout string */
- if (!list_is_empty(&iclass->match_layout)) {
- if (!MatchAttrToken(xf86ConfigLayout.id,
- &iclass->match_layout, match_string_implicit))
- return FALSE;
- }
-
- /* MatchIs* booleans */
- if (iclass->is_keyboard.set &&
- iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
- return FALSE;
- if (iclass->is_pointer.set &&
- iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER))
- return FALSE;
- if (iclass->is_joystick.set &&
- iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK))
- return FALSE;
- if (iclass->is_tablet.set &&
- iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET))
- return FALSE;
- if (iclass->is_touchpad.set &&
- iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD))
- return FALSE;
- if (iclass->is_touchscreen.set &&
- iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN))
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * Merge in any InputClass configurations. Options in each InputClass
- * section have more priority than the original device configuration as
- * well as any previous InputClass sections.
- */
-static int
-MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs)
-{
- XF86ConfInputClassPtr cl;
- XF86OptionPtr classopts;
-
- for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
- if (!InputClassMatches(cl, idev, attrs))
- continue;
-
- /* Collect class options and driver settings */
- classopts = xf86optionListDup(cl->option_lst);
- if (cl->driver) {
- free(idev->driver);
- idev->driver = xstrdup(cl->driver);
- if (!idev->driver) {
- xf86Msg(X_ERROR, "Failed to allocate memory while merging "
- "InputClass configuration");
- return BadAlloc;
- }
- classopts = xf86ReplaceStrOption(classopts, "driver",
- idev->driver);
- }
-
- /* Apply options to device with InputClass settings preferred. */
- xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n",
- idev->name, cl->identifier);
- idev->options = xf86optionListMerge(idev->options, classopts);
- }
-
- return Success;
-}
-
-/*
- * Iterate the list of classes and look for Option "Ignore". Return the
- * value of the last matching class and holler when returning TRUE.
- */
-static Bool
-IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs)
-{
- XF86ConfInputClassPtr cl;
- Bool ignore = FALSE;
- const char *ignore_class;
-
- for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
- if (!InputClassMatches(cl, idev, attrs))
- continue;
- if (xf86findOption(cl->option_lst, "Ignore")) {
- ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE);
- ignore_class = cl->identifier;
- }
- }
-
- if (ignore)
- xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n",
- idev->name, ignore_class);
- return ignore;
-}
-
-InputInfoPtr
-xf86AllocateInput(void)
-{
- InputInfoPtr pInfo;
-
- pInfo = calloc(sizeof(*pInfo), 1);
- if (!pInfo)
- return NULL;
-
- pInfo->fd = -1;
- pInfo->type_name = "UNKNOWN";
-
- return pInfo;
-}
-
-/* Append InputInfoRec to the tail of xf86InputDevs. */
-static void
-xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo)
-{
- InputInfoPtr *prev = NULL;
-
- pInfo->drv = drv;
- pInfo->module = DuplicateModule(drv->module, NULL);
-
- for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next)
- ;
-
- *prev = pInfo;
- pInfo->next = NULL;
-
- xf86CollectInputOptions(pInfo, (const char**)drv->default_options);
- xf86OptionListReport(pInfo->options);
- xf86ProcessCommonOptions(pInfo, pInfo->options);
-}
-
-/*
- * Remove an entry from xf86InputDevs and free all the device's information.
- */
-void
-xf86DeleteInput(InputInfoPtr pInp, int flags)
-{
- /* First check if the inputdev is valid. */
- if (pInp == NULL)
- return;
-
- if (pInp->module)
- UnloadModule(pInp->module);
-
- /* This should *really* be handled in drv->UnInit(dev) call instead, but
- * if the driver forgets about it make sure we free it or at least crash
- * with flying colors */
- free(pInp->private);
-
- FreeInputAttributes(pInp->attrs);
-
- /* Remove the entry from the list. */
- if (pInp == xf86InputDevs)
- xf86InputDevs = pInp->next;
- else {
- InputInfoPtr p = xf86InputDevs;
- while (p && p->next != pInp)
- p = p->next;
- if (p)
- p->next = pInp->next;
- /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
- }
-
- free(pInp->driver);
- free(pInp->name);
- xf86optionListFree(pInp->options);
- free(pInp);
-}
-
-/*
- * Apply backend-specific initialization. Invoked after ActiveteDevice(),
- * i.e. after the driver successfully completed DEVICE_INIT and the device
- * is advertised.
- * @param dev the device
- * @return Success or an error code
- */
-static int
-xf86InputDevicePostInit(DeviceIntPtr dev) {
- ApplyAccelerationSettings(dev);
- return Success;
-}
-
-/**
- * Create a new input device, activate and enable it.
- *
- * Possible return codes:
- * BadName .. a bad driver name was supplied.
- * BadImplementation ... The driver does not have a PreInit function. This
- * is a driver bug.
- * BadMatch .. device initialization failed.
- * BadAlloc .. too many input devices
- *
- * @param idev The device, already set up with identifier, driver, and the
- * options.
- * @param pdev Pointer to the new device, if Success was reported.
- * @param enable Enable the device after activating it.
- *
- * @return Success or an error code
- */
-_X_INTERNAL int
-xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
-{
- InputDriverPtr drv = NULL;
- DeviceIntPtr dev = NULL;
- int rval;
-
- /* Memory leak for every attached device if we don't
- * test if the module is already loaded first */
- drv = xf86LookupInputDriver(pInfo->driver);
- if (!drv)
- if (xf86LoadOneModule(pInfo->driver, NULL))
- drv = xf86LookupInputDriver(pInfo->driver);
- if (!drv) {
- xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver);
- rval = BadName;
- goto unwind;
- }
-
- xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, pInfo->name);
-
- if (!drv->PreInit) {
- xf86Msg(X_ERROR,
- "Input driver `%s' has no PreInit function (ignoring)\n",
- drv->driverName);
- rval = BadImplementation;
- goto unwind;
- }
-
- xf86AddInput(drv, pInfo);
-
- rval = drv->PreInit(drv, pInfo, 0);
-
- if (rval != Success) {
- xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name);
- goto unwind;
- }
-
- if (!(dev = xf86ActivateDevice(pInfo)))
- {
- rval = BadAlloc;
- goto unwind;
- }
-
- rval = ActivateDevice(dev, TRUE);
- if (rval != Success)
- {
- xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name);
- RemoveDevice(dev, TRUE);
- goto unwind;
- }
-
- rval = xf86InputDevicePostInit(dev);
- if (rval != Success)
- {
- xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name);
- RemoveDevice(dev, TRUE);
- goto unwind;
- }
-
- /* Enable it if it's properly initialised and we're currently in the VT */
- if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema)
- {
- OsBlockSignals();
- EnableDevice(dev, TRUE);
- if (!dev->enabled)
- {
- OsReleaseSignals();
- xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name);
- RemoveDevice(dev, TRUE);
- rval = BadMatch;
- goto unwind;
- }
- /* send enter/leave event, update sprite window */
- CheckMotion(NULL, dev);
- OsReleaseSignals();
- }
-
- *pdev = dev;
- return Success;
-
-unwind:
- if(pInfo) {
- if(drv && drv->UnInit)
- drv->UnInit(drv, pInfo, 0);
- else
- xf86DeleteInput(pInfo, 0);
- }
- return rval;
-}
-
-int
-NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
- DeviceIntPtr *pdev)
-{
- InputInfoPtr pInfo = NULL;
- InputOption *option = NULL;
- int rval = Success;
- int is_auto = 0;
-
- pInfo = xf86AllocateInput();
- if (!pInfo)
- return BadAlloc;
-
- for (option = options; option; option = option->next) {
- if (strcasecmp(option->key, "driver") == 0) {
- if (pInfo->driver) {
- rval = BadRequest;
- goto unwind;
- }
- pInfo->driver = xstrdup(option->value);
- if (!pInfo->driver) {
- rval = BadAlloc;
- goto unwind;
- }
- }
-
- if (strcasecmp(option->key, "name") == 0 ||
- strcasecmp(option->key, "identifier") == 0) {
- if (pInfo->name) {
- rval = BadRequest;
- goto unwind;
- }
- pInfo->name = xstrdup(option->value);
- if (!pInfo->name) {
- rval = BadAlloc;
- goto unwind;
- }
- }
-
- if (strcmp(option->key, "_source") == 0 &&
- (strcmp(option->value, "server/hal") == 0 ||
- strcmp(option->value, "server/udev") == 0)) {
- is_auto = 1;
- if (!xf86Info.autoAddDevices) {
- rval = BadMatch;
- goto unwind;
- }
- }
- }
-
- for (option = options; option; option = option->next) {
- /* Steal option key/value strings from the provided list.
- * We need those strings, the InputOption list doesn't. */
- pInfo->options = xf86addNewOption(pInfo->options,
- option->key, option->value);
- option->key = NULL;
- option->value = NULL;
- }
-
- /* Apply InputClass settings */
- if (attrs) {
- if (IgnoreInputClass(pInfo, attrs)) {
- rval = BadIDChoice;
- goto unwind;
- }
-
- rval = MergeInputClasses(pInfo, attrs);
- if (rval != Success)
- goto unwind;
-
- pInfo->attrs = DuplicateInputAttributes(attrs);
- }
-
- if (!pInfo->driver || !pInfo->name) {
- xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n");
- rval = BadRequest;
- goto unwind;
- }
-
- if (!pInfo->name) {
- xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n");
- rval = BadMatch;
- goto unwind;
- }
-
- rval = xf86NewInputDevice(pInfo, pdev,
- (!is_auto || (is_auto && xf86Info.autoEnableDevices)));
-
- return rval;
-
-unwind:
- if (is_auto && !xf86Info.autoAddDevices)
- xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n");
- xf86DeleteInput(pInfo, 0);
- return rval;
-}
-
-void
-DeleteInputDeviceRequest(DeviceIntPtr pDev)
-{
- InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate;
- InputDriverPtr drv = NULL;
- Bool isMaster = IsMaster(pDev);
-
- if (pInfo) /* need to get these before RemoveDevice */
- drv = pInfo->drv;
-
- OsBlockSignals();
- RemoveDevice(pDev, TRUE);
-
- if (!isMaster && pInfo != NULL)
- {
- if(drv->UnInit)
- drv->UnInit(drv, pInfo, 0);
- else
- xf86DeleteInput(pInfo, 0);
- }
- OsReleaseSignals();
-}
-
-/*
- * convenient functions to post events
- */
-
-void
-xf86PostMotionEvent(DeviceIntPtr device,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- int i = 0;
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostMotionEventM(device, is_absolute, &mask);
-}
-
-void
-xf86PostMotionEventP(DeviceIntPtr device,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostMotionEventM(device, is_absolute, &mask);
-}
-
-void
-xf86PostMotionEventM(DeviceIntPtr device,
- int is_absolute,
- const ValuatorMask *mask)
-{
- int flags = 0;
-
- if (valuator_mask_num_valuators(mask) > 0)
- {
- if (is_absolute)
- flags = POINTER_ABSOLUTE;
- else
- flags = POINTER_RELATIVE | POINTER_ACCELERATE;
- }
-
-#if XFreeXDGA
- /* The evdev driver may not always send all axes across. */
- if (valuator_mask_isset(mask, 0) ||
- valuator_mask_isset(mask, 1))
- if (miPointerGetScreen(device)) {
- int index = miPointerGetScreen(device)->myNum;
- int dx = 0, dy = 0;
-
- if (valuator_mask_isset(mask, 0))
- {
- dx = valuator_mask_get(mask, 0);
- if (is_absolute)
- dx -= device->last.valuators[0];
- }
-
- if (valuator_mask_isset(mask, 1))
- {
- dy = valuator_mask_get(mask, 1);
- if (is_absolute)
- dy -= device->last.valuators[1];
- }
-
- if (DGAStealMotionEvent(device, index, dx, dy))
- return;
- }
-#endif
-
- QueuePointerEvents(device, MotionNotify, 0, flags, mask);
-}
-
-void
-xf86PostProximityEvent(DeviceIntPtr device,
- int is_in,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- int i;
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostProximityEventM(device, is_in, &mask);
-}
-
-void
-xf86PostProximityEventP(DeviceIntPtr device,
- int is_in,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostProximityEventM(device, is_in, &mask);
-}
-
-void
-xf86PostProximityEventM(DeviceIntPtr device,
- int is_in,
- const ValuatorMask *mask)
-{
- QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask);
-}
-
-void
-xf86PostButtonEvent(DeviceIntPtr device,
- int is_absolute,
- int button,
- int is_down,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- ValuatorMask mask;
- int i = 0;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
-
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostButtonEventM(device, is_absolute, button, is_down, &mask);
-}
-
-void
-xf86PostButtonEventP(DeviceIntPtr device,
- int is_absolute,
- int button,
- int is_down,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostButtonEventM(device, is_absolute, button, is_down, &mask);
-}
-
-void
-xf86PostButtonEventM(DeviceIntPtr device,
- int is_absolute,
- int button,
- int is_down,
- const ValuatorMask *mask)
-{
- int flags = 0;
-
- if (valuator_mask_num_valuators(mask) > 0)
- {
- if (is_absolute)
- flags = POINTER_ABSOLUTE;
- else
- flags = POINTER_RELATIVE | POINTER_ACCELERATE;
- }
-
-#if XFreeXDGA
- if (miPointerGetScreen(device)) {
- int index = miPointerGetScreen(device)->myNum;
-
- if (DGAStealButtonEvent(device, index, button, is_down))
- return;
- }
-#endif
-
- QueuePointerEvents(device,
- is_down ? ButtonPress : ButtonRelease, button,
- flags, mask);
-}
-
-void
-xf86PostKeyEvent(DeviceIntPtr device,
- unsigned int key_code,
- int is_down,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- ...)
-{
- va_list var;
- int i = 0;
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_zero(&mask);
-
- va_start(var, num_valuators);
- for (i = 0; i < num_valuators; i++)
- valuator_mask_set(&mask, first_valuator + i, va_arg(var, int));
- va_end(var);
-
- xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask);
-}
-
-void
-xf86PostKeyEventP(DeviceIntPtr device,
- unsigned int key_code,
- int is_down,
- int is_absolute,
- int first_valuator,
- int num_valuators,
- const int *valuators)
-{
- ValuatorMask mask;
-
- XI_VERIFY_VALUATORS(num_valuators);
-
- valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
- xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask);
-}
-
-void
-xf86PostKeyEventM(DeviceIntPtr device,
- unsigned int key_code,
- int is_down,
- int is_absolute,
- const ValuatorMask *mask)
-{
-#if XFreeXDGA
- DeviceIntPtr pointer;
-
- /* Some pointers send key events, paired device is wrong then. */
- pointer = IsPointerDevice(device) ? device : GetPairedDevice(device);
- if (miPointerGetScreen(pointer)) {
- int index = miPointerGetScreen(pointer)->myNum;
-
- if (DGAStealKeyEvent(device, index, key_code, is_down))
- return;
- }
-#endif
-
- QueueKeyboardEvents(device,
- is_down ? KeyPress : KeyRelease,
- key_code, mask);
-}
-
-void
-xf86PostKeyboardEvent(DeviceIntPtr device,
- unsigned int key_code,
- int is_down)
-{
- ValuatorMask mask;
-
- valuator_mask_zero(&mask);
- xf86PostKeyEventM(device, key_code, is_down, 0, &mask);
-}
-
-InputInfoPtr
-xf86FirstLocalDevice(void)
-{
- return xf86InputDevs;
-}
-
-/*
- * Cx - raw data from touch screen
- * to_max - scaled highest dimension
- * (remember, this is of rows - 1 because of 0 origin)
- * to_min - scaled lowest dimension
- * from_max - highest raw value from touch screen calibration
- * from_min - lowest raw value from touch screen calibration
- *
- * This function is the same for X or Y coordinates.
- * You may have to reverse the high and low values to compensate for
- * different orgins on the touch screen vs X.
- *
- * e.g. to scale from device coordinates into screen coordinates, call
- * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max);
- */
-
-int
-xf86ScaleAxis(int Cx,
- int to_max,
- int to_min,
- int from_max,
- int from_min )
-{
- int X;
- int64_t to_width = to_max - to_min;
- int64_t from_width = from_max - from_min;
-
- if (from_width) {
- X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min);
- }
- else {
- X = 0;
- ErrorF ("Divide by Zero in xf86ScaleAxis\n");
- }
-
- if (X > to_max)
- X = to_max;
- if (X < to_min)
- X = to_min;
-
- return X;
-}
-
-/*
- * This function checks the given screen against the current screen and
- * makes changes if appropriate. It should be called from an XInput driver's
- * ReadInput function before any events are posted, if the device is screen
- * specific like a touch screen.
- */
-void
-xf86XInputSetScreen(InputInfoPtr pInfo,
- int screen_number,
- int x,
- int y)
-{
- if (miPointerGetScreen(pInfo->dev) !=
- screenInfo.screens[screen_number]) {
- miPointerSetScreen(pInfo->dev, screen_number, x, y);
- }
-}
-
-
-void
-xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
- int resolution, int min_res, int max_res, int mode)
-{
- if (!dev || !dev->valuator)
- return;
-
- InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res,
- max_res, mode);
-}
-
-/*
- * Set the valuator values to be in synch with dix/event.c
- * DefineInitialRootWindow().
- */
-void
-xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum)
-{
- if (axnum == 0) {
- dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
- dev->last.valuators[0] = dev->valuator->axisVal[0];
- }
- else if (axnum == 1) {
- dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
- dev->last.valuators[1] = dev->valuator->axisVal[1];
- }
-}
-
-
-/**
- * Deactivate a device. Call this function from the driver if you receive a
- * read error or something else that spoils your day.
- * Device will be moved to the off_devices list, but it will still be there
- * until you really clean up after it.
- * Notifies the client about an inactive device.
- *
- * @param panic True if device is unrecoverable and needs to be removed.
- */
-void
-xf86DisableDevice(DeviceIntPtr dev, Bool panic)
-{
- if(!panic)
- {
- DisableDevice(dev, TRUE);
- } else
- {
- SendDevicePresenceEvent(dev->id, DeviceUnrecoverable);
- DeleteInputDeviceRequest(dev);
- }
-}
-
-/**
- * Reactivate a device. Call this function from the driver if you just found
- * out that the read error wasn't quite that bad after all.
- * Device will be re-activated, and an event sent to the client.
- */
-void
-xf86EnableDevice(DeviceIntPtr dev)
-{
- EnableDevice(dev, TRUE);
-}
-
-/* end of xf86Xinput.c */
+/* + * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include <X11/Xatom.h> +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "mipointer.h" +#include "extinit.h" +#include "loaderProcs.h" + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" +#include "inpututils.h" + +#include <string.h> /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif + +#include <stdarg.h> +#include <stdint.h> /* for int64_t */ + +#include "mi.h" + +#include <ptrveloc.h> /* dix pointer acceleration */ +#include <xserver-properties.h> + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "xkbsrv.h" + +/* Valuator verification macro */ +#define XI_VERIFY_VALUATORS(num_valuators) \ + if (num_valuators > MAX_VALUATORS) { \ + xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ + " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ + return; \ + } + +static int +xf86InputDevicePostInit(DeviceIntPtr dev); + +/** + * Eval config and modify DeviceVelocityRec accordingly + */ +static void +ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, + DeviceVelocityPtr s) +{ + int tempi; + float tempf; + Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); + Atom prop; + + if(!s) + return; + + /* common settings (available via device properties) */ + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + /* select profile by number */ + tempi = xf86SetIntOption(list, "AccelerationProfile", + s->statistics.profile_number); + + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, + PropModeReplace, 1, &tempi, FALSE) == Success) { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, + tempi); + } else { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", + devname, tempi); + } + + /* set scaling */ + tempf = xf86SetRealOption(list, "ExpectedRate", 0); + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + if (tempf > 0) { + tempf = 1000.0 / tempf; + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } else { + tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); + if (tempi > 1) + InitTrackers(s, tempi); + + s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", + s->initial_range); + + s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); + + tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); + if (tempf >= 0) { + xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", + devname, tempf*100.0); + s->max_rel_diff = tempf; + } + + /* Configure softening. If const deceleration is used, this is expected + * to provide better subpixel information so we enable + * softening by default only if ConstantDeceleration is not used + */ + s->use_softening = xf86SetBoolOption(list, "Softening", + s->const_acceleration == 1.0); + + s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", + s->average_accel); + + s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); +} + +static void +ApplyAccelerationSettings(DeviceIntPtr dev){ + int scheme, i; + DeviceVelocityPtr pVel; + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + char* schemeStr; + + if (dev->valuator && dev->ptrfeed) { + schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); + + scheme = dev->valuator->accelScheme.number; + + if (!xf86NameCmp(schemeStr, "predictable")) + scheme = PtrAccelPredictable; + + if (!xf86NameCmp(schemeStr, "lightweight")) + scheme = PtrAccelLightweight; + + if (!xf86NameCmp(schemeStr, "none")) + scheme = PtrAccelNoOp; + + /* reinit scheme if needed */ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { + dev->valuator->accelScheme.AccelCleanupProc(dev); + } + + if (InitPointerAccelerationScheme(dev, scheme)) { + xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", + pInfo->name, schemeStr, scheme); + } else { + xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", + pInfo->name, schemeStr); + scheme = dev->valuator->accelScheme.number; + } + } else { + xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", + pInfo->name, scheme); + } + + free(schemeStr); + + /* process special configuration */ + switch (scheme) { + case PtrAccelPredictable: + pVel = GetDevicePredictableAccelData(dev); + ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, + pVel); + break; + } + + i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + pInfo->name, dev->ptrfeed->ctrl.threshold); + } +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(InputInfoPtr pInfo, + pointer list) +{ + if (xf86SetBoolOption(list, "Floating", 0) || + !xf86SetBoolOption(list, "AlwaysCore", 1) || + !xf86SetBoolOption(list, "SendCoreEvents", 1) || + !xf86SetBoolOption(list, "CorePointer", 1) || + !xf86SetBoolOption(list, "CoreKeyboard", 1)) { + xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); + } else { + pInfo->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); + } +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + * Returns TRUE on success, or FALSE otherwise. + *********************************************************************** + */ +static DeviceIntPtr +xf86ActivateDevice(InputInfoPtr pInfo) +{ + DeviceIntPtr dev; + Atom atom; + + dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); + + if (dev == NULL) + { + xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", + pInfo->name); + pInfo->dev = NULL; + return NULL; + } + + atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); + AssignTypeAndName(dev, atom, pInfo->name); + dev->public.devicePrivate = pInfo; + pInfo->dev = dev; + + dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n", + pInfo->name, pInfo->type_name, dev->id); + + return dev; +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (pInfo->switch_mode) { + return (*pInfo->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, + int first_valuator, int num_valuators) +{ + InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; + + if (pInfo->set_device_valuators) + return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, + num_valuators); + + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (!pInfo->control_proc) { + switch (control->control) { + case DEVICE_CORE: + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + return BadMatch; + case DEVICE_RESOLUTION: + case DEVICE_ENABLE: + return Success; + default: + return BadMatch; + } + } + else { + return (*pInfo->control_proc)(pInfo, control); + } +} + +/* + * Get the operating system name from uname and store it statically to avoid + * repeating the system call each time MatchOS is checked. + */ +static const char * +HostOS(void) +{ +#ifdef HAVE_SYS_UTSNAME_H + struct utsname name; + static char host_os[sizeof(name.sysname)] = ""; + + if (*host_os == '\0') { + if (uname(&name) >= 0) + strcpy(host_os, name.sysname); + else { + strncpy(host_os, "unknown", sizeof(host_os)); + host_os[sizeof(host_os)-1] = '\0'; + } + } + return host_os; +#else + return ""; +#endif +} + +static int +match_substring(const char *attr, const char *pattern) +{ + return (strstr(attr, pattern)) ? 0 : -1; +} + +#ifdef HAVE_FNMATCH_H +static int +match_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, 0); +} +#else +#define match_pattern match_substring +#endif + +#ifdef HAVE_FNMATCH_H +static int +match_path_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, FNM_PATHNAME); +} +#else +#define match_path_pattern match_substring +#endif + +/* + * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" + * It is convenient that "" in patterns means "no explicit layout" + */ +static int +match_string_implicit(const char *attr, const char *pattern) +{ + if (strlen(pattern)) { + return strcmp(attr, pattern); + } else { + return strcmp(attr,"(implicit)"); + } +} + +/* + * Match an attribute against a list of NULL terminated arrays of patterns. + * If a pattern in each list entry is matched, return TRUE. + */ +static Bool +MatchAttrToken(const char *attr, struct list *patterns, + int (*compare)(const char *attr, const char *pattern)) +{ + const xf86MatchGroup *group; + + /* If there are no patterns, accept the match */ + if (list_is_empty(patterns)) + return TRUE; + + /* If there are patterns but no attribute, reject the match */ + if (!attr) + return FALSE; + + /* + * Otherwise, iterate the list of patterns ensuring each entry has a + * match. Each list entry is a separate Match line of the same type. + */ + list_for_each_entry(group, patterns, entry) { + char * const *cur; + Bool match = FALSE; + + for (cur = group->values; *cur; cur++) + if ((*compare)(attr, *cur) == 0) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + + /* All the entries in the list matched the attribute */ + return TRUE; +} + +/* + * Classes without any Match statements match all devices. Otherwise, all + * statements must match. + */ +static Bool +InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, + const InputAttributes *attrs) +{ + /* MatchProduct substring */ + if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) + return FALSE; + + /* MatchVendor substring */ + if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) + return FALSE; + + /* MatchDevicePath pattern */ + if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) + return FALSE; + + /* MatchOS case-insensitive string */ + if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) + return FALSE; + + /* MatchPnPID pattern */ + if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) + return FALSE; + + /* MatchUSBID pattern */ + if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) + return FALSE; + + /* MatchDriver string */ + if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) + return FALSE; + + /* + * MatchTag string + * See if any of the device's tags match any of the MatchTag tokens. + */ + if (!list_is_empty(&iclass->match_tag)) { + char * const *tag; + Bool match; + + if (!attrs->tags) + return FALSE; + for (tag = attrs->tags, match = FALSE; *tag; tag++) { + if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { + match = TRUE; + break; + } + } + if (!match) + return FALSE; + } + + /* MatchLayout string */ + if (!list_is_empty(&iclass->match_layout)) { + if (!MatchAttrToken(xf86ConfigLayout.id, + &iclass->match_layout, match_string_implicit)) + return FALSE; + } + + /* MatchIs* booleans */ + if (iclass->is_keyboard.set && + iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) + return FALSE; + if (iclass->is_pointer.set && + iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) + return FALSE; + if (iclass->is_joystick.set && + iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) + return FALSE; + if (iclass->is_tablet.set && + iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) + return FALSE; + if (iclass->is_touchpad.set && + iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) + return FALSE; + if (iclass->is_touchscreen.set && + iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) + return FALSE; + + return TRUE; +} + +/* + * Merge in any InputClass configurations. Options in each InputClass + * section have more priority than the original device configuration as + * well as any previous InputClass sections. + */ +static int +MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + XF86OptionPtr classopts; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + + /* Collect class options and driver settings */ + classopts = xf86optionListDup(cl->option_lst); + if (cl->driver) { + free(idev->driver); + idev->driver = xstrdup(cl->driver); + if (!idev->driver) { + xf86Msg(X_ERROR, "Failed to allocate memory while merging " + "InputClass configuration"); + return BadAlloc; + } + classopts = xf86ReplaceStrOption(classopts, "driver", + idev->driver); + } + + /* Apply options to device with InputClass settings preferred. */ + xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", + idev->name, cl->identifier); + idev->options = xf86optionListMerge(idev->options, classopts); + } + + return Success; +} + +/* + * Iterate the list of classes and look for Option "Ignore". Return the + * value of the last matching class and holler when returning TRUE. + */ +static Bool +IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + Bool ignore = FALSE; + const char *ignore_class; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + if (xf86findOption(cl->option_lst, "Ignore")) { + ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); + ignore_class = cl->identifier; + } + } + + if (ignore) + xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", + idev->name, ignore_class); + return ignore; +} + +InputInfoPtr +xf86AllocateInput(void) +{ + InputInfoPtr pInfo; + + pInfo = calloc(sizeof(*pInfo), 1); + if (!pInfo) + return NULL; + + pInfo->fd = -1; + pInfo->type_name = "UNKNOWN"; + + return pInfo; +} + +/* Append InputInfoRec to the tail of xf86InputDevs. */ +static void +xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) +{ + InputInfoPtr *prev = NULL; + + pInfo->drv = drv; + pInfo->module = DuplicateModule(drv->module, NULL); + + for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) + ; + + *prev = pInfo; + pInfo->next = NULL; + + xf86CollectInputOptions(pInfo, (const char**)drv->default_options); + xf86OptionListReport(pInfo->options); + xf86ProcessCommonOptions(pInfo, pInfo->options); +} + +/* + * Remove an entry from xf86InputDevs and free all the device's information. + */ +void +xf86DeleteInput(InputInfoPtr pInp, int flags) +{ + /* First check if the inputdev is valid. */ + if (pInp == NULL) + return; + + if (pInp->module) + UnloadModule(pInp->module); + + /* This should *really* be handled in drv->UnInit(dev) call instead, but + * if the driver forgets about it make sure we free it or at least crash + * with flying colors */ + free(pInp->private); + + FreeInputAttributes(pInp->attrs); + + /* Remove the entry from the list. */ + if (pInp == xf86InputDevs) + xf86InputDevs = pInp->next; + else { + InputInfoPtr p = xf86InputDevs; + while (p && p->next != pInp) + p = p->next; + if (p) + p->next = pInp->next; + /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ + } + + free(pInp->driver); + free(pInp->name); + xf86optionListFree(pInp->options); + free(pInp); +} + +/* + * Apply backend-specific initialization. Invoked after ActiveteDevice(), + * i.e. after the driver successfully completed DEVICE_INIT and the device + * is advertised. + * @param dev the device + * @return Success or an error code + */ +static int +xf86InputDevicePostInit(DeviceIntPtr dev) { + ApplyAccelerationSettings(dev); + return Success; +} + +/** + * Create a new input device, activate and enable it. + * + * Possible return codes: + * BadName .. a bad driver name was supplied. + * BadImplementation ... The driver does not have a PreInit function. This + * is a driver bug. + * BadMatch .. device initialization failed. + * BadAlloc .. too many input devices + * + * @param idev The device, already set up with identifier, driver, and the + * options. + * @param pdev Pointer to the new device, if Success was reported. + * @param enable Enable the device after activating it. + * + * @return Success or an error code + */ +_X_INTERNAL int +xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) +{ + InputDriverPtr drv = NULL; + DeviceIntPtr dev = NULL; + int rval; + + /* Memory leak for every attached device if we don't + * test if the module is already loaded first */ + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) + if (xf86LoadOneModule(pInfo->driver, NULL)) + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) { + xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); + rval = BadName; + goto unwind; + } + + xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, pInfo->name); + + if (!drv->PreInit) { + xf86Msg(X_ERROR, + "Input driver `%s' has no PreInit function (ignoring)\n", + drv->driverName); + rval = BadImplementation; + goto unwind; + } + + xf86AddInput(drv, pInfo); + + rval = drv->PreInit(drv, pInfo, 0); + + if (rval != Success) { + xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); + goto unwind; + } + + if (!(dev = xf86ActivateDevice(pInfo))) + { + rval = BadAlloc; + goto unwind; + } + + rval = ActivateDevice(dev, TRUE); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + rval = xf86InputDevicePostInit(dev); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + /* Enable it if it's properly initialised and we're currently in the VT */ + if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) + { + OsBlockSignals(); + EnableDevice(dev, TRUE); + if (!dev->enabled) + { + OsReleaseSignals(); + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + rval = BadMatch; + goto unwind; + } + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + OsReleaseSignals(); + } + + *pdev = dev; + return Success; + +unwind: + if(pInfo) { + if(drv && drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + return rval; +} + +int +NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + InputInfoPtr pInfo = NULL; + InputOption *option = NULL; + int rval = Success; + int is_auto = 0; + + pInfo = xf86AllocateInput(); + if (!pInfo) + return BadAlloc; + + for (option = options; option; option = option->next) { + if (strcasecmp(option->key, "driver") == 0) { + if (pInfo->driver) { + rval = BadRequest; + goto unwind; + } + pInfo->driver = xstrdup(option->value); + if (!pInfo->driver) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcasecmp(option->key, "name") == 0 || + strcasecmp(option->key, "identifier") == 0) { + if (pInfo->name) { + rval = BadRequest; + goto unwind; + } + pInfo->name = xstrdup(option->value); + if (!pInfo->name) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcmp(option->key, "_source") == 0 && + (strcmp(option->value, "server/hal") == 0 || + strcmp(option->value, "server/udev") == 0)) { + is_auto = 1; + if (!xf86Info.autoAddDevices) { + rval = BadMatch; + goto unwind; + } + } + } + + for (option = options; option; option = option->next) { + /* Steal option key/value strings from the provided list. + * We need those strings, the InputOption list doesn't. */ + pInfo->options = xf86addNewOption(pInfo->options, + option->key, option->value); + option->key = NULL; + option->value = NULL; + } + + /* Apply InputClass settings */ + if (attrs) { + if (IgnoreInputClass(pInfo, attrs)) { + rval = BadIDChoice; + goto unwind; + } + + rval = MergeInputClasses(pInfo, attrs); + if (rval != Success) + goto unwind; + + pInfo->attrs = DuplicateInputAttributes(attrs); + } + + if (!pInfo->driver || !pInfo->name) { + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); + rval = BadRequest; + goto unwind; + } + + if (!pInfo->name) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + rval = BadMatch; + goto unwind; + } + + rval = xf86NewInputDevice(pInfo, pdev, + (!is_auto || (is_auto && xf86Info.autoEnableDevices))); + + return rval; + +unwind: + if (is_auto && !xf86Info.autoAddDevices) + xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); + xf86DeleteInput(pInfo, 0); + return rval; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; + InputDriverPtr drv = NULL; + Bool isMaster = IsMaster(pDev); + + if (pInfo) /* need to get these before RemoveDevice */ + drv = pInfo->drv; + + OsBlockSignals(); + RemoveDevice(pDev, TRUE); + + if (!isMaster && pInfo != NULL) + { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + OsReleaseSignals(); +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventP(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventM(DeviceIntPtr device, + int is_absolute, + const ValuatorMask *mask) +{ + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + /* The evdev driver may not always send all axes across. */ + if (valuator_mask_isset(mask, 0) || + valuator_mask_isset(mask, 1)) + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + int dx = 0, dy = 0; + + if (valuator_mask_isset(mask, 0)) + { + dx = valuator_mask_get(mask, 0); + if (is_absolute) + dx -= device->last.valuators[0]; + } + + if (valuator_mask_isset(mask, 1)) + { + dy = valuator_mask_get(mask, 1); + if (is_absolute) + dy -= device->last.valuators[1]; + } + + if (DGAStealMotionEvent(device, index, dx, dy)) + return; + } +#endif + + QueuePointerEvents(device, MotionNotify, 0, flags, mask); +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventP(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventM(DeviceIntPtr device, + int is_in, + const ValuatorMask *mask) +{ + QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask); +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + ValuatorMask mask; + int i = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventP(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventM(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + const ValuatorMask *mask) +{ + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + + if (DGAStealButtonEvent(device, index, button, is_down)) + return; + } +#endif + + QueuePointerEvents(device, + is_down ? ButtonPress : ButtonRelease, button, + flags, mask); +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventP(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventM(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + const ValuatorMask *mask) +{ +#if XFreeXDGA + DeviceIntPtr pointer; + + /* Some pointers send key events, paired device is wrong then. */ + pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); + if (miPointerGetScreen(pointer)) { + int index = miPointerGetScreen(pointer)->myNum; + + if (DGAStealKeyEvent(device, index, key_code, is_down)) + return; + } +#endif + + QueueKeyboardEvents(device, + is_down ? KeyPress : KeyRelease, + key_code, mask); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + ValuatorMask mask; + + valuator_mask_zero(&mask); + xf86PostKeyEventM(device, key_code, is_down, 0, &mask); +} + +InputInfoPtr +xf86FirstLocalDevice(void) +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * to_max - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * to_min - scaled lowest dimension + * from_max - highest raw value from touch screen calibration + * from_min - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + * + * e.g. to scale from device coordinates into screen coordinates, call + * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); + */ + +int +xf86ScaleAxis(int Cx, + int to_max, + int to_min, + int from_max, + int from_min ) +{ + int X; + int64_t to_width = to_max - to_min; + int64_t from_width = from_max - from_min; + + if (from_width) { + X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis\n"); + } + + if (X > to_max) + X = to_max; + if (X < to_min) + X = to_min; + + return X; +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(InputInfoPtr pInfo, + int screen_number, + int x, + int y) +{ + if (miPointerGetScreen(pInfo->dev) != + screenInfo.screens[screen_number]) { + miPointerSetScreen(pInfo->dev, screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, + int resolution, int min_res, int max_res, int mode) +{ + if (!dev || !dev->valuator) + return; + + InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res, mode); +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ + if (axnum == 0) { + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + dev->last.valuators[0] = dev->valuator->axisVal[0]; + } + else if (axnum == 1) { + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + dev->last.valuators[1] = dev->valuator->axisVal[1]; + } +} + + +/** + * Deactivate a device. Call this function from the driver if you receive a + * read error or something else that spoils your day. + * Device will be moved to the off_devices list, but it will still be there + * until you really clean up after it. + * Notifies the client about an inactive device. + * + * @param panic True if device is unrecoverable and needs to be removed. + */ +void +xf86DisableDevice(DeviceIntPtr dev, Bool panic) +{ + if(!panic) + { + DisableDevice(dev, TRUE); + } else + { + SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); + DeleteInputDeviceRequest(dev); + } +} + +/** + * Reactivate a device. Call this function from the driver if you just found + * out that the read error wasn't quite that bad after all. + * Device will be re-activated, and an event sent to the client. + */ +void +xf86EnableDevice(DeviceIntPtr dev) +{ + EnableDevice(dev, TRUE); +} + +/* end of xf86Xinput.c */ |