Compare commits

..

9 Commits

Author SHA1 Message Date
Peter Hutterer
f7850a4042 evdev 2.3.2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-12-11 13:42:33 +10:00
Peter Hutterer
bd4102af6e Fix up BTN_TOUCH handling for non-button tablets.
BTN_TOOL_* is treated as tool, just like before. BTN_TOUCH on the other hand
may need to be treated as a button left press. This again requires a button
class.

Tested on an HP Touchsmart and a Wacom tablet.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 1b0df04abe)
2009-12-03 09:27:32 +10:00
Peter Hutterer
22e816eb32 Only init the calibration property for absolute devices.
Relative devices can't be calibrated anyway so why bother.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 2ca24a16f0)
2009-12-03 09:27:31 +10:00
David Woodhouse
b6b377fe9a Report initial calibration parameters.
Where an initial calibration is provided through the Calibration option
to the driver, it wasn't being exposed in the 'Evdev Axis Calibration'
property. Remedy that...

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 7b285a802b)
2009-12-03 09:27:28 +10:00
David Woodhouse
3772676fd6 Swap axes before applying touch screen calibration.
When the SwapAxes option is set, the X and Y axes in calibration should
be labelled as the user perceives them -- not as the kernel sends them.

Currently, we apply the X-axis calibration to the X-axis of the input,
and then do the axis swapping so we've actually applied the X-axis
calibration to what the user sees as the Y-axis.

This patch changes the order of the operations, so that the axes are
swapped before the calibration is applied.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit f187badb71)
2009-12-03 09:27:25 +10:00
Peter Hutterer
4f05afd495 evdev 2.3.1
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2009-11-20 11:18:03 +10:00
Bartosz Brachaczek
c6964dd28a Set all valuators for relative motion events (#24737)
We should process all the deltas reported by a relative motion device,
otherwise some devices such as A4Tech X-750F or similar may trigger a
situation when the `v` array contains random values (it isn't
initialized anywhere) and later we process them and in effect the mouse
cursor "jumps" on the screen.
I'm not sure why, but we also must be sure that the `first` and `last`
variables reflect the axis map, otherwise the mouse cursor "jumps" on
the screen when clicking mouse buttons in some rare cases reported by
Bartek Iwaniec on Bugzilla. That's why a simple initialization of the
`v` array with zeros isn't sufficient.

X.Org Bug 24737 <http://bugs.freedesktop.org/show_bug.cgi?id=24737>

Signed-off-by: Bartosz Brachaczek <b.brachaczek@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit c1f16a4f59)
2009-11-20 11:17:44 +10:00
Dmitry Torokhov
175af93bdb Relax checks when reopening devices
When checking whether we are dealing with the same device as before
when we try to reopen it evdev should not require exact match of
entire keymap. Users should be allowed to adjust keymaps to better
match their hardware even after X starts. However we don't expect
changes in [BTN_MISC, KEY_OK) range since these codes are reserved for
mice, joysticks, tablets and so forth, so we will limit the check to
this range.

The same goes for absinfo - limits can change and it should not result
in device being disabled.

Also check the length of the data returned by ioctl and don't try to
compare more than we were given.

[peter: moved the key comparison below the led+abs comparison]

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit a0f7f34dc5)
2009-11-20 11:17:42 +10:00
Peter Hutterer
7c3c7f83d0 Fix drag-lock property handler for multiple draglock buttons.
Parsing of the values was wrong. Given an input of 1 2 3 4, button 1 sets
the lock for button 2 and button 3 sets the lock for button 4.

This also means we need to return BadMatch if the property isn't a multiple
of 2.

Red Hat Bug 524428 <https://bugzilla.redhat.com/show_bug.cgi?id=524428>

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 11669d8279)
2009-11-20 11:17:41 +10:00
14 changed files with 492 additions and 474 deletions

76
.gitignore vendored
View File

@@ -1,78 +1,28 @@
# *.patch
# X.Org module default exclusion patterns
# The next section if for module specific patterns
#
# Do not edit the following section
# GNU Build System (Autotools)
aclocal.m4
autom4te.cache/
autoscan.log
ChangeLog ChangeLog
compile Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.guess config.guess
config.h config.h
config.h.in config.h.in
config.log config.log
config-ml.in
config.py
config.status config.status
config.status.lineno
config.sub config.sub
configure configure
configure.scan
depcomp depcomp
.deps/
INSTALL
install-sh install-sh
.libs/
libtool libtool
libtool.m4
ltmain.sh ltmain.sh
lt~obsolete.m4 man/evdev.4
ltoptions.m4
ltsugar.m4
ltversion.m4
Makefile
Makefile.in
mdate-sh
missing missing
mkinstalldirs .deps
.libs
*.lo
*.la
stamp-h1
xf86-input-evdev-*.tar.*
*.pc *.pc
py-compile
stamp-h?
symlink-tree
texinfo.tex
ylwrap
# Do not edit the following section
# Edit Compile Debug Document Distribute
*~ *~
*.[0-9] tags
*.[0-9]x
*.bak
*.bin
core
*.dll
*.exe
*-ISO*.bdf
*-JIS*.bdf
*-KOI8*.bdf
*.kld
*.ko
*.ko.cmd
*.lai
*.l[oa]
*.[oa]
*.obj
*.patch
*.so
*.pcf.gz
*.pdb
*.tar.bz2
*.tar.gz
#
# Add & Override patterns for xf86-input-evdev
#
# Edit the following section as needed
# For example, !report.pc overrides *.pc. See 'man gitignore'
#

72
COPYING
View File

@@ -1,11 +1,57 @@
Various copyright notices found in this driver:
Copyright © 2004-2008 Red Hat, Inc.
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without
fee, provided that the above copyright notice appear in all copies
and that both that copyright notice and this permission notice
appear in supporting documentation, and that the name of Red Hat
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission. Red
Hat makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied
warranty.
THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright 2005 Sun Microsystems, Inc. All rights reserved.
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the copyright holders shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the copyright holders.
Copyright © 2008 University of South Australia
copyrights taken from xf86-input-mouse, partly valid for this driver.
Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
Copyright 1993 by David Dawes <dawes@xfree86.org> Copyright 1993 by David Dawes <dawes@xfree86.org>
Copyright 2002 by SuSE Linux AG, Author: Egbert Eich Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
Copyright 1994-2002 by The XFree86 Project, Inc. Copyright 1994-2002 by The XFree86 Project, Inc.
Copyright 2002 by Paul Elliott Copyright 2002 by Paul Elliott
Copyright © 2008 University of South Australia
Copyright 2008 by Chris Salch
Copyright © 2008 Red Hat, Inc.
Permission to use, copy, modify, distribute, and sell this software Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without and its documentation for any purpose is hereby granted without
@@ -26,26 +72,6 @@ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright 2005 Sun Microsystems, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Copyright 2005 Adam Jackson. Copyright 2005 Adam Jackson.

View File

@@ -18,23 +18,23 @@
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = foreign
# Provide an sdk location that is writable by the evdev module # Ensure headers are installed below $(prefix) for distcheck
DISTCHECK_CONFIGURE_FLAGS = --with-sdkdir='$${includedir}/xorg' DISTCHECK_CONFIGURE_FLAGS = --with-sdkdir='$${includedir}/xorg'
SUBDIRS = src man include SUBDIRS = src man include
MAINTAINERCLEANFILES = ChangeLog INSTALL
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = xorg-evdev.pc pkgconfig_DATA = xorg-evdev.pc
EXTRA_DIST = ChangeLog
.PHONY: ChangeLog INSTALL MAINTAINERCLEANFILES=ChangeLog
INSTALL: .PHONY: ChangeLog
$(INSTALL_CMD)
ChangeLog: ChangeLog:
$(CHANGELOG_CMD) $(CHANGELOG_CMD)
dist-hook: ChangeLog INSTALL dist-hook: ChangeLog

View File

@@ -20,34 +20,31 @@
# #
# Process this file with autoconf to produce a configure script # Process this file with autoconf to produce a configure script
# Initialize Autoconf AC_PREREQ(2.57)
AC_PREREQ([2.60])
AC_INIT([xf86-input-evdev], AC_INIT([xf86-input-evdev],
[2.5.0], 2.3.2,
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
[xf86-input-evdev]) xf86-input-evdev)
AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR(.) AC_CONFIG_AUX_DIR(.)
AM_INIT_AUTOMAKE([dist-bzip2])
# Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
# Initialize libtool # Require xorg-macros: XORG_DEFAULT_OPTIONS
m4_ifndef([XORG_MACROS_VERSION], [AC_FATAL([must install xorg-macros 1.3 or later before running autoconf/autogen])])
XORG_MACROS_VERSION(1.3)
AM_CONFIG_HEADER([config.h])
# Checks for programs.
AC_DISABLE_STATIC AC_DISABLE_STATIC
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
AC_PROG_CC
# Initialize X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS
m4_ifndef([XORG_MACROS_VERSION],
[m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])])
XORG_MACROS_VERSION(1.8)
XORG_DEFAULT_OPTIONS XORG_DEFAULT_OPTIONS
# Obtain compiler/linker options from server and required extensions AH_TOP([#include "xorg-server.h"])
PKG_CHECK_MODULES(XORG, xorg-server xproto inputproto)
# Define a configure option for an alternate input module directory
AC_ARG_WITH(xorg-module-dir, AC_ARG_WITH(xorg-module-dir,
AC_HELP_STRING([--with-xorg-module-dir=DIR], AC_HELP_STRING([--with-xorg-module-dir=DIR],
[Default xorg module directory [[default=$libdir/xorg/modules]]]), [Default xorg module directory [[default=$libdir/xorg/modules]]]),
@@ -56,21 +53,25 @@ AC_ARG_WITH(xorg-module-dir,
inputdir=${moduledir}/input inputdir=${moduledir}/input
AC_SUBST(inputdir) AC_SUBST(inputdir)
# X Server SDK location is required to install evdev header files # Checks for pkg-config packages. We need to be able to override sdkdir
# This location is also relayed in the xorg-evdev.pc file # to satisfy silly distcheck requirements.
sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server` PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
XORG_CFLAGS="$CWARNFLAGS $XORG_CFLAGS"
# Workaround overriding sdkdir to be able to create a tarball when user has no AC_ARG_WITH([sdkdir], [],
# write permission in sdkdir. See DISTCHECK_CONFIGURE_FLAGS in Makefile.am [sdkdir="$withval"],
AC_ARG_WITH([sdkdir], [], [sdkdir="$withval"]) [sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server`])
AC_SUBST([sdkdir]) AC_SUBST([sdkdir])
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
DRIVER_NAME=evdev DRIVER_NAME=evdev
AC_SUBST([DRIVER_NAME]) AC_SUBST([DRIVER_NAME])
AC_CONFIG_FILES([Makefile AC_OUTPUT([Makefile
src/Makefile src/Makefile
man/Makefile man/Makefile
include/Makefile include/Makefile
xorg-evdev.pc]) xorg-evdev.pc])
AC_OUTPUT

View File

@@ -1 +1,2 @@
EXTRA_DIST = evdev-properties.h
sdk_HEADERS = evdev-properties.h sdk_HEADERS = evdev-properties.h

View File

@@ -56,7 +56,7 @@
/* Reopen attempts. */ /* Reopen attempts. */
/* CARD8 */ /* CARD8 */
#define EVDEV_PROP_REOPEN "Evdev Reopen Attempts" /* OBSOLETE */ #define EVDEV_PROP_REOPEN "Evdev Reopen Attempts"
/* Run-time calibration */ /* Run-time calibration */
/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */ /* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */

View File

@@ -1,37 +1,57 @@
# Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# #
# Permission is hereby granted, free of charge, to any person obtaining a # Permission to use, copy, modify, distribute, and sell this software and its
# copy of this software and associated documentation files (the "Software"), # documentation for any purpose is hereby granted without fee, provided that
# to deal in the Software without restriction, including without limitation # the above copyright notice appear in all copies and that both that
# the rights to use, copy, modify, merge, publish, distribute, sublicense, # copyright notice and this permission notice appear in supporting
# and/or sell copies of the Software, and to permit persons to whom the # documentation.
# Software is furnished to do so, subject to the following conditions: #
# # The above copyright notice and this permission notice shall be included
# The above copyright notice and this permission notice (including the next # in all copies or substantial portions of the Software.
# paragraph) shall be included in all copies or substantial portions of the #
# Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # OTHER DEALINGS IN THE SOFTWARE.
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #
# DEALINGS IN THE SOFTWARE. # Except as contained in this notice, the name of the copyright holders shall
# not be used in advertising or otherwise to promote the sale, use or
# other dealings in this Software without prior written authorization
# from the copyright holders.
# #
drivermandir = $(DRIVER_MAN_DIR) drivermandir = $(DRIVER_MAN_DIR)
driverman_PRE = $(DRIVER_NAME).man driverman_PRE = @DRIVER_NAME@.man
driverman_DATA = $(driverman_PRE:man=$(DRIVER_MAN_SUFFIX)) driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
EXTRA_DIST = $(DRIVER_NAME).man EXTRA_DIST = @DRIVER_NAME@.man
CLEANFILES = $(driverman_DATA) CLEANFILES = $(driverman_DATA)
SED = sed
# Strings to replace in man pages
XORGRELSTRING = @PACKAGE_STRING@
XORGMANNAME = X Version 11
MAN_SUBSTS = \
-e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
-e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
-e 's|__xservername__|Xorg|g' \
-e 's|__xconfigfile__|xorg.conf|g' \
-e 's|__projectroot__|$(prefix)|g' \
-e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \
-e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
-e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
-e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \
-e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g'
SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
.man.$(DRIVER_MAN_SUFFIX): .man.$(DRIVER_MAN_SUFFIX):
$(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@ sed $(MAN_SUBSTS) < $< > $@

View File

@@ -19,24 +19,15 @@ evdev \- Generic Linux input driver
.B evdev .B evdev
is an __xservername__ input driver for Linux\'s generic event devices. It is an __xservername__ input driver for Linux\'s generic event devices. It
therefore supports all input devices that the kernel knows about, including therefore supports all input devices that the kernel knows about, including
most mice, keyboards, tablets and touchscreens. most mice and keyboards.
.B evdev
is the default driver on the major Linux distributions.
.PP .PP
The The
.B evdev .B evdev
driver can serve as both a pointer and a keyboard input device. Multiple driver can serve as both a pointer and a keyboard input device, and may be
input devices are supported by multiple instances of this driver, with one used as both the core keyboard and the core pointer. Multiple input devices
InputDevice section of your __xconfigfile__ for each input device that will are supported by multiple instances of this driver, with one Load
use this driver. directive for evdev in the Module section of your __xconfigfile__ for each
.PP input device that will use this driver.
It is recommended that
.B evdev
devices are configured through the
.B InputClass
directive (refer to __xconfigfile__(__filemansuffix__)) instead of manual
per-device configuration. Devices configured in the
__xconfigfile__(__filemansuffix__) are not hot-plug capable.
.PP .PP
.SH SUPPORTED HARDWARE .SH SUPPORTED HARDWARE
In general, any input device that the kernel has a driver for can be accessed In general, any input device that the kernel has a driver for can be accessed
@@ -85,14 +76,13 @@ indicating that the next button pressed is to be
.BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q .BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
Enable/disable the emulation of the third (middle) mouse button for mice Enable/disable the emulation of the third (middle) mouse button for mice
which only have two physical buttons. The third button is emulated by which only have two physical buttons. The third button is emulated by
pressing both buttons simultaneously. Default: off. Property: "Evdev Middle pressing both buttons simultaneously. Default: on, until a middle mouse
Button Emulation". button event is registered. Property: "Evdev Middle Button Emulation".
.TP 7 .TP 7
.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q .BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
Sets the timeout (in milliseconds) that the driver waits before deciding Sets the timeout (in milliseconds) that the driver waits before deciding
if two buttons where pressed "simultaneously" when 3 button emulation is if two buttons where pressed "simultaneously" when 3 button emulation is
enabled. Default: 50. Property: "Evdev Middle Button Timeout". enabled. Default: 50. Property: "Evdev Middle Button Timeout".
.TP 7
.BI "Option \*qEmulateWheel\*q \*q" boolean \*q .BI "Option \*qEmulateWheel\*q \*q" boolean \*q
Enable/disable "wheel" emulation. Wheel emulation means emulating button Enable/disable "wheel" emulation. Wheel emulation means emulating button
press/release events when the mouse is moved while a specific real button press/release events when the mouse is moved while a specific real button
@@ -161,6 +151,10 @@ axes regardless of the presence of other axes. This may trigger buggy
behavior and events from this axis are always forwarded. Users are behavior and events from this axis are always forwarded. Users are
discouraged from setting this option. discouraged from setting this option.
.TP 7 .TP 7
.BI "Option \*qReopenAttempts\*q \*q" integer \*q
Number of reopen attempts after a read error occurs on the device (e.g. after
waking up from suspend). In between each attempt is a 100ms wait. Default: 10.
.TP 7
.BI "Option \*qCalibration\*q \*q" "min-x max-x min-y max-y" \*q .BI "Option \*qCalibration\*q \*q" "min-x max-x min-y max-y" \*q
Calibrates the X and Y axes for devices that need to scale to a different Calibrates the X and Y axes for devices that need to scale to a different
coordinate system than reported to the X server. This feature is required coordinate system than reported to the X server. This feature is required
@@ -169,11 +163,6 @@ originally reported by the kernel (e.g. touchscreens). The scaling to the
custom coordinate system is done in-driver and the X server is unaware of custom coordinate system is done in-driver and the X server is unaware of
the transformation. Property: "Evdev Axis Calibration". the transformation. Property: "Evdev Axis Calibration".
.TP 7 .TP 7
.B Option \*qMode\*q \*qRelative\*q\fP|\fP\*qAbsolute\*q
Sets the mode of the device if device has absolute axes.
The default value for touchpads is relative, for other absolute.
This option has no effect on devices without absolute axes.
.TP 7
.BI "Option \*qSwapAxes\*q \*q" Bool \*q .BI "Option \*qSwapAxes\*q \*q" Bool \*q
Swap x/y axes. Default: off. Property: "Evdev Axes Swap". Swap x/y axes. Default: off. Property: "Evdev Axes Swap".
.TP 7 .TP 7
@@ -236,6 +225,7 @@ value.
1 16-bit positive value. 1 16-bit positive value.
.SH AUTHORS .SH AUTHORS
Kristian Høgsberg, Peter Hutterer Kristian Høgsberg.
.SH "SEE ALSO" .SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__),
README.mouse.

View File

@@ -24,14 +24,14 @@
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
# _ladir passes a dummy rpath to libtool so the thing will actually link # _ladir passes a dummy rpath to libtool so the thing will actually link
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = $(XORG_CFLAGS)
AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS)
AM_CPPFLAGS =-I$(top_srcdir)/include
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
@DRIVER_NAME@_drv_ladir = @inputdir@ @DRIVER_NAME@_drv_ladir = @inputdir@
INCLUDES=-I$(top_srcdir)/include/
@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
@DRIVER_NAME@.h \ @DRIVER_NAME@.h \
emuMB.c \ emuMB.c \

View File

@@ -35,7 +35,6 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "evdev.h"
#include <xf86.h> #include <xf86.h>
#include <xf86Xinput.h> #include <xf86Xinput.h>
@@ -43,6 +42,7 @@
#include <exevents.h> #include <exevents.h>
#include <evdev-properties.h> #include <evdev-properties.h>
#include "evdev.h"
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
static Atom prop_dlock = 0; /* Drag lock buttons. */ static Atom prop_dlock = 0; /* Drag lock buttons. */
@@ -145,8 +145,6 @@ EvdevDragLockPreInit(InputInfoPtr pInfo)
if (next_num != NULL && *next_num == '\0') if (next_num != NULL && *next_num == '\0')
next_num = NULL; next_num = NULL;
} }
free(option_string);
} }
/* Updates DragLock button state and fires button event messges */ /* Updates DragLock button state and fires button event messges */

View File

@@ -34,14 +34,19 @@
#include "config.h" #include "config.h"
#endif #endif
#include "evdev.h"
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <xf86.h> #include <xf86.h>
#include <xf86Xinput.h> #include <xf86Xinput.h>
#include <exevents.h> #include <exevents.h>
#include <evdev-properties.h> #include <evdev-properties.h>
#include "evdev.h"
enum {
MBEMU_DISABLED = 0,
MBEMU_ENABLED,
MBEMU_AUTO
};
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
static Atom prop_mbemu = 0; /* Middle button emulation on/off property */ static Atom prop_mbemu = 0; /* Middle button emulation on/off property */
@@ -226,6 +231,11 @@ EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int button, BOOL press)
if (!pEvdev->emulateMB.enabled) if (!pEvdev->emulateMB.enabled)
return ret; return ret;
if (button == 2) {
EvdevMBEmuEnable(pInfo, FALSE);
return ret;
}
/* don't care about other buttons */ /* don't care about other buttons */
if (button != 1 && button != 3) if (button != 1 && button != 3)
return ret; return ret;
@@ -299,10 +309,17 @@ void
EvdevMBEmuPreInit(InputInfoPtr pInfo) EvdevMBEmuPreInit(InputInfoPtr pInfo)
{ {
EvdevPtr pEvdev = (EvdevPtr)pInfo->private; EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
pEvdev->emulateMB.enabled = MBEMU_AUTO;
if (xf86FindOption(pInfo->options, "Emulate3Buttons"))
{
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
"Emulate3Buttons",
MBEMU_ENABLED);
xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation %s.\n",
pInfo->name, (pEvdev->emulateMB.enabled) ? "on" : "off");
}
pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
"Emulate3Buttons",
FALSE);
pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options, pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
"Emulate3Timeout", 50); "Emulate3Timeout", 50);
} }
@@ -330,6 +347,16 @@ EvdevMBEmuFinalize(InputInfoPtr pInfo)
} }
/* Enable/disable middle mouse button emulation. */
void
EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
if (pEvdev->emulateMB.enabled == MBEMU_AUTO)
pEvdev->emulateMB.enabled = enable;
}
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
static int static int
EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,

View File

@@ -33,7 +33,6 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "evdev.h"
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <xf86.h> #include <xf86.h>
@@ -41,6 +40,7 @@
#include <exevents.h> #include <exevents.h>
#include <evdev-properties.h> #include <evdev-properties.h>
#include "evdev.h"
#define WHEEL_NOT_CONFIGURED 0 #define WHEEL_NOT_CONFIGURED 0
@@ -100,7 +100,6 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
EvdevPtr pEvdev = (EvdevPtr)pInfo->private; EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
WheelAxisPtr pAxis = NULL, pOtherAxis = NULL; WheelAxisPtr pAxis = NULL, pOtherAxis = NULL;
int value = pEv->value; int value = pEv->value;
int oldValue;
/* Has wheel emulation been configured to be enabled? */ /* Has wheel emulation been configured to be enabled? */
if (!pEvdev->emulateWheel.enabled) if (!pEvdev->emulateWheel.enabled)
@@ -119,21 +118,12 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
} }
/* We don't want to intercept real mouse wheel events */ /* We don't want to intercept real mouse wheel events */
if(pEv->type == EV_ABS) {
oldValue = pEvdev->vals[pEvdev->axis_map[pEv->code]];
pEvdev->vals[pEvdev->axis_map[pEv->code]] = value;
value -= oldValue; /* make value into a differential measurement */
}
switch(pEv->code) { switch(pEv->code) {
/* ABS_X has the same value as REL_X, so this case catches both */
case REL_X: case REL_X:
pAxis = &(pEvdev->emulateWheel.X); pAxis = &(pEvdev->emulateWheel.X);
pOtherAxis = &(pEvdev->emulateWheel.Y); pOtherAxis = &(pEvdev->emulateWheel.Y);
break; break;
/* ABS_Y has the same value as REL_Y, so this case catches both */
case REL_Y: case REL_Y:
pAxis = &(pEvdev->emulateWheel.Y); pAxis = &(pEvdev->emulateWheel.Y);
pOtherAxis = &(pEvdev->emulateWheel.X); pOtherAxis = &(pEvdev->emulateWheel.X);
@@ -143,11 +133,11 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
break; break;
} }
/* If we found REL_X, REL_Y, ABS_X or ABS_Y then emulate a mouse /* If we found REL_X or REL_Y, emulate a mouse wheel.
wheel. Reset the inertia of the other axis when a scroll event Reset the inertia of the other axis when a scroll event was sent
was sent to avoid the buildup of erroneous scroll events if the to avoid the buildup of erroneous scroll events if the user
user doesn't move in a perfectly straight line. doesn't move in a perfectly straight line.
*/ */
if (pAxis) if (pAxis)
{ {
if (EvdevWheelEmuInertia(pInfo, pAxis, value)) if (EvdevWheelEmuInertia(pInfo, pAxis, value))
@@ -232,13 +222,13 @@ EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char* axis_
} else { } else {
xf86Msg(X_WARNING, "%s: Invalid %s value:\"%s\"\n", xf86Msg(X_WARNING, "%s: Invalid %s value:\"%s\"\n",
pInfo->name, axis_name, option_string); pInfo->name, axis_name, option_string);
} }
free(option_string);
/* Clean up and log what happened */ /* Clean up and log what happened */
if (msg) { if (msg) {
xf86Msg(X_CONFIG, "%s: %s: %s\n",pInfo->name, axis_name, msg); xf86Msg(X_CONFIG, "%s: %s: %s\n",pInfo->name, axis_name, msg);
free(msg); xfree(msg);
return TRUE; return TRUE;
} }
} }

View File

@@ -31,12 +31,8 @@
#include "config.h" #include "config.h"
#endif #endif
#include "evdev.h"
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/extensions/XI.h>
#include <linux/version.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@@ -48,6 +44,8 @@
#include <xorgVersion.h> #include <xorgVersion.h>
#include <xkbsrv.h> #include <xkbsrv.h>
#include "evdev.h"
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <evdev-properties.h> #include <evdev-properties.h>
@@ -66,8 +64,35 @@
#define MAXDEVICES MAX_DEVICES #define MAXDEVICES MAX_DEVICES
#endif #endif
/* 2.4 compatibility */
#ifndef EVIOCGRAB
#define EVIOCGRAB _IOW('E', 0x90, int)
#endif
#ifndef BTN_TASK
#define BTN_TASK 0x117
#endif
#ifndef EV_SYN
#define EV_SYN EV_RST
#endif
/* end compat */
#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0]))) #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
/* evdev flags */
#define EVDEV_KEYBOARD_EVENTS (1 << 0)
#define EVDEV_BUTTON_EVENTS (1 << 1)
#define EVDEV_RELATIVE_EVENTS (1 << 2)
#define EVDEV_ABSOLUTE_EVENTS (1 << 3)
#define EVDEV_TOUCHPAD (1 << 4)
#define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
#define EVDEV_TOUCHSCREEN (1 << 6)
#define EVDEV_CALIBRATED (1 << 7) /* run-time calibrated? */
#define EVDEV_TABLET (1 << 8) /* device looks like a tablet? */
#define EVDEV_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
#define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
#define MIN_KEYCODE 8 #define MIN_KEYCODE 8
#define GLYPHS_PER_KEY 2 #define GLYPHS_PER_KEY 2
#define AltMask Mod1Mask #define AltMask Mod1Mask
@@ -92,10 +117,6 @@ static const char *evdevDefaults[] = {
static int EvdevOn(DeviceIntPtr); static int EvdevOn(DeviceIntPtr);
static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare); static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare);
static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl); static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode);
static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
static BOOL EvdevOpenDevice(InputInfoPtr pInfo);
#ifdef HAVE_PROPERTIES #ifdef HAVE_PROPERTIES
static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms); static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
@@ -104,6 +125,7 @@ static void EvdevInitProperty(DeviceIntPtr dev);
static int EvdevSetProperty(DeviceIntPtr dev, Atom atom, static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
XIPropertyValuePtr val, BOOL checkonly); XIPropertyValuePtr val, BOOL checkonly);
static Atom prop_invert = 0; static Atom prop_invert = 0;
static Atom prop_reopen = 0;
static Atom prop_calibration = 0; static Atom prop_calibration = 0;
static Atom prop_swap = 0; static Atom prop_swap = 0;
static Atom prop_axis_label = 0; static Atom prop_axis_label = 0;
@@ -115,38 +137,6 @@ static Atom prop_btn_label = 0;
* cannot be used by evdev, leaving us with a space of 2 at the end. */ * cannot be used by evdev, leaving us with a space of 2 at the end. */
static EvdevPtr evdev_devices[MAXDEVICES] = {NULL}; static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode)
{
InputInfoPtr pInfo;
EvdevPtr pEvdev;
pInfo = device->public.devicePrivate;
pEvdev = pInfo->private;
if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
{
if (mode == Relative)
return Success;
else
return XI_BadMode;
}
switch (mode) {
case Absolute:
pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
break;
case Relative:
pEvdev->flags |= EVDEV_RELATIVE_MODE;
break;
default:
return XI_BadMode;
}
return Success;
}
static size_t CountBits(unsigned long *array, size_t nlongs) static size_t CountBits(unsigned long *array, size_t nlongs)
{ {
unsigned int i; unsigned int i;
@@ -249,7 +239,7 @@ SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
if ((s = xf86SetStrOption(pInfo->options, name, NULL))) { if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
if (!s[0]) { if (!s[0]) {
free(s); xfree(s);
*option = NULL; *option = NULL;
} else { } else {
*option = s; *option = s;
@@ -266,6 +256,7 @@ void
EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
{ {
int code = ev->code + MIN_KEYCODE; int code = ev->code + MIN_KEYCODE;
static char warned[KEY_CNT];
EventQueuePtr pQueue; EventQueuePtr pQueue;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
@@ -283,6 +274,19 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
) )
return; return;
if (code > 255)
{
if (ev->code <= KEY_MAX && !warned[ev->code])
{
xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
pInfo->name, ev->code);
warned[ev->code] = 1;
}
/* The X server can't handle keycodes > 255. */
return;
}
if (pEvdev->num_queue >= EVDEV_MAXQUEUE) if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
{ {
xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name); xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
@@ -336,6 +340,56 @@ EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
} }
} }
/**
* Coming back from resume may leave us with a file descriptor that can be
* opened but fails on the first read (ENODEV).
* In this case, try to open the device until it becomes available or until
* the predefined count expires.
*/
static CARD32
EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
{
InputInfoPtr pInfo = (InputInfoPtr)arg;
EvdevPtr pEvdev = pInfo->private;
do {
pInfo->fd = open(pEvdev->device, O_RDWR | O_NONBLOCK, 0);
} while (pInfo->fd < 0 && errno == EINTR);
if (pInfo->fd != -1)
{
if (EvdevCacheCompare(pInfo, TRUE) == Success)
{
xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
pEvdev->reopen_attempts - pEvdev->reopen_left + 1);
EvdevOn(pInfo->dev);
} else
{
xf86Msg(X_ERROR, "%s: Device has changed - disabling.\n",
pInfo->name);
xf86DisableDevice(pInfo->dev, FALSE);
close(pInfo->fd);
pInfo->fd = -1;
pEvdev->min_maj = 0; /* don't hog the device */
}
pEvdev->reopen_left = 0;
return 0;
}
pEvdev->reopen_left--;
if (!pEvdev->reopen_left)
{
xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
pInfo->name, pEvdev->reopen_attempts);
xf86DisableDevice(pInfo->dev, FALSE);
pEvdev->min_maj = 0; /* don't hog the device */
return 0;
}
return 100; /* come back in 100 ms */
}
#define ABS_X_VALUE 0x1 #define ABS_X_VALUE 0x1
#define ABS_Y_VALUE 0x2 #define ABS_Y_VALUE 0x2
#define ABS_VALUE 0x4 #define ABS_VALUE 0x4
@@ -352,7 +406,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
*num_v = *first_v = 0; *num_v = *first_v = 0;
/* convert to relative motion for touchpads */ /* convert to relative motion for touchpads */
if (pEvdev->abs && (pEvdev->flags & EVDEV_RELATIVE_MODE)) { if (pEvdev->abs && (pEvdev->flags & EVDEV_TOUCHPAD)) {
if (pEvdev->tool) { /* meaning, touch is active */ if (pEvdev->tool) { /* meaning, touch is active */
if (pEvdev->old_vals[0] != -1) if (pEvdev->old_vals[0] != -1)
pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0]; pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
@@ -386,7 +440,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
for (i = 0; i < REL_CNT; i++) for (i = 0; i < REL_CNT; i++)
{ {
int map = pEvdev->axis_map[i]; int map = pEvdev->axis_map[i];
if (pEvdev->delta[i] && map != -1) if (map != -1)
{ {
v[map] = pEvdev->delta[i]; v[map] = pEvdev->delta[i];
if (map < first) if (map < first)
@@ -478,12 +532,14 @@ EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
static void static void
EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
{ {
int value; static int value;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
/* Get the signed value, earlier kernels had this as unsigned */ /* Get the signed value, earlier kernels had this as unsigned */
value = ev->value; value = ev->value;
pEvdev->rel = 1;
switch (ev->code) { switch (ev->code) {
case REL_WHEEL: case REL_WHEEL:
if (value > 0) if (value > 0)
@@ -510,7 +566,6 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
if (EvdevWheelEmuFilterMotion(pInfo, ev)) if (EvdevWheelEmuFilterMotion(pInfo, ev))
return; return;
pEvdev->rel = 1;
pEvdev->delta[ev->code] += value; pEvdev->delta[ev->code] += value;
break; break;
} }
@@ -522,7 +577,7 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
static void static void
EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
{ {
int value; static int value;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
/* Get the signed value, earlier kernels had this as unsigned */ /* Get the signed value, earlier kernels had this as unsigned */
@@ -535,9 +590,6 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
if (ev->code > ABS_MAX) if (ev->code > ABS_MAX)
return; return;
if (EvdevWheelEmuFilterMotion(pInfo, ev))
return;
pEvdev->vals[pEvdev->axis_map[ev->code]] = value; pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
if (ev->code == ABS_X) if (ev->code == ABS_X)
pEvdev->abs |= ABS_X_VALUE; pEvdev->abs |= ABS_X_VALUE;
@@ -553,7 +605,7 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
static void static void
EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
{ {
int value; static int value;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
/* Get the signed value, earlier kernels had this as unsigned */ /* Get the signed value, earlier kernels had this as unsigned */
@@ -577,6 +629,7 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
break; break;
case BTN_TOUCH: case BTN_TOUCH:
pEvdev->tool = value ? ev->code : 0;
if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET))) if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)))
break; break;
/* Treat BTN_TOUCH from devices that only have BTN_TOUCH as /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
@@ -618,9 +671,9 @@ EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
* pressed. On wacom tablets, this means that the pen is in * pressed. On wacom tablets, this means that the pen is in
* proximity of the tablet. After the pen is removed, BTN_DIGI is * proximity of the tablet. After the pen is removed, BTN_DIGI is
* released, and a (0, 0) absolute event is generated. Checking * released, and a (0, 0) absolute event is generated. Checking
* pEvdev->tool here, lets us ignore that event. pEvdev->tool is * pEvdev->digi here, lets us ignore that event. pEvdev is
* initialized to 1 so devices that don't use this scheme still * initialized to 1 so devices that doesn't use this scheme still
* just work. * just works.
*/ */
if (pEvdev->abs && pEvdev->tool) { if (pEvdev->abs && pEvdev->tool) {
xf86PostMotionEventP(pInfo->dev, TRUE, *first_v, *num_v, v); xf86PostMotionEventP(pInfo->dev, TRUE, *first_v, *num_v, v);
@@ -661,7 +714,7 @@ static void
EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
{ {
int num_v = 0, first_v = 0; int num_v = 0, first_v = 0;
int v[MAX_VALUATORS] = {}; int v[MAX_VALUATORS];
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
EvdevProcessValuators(pInfo, v, &num_v, &first_v); EvdevProcessValuators(pInfo, v, &num_v, &first_v);
@@ -712,6 +765,7 @@ EvdevReadInput(InputInfoPtr pInfo)
{ {
struct input_event ev[NUM_EVENTS]; struct input_event ev[NUM_EVENTS];
int i, len = sizeof(ev); int i, len = sizeof(ev);
EvdevPtr pEvdev = pInfo->private;
while (len == sizeof(ev)) while (len == sizeof(ev))
{ {
@@ -724,6 +778,11 @@ EvdevReadInput(InputInfoPtr pInfo)
xf86RemoveEnabledDevice(pInfo); xf86RemoveEnabledDevice(pInfo);
close(pInfo->fd); close(pInfo->fd);
pInfo->fd = -1; pInfo->fd = -1;
if (pEvdev->reopen_timer)
{
pEvdev->reopen_left = pEvdev->reopen_attempts;
pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);
}
} else if (errno != EAGAIN) } else if (errno != EAGAIN)
{ {
/* We use X_NONE here because it doesn't alloc */ /* We use X_NONE here because it doesn't alloc */
@@ -1148,18 +1207,12 @@ EvdevAddAbsClass(DeviceIntPtr device)
num_axes = CountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX)); num_axes = CountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
if (num_axes < 1) if (num_axes < 1)
return !Success; return !Success;
if (num_axes > MAX_VALUATORS) {
xf86Msg(X_WARNING, "%s: found %d axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
num_axes = MAX_VALUATORS;
}
pEvdev->num_vals = num_axes; pEvdev->num_vals = num_axes;
memset(pEvdev->vals, 0, num_axes * sizeof(int)); memset(pEvdev->vals, 0, num_axes * sizeof(int));
memset(pEvdev->old_vals, -1, num_axes * sizeof(int)); memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
atoms = malloc(pEvdev->num_vals * sizeof(Atom)); atoms = xalloc(pEvdev->num_vals * sizeof(Atom));
for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { for (axis = ABS_X; axis <= ABS_MAX; axis++) {
pEvdev->axis_map[axis] = -1; pEvdev->axis_map[axis] = -1;
if (!TestBit(axis, pEvdev->abs_bitmask)) if (!TestBit(axis, pEvdev->abs_bitmask))
continue; continue;
@@ -1181,29 +1234,20 @@ EvdevAddAbsClass(DeviceIntPtr device)
for (axis = ABS_X; axis <= ABS_MAX; axis++) { for (axis = ABS_X; axis <= ABS_MAX; axis++) {
int axnum = pEvdev->axis_map[axis]; int axnum = pEvdev->axis_map[axis];
int resolution = 10000;
if (axnum == -1) if (axnum == -1)
continue; continue;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
/* Kernel provides units/mm, X wants units/m */
if (pEvdev->absinfo[axis].resolution)
resolution = pEvdev->absinfo[axis].resolution * 1000;
#endif
xf86InitValuatorAxisStruct(device, axnum, xf86InitValuatorAxisStruct(device, axnum,
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
atoms[axnum], atoms[axnum],
#endif #endif
pEvdev->absinfo[axis].minimum, pEvdev->absinfo[axis].minimum,
pEvdev->absinfo[axis].maximum, pEvdev->absinfo[axis].maximum,
resolution, 0, resolution); 10000, 0, 10000);
xf86InitValuatorDefaults(device, axnum); xf86InitValuatorDefaults(device, axnum);
pEvdev->old_vals[axnum] = -1; pEvdev->old_vals[axnum] = -1;
} }
free(atoms); xfree(atoms);
if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
return !Success; return !Success;
@@ -1224,24 +1268,6 @@ EvdevAddAbsClass(DeviceIntPtr device)
TestBit(ABS_TILT_Y, pEvdev->abs_bitmask))) TestBit(ABS_TILT_Y, pEvdev->abs_bitmask)))
pInfo->flags |= XI86_POINTER_CAPABLE; pInfo->flags |= XI86_POINTER_CAPABLE;
if (pEvdev->flags & EVDEV_TOUCHPAD)
pEvdev->flags |= EVDEV_RELATIVE_MODE;
else
pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
if (xf86FindOption(pInfo->options, "Mode"))
{
char *mode;
mode = xf86SetStrOption(pInfo->options, "Mode", NULL);
if (!strcasecmp("absolute", mode))
pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
else if (!strcasecmp("relative", mode))
pEvdev->flags |= EVDEV_RELATIVE_MODE;
else
xf86Msg(X_INFO, "%s: unknown mode, use default\n", pInfo->name);
free(mode);
}
return Success; return Success;
} }
@@ -1275,16 +1301,11 @@ EvdevAddRelClass(DeviceIntPtr device)
if (num_axes <= 0) if (num_axes <= 0)
return !Success; return !Success;
if (num_axes > MAX_VALUATORS) {
xf86Msg(X_WARNING, "%s: found %d axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
num_axes = MAX_VALUATORS;
}
pEvdev->num_vals = num_axes; pEvdev->num_vals = num_axes;
memset(pEvdev->vals, 0, num_axes * sizeof(int)); memset(pEvdev->vals, 0, num_axes * sizeof(int));
atoms = malloc(pEvdev->num_vals * sizeof(Atom)); atoms = xalloc(pEvdev->num_vals * sizeof(Atom));
for (axis = REL_X; i < MAX_VALUATORS && axis <= REL_MAX; axis++) for (axis = REL_X; axis <= REL_MAX; axis++)
{ {
pEvdev->axis_map[axis] = -1; pEvdev->axis_map[axis] = -1;
/* We don't post wheel events, so ignore them here too */ /* We don't post wheel events, so ignore them here too */
@@ -1308,9 +1329,6 @@ EvdevAddRelClass(DeviceIntPtr device)
GetMotionHistorySize(), Relative)) GetMotionHistorySize(), Relative))
return !Success; return !Success;
if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
return !Success;
for (axis = REL_X; axis <= REL_MAX; axis++) for (axis = REL_X; axis <= REL_MAX; axis++)
{ {
int axnum = pEvdev->axis_map[axis]; int axnum = pEvdev->axis_map[axis];
@@ -1325,7 +1343,10 @@ EvdevAddRelClass(DeviceIntPtr device)
xf86InitValuatorDefaults(device, axnum); xf86InitValuatorDefaults(device, axnum);
} }
free(atoms); xfree(atoms);
if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
return !Success;
pInfo->flags |= XI86_POINTER_CAPABLE; pInfo->flags |= XI86_POINTER_CAPABLE;
@@ -1342,7 +1363,7 @@ EvdevAddButtonClass(DeviceIntPtr device)
pInfo = device->public.devicePrivate; pInfo = device->public.devicePrivate;
pEvdev = pInfo->private; pEvdev = pInfo->private;
labels = malloc(pEvdev->num_buttons * sizeof(Atom)); labels = xalloc(pEvdev->num_buttons * sizeof(Atom));
EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels); EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons,
@@ -1352,7 +1373,7 @@ EvdevAddButtonClass(DeviceIntPtr device)
pEvdev->btnmap)) pEvdev->btnmap))
return !Success; return !Success;
free(labels); xfree(labels);
return Success; return Success;
} }
@@ -1380,16 +1401,15 @@ EvdevInitButtonMapping(InputInfoPtr pInfo)
/* Check for user-defined button mapping */ /* Check for user-defined button mapping */
if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL))) if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
{ {
char *map, *s = " "; char *s = " ";
int btn = 0; int btn = 0;
xf86Msg(X_CONFIG, "%s: ButtonMapping '%s'\n", pInfo->name, mapping); xf86Msg(X_CONFIG, "%s: ButtonMapping '%s'\n", pInfo->name, mapping);
map = mapping;
while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS) while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS)
{ {
btn = strtol(map, &s, 10); btn = strtol(mapping, &s, 10);
if (s == map || btn < 0 || btn > EVDEV_MAXBUTTONS) if (s == mapping || btn < 0 || btn > EVDEV_MAXBUTTONS)
{ {
xf86Msg(X_ERROR, xf86Msg(X_ERROR,
"%s: ... Invalid button mapping. Using defaults\n", "%s: ... Invalid button mapping. Using defaults\n",
@@ -1399,9 +1419,8 @@ EvdevInitButtonMapping(InputInfoPtr pInfo)
} }
pEvdev->btnmap[nbuttons++] = btn; pEvdev->btnmap[nbuttons++] = btn;
map = s; mapping = s;
} }
free(mapping);
} }
for (i = nbuttons; i < ArrayLength(pEvdev->btnmap); i++) for (i = nbuttons; i < ArrayLength(pEvdev->btnmap); i++)
@@ -1536,26 +1555,56 @@ EvdevInit(DeviceIntPtr device)
/** /**
* Init all extras (wheel emulation, etc.) and grab the device. * Init all extras (wheel emulation, etc.) and grab the device.
*
* Coming from a resume, the grab may fail with ENODEV. In this case, we set a
* timer to wake up and try to reopen the device later.
*/ */
static int static int
EvdevOn(DeviceIntPtr device) EvdevOn(DeviceIntPtr device)
{ {
InputInfoPtr pInfo; InputInfoPtr pInfo;
EvdevPtr pEvdev; EvdevPtr pEvdev;
int rc = 0;
pInfo = device->public.devicePrivate; pInfo = device->public.devicePrivate;
pEvdev = pInfo->private; pEvdev = pInfo->private;
/* after PreInit fd is still open */
if (!EvdevOpenDevice(pInfo))
return !Success;
EvdevGrabDevice(pInfo, 1, 0); if (pInfo->fd != -1 && pEvdev->grabDevice &&
(rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1)))
{
xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
strerror(errno));
xf86FlushInput(pInfo->fd); /* ENODEV - device has disappeared after resume */
xf86AddEnabledDevice(pInfo); if (rc && errno == ENODEV)
EvdevMBEmuOn(pInfo); {
pEvdev->flags |= EVDEV_INITIALIZED; close(pInfo->fd);
device->public.on = TRUE; pInfo->fd = -1;
}
}
if (pInfo->fd == -1)
{
pEvdev->reopen_left = pEvdev->reopen_attempts;
pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);
} else
{
pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
if (EvdevIsDuplicate(pInfo))
{
xf86Msg(X_WARNING, "%s: Refusing to enable duplicate device.\n",
pInfo->name);
return !Success;
}
pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 0, NULL, NULL);
xf86FlushInput(pInfo->fd);
xf86AddEnabledDevice(pInfo);
EvdevMBEmuOn(pInfo);
pEvdev->flags |= EVDEV_INITIALIZED;
device->public.on = TRUE;
}
return Success; return Success;
} }
@@ -1583,7 +1632,9 @@ EvdevProc(DeviceIntPtr device, int what)
EvdevMBEmuFinalize(pInfo); EvdevMBEmuFinalize(pInfo);
if (pInfo->fd != -1) if (pInfo->fd != -1)
{ {
EvdevGrabDevice(pInfo, 0, 1); if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
strerror(errno));
xf86RemoveEnabledDevice(pInfo); xf86RemoveEnabledDevice(pInfo);
close(pInfo->fd); close(pInfo->fd);
pInfo->fd = -1; pInfo->fd = -1;
@@ -1591,6 +1642,11 @@ EvdevProc(DeviceIntPtr device, int what)
pEvdev->min_maj = 0; pEvdev->min_maj = 0;
pEvdev->flags &= ~EVDEV_INITIALIZED; pEvdev->flags &= ~EVDEV_INITIALIZED;
device->public.on = FALSE; device->public.on = FALSE;
if (pEvdev->reopen_timer)
{
TimerFree(pEvdev->reopen_timer);
pEvdev->reopen_timer = NULL;
}
break; break;
case DEVICE_CLOSE: case DEVICE_CLOSE:
@@ -1619,7 +1675,8 @@ static int
EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare) EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
{ {
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int i, len; size_t len;
int i;
char name[1024] = {0}; char name[1024] = {0};
unsigned long bitmask[NLONGS(EV_CNT)] = {0}; unsigned long bitmask[NLONGS(EV_CNT)] = {0};
@@ -1750,39 +1807,27 @@ error:
} }
/**
* Issue an EVIOCGRAB on the device file, either as a grab or to ungrab, or
* both. Return TRUE on success, otherwise FALSE. Failing the release is a
* still considered a success, because it's not as if you could do anything
* about it.
*/
static BOOL
EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab)
{
EvdevPtr pEvdev = pInfo->private;
if (pEvdev->grabDevice)
{
if (grab && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
strerror(errno));
return FALSE;
} else if (ungrab && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
strerror(errno));
}
return TRUE;
}
static int static int
EvdevProbe(InputInfoPtr pInfo) EvdevProbe(InputInfoPtr pInfo)
{ {
int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll; int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
int has_lmr; /* left middle right */ int kernel24 = 0;
int ignore_abs = 0, ignore_rel = 0; int ignore_abs = 0, ignore_rel = 0;
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
if (errno == EINVAL) {
/* keyboards are unsafe in 2.4 */
kernel24 = 1;
pEvdev->grabDevice = 0;
} else {
xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
return 1;
}
} else if (pEvdev->grabDevice) {
ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
}
/* Trinary state for ignoring axes: /* Trinary state for ignoring axes:
- unset: do the normal thing. - unset: do the normal thing.
- TRUE: explicitly ignore them. - TRUE: explicitly ignore them.
@@ -1808,7 +1853,6 @@ EvdevProbe(InputInfoPtr pInfo)
has_abs_axes = FALSE; has_abs_axes = FALSE;
has_keys = FALSE; has_keys = FALSE;
has_scroll = FALSE; has_scroll = FALSE;
has_lmr = FALSE;
num_buttons = 0; num_buttons = 0;
/* count all buttons */ /* count all buttons */
@@ -1823,15 +1867,11 @@ EvdevProbe(InputInfoPtr pInfo)
} }
} }
has_lmr = TestBit(BTN_LEFT, pEvdev->key_bitmask) ||
TestBit(BTN_MIDDLE, pEvdev->key_bitmask) ||
TestBit(BTN_RIGHT, pEvdev->key_bitmask);
if (num_buttons) if (num_buttons)
{ {
pEvdev->flags |= EVDEV_BUTTON_EVENTS; pEvdev->flags |= EVDEV_BUTTON_EVENTS;
pEvdev->num_buttons = num_buttons; pEvdev->num_buttons = num_buttons;
xf86Msg(X_PROBED, "%s: Found %d mouse buttons\n", pInfo->name, xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name,
num_buttons); num_buttons);
} }
@@ -1846,7 +1886,7 @@ EvdevProbe(InputInfoPtr pInfo)
if (TestBit(REL_WHEEL, pEvdev->rel_bitmask) || if (TestBit(REL_WHEEL, pEvdev->rel_bitmask) ||
TestBit(REL_HWHEEL, pEvdev->rel_bitmask) || TestBit(REL_HWHEEL, pEvdev->rel_bitmask) ||
TestBit(REL_DIAL, pEvdev->rel_bitmask)) { TestBit(REL_DIAL, pEvdev->rel_bitmask)) {
xf86Msg(X_PROBED, "%s: Found scroll wheel(s)\n", pInfo->name); xf86Msg(X_INFO, "%s: Found scroll wheel(s)\n", pInfo->name);
has_scroll = TRUE; has_scroll = TRUE;
if (!num_buttons) if (!num_buttons)
xf86Msg(X_INFO, "%s: Forcing buttons for scroll wheel(s)\n", xf86Msg(X_INFO, "%s: Forcing buttons for scroll wheel(s)\n",
@@ -1857,12 +1897,12 @@ EvdevProbe(InputInfoPtr pInfo)
if (!ignore_rel) if (!ignore_rel)
{ {
xf86Msg(X_PROBED, "%s: Found relative axes\n", pInfo->name); xf86Msg(X_INFO, "%s: Found relative axes\n", pInfo->name);
pEvdev->flags |= EVDEV_RELATIVE_EVENTS; pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
if (TestBit(REL_X, pEvdev->rel_bitmask) && if (TestBit(REL_X, pEvdev->rel_bitmask) &&
TestBit(REL_Y, pEvdev->rel_bitmask)) { TestBit(REL_Y, pEvdev->rel_bitmask)) {
xf86Msg(X_PROBED, "%s: Found x and y relative axes\n", pInfo->name); xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
} }
} else { } else {
xf86Msg(X_INFO, "%s: Relative axes present but ignored.\n", pInfo->name); xf86Msg(X_INFO, "%s: Relative axes present but ignored.\n", pInfo->name);
@@ -1882,15 +1922,15 @@ EvdevProbe(InputInfoPtr pInfo)
xf86Msg(X_INFO, "%s: Absolute axes present but ignored.\n", pInfo->name); xf86Msg(X_INFO, "%s: Absolute axes present but ignored.\n", pInfo->name);
has_abs_axes = FALSE; has_abs_axes = FALSE;
} else if (has_abs_axes) { } else if (has_abs_axes) {
xf86Msg(X_PROBED, "%s: Found absolute axes\n", pInfo->name); xf86Msg(X_INFO, "%s: Found absolute axes\n", pInfo->name);
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS; pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
if ((TestBit(ABS_X, pEvdev->abs_bitmask) && if ((TestBit(ABS_X, pEvdev->abs_bitmask) &&
TestBit(ABS_Y, pEvdev->abs_bitmask))) { TestBit(ABS_Y, pEvdev->abs_bitmask))) {
xf86Msg(X_PROBED, "%s: Found x and y absolute axes\n", pInfo->name); xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
if (TestBit(BTN_TOOL_PEN, pEvdev->key_bitmask)) if (TestBit(BTN_TOOL_PEN, pEvdev->key_bitmask))
{ {
xf86Msg(X_PROBED, "%s: Found absolute tablet.\n", pInfo->name); xf86Msg(X_INFO, "%s: Found absolute tablet.\n", pInfo->name);
pEvdev->flags |= EVDEV_TABLET; pEvdev->flags |= EVDEV_TABLET;
if (!pEvdev->num_buttons) if (!pEvdev->num_buttons)
{ {
@@ -1899,12 +1939,12 @@ EvdevProbe(InputInfoPtr pInfo)
} }
} else if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) || } else if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) ||
TestBit(BTN_TOUCH, pEvdev->key_bitmask)) { TestBit(BTN_TOUCH, pEvdev->key_bitmask)) {
if (has_lmr || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) { if (num_buttons || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) {
xf86Msg(X_PROBED, "%s: Found absolute touchpad.\n", pInfo->name); xf86Msg(X_INFO, "%s: Found absolute touchpad.\n", pInfo->name);
pEvdev->flags |= EVDEV_TOUCHPAD; pEvdev->flags |= EVDEV_TOUCHPAD;
memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals); memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals);
} else { } else {
xf86Msg(X_PROBED, "%s: Found absolute touchscreen\n", pInfo->name); xf86Msg(X_INFO, "%s: Found absolute touchscreen\n", pInfo->name);
pEvdev->flags |= EVDEV_TOUCHSCREEN; pEvdev->flags |= EVDEV_TOUCHSCREEN;
pEvdev->flags |= EVDEV_BUTTON_EVENTS; pEvdev->flags |= EVDEV_BUTTON_EVENTS;
} }
@@ -1914,37 +1954,13 @@ EvdevProbe(InputInfoPtr pInfo)
for (i = 0; i < BTN_MISC; i++) { for (i = 0; i < BTN_MISC; i++) {
if (TestBit(i, pEvdev->key_bitmask)) { if (TestBit(i, pEvdev->key_bitmask)) {
xf86Msg(X_PROBED, "%s: Found keys\n", pInfo->name); xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name);
pEvdev->flags |= EVDEV_KEYBOARD_EVENTS; pEvdev->flags |= EVDEV_KEYBOARD_EVENTS;
has_keys = TRUE; has_keys = TRUE;
break; break;
} }
} }
if (has_rel_axes || has_abs_axes)
{
char *str;
int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
if (str) {
num_calibration = sscanf(str, "%d %d %d %d",
&calibration[0], &calibration[1],
&calibration[2], &calibration[3]);
free(str);
if (num_calibration == 4)
EvdevSetCalibration(pInfo, num_calibration, calibration);
else
xf86Msg(X_ERROR,
"%s: Insufficient calibration factors (%d). Ignoring calibration\n",
pInfo->name, num_calibration);
}
}
if (has_rel_axes || has_abs_axes || num_buttons) { if (has_rel_axes || has_abs_axes || num_buttons) {
pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS | pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
XI86_CONFIGURED; XI86_CONFIGURED;
@@ -1964,9 +1980,14 @@ EvdevProbe(InputInfoPtr pInfo)
} }
if (has_keys) { if (has_keys) {
xf86Msg(X_INFO, "%s: Configuring as keyboard\n", pInfo->name); if (kernel24) {
pInfo->flags |= XI86_KEYBOARD_CAPABLE | XI86_CONFIGURED; xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n",
pInfo->type_name = XI_KEYBOARD; pInfo->name);
} else {
xf86Msg(X_INFO, "%s: Configuring as keyboard\n", pInfo->name);
pInfo->flags |= XI86_KEYBOARD_CAPABLE | XI86_CONFIGURED;
pInfo->type_name = XI_KEYBOARD;
}
} }
if (has_scroll && (pInfo->flags & XI86_CONFIGURED) && if (has_scroll && (pInfo->flags & XI86_CONFIGURED) &&
@@ -2007,60 +2028,18 @@ EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
} }
} }
static BOOL
EvdevOpenDevice(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
char *device = (char*)pEvdev->device;
if (!device)
{
device = xf86CheckStrOption(pInfo->options, "Device", NULL);
if (!device) {
xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name);
return FALSE;
}
pEvdev->device = device;
xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
}
if (pInfo->fd < 0)
{
do {
pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
} while (pInfo->fd < 0 && errno == EINTR);
if (pInfo->fd < 0) {
xf86Msg(X_ERROR, "Unable to open evdev device \"%s\".\n", device);
return FALSE;
}
}
/* Check major/minor of device node to avoid adding duplicate devices. */
pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
if (EvdevIsDuplicate(pInfo))
{
xf86Msg(X_WARNING, "%s: device file is duplicate. Ignoring.\n",
pInfo->name);
close(pInfo->fd);
return FALSE;
}
return TRUE;
}
static InputInfoPtr static InputInfoPtr
EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags) EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{ {
InputInfoPtr pInfo; InputInfoPtr pInfo;
const char *device, *str;
int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
EvdevPtr pEvdev; EvdevPtr pEvdev;
if (!(pInfo = xf86AllocateInput(drv, 0))) if (!(pInfo = xf86AllocateInput(drv, 0)))
return NULL; return NULL;
/* Initialise the InputInfoRec. */ /* Initialise the InputInfoRec. */
pInfo->fd = -1;
pInfo->name = dev->identifier; pInfo->name = dev->identifier;
pInfo->flags = 0; pInfo->flags = 0;
pInfo->type_name = "UNKNOWN"; pInfo->type_name = "UNKNOWN";
@@ -2069,52 +2048,89 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
pInfo->history_size = 0; pInfo->history_size = 0;
pInfo->control_proc = NULL; pInfo->control_proc = NULL;
pInfo->close_proc = NULL; pInfo->close_proc = NULL;
pInfo->switch_mode = EvdevSwitchMode; pInfo->switch_mode = NULL;
pInfo->conversion_proc = NULL; pInfo->conversion_proc = NULL;
pInfo->reverse_conversion_proc = NULL; pInfo->reverse_conversion_proc = NULL;
pInfo->dev = NULL; pInfo->dev = NULL;
pInfo->private_flags = 0; pInfo->private_flags = 0;
pInfo->always_core_feedback = NULL; pInfo->always_core_feedback = NULL;
pInfo->conf_idev = dev; pInfo->conf_idev = dev;
pInfo->private = NULL;
if (!(pEvdev = calloc(sizeof(EvdevRec), 1))) if (!(pEvdev = xcalloc(sizeof(EvdevRec), 1)))
goto error; return pInfo;
pInfo->private = pEvdev; pInfo->private = pEvdev;
xf86CollectInputOptions(pInfo, evdevDefaults, NULL); xf86CollectInputOptions(pInfo, evdevDefaults, NULL);
xf86ProcessCommonOptions(pInfo, pInfo->options); xf86ProcessCommonOptions(pInfo, pInfo->options);
if (!EvdevOpenDevice(pInfo))
goto error;
/* /*
* We initialize pEvdev->tool to 1 so that device that doesn't use * We initialize pEvdev->tool to 1 so that device that doesn't use
* proximity will still report events. * proximity will still report events.
*/ */
pEvdev->tool = 1; pEvdev->tool = 1;
device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
if (!device) {
xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name);
xf86DeleteInput(pInfo, 0);
return NULL;
}
pEvdev->device = device;
xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
do {
pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
} while (pInfo->fd < 0 && errno == EINTR);
if (pInfo->fd < 0) {
xf86Msg(X_ERROR, "Unable to open evdev device \"%s\".\n", device);
xf86DeleteInput(pInfo, 0);
return NULL;
}
/* Check major/minor of device node to avoid adding duplicate devices. */
pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
if (EvdevIsDuplicate(pInfo))
{
xf86Msg(X_WARNING, "%s: device file already in use. Ignoring.\n",
pInfo->name);
close(pInfo->fd);
xf86DeleteInput(pInfo, 0);
return NULL;
}
pEvdev->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
if (str) {
num_calibration = sscanf(str, "%d %d %d %d",
&calibration[0], &calibration[1],
&calibration[2], &calibration[3]);
if (num_calibration == 4)
EvdevSetCalibration(pInfo, num_calibration, calibration);
else
xf86Msg(X_ERROR,
"%s: Insufficient calibration factors (%d). Ignoring calibration\n",
pInfo->name, num_calibration);
}
/* Grabbing the event device stops in-kernel event forwarding. In other /* Grabbing the event device stops in-kernel event forwarding. In other
words, it disables rfkill and the "Macintosh mouse button emulation". words, it disables rfkill and the "Macintosh mouse button emulation".
Note that this needs a server that sets the console to RAW mode. */ Note that this needs a server that sets the console to RAW mode. */
pEvdev->grabDevice = xf86CheckBoolOption(dev->commonOptions, "GrabDevice", 0); pEvdev->grabDevice = xf86CheckBoolOption(dev->commonOptions, "GrabDevice", 0);
/* If grabDevice is set, ungrab immediately since we only want to grab
* between DEVICE_ON and DEVICE_OFF. If we never get DEVICE_ON, don't
* hold a grab. */
if (!EvdevGrabDevice(pInfo, 1, 1))
{
xf86Msg(X_WARNING, "%s: Device may already be configured.\n",
pInfo->name);
goto error;
}
EvdevInitButtonMapping(pInfo); EvdevInitButtonMapping(pInfo);
if (EvdevCacheCompare(pInfo, FALSE) || if (EvdevCacheCompare(pInfo, FALSE) ||
EvdevProbe(pInfo)) { EvdevProbe(pInfo)) {
goto error; close(pInfo->fd);
xf86DeleteInput(pInfo, 0);
return NULL;
} }
EvdevAddDevice(pInfo); EvdevAddDevice(pInfo);
@@ -2127,12 +2143,6 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
} }
return pInfo; return pInfo;
error:
if (pInfo->fd >= 0)
close(pInfo->fd);
xf86DeleteInput(pInfo, 0);
return NULL;
} }
_X_EXPORT InputDriverRec EVDEV = { _X_EXPORT InputDriverRec EVDEV = {
@@ -2479,6 +2489,18 @@ EvdevInitProperty(DeviceIntPtr dev)
EvdevPtr pEvdev = pInfo->private; EvdevPtr pEvdev = pInfo->private;
int rc; int rc;
BOOL invert[2]; BOOL invert[2];
char reopen;
prop_reopen = MakeAtom(EVDEV_PROP_REOPEN, strlen(EVDEV_PROP_REOPEN),
TRUE);
reopen = pEvdev->reopen_attempts;
rc = XIChangeDeviceProperty(dev, prop_reopen, XA_INTEGER, 8,
PropModeReplace, 1, &reopen, FALSE);
if (rc != Success)
return;
XISetDevicePropertyDeletable(dev, prop_reopen, FALSE);
if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS)) if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS))
{ {
@@ -2571,6 +2593,13 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
pEvdev->invert_x = data[0]; pEvdev->invert_x = data[0];
pEvdev->invert_y = data[1]; pEvdev->invert_y = data[1];
} }
} else if (atom == prop_reopen)
{
if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
return BadMatch;
if (!checkonly)
pEvdev->reopen_attempts = *((CARD8*)val->data);
} else if (atom == prop_calibration) } else if (atom == prop_calibration)
{ {
if (val->format != 32 || val->type != XA_INTEGER) if (val->format != 32 || val->type != XA_INTEGER)

View File

@@ -34,12 +34,11 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/types.h> #include <linux/types.h>
#include <xorg-server.h>
#include <xf86Xinput.h> #include <xf86Xinput.h>
#include <xf86_OSproc.h> #include <xf86_OSproc.h>
#include <xkbstr.h> #include <xkbstr.h>
#ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */ #ifndef EV_CNT /* linux 2.4 kernels and earlier lack _CNT defines */
#define EV_CNT (EV_MAX+1) #define EV_CNT (EV_MAX+1)
#endif #endif
#ifndef KEY_CNT #ifndef KEY_CNT
@@ -58,20 +57,6 @@
#define EVDEV_MAXBUTTONS 32 #define EVDEV_MAXBUTTONS 32
#define EVDEV_MAXQUEUE 32 #define EVDEV_MAXQUEUE 32
/* evdev flags */
#define EVDEV_KEYBOARD_EVENTS (1 << 0)
#define EVDEV_BUTTON_EVENTS (1 << 1)
#define EVDEV_RELATIVE_EVENTS (1 << 2)
#define EVDEV_ABSOLUTE_EVENTS (1 << 3)
#define EVDEV_TOUCHPAD (1 << 4)
#define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
#define EVDEV_TOUCHSCREEN (1 << 6)
#define EVDEV_CALIBRATED (1 << 7) /* run-time calibrated? */
#define EVDEV_TABLET (1 << 8) /* device looks like a tablet? */
#define EVDEV_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
#define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
#define EVDEV_RELATIVE_MODE (1 << 11) /* Force relative events for devices with absolute axes */
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
#define HAVE_PROPERTIES 1 #define HAVE_PROPERTIES 1
#endif #endif
@@ -214,6 +199,7 @@ void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer);
void EvdevMBEmuPreInit(InputInfoPtr); void EvdevMBEmuPreInit(InputInfoPtr);
void EvdevMBEmuOn(InputInfoPtr); void EvdevMBEmuOn(InputInfoPtr);
void EvdevMBEmuFinalize(InputInfoPtr); void EvdevMBEmuFinalize(InputInfoPtr);
void EvdevMBEmuEnable(InputInfoPtr, BOOL);
/* Mouse Wheel emulation */ /* Mouse Wheel emulation */
void EvdevWheelEmuPreInit(InputInfoPtr pInfo); void EvdevWheelEmuPreInit(InputInfoPtr pInfo);