105b261ecSmrg/* 205b261ecSmrg * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> 335c4bbdfSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that 705b261ecSmrg * copyright notice and this permission notice appear in supporting 805b261ecSmrg * documentation, and that the name of Frederic Lepied not be used in 905b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1005b261ecSmrg * specific, written prior permission. Frederic Lepied makes no 1105b261ecSmrg * representations about the suitability of this software for any purpose. It 1235c4bbdfSmrg * is provided "as is" without express or implied warranty. 1335c4bbdfSmrg * 1405b261ecSmrg * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2105b261ecSmrg * 2205b261ecSmrg */ 2305b261ecSmrg/* 2405b261ecSmrg * Copyright (c) 2000-2002 by The XFree86 Project, Inc. 2505b261ecSmrg * 2605b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 2705b261ecSmrg * copy of this software and associated documentation files (the "Software"), 2805b261ecSmrg * to deal in the Software without restriction, including without limitation 2905b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 3005b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 3105b261ecSmrg * Software is furnished to do so, subject to the following conditions: 3205b261ecSmrg * 3305b261ecSmrg * The above copyright notice and this permission notice shall be included in 3405b261ecSmrg * all copies or substantial portions of the Software. 3505b261ecSmrg * 3605b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3705b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3805b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 3905b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 4005b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 4105b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE. 4205b261ecSmrg * 4305b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s) 4405b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote 4505b261ecSmrg * the sale, use or other dealings in this Software without prior written 4605b261ecSmrg * authorization from the copyright holder(s) and author(s). 4705b261ecSmrg */ 4805b261ecSmrg 4905b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 5005b261ecSmrg#include <xorg-config.h> 5105b261ecSmrg#endif 5205b261ecSmrg 5305b261ecSmrg#include <X11/Xfuncproto.h> 5405b261ecSmrg#include <X11/Xmd.h> 5505b261ecSmrg#include <X11/extensions/XI.h> 5605b261ecSmrg#include <X11/extensions/XIproto.h> 576747b715Smrg#include <X11/Xatom.h> 5805b261ecSmrg#include "xf86.h" 5905b261ecSmrg#include "xf86Priv.h" 606747b715Smrg#include "xf86Config.h" 6105b261ecSmrg#include "xf86Xinput.h" 6205b261ecSmrg#include "xf86Optrec.h" 6305b261ecSmrg#include "mipointer.h" 644642e01fSmrg#include "extinit.h" 656747b715Smrg#include "loaderProcs.h" 6635c4bbdfSmrg#include "systemd-logind.h" 6705b261ecSmrg 6835c4bbdfSmrg#include "exevents.h" /* AddInputDevice */ 6905b261ecSmrg#include "exglobals.h" 706747b715Smrg#include "eventstr.h" 719ace9065Smrg#include "inpututils.h" 7235c4bbdfSmrg#include "optionstr.h" 736747b715Smrg 7435c4bbdfSmrg#include <string.h> /* InputClassMatches */ 756747b715Smrg#ifdef HAVE_FNMATCH_H 766747b715Smrg#include <fnmatch.h> 776747b715Smrg#endif 786747b715Smrg#ifdef HAVE_SYS_UTSNAME_H 796747b715Smrg#include <sys/utsname.h> 806747b715Smrg#endif 8105b261ecSmrg 8205b261ecSmrg#include <stdarg.h> 8335c4bbdfSmrg#include <stdint.h> /* for int64_t */ 8435c4bbdfSmrg#include <sys/types.h> 8535c4bbdfSmrg#include <sys/stat.h> 8635c4bbdfSmrg#include <unistd.h> 871b5d61b8Smrg#ifdef HAVE_SYS_SYSMACROS_H 881b5d61b8Smrg#include <sys/sysmacros.h> 891b5d61b8Smrg#endif 9035c4bbdfSmrg#ifdef HAVE_SYS_MKDEV_H 9135c4bbdfSmrg#include <sys/mkdev.h> /* for major() & minor() on Solaris */ 9235c4bbdfSmrg#endif 9305b261ecSmrg 9405b261ecSmrg#include "mi.h" 9505b261ecSmrg 9635c4bbdfSmrg#include <ptrveloc.h> /* dix pointer acceleration */ 976747b715Smrg#include <xserver-properties.h> 984642e01fSmrg 9905b261ecSmrg#ifdef XFreeXDGA 10005b261ecSmrg#include "dgaproc.h" 10105b261ecSmrg#endif 10205b261ecSmrg 1034642e01fSmrg#include "xkbsrv.h" 1044642e01fSmrg 1059ace9065Smrg/* Valuator verification macro */ 1069ace9065Smrg#define XI_VERIFY_VALUATORS(num_valuators) \ 1079ace9065Smrg if (num_valuators > MAX_VALUATORS) { \ 1089ace9065Smrg xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ 1099ace9065Smrg " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ 1109ace9065Smrg return; \ 1119ace9065Smrg } 1124642e01fSmrg 1139ace9065Smrgstatic int 11435c4bbdfSmrg xf86InputDevicePostInit(DeviceIntPtr dev); 11535c4bbdfSmrg 1161b5d61b8Smrgtypedef struct { 1171b5d61b8Smrg struct xorg_list node; 1181b5d61b8Smrg InputInfoPtr pInfo; 1191b5d61b8Smrg} PausedInputDeviceRec; 1201b5d61b8Smrgtypedef PausedInputDeviceRec *PausedInputDevicePtr; 1211b5d61b8Smrg 1221b5d61b8Smrgstatic struct xorg_list new_input_devices_list = { 1231b5d61b8Smrg .next = &new_input_devices_list, 1241b5d61b8Smrg .prev = &new_input_devices_list, 1251b5d61b8Smrg}; 1269ace9065Smrg 1274642e01fSmrg/** 1284642e01fSmrg * Eval config and modify DeviceVelocityRec accordingly 1294642e01fSmrg */ 1304642e01fSmrgstatic void 13135c4bbdfSmrgProcessVelocityConfiguration(DeviceIntPtr pDev, const char *devname, void *list, 1326747b715Smrg DeviceVelocityPtr s) 1336747b715Smrg{ 1346747b715Smrg int tempi; 1356747b715Smrg float tempf; 1366747b715Smrg Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); 1376747b715Smrg Atom prop; 1384642e01fSmrg 13935c4bbdfSmrg if (!s) 1404642e01fSmrg return; 1414642e01fSmrg 1426747b715Smrg /* common settings (available via device properties) */ 1434642e01fSmrg tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); 1441b5d61b8Smrg if (tempf != 1.0) { 1454642e01fSmrg xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", 1464642e01fSmrg devname, tempf); 1476747b715Smrg prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); 1486747b715Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 1496747b715Smrg PropModeReplace, 1, &tempf, FALSE); 1504642e01fSmrg } 1514642e01fSmrg 1524642e01fSmrg tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); 1536747b715Smrg if (tempf > 1.0) { 1544642e01fSmrg xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", 1554642e01fSmrg devname, tempf); 1566747b715Smrg prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); 1576747b715Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 1586747b715Smrg PropModeReplace, 1, &tempf, FALSE); 1596747b715Smrg } 1606747b715Smrg 1616747b715Smrg /* select profile by number */ 1626747b715Smrg tempi = xf86SetIntOption(list, "AccelerationProfile", 16335c4bbdfSmrg s->statistics.profile_number); 1646747b715Smrg 1656747b715Smrg prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); 1666747b715Smrg if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, 1676747b715Smrg PropModeReplace, 1, &tempi, FALSE) == Success) { 1686747b715Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, 1696747b715Smrg tempi); 17035c4bbdfSmrg } 17135c4bbdfSmrg else { 1726747b715Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", 1736747b715Smrg devname, tempi); 1746747b715Smrg } 1756747b715Smrg 1766747b715Smrg /* set scaling */ 1776747b715Smrg tempf = xf86SetRealOption(list, "ExpectedRate", 0); 1786747b715Smrg prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); 1796747b715Smrg if (tempf > 0) { 1806747b715Smrg tempf = 1000.0 / tempf; 1816747b715Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 1826747b715Smrg PropModeReplace, 1, &tempf, FALSE); 18335c4bbdfSmrg } 18435c4bbdfSmrg else { 1856747b715Smrg tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); 1866747b715Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 1876747b715Smrg PropModeReplace, 1, &tempf, FALSE); 1884642e01fSmrg } 1894642e01fSmrg 1906747b715Smrg tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); 1916747b715Smrg if (tempi > 1) 19235c4bbdfSmrg InitTrackers(s, tempi); 1936747b715Smrg 1946747b715Smrg s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", 1956747b715Smrg s->initial_range); 1966747b715Smrg 1976747b715Smrg s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); 1986747b715Smrg 1996747b715Smrg tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); 2006747b715Smrg if (tempf >= 0) { 20135c4bbdfSmrg xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", 20235c4bbdfSmrg devname, tempf * 100.0); 20335c4bbdfSmrg s->max_rel_diff = tempf; 2044642e01fSmrg } 2054642e01fSmrg 2064642e01fSmrg /* Configure softening. If const deceleration is used, this is expected 2074642e01fSmrg * to provide better subpixel information so we enable 2084642e01fSmrg * softening by default only if ConstantDeceleration is not used 2094642e01fSmrg */ 2104642e01fSmrg s->use_softening = xf86SetBoolOption(list, "Softening", 2114642e01fSmrg s->const_acceleration == 1.0); 2124642e01fSmrg 2134642e01fSmrg s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", 2144642e01fSmrg s->average_accel); 2154642e01fSmrg 2164642e01fSmrg s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); 2174642e01fSmrg} 2184642e01fSmrg 2194642e01fSmrgstatic void 22035c4bbdfSmrgApplyAccelerationSettings(DeviceIntPtr dev) 22135c4bbdfSmrg{ 2226747b715Smrg int scheme, i; 2234642e01fSmrg DeviceVelocityPtr pVel; 22435c4bbdfSmrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 22535c4bbdfSmrg char *schemeStr; 2264642e01fSmrg 2276747b715Smrg if (dev->valuator && dev->ptrfeed) { 22835c4bbdfSmrg schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); 2294642e01fSmrg 23035c4bbdfSmrg scheme = dev->valuator->accelScheme.number; 2314642e01fSmrg 23235c4bbdfSmrg if (!xf86NameCmp(schemeStr, "predictable")) 23335c4bbdfSmrg scheme = PtrAccelPredictable; 2344642e01fSmrg 23535c4bbdfSmrg if (!xf86NameCmp(schemeStr, "lightweight")) 23635c4bbdfSmrg scheme = PtrAccelLightweight; 2374642e01fSmrg 23835c4bbdfSmrg if (!xf86NameCmp(schemeStr, "none")) 23935c4bbdfSmrg scheme = PtrAccelNoOp; 2404642e01fSmrg 2414642e01fSmrg /* reinit scheme if needed */ 2426747b715Smrg if (dev->valuator->accelScheme.number != scheme) { 2436747b715Smrg if (dev->valuator->accelScheme.AccelCleanupProc) { 2444642e01fSmrg dev->valuator->accelScheme.AccelCleanupProc(dev); 2454642e01fSmrg } 2464642e01fSmrg 2476747b715Smrg if (InitPointerAccelerationScheme(dev, scheme)) { 24835c4bbdfSmrg xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", 24935c4bbdfSmrg pInfo->name, schemeStr, scheme); 25035c4bbdfSmrg } 25135c4bbdfSmrg else { 25235c4bbdfSmrg xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", 25335c4bbdfSmrg pInfo->name, schemeStr); 25435c4bbdfSmrg scheme = dev->valuator->accelScheme.number; 2554642e01fSmrg } 25635c4bbdfSmrg } 25735c4bbdfSmrg else { 2584642e01fSmrg xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", 2599ace9065Smrg pInfo->name, scheme); 2604642e01fSmrg } 2614642e01fSmrg 2626747b715Smrg free(schemeStr); 2634642e01fSmrg 2644642e01fSmrg /* process special configuration */ 2656747b715Smrg switch (scheme) { 26635c4bbdfSmrg case PtrAccelPredictable: 26735c4bbdfSmrg pVel = GetDevicePredictableAccelData(dev); 26835c4bbdfSmrg ProcessVelocityConfiguration(dev, pInfo->name, pInfo->options, 26935c4bbdfSmrg pVel); 27035c4bbdfSmrg break; 2714642e01fSmrg } 2726747b715Smrg 2739ace9065Smrg i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", 2746747b715Smrg dev->ptrfeed->ctrl.num); 2756747b715Smrg if (i >= 0) 2766747b715Smrg dev->ptrfeed->ctrl.num = i; 2776747b715Smrg 2789ace9065Smrg i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", 2796747b715Smrg dev->ptrfeed->ctrl.den); 2806747b715Smrg if (i > 0) 2816747b715Smrg dev->ptrfeed->ctrl.den = i; 2826747b715Smrg 2839ace9065Smrg i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", 2846747b715Smrg dev->ptrfeed->ctrl.threshold); 2856747b715Smrg if (i >= 0) 2866747b715Smrg dev->ptrfeed->ctrl.threshold = i; 2876747b715Smrg 2886747b715Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", 28935c4bbdfSmrg pInfo->name, ((float) dev->ptrfeed->ctrl.num) / 29035c4bbdfSmrg ((float) dev->ptrfeed->ctrl.den)); 2916747b715Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", 2929ace9065Smrg pInfo->name, dev->ptrfeed->ctrl.threshold); 2934642e01fSmrg } 2944642e01fSmrg} 29505b261ecSmrg 29635c4bbdfSmrgstatic void 29735c4bbdfSmrgApplyTransformationMatrix(DeviceIntPtr dev) 29835c4bbdfSmrg{ 29935c4bbdfSmrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 30035c4bbdfSmrg char *str; 30135c4bbdfSmrg int rc; 30235c4bbdfSmrg float matrix[9] = { 0 }; 30335c4bbdfSmrg 30435c4bbdfSmrg if (!dev->valuator) 30535c4bbdfSmrg return; 30635c4bbdfSmrg 30735c4bbdfSmrg str = xf86SetStrOption(pInfo->options, "TransformationMatrix", NULL); 30835c4bbdfSmrg if (!str) 30935c4bbdfSmrg return; 31035c4bbdfSmrg 31135c4bbdfSmrg rc = sscanf(str, "%f %f %f %f %f %f %f %f %f", &matrix[0], &matrix[1], 31235c4bbdfSmrg &matrix[2], &matrix[3], &matrix[4], &matrix[5], &matrix[6], 31335c4bbdfSmrg &matrix[7], &matrix[8]); 31435c4bbdfSmrg if (rc != 9) { 31535c4bbdfSmrg xf86Msg(X_ERROR, 31635c4bbdfSmrg "%s: invalid format for transformation matrix. Ignoring configuration.\n", 31735c4bbdfSmrg pInfo->name); 31835c4bbdfSmrg return; 31935c4bbdfSmrg } 32035c4bbdfSmrg 32135c4bbdfSmrg XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), 32235c4bbdfSmrg XIGetKnownProperty(XATOM_FLOAT), 32, 32335c4bbdfSmrg PropModeReplace, 9, matrix, FALSE); 32435c4bbdfSmrg} 32535c4bbdfSmrg 326ed6184dfSmrgstatic void 327ed6184dfSmrgApplyAutoRepeat(DeviceIntPtr dev) 328ed6184dfSmrg{ 329ed6184dfSmrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 330ed6184dfSmrg XkbSrvInfoPtr xkbi; 331ed6184dfSmrg char *repeatStr; 332ed6184dfSmrg long delay, rate; 333ed6184dfSmrg 334ed6184dfSmrg if (!dev->key) 335ed6184dfSmrg return; 336ed6184dfSmrg 337ed6184dfSmrg xkbi = dev->key->xkbInfo; 338ed6184dfSmrg 339ed6184dfSmrg repeatStr = xf86SetStrOption(pInfo->options, "AutoRepeat", NULL); 340ed6184dfSmrg if (!repeatStr) 341ed6184dfSmrg return; 342ed6184dfSmrg 343ed6184dfSmrg if (sscanf(repeatStr, "%ld %ld", &delay, &rate) != 2) { 344ed6184dfSmrg xf86Msg(X_ERROR, "\"%s\" is not a valid AutoRepeat value\n", repeatStr); 345ed6184dfSmrg return; 346ed6184dfSmrg } 347ed6184dfSmrg 348ed6184dfSmrg xf86Msg(X_CONFIG, "AutoRepeat: %ld %ld\n", delay, rate); 349ed6184dfSmrg xkbi->desc->ctrls->repeat_delay = delay; 350ed6184dfSmrg xkbi->desc->ctrls->repeat_interval = rate; 351ed6184dfSmrg} 352ed6184dfSmrg 35305b261ecSmrg/*********************************************************************** 35405b261ecSmrg * 35505b261ecSmrg * xf86ProcessCommonOptions -- 35635c4bbdfSmrg * 35705b261ecSmrg * Process global options. 35805b261ecSmrg * 35905b261ecSmrg *********************************************************************** 36005b261ecSmrg */ 3616747b715Smrgvoid 36235c4bbdfSmrgxf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr list) 36305b261ecSmrg{ 3649ace9065Smrg if (xf86SetBoolOption(list, "Floating", 0) || 3659ace9065Smrg !xf86SetBoolOption(list, "AlwaysCore", 1) || 36605b261ecSmrg !xf86SetBoolOption(list, "SendCoreEvents", 1) || 36705b261ecSmrg !xf86SetBoolOption(list, "CorePointer", 1) || 36805b261ecSmrg !xf86SetBoolOption(list, "CoreKeyboard", 1)) { 3699ace9065Smrg xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); 37035c4bbdfSmrg } 37135c4bbdfSmrg else { 3729ace9065Smrg pInfo->flags |= XI86_ALWAYS_CORE; 3739ace9065Smrg xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); 37405b261ecSmrg } 37505b261ecSmrg} 37605b261ecSmrg 37705b261ecSmrg/*********************************************************************** 37805b261ecSmrg * 37905b261ecSmrg * xf86ActivateDevice -- 3804642e01fSmrg * 38105b261ecSmrg * Initialize an input device. 38205b261ecSmrg * 3834642e01fSmrg * Returns TRUE on success, or FALSE otherwise. 38405b261ecSmrg *********************************************************************** 38505b261ecSmrg */ 3869ace9065Smrgstatic DeviceIntPtr 3879ace9065Smrgxf86ActivateDevice(InputInfoPtr pInfo) 38805b261ecSmrg{ 38935c4bbdfSmrg DeviceIntPtr dev; 39035c4bbdfSmrg Atom atom; 39105b261ecSmrg 3929ace9065Smrg dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); 3934642e01fSmrg 39435c4bbdfSmrg if (dev == NULL) { 39535c4bbdfSmrg xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", pInfo->name); 3969ace9065Smrg pInfo->dev = NULL; 3979ace9065Smrg return NULL; 39805b261ecSmrg } 3994642e01fSmrg 4009ace9065Smrg atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); 4019ace9065Smrg AssignTypeAndName(dev, atom, pInfo->name); 4029ace9065Smrg dev->public.devicePrivate = pInfo; 4039ace9065Smrg pInfo->dev = dev; 40405b261ecSmrg 4059ace9065Smrg dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; 4069ace9065Smrg dev->type = SLAVE; 4079ace9065Smrg dev->spriteInfo->spriteOwner = FALSE; 40805b261ecSmrg 4099ace9065Smrg dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); 41005b261ecSmrg 4119ace9065Smrg if (serverGeneration == 1) 41235c4bbdfSmrg xf86Msg(X_INFO, 41335c4bbdfSmrg "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n", 41435c4bbdfSmrg pInfo->name, pInfo->type_name, dev->id); 41505b261ecSmrg 4169ace9065Smrg return dev; 41705b261ecSmrg} 41805b261ecSmrg 41905b261ecSmrg/**************************************************************************** 42005b261ecSmrg * 42105b261ecSmrg * Caller: ProcXSetDeviceMode 42205b261ecSmrg * 42305b261ecSmrg * Change the mode of an extension device. 42405b261ecSmrg * This function is used to change the mode of a device from reporting 42505b261ecSmrg * relative motion to reporting absolute positional information, and 42605b261ecSmrg * vice versa. 42705b261ecSmrg * The default implementation below is that no such devices are supported. 42805b261ecSmrg * 42905b261ecSmrg *********************************************************************** 43005b261ecSmrg */ 43105b261ecSmrg 43205b261ecSmrgint 43335c4bbdfSmrgSetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode) 43405b261ecSmrg{ 43535c4bbdfSmrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 43605b261ecSmrg 43735c4bbdfSmrg if (pInfo->switch_mode) { 43835c4bbdfSmrg return (*pInfo->switch_mode) (client, dev, mode); 43935c4bbdfSmrg } 44035c4bbdfSmrg else 44135c4bbdfSmrg return BadMatch; 44205b261ecSmrg} 44305b261ecSmrg 44405b261ecSmrg/*********************************************************************** 44505b261ecSmrg * 44605b261ecSmrg * Caller: ProcXSetDeviceValuators 44705b261ecSmrg * 44805b261ecSmrg * Set the value of valuators on an extension input device. 44905b261ecSmrg * This function is used to set the initial value of valuators on 45005b261ecSmrg * those input devices that are capable of reporting either relative 45105b261ecSmrg * motion or an absolute position, and allow an initial position to be set. 45205b261ecSmrg * The default implementation below is that no such devices are supported. 45305b261ecSmrg * 45405b261ecSmrg *********************************************************************** 45505b261ecSmrg */ 45605b261ecSmrg 45705b261ecSmrgint 45835c4bbdfSmrgSetDeviceValuators(ClientPtr client, DeviceIntPtr dev, int *valuators, 45935c4bbdfSmrg int first_valuator, int num_valuators) 46005b261ecSmrg{ 4619ace9065Smrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 46205b261ecSmrg 4639ace9065Smrg if (pInfo->set_device_valuators) 46435c4bbdfSmrg return (*pInfo->set_device_valuators) (pInfo, valuators, first_valuator, 46535c4bbdfSmrg num_valuators); 46605b261ecSmrg 46705b261ecSmrg return BadMatch; 46805b261ecSmrg} 46905b261ecSmrg 47005b261ecSmrg/*********************************************************************** 47105b261ecSmrg * 47205b261ecSmrg * Caller: ProcXChangeDeviceControl 47305b261ecSmrg * 47405b261ecSmrg * Change the specified device controls on an extension input device. 47505b261ecSmrg * 47605b261ecSmrg *********************************************************************** 47705b261ecSmrg */ 47805b261ecSmrg 47905b261ecSmrgint 48035c4bbdfSmrgChangeDeviceControl(ClientPtr client, DeviceIntPtr dev, xDeviceCtl * control) 48105b261ecSmrg{ 48235c4bbdfSmrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 48335c4bbdfSmrg 48435c4bbdfSmrg if (!pInfo->control_proc) { 48535c4bbdfSmrg switch (control->control) { 48635c4bbdfSmrg case DEVICE_CORE: 48735c4bbdfSmrg case DEVICE_ABS_CALIB: 48835c4bbdfSmrg case DEVICE_ABS_AREA: 48935c4bbdfSmrg return BadMatch; 49035c4bbdfSmrg case DEVICE_RESOLUTION: 49135c4bbdfSmrg case DEVICE_ENABLE: 49235c4bbdfSmrg return Success; 49335c4bbdfSmrg default: 49435c4bbdfSmrg return BadMatch; 49535c4bbdfSmrg } 49635c4bbdfSmrg } 49735c4bbdfSmrg else { 49835c4bbdfSmrg return (*pInfo->control_proc) (pInfo, control); 49935c4bbdfSmrg } 50005b261ecSmrg} 50105b261ecSmrg 5026747b715Smrg/* 5036747b715Smrg * Get the operating system name from uname and store it statically to avoid 5046747b715Smrg * repeating the system call each time MatchOS is checked. 5056747b715Smrg */ 5066747b715Smrgstatic const char * 5076747b715SmrgHostOS(void) 5086747b715Smrg{ 5096747b715Smrg#ifdef HAVE_SYS_UTSNAME_H 5106747b715Smrg struct utsname name; 5116747b715Smrg static char host_os[sizeof(name.sysname)] = ""; 5126747b715Smrg 5136747b715Smrg if (*host_os == '\0') { 5146747b715Smrg if (uname(&name) >= 0) 51535c4bbdfSmrg strlcpy(host_os, name.sysname, sizeof(host_os)); 5166747b715Smrg else { 51735c4bbdfSmrg strlcpy(host_os, "unknown", sizeof(host_os)); 5186747b715Smrg } 5196747b715Smrg } 5206747b715Smrg return host_os; 5216747b715Smrg#else 5226747b715Smrg return ""; 5236747b715Smrg#endif 5246747b715Smrg} 5256747b715Smrg 5266747b715Smrgstatic int 5276747b715Smrgmatch_substring(const char *attr, const char *pattern) 5286747b715Smrg{ 5296747b715Smrg return (strstr(attr, pattern)) ? 0 : -1; 5306747b715Smrg} 5316747b715Smrg 5326747b715Smrg#ifdef HAVE_FNMATCH_H 5336747b715Smrgstatic int 5346747b715Smrgmatch_pattern(const char *attr, const char *pattern) 53505b261ecSmrg{ 5366747b715Smrg return fnmatch(pattern, attr, 0); 5376747b715Smrg} 5386747b715Smrg#else 5396747b715Smrg#define match_pattern match_substring 5406747b715Smrg#endif 5416747b715Smrg 5426747b715Smrg#ifdef HAVE_FNMATCH_H 5436747b715Smrgstatic int 5446747b715Smrgmatch_path_pattern(const char *attr, const char *pattern) 5456747b715Smrg{ 5466747b715Smrg return fnmatch(pattern, attr, FNM_PATHNAME); 5476747b715Smrg} 5486747b715Smrg#else 5496747b715Smrg#define match_path_pattern match_substring 5506747b715Smrg#endif 5516747b715Smrg 55235c4bbdfSmrg/* 55335c4bbdfSmrg * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" 55435c4bbdfSmrg * It is convenient that "" in patterns means "no explicit layout" 55535c4bbdfSmrg */ 55635c4bbdfSmrgstatic int 55735c4bbdfSmrgmatch_string_implicit(const char *attr, const char *pattern) 55835c4bbdfSmrg{ 55935c4bbdfSmrg if (strlen(pattern)) { 56035c4bbdfSmrg return strcmp(attr, pattern); 56135c4bbdfSmrg } 56235c4bbdfSmrg else { 56335c4bbdfSmrg return strcmp(attr, "(implicit)"); 56435c4bbdfSmrg } 56535c4bbdfSmrg} 56635c4bbdfSmrg 5676747b715Smrg/* 5686747b715Smrg * Match an attribute against a list of NULL terminated arrays of patterns. 5696747b715Smrg * If a pattern in each list entry is matched, return TRUE. 5706747b715Smrg */ 5716747b715Smrgstatic Bool 57235c4bbdfSmrgMatchAttrToken(const char *attr, struct xorg_list *patterns, 57335c4bbdfSmrg int (*compare) (const char *attr, const char *pattern)) 5746747b715Smrg{ 5756747b715Smrg const xf86MatchGroup *group; 5766747b715Smrg 5776747b715Smrg /* If there are no patterns, accept the match */ 57835c4bbdfSmrg if (xorg_list_is_empty(patterns)) 5796747b715Smrg return TRUE; 5806747b715Smrg 5816747b715Smrg /* 5821b5d61b8Smrg * Iterate the list of patterns ensuring each entry has a 5836747b715Smrg * match. Each list entry is a separate Match line of the same type. 5846747b715Smrg */ 58535c4bbdfSmrg xorg_list_for_each_entry(group, patterns, entry) { 58635c4bbdfSmrg char *const *cur; 5871b5d61b8Smrg Bool is_negated = group->is_negated; 5881b5d61b8Smrg Bool match = is_negated; 5891b5d61b8Smrg 5901b5d61b8Smrg /* If there's a pattern but no attribute, we reject the match for a 5911b5d61b8Smrg * MatchFoo directive, and accept it for a NoMatchFoo directive 5921b5d61b8Smrg */ 5931b5d61b8Smrg if (!attr) 5941b5d61b8Smrg return is_negated; 5956747b715Smrg 5966747b715Smrg for (cur = group->values; *cur; cur++) 59735c4bbdfSmrg if ((*compare) (attr, *cur) == 0) { 5981b5d61b8Smrg match = !is_negated; 5996747b715Smrg break; 6006747b715Smrg } 6016747b715Smrg if (!match) 6026747b715Smrg return FALSE; 6036747b715Smrg } 6046747b715Smrg 6056747b715Smrg /* All the entries in the list matched the attribute */ 6066747b715Smrg return TRUE; 6076747b715Smrg} 6086747b715Smrg 6096747b715Smrg/* 6106747b715Smrg * Classes without any Match statements match all devices. Otherwise, all 6116747b715Smrg * statements must match. 6126747b715Smrg */ 6136747b715Smrgstatic Bool 6149ace9065SmrgInputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, 61535c4bbdfSmrg const InputAttributes * attrs) 6166747b715Smrg{ 6176747b715Smrg /* MatchProduct substring */ 61835c4bbdfSmrg if (!MatchAttrToken 61935c4bbdfSmrg (attrs->product, &iclass->match_product, match_substring)) 6206747b715Smrg return FALSE; 6216747b715Smrg 6226747b715Smrg /* MatchVendor substring */ 6236747b715Smrg if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) 6246747b715Smrg return FALSE; 6256747b715Smrg 6266747b715Smrg /* MatchDevicePath pattern */ 62735c4bbdfSmrg if (!MatchAttrToken 62835c4bbdfSmrg (attrs->device, &iclass->match_device, match_path_pattern)) 6296747b715Smrg return FALSE; 6306747b715Smrg 6316747b715Smrg /* MatchOS case-insensitive string */ 6326747b715Smrg if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) 6336747b715Smrg return FALSE; 6346747b715Smrg 6356747b715Smrg /* MatchPnPID pattern */ 6366747b715Smrg if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) 6376747b715Smrg return FALSE; 6386747b715Smrg 6396747b715Smrg /* MatchUSBID pattern */ 6406747b715Smrg if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) 6416747b715Smrg return FALSE; 6426747b715Smrg 6436747b715Smrg /* MatchDriver string */ 6446747b715Smrg if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) 6456747b715Smrg return FALSE; 6466747b715Smrg 6476747b715Smrg /* 6486747b715Smrg * MatchTag string 6496747b715Smrg * See if any of the device's tags match any of the MatchTag tokens. 6506747b715Smrg */ 65135c4bbdfSmrg if (!xorg_list_is_empty(&iclass->match_tag)) { 65235c4bbdfSmrg char *const *tag; 6536747b715Smrg Bool match; 6546747b715Smrg 6556747b715Smrg if (!attrs->tags) 6566747b715Smrg return FALSE; 6576747b715Smrg for (tag = attrs->tags, match = FALSE; *tag; tag++) { 6586747b715Smrg if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { 6596747b715Smrg match = TRUE; 6606747b715Smrg break; 6616747b715Smrg } 6626747b715Smrg } 6636747b715Smrg if (!match) 6646747b715Smrg return FALSE; 6656747b715Smrg } 6666747b715Smrg 66735c4bbdfSmrg /* MatchLayout string */ 66835c4bbdfSmrg if (!xorg_list_is_empty(&iclass->match_layout)) { 66935c4bbdfSmrg if (!MatchAttrToken(xf86ConfigLayout.id, 67035c4bbdfSmrg &iclass->match_layout, match_string_implicit)) 67135c4bbdfSmrg return FALSE; 67235c4bbdfSmrg } 67335c4bbdfSmrg 6746747b715Smrg /* MatchIs* booleans */ 6756747b715Smrg if (iclass->is_keyboard.set && 6761b5d61b8Smrg iclass->is_keyboard.val != ! !(attrs->flags & (ATTR_KEY|ATTR_KEYBOARD))) 6776747b715Smrg return FALSE; 6786747b715Smrg if (iclass->is_pointer.set && 67935c4bbdfSmrg iclass->is_pointer.val != ! !(attrs->flags & ATTR_POINTER)) 6806747b715Smrg return FALSE; 6816747b715Smrg if (iclass->is_joystick.set && 68235c4bbdfSmrg iclass->is_joystick.val != ! !(attrs->flags & ATTR_JOYSTICK)) 6836747b715Smrg return FALSE; 6846747b715Smrg if (iclass->is_tablet.set && 68535c4bbdfSmrg iclass->is_tablet.val != ! !(attrs->flags & ATTR_TABLET)) 6866747b715Smrg return FALSE; 6871b5d61b8Smrg if (iclass->is_tablet_pad.set && 6881b5d61b8Smrg iclass->is_tablet_pad.val != ! !(attrs->flags & ATTR_TABLET_PAD)) 6891b5d61b8Smrg return FALSE; 6906747b715Smrg if (iclass->is_touchpad.set && 69135c4bbdfSmrg iclass->is_touchpad.val != ! !(attrs->flags & ATTR_TOUCHPAD)) 6926747b715Smrg return FALSE; 6936747b715Smrg if (iclass->is_touchscreen.set && 69435c4bbdfSmrg iclass->is_touchscreen.val != ! !(attrs->flags & ATTR_TOUCHSCREEN)) 6956747b715Smrg return FALSE; 6966747b715Smrg 6976747b715Smrg return TRUE; 6986747b715Smrg} 6996747b715Smrg 7006747b715Smrg/* 7016747b715Smrg * Merge in any InputClass configurations. Options in each InputClass 7026747b715Smrg * section have more priority than the original device configuration as 7036747b715Smrg * well as any previous InputClass sections. 7046747b715Smrg */ 7056747b715Smrgstatic int 70635c4bbdfSmrgMergeInputClasses(const InputInfoPtr idev, const InputAttributes * attrs) 7076747b715Smrg{ 7086747b715Smrg XF86ConfInputClassPtr cl; 7096747b715Smrg XF86OptionPtr classopts; 7106747b715Smrg 7116747b715Smrg for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 7126747b715Smrg if (!InputClassMatches(cl, idev, attrs)) 7136747b715Smrg continue; 7146747b715Smrg 7156747b715Smrg /* Collect class options and driver settings */ 7166747b715Smrg classopts = xf86optionListDup(cl->option_lst); 7176747b715Smrg if (cl->driver) { 71835c4bbdfSmrg free((void *) idev->driver); 7196747b715Smrg idev->driver = xstrdup(cl->driver); 7206747b715Smrg if (!idev->driver) { 7216747b715Smrg xf86Msg(X_ERROR, "Failed to allocate memory while merging " 7226747b715Smrg "InputClass configuration"); 7236747b715Smrg return BadAlloc; 7246747b715Smrg } 72535c4bbdfSmrg classopts = xf86ReplaceStrOption(classopts, "driver", idev->driver); 7266747b715Smrg } 7276747b715Smrg 7286747b715Smrg /* Apply options to device with InputClass settings preferred. */ 7296747b715Smrg xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", 7309ace9065Smrg idev->name, cl->identifier); 7319ace9065Smrg idev->options = xf86optionListMerge(idev->options, classopts); 7326747b715Smrg } 7336747b715Smrg 7346747b715Smrg return Success; 7356747b715Smrg} 7366747b715Smrg 7376747b715Smrg/* 7386747b715Smrg * Iterate the list of classes and look for Option "Ignore". Return the 7396747b715Smrg * value of the last matching class and holler when returning TRUE. 7406747b715Smrg */ 7416747b715Smrgstatic Bool 74235c4bbdfSmrgIgnoreInputClass(const InputInfoPtr idev, const InputAttributes * attrs) 7436747b715Smrg{ 7446747b715Smrg XF86ConfInputClassPtr cl; 7456747b715Smrg Bool ignore = FALSE; 7466747b715Smrg const char *ignore_class; 7476747b715Smrg 7486747b715Smrg for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 7496747b715Smrg if (!InputClassMatches(cl, idev, attrs)) 7506747b715Smrg continue; 7516747b715Smrg if (xf86findOption(cl->option_lst, "Ignore")) { 7526747b715Smrg ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); 7536747b715Smrg ignore_class = cl->identifier; 7546747b715Smrg } 7556747b715Smrg } 7566747b715Smrg 7576747b715Smrg if (ignore) 7586747b715Smrg xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", 7599ace9065Smrg idev->name, ignore_class); 7606747b715Smrg return ignore; 76105b261ecSmrg} 76205b261ecSmrg 7639ace9065SmrgInputInfoPtr 7649ace9065Smrgxf86AllocateInput(void) 7659ace9065Smrg{ 7669ace9065Smrg InputInfoPtr pInfo; 7679ace9065Smrg 7689ace9065Smrg pInfo = calloc(sizeof(*pInfo), 1); 7699ace9065Smrg if (!pInfo) 7709ace9065Smrg return NULL; 7719ace9065Smrg 7729ace9065Smrg pInfo->fd = -1; 7739ace9065Smrg pInfo->type_name = "UNKNOWN"; 7749ace9065Smrg 7759ace9065Smrg return pInfo; 7769ace9065Smrg} 7779ace9065Smrg 7789ace9065Smrg/* Append InputInfoRec to the tail of xf86InputDevs. */ 7799ace9065Smrgstatic void 7809ace9065Smrgxf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) 7819ace9065Smrg{ 7829ace9065Smrg InputInfoPtr *prev = NULL; 7839ace9065Smrg 7849ace9065Smrg pInfo->drv = drv; 7859ace9065Smrg pInfo->module = DuplicateModule(drv->module, NULL); 7869ace9065Smrg 78735c4bbdfSmrg for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next); 7889ace9065Smrg 7899ace9065Smrg *prev = pInfo; 7909ace9065Smrg pInfo->next = NULL; 7919ace9065Smrg 79235c4bbdfSmrg xf86CollectInputOptions(pInfo, (const char **) drv->default_options); 7939ace9065Smrg xf86OptionListReport(pInfo->options); 7949ace9065Smrg xf86ProcessCommonOptions(pInfo, pInfo->options); 7959ace9065Smrg} 7969ace9065Smrg 7979ace9065Smrg/* 7989ace9065Smrg * Remove an entry from xf86InputDevs and free all the device's information. 7999ace9065Smrg */ 8009ace9065Smrgvoid 8019ace9065Smrgxf86DeleteInput(InputInfoPtr pInp, int flags) 8029ace9065Smrg{ 8039ace9065Smrg /* First check if the inputdev is valid. */ 8049ace9065Smrg if (pInp == NULL) 80535c4bbdfSmrg return; 8069ace9065Smrg 8079ace9065Smrg if (pInp->module) 80835c4bbdfSmrg UnloadModule(pInp->module); 8099ace9065Smrg 8109ace9065Smrg /* This should *really* be handled in drv->UnInit(dev) call instead, but 8119ace9065Smrg * if the driver forgets about it make sure we free it or at least crash 8129ace9065Smrg * with flying colors */ 8139ace9065Smrg free(pInp->private); 8149ace9065Smrg 8159ace9065Smrg FreeInputAttributes(pInp->attrs); 8169ace9065Smrg 81735c4bbdfSmrg if (pInp->flags & XI86_SERVER_FD) 81835c4bbdfSmrg systemd_logind_release_fd(pInp->major, pInp->minor, pInp->fd); 81935c4bbdfSmrg 8209ace9065Smrg /* Remove the entry from the list. */ 8219ace9065Smrg if (pInp == xf86InputDevs) 82235c4bbdfSmrg xf86InputDevs = pInp->next; 8239ace9065Smrg else { 82435c4bbdfSmrg InputInfoPtr p = xf86InputDevs; 82535c4bbdfSmrg 82635c4bbdfSmrg while (p && p->next != pInp) 82735c4bbdfSmrg p = p->next; 82835c4bbdfSmrg if (p) 82935c4bbdfSmrg p->next = pInp->next; 83035c4bbdfSmrg /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ 8319ace9065Smrg } 8329ace9065Smrg 83335c4bbdfSmrg free((void *) pInp->driver); 83435c4bbdfSmrg free((void *) pInp->name); 8359ace9065Smrg xf86optionListFree(pInp->options); 8369ace9065Smrg free(pInp); 8379ace9065Smrg} 8389ace9065Smrg 8399ace9065Smrg/* 84035c4bbdfSmrg * Apply backend-specific initialization. Invoked after ActivateDevice(), 8419ace9065Smrg * i.e. after the driver successfully completed DEVICE_INIT and the device 8429ace9065Smrg * is advertised. 8439ace9065Smrg * @param dev the device 8449ace9065Smrg * @return Success or an error code 8459ace9065Smrg */ 8469ace9065Smrgstatic int 84735c4bbdfSmrgxf86InputDevicePostInit(DeviceIntPtr dev) 84835c4bbdfSmrg{ 8499ace9065Smrg ApplyAccelerationSettings(dev); 85035c4bbdfSmrg ApplyTransformationMatrix(dev); 851ed6184dfSmrg ApplyAutoRepeat(dev); 8529ace9065Smrg return Success; 8539ace9065Smrg} 8549ace9065Smrg 85535c4bbdfSmrgstatic void 85635c4bbdfSmrgxf86stat(const char *path, int *maj, int *min) 85735c4bbdfSmrg{ 85835c4bbdfSmrg struct stat st; 85935c4bbdfSmrg 86035c4bbdfSmrg if (stat(path, &st) == -1) 86135c4bbdfSmrg return; 86235c4bbdfSmrg 86335c4bbdfSmrg *maj = major(st.st_rdev); 86435c4bbdfSmrg *min = minor(st.st_rdev); 86535c4bbdfSmrg} 86635c4bbdfSmrg 8671b5d61b8Smrgstatic inline InputDriverPtr 8681b5d61b8Smrgxf86LoadInputDriver(const char *driver_name) 8691b5d61b8Smrg{ 8701b5d61b8Smrg InputDriverPtr drv = NULL; 8711b5d61b8Smrg 8721b5d61b8Smrg /* Memory leak for every attached device if we don't 8731b5d61b8Smrg * test if the module is already loaded first */ 8741b5d61b8Smrg drv = xf86LookupInputDriver(driver_name); 8751b5d61b8Smrg if (!drv) { 8761b5d61b8Smrg if (xf86LoadOneModule(driver_name, NULL)) 8771b5d61b8Smrg drv = xf86LookupInputDriver(driver_name); 8781b5d61b8Smrg } 8791b5d61b8Smrg 8801b5d61b8Smrg return drv; 8811b5d61b8Smrg} 8821b5d61b8Smrg 8834642e01fSmrg/** 8844642e01fSmrg * Create a new input device, activate and enable it. 8854642e01fSmrg * 8864642e01fSmrg * Possible return codes: 8874642e01fSmrg * BadName .. a bad driver name was supplied. 8884642e01fSmrg * BadImplementation ... The driver does not have a PreInit function. This 8894642e01fSmrg * is a driver bug. 8904642e01fSmrg * BadMatch .. device initialization failed. 8914642e01fSmrg * BadAlloc .. too many input devices 8924642e01fSmrg * 8934642e01fSmrg * @param idev The device, already set up with identifier, driver, and the 8944642e01fSmrg * options. 8954642e01fSmrg * @param pdev Pointer to the new device, if Success was reported. 8964642e01fSmrg * @param enable Enable the device after activating it. 8974642e01fSmrg * 8984642e01fSmrg * @return Success or an error code 8994642e01fSmrg */ 9004642e01fSmrg_X_INTERNAL int 9019ace9065Smrgxf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) 90205b261ecSmrg{ 90305b261ecSmrg InputDriverPtr drv = NULL; 90405b261ecSmrg DeviceIntPtr dev = NULL; 905ed6184dfSmrg Bool paused = FALSE; 9064642e01fSmrg int rval; 90735c4bbdfSmrg char *path = NULL; 9084642e01fSmrg 9091b5d61b8Smrg drv = xf86LoadInputDriver(pInfo->driver); 9104642e01fSmrg if (!drv) { 9119ace9065Smrg xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); 9121b5d61b8Smrg 9131b5d61b8Smrg if (strlen(FALLBACK_INPUT_DRIVER) > 0) { 9141b5d61b8Smrg xf86Msg(X_INFO, "Falling back to input driver `%s'\n", 9151b5d61b8Smrg FALLBACK_INPUT_DRIVER); 9161b5d61b8Smrg drv = xf86LoadInputDriver(FALLBACK_INPUT_DRIVER); 9171b5d61b8Smrg if (drv) { 9181b5d61b8Smrg free(pInfo->driver); 9191b5d61b8Smrg pInfo->driver = strdup(FALLBACK_INPUT_DRIVER); 9201b5d61b8Smrg } 9211b5d61b8Smrg } 9221b5d61b8Smrg if (!drv) { 9231b5d61b8Smrg rval = BadName; 9241b5d61b8Smrg goto unwind; 9251b5d61b8Smrg } 9261b5d61b8Smrg } 9271b5d61b8Smrg 9281b5d61b8Smrg xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, 9291b5d61b8Smrg pInfo->name); 9301b5d61b8Smrg 9311b5d61b8Smrg if (!drv->PreInit) { 9321b5d61b8Smrg xf86Msg(X_ERROR, 9331b5d61b8Smrg "Input driver `%s' has no PreInit function (ignoring)\n", 9341b5d61b8Smrg drv->driverName); 9351b5d61b8Smrg rval = BadImplementation; 9364642e01fSmrg goto unwind; 9374642e01fSmrg } 9384642e01fSmrg 93935c4bbdfSmrg path = xf86CheckStrOption(pInfo->options, "Device", NULL); 94035c4bbdfSmrg if (path && pInfo->major == 0 && pInfo->minor == 0) 94135c4bbdfSmrg xf86stat(path, &pInfo->major, &pInfo->minor); 94235c4bbdfSmrg 94335c4bbdfSmrg if (path && (drv->capabilities & XI86_DRV_CAP_SERVER_FD)){ 94435c4bbdfSmrg int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor, 94535c4bbdfSmrg path, &paused); 94635c4bbdfSmrg if (fd != -1) { 94735c4bbdfSmrg if (paused) { 94835c4bbdfSmrg /* Put on new_input_devices list for delayed probe */ 9491b5d61b8Smrg PausedInputDevicePtr new_device = xnfalloc(sizeof *new_device); 9501b5d61b8Smrg new_device->pInfo = pInfo; 9511b5d61b8Smrg 9521b5d61b8Smrg xorg_list_append(&new_device->node, &new_input_devices_list); 95335c4bbdfSmrg systemd_logind_release_fd(pInfo->major, pInfo->minor, fd); 95435c4bbdfSmrg free(path); 95535c4bbdfSmrg return BadMatch; 95635c4bbdfSmrg } 95735c4bbdfSmrg pInfo->fd = fd; 95835c4bbdfSmrg pInfo->flags |= XI86_SERVER_FD; 95935c4bbdfSmrg pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd); 96035c4bbdfSmrg } 96135c4bbdfSmrg } 96235c4bbdfSmrg 96335c4bbdfSmrg free(path); 96435c4bbdfSmrg 9659ace9065Smrg xf86AddInput(drv, pInfo); 9664642e01fSmrg 9671b5d61b8Smrg input_lock(); 9689ace9065Smrg rval = drv->PreInit(drv, pInfo, 0); 9691b5d61b8Smrg input_unlock(); 9709ace9065Smrg 9719ace9065Smrg if (rval != Success) { 9729ace9065Smrg xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); 9734642e01fSmrg goto unwind; 9744642e01fSmrg } 9754642e01fSmrg 97635c4bbdfSmrg if (!(dev = xf86ActivateDevice(pInfo))) { 9774642e01fSmrg rval = BadAlloc; 9784642e01fSmrg goto unwind; 9794642e01fSmrg } 9804642e01fSmrg 9816747b715Smrg rval = ActivateDevice(dev, TRUE); 98235c4bbdfSmrg if (rval != Success) { 9839ace9065Smrg xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 9846747b715Smrg RemoveDevice(dev, TRUE); 9854642e01fSmrg goto unwind; 9864642e01fSmrg } 9874642e01fSmrg 9889ace9065Smrg rval = xf86InputDevicePostInit(dev); 98935c4bbdfSmrg if (rval != Success) { 99035c4bbdfSmrg xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); 99135c4bbdfSmrg RemoveDevice(dev, TRUE); 99235c4bbdfSmrg goto unwind; 9939ace9065Smrg } 9949ace9065Smrg 9954642e01fSmrg /* Enable it if it's properly initialised and we're currently in the VT */ 99635c4bbdfSmrg if (enable && dev->inited && dev->startup && xf86VTOwner()) { 9971b5d61b8Smrg input_lock(); 9986747b715Smrg EnableDevice(dev, TRUE); 99935c4bbdfSmrg if (!dev->enabled) { 10009ace9065Smrg xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 1001475c125cSmrg RemoveDevice(dev, TRUE); 10026747b715Smrg rval = BadMatch; 10031b5d61b8Smrg input_unlock(); 10046747b715Smrg goto unwind; 10056747b715Smrg } 10064642e01fSmrg /* send enter/leave event, update sprite window */ 10074642e01fSmrg CheckMotion(NULL, dev); 10081b5d61b8Smrg input_unlock(); 10094642e01fSmrg } 10104642e01fSmrg 10114642e01fSmrg *pdev = dev; 10124642e01fSmrg return Success; 10134642e01fSmrg 101435c4bbdfSmrg unwind: 101535c4bbdfSmrg if (pInfo) { 101635c4bbdfSmrg if (drv && drv->UnInit) 10174642e01fSmrg drv->UnInit(drv, pInfo, 0); 10184642e01fSmrg else 10194642e01fSmrg xf86DeleteInput(pInfo, 0); 10204642e01fSmrg } 10214642e01fSmrg return rval; 10224642e01fSmrg} 10234642e01fSmrg 10246747b715Smrgint 102535c4bbdfSmrgNewInputDeviceRequest(InputOption *options, InputAttributes * attrs, 102635c4bbdfSmrg DeviceIntPtr *pdev) 10274642e01fSmrg{ 10289ace9065Smrg InputInfoPtr pInfo = NULL; 10294642e01fSmrg InputOption *option = NULL; 103005b261ecSmrg int rval = Success; 103105b261ecSmrg int is_auto = 0; 103205b261ecSmrg 10339ace9065Smrg pInfo = xf86AllocateInput(); 10349ace9065Smrg if (!pInfo) 103505b261ecSmrg return BadAlloc; 103605b261ecSmrg 103735c4bbdfSmrg nt_list_for_each_entry(option, options, list.next) { 103835c4bbdfSmrg const char *key = input_option_get_key(option); 103935c4bbdfSmrg const char *value = input_option_get_value(option); 104035c4bbdfSmrg 104135c4bbdfSmrg if (strcasecmp(key, "driver") == 0) { 10429ace9065Smrg if (pInfo->driver) { 104305b261ecSmrg rval = BadRequest; 104405b261ecSmrg goto unwind; 104505b261ecSmrg } 104635c4bbdfSmrg pInfo->driver = xstrdup(value); 10479ace9065Smrg if (!pInfo->driver) { 104805b261ecSmrg rval = BadAlloc; 104905b261ecSmrg goto unwind; 105005b261ecSmrg } 105105b261ecSmrg } 105205b261ecSmrg 105335c4bbdfSmrg if (strcasecmp(key, "name") == 0 || strcasecmp(key, "identifier") == 0) { 10549ace9065Smrg if (pInfo->name) { 105505b261ecSmrg rval = BadRequest; 105605b261ecSmrg goto unwind; 105705b261ecSmrg } 105835c4bbdfSmrg pInfo->name = xstrdup(value); 10599ace9065Smrg if (!pInfo->name) { 106005b261ecSmrg rval = BadAlloc; 106105b261ecSmrg goto unwind; 106205b261ecSmrg } 106305b261ecSmrg } 106405b261ecSmrg 106535c4bbdfSmrg if (strcmp(key, "_source") == 0 && 106635c4bbdfSmrg (strcmp(value, "server/hal") == 0 || 106735c4bbdfSmrg strcmp(value, "server/udev") == 0 || 106835c4bbdfSmrg strcmp(value, "server/wscons") == 0)) { 10696747b715Smrg is_auto = 1; 107005b261ecSmrg if (!xf86Info.autoAddDevices) { 107105b261ecSmrg rval = BadMatch; 107205b261ecSmrg goto unwind; 107305b261ecSmrg } 10746747b715Smrg } 107535c4bbdfSmrg 107635c4bbdfSmrg if (strcmp(key, "major") == 0) 107735c4bbdfSmrg pInfo->major = atoi(value); 107835c4bbdfSmrg 107935c4bbdfSmrg if (strcmp(key, "minor") == 0) 108035c4bbdfSmrg pInfo->minor = atoi(value); 10816747b715Smrg } 108205b261ecSmrg 108335c4bbdfSmrg nt_list_for_each_entry(option, options, list.next) { 108435c4bbdfSmrg /* Copy option key/value strings from the provided list */ 108535c4bbdfSmrg pInfo->options = xf86AddNewOption(pInfo->options, 108635c4bbdfSmrg input_option_get_key(option), 108735c4bbdfSmrg input_option_get_value(option)); 10886747b715Smrg } 10896747b715Smrg 10906747b715Smrg /* Apply InputClass settings */ 10916747b715Smrg if (attrs) { 10929ace9065Smrg if (IgnoreInputClass(pInfo, attrs)) { 10936747b715Smrg rval = BadIDChoice; 10946747b715Smrg goto unwind; 109505b261ecSmrg } 10966747b715Smrg 10979ace9065Smrg rval = MergeInputClasses(pInfo, attrs); 10986747b715Smrg if (rval != Success) 10996747b715Smrg goto unwind; 11006747b715Smrg 11019ace9065Smrg pInfo->attrs = DuplicateInputAttributes(attrs); 110205b261ecSmrg } 11036747b715Smrg 1104475c125cSmrg if (!pInfo->name) { 1105475c125cSmrg xf86Msg(X_INFO, "No identifier specified, ignoring this device.\n"); 110605b261ecSmrg rval = BadRequest; 110705b261ecSmrg goto unwind; 110805b261ecSmrg } 110905b261ecSmrg 1110475c125cSmrg if (!pInfo->driver) { 1111475c125cSmrg xf86Msg(X_INFO, "No input driver specified, ignoring this device.\n"); 111235c4bbdfSmrg xf86Msg(X_INFO, 111335c4bbdfSmrg "This device may have been added with another device file.\n"); 1114475c125cSmrg rval = BadRequest; 11159ace9065Smrg goto unwind; 111605b261ecSmrg } 111705b261ecSmrg 11189ace9065Smrg rval = xf86NewInputDevice(pInfo, pdev, 111935c4bbdfSmrg (!is_auto || 112035c4bbdfSmrg (is_auto && xf86Info.autoEnableDevices))); 11219ace9065Smrg 11229ace9065Smrg return rval; 112305b261ecSmrg 112435c4bbdfSmrg unwind: 11256747b715Smrg if (is_auto && !xf86Info.autoAddDevices) 11266747b715Smrg xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); 11279ace9065Smrg xf86DeleteInput(pInfo, 0); 112805b261ecSmrg return rval; 112905b261ecSmrg} 113005b261ecSmrg 11316747b715Smrgvoid 113205b261ecSmrgDeleteInputDeviceRequest(DeviceIntPtr pDev) 113305b261ecSmrg{ 11349ace9065Smrg InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; 11354642e01fSmrg InputDriverPtr drv = NULL; 11366747b715Smrg Bool isMaster = IsMaster(pDev); 113705b261ecSmrg 113835c4bbdfSmrg if (pInfo) /* need to get these before RemoveDevice */ 11394642e01fSmrg drv = pInfo->drv; 11404642e01fSmrg 11411b5d61b8Smrg input_lock(); 11426747b715Smrg RemoveDevice(pDev, TRUE); 114305b261ecSmrg 114435c4bbdfSmrg if (!isMaster && pInfo != NULL) { 114535c4bbdfSmrg if (drv->UnInit) 11464642e01fSmrg drv->UnInit(drv, pInfo, 0); 11474642e01fSmrg else 11484642e01fSmrg xf86DeleteInput(pInfo, 0); 11494642e01fSmrg } 11501b5d61b8Smrg input_unlock(); 11511b5d61b8Smrg} 11521b5d61b8Smrg 11531b5d61b8Smrgvoid 11541b5d61b8SmrgRemoveInputDeviceTraces(const char *config_info) 11551b5d61b8Smrg{ 11561b5d61b8Smrg PausedInputDevicePtr d, tmp; 11571b5d61b8Smrg 11581b5d61b8Smrg xorg_list_for_each_entry_safe(d, tmp, &new_input_devices_list, node) { 11591b5d61b8Smrg const char *ci = xf86findOptionValue(d->pInfo->options, "config_info"); 11601b5d61b8Smrg if (!ci || strcmp(ci, config_info) != 0) 11611b5d61b8Smrg continue; 11621b5d61b8Smrg 11631b5d61b8Smrg xorg_list_del(&d->node); 11641b5d61b8Smrg free(d); 11651b5d61b8Smrg } 116605b261ecSmrg} 116705b261ecSmrg 116835c4bbdfSmrg/* 116905b261ecSmrg * convenient functions to post events 117005b261ecSmrg */ 117105b261ecSmrg 11726747b715Smrgvoid 117335c4bbdfSmrgxf86PostMotionEvent(DeviceIntPtr device, 117435c4bbdfSmrg int is_absolute, int first_valuator, int num_valuators, ...) 117505b261ecSmrg{ 117605b261ecSmrg va_list var; 117705b261ecSmrg int i = 0; 11789ace9065Smrg ValuatorMask mask; 117905b261ecSmrg 11806747b715Smrg XI_VERIFY_VALUATORS(num_valuators); 118105b261ecSmrg 11829ace9065Smrg valuator_mask_zero(&mask); 118305b261ecSmrg va_start(var, num_valuators); 118405b261ecSmrg for (i = 0; i < num_valuators; i++) 11859ace9065Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 118635c4bbdfSmrg 118705b261ecSmrg va_end(var); 118805b261ecSmrg 11899ace9065Smrg xf86PostMotionEventM(device, is_absolute, &mask); 119005b261ecSmrg} 119105b261ecSmrg 11926747b715Smrgvoid 119335c4bbdfSmrgxf86PostMotionEventP(DeviceIntPtr device, 119435c4bbdfSmrg int is_absolute, 119535c4bbdfSmrg int first_valuator, 119635c4bbdfSmrg int num_valuators, const int *valuators) 11979ace9065Smrg{ 11989ace9065Smrg ValuatorMask mask; 11999ace9065Smrg 12009ace9065Smrg XI_VERIFY_VALUATORS(num_valuators); 12019ace9065Smrg 12029ace9065Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 12039ace9065Smrg xf86PostMotionEventM(device, is_absolute, &mask); 12049ace9065Smrg} 12059ace9065Smrg 120635c4bbdfSmrgstatic int 120735c4bbdfSmrgxf86CheckMotionEvent4DGA(DeviceIntPtr device, int is_absolute, 120835c4bbdfSmrg const ValuatorMask *mask) 120905b261ecSmrg{ 121035c4bbdfSmrg int stolen = 0; 121105b261ecSmrg 12121b5d61b8Smrg#ifdef XFreeXDGA 121335c4bbdfSmrg ScreenPtr scr = NULL; 121435c4bbdfSmrg int idx = 0, i; 121535c4bbdfSmrg 12164642e01fSmrg /* The evdev driver may not always send all axes across. */ 121735c4bbdfSmrg if (valuator_mask_isset(mask, 0) || valuator_mask_isset(mask, 1)) { 121835c4bbdfSmrg scr = miPointerGetScreen(device); 121935c4bbdfSmrg if (scr) { 12209ace9065Smrg int dx = 0, dy = 0; 12219ace9065Smrg 122235c4bbdfSmrg idx = scr->myNum; 122335c4bbdfSmrg 122435c4bbdfSmrg if (valuator_mask_isset(mask, 0)) { 12259ace9065Smrg dx = valuator_mask_get(mask, 0); 12264642e01fSmrg if (is_absolute) 12274642e01fSmrg dx -= device->last.valuators[0]; 122835c4bbdfSmrg else if (valuator_mask_has_unaccelerated(mask)) 122935c4bbdfSmrg dx = valuator_mask_get_unaccelerated(mask, 0); 123005b261ecSmrg } 12314642e01fSmrg 123235c4bbdfSmrg if (valuator_mask_isset(mask, 1)) { 12339ace9065Smrg dy = valuator_mask_get(mask, 1); 12344642e01fSmrg if (is_absolute) 12354642e01fSmrg dy -= device->last.valuators[1]; 123635c4bbdfSmrg else if (valuator_mask_has_unaccelerated(mask)) 123735c4bbdfSmrg dy = valuator_mask_get_unaccelerated(mask, 1); 12384642e01fSmrg } 12394642e01fSmrg 124035c4bbdfSmrg if (DGAStealMotionEvent(device, idx, dx, dy)) 124135c4bbdfSmrg stolen = 1; 124205b261ecSmrg } 124335c4bbdfSmrg } 124435c4bbdfSmrg 124535c4bbdfSmrg for (i = 2; i < valuator_mask_size(mask); i++) { 124635c4bbdfSmrg AxisInfoPtr ax; 124735c4bbdfSmrg double incr; 124835c4bbdfSmrg int val, button; 124935c4bbdfSmrg 125035c4bbdfSmrg if (i >= device->valuator->numAxes) 125135c4bbdfSmrg break; 125235c4bbdfSmrg 125335c4bbdfSmrg if (!valuator_mask_isset(mask, i)) 125435c4bbdfSmrg continue; 125535c4bbdfSmrg 125635c4bbdfSmrg ax = &device->valuator->axes[i]; 125735c4bbdfSmrg 125835c4bbdfSmrg if (ax->scroll.type == SCROLL_TYPE_NONE) 125935c4bbdfSmrg continue; 126035c4bbdfSmrg 126135c4bbdfSmrg if (!scr) { 126235c4bbdfSmrg scr = miPointerGetScreen(device); 126335c4bbdfSmrg if (!scr) 126435c4bbdfSmrg break; 126535c4bbdfSmrg idx = scr->myNum; 126635c4bbdfSmrg } 126735c4bbdfSmrg 126835c4bbdfSmrg incr = ax->scroll.increment; 126935c4bbdfSmrg val = valuator_mask_get(mask, i); 127035c4bbdfSmrg 127135c4bbdfSmrg if (ax->scroll.type == SCROLL_TYPE_VERTICAL) { 127235c4bbdfSmrg if (incr * val < 0) 127335c4bbdfSmrg button = 4; /* up */ 127435c4bbdfSmrg else 127535c4bbdfSmrg button = 5; /* down */ 127635c4bbdfSmrg } else { /* SCROLL_TYPE_HORIZONTAL */ 127735c4bbdfSmrg if (incr * val < 0) 127835c4bbdfSmrg button = 6; /* left */ 127935c4bbdfSmrg else 128035c4bbdfSmrg button = 7; /* right */ 128135c4bbdfSmrg } 128235c4bbdfSmrg 128335c4bbdfSmrg if (DGAStealButtonEvent(device, idx, button, 1) && 128435c4bbdfSmrg DGAStealButtonEvent(device, idx, button, 0)) 128535c4bbdfSmrg stolen = 1; 128635c4bbdfSmrg } 128735c4bbdfSmrg 128805b261ecSmrg#endif 128905b261ecSmrg 129035c4bbdfSmrg return stolen; 129135c4bbdfSmrg} 129235c4bbdfSmrg 129335c4bbdfSmrgvoid 129435c4bbdfSmrgxf86PostMotionEventM(DeviceIntPtr device, 129535c4bbdfSmrg int is_absolute, const ValuatorMask *mask) 129635c4bbdfSmrg{ 129735c4bbdfSmrg int flags = 0; 129805b261ecSmrg 129935c4bbdfSmrg if (xf86CheckMotionEvent4DGA(device, is_absolute, mask)) 130035c4bbdfSmrg return; 130135c4bbdfSmrg 130235c4bbdfSmrg if (valuator_mask_num_valuators(mask) > 0) { 130335c4bbdfSmrg if (is_absolute) 130435c4bbdfSmrg flags = POINTER_ABSOLUTE; 130535c4bbdfSmrg else 130635c4bbdfSmrg flags = POINTER_RELATIVE | POINTER_ACCELERATE; 130705b261ecSmrg } 130835c4bbdfSmrg 130935c4bbdfSmrg QueuePointerEvents(device, MotionNotify, 0, flags, mask); 131005b261ecSmrg} 131105b261ecSmrg 13126747b715Smrgvoid 131335c4bbdfSmrgxf86PostProximityEvent(DeviceIntPtr device, 131435c4bbdfSmrg int is_in, int first_valuator, int num_valuators, ...) 131505b261ecSmrg{ 131605b261ecSmrg va_list var; 13176747b715Smrg int i; 13189ace9065Smrg ValuatorMask mask; 131905b261ecSmrg 13206747b715Smrg XI_VERIFY_VALUATORS(num_valuators); 132105b261ecSmrg 13229ace9065Smrg valuator_mask_zero(&mask); 132305b261ecSmrg va_start(var, num_valuators); 132405b261ecSmrg for (i = 0; i < num_valuators; i++) 13259ace9065Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 132635c4bbdfSmrg 132705b261ecSmrg va_end(var); 132805b261ecSmrg 13299ace9065Smrg xf86PostProximityEventM(device, is_in, &mask); 13306747b715Smrg} 13316747b715Smrg 13326747b715Smrgvoid 133335c4bbdfSmrgxf86PostProximityEventP(DeviceIntPtr device, 133435c4bbdfSmrg int is_in, 133535c4bbdfSmrg int first_valuator, 133635c4bbdfSmrg int num_valuators, const int *valuators) 13376747b715Smrg{ 13389ace9065Smrg ValuatorMask mask; 13396747b715Smrg 13406747b715Smrg XI_VERIFY_VALUATORS(num_valuators); 13416747b715Smrg 13429ace9065Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 13439ace9065Smrg xf86PostProximityEventM(device, is_in, &mask); 13449ace9065Smrg} 13459ace9065Smrg 13469ace9065Smrgvoid 134735c4bbdfSmrgxf86PostProximityEventM(DeviceIntPtr device, 134835c4bbdfSmrg int is_in, const ValuatorMask *mask) 13499ace9065Smrg{ 135035c4bbdfSmrg QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask); 135105b261ecSmrg} 135205b261ecSmrg 13536747b715Smrgvoid 135435c4bbdfSmrgxf86PostButtonEvent(DeviceIntPtr device, 135535c4bbdfSmrg int is_absolute, 135635c4bbdfSmrg int button, 135735c4bbdfSmrg int is_down, int first_valuator, int num_valuators, ...) 135805b261ecSmrg{ 135905b261ecSmrg va_list var; 13609ace9065Smrg ValuatorMask mask; 13616747b715Smrg int i = 0; 13626747b715Smrg 13636747b715Smrg XI_VERIFY_VALUATORS(num_valuators); 13646747b715Smrg 13659ace9065Smrg valuator_mask_zero(&mask); 13669ace9065Smrg 13676747b715Smrg va_start(var, num_valuators); 13686747b715Smrg for (i = 0; i < num_valuators; i++) 13699ace9065Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 137035c4bbdfSmrg 13716747b715Smrg va_end(var); 13726747b715Smrg 13739ace9065Smrg xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 13746747b715Smrg} 13756747b715Smrg 13766747b715Smrgvoid 137735c4bbdfSmrgxf86PostButtonEventP(DeviceIntPtr device, 137835c4bbdfSmrg int is_absolute, 137935c4bbdfSmrg int button, 138035c4bbdfSmrg int is_down, 138135c4bbdfSmrg int first_valuator, 138235c4bbdfSmrg int num_valuators, const int *valuators) 13836747b715Smrg{ 13849ace9065Smrg ValuatorMask mask; 13856747b715Smrg 13866747b715Smrg XI_VERIFY_VALUATORS(num_valuators); 13876747b715Smrg 13889ace9065Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 13899ace9065Smrg xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 13909ace9065Smrg} 13919ace9065Smrg 13929ace9065Smrgvoid 139335c4bbdfSmrgxf86PostButtonEventM(DeviceIntPtr device, 139435c4bbdfSmrg int is_absolute, 139535c4bbdfSmrg int button, int is_down, const ValuatorMask *mask) 13969ace9065Smrg{ 13979ace9065Smrg int flags = 0; 13989ace9065Smrg 139935c4bbdfSmrg if (valuator_mask_num_valuators(mask) > 0) { 14009ace9065Smrg if (is_absolute) 14019ace9065Smrg flags = POINTER_ABSOLUTE; 14029ace9065Smrg else 14039ace9065Smrg flags = POINTER_RELATIVE | POINTER_ACCELERATE; 14049ace9065Smrg } 140505b261ecSmrg 14061b5d61b8Smrg#ifdef XFreeXDGA 14074642e01fSmrg if (miPointerGetScreen(device)) { 14089ace9065Smrg int index = miPointerGetScreen(device)->myNum; 14099ace9065Smrg 14104642e01fSmrg if (DGAStealButtonEvent(device, index, button, is_down)) 141105b261ecSmrg return; 141205b261ecSmrg } 141305b261ecSmrg#endif 141405b261ecSmrg 141535c4bbdfSmrg QueuePointerEvents(device, 141635c4bbdfSmrg is_down ? ButtonPress : ButtonRelease, button, 141735c4bbdfSmrg flags, mask); 141805b261ecSmrg} 141905b261ecSmrg 14206747b715Smrgvoid 142135c4bbdfSmrgxf86PostKeyEvent(DeviceIntPtr device, unsigned int key_code, int is_down) 142205b261ecSmrg{ 142335c4bbdfSmrg xf86PostKeyEventM(device, key_code, is_down); 14246747b715Smrg} 14256747b715Smrg 14266747b715Smrgvoid 142735c4bbdfSmrgxf86PostKeyEventP(DeviceIntPtr device, 142835c4bbdfSmrg unsigned int key_code, 142935c4bbdfSmrg int is_down) 14306747b715Smrg{ 143135c4bbdfSmrg xf86PostKeyEventM(device, key_code, is_down); 14329ace9065Smrg} 14339ace9065Smrg 14349ace9065Smrgvoid 143535c4bbdfSmrgxf86PostKeyEventM(DeviceIntPtr device, unsigned int key_code, int is_down) 14369ace9065Smrg{ 14371b5d61b8Smrg#ifdef XFreeXDGA 14389ace9065Smrg DeviceIntPtr pointer; 14399ace9065Smrg 14409ace9065Smrg /* Some pointers send key events, paired device is wrong then. */ 144135c4bbdfSmrg pointer = GetMaster(device, POINTER_OR_FLOAT); 144235c4bbdfSmrg 14439ace9065Smrg if (miPointerGetScreen(pointer)) { 14449ace9065Smrg int index = miPointerGetScreen(pointer)->myNum; 14459ace9065Smrg 14469ace9065Smrg if (DGAStealKeyEvent(device, index, key_code, is_down)) 14479ace9065Smrg return; 14489ace9065Smrg } 14499ace9065Smrg#endif 14509ace9065Smrg 145135c4bbdfSmrg QueueKeyboardEvents(device, is_down ? KeyPress : KeyRelease, key_code); 145205b261ecSmrg} 145305b261ecSmrg 14546747b715Smrgvoid 145535c4bbdfSmrgxf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code, int is_down) 145605b261ecSmrg{ 14579ace9065Smrg ValuatorMask mask; 14589ace9065Smrg 14599ace9065Smrg valuator_mask_zero(&mask); 146035c4bbdfSmrg xf86PostKeyEventM(device, key_code, is_down); 146105b261ecSmrg} 146205b261ecSmrg 14639ace9065SmrgInputInfoPtr 14646747b715Smrgxf86FirstLocalDevice(void) 146505b261ecSmrg{ 146605b261ecSmrg return xf86InputDevs; 146705b261ecSmrg} 146805b261ecSmrg 146935c4bbdfSmrg/* 147005b261ecSmrg * Cx - raw data from touch screen 14719ace9065Smrg * to_max - scaled highest dimension 147205b261ecSmrg * (remember, this is of rows - 1 because of 0 origin) 14739ace9065Smrg * to_min - scaled lowest dimension 14749ace9065Smrg * from_max - highest raw value from touch screen calibration 14759ace9065Smrg * from_min - lowest raw value from touch screen calibration 147605b261ecSmrg * 147705b261ecSmrg * This function is the same for X or Y coordinates. 147805b261ecSmrg * You may have to reverse the high and low values to compensate for 1479ed6184dfSmrg * different origins on the touch screen vs X. 14809ace9065Smrg * 14819ace9065Smrg * e.g. to scale from device coordinates into screen coordinates, call 14829ace9065Smrg * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); 148305b261ecSmrg */ 148405b261ecSmrg 14856747b715Smrgint 148635c4bbdfSmrgxf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min) 148705b261ecSmrg{ 148805b261ecSmrg int X; 14899ace9065Smrg int64_t to_width = to_max - to_min; 14909ace9065Smrg int64_t from_width = from_max - from_min; 149105b261ecSmrg 14929ace9065Smrg if (from_width) { 149335c4bbdfSmrg X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min); 149405b261ecSmrg } 149505b261ecSmrg else { 149635c4bbdfSmrg X = 0; 149735c4bbdfSmrg ErrorF("Divide by Zero in xf86ScaleAxis\n"); 149805b261ecSmrg } 149935c4bbdfSmrg 15009ace9065Smrg if (X > to_max) 150135c4bbdfSmrg X = to_max; 15029ace9065Smrg if (X < to_min) 150335c4bbdfSmrg X = to_min; 150405b261ecSmrg 150535c4bbdfSmrg return X; 150605b261ecSmrg} 150705b261ecSmrg 150835c4bbdfSmrgBool 150935c4bbdfSmrgxf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, 151035c4bbdfSmrg int maxval, int resolution, int min_res, int max_res, 151135c4bbdfSmrg int mode) 151205b261ecSmrg{ 151305b261ecSmrg if (!dev || !dev->valuator) 151435c4bbdfSmrg return FALSE; 151505b261ecSmrg 151635c4bbdfSmrg return InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, 151735c4bbdfSmrg min_res, max_res, mode); 151805b261ecSmrg} 151905b261ecSmrg 152005b261ecSmrg/* 152135c4bbdfSmrg * Set the valuator values to be in sync with dix/event.c 152205b261ecSmrg * DefineInitialRootWindow(). 152305b261ecSmrg */ 15246747b715Smrgvoid 152505b261ecSmrgxf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) 152605b261ecSmrg{ 152705b261ecSmrg if (axnum == 0) { 152835c4bbdfSmrg dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 15294642e01fSmrg dev->last.valuators[0] = dev->valuator->axisVal[0]; 153005b261ecSmrg } 153105b261ecSmrg else if (axnum == 1) { 153235c4bbdfSmrg dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 15334642e01fSmrg dev->last.valuators[1] = dev->valuator->axisVal[1]; 153405b261ecSmrg } 153505b261ecSmrg} 153605b261ecSmrg 153705b261ecSmrg/** 153805b261ecSmrg * Deactivate a device. Call this function from the driver if you receive a 153905b261ecSmrg * read error or something else that spoils your day. 154005b261ecSmrg * Device will be moved to the off_devices list, but it will still be there 154105b261ecSmrg * until you really clean up after it. 154205b261ecSmrg * Notifies the client about an inactive device. 154335c4bbdfSmrg * 154405b261ecSmrg * @param panic True if device is unrecoverable and needs to be removed. 154505b261ecSmrg */ 15466747b715Smrgvoid 154705b261ecSmrgxf86DisableDevice(DeviceIntPtr dev, Bool panic) 154805b261ecSmrg{ 154935c4bbdfSmrg if (!panic) { 15506747b715Smrg DisableDevice(dev, TRUE); 155135c4bbdfSmrg } 155235c4bbdfSmrg else { 15536747b715Smrg SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); 155405b261ecSmrg DeleteInputDeviceRequest(dev); 155505b261ecSmrg } 155605b261ecSmrg} 155705b261ecSmrg 155805b261ecSmrg/** 155905b261ecSmrg * Reactivate a device. Call this function from the driver if you just found 156005b261ecSmrg * out that the read error wasn't quite that bad after all. 156135c4bbdfSmrg * Device will be re-activated, and an event sent to the client. 156205b261ecSmrg */ 15636747b715Smrgvoid 156405b261ecSmrgxf86EnableDevice(DeviceIntPtr dev) 156505b261ecSmrg{ 15666747b715Smrg EnableDevice(dev, TRUE); 156705b261ecSmrg} 156805b261ecSmrg 156935c4bbdfSmrg/** 157035c4bbdfSmrg * Post a touch event with optional valuators. If this is the first touch in 157135c4bbdfSmrg * the sequence, at least x & y valuators must be provided. The driver is 157235c4bbdfSmrg * responsible for maintaining the correct event sequence (TouchBegin, TouchUpdate, 157335c4bbdfSmrg * TouchEnd). Submitting an update or end event for a unregistered touchid will 157435c4bbdfSmrg * result in errors. 157535c4bbdfSmrg * Touch IDs may be reused by the driver but only after a TouchEnd has been 157635c4bbdfSmrg * submitted for that touch ID. 157735c4bbdfSmrg * 157835c4bbdfSmrg * @param dev The device to post the event for 157935c4bbdfSmrg * @param touchid The touchid of the current touch event. Must be an 158035c4bbdfSmrg * existing ID for TouchUpdate or TouchEnd events 158135c4bbdfSmrg * @param type One of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd 158235c4bbdfSmrg * @param flags Flags for this event 158335c4bbdfSmrg * @param The valuator mask with all valuators set for this event. 158435c4bbdfSmrg */ 158535c4bbdfSmrgvoid 158635c4bbdfSmrgxf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type, 158735c4bbdfSmrg uint32_t flags, const ValuatorMask *mask) 158835c4bbdfSmrg{ 158935c4bbdfSmrg 159035c4bbdfSmrg QueueTouchEvents(dev, type, touchid, flags, mask); 159135c4bbdfSmrg} 159235c4bbdfSmrg 1593ed6184dfSmrg/** 1594ed6184dfSmrg * Post a gesture pinch event. The driver is responsible for maintaining the 1595ed6184dfSmrg * correct event sequence (GesturePinchBegin, GesturePinchUpdate, 1596ed6184dfSmrg * GesturePinchEnd). 1597ed6184dfSmrg * 1598ed6184dfSmrg * @param dev The device to post the event for 1599ed6184dfSmrg * @param type One of XI_GesturePinchBegin, XI_GesturePinchUpdate, 1600ed6184dfSmrg * XI_GesturePinchEnd 1601ed6184dfSmrg * @param num_touches The number of touches in the gesture 1602ed6184dfSmrg * @param flags Flags for this event 1603ed6184dfSmrg * @param delta_x,delta_y accelerated relative motion delta 1604ed6184dfSmrg * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta 1605ed6184dfSmrg * @param scale absolute scale of a pinch gesture 1606ed6184dfSmrg * @param delta_angle the ange delta in degrees between the last and the current pinch event. 1607ed6184dfSmrg */ 1608ed6184dfSmrgvoid 1609ed6184dfSmrgxf86PostGesturePinchEvent(DeviceIntPtr dev, uint16_t type, 1610ed6184dfSmrg uint16_t num_touches, uint32_t flags, 1611ed6184dfSmrg double delta_x, double delta_y, 1612ed6184dfSmrg double delta_unaccel_x, 1613ed6184dfSmrg double delta_unaccel_y, 1614ed6184dfSmrg double scale, double delta_angle) 1615ed6184dfSmrg{ 1616ed6184dfSmrg QueueGesturePinchEvents(dev, type, num_touches, flags, delta_x, delta_y, 1617ed6184dfSmrg delta_unaccel_x, delta_unaccel_y, 1618ed6184dfSmrg scale, delta_angle); 1619ed6184dfSmrg} 1620ed6184dfSmrg 1621ed6184dfSmrg/** 1622ed6184dfSmrg * Post a gesture swipe event. The driver is responsible for maintaining the 1623ed6184dfSmrg * correct event sequence (GestureSwipeBegin, GestureSwipeUpdate, 1624ed6184dfSmrg * GestureSwipeEnd). 1625ed6184dfSmrg * 1626ed6184dfSmrg * @param dev The device to post the event for 1627ed6184dfSmrg * @param type One of XI_GestureSwipeBegin, XI_GestureSwipeUpdate, 1628ed6184dfSmrg * XI_GestureSwipeEnd 1629ed6184dfSmrg * @param num_touches The number of touches in the gesture 1630ed6184dfSmrg * @param flags Flags for this event 1631ed6184dfSmrg * @param delta_x,delta_y accelerated relative motion delta 1632ed6184dfSmrg * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta 1633ed6184dfSmrg */ 1634ed6184dfSmrgvoid 1635ed6184dfSmrgxf86PostGestureSwipeEvent(DeviceIntPtr dev, uint16_t type, 1636ed6184dfSmrg uint16_t num_touches, uint32_t flags, 1637ed6184dfSmrg double delta_x, double delta_y, 1638ed6184dfSmrg double delta_unaccel_x, 1639ed6184dfSmrg double delta_unaccel_y) 1640ed6184dfSmrg{ 1641ed6184dfSmrg QueueGestureSwipeEvents(dev, type, num_touches, flags, delta_x, delta_y, 1642ed6184dfSmrg delta_unaccel_x, delta_unaccel_y); 1643ed6184dfSmrg} 1644ed6184dfSmrg 164535c4bbdfSmrgvoid 164635c4bbdfSmrgxf86InputEnableVTProbe(void) 164735c4bbdfSmrg{ 16481b5d61b8Smrg int is_auto = 0; 164935c4bbdfSmrg DeviceIntPtr pdev; 16501b5d61b8Smrg PausedInputDevicePtr d, tmp; 165135c4bbdfSmrg 16521b5d61b8Smrg xorg_list_for_each_entry_safe(d, tmp, &new_input_devices_list, node) { 16531b5d61b8Smrg InputInfoPtr pInfo = d->pInfo; 16541b5d61b8Smrg const char *value = xf86findOptionValue(pInfo->options, "_source"); 165535c4bbdfSmrg 165635c4bbdfSmrg is_auto = 0; 16571b5d61b8Smrg if (value && 16581b5d61b8Smrg (strcmp(value, "server/hal") == 0 || 16591b5d61b8Smrg strcmp(value, "server/udev") == 0 || 16601b5d61b8Smrg strcmp(value, "server/wscons") == 0)) 16611b5d61b8Smrg is_auto = 1; 16621b5d61b8Smrg 166335c4bbdfSmrg xf86NewInputDevice(pInfo, &pdev, 166435c4bbdfSmrg (!is_auto || 166535c4bbdfSmrg (is_auto && xf86Info.autoEnableDevices))); 16661b5d61b8Smrg xorg_list_del(&d->node); 16671b5d61b8Smrg free(d); 166835c4bbdfSmrg } 166935c4bbdfSmrg} 167035c4bbdfSmrg 167105b261ecSmrg/* end of xf86Xinput.c */ 1672