1706f2543Smrg/* 2706f2543Smrg * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that 7706f2543Smrg * copyright notice and this permission notice appear in supporting 8706f2543Smrg * documentation, and that the name of Frederic Lepied not be used in 9706f2543Smrg * advertising or publicity pertaining to distribution of the software without 10706f2543Smrg * specific, written prior permission. Frederic Lepied makes no 11706f2543Smrg * representations about the suitability of this software for any purpose. It 12706f2543Smrg * is provided "as is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg * 22706f2543Smrg */ 23706f2543Smrg/* 24706f2543Smrg * Copyright (c) 2000-2002 by The XFree86 Project, Inc. 25706f2543Smrg * 26706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 27706f2543Smrg * copy of this software and associated documentation files (the "Software"), 28706f2543Smrg * to deal in the Software without restriction, including without limitation 29706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 30706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 31706f2543Smrg * Software is furnished to do so, subject to the following conditions: 32706f2543Smrg * 33706f2543Smrg * The above copyright notice and this permission notice shall be included in 34706f2543Smrg * all copies or substantial portions of the Software. 35706f2543Smrg * 36706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 39706f2543Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 40706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 41706f2543Smrg * OTHER DEALINGS IN THE SOFTWARE. 42706f2543Smrg * 43706f2543Smrg * Except as contained in this notice, the name of the copyright holder(s) 44706f2543Smrg * and author(s) shall not be used in advertising or otherwise to promote 45706f2543Smrg * the sale, use or other dealings in this Software without prior written 46706f2543Smrg * authorization from the copyright holder(s) and author(s). 47706f2543Smrg */ 48706f2543Smrg 49706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 50706f2543Smrg#include <xorg-config.h> 51706f2543Smrg#endif 52706f2543Smrg 53706f2543Smrg#include <X11/Xfuncproto.h> 54706f2543Smrg#include <X11/Xmd.h> 55706f2543Smrg#include <X11/extensions/XI.h> 56706f2543Smrg#include <X11/extensions/XIproto.h> 57706f2543Smrg#include <X11/Xatom.h> 58706f2543Smrg#include "xf86.h" 59706f2543Smrg#include "xf86Priv.h" 60706f2543Smrg#include "xf86Config.h" 61706f2543Smrg#include "xf86Xinput.h" 62706f2543Smrg#include "xf86Optrec.h" 63706f2543Smrg#include "mipointer.h" 64706f2543Smrg#include "extinit.h" 65706f2543Smrg#include "loaderProcs.h" 66706f2543Smrg 67706f2543Smrg#include "exevents.h" /* AddInputDevice */ 68706f2543Smrg#include "exglobals.h" 69706f2543Smrg#include "eventstr.h" 70706f2543Smrg#include "inpututils.h" 71706f2543Smrg 72706f2543Smrg#include <string.h> /* InputClassMatches */ 73706f2543Smrg#ifdef HAVE_FNMATCH_H 74706f2543Smrg#include <fnmatch.h> 75706f2543Smrg#endif 76706f2543Smrg#ifdef HAVE_SYS_UTSNAME_H 77706f2543Smrg#include <sys/utsname.h> 78706f2543Smrg#endif 79706f2543Smrg 80706f2543Smrg#include <stdarg.h> 81706f2543Smrg#include <stdint.h> /* for int64_t */ 82706f2543Smrg 83706f2543Smrg#include "mi.h" 84706f2543Smrg 85706f2543Smrg#include <ptrveloc.h> /* dix pointer acceleration */ 86706f2543Smrg#include <xserver-properties.h> 87706f2543Smrg 88706f2543Smrg#ifdef XFreeXDGA 89706f2543Smrg#include "dgaproc.h" 90706f2543Smrg#endif 91706f2543Smrg 92706f2543Smrg#include "xkbsrv.h" 93706f2543Smrg 94706f2543Smrg/* Valuator verification macro */ 95706f2543Smrg#define XI_VERIFY_VALUATORS(num_valuators) \ 96706f2543Smrg if (num_valuators > MAX_VALUATORS) { \ 97706f2543Smrg xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ 98706f2543Smrg " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ 99706f2543Smrg return; \ 100706f2543Smrg } 101706f2543Smrg 102706f2543SmrgEventListPtr xf86Events = NULL; 103706f2543Smrg 104706f2543Smrgstatic int 105706f2543Smrgxf86InputDevicePostInit(DeviceIntPtr dev); 106706f2543Smrg 107706f2543Smrg/** 108706f2543Smrg * Eval config and modify DeviceVelocityRec accordingly 109706f2543Smrg */ 110706f2543Smrgstatic void 111706f2543SmrgProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, 112706f2543Smrg DeviceVelocityPtr s) 113706f2543Smrg{ 114706f2543Smrg int tempi; 115706f2543Smrg float tempf; 116706f2543Smrg Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); 117706f2543Smrg Atom prop; 118706f2543Smrg 119706f2543Smrg if(!s) 120706f2543Smrg return; 121706f2543Smrg 122706f2543Smrg /* common settings (available via device properties) */ 123706f2543Smrg tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); 124706f2543Smrg if (tempf > 1.0) { 125706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", 126706f2543Smrg devname, tempf); 127706f2543Smrg prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); 128706f2543Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 129706f2543Smrg PropModeReplace, 1, &tempf, FALSE); 130706f2543Smrg } 131706f2543Smrg 132706f2543Smrg tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); 133706f2543Smrg if (tempf > 1.0) { 134706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", 135706f2543Smrg devname, tempf); 136706f2543Smrg prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); 137706f2543Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 138706f2543Smrg PropModeReplace, 1, &tempf, FALSE); 139706f2543Smrg } 140706f2543Smrg 141706f2543Smrg /* select profile by number */ 142706f2543Smrg tempi = xf86SetIntOption(list, "AccelerationProfile", 143706f2543Smrg s->statistics.profile_number); 144706f2543Smrg 145706f2543Smrg prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); 146706f2543Smrg if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, 147706f2543Smrg PropModeReplace, 1, &tempi, FALSE) == Success) { 148706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, 149706f2543Smrg tempi); 150706f2543Smrg } else { 151706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", 152706f2543Smrg devname, tempi); 153706f2543Smrg } 154706f2543Smrg 155706f2543Smrg /* set scaling */ 156706f2543Smrg tempf = xf86SetRealOption(list, "ExpectedRate", 0); 157706f2543Smrg prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); 158706f2543Smrg if (tempf > 0) { 159706f2543Smrg tempf = 1000.0 / tempf; 160706f2543Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 161706f2543Smrg PropModeReplace, 1, &tempf, FALSE); 162706f2543Smrg } else { 163706f2543Smrg tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); 164706f2543Smrg XIChangeDeviceProperty(pDev, prop, float_prop, 32, 165706f2543Smrg PropModeReplace, 1, &tempf, FALSE); 166706f2543Smrg } 167706f2543Smrg 168706f2543Smrg tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); 169706f2543Smrg if (tempi > 1) 170706f2543Smrg InitTrackers(s, tempi); 171706f2543Smrg 172706f2543Smrg s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", 173706f2543Smrg s->initial_range); 174706f2543Smrg 175706f2543Smrg s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); 176706f2543Smrg 177706f2543Smrg tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); 178706f2543Smrg if (tempf >= 0) { 179706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", 180706f2543Smrg devname, tempf*100.0); 181706f2543Smrg s->max_rel_diff = tempf; 182706f2543Smrg } 183706f2543Smrg 184706f2543Smrg /* Configure softening. If const deceleration is used, this is expected 185706f2543Smrg * to provide better subpixel information so we enable 186706f2543Smrg * softening by default only if ConstantDeceleration is not used 187706f2543Smrg */ 188706f2543Smrg s->use_softening = xf86SetBoolOption(list, "Softening", 189706f2543Smrg s->const_acceleration == 1.0); 190706f2543Smrg 191706f2543Smrg s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", 192706f2543Smrg s->average_accel); 193706f2543Smrg 194706f2543Smrg s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); 195706f2543Smrg} 196706f2543Smrg 197706f2543Smrgstatic void 198706f2543SmrgApplyAccelerationSettings(DeviceIntPtr dev){ 199706f2543Smrg int scheme, i; 200706f2543Smrg DeviceVelocityPtr pVel; 201706f2543Smrg InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; 202706f2543Smrg char* schemeStr; 203706f2543Smrg 204706f2543Smrg if (dev->valuator && dev->ptrfeed) { 205706f2543Smrg schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); 206706f2543Smrg 207706f2543Smrg scheme = dev->valuator->accelScheme.number; 208706f2543Smrg 209706f2543Smrg if (!xf86NameCmp(schemeStr, "predictable")) 210706f2543Smrg scheme = PtrAccelPredictable; 211706f2543Smrg 212706f2543Smrg if (!xf86NameCmp(schemeStr, "lightweight")) 213706f2543Smrg scheme = PtrAccelLightweight; 214706f2543Smrg 215706f2543Smrg if (!xf86NameCmp(schemeStr, "none")) 216706f2543Smrg scheme = PtrAccelNoOp; 217706f2543Smrg 218706f2543Smrg /* reinit scheme if needed */ 219706f2543Smrg if (dev->valuator->accelScheme.number != scheme) { 220706f2543Smrg if (dev->valuator->accelScheme.AccelCleanupProc) { 221706f2543Smrg dev->valuator->accelScheme.AccelCleanupProc(dev); 222706f2543Smrg } 223706f2543Smrg 224706f2543Smrg if (InitPointerAccelerationScheme(dev, scheme)) { 225706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", 226706f2543Smrg pInfo->name, schemeStr, scheme); 227706f2543Smrg } else { 228706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", 229706f2543Smrg pInfo->name, schemeStr); 230706f2543Smrg scheme = dev->valuator->accelScheme.number; 231706f2543Smrg } 232706f2543Smrg } else { 233706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", 234706f2543Smrg pInfo->name, scheme); 235706f2543Smrg } 236706f2543Smrg 237706f2543Smrg free(schemeStr); 238706f2543Smrg 239706f2543Smrg /* process special configuration */ 240706f2543Smrg switch (scheme) { 241706f2543Smrg case PtrAccelPredictable: 242706f2543Smrg pVel = GetDevicePredictableAccelData(dev); 243706f2543Smrg ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, 244706f2543Smrg pVel); 245706f2543Smrg break; 246706f2543Smrg } 247706f2543Smrg 248706f2543Smrg i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", 249706f2543Smrg dev->ptrfeed->ctrl.num); 250706f2543Smrg if (i >= 0) 251706f2543Smrg dev->ptrfeed->ctrl.num = i; 252706f2543Smrg 253706f2543Smrg i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", 254706f2543Smrg dev->ptrfeed->ctrl.den); 255706f2543Smrg if (i > 0) 256706f2543Smrg dev->ptrfeed->ctrl.den = i; 257706f2543Smrg 258706f2543Smrg i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", 259706f2543Smrg dev->ptrfeed->ctrl.threshold); 260706f2543Smrg if (i >= 0) 261706f2543Smrg dev->ptrfeed->ctrl.threshold = i; 262706f2543Smrg 263706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", 264706f2543Smrg pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ 265706f2543Smrg ((float)dev->ptrfeed->ctrl.den)); 266706f2543Smrg xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", 267706f2543Smrg pInfo->name, dev->ptrfeed->ctrl.threshold); 268706f2543Smrg } 269706f2543Smrg} 270706f2543Smrg 271706f2543Smrg/*********************************************************************** 272706f2543Smrg * 273706f2543Smrg * xf86ProcessCommonOptions -- 274706f2543Smrg * 275706f2543Smrg * Process global options. 276706f2543Smrg * 277706f2543Smrg *********************************************************************** 278706f2543Smrg */ 279706f2543Smrgvoid 280706f2543Smrgxf86ProcessCommonOptions(InputInfoPtr pInfo, 281706f2543Smrg pointer list) 282706f2543Smrg{ 283706f2543Smrg if (xf86SetBoolOption(list, "Floating", 0) || 284706f2543Smrg !xf86SetBoolOption(list, "AlwaysCore", 1) || 285706f2543Smrg !xf86SetBoolOption(list, "SendCoreEvents", 1) || 286706f2543Smrg !xf86SetBoolOption(list, "CorePointer", 1) || 287706f2543Smrg !xf86SetBoolOption(list, "CoreKeyboard", 1)) { 288706f2543Smrg xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); 289706f2543Smrg } else { 290706f2543Smrg pInfo->flags |= XI86_ALWAYS_CORE; 291706f2543Smrg xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); 292706f2543Smrg } 293706f2543Smrg} 294706f2543Smrg 295706f2543Smrg/*********************************************************************** 296706f2543Smrg * 297706f2543Smrg * xf86ActivateDevice -- 298706f2543Smrg * 299706f2543Smrg * Initialize an input device. 300706f2543Smrg * 301706f2543Smrg * Returns TRUE on success, or FALSE otherwise. 302706f2543Smrg *********************************************************************** 303706f2543Smrg */ 304706f2543Smrgstatic DeviceIntPtr 305706f2543Smrgxf86ActivateDevice(InputInfoPtr pInfo) 306706f2543Smrg{ 307706f2543Smrg DeviceIntPtr dev; 308706f2543Smrg Atom atom; 309706f2543Smrg 310706f2543Smrg dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); 311706f2543Smrg 312706f2543Smrg if (dev == NULL) 313706f2543Smrg { 314706f2543Smrg xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", 315706f2543Smrg pInfo->name); 316706f2543Smrg pInfo->dev = NULL; 317706f2543Smrg return NULL; 318706f2543Smrg } 319706f2543Smrg 320706f2543Smrg atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); 321706f2543Smrg AssignTypeAndName(dev, atom, pInfo->name); 322706f2543Smrg dev->public.devicePrivate = pInfo; 323706f2543Smrg pInfo->dev = dev; 324706f2543Smrg 325706f2543Smrg dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; 326706f2543Smrg dev->type = SLAVE; 327706f2543Smrg dev->spriteInfo->spriteOwner = FALSE; 328706f2543Smrg 329706f2543Smrg dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); 330706f2543Smrg 331706f2543Smrg if (serverGeneration == 1) 332706f2543Smrg xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", 333706f2543Smrg pInfo->name, pInfo->type_name); 334706f2543Smrg 335706f2543Smrg return dev; 336706f2543Smrg} 337706f2543Smrg 338706f2543Smrg/**************************************************************************** 339706f2543Smrg * 340706f2543Smrg * Caller: ProcXSetDeviceMode 341706f2543Smrg * 342706f2543Smrg * Change the mode of an extension device. 343706f2543Smrg * This function is used to change the mode of a device from reporting 344706f2543Smrg * relative motion to reporting absolute positional information, and 345706f2543Smrg * vice versa. 346706f2543Smrg * The default implementation below is that no such devices are supported. 347706f2543Smrg * 348706f2543Smrg *********************************************************************** 349706f2543Smrg */ 350706f2543Smrg 351706f2543Smrgint 352706f2543SmrgSetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) 353706f2543Smrg{ 354706f2543Smrg InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; 355706f2543Smrg 356706f2543Smrg if (pInfo->switch_mode) { 357706f2543Smrg return (*pInfo->switch_mode)(client, dev, mode); 358706f2543Smrg } 359706f2543Smrg else 360706f2543Smrg return BadMatch; 361706f2543Smrg} 362706f2543Smrg 363706f2543Smrg 364706f2543Smrg/*********************************************************************** 365706f2543Smrg * 366706f2543Smrg * Caller: ProcXSetDeviceValuators 367706f2543Smrg * 368706f2543Smrg * Set the value of valuators on an extension input device. 369706f2543Smrg * This function is used to set the initial value of valuators on 370706f2543Smrg * those input devices that are capable of reporting either relative 371706f2543Smrg * motion or an absolute position, and allow an initial position to be set. 372706f2543Smrg * The default implementation below is that no such devices are supported. 373706f2543Smrg * 374706f2543Smrg *********************************************************************** 375706f2543Smrg */ 376706f2543Smrg 377706f2543Smrgint 378706f2543SmrgSetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, 379706f2543Smrg int first_valuator, int num_valuators) 380706f2543Smrg{ 381706f2543Smrg InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; 382706f2543Smrg 383706f2543Smrg if (pInfo->set_device_valuators) 384706f2543Smrg return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, 385706f2543Smrg num_valuators); 386706f2543Smrg 387706f2543Smrg return BadMatch; 388706f2543Smrg} 389706f2543Smrg 390706f2543Smrg 391706f2543Smrg/*********************************************************************** 392706f2543Smrg * 393706f2543Smrg * Caller: ProcXChangeDeviceControl 394706f2543Smrg * 395706f2543Smrg * Change the specified device controls on an extension input device. 396706f2543Smrg * 397706f2543Smrg *********************************************************************** 398706f2543Smrg */ 399706f2543Smrg 400706f2543Smrgint 401706f2543SmrgChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) 402706f2543Smrg{ 403706f2543Smrg InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; 404706f2543Smrg 405706f2543Smrg if (!pInfo->control_proc) { 406706f2543Smrg switch (control->control) { 407706f2543Smrg case DEVICE_CORE: 408706f2543Smrg return BadMatch; 409706f2543Smrg case DEVICE_RESOLUTION: 410706f2543Smrg case DEVICE_ABS_CALIB: 411706f2543Smrg case DEVICE_ABS_AREA: 412706f2543Smrg case DEVICE_ENABLE: 413706f2543Smrg return Success; 414706f2543Smrg default: 415706f2543Smrg return BadMatch; 416706f2543Smrg } 417706f2543Smrg } 418706f2543Smrg else { 419706f2543Smrg return (*pInfo->control_proc)(pInfo, control); 420706f2543Smrg } 421706f2543Smrg} 422706f2543Smrg 423706f2543Smrg/* 424706f2543Smrg * Get the operating system name from uname and store it statically to avoid 425706f2543Smrg * repeating the system call each time MatchOS is checked. 426706f2543Smrg */ 427706f2543Smrgstatic const char * 428706f2543SmrgHostOS(void) 429706f2543Smrg{ 430706f2543Smrg#ifdef HAVE_SYS_UTSNAME_H 431706f2543Smrg struct utsname name; 432706f2543Smrg static char host_os[sizeof(name.sysname)] = ""; 433706f2543Smrg 434706f2543Smrg if (*host_os == '\0') { 435706f2543Smrg if (uname(&name) >= 0) 436706f2543Smrg strcpy(host_os, name.sysname); 437706f2543Smrg else { 438706f2543Smrg strncpy(host_os, "unknown", sizeof(host_os)); 439706f2543Smrg host_os[sizeof(host_os)-1] = '\0'; 440706f2543Smrg } 441706f2543Smrg } 442706f2543Smrg return host_os; 443706f2543Smrg#else 444706f2543Smrg return ""; 445706f2543Smrg#endif 446706f2543Smrg} 447706f2543Smrg 448706f2543Smrgstatic int 449706f2543Smrgmatch_substring(const char *attr, const char *pattern) 450706f2543Smrg{ 451706f2543Smrg return (strstr(attr, pattern)) ? 0 : -1; 452706f2543Smrg} 453706f2543Smrg 454706f2543Smrg#ifdef HAVE_FNMATCH_H 455706f2543Smrgstatic int 456706f2543Smrgmatch_pattern(const char *attr, const char *pattern) 457706f2543Smrg{ 458706f2543Smrg return fnmatch(pattern, attr, 0); 459706f2543Smrg} 460706f2543Smrg#else 461706f2543Smrg#define match_pattern match_substring 462706f2543Smrg#endif 463706f2543Smrg 464706f2543Smrg#ifdef HAVE_FNMATCH_H 465706f2543Smrgstatic int 466706f2543Smrgmatch_path_pattern(const char *attr, const char *pattern) 467706f2543Smrg{ 468706f2543Smrg return fnmatch(pattern, attr, FNM_PATHNAME); 469706f2543Smrg} 470706f2543Smrg#else 471706f2543Smrg#define match_path_pattern match_substring 472706f2543Smrg#endif 473706f2543Smrg 474706f2543Smrg/* 475706f2543Smrg * Match an attribute against a list of NULL terminated arrays of patterns. 476706f2543Smrg * If a pattern in each list entry is matched, return TRUE. 477706f2543Smrg */ 478706f2543Smrgstatic Bool 479706f2543SmrgMatchAttrToken(const char *attr, struct list *patterns, 480706f2543Smrg int (*compare)(const char *attr, const char *pattern)) 481706f2543Smrg{ 482706f2543Smrg const xf86MatchGroup *group; 483706f2543Smrg 484706f2543Smrg /* If there are no patterns, accept the match */ 485706f2543Smrg if (list_is_empty(patterns)) 486706f2543Smrg return TRUE; 487706f2543Smrg 488706f2543Smrg /* If there are patterns but no attribute, reject the match */ 489706f2543Smrg if (!attr) 490706f2543Smrg return FALSE; 491706f2543Smrg 492706f2543Smrg /* 493706f2543Smrg * Otherwise, iterate the list of patterns ensuring each entry has a 494706f2543Smrg * match. Each list entry is a separate Match line of the same type. 495706f2543Smrg */ 496706f2543Smrg list_for_each_entry(group, patterns, entry) { 497706f2543Smrg char * const *cur; 498706f2543Smrg Bool match = FALSE; 499706f2543Smrg 500706f2543Smrg for (cur = group->values; *cur; cur++) 501706f2543Smrg if ((*compare)(attr, *cur) == 0) { 502706f2543Smrg match = TRUE; 503706f2543Smrg break; 504706f2543Smrg } 505706f2543Smrg if (!match) 506706f2543Smrg return FALSE; 507706f2543Smrg } 508706f2543Smrg 509706f2543Smrg /* All the entries in the list matched the attribute */ 510706f2543Smrg return TRUE; 511706f2543Smrg} 512706f2543Smrg 513706f2543Smrg/* 514706f2543Smrg * Classes without any Match statements match all devices. Otherwise, all 515706f2543Smrg * statements must match. 516706f2543Smrg */ 517706f2543Smrgstatic Bool 518706f2543SmrgInputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, 519706f2543Smrg const InputAttributes *attrs) 520706f2543Smrg{ 521706f2543Smrg /* MatchProduct substring */ 522706f2543Smrg if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) 523706f2543Smrg return FALSE; 524706f2543Smrg 525706f2543Smrg /* MatchVendor substring */ 526706f2543Smrg if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) 527706f2543Smrg return FALSE; 528706f2543Smrg 529706f2543Smrg /* MatchDevicePath pattern */ 530706f2543Smrg if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) 531706f2543Smrg return FALSE; 532706f2543Smrg 533706f2543Smrg /* MatchOS case-insensitive string */ 534706f2543Smrg if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) 535706f2543Smrg return FALSE; 536706f2543Smrg 537706f2543Smrg /* MatchPnPID pattern */ 538706f2543Smrg if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) 539706f2543Smrg return FALSE; 540706f2543Smrg 541706f2543Smrg /* MatchUSBID pattern */ 542706f2543Smrg if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) 543706f2543Smrg return FALSE; 544706f2543Smrg 545706f2543Smrg /* MatchDriver string */ 546706f2543Smrg if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) 547706f2543Smrg return FALSE; 548706f2543Smrg 549706f2543Smrg /* 550706f2543Smrg * MatchTag string 551706f2543Smrg * See if any of the device's tags match any of the MatchTag tokens. 552706f2543Smrg */ 553706f2543Smrg if (!list_is_empty(&iclass->match_tag)) { 554706f2543Smrg char * const *tag; 555706f2543Smrg Bool match; 556706f2543Smrg 557706f2543Smrg if (!attrs->tags) 558706f2543Smrg return FALSE; 559706f2543Smrg for (tag = attrs->tags, match = FALSE; *tag; tag++) { 560706f2543Smrg if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { 561706f2543Smrg match = TRUE; 562706f2543Smrg break; 563706f2543Smrg } 564706f2543Smrg } 565706f2543Smrg if (!match) 566706f2543Smrg return FALSE; 567706f2543Smrg } 568706f2543Smrg 569706f2543Smrg /* MatchIs* booleans */ 570706f2543Smrg if (iclass->is_keyboard.set && 571706f2543Smrg iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) 572706f2543Smrg return FALSE; 573706f2543Smrg if (iclass->is_pointer.set && 574706f2543Smrg iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) 575706f2543Smrg return FALSE; 576706f2543Smrg if (iclass->is_joystick.set && 577706f2543Smrg iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) 578706f2543Smrg return FALSE; 579706f2543Smrg if (iclass->is_tablet.set && 580706f2543Smrg iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) 581706f2543Smrg return FALSE; 582706f2543Smrg if (iclass->is_touchpad.set && 583706f2543Smrg iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) 584706f2543Smrg return FALSE; 585706f2543Smrg if (iclass->is_touchscreen.set && 586706f2543Smrg iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) 587706f2543Smrg return FALSE; 588706f2543Smrg 589706f2543Smrg return TRUE; 590706f2543Smrg} 591706f2543Smrg 592706f2543Smrg/* 593706f2543Smrg * Merge in any InputClass configurations. Options in each InputClass 594706f2543Smrg * section have more priority than the original device configuration as 595706f2543Smrg * well as any previous InputClass sections. 596706f2543Smrg */ 597706f2543Smrgstatic int 598706f2543SmrgMergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) 599706f2543Smrg{ 600706f2543Smrg XF86ConfInputClassPtr cl; 601706f2543Smrg XF86OptionPtr classopts; 602706f2543Smrg 603706f2543Smrg for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 604706f2543Smrg if (!InputClassMatches(cl, idev, attrs)) 605706f2543Smrg continue; 606706f2543Smrg 607706f2543Smrg /* Collect class options and driver settings */ 608706f2543Smrg classopts = xf86optionListDup(cl->option_lst); 609706f2543Smrg if (cl->driver) { 610706f2543Smrg free(idev->driver); 611706f2543Smrg idev->driver = xstrdup(cl->driver); 612706f2543Smrg if (!idev->driver) { 613706f2543Smrg xf86Msg(X_ERROR, "Failed to allocate memory while merging " 614706f2543Smrg "InputClass configuration"); 615706f2543Smrg return BadAlloc; 616706f2543Smrg } 617706f2543Smrg classopts = xf86ReplaceStrOption(classopts, "driver", 618706f2543Smrg idev->driver); 619706f2543Smrg } 620706f2543Smrg 621706f2543Smrg /* Apply options to device with InputClass settings preferred. */ 622706f2543Smrg xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", 623706f2543Smrg idev->name, cl->identifier); 624706f2543Smrg idev->options = xf86optionListMerge(idev->options, classopts); 625706f2543Smrg } 626706f2543Smrg 627706f2543Smrg return Success; 628706f2543Smrg} 629706f2543Smrg 630706f2543Smrg/* 631706f2543Smrg * Iterate the list of classes and look for Option "Ignore". Return the 632706f2543Smrg * value of the last matching class and holler when returning TRUE. 633706f2543Smrg */ 634706f2543Smrgstatic Bool 635706f2543SmrgIgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) 636706f2543Smrg{ 637706f2543Smrg XF86ConfInputClassPtr cl; 638706f2543Smrg Bool ignore = FALSE; 639706f2543Smrg const char *ignore_class; 640706f2543Smrg 641706f2543Smrg for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { 642706f2543Smrg if (!InputClassMatches(cl, idev, attrs)) 643706f2543Smrg continue; 644706f2543Smrg if (xf86findOption(cl->option_lst, "Ignore")) { 645706f2543Smrg ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); 646706f2543Smrg ignore_class = cl->identifier; 647706f2543Smrg } 648706f2543Smrg } 649706f2543Smrg 650706f2543Smrg if (ignore) 651706f2543Smrg xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", 652706f2543Smrg idev->name, ignore_class); 653706f2543Smrg return ignore; 654706f2543Smrg} 655706f2543Smrg 656706f2543SmrgInputInfoPtr 657706f2543Smrgxf86AllocateInput(void) 658706f2543Smrg{ 659706f2543Smrg InputInfoPtr pInfo; 660706f2543Smrg 661706f2543Smrg pInfo = calloc(sizeof(*pInfo), 1); 662706f2543Smrg if (!pInfo) 663706f2543Smrg return NULL; 664706f2543Smrg 665706f2543Smrg pInfo->fd = -1; 666706f2543Smrg pInfo->type_name = "UNKNOWN"; 667706f2543Smrg 668706f2543Smrg return pInfo; 669706f2543Smrg} 670706f2543Smrg 671706f2543Smrg/* Append InputInfoRec to the tail of xf86InputDevs. */ 672706f2543Smrgstatic void 673706f2543Smrgxf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) 674706f2543Smrg{ 675706f2543Smrg InputInfoPtr *prev = NULL; 676706f2543Smrg 677706f2543Smrg pInfo->drv = drv; 678706f2543Smrg pInfo->module = DuplicateModule(drv->module, NULL); 679706f2543Smrg 680706f2543Smrg for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) 681706f2543Smrg ; 682706f2543Smrg 683706f2543Smrg *prev = pInfo; 684706f2543Smrg pInfo->next = NULL; 685706f2543Smrg 686706f2543Smrg xf86CollectInputOptions(pInfo, (const char**)drv->default_options); 687706f2543Smrg xf86OptionListReport(pInfo->options); 688706f2543Smrg xf86ProcessCommonOptions(pInfo, pInfo->options); 689706f2543Smrg} 690706f2543Smrg 691706f2543Smrg/* 692706f2543Smrg * Remove an entry from xf86InputDevs and free all the device's information. 693706f2543Smrg */ 694706f2543Smrgvoid 695706f2543Smrgxf86DeleteInput(InputInfoPtr pInp, int flags) 696706f2543Smrg{ 697706f2543Smrg /* First check if the inputdev is valid. */ 698706f2543Smrg if (pInp == NULL) 699706f2543Smrg return; 700706f2543Smrg 701706f2543Smrg if (pInp->module) 702706f2543Smrg UnloadModule(pInp->module); 703706f2543Smrg 704706f2543Smrg /* This should *really* be handled in drv->UnInit(dev) call instead, but 705706f2543Smrg * if the driver forgets about it make sure we free it or at least crash 706706f2543Smrg * with flying colors */ 707706f2543Smrg free(pInp->private); 708706f2543Smrg 709706f2543Smrg FreeInputAttributes(pInp->attrs); 710706f2543Smrg 711706f2543Smrg /* Remove the entry from the list. */ 712706f2543Smrg if (pInp == xf86InputDevs) 713706f2543Smrg xf86InputDevs = pInp->next; 714706f2543Smrg else { 715706f2543Smrg InputInfoPtr p = xf86InputDevs; 716706f2543Smrg while (p && p->next != pInp) 717706f2543Smrg p = p->next; 718706f2543Smrg if (p) 719706f2543Smrg p->next = pInp->next; 720706f2543Smrg /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ 721706f2543Smrg } 722706f2543Smrg 723706f2543Smrg free(pInp->driver); 724706f2543Smrg free(pInp->name); 725706f2543Smrg xf86optionListFree(pInp->options); 726706f2543Smrg free(pInp); 727706f2543Smrg} 728706f2543Smrg 729706f2543Smrg/* 730706f2543Smrg * Apply backend-specific initialization. Invoked after ActiveteDevice(), 731706f2543Smrg * i.e. after the driver successfully completed DEVICE_INIT and the device 732706f2543Smrg * is advertised. 733706f2543Smrg * @param dev the device 734706f2543Smrg * @return Success or an error code 735706f2543Smrg */ 736706f2543Smrgstatic int 737706f2543Smrgxf86InputDevicePostInit(DeviceIntPtr dev) { 738706f2543Smrg ApplyAccelerationSettings(dev); 739706f2543Smrg return Success; 740706f2543Smrg} 741706f2543Smrg 742706f2543Smrg/** 743706f2543Smrg * Create a new input device, activate and enable it. 744706f2543Smrg * 745706f2543Smrg * Possible return codes: 746706f2543Smrg * BadName .. a bad driver name was supplied. 747706f2543Smrg * BadImplementation ... The driver does not have a PreInit function. This 748706f2543Smrg * is a driver bug. 749706f2543Smrg * BadMatch .. device initialization failed. 750706f2543Smrg * BadAlloc .. too many input devices 751706f2543Smrg * 752706f2543Smrg * @param idev The device, already set up with identifier, driver, and the 753706f2543Smrg * options. 754706f2543Smrg * @param pdev Pointer to the new device, if Success was reported. 755706f2543Smrg * @param enable Enable the device after activating it. 756706f2543Smrg * 757706f2543Smrg * @return Success or an error code 758706f2543Smrg */ 759706f2543Smrg_X_INTERNAL int 760706f2543Smrgxf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) 761706f2543Smrg{ 762706f2543Smrg InputDriverPtr drv = NULL; 763706f2543Smrg DeviceIntPtr dev = NULL; 764706f2543Smrg int rval; 765706f2543Smrg 766706f2543Smrg /* Memory leak for every attached device if we don't 767706f2543Smrg * test if the module is already loaded first */ 768706f2543Smrg drv = xf86LookupInputDriver(pInfo->driver); 769706f2543Smrg if (!drv) 770706f2543Smrg if (xf86LoadOneModule(pInfo->driver, NULL)) 771706f2543Smrg drv = xf86LookupInputDriver(pInfo->driver); 772706f2543Smrg if (!drv) { 773706f2543Smrg xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); 774706f2543Smrg rval = BadName; 775706f2543Smrg goto unwind; 776706f2543Smrg } 777706f2543Smrg 778706f2543Smrg xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, pInfo->name); 779706f2543Smrg 780706f2543Smrg if (!drv->PreInit) { 781706f2543Smrg xf86Msg(X_ERROR, 782706f2543Smrg "Input driver `%s' has no PreInit function (ignoring)\n", 783706f2543Smrg drv->driverName); 784706f2543Smrg rval = BadImplementation; 785706f2543Smrg goto unwind; 786706f2543Smrg } 787706f2543Smrg 788706f2543Smrg xf86AddInput(drv, pInfo); 789706f2543Smrg 790706f2543Smrg rval = drv->PreInit(drv, pInfo, 0); 791706f2543Smrg 792706f2543Smrg if (rval != Success) { 793706f2543Smrg xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); 794706f2543Smrg goto unwind; 795706f2543Smrg } 796706f2543Smrg 797706f2543Smrg if (!(dev = xf86ActivateDevice(pInfo))) 798706f2543Smrg { 799706f2543Smrg rval = BadAlloc; 800706f2543Smrg goto unwind; 801706f2543Smrg } 802706f2543Smrg 803706f2543Smrg rval = ActivateDevice(dev, TRUE); 804706f2543Smrg if (rval != Success) 805706f2543Smrg { 806706f2543Smrg xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 807706f2543Smrg RemoveDevice(dev, TRUE); 808706f2543Smrg goto unwind; 809706f2543Smrg } 810706f2543Smrg 811706f2543Smrg rval = xf86InputDevicePostInit(dev); 812706f2543Smrg if (rval != Success) 813706f2543Smrg { 814706f2543Smrg xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); 815706f2543Smrg RemoveDevice(dev, TRUE); 816706f2543Smrg goto unwind; 817706f2543Smrg } 818706f2543Smrg 819706f2543Smrg /* Enable it if it's properly initialised and we're currently in the VT */ 820706f2543Smrg if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) 821706f2543Smrg { 822706f2543Smrg OsBlockSignals(); 823706f2543Smrg EnableDevice(dev, TRUE); 824706f2543Smrg if (!dev->enabled) 825706f2543Smrg { 826706f2543Smrg OsReleaseSignals(); 827706f2543Smrg xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); 828706f2543Smrg RemoveDevice(dev, TRUE); 829706f2543Smrg rval = BadMatch; 830706f2543Smrg goto unwind; 831706f2543Smrg } 832706f2543Smrg /* send enter/leave event, update sprite window */ 833706f2543Smrg CheckMotion(NULL, dev); 834706f2543Smrg OsReleaseSignals(); 835706f2543Smrg } 836706f2543Smrg 837706f2543Smrg *pdev = dev; 838706f2543Smrg return Success; 839706f2543Smrg 840706f2543Smrgunwind: 841706f2543Smrg if(pInfo) { 842706f2543Smrg if(drv && drv->UnInit) 843706f2543Smrg drv->UnInit(drv, pInfo, 0); 844706f2543Smrg else 845706f2543Smrg xf86DeleteInput(pInfo, 0); 846706f2543Smrg } 847706f2543Smrg return rval; 848706f2543Smrg} 849706f2543Smrg 850706f2543Smrgint 851706f2543SmrgNewInputDeviceRequest (InputOption *options, InputAttributes *attrs, 852706f2543Smrg DeviceIntPtr *pdev) 853706f2543Smrg{ 854706f2543Smrg InputInfoPtr pInfo = NULL; 855706f2543Smrg InputOption *option = NULL; 856706f2543Smrg int rval = Success; 857706f2543Smrg int is_auto = 0; 858706f2543Smrg 859706f2543Smrg pInfo = xf86AllocateInput(); 860706f2543Smrg if (!pInfo) 861706f2543Smrg return BadAlloc; 862706f2543Smrg 863706f2543Smrg for (option = options; option; option = option->next) { 864706f2543Smrg if (strcasecmp(option->key, "driver") == 0) { 865706f2543Smrg if (pInfo->driver) { 866706f2543Smrg rval = BadRequest; 867706f2543Smrg goto unwind; 868706f2543Smrg } 869706f2543Smrg pInfo->driver = xstrdup(option->value); 870706f2543Smrg if (!pInfo->driver) { 871706f2543Smrg rval = BadAlloc; 872706f2543Smrg goto unwind; 873706f2543Smrg } 874706f2543Smrg } 875706f2543Smrg 876706f2543Smrg if (strcasecmp(option->key, "name") == 0 || 877706f2543Smrg strcasecmp(option->key, "identifier") == 0) { 878706f2543Smrg if (pInfo->name) { 879706f2543Smrg rval = BadRequest; 880706f2543Smrg goto unwind; 881706f2543Smrg } 882706f2543Smrg pInfo->name = xstrdup(option->value); 883706f2543Smrg if (!pInfo->name) { 884706f2543Smrg rval = BadAlloc; 885706f2543Smrg goto unwind; 886706f2543Smrg } 887706f2543Smrg } 888706f2543Smrg 889706f2543Smrg if (strcmp(option->key, "_source") == 0 && 890706f2543Smrg (strcmp(option->value, "server/hal") == 0 || 891706f2543Smrg strcmp(option->value, "server/udev") == 0)) { 892706f2543Smrg is_auto = 1; 893706f2543Smrg if (!xf86Info.autoAddDevices) { 894706f2543Smrg rval = BadMatch; 895706f2543Smrg goto unwind; 896706f2543Smrg } 897706f2543Smrg } 898706f2543Smrg } 899706f2543Smrg 900706f2543Smrg for (option = options; option; option = option->next) { 901706f2543Smrg /* Steal option key/value strings from the provided list. 902706f2543Smrg * We need those strings, the InputOption list doesn't. */ 903706f2543Smrg pInfo->options = xf86addNewOption(pInfo->options, 904706f2543Smrg option->key, option->value); 905706f2543Smrg option->key = NULL; 906706f2543Smrg option->value = NULL; 907706f2543Smrg } 908706f2543Smrg 909706f2543Smrg /* Apply InputClass settings */ 910706f2543Smrg if (attrs) { 911706f2543Smrg if (IgnoreInputClass(pInfo, attrs)) { 912706f2543Smrg rval = BadIDChoice; 913706f2543Smrg goto unwind; 914706f2543Smrg } 915706f2543Smrg 916706f2543Smrg rval = MergeInputClasses(pInfo, attrs); 917706f2543Smrg if (rval != Success) 918706f2543Smrg goto unwind; 919706f2543Smrg 920706f2543Smrg pInfo->attrs = DuplicateInputAttributes(attrs); 921706f2543Smrg } 922706f2543Smrg 923706f2543Smrg if (!pInfo->name) { 924706f2543Smrg xf86Msg(X_INFO, "No identifier specified, ignoring this device.\n"); 925706f2543Smrg rval = BadRequest; 926706f2543Smrg goto unwind; 927706f2543Smrg } 928706f2543Smrg 929706f2543Smrg if (!pInfo->driver) { 930706f2543Smrg xf86Msg(X_INFO, "No input driver specified, ignoring this device.\n"); 931706f2543Smrg xf86Msg(X_INFO, "This device may have been added with another device file.\n"); 932706f2543Smrg rval = BadRequest; 933706f2543Smrg goto unwind; 934706f2543Smrg } 935706f2543Smrg 936706f2543Smrg rval = xf86NewInputDevice(pInfo, pdev, 937706f2543Smrg (!is_auto || (is_auto && xf86Info.autoEnableDevices))); 938706f2543Smrg 939706f2543Smrg return rval; 940706f2543Smrg 941706f2543Smrgunwind: 942706f2543Smrg if (is_auto && !xf86Info.autoAddDevices) 943706f2543Smrg xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); 944706f2543Smrg xf86DeleteInput(pInfo, 0); 945706f2543Smrg return rval; 946706f2543Smrg} 947706f2543Smrg 948706f2543Smrgvoid 949706f2543SmrgDeleteInputDeviceRequest(DeviceIntPtr pDev) 950706f2543Smrg{ 951706f2543Smrg InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; 952706f2543Smrg InputDriverPtr drv = NULL; 953706f2543Smrg Bool isMaster = IsMaster(pDev); 954706f2543Smrg 955706f2543Smrg if (pInfo) /* need to get these before RemoveDevice */ 956706f2543Smrg drv = pInfo->drv; 957706f2543Smrg 958706f2543Smrg OsBlockSignals(); 959706f2543Smrg RemoveDevice(pDev, TRUE); 960706f2543Smrg 961706f2543Smrg if (!isMaster && pInfo != NULL) 962706f2543Smrg { 963706f2543Smrg if(drv->UnInit) 964706f2543Smrg drv->UnInit(drv, pInfo, 0); 965706f2543Smrg else 966706f2543Smrg xf86DeleteInput(pInfo, 0); 967706f2543Smrg } 968706f2543Smrg OsReleaseSignals(); 969706f2543Smrg} 970706f2543Smrg 971706f2543Smrg/* 972706f2543Smrg * convenient functions to post events 973706f2543Smrg */ 974706f2543Smrg 975706f2543Smrgvoid 976706f2543Smrgxf86PostMotionEvent(DeviceIntPtr device, 977706f2543Smrg int is_absolute, 978706f2543Smrg int first_valuator, 979706f2543Smrg int num_valuators, 980706f2543Smrg ...) 981706f2543Smrg{ 982706f2543Smrg va_list var; 983706f2543Smrg int i = 0; 984706f2543Smrg ValuatorMask mask; 985706f2543Smrg 986706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 987706f2543Smrg 988706f2543Smrg valuator_mask_zero(&mask); 989706f2543Smrg va_start(var, num_valuators); 990706f2543Smrg for (i = 0; i < num_valuators; i++) 991706f2543Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 992706f2543Smrg va_end(var); 993706f2543Smrg 994706f2543Smrg xf86PostMotionEventM(device, is_absolute, &mask); 995706f2543Smrg} 996706f2543Smrg 997706f2543Smrgvoid 998706f2543Smrgxf86PostMotionEventP(DeviceIntPtr device, 999706f2543Smrg int is_absolute, 1000706f2543Smrg int first_valuator, 1001706f2543Smrg int num_valuators, 1002706f2543Smrg const int *valuators) 1003706f2543Smrg{ 1004706f2543Smrg ValuatorMask mask; 1005706f2543Smrg 1006706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1007706f2543Smrg 1008706f2543Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1009706f2543Smrg xf86PostMotionEventM(device, is_absolute, &mask); 1010706f2543Smrg} 1011706f2543Smrg 1012706f2543Smrgvoid 1013706f2543Smrgxf86PostMotionEventM(DeviceIntPtr device, 1014706f2543Smrg int is_absolute, 1015706f2543Smrg const ValuatorMask *mask) 1016706f2543Smrg{ 1017706f2543Smrg int i = 0, nevents = 0; 1018706f2543Smrg DeviceEvent *event; 1019706f2543Smrg int flags = 0; 1020706f2543Smrg 1021706f2543Smrg if (valuator_mask_num_valuators(mask) > 0) 1022706f2543Smrg { 1023706f2543Smrg if (is_absolute) 1024706f2543Smrg flags = POINTER_ABSOLUTE; 1025706f2543Smrg else 1026706f2543Smrg flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1027706f2543Smrg } 1028706f2543Smrg 1029706f2543Smrg#if XFreeXDGA 1030706f2543Smrg /* The evdev driver may not always send all axes across. */ 1031706f2543Smrg if (valuator_mask_isset(mask, 0) || 1032706f2543Smrg valuator_mask_isset(mask, 1)) 1033706f2543Smrg if (miPointerGetScreen(device)) { 1034706f2543Smrg int index = miPointerGetScreen(device)->myNum; 1035706f2543Smrg int dx = 0, dy = 0; 1036706f2543Smrg 1037706f2543Smrg if (valuator_mask_isset(mask, 0)) 1038706f2543Smrg { 1039706f2543Smrg dx = valuator_mask_get(mask, 0); 1040706f2543Smrg if (is_absolute) 1041706f2543Smrg dx -= device->last.valuators[0]; 1042706f2543Smrg } 1043706f2543Smrg 1044706f2543Smrg if (valuator_mask_isset(mask, 1)) 1045706f2543Smrg { 1046706f2543Smrg dy = valuator_mask_get(mask, 1); 1047706f2543Smrg if (is_absolute) 1048706f2543Smrg dy -= device->last.valuators[1]; 1049706f2543Smrg } 1050706f2543Smrg 1051706f2543Smrg if (DGAStealMotionEvent(device, index, dx, dy)) 1052706f2543Smrg return; 1053706f2543Smrg } 1054706f2543Smrg#endif 1055706f2543Smrg 1056706f2543Smrg nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask); 1057706f2543Smrg 1058706f2543Smrg for (i = 0; i < nevents; i++) { 1059706f2543Smrg event = (DeviceEvent*)((xf86Events + i)->event); 1060706f2543Smrg mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1061706f2543Smrg } 1062706f2543Smrg} 1063706f2543Smrg 1064706f2543Smrgvoid 1065706f2543Smrgxf86PostProximityEvent(DeviceIntPtr device, 1066706f2543Smrg int is_in, 1067706f2543Smrg int first_valuator, 1068706f2543Smrg int num_valuators, 1069706f2543Smrg ...) 1070706f2543Smrg{ 1071706f2543Smrg va_list var; 1072706f2543Smrg int i; 1073706f2543Smrg ValuatorMask mask; 1074706f2543Smrg 1075706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1076706f2543Smrg 1077706f2543Smrg valuator_mask_zero(&mask); 1078706f2543Smrg va_start(var, num_valuators); 1079706f2543Smrg for (i = 0; i < num_valuators; i++) 1080706f2543Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1081706f2543Smrg va_end(var); 1082706f2543Smrg 1083706f2543Smrg xf86PostProximityEventM(device, is_in, &mask); 1084706f2543Smrg} 1085706f2543Smrg 1086706f2543Smrgvoid 1087706f2543Smrgxf86PostProximityEventP(DeviceIntPtr device, 1088706f2543Smrg int is_in, 1089706f2543Smrg int first_valuator, 1090706f2543Smrg int num_valuators, 1091706f2543Smrg const int *valuators) 1092706f2543Smrg{ 1093706f2543Smrg ValuatorMask mask; 1094706f2543Smrg 1095706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1096706f2543Smrg 1097706f2543Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1098706f2543Smrg xf86PostProximityEventM(device, is_in, &mask); 1099706f2543Smrg} 1100706f2543Smrg 1101706f2543Smrgvoid 1102706f2543Smrgxf86PostProximityEventM(DeviceIntPtr device, 1103706f2543Smrg int is_in, 1104706f2543Smrg const ValuatorMask *mask) 1105706f2543Smrg{ 1106706f2543Smrg int i, nevents; 1107706f2543Smrg 1108706f2543Smrg nevents = GetProximityEvents(xf86Events, device, 1109706f2543Smrg is_in ? ProximityIn : ProximityOut, mask); 1110706f2543Smrg for (i = 0; i < nevents; i++) 1111706f2543Smrg mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1112706f2543Smrg 1113706f2543Smrg} 1114706f2543Smrg 1115706f2543Smrgvoid 1116706f2543Smrgxf86PostButtonEvent(DeviceIntPtr device, 1117706f2543Smrg int is_absolute, 1118706f2543Smrg int button, 1119706f2543Smrg int is_down, 1120706f2543Smrg int first_valuator, 1121706f2543Smrg int num_valuators, 1122706f2543Smrg ...) 1123706f2543Smrg{ 1124706f2543Smrg va_list var; 1125706f2543Smrg ValuatorMask mask; 1126706f2543Smrg int i = 0; 1127706f2543Smrg 1128706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1129706f2543Smrg 1130706f2543Smrg valuator_mask_zero(&mask); 1131706f2543Smrg 1132706f2543Smrg va_start(var, num_valuators); 1133706f2543Smrg for (i = 0; i < num_valuators; i++) 1134706f2543Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1135706f2543Smrg va_end(var); 1136706f2543Smrg 1137706f2543Smrg xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1138706f2543Smrg} 1139706f2543Smrg 1140706f2543Smrgvoid 1141706f2543Smrgxf86PostButtonEventP(DeviceIntPtr device, 1142706f2543Smrg int is_absolute, 1143706f2543Smrg int button, 1144706f2543Smrg int is_down, 1145706f2543Smrg int first_valuator, 1146706f2543Smrg int num_valuators, 1147706f2543Smrg const int *valuators) 1148706f2543Smrg{ 1149706f2543Smrg ValuatorMask mask; 1150706f2543Smrg 1151706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1152706f2543Smrg 1153706f2543Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1154706f2543Smrg xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); 1155706f2543Smrg} 1156706f2543Smrg 1157706f2543Smrgvoid 1158706f2543Smrgxf86PostButtonEventM(DeviceIntPtr device, 1159706f2543Smrg int is_absolute, 1160706f2543Smrg int button, 1161706f2543Smrg int is_down, 1162706f2543Smrg const ValuatorMask *mask) 1163706f2543Smrg{ 1164706f2543Smrg int i = 0, nevents = 0; 1165706f2543Smrg int flags = 0; 1166706f2543Smrg 1167706f2543Smrg if (valuator_mask_num_valuators(mask) > 0) 1168706f2543Smrg { 1169706f2543Smrg if (is_absolute) 1170706f2543Smrg flags = POINTER_ABSOLUTE; 1171706f2543Smrg else 1172706f2543Smrg flags = POINTER_RELATIVE | POINTER_ACCELERATE; 1173706f2543Smrg } 1174706f2543Smrg 1175706f2543Smrg#if XFreeXDGA 1176706f2543Smrg if (miPointerGetScreen(device)) { 1177706f2543Smrg int index = miPointerGetScreen(device)->myNum; 1178706f2543Smrg 1179706f2543Smrg if (DGAStealButtonEvent(device, index, button, is_down)) 1180706f2543Smrg return; 1181706f2543Smrg } 1182706f2543Smrg#endif 1183706f2543Smrg 1184706f2543Smrg nevents = GetPointerEvents(xf86Events, device, 1185706f2543Smrg is_down ? ButtonPress : ButtonRelease, button, 1186706f2543Smrg flags, mask); 1187706f2543Smrg 1188706f2543Smrg for (i = 0; i < nevents; i++) 1189706f2543Smrg mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1190706f2543Smrg 1191706f2543Smrg} 1192706f2543Smrg 1193706f2543Smrgvoid 1194706f2543Smrgxf86PostKeyEvent(DeviceIntPtr device, 1195706f2543Smrg unsigned int key_code, 1196706f2543Smrg int is_down, 1197706f2543Smrg int is_absolute, 1198706f2543Smrg int first_valuator, 1199706f2543Smrg int num_valuators, 1200706f2543Smrg ...) 1201706f2543Smrg{ 1202706f2543Smrg va_list var; 1203706f2543Smrg int i = 0; 1204706f2543Smrg ValuatorMask mask; 1205706f2543Smrg 1206706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1207706f2543Smrg 1208706f2543Smrg valuator_mask_zero(&mask); 1209706f2543Smrg 1210706f2543Smrg va_start(var, num_valuators); 1211706f2543Smrg for (i = 0; i < num_valuators; i++) 1212706f2543Smrg valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); 1213706f2543Smrg va_end(var); 1214706f2543Smrg 1215706f2543Smrg xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); 1216706f2543Smrg} 1217706f2543Smrg 1218706f2543Smrgvoid 1219706f2543Smrgxf86PostKeyEventP(DeviceIntPtr device, 1220706f2543Smrg unsigned int key_code, 1221706f2543Smrg int is_down, 1222706f2543Smrg int is_absolute, 1223706f2543Smrg int first_valuator, 1224706f2543Smrg int num_valuators, 1225706f2543Smrg const int *valuators) 1226706f2543Smrg{ 1227706f2543Smrg ValuatorMask mask; 1228706f2543Smrg 1229706f2543Smrg XI_VERIFY_VALUATORS(num_valuators); 1230706f2543Smrg 1231706f2543Smrg valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); 1232706f2543Smrg xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); 1233706f2543Smrg} 1234706f2543Smrg 1235706f2543Smrgvoid 1236706f2543Smrgxf86PostKeyEventM(DeviceIntPtr device, 1237706f2543Smrg unsigned int key_code, 1238706f2543Smrg int is_down, 1239706f2543Smrg int is_absolute, 1240706f2543Smrg const ValuatorMask *mask) 1241706f2543Smrg{ 1242706f2543Smrg int i = 0, nevents = 0; 1243706f2543Smrg 1244706f2543Smrg#if XFreeXDGA 1245706f2543Smrg DeviceIntPtr pointer; 1246706f2543Smrg 1247706f2543Smrg /* Some pointers send key events, paired device is wrong then. */ 1248706f2543Smrg pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); 1249706f2543Smrg if (miPointerGetScreen(pointer)) { 1250706f2543Smrg int index = miPointerGetScreen(pointer)->myNum; 1251706f2543Smrg 1252706f2543Smrg if (DGAStealKeyEvent(device, index, key_code, is_down)) 1253706f2543Smrg return; 1254706f2543Smrg } 1255706f2543Smrg#endif 1256706f2543Smrg 1257706f2543Smrg if (is_absolute) { 1258706f2543Smrg nevents = GetKeyboardValuatorEvents(xf86Events, device, 1259706f2543Smrg is_down ? KeyPress : KeyRelease, 1260706f2543Smrg key_code, mask); 1261706f2543Smrg } 1262706f2543Smrg else { 1263706f2543Smrg nevents = GetKeyboardEvents(xf86Events, device, 1264706f2543Smrg is_down ? KeyPress : KeyRelease, 1265706f2543Smrg key_code); 1266706f2543Smrg } 1267706f2543Smrg 1268706f2543Smrg for (i = 0; i < nevents; i++) 1269706f2543Smrg mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); 1270706f2543Smrg} 1271706f2543Smrg 1272706f2543Smrgvoid 1273706f2543Smrgxf86PostKeyboardEvent(DeviceIntPtr device, 1274706f2543Smrg unsigned int key_code, 1275706f2543Smrg int is_down) 1276706f2543Smrg{ 1277706f2543Smrg ValuatorMask mask; 1278706f2543Smrg 1279706f2543Smrg valuator_mask_zero(&mask); 1280706f2543Smrg xf86PostKeyEventM(device, key_code, is_down, 0, &mask); 1281706f2543Smrg} 1282706f2543Smrg 1283706f2543SmrgInputInfoPtr 1284706f2543Smrgxf86FirstLocalDevice(void) 1285706f2543Smrg{ 1286706f2543Smrg return xf86InputDevs; 1287706f2543Smrg} 1288706f2543Smrg 1289706f2543Smrg/* 1290706f2543Smrg * Cx - raw data from touch screen 1291706f2543Smrg * to_max - scaled highest dimension 1292706f2543Smrg * (remember, this is of rows - 1 because of 0 origin) 1293706f2543Smrg * to_min - scaled lowest dimension 1294706f2543Smrg * from_max - highest raw value from touch screen calibration 1295706f2543Smrg * from_min - lowest raw value from touch screen calibration 1296706f2543Smrg * 1297706f2543Smrg * This function is the same for X or Y coordinates. 1298706f2543Smrg * You may have to reverse the high and low values to compensate for 1299706f2543Smrg * different orgins on the touch screen vs X. 1300706f2543Smrg * 1301706f2543Smrg * e.g. to scale from device coordinates into screen coordinates, call 1302706f2543Smrg * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); 1303706f2543Smrg */ 1304706f2543Smrg 1305706f2543Smrgint 1306706f2543Smrgxf86ScaleAxis(int Cx, 1307706f2543Smrg int to_max, 1308706f2543Smrg int to_min, 1309706f2543Smrg int from_max, 1310706f2543Smrg int from_min ) 1311706f2543Smrg{ 1312706f2543Smrg int X; 1313706f2543Smrg int64_t to_width = to_max - to_min; 1314706f2543Smrg int64_t from_width = from_max - from_min; 1315706f2543Smrg 1316706f2543Smrg if (from_width) { 1317706f2543Smrg X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); 1318706f2543Smrg } 1319706f2543Smrg else { 1320706f2543Smrg X = 0; 1321706f2543Smrg ErrorF ("Divide by Zero in xf86ScaleAxis\n"); 1322706f2543Smrg } 1323706f2543Smrg 1324706f2543Smrg if (X > to_max) 1325706f2543Smrg X = to_max; 1326706f2543Smrg if (X < to_min) 1327706f2543Smrg X = to_min; 1328706f2543Smrg 1329706f2543Smrg return X; 1330706f2543Smrg} 1331706f2543Smrg 1332706f2543Smrg/* 1333706f2543Smrg * This function checks the given screen against the current screen and 1334706f2543Smrg * makes changes if appropriate. It should be called from an XInput driver's 1335706f2543Smrg * ReadInput function before any events are posted, if the device is screen 1336706f2543Smrg * specific like a touch screen. 1337706f2543Smrg */ 1338706f2543Smrgvoid 1339706f2543Smrgxf86XInputSetScreen(InputInfoPtr pInfo, 1340706f2543Smrg int screen_number, 1341706f2543Smrg int x, 1342706f2543Smrg int y) 1343706f2543Smrg{ 1344706f2543Smrg if (miPointerGetScreen(pInfo->dev) != 1345706f2543Smrg screenInfo.screens[screen_number]) { 1346706f2543Smrg miPointerSetScreen(pInfo->dev, screen_number, x, y); 1347706f2543Smrg } 1348706f2543Smrg} 1349706f2543Smrg 1350706f2543Smrg 1351706f2543Smrgvoid 1352706f2543Smrgxf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, 1353706f2543Smrg int resolution, int min_res, int max_res, int mode) 1354706f2543Smrg{ 1355706f2543Smrg if (!dev || !dev->valuator) 1356706f2543Smrg return; 1357706f2543Smrg 1358706f2543Smrg InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, 1359706f2543Smrg max_res, mode); 1360706f2543Smrg} 1361706f2543Smrg 1362706f2543Smrg/* 1363706f2543Smrg * Set the valuator values to be in synch with dix/event.c 1364706f2543Smrg * DefineInitialRootWindow(). 1365706f2543Smrg */ 1366706f2543Smrgvoid 1367706f2543Smrgxf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) 1368706f2543Smrg{ 1369706f2543Smrg if (axnum == 0) { 1370706f2543Smrg dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; 1371706f2543Smrg dev->last.valuators[0] = dev->valuator->axisVal[0]; 1372706f2543Smrg } 1373706f2543Smrg else if (axnum == 1) { 1374706f2543Smrg dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; 1375706f2543Smrg dev->last.valuators[1] = dev->valuator->axisVal[1]; 1376706f2543Smrg } 1377706f2543Smrg} 1378706f2543Smrg 1379706f2543Smrg 1380706f2543Smrg/** 1381706f2543Smrg * Deactivate a device. Call this function from the driver if you receive a 1382706f2543Smrg * read error or something else that spoils your day. 1383706f2543Smrg * Device will be moved to the off_devices list, but it will still be there 1384706f2543Smrg * until you really clean up after it. 1385706f2543Smrg * Notifies the client about an inactive device. 1386706f2543Smrg * 1387706f2543Smrg * @param panic True if device is unrecoverable and needs to be removed. 1388706f2543Smrg */ 1389706f2543Smrgvoid 1390706f2543Smrgxf86DisableDevice(DeviceIntPtr dev, Bool panic) 1391706f2543Smrg{ 1392706f2543Smrg if(!panic) 1393706f2543Smrg { 1394706f2543Smrg DisableDevice(dev, TRUE); 1395706f2543Smrg } else 1396706f2543Smrg { 1397706f2543Smrg SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); 1398706f2543Smrg DeleteInputDeviceRequest(dev); 1399706f2543Smrg } 1400706f2543Smrg} 1401706f2543Smrg 1402706f2543Smrg/** 1403706f2543Smrg * Reactivate a device. Call this function from the driver if you just found 1404706f2543Smrg * out that the read error wasn't quite that bad after all. 1405706f2543Smrg * Device will be re-activated, and an event sent to the client. 1406706f2543Smrg */ 1407706f2543Smrgvoid 1408706f2543Smrgxf86EnableDevice(DeviceIntPtr dev) 1409706f2543Smrg{ 1410706f2543Smrg EnableDevice(dev, TRUE); 1411706f2543Smrg} 1412706f2543Smrg 1413706f2543Smrg/* end of xf86Xinput.c */ 1414