Git init
authorKibum Kim <kb0929.kim@samsung.com>
Fri, 6 Jan 2012 16:10:14 +0000 (01:10 +0900)
committerKibum Kim <kb0929.kim@samsung.com>
Fri, 6 Jan 2012 16:10:14 +0000 (01:10 +0900)
38 files changed:
10-diamondtouch.fdi [new file with mode: 0644]
10-logitech.fdi [new file with mode: 0644]
10-stantum.fdi [new file with mode: 0644]
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0755]
debian/README.source [new file with mode: 0644]
debian/changelog [new file with mode: 0755]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/local/10-x11-evdev.fdi [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/watch [new file with mode: 0644]
debian/xserver-xorg-input-evdev-multitouch.install [new file with mode: 0644]
debian/xserver-xorg-input-evdev-multitouch.links [new file with mode: 0644]
debian/xserver-xorg-input-evdev-multitouch.manpages [new file with mode: 0644]
debian/xsfbs/repack.sh [new file with mode: 0644]
debian/xsfbs/xsfbs.mk [new file with mode: 0644]
debian/xsfbs/xsfbs.sh [new file with mode: 0644]
include/Makefile.am [new file with mode: 0644]
include/evdevmultitouch-properties.h [new file with mode: 0755]
include/vsync_debug_info.h [new file with mode: 0755]
include/vsync_input_protocol.h [new file with mode: 0755]
man/Makefile.am [new file with mode: 0644]
man/evdevmultitouch.man [new file with mode: 0644]
packaging/xorg-x11-drv-evdev-multitouch.spec [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/draglock.c [new file with mode: 0755]
src/emuMB.c [new file with mode: 0755]
src/emuWheel.c [new file with mode: 0755]
src/evdevmultitouch.c [new file with mode: 0755]
src/evdevmultitouch.h [new file with mode: 0755]
xorg-evdev-multitouch.pc.in [new file with mode: 0644]

diff --git a/10-diamondtouch.fdi b/10-diamondtouch.fdi
new file mode 100644 (file)
index 0000000..dc0bc15
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- this is probably a bit imprecise -->
+<deviceinfo version="0.2">
+  <device>
+    <match key="info.product" contains="DiamondTouch">
+      <match key="info.category" contains="input">
+        <merge key="input.x11_driver" type="string">evdevmultitouch</merge>
+      </match>
+  </device>
+</deviceinfo>
diff --git a/10-logitech.fdi b/10-logitech.fdi
new file mode 100644 (file)
index 0000000..4151d70
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- this is probably a bit imprecise -->
+<deviceinfo version="0.2">
+  <device>
+    <match key="info.product" contains="Logitech Optical USB Mouse">
+      <match key="info.category" contains="input">
+        <match key="info.capabilities" contains="input.mouse">
+            <merge key="input.x11_driver" type="string">evdevmultitouchmultitouch</merge>
+        </match>
+      </match>
+    </match>
+  </device>
+</deviceinfo>
diff --git a/10-stantum.fdi b/10-stantum.fdi
new file mode 100644 (file)
index 0000000..33d080d
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- this is probably a bit imprecise -->
+<deviceinfo version="0.2">
+  <device>
+    <match key="info.product" contains="Stantum MTP USB Controller">
+      <match key="info.category" contains="input">
+        <merge key="input.x11_driver" type="string">evdevmultitouch</merge>
+      </match>
+    </match>
+  </device>
+</deviceinfo>
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e903784
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Sung-Jin Park <sj76.park@samsung.com>
+Sangjin Lee <lsj119@samsung.com>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..b76958b
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,115 @@
+Various copyright notices found in this driver:
+
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. 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 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 © 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 1993 by David Dawes <dawes@xfree86.org>
+Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+Copyright 1994-2002 by The XFree86 Project, Inc.
+Copyright 2002 by Paul Elliott
+
+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 the authors
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  The authors make 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 Adam Jackson.
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ADAM JACKSON 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.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..d23f650
--- /dev/null
@@ -0,0 +1,40 @@
+#  Copyright 2005 Adam Jackson.
+#
+#  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
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON 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.
+
+AUTOMAKE_OPTIONS = foreign
+
+# Ensure headers are installed below $(prefix) for distcheck
+DISTCHECK_CONFIGURE_FLAGS = --with-sdkdir='$${includedir}/xorg'
+
+SUBDIRS = src man include
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xorg-evdev-multitouch.pc
+
+EXTRA_DIST = ChangeLog
+
+MAINTAINERCLEANFILES=ChangeLog
+
+.PHONY: ChangeLog
+
+ChangeLog:
+       $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..3b3e134
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+xf86-input-evdevmultitouch - Generic Linux input driver for the Xorg X server
+
+Please submit bugs & patches to the Xorg bugzilla:
+
+        https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+        http://lists.freedesktop.org/mailman/listinfo/xorg
+
+The master development code repository can be found at:
+
+        git://anongit.freedesktop.org/git/xorg/driver/xf86-input-evdevmultitouch
+
+        http://cgit.freedesktop.org/xorg/driver/xf86-input-evdevmultitouch
+
+For more information on the git code manager, see:
+
+        http://wiki.x.org/wiki/GitPage
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..904cd67
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100755 (executable)
index 0000000..5dabddc
--- /dev/null
@@ -0,0 +1,87 @@
+#  Copyright 2005 Adam Jackson.
+#
+#  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
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON 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.
+#
+# Process this file with autoconf to produce a configure script
+
+AC_PREREQ(2.57)
+AC_INIT([xf86-input-evdev-multitouch],
+        2.3.1,
+        [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
+        xf86-input-evdev-multitouch)
+
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_AUX_DIR(.)
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+AM_MAINTAINER_MODE
+
+# 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_PROG_LIBTOOL
+AC_PROG_CC
+XORG_DEFAULT_OPTIONS
+
+AH_TOP([#include "xorg-server.h"])
+
+AC_ARG_WITH(xorg-module-dir,
+            AC_HELP_STRING([--with-xorg-module-dir=DIR],
+                           [Default xorg module directory [[default=$libdir/xorg/modules]]]),
+            [moduledir="$withval"],
+            [moduledir="$libdir/xorg/modules"])
+inputdir=${moduledir}/input
+AC_SUBST(inputdir)
+
+# Checks for pkg-config packages. We need to be able to override sdkdir
+# to satisfy silly distcheck requirements.
+PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
+XORG_CFLAGS="$CWARNFLAGS $XORG_CFLAGS"
+AC_ARG_WITH([sdkdir], [],
+    [sdkdir="$withval"],
+    [sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server`])
+AC_SUBST([sdkdir])
+
+# Checks for libraries.
+#PKG_CHECK_MODULES(HAL,hal)
+#AC_SUBST(HAL_CFLAGS)
+#AC_SUBST(HAL_LIBS)
+
+#CFLAGS="$CFLAGS $XORG_CFLAGS $HAL_CFLAGS"' -I$(top_srcdir)/src'
+#LIBS="$LIBS $XORG_LIBS $HAL_LIBS"
+CFLAGS="$CFLAGS $XORG_CFLAGS"' -I$(top_srcdir)/src'
+LIBS="$LIBS $XORG_LIBS"
+AC_SUBST(CFLAGS)
+AC_SUBST(LIBS)
+
+# Checks for header files.
+AC_HEADER_STDC
+
+DRIVER_NAME=evdevmultitouch
+AC_SUBST([DRIVER_NAME])
+
+AC_OUTPUT([Makefile
+           src/Makefile
+           man/Makefile
+           include/Makefile
+           xorg-evdev-multitouch.pc])
diff --git a/debian/README.source b/debian/README.source
new file mode 100644 (file)
index 0000000..34ab4bf
--- /dev/null
@@ -0,0 +1,73 @@
+------------------------------------------------------
+Quick Guide To Patching This Package For The Impatient
+------------------------------------------------------
+
+1. Make sure you have quilt installed
+2. Unpack the package as usual with "dpkg-source -x"
+3. Run the "patch" target in debian/rules
+4. Create a new patch with "quilt new" (see quilt(1))
+5. Edit all the files you want to include in the patch with "quilt edit" 
+   (see quilt(1)).
+6. Write the patch with "quilt refresh" (see quilt(1))
+7. Run the "clean" target in debian/rules
+
+Alternatively, instead of using quilt directly, you can drop the patch in to 
+debian/patches and add the name of the patch to debian/patches/series.
+
+------------------------------------
+Guide To The X Strike Force Packages
+------------------------------------
+
+The X Strike Force team maintains X packages in git repositories on
+git.debian.org in the pkg-xorg subdirectory. Most upstream packages
+are actually maintained in git repositories as well, so they often
+just need to be pulled into git.debian.org in a "upstream-*" branch.
+Otherwise, the upstream sources are manually installed in the Debian
+git repository.
+
+The .orig.tar.gz upstream source file could be generated this
+"upstream-*" branch in the Debian git repository but it is actually
+copied from upstream tarballs directly.
+
+Due to X.org being highly modular, packaging all X.org applications
+as their own independent packages would have created too many Debian
+packages. For this reason, some X.org applications have been grouped
+into larger packages: xutils, xutils-dev, x11-apps, x11-session-utils,
+x11-utils, x11-xfs-utils, x11-xkb-utils, x11-xserver-utils.
+Most packages, including the X.org server itself and all libraries
+and drivers are, however maintained independently.
+
+The Debian packaging is added by creating the "debian-*" git branch
+which contains the aforementioned "upstream-*" branch plus the debian/
+repository files.
+When a patch has to be applied to the Debian package, two solutions
+are involved:
+* If the patch is available in one of the upstream branches, it
+  may be git'cherry-picked into the Debian repository. In this
+  case, it appears directly in the .diff.gz.
+* Otherwise, the patch is added to debian/patches/ which is managed
+  with quilt as documented in /usr/share/doc/quilt/README.source.
+
+quilt is actually invoked by the Debian X packaging through a larger
+set of scripts called XSFBS. XSFBS brings some other X specific
+features such as managing dependencies and conflicts due to the video
+and input driver ABIs.
+XSFBS itself is maintained in a separate repository at
+  git://git.debian.org/pkg-xorg/xsfbs.git
+and it is pulled inside the other Debian X repositories when needed.
+
+The XSFBS patching system requires a build dependency on quilt. Also
+a dependency on $(STAMP_DIR)/patch has to be added to debian/rules
+so that the XSFBS patching occurs before the actual build. So the
+very first target of the build (likely the one running autoreconf)
+should depend on $(STAMP_DIR)/patch. It should also not depend on
+anything so that parallel builds are correctly supported (nothing
+should probably run while patching is being done). And finally, the
+clean target should depend on the xsfclean target so that patches
+are unapplied on clean.
+
+When the upstream sources contain some DFSG-nonfree files, they are
+listed in text files in debian/prune/ in the "debian-*" branch of
+the Debian repository. XSFBS' scripts then take care of removing
+these listed files during the build so as to generate a modified
+DFSG-free .orig.tar.gz tarball.
diff --git a/debian/changelog b/debian/changelog
new file mode 100755 (executable)
index 0000000..e19e0f9
--- /dev/null
@@ -0,0 +1,236 @@
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+24) unstable; urgency=low
+
+  * Add EvdevMultitouchFrameSync() and related data structures for supporting X gesture driver
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+24
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Wed, 02 Nov 2011 17:49:35 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+23) unstable; urgency=low
+
+  * Add EvdevMultitouchGetGrabInfo() to check grab status of each touch device
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+23
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 19 Sep 2011 14:15:48 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+22) unstable; urgency=low
+
+  * oal rollback
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+22
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Fri, 08 Apr 2011 13:56:36 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+21) unstable; urgency=low
+
+  * Work for oal
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+21
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Tue, 05 Apr 2011 10:37:29 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+20) unstable; urgency=low
+
+  * [X11R7.6] upgrade package 
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+20
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Thu, 03 Mar 2011 19:37:30 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+19) unstable; urgency=low
+
+  * Remove the multitouch error filtering routine from EvdevMultitouchStoreMTData()
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+19
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 31 Jan 2011 17:30:00 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+18) unstable; urgency=low
+
+  * Modify evdev multitouch driver to set the number of multitouch to be set
+    properly on "MultiTouch" property
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+18
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Wed, 26 Jan 2011 14:24:52 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+17) unstable; urgency=low
+
+  * Modify evdevmultitouch.* to process events from both MT protocol A kernel
+    and MT protocol B kernel
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+17
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Thu, 23 Dec 2010 14:18:28 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+16) unstable; urgency=low
+
+  * Do not call xf86AddEnabledDevice() for devices named "*subdev*"
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+16
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 07 Dec 2010 17:31:08 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+15) unstable; urgency=low
+
+  * Add a macro _F_IGNORE_TSP_RESOLUTION_ to ignore TSP resolution when 
+    resolution was not specified in input.conf of Xorg server
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+15
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Fri, 26 Nov 2010 22:04:49 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+14) unstable; urgency=low
+
+  * Add Conflicts and Replaces info in debian/control
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+14
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Fri, 26 Nov 2010 14:53:20 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+13) unstable; urgency=low
+
+  * Modify evdevmultitouch.c not to call ProcessInputEvents() when subdevices
+    were being removed
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+13
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 23 Nov 2010 16:05:31 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+12) unstable; urgency=low
+
+  * Add xserver-xorg-input-evdev-multitouch-dbg into debian/control
+  * Modify debian/rules to strip binary except xserver-xorg-input-evdev-multitouch-dbg
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+12
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 22 Nov 2010 14:08:05 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+11) unstable; urgency=low
+
+  [ Sung-Jin Park ]
+  * Add --as-needed option
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+11
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 22 Nov 2010 14:08:02 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+10) unstable; urgency=low
+
+  * Modify driver name from evdev to evdevmultitouch
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+10
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Wed, 10 Nov 2010 15:43:01 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+9) unstable; urgency=low
+
+  * Fix a checking gab bug
+    - If a touch coordinates pair increases/decreases suddenly over 100 px in x or y axis,
+      the event pair will not be processed
+    - There is a bug, if the jumping of the coordinates happends,
+      most of the following events will not be processed either,
+      until the touch is released from the touchscreen
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+9
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Wed, 10 Nov 2010 11:26:57 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+8) unstable; urgency=low
+
+  * Add EvdevMultitouchSettingTimer() to set multitouch devices after
+    every initialization of core evdev device
+  * Git: 165.213.180.234:/git/slp/pkgs/xorg/driver/xserver-xorg-input-evdev-multitouch
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+8
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Thu, 04 Nov 2010 22:17:32 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+7) unstable; urgency=low
+
+  * Add codes for debugging multitouch event sequences from kernel driver
+  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+7
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 04 Oct 2010 13:58:49 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+6) unstable; urgency=low
+
+  * Do not get absinfo if "Resolution" option exists in input.conf file
+  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+6
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Fri, 17 Sep 2010 11:05:57 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+5) unstable; urgency=low
+
+  * Fix EvdevSwapAxes() for setting resolution properly.
+  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+5
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 29 Jun 2010 15:44:41 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+4) unstable; urgency=low
+
+  * Add input polling with vsync
+  * Modify evdev.c to add an additional argument to NewInputDeviceRequest()
+    for xserver-1.8.0
+  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+4
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 10 May 2010 16:18:28 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+3) unstable; urgency=low
+
+  * upload package
+  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+3
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 04 May 2010 11:54:56 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+2) unstable; urgency=low
+
+  * update
+  * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11
+  * Tag: xserver-xorg-input-evdev-multitouch_2.3.2-5slp2+2
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 03 May 2010 19:06:52 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5slp2+1) unstable; urgency=low
+
+  * Change revision
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Thu, 25 Mar 2010 18:14:29 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-5) unstable; urgency=low
+
+  * Add EvdevSwapAxes() function for adjusting touch screen size properly
+    when screen is rotated with xrandr extension
+    (Adjust absinfo of max_x, min_x, max_y, min_y)
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Fri, 19 Mar 2010 16:38:02 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-4) unstable; urgency=low
+
+  * Remove evdev log related to touch gap
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 09 Feb 2010 18:22:16 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-3) unstable; urgency=low
+
+  * Add routines for applying touch screen resolution properly from options in xorg.conf
+    Bug fix related to InvertX, InvertY
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 09 Feb 2010 09:47:05 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-2) unstable; urgency=low
+
+  * Change not to strip binary
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Thu, 04 Feb 2010 17:03:03 +0900
+
+xserver-xorg-input-evdev-multitouch (2.3.2-1) unstable; urgency=low
+
+  * Initial release
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Tue, 29 Sep 2009 21:04:26 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..ea1a2d7
--- /dev/null
@@ -0,0 +1,31 @@
+Source: xserver-xorg-input-evdev-multitouch
+Section: x11
+Priority: optional
+Maintainer: Sung-Jin Park <sj76.park@samsung.com>
+Uploaders: Sung-Jin Park <sj76.park@samsung.com>, SooChan Lim <sc1.lim@samsung.com>
+#Uploaders: David Nusinow <dnusinow@debian.org>, Drew Parsons <dparsons@debian.org>, Julien Cristau <jcristau@debian.org>, Brice Goglin <bgoglin@debian.org>
+Build-Depends: debhelper (>= 5.0.0), pkg-config, quilt, xserver-xorg-dev (>= 1.6.99.900), x11proto-core-dev, x11proto-randr-dev, x11proto-input-dev, x11proto-kb-dev, libxkbfile-dev, dpkg-dev (>= 1.14.17), automake, libtool, xutils-dev (>= 1:7.3~1)
+Standards-Version: 3.8.3
+
+Package: xserver-xorg-input-evdev-multitouch
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${xserver}
+Provides: ${xinpdriver:Provides}
+Conflicts: xserver-xorg-input-evdev-multitouch-c210
+Replaces: xserver-xorg-input-evdev-multitouch-c210, xserver-xorg (<< 6.8.2-35)
+Description: X.Org X server -- evdev input multitouch driver
+ This package provides the driver for input devices using evdev, the Linux
+ kernel's event delivery mechanism.  This driver allows for multiple keyboards
+ and mice to be treated as separate input devices.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xf86-input-evdev driver module.
+
+Package: xserver-xorg-input-evdev-multitouch-dbg
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${xserver}, xserver-xorg-input-evdev-multitouch (=${Source-Version})
+Description: Debug package of xserver-xorg-input-evdev-multitouch
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..4cf9803
--- /dev/null
@@ -0,0 +1,100 @@
+This package was downloaded from
+git://anongit.freedesktop.org/git/xorg/driver/xf86-input-evdev.
+Release tarballs are available at
+http://xorg.freedesktop.org/releases/individual/driver/
+
+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 1993 by David Dawes <dawes@xfree86.org>
+Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+Copyright 1994-2002 by The XFree86 Project, Inc.
+Copyright 2002 by Paul Elliott
+
+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 the authors
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  The authors make 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 Adam Jackson.
+
+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
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ADAM JACKSON 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.
+
diff --git a/debian/local/10-x11-evdev.fdi b/debian/local/10-x11-evdev.fdi
new file mode 100644 (file)
index 0000000..a7fe8cc
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<deviceinfo version="0.2">
+  <device>
+    <match key="info.capabilities" contains="input.mouse">
+      <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
+             string="Linux">
+        <merge key="input.x11_driver" type="string">evdev</merge>
+      </match>
+    </match>
+
+    <match key="info.capabilities" contains="input.keys">
+      <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
+             string="Linux">
+        <merge key="input.x11_driver" type="string">evdev</merge>
+      </match>
+    </match>
+  </device>
+</deviceinfo>
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..0df75f7
--- /dev/null
@@ -0,0 +1,110 @@
+#!/usr/bin/make -f
+# debian/rules for the Debian xserver-xorg-input-evdev-multitouch package.
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>
+# Copyright © 2005 Daniel Stone <daniel@fooishbar.org>
+# Copyright © 2005 David Nusinow <dnusinow@debian.org>
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+include debian/xsfbs/xsfbs.mk
+
+CFLAGS = -Wall -g -D_F_IGNORE_TSP_RESOLUTION_
+CFLAGS += -D_F_GESTURE_EXTENSION_
+#CFLAGS += -D_DEBUG_MT_SEQUENCE_
+LDFLAGS +=  -Wl,--hash-style=both -Wl,--as-needed
+ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+else
+       CFLAGS += -O2
+endif
+ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+       NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+       MAKEFLAGS += -j$(NUMJOBS)
+endif
+
+DEB_HOST_ARCH      ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+DEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+       confflags += --build=$(DEB_HOST_GNU_TYPE)
+else
+       confflags += --build=$(DEB_HOST_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+#      confflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+endif
+
+# kbd_drv.a isn't phenomenally useful; kbd_drv.so more so
+confflags += --disable-static
+
+#configure: $(STAMP_DIR)/patch
+configure:
+       autoreconf -vfi
+       #./autogen.sh
+
+obj-$(DEB_BUILD_GNU_TYPE)/config.status: configure
+       mkdir -p obj-$(DEB_BUILD_GNU_TYPE)
+       cd obj-$(DEB_BUILD_GNU_TYPE) && \
+       ../configure --prefix=/usr --mandir=\$${prefix}/share/man \
+                    --infodir=\$${prefix}/share/info $(confflags) \
+                    CFLAGS="$(CFLAGS)" \
+                    LDFLAGS="$(LDFLAGS)" 
+
+build: build-stamp
+build-stamp: obj-$(DEB_BUILD_GNU_TYPE)/config.status
+       dh_testdir
+       cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE)
+       >$@
+
+clean: xsfclean
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp
+
+       rm -f config.cache config.log config.status
+       rm -f */config.cache */config.log */config.status
+       rm -f conftest* */conftest*
+       rm -rf autom4te.cache */autom4te.cache
+       rm -rf obj-*
+       rm -f $$(find -name Makefile.in)
+       rm -f compile config.guess config.sub configure depcomp install-sh
+       rm -f ltmain.sh missing INSTALL aclocal.m4 ylwrap mkinstalldirs config.h.in
+
+       dh_clean
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+
+       cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+# Build architecture-dependent files here.
+binary-arch: build install serverabi
+       dh_testdir
+       dh_testroot
+
+       dh_installdocs
+       dh_installchangelogs ChangeLog
+       dh_install --sourcedir=debian/tmp --list-missing  --exclude=usr/share/man/man4
+       #dh_install --sourcedir=debian/tmp --list-missing --exclude=evdev_drv.la --exclude=usr/share/man/man4
+#      install -d debian/xserver-xorg-input-evdev/usr/share/hal/fdi/policy/20thirdparty
+#      install -m 644 debian/local/10-x11-evdev.fdi debian/xserver-xorg-input-evdev/usr/share/hal/fdi/policy/20thirdparty/
+       dh_installman
+       dh_link
+       dh_strip --dbg-package=xserver-xorg-input-evdev-multitouch-dbg
+       dh_compress
+       dh_fixperms
+       dh_installdeb
+#      dh_shlibdeps -- --warnings=6
+       dh_shlibdeps --
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+# Build architecture-independent files here.
+binary-indep: build install
+# Nothing to do
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/watch b/debian/watch
new file mode 100644 (file)
index 0000000..16cd015
--- /dev/null
@@ -0,0 +1,2 @@
+version=3
+http://xorg.freedesktop.org/releases/individual/driver/ xf86-input-evdev-(.*)\.tar\.gz
diff --git a/debian/xserver-xorg-input-evdev-multitouch.install b/debian/xserver-xorg-input-evdev-multitouch.install
new file mode 100644 (file)
index 0000000..1002d70
--- /dev/null
@@ -0,0 +1,2 @@
+usr/lib/xorg/modules/input/*.so
+usr/lib/xorg/modules/input/*.la
diff --git a/debian/xserver-xorg-input-evdev-multitouch.links b/debian/xserver-xorg-input-evdev-multitouch.links
new file mode 100644 (file)
index 0000000..7b68e25
--- /dev/null
@@ -0,0 +1 @@
+usr/share/bug/xserver-xorg-core/script usr/share/bug/xserver-xorg-input-evdev-multitouch/script
diff --git a/debian/xserver-xorg-input-evdev-multitouch.manpages b/debian/xserver-xorg-input-evdev-multitouch.manpages
new file mode 100644 (file)
index 0000000..603f9bd
--- /dev/null
@@ -0,0 +1 @@
+debian/tmp/usr/share/man/man4/*
diff --git a/debian/xsfbs/repack.sh b/debian/xsfbs/repack.sh
new file mode 100644 (file)
index 0000000..5935cc9
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+if ! [ -d debian/prune ]; then
+       exit 0
+fi
+
+if [ "x$1" != x--upstream-version ]; then
+       exit 1
+fi
+
+version="$2"
+filename="$3"
+
+if [ -z "$version" ] || ! [ -f "$filename" ]; then
+       exit 1
+fi
+
+dir="$(pwd)"
+tempdir="$(mktemp -d)"
+
+cd "$tempdir"
+tar xf "$dir/$filename"
+cat "$dir"/debian/prune/* | while read file; do rm -f */$file; done
+
+tar czf "$dir/$filename" *
+cd "$dir"
+rm -rf "$tempdir"
+echo "Done pruning upstream tarball"
+
+exit 0
diff --git a/debian/xsfbs/xsfbs.mk b/debian/xsfbs/xsfbs.mk
new file mode 100644 (file)
index 0000000..f0f8953
--- /dev/null
@@ -0,0 +1,293 @@
+#!/usr/bin/make -f
+
+# Debian X Strike Force Build System (XSFBS): Make portion
+
+# Copyright 1996 Stephen Early
+# Copyright 1997 Mark Eichin
+# Copyright 1998-2005, 2007 Branden Robinson
+# Copyright 2005 David Nusinow
+#
+# Licensed under the GNU General Public License, version 2.  See the file
+# /usr/share/common-licenses/GPL or <http://www.gnu.org/copyleft/gpl.txt>.
+
+# Originally by Stephen Early <sde1000@debian.org>
+# Modified by Mark W. Eichin <eichin@kitten.gen.ma.us>
+# Modified by Adam Heath <doogie@debian.org>
+# Modified by Branden Robinson <branden@debian.org>
+# Modified by Fabio Massimo Di Nitto <fabbione@fabbione.net>
+# Modified by David Nusinow <dnusinow@debian.org>
+# Acknowledgements to Manoj Srivastava.
+
+# Pass $(DH_OPTIONS) into the environment for debhelper's benefit.
+export DH_OPTIONS
+
+# force quilt to not use ~/.quiltrc and to use debian/patches
+QUILT = QUILT_PATCHES=debian/patches quilt --quiltrc /dev/null
+
+# Set up parameters for the upstream build environment.
+
+# Determine (source) package name from Debian changelog.
+SOURCE_NAME:=$(shell dpkg-parsechangelog -ldebian/changelog \
+                        | grep '^Source:' | awk '{print $$2}')
+
+# Determine package version from Debian changelog.
+SOURCE_VERSION:=$(shell dpkg-parsechangelog -ldebian/changelog \
+                        | grep '^Version:' | awk '{print $$2}')
+
+# Determine upstream version number.
+UPSTREAM_VERSION:=$(shell echo $(SOURCE_VERSION) | sed 's/-.*//')
+
+# Determine the source version without the epoch for make-orig-tar-gz
+NO_EPOCH_VER:=$(shell echo $(UPSTREAM_VERSION) | sed 's/^.://')
+
+# Figure out who's building this package.
+BUILDER:=$(shell echo $${DEBEMAIL:-$${EMAIL:-$$(echo $$LOGNAME@$$(cat /etc/mailname 2>/dev/null))}})
+
+# Find out if this is an official build; an official build has nothing but
+# digits, dots, and/or the codename of a release in the Debian part of the
+# version number.  Anything else indicates an unofficial build.
+OFFICIAL_BUILD:=$(shell VERSION=$(SOURCE_VERSION); if ! expr "$$(echo $${VERSION\#\#*-} | sed 's/\(woody\|sarge\|etch\|lenny\)//g')" : ".*[^0-9.].*" >/dev/null 2>&1; then echo yes; fi)
+
+# Set up parameters for the Debian build environment.
+
+# Determine our architecture.
+BUILD_ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH)
+# Work around some old-time dpkg braindamage.
+BUILD_ARCH:=$(subst i486,i386,$(BUILD_ARCH))
+# The DEB_HOST_ARCH variable may be set per the Debian cross-compilation policy.
+ifdef DEB_HOST_ARCH
+ ARCH:=$(DEB_HOST_ARCH)
+else
+ # dpkg-cross sets the ARCH environment variable; if set, use it.
+ ifdef ARCH
+  ARCH:=$(ARCH)
+ else
+  ARCH:=$(BUILD_ARCH)
+ endif
+endif
+
+# $(STAMP_DIR) houses stamp files for complex targets.
+STAMP_DIR:=stampdir
+
+# $(DEBTREEDIR) is where all install rules are told (via $(DESTDIR)) to place
+# their files.
+DEBTREEDIR:=$(CURDIR)/debian/tmp
+
+# All "important" targets have four lines:
+#   1) A target name that is invoked by a package-building tool or the user.
+#      This consists of a dependency on a "$(STAMP_DIR)/"-prefixed counterpart.
+#   2) A line delcaring 1) as a phony target (".PHONY:").
+#   3) A "$(STAMP_DIR)/"-prefixed target which does the actual work, and may
+#   depend on other targets.
+#   4) A line declaring 3) as a member of the $(stampdir_targets) variable; the
+#   "$(STAMP_DIR)/" prefix is omitted.
+#
+# This indirection is needed so that the "stamp" files that signify when a rule
+# is done can be located in a separate "stampdir".  Recall that make has no way
+# to know when a goal has been met for a phony target (like "build" or
+# "install").
+#
+# At the end of each "$(STAMP_DIR)/" target, be sure to run the command ">$@"
+# so that the target will not be run again.  Removing the file will make Make
+# run the target over.
+
+# All phony targets should be declared as dependencies of .PHONY, even if they
+# do not have "($STAMP_DIR)/"-prefixed counterparts.
+
+# Define a harmless default rule to keep things from going nuts by accident.
+.PHONY: default
+default:
+
+# Set up the $(STAMP_DIR) directory.
+.PHONY: stampdir
+stampdir_targets+=stampdir
+stampdir: $(STAMP_DIR)/stampdir
+$(STAMP_DIR)/stampdir:
+       mkdir $(STAMP_DIR)
+       >$@
+
+# Set up the package build directory as quilt expects to find it.
+.PHONY: prepare
+stampdir_targets+=prepare
+prepare: $(STAMP_DIR)/prepare
+$(STAMP_DIR)/prepare: $(STAMP_DIR)/log $(STAMP_DIR)/genscripts
+       >$@
+
+.PHONY: log
+stampdir_targets+=log
+log: $(STAMP_DIR)/log
+$(STAMP_DIR)/log: $(STAMP_DIR)/stampdir
+       mkdir -p $(STAMP_DIR)/log
+
+# Apply all patches to the upstream source.
+.PHONY: patch
+stampdir_targets+=patch
+patch: $(STAMP_DIR)/patch
+$(STAMP_DIR)/patch: $(STAMP_DIR)/prepare
+       if ! [ `which quilt` ]; then \
+               echo "Couldn't find quilt. Please install it or add it to the build-depends for this package."; \
+               exit 1; \
+       fi; \
+       if $(QUILT) next >/dev/null 2>&1; then \
+         echo -n "Applying patches..."; \
+         if $(QUILT) push -a -v >$(STAMP_DIR)/log/patch 2>&1; then \
+           cat $(STAMP_DIR)/log/patch; \
+           echo "successful."; \
+         else \
+           cat $(STAMP_DIR)/log/patch; \
+           echo "failed! (check $(STAMP_DIR)/log/patch for details)"; \
+           exit 1; \
+         fi; \
+       else \
+         echo "No patches to apply"; \
+       fi; \
+       >$@
+
+# Revert all patches to the upstream source.
+.PHONY: unpatch
+unpatch: $(STAMP_DIR)/log
+       rm -f $(STAMP_DIR)/patch
+       @echo -n "Unapplying patches..."; \
+       if $(QUILT) applied >/dev/null 2>/dev/null; then \
+         if $(QUILT) pop -a -v >$(STAMP_DIR)/log/unpatch 2>&1; then \
+           cat $(STAMP_DIR)/log/unpatch; \
+           echo "successful."; \
+         else \
+           cat $(STAMP_DIR)/log/unpatch; \
+           echo "failed! (check $(STAMP_DIR)/log/unpatch for details)"; \
+           exit 1; \
+         fi; \
+       else \
+         echo "nothing to do."; \
+       fi
+
+# Clean the generated maintainer scripts.
+.PHONY: cleanscripts
+cleanscripts:
+       rm -f $(STAMP_DIR)/genscripts
+       rm -f debian/*.config \
+             debian/*.postinst \
+             debian/*.postrm \
+             debian/*.preinst \
+             debian/*.prerm
+
+# Clean the package build tree.
+.PHONY: xsfclean
+xsfclean: cleanscripts unpatch
+       dh_testdir
+       rm -rf .pc
+       rm -rf $(STAMP_DIR) $(SOURCE_DIR)
+       rm -rf imports
+       dh_clean debian/shlibs.local \
+                debian/po/pothead
+
+# Generate the debconf templates POT file header.
+debian/po/pothead: debian/po/pothead.in
+       sed -e 's/SOURCE_VERSION/$(SOURCE_VERSION)/' \
+         -e 's/DATE/$(shell date "+%F %X%z"/)' <$< >$@
+
+# Update POT and PO files.
+.PHONY: updatepo
+updatepo: debian/po/pothead
+       debian/scripts/debconf-updatepo --pot-header=pothead --verbose
+
+# Remove files from the upstream source tree that we don't need, or which have
+# licensing problems.  It must be run before creating the .orig.tar.gz.
+#
+# Note: This rule is for Debian package maintainers' convenience, and is not
+# needed for conventional build scenarios.
+.PHONY: prune-upstream-tree
+prune-upstream-tree:
+       # Ensure we're in the correct directory.
+       dh_testdir
+       grep -rvh '^#' debian/prune/ | xargs --no-run-if-empty rm -rf
+
+# Verify that there are no offsets or fuzz in the patches we apply.
+#
+# Note: This rule is for Debian package maintainers' convenience, and is not
+# needed for conventional build scenarios.
+.PHONY: patch-audit
+patch-audit: prepare unpatch
+       @echo -n "Auditing patches..."; \
+       >$(STAMP_DIR)/log/patch; \
+       FUZZY=; \
+       while [ -n "$$($(QUILT) next)" ]; do \
+         RESULT=$$($(QUILT) push -v | tee -a $(STAMP_DIR)/log/patch | grep ^Hunk | sed 's/^Hunk.*\(succeeded\|FAILED\).*/\1/');\
+         case "$$RESULT" in \
+           succeeded) \
+             echo "fuzzy patch: $$($(QUILT) top)" \
+               | tee -a $(STAMP_DIR)/log/$$($(QUILT) top); \
+             FUZZY=yes; \
+             ;; \
+           FAILED) \
+             echo "broken patch: $$($(QUILT) next)" \
+               | tee -a $(STAMP_DIR)/log/$$($(QUILT) next); \
+             exit 1; \
+             ;; \
+         esac; \
+       done; \
+       if [ -n "$$FUZZY" ]; then \
+         echo "there were fuzzy patches; please fix."; \
+         exit 1; \
+       else \
+         echo "done."; \
+       fi
+
+# Generate the maintainer scripts.
+.PHONY: genscripts
+stampdir_targets+=genscripts
+genscripts: $(STAMP_DIR)/genscripts
+$(STAMP_DIR)/genscripts: $(STAMP_DIR)/stampdir
+       for FILE in debian/*.config.in \
+                   debian/*.postinst.in \
+                   debian/*.postrm.in \
+                   debian/*.preinst.in \
+                   debian/*.prerm.in; do \
+         if [ -e "$$FILE" ]; then \
+           MAINTSCRIPT=$$(echo $$FILE | sed 's/.in$$//'); \
+           sed -n '1,/^#INCLUDE_SHELL_LIB#$$/p' <$$FILE \
+             | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >$$MAINTSCRIPT.tmp; \
+           cat debian/xsfbs/xsfbs.sh >>$$MAINTSCRIPT.tmp; \
+           sed -n '/^#INCLUDE_SHELL_LIB#$$/,$$p' <$$FILE \
+             | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >>$$MAINTSCRIPT.tmp; \
+           sed -e 's/@SOURCE_VERSION@/$(SOURCE_VERSION)/' \
+               -e 's/@OFFICIAL_BUILD@/$(OFFICIAL_BUILD)/' \
+               -e 's/@DEFAULT_DCRESOLUTIONS@/$(DEFAULT_DCRESOLUTIONS)/' \
+             <$$MAINTSCRIPT.tmp >$$MAINTSCRIPT; \
+           rm $$MAINTSCRIPT.tmp; \
+         fi; \
+       done
+       # Validate syntax of generated shell scripts.
+       #sh debian/scripts/validate-posix-sh debian/*.config \
+       #                                    debian/*.postinst \
+       #                                    debian/*.postrm \
+       #                                    debian/*.preinst \
+       #                                    debian/*.prerm
+       >$@
+
+# Generate the shlibs.local file.
+debian/shlibs.local:
+       cat debian/*.shlibs >$@
+
+SERVERMINVERS = $(shell cat /usr/share/xserver-xorg/serverminver 2>/dev/null)
+VIDEOABI = $(shell cat /usr/share/xserver-xorg/videoabiver 2>/dev/null)
+INPUTABI = $(shell cat /usr/share/xserver-xorg/inputabiver 2>/dev/null)
+SERVER_DEPENDS = xserver-xorg-core (>= $(SERVERMINVERS))
+VIDDRIVER_PROVIDES = xserver-xorg-video-$(VIDEOABI)
+INPDRIVER_PROVIDES = xserver-xorg-input-$(INPUTABI)
+ifeq ($(PACKAGE),)
+PACKAGE=$(shell awk '/^Package:/ { print $$2; exit }' < debian/control)
+endif
+
+.PHONY: serverabi
+serverabi: install
+ifeq ($(SERVERMINVERS),)
+       @echo error: xserver-xorg-dev needs to be installed
+       @exit 1
+else
+       echo "xserver:Depends=$(SERVER_DEPENDS)" >> debian/$(PACKAGE).substvars
+       echo "xviddriver:Provides=$(VIDDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars
+       echo "xinpdriver:Provides=$(INPDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars
+endif
+
+# vim:set noet ai sts=8 sw=8 tw=0:
diff --git a/debian/xsfbs/xsfbs.sh b/debian/xsfbs/xsfbs.sh
new file mode 100644 (file)
index 0000000..781826f
--- /dev/null
@@ -0,0 +1,853 @@
+# $Id$
+
+# This is the X Strike Force shell library for X Window System package
+# maintainer scripts.  It serves to define shell functions commonly used by
+# such packages, and performs some error checking necessary for proper operation
+# of those functions.  By itself, it does not "do" much; the maintainer scripts
+# invoke the functions defined here to accomplish package installation and
+# removal tasks.
+
+# If you are reading this within a Debian package maintainer script (e.g.,
+# /var/lib/dpkg)info/PACKAGE.{config,preinst,postinst,prerm,postrm}), you can
+# skip past this library by scanning forward in this file to the string
+# "GOBSTOPPER".
+
+SOURCE_VERSION=@SOURCE_VERSION@
+OFFICIAL_BUILD=@OFFICIAL_BUILD@
+
+# Use special abnormal exit codes so that problems with this library are more
+# easily tracked down.
+SHELL_LIB_INTERNAL_ERROR=86
+SHELL_LIB_THROWN_ERROR=74
+SHELL_LIB_USAGE_ERROR=99
+
+# old -> new variable names
+if [ -z "$DEBUG_XORG_PACKAGE" ] && [ -n "$DEBUG_XFREE86_PACKAGE" ]; then
+  DEBUG_XORG_PACKAGE="$DEBUG_XFREE86_PACKAGE"
+fi
+if [ -z "$DEBUG_XORG_DEBCONF" ] && [ -n "$DEBUG_XFREE86_DEBCONF" ]; then
+  DEBUG_XORG_DEBCONF="$DEBUG_XFREE86_DEBCONF"
+fi
+
+# initial sanity checks
+if [ -z "$THIS_PACKAGE" ]; then
+  cat >&2 <<EOF
+Error: package maintainer script attempted to use shell library without
+definining \$THIS_PACKAGE shell variable.  Please report the package name,
+version, and the text of this error message to the Debian Bug Tracking System.
+Visit <http://www.debian.org/Bugs/Reporting> on the World Wide Web for
+instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the
+"doc-debian" package, or install the "reportbug" package and use the command of
+the same name to file a report against version $SOURCE_VERSION of this package.
+EOF
+  exit $SHELL_LIB_USAGE_ERROR
+fi
+
+if [ -z "$THIS_SCRIPT" ]; then
+  cat >&2 <<EOF
+Error: package maintainer script attempted to use shell library without
+definining \$THIS_SCRIPT shell variable.  Please report the package name,
+version, and the text of this error message to the Debian Bug Tracking System.
+Visit <http://www.debian.org/Bugs/Reporting> on the World Wide Web for
+instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the
+"doc-debian" package, or install the "reportbug" package and use the command of
+the same name to file a report against version $SOURCE_VERSION of the
+"$THIS_PACKAGE" package.
+EOF
+  exit $SHELL_LIB_USAGE_ERROR
+fi
+
+if [ "$1" = "reconfigure" ] || [ -n "$DEBCONF_RECONFIGURE" ]; then
+  RECONFIGURE="true"
+else
+  RECONFIGURE=
+fi
+
+if ([ "$1" = "install" ] || [ "$1" = "configure" ]) && [ -z "$2" ]; then
+  FIRSTINST="yes"
+fi
+
+if [ -z "$RECONFIGURE" ] && [ -z "$FIRSTINST" ]; then
+  UPGRADE="yes"
+fi
+
+trap "message;\
+      message \"Received signal.  Aborting $THIS_PACKAGE package $THIS_SCRIPT script.\";\
+      message;\
+      exit 1" HUP INT QUIT TERM
+
+reject_nondigits () {
+  # syntax: reject_nondigits [ operand ... ]
+  #
+  # scan operands (typically shell variables whose values cannot be trusted) for
+  # characters other than decimal digits and barf if any are found
+  while [ -n "$1" ]; do
+    # does the operand contain anything but digits?
+    if ! expr "$1" : "[[:digit:]]\+$" > /dev/null 2>&1; then
+      # can't use die(), because it wraps message() which wraps this function
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_nondigits() encountered" \
+           "possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+    shift
+  done
+}
+
+reject_whitespace () {
+  # syntax: reject_whitespace [ operand ]
+  #
+  # scan operand (typically a shell variable whose value cannot be trusted) for
+  # whitespace characters and barf if any are found
+  if [ -n "$1" ]; then
+    # does the operand contain any whitespace?
+    if expr "$1" : "[[:space:]]" > /dev/null 2>&1; then
+      # can't use die(), because I want to avoid forward references
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_whitespace() encountered" \
+           "possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+  fi
+}
+
+reject_unlikely_path_chars () {
+  # syntax: reject_unlikely_path_chars [ operand ... ]
+  #
+  # scan operands (typically shell variables whose values cannot be trusted) for
+  # characters unlikely to be seen in a path and which the shell might
+  # interpret and barf if any are found
+  while [ -n "$1" ]; do
+    # does the operand contain any funny characters?
+    if expr "$1" : '.*[!$&()*;<>?|].*' > /dev/null 2>&1; then
+      # can't use die(), because I want to avoid forward references
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_unlikely_path_chars()" \
+           "encountered possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+    shift
+  done
+}
+
+# Query the terminal to establish a default number of columns to use for
+# displaying messages to the user.  This is used only as a fallback in the
+# event the COLUMNS variable is not set.  ($COLUMNS can react to SIGWINCH while
+# the script is running, and this cannot, only being calculated once.)
+DEFCOLUMNS=$(stty size 2> /dev/null | awk '{print $2}') || true
+if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" > /dev/null 2>&1; then
+  DEFCOLUMNS=80
+fi
+
+message () {
+  # pretty-print messages of arbitrary length
+  reject_nondigits "$COLUMNS"
+  echo "$*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS} >&2
+}
+
+observe () {
+  # syntax: observe message ...
+  #
+  # issue observational message suitable for logging someday when support for
+  # it exists in dpkg
+  if [ -n "$DEBUG_XORG_PACKAGE" ]; then
+    message "$THIS_PACKAGE $THIS_SCRIPT note: $*"
+  fi
+}
+
+warn () {
+  # syntax: warn message ...
+  #
+  # issue warning message suitable for logging someday when support for
+  # it exists in dpkg; also send to standard error
+  message "$THIS_PACKAGE $THIS_SCRIPT warning: $*"
+}
+
+die () {
+  # syntax: die message ...
+  #
+  # exit script with error message
+  message "$THIS_PACKAGE $THIS_SCRIPT error: $*"
+  exit $SHELL_LIB_THROWN_ERROR
+}
+
+internal_error () {
+  # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message
+  message "internal error: $*"
+  if [ -n "$OFFICIAL_BUILD" ]; then
+    message "Please report a bug in the $THIS_SCRIPT script of the" \
+            "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \
+            "Tracking System.  Include all messages above that mention the" \
+            "$THIS_PACKAGE package.  Visit " \
+            "<http://www.debian.org/Bugs/Reporting> on the World Wide Web for" \
+            "instructions, read the file" \
+            "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \
+            "package, or install the reportbug package and use the command of" \
+            "the same name to file a report."
+  fi
+  exit $SHELL_LIB_INTERNAL_ERROR
+}
+
+usage_error () {
+  message "usage error: $*"
+  message "Please report a bug in the $THIS_SCRIPT script of the" \
+          "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \
+          "Tracking System.  Include all messages above that mention the" \
+          "$THIS_PACKAGE package.  Visit " \
+          "<http://www.debian.org/Bugs/Reporting> on the World Wide Web for" \
+          "instructions, read the file" \
+          "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \
+          "package, or install the reportbug package and use the command of" \
+          "the same name to file a report."
+  exit $SHELL_LIB_USAGE_ERROR
+}
+
+
+maplink () {
+  # returns what symlink should point to; i.e., what the "sane" answer is
+  # Keep this in sync with the debian/*.links files.
+  # This is only needed for symlinks to directories.
+  #
+  # XXX: Most of these look wrong in the X11R7 world and need to be fixed.
+  # If we've stopped using this function, fixing it might enable us to re-enable
+  # it again and catch more errors.
+  case "$1" in
+    /etc/X11/xkb/compiled) echo /var/lib/xkb ;;
+    /etc/X11/xkb/xkbcomp) echo /usr/X11R6/bin/xkbcomp ;;
+    /usr/X11R6/lib/X11/app-defaults) echo /etc/X11/app-defaults ;;
+    /usr/X11R6/lib/X11/fs) echo /etc/X11/fs ;;
+    /usr/X11R6/lib/X11/lbxproxy) echo /etc/X11/lbxproxy ;;
+    /usr/X11R6/lib/X11/proxymngr) echo /etc/X11/proxymngr ;;
+    /usr/X11R6/lib/X11/rstart) echo /etc/X11/rstart ;;
+    /usr/X11R6/lib/X11/twm) echo /etc/X11/twm ;;
+    /usr/X11R6/lib/X11/xdm) echo /etc/X11/xdm ;;
+    /usr/X11R6/lib/X11/xinit) echo /etc/X11/xinit ;;
+    /usr/X11R6/lib/X11/xkb) echo /etc/X11/xkb ;;
+    /usr/X11R6/lib/X11/xserver) echo /etc/X11/xserver ;;
+    /usr/X11R6/lib/X11/xsm) echo /etc/X11/xsm ;;
+    /usr/bin/X11) echo ../X11R6/bin ;;
+    /usr/bin/rstartd) echo ../X11R6/bin/rstartd ;;
+    /usr/include/X11) echo ../X11R6/include/X11 ;;
+    /usr/lib/X11) echo ../X11R6/lib/X11 ;;
+    *) internal_error "maplink() called with unknown path \"$1\"" ;;
+  esac
+}
+
+analyze_path () {
+  # given a supplied set of pathnames, break each one up by directory and do an
+  # ls -dl on each component, cumulatively; i.e.
+  # analyze_path /usr/X11R6/bin -> ls -dl /usr /usr/X11R6 /usr/X11R6/bin
+  # Thanks to Randolph Chung for this clever hack.
+
+  local f g
+
+  while [ -n "$1" ]; do
+    reject_whitespace "$1"
+    g=
+    message "Analyzing $1:"
+    for f in $(echo "$1" | tr / \  ); do
+      if [ -e /$g$f ]; then
+        ls -dl /$g$f /$g$f.dpkg-* 2> /dev/null || true
+        g=$g$f/
+      else
+        message "/$g$f: nonexistent; directory contents of /$g:"
+        ls -l /$g
+        break
+      fi
+    done
+    shift
+  done
+}
+
+find_culprits () {
+  local f p dpkg_info_dir possible_culprits smoking_guns bad_packages package \
+    msg
+
+  reject_whitespace "$1"
+  message "Searching for overlapping packages..."
+  dpkg_info_dir=/var/lib/dpkg/info
+  if [ -d $dpkg_info_dir ]; then
+    if [ "$(echo $dpkg_info_dir/*.list)" != "$dpkg_info_dir/*.list" ]; then
+      possible_culprits=$(ls -1 $dpkg_info_dir/*.list | egrep -v \
+        "(xbase-clients|x11-common|xfs|xlibs)")
+      if [ -n "$possible_culprits" ]; then
+        smoking_guns=$(grep -l "$1" $possible_culprits || true)
+        if [ -n "$smoking_guns" ]; then
+          bad_packages=$(printf "\\n")
+          for f in $smoking_guns; do
+            # too bad you can't nest parameter expansion voodoo
+            p=${f%*.list}      # strip off the trailing ".list"
+            package=${p##*/}   # strip off the directories
+            bad_packages=$(printf "%s\n%s" "$bad_packages" "$package")
+          done
+          msg=$(cat <<EOF
+The following packages appear to have file overlaps with the X.Org packages;
+these packages are either very old, or in violation of Debian Policy.  Try
+upgrading each of these packages to the latest available version if possible:
+for example, with the command "apt-get install".  If no newer version of a
+package is available, you will have to remove it; for example, with the command
+"apt-get remove".  If even the latest available version of the package has
+this file overlap, please file a bug against that package with the Debian Bug
+Tracking System.  You may want to refer the package maintainer to section 12.8
+of the Debian Policy manual.
+EOF
+)
+          message "$msg"
+          message "The overlapping packages are: $bad_packages"
+        else
+          message "no overlaps found."
+        fi
+      fi
+    else
+      message "cannot search; no matches for $dpkg_info_dir/*.list."
+    fi
+  else
+    message "cannot search; $dpkg_info_dir does not exist."
+  fi
+}
+
+check_symlink () {
+  # syntax: check_symlink symlink
+  #
+  # See if specified symlink points where it is supposed to.  Return 0 if it
+  # does, and 1 if it does not.
+  #
+  # Primarily used by check_symlinks_and_warn() and check_symlinks_and_bomb().
+
+  local symlink
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "check_symlink() called with wrong number of arguments;" \
+                "expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  symlink="$1"
+
+  if [ "$(maplink "$symlink")" = "$(readlink "$symlink")" ]; then
+    return 0
+  else
+    return 1
+  fi
+}
+
+check_symlinks_and_warn () {
+  # syntax: check_symlinks_and_warn symlink ...
+  #
+  # For each argument, check for symlink sanity, and warn if it isn't sane.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install".
+
+  local errmsg symlink
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "check_symlinks_and_warn() called with wrong number of" \
+                "arguments; expected at least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  while [ -n "$1" ]; do
+    symlink="$1"
+    if [ -L "$symlink" ]; then
+      if ! check_symlink "$symlink"; then
+        observe "$symlink symbolic link points to wrong location" \
+                "$(readlink "$symlink"); removing"
+        rm "$symlink"
+      fi
+    elif [ -e "$symlink" ]; then
+      errmsg="$symlink exists and is not a symbolic link; this package cannot"
+      errmsg="$errmsg be installed until this"
+      if [ -f "$symlink" ]; then
+        errmsg="$errmsg file"
+      elif [ -d "$symlink" ]; then
+        errmsg="$errmsg directory"
+      else
+        errmsg="$errmsg thing"
+      fi
+      errmsg="$errmsg is removed"
+      die "$errmsg"
+    fi
+    shift
+  done
+}
+
+check_symlinks_and_bomb () {
+  # syntax: check_symlinks_and_bomb symlink ...
+  #
+  # For each argument, check for symlink sanity, and bomb if it isn't sane.
+  #
+  # Call this function from a postinst script.
+
+  local problem symlink
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "check_symlinks_and_bomb() called with wrong number of"
+                "arguments; expected at least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  while [ -n "$1" ]; do
+    problem=
+    symlink="$1"
+    if [ -L "$symlink" ]; then
+      if ! check_symlink "$symlink"; then
+        problem=yes
+        warn "$symlink symbolic link points to wrong location" \
+             "$(readlink "$symlink")"
+      fi
+    elif [ -e "$symlink" ]; then
+      problem=yes
+      warn "$symlink is not a symbolic link"
+    else
+      problem=yes
+      warn "$symlink symbolic link does not exist"
+    fi
+    if [ -n "$problem" ]; then
+      analyze_path "$symlink" "$(readlink "$symlink")"
+      find_culprits "$symlink"
+      die "bad symbolic links on system"
+    fi
+    shift
+  done
+}
+
+font_update () {
+  # run $UPDATECMDS in $FONTDIRS
+
+  local dir cmd shortcmd x_font_dir_prefix
+
+  x_font_dir_prefix="/usr/share/fonts/X11"
+
+  if [ -z "$UPDATECMDS" ]; then
+    usage_error "font_update() called but \$UPDATECMDS not set"
+  fi
+  if [ -z "$FONTDIRS" ]; then
+    usage_error "font_update() called but \$FONTDIRS not set"
+  fi
+
+  reject_unlikely_path_chars "$UPDATECMDS"
+  reject_unlikely_path_chars "$FONTDIRS"
+
+  for dir in $FONTDIRS; do
+    if [ -d "$x_font_dir_prefix/$dir" ]; then
+      for cmd in $UPDATECMDS; do
+        if which "$cmd" > /dev/null 2>&1; then
+          shortcmd=${cmd##*/}
+          observe "running $shortcmd in $dir font directory"
+         cmd_opts=
+          if [ "$shortcmd" = "update-fonts-alias" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          if [ "$shortcmd" = "update-fonts-dir" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          if [ "$shortcmd" = "update-fonts-scale" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          $cmd $cmd_opts $dir || warn "$cmd $cmd_opts $dir" \
+                              "failed; font directory data may not" \
+                              "be up to date"
+        else
+          warn "$cmd not found; not updating corresponding $dir font" \
+               "directory data"
+        fi
+      done
+    else
+      warn "$dir is not a directory; not updating font directory data"
+    fi
+  done
+}
+
+remove_conffile_prepare () {
+  # syntax: remove_conffile_prepare filename official_md5sum ...
+  #
+  # Check a conffile "filename" against a list of canonical MD5 checksums.
+  # If the file's current MD5 checksum matches one of the "official_md5sum"
+  # operands provided, then prepare the conffile for removal from the system.
+  # We defer actual deletion until the package is configured so that we can
+  # roll this operation back if package installation fails.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install" and verify $2 to ensure the package is being upgraded from a
+  # version (or installed over a version removed-but-not-purged) prior to the
+  # one in which the conffile was obsoleted.
+
+  local conffile current_checksum
+
+  # validate arguments
+  if [ $# -lt 2 ]; then
+    usage_error "remove_conffile_prepare() called with wrong number of" \
+                "arguments; expected at least 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+  shift
+
+  # does the conffile even exist?
+  if [ -e "$conffile" ]; then
+    # calculate its checksum
+    current_checksum=$(md5sum < "$conffile" | sed 's/[[:space:]].*//')
+    # compare it to each supplied checksum
+    while [ -n "$1" ]; do
+      if [ "$current_checksum" = "$1" ]; then
+        # we found a match; move the confffile and stop looking
+        observe "preparing obsolete conffile $conffile for removal"
+        mv "$conffile" "$conffile.$THIS_PACKAGE-tmp"
+        break
+      fi
+      shift
+    done
+  fi
+}
+
+remove_conffile_lookup () {
+  # syntax: remove_conffile_lookup package filename
+  #
+  # Lookup the md5sum of a conffile in dpkg's database, and prepare for removal
+  # if it matches the actual file's md5sum.
+  #
+  # Call this function when you would call remove_conffile_prepare but only
+  # want to check against dpkg's status database instead of known checksums.
+
+  local package conffile old_md5sum
+
+  # validate arguments
+  if [ $# -ne 2 ]; then
+    usage_error "remove_conffile_lookup() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  package="$1"
+  conffile="$2"
+
+  if ! [ -e "$conffile" ]; then
+    return
+  fi
+  old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$package" | \
+    awk '{ if (match($0, "^ '"$conffile"' ")) print $2}')"
+  if [ -n "$old_md5sum" ]; then
+    remove_conffile_prepare "$conffile" "$old_md5sum"
+  fi
+}
+
+remove_conffile_commit () {
+  # syntax: remove_conffile_commit filename
+  #
+  # Complete the removal of a conffile "filename" that has become obsolete.
+  #
+  # Call this function from a postinst script after having used
+  # remove_conffile_prepare() in the preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "remove_conffile_commit() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  # if the temporary file created by remove_conffile_prepare() exists, remove it
+  if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then
+    observe "committing removal of obsolete conffile $conffile"
+    rm "$conffile.$THIS_PACKAGE-tmp"
+  fi
+}
+
+remove_conffile_rollback () {
+  # syntax: remove_conffile_rollback filename
+  #
+  # Roll back the removal of a conffile "filename".
+  #
+  # Call this function from a postrm script in the event $1 is "abort-upgrade"
+  # or "abort-install" is  after having used remove_conffile_prepare() in the
+  # preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "remove_conffile_rollback() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  # if the temporary file created by remove_conffile_prepare() exists, move it
+  # back
+  if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then
+    observe "rolling back removal of obsolete conffile $conffile"
+    mv "$conffile.$THIS_PACKAGE-tmp" "$conffile"
+  fi
+}
+
+replace_conffile_with_symlink_prepare () {
+  # syntax: replace_conffile_with_symlink_prepare oldfilename newfilename \
+  # official_md5sum ...
+  #
+  # Check a conffile "oldfilename" against a list of canonical MD5 checksums.
+  # If the file's current MD5 checksum matches one of the "official_md5sum"
+  # operands provided, then prepare the conffile for removal from the system.
+  # We defer actual deletion until the package is configured so that we can
+  # roll this operation back if package installation fails. Otherwise copy it
+  # to newfilename and let dpkg handle it through conffiles mechanism.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install" and verify $2 to ensure the package is being upgraded from a
+  # version (or installed over a version removed-but-not-purged) prior to the
+  # one in which the conffile was obsoleted.
+
+  local conffile current_checksum
+
+  # validate arguments
+  if [ $# -lt 3 ]; then
+    usage_error "replace_conffile_with_symlink_prepare() called with wrong" \
+                " number of arguments; expected at least 3, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  oldconffile="$1"
+  shift
+  newconffile="$1"
+  shift
+
+  remove_conffile_prepare "$_oldconffile" "$@"
+  # If $oldconffile still exists, then md5sums didn't match.
+  # Copy it to new one.
+  if [ -f "$oldconffile" ]; then
+    cp "$oldconffile" "$newconffile"
+  fi
+
+}
+
+replace_conffile_with_symlink_commit () {
+  # syntax: replace_conffile_with_symlink_commit oldfilename
+  #
+  # Complete the removal of a conffile "oldfilename" that has been
+  # replaced by a symlink.
+  #
+  # Call this function from a postinst script after having used
+  # replace_conffile_with_symlink_prepare() in the preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "replace_conffile_with_symlink_commit() called with wrong" \
+                "number of arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  remove_conffile_commit "$conffile"
+}
+
+replace_conffile_with_symlink_rollback () {
+  # syntax: replace_conffile_with_symlink_rollback oldfilename newfilename
+  #
+  # Roll back the replacing of a conffile "oldfilename" with symlink to
+  # "newfilename".
+  #
+  # Call this function from a postrm script in the event $1 is "abort-upgrade"
+  # or "abort-install" and verify $2 to ensure the package failed to upgrade
+  # from a version (or install over a version removed-but-not-purged) prior
+  # to the one in which the conffile was obsoleted.
+  # You should have  used replace_conffile_with_symlink_prepare() in the
+  # preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 2 ]; then
+    usage_error "replace_conffile_with_symlink_rollback() called with wrong" \
+                "number of arguments; expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  oldconffile="$1"
+  newconffile="$2"
+
+  remove_conffile_rollback "$_oldconffile"
+  if [ -f "$newconffile" ]; then
+    rm "$newconffile"
+  fi
+}
+
+run () {
+  # syntax: run command [ argument ... ]
+  #
+  # Run specified command with optional arguments and report its exit status.
+  # Useful for commands whose exit status may be nonzero, but still acceptable,
+  # or commands whose failure is not fatal to us.
+  #
+  # NOTE: Do *not* use this function with db_get or db_metaget commands; in
+  # those cases the return value of the debconf command *must* be checked
+  # before the string returned by debconf is used for anything.
+
+  local retval
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "run() called with wrong number of arguments; expected at" \
+                "least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  "$@" || retval=$?
+
+  if [ ${retval:-0} -ne 0 ]; then
+    observe "command \"$*\" exited with status $retval"
+  fi
+}
+
+make_symlink_sane () {
+  # syntax: make_symlink_sane symlink target
+  #
+  # Ensure that the symbolic link symlink exists, and points to target.
+  #
+  # If symlink does not exist, create it and point it at target.
+  #
+  # If symlink exists but is not a symbolic link, back it up.
+  #
+  # If symlink exists, is a symbolic link, but points to the wrong location, fix
+  # it.
+  #
+  # If symlink exists, is a symbolic link, and already points to target, do
+  # nothing.
+  #
+  # This function wouldn't be needed if ln had an -I, --idempotent option.
+
+  # Validate arguments.
+  if [ $# -ne 2 ]; then
+    usage_error "make_symlink_sane() called with wrong number of arguments;" \
+      "expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  # We could just use the positional parameters as-is, but that makes things
+  # harder to follow.
+  local symlink target
+
+  symlink="$1"
+  target="$2"
+
+  if [ -L "$symlink" ] && [ "$(readlink "$symlink")" = "$target" ]; then
+      observe "link from $symlink to $target already exists"
+  else
+    observe "creating symbolic link from $symlink to $target"
+    mkdir -p "${target%/*}" "${symlink%/*}"
+    ln -s -b -S ".dpkg-old" "$target" "$symlink"
+  fi
+}
+
+migrate_dir_to_symlink () {
+  # syntax: migrate_dir_to_symlink old_location new_location
+  #
+  # Per Debian Policy section 6.5.4, "A directory will never be replaced by a
+  # symbolic link to a directory or vice versa; instead, the existing state
+  # (symlink or not) will be left alone and dpkg will follow the symlink if
+  # there is one."
+  #
+  # We have to do it ourselves.
+  #
+  # This function moves the contents of old_location, a directory, into
+  # new_location, a directory, then makes old_location a symbolic link to
+  # new_location.
+  #
+  # old_location need not exist, but if it does, it must be a directory (or a
+  # symlink to a directory).  If it is not, it is backed up.  If new_location
+  # exists already and is not a directory, it is backed up.
+  #
+  # This function should be called from a package's preinst so that other
+  # packages unpacked after this one --- but before this package's postinst runs
+  # --- are unpacked into new_location even if their payloads contain
+  # old_location filespecs.
+
+  # Validate arguments.
+  if [ $# -ne 2 ]; then
+    usage_error "migrate_dir_to_symlink() called with wrong number of"
+                "arguments; expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  # We could just use the positional parameters as-is, but that makes things
+  # harder to follow.
+  local new old
+
+  old="$1"
+  new="$2"
+
+  # Is old location a symlink?
+  if [ -L "$old" ]; then
+    # Does it already point to new location?
+    if [ "$(readlink "$old")" = "$new" ]; then
+      # Nothing to do; migration has already been done.
+      observe "migration of $old to $new already done"
+      return 0
+    else
+      # Back it up.
+      warn "backing up symbolic link $old as $old.dpkg-old"
+      mv -b "$old" "$old.dpkg-old"
+    fi
+  fi
+
+  # Does old location exist, but is not a directory?
+  if [ -e "$old" ] && ! [ -d "$old" ]; then
+      # Back it up.
+      warn "backing up non-directory $old as $old.dpkg-old"
+      mv -b "$old" "$old.dpkg-old"
+  fi
+
+  observe "migrating $old to $new"
+
+  # Is new location a symlink?
+  if [ -L "$new" ]; then
+    # Does it point the wrong way, i.e., back to where we're migrating from?
+    if [ "$(readlink "$new")" = "$old" ]; then
+      # Get rid of it.
+      observe "removing symbolic link $new which points to $old"
+      rm "$new"
+    else
+      # Back it up.
+      warn "backing up symbolic link $new as $new.dpkg-old"
+      mv -b "$new" "$new.dpkg-old"
+    fi
+  fi
+
+  # Does new location exist, but is not a directory?
+  if [ -e "$new" ] && ! [ -d "$new" ]; then
+    warn "backing up non-directory $new as $new.dpkg-old"
+    mv -b "$new" "$new.dpkg-old"
+  fi
+
+  # Create new directory if it does not yet exist.
+  if ! [ -e "$new" ]; then
+    observe "creating $new"
+    mkdir -p "$new"
+  fi
+
+  # Copy files in old location to new location.  Back up any filenames that
+  # already exist in the new location with the extension ".dpkg-old".
+  observe "copying files from $old to $new"
+  if ! (cd "$old" && cp -a -b -S ".dpkg-old" . "$new"); then
+    die "error(s) encountered while copying files from $old to $new"
+  fi
+
+  # Remove files at old location.
+  observe "removing $old"
+  rm -r "$old"
+
+  # Create symlink from old location to new location.
+  make_symlink_sane "$old" "$new"
+}
+
+# vim:set ai et sw=2 ts=2 tw=80:
+
+# GOBSTOPPER: The X Strike Force shell library ends here.
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644 (file)
index 0000000..1f93750
--- /dev/null
@@ -0,0 +1,2 @@
+EXTRA_DIST = evdevmultitouch-properties.h
+sdk_HEADERS = evdevmultitouch-properties.h
diff --git a/include/evdevmultitouch-properties.h b/include/evdevmultitouch-properties.h
new file mode 100755 (executable)
index 0000000..0be50c0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * 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 © 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.
+ *
+ * Authors:
+ *     Peter Hutterer (peter.hutterer@redhat.com)
+ */
+
+
+#ifndef _EVDEVMULTITOUCH_PROPERTIES_H_
+#define _EVDEVMULTITOUCH_PROPERTIES_H_
+
+/* Middle mouse button emulation */
+/* BOOL */
+#define EVDEVMULTITOUCH_PROP_MIDBUTTON "EvdevMultitouch Middle Button Emulation"
+/* CARD32 */
+#define EVDEVMULTITOUCH_PROP_MIDBUTTON_TIMEOUT "EvdevMultitouch Middle Button Timeout"
+
+/* Wheel emulation */
+/* BOOL */
+#define EVDEVMULTITOUCH_PROP_WHEEL "EvdevMultitouch Wheel Emulation"
+/* CARD8, 4 values [x up, x down, y up, y down], 0 to disable a value*/
+#define EVDEVMULTITOUCH_PROP_WHEEL_AXES "EvdevMultitouch Wheel Emulation Axes"
+/* CARD16 */
+#define EVDEVMULTITOUCH_PROP_WHEEL_INERTIA "EvdevMultitouch Wheel Emulation Inertia"
+/* CARD16 */
+#define EVDEVMULTITOUCH_PROP_WHEEL_TIMEOUT "EvdevMultitouch Wheel Emulation Timeout"
+/* CARD8, value range 0-32, 0 to always scroll */
+#define EVDEVMULTITOUCH_PROP_WHEEL_BUTTON "EvdevMultitouch Wheel Emulation Button"
+
+/* Drag lock */
+/* CARD8, either 1 value or pairs, value range 0-32, 0 to disable a value*/
+#define EVDEVMULTITOUCH_PROP_DRAGLOCK "EvdevMultitouch Drag Lock Buttons"
+
+/* Axis inversion */
+/* BOOL, 2 values [x, y], 1 inverts axis */
+#define EVDEVMULTITOUCH_PROP_INVERT_AXES "EvdevMultitouch Axis Inversion"
+
+/* Reopen attempts. */
+/* CARD8 */
+#define EVDEVMULTITOUCH_PROP_REOPEN "EvdevMultitouch Reopen Attempts"
+
+/* Run-time calibration */
+/* CARD32, 4 values [minx, maxx, miny, maxy], or no values for unset */
+#define EVDEVMULTITOUCH_PROP_CALIBRATION "EvdevMultitouch Axis Calibration"
+
+/* Swap x and y axis. */
+/* BOOL */
+#define EVDEVMULTITOUCH_PROP_SWAP_AXES "EvdevMultitouch Axes Swap"
+
+#endif
diff --git a/include/vsync_debug_info.h b/include/vsync_debug_info.h
new file mode 100755 (executable)
index 0000000..481b8ad
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _SYNC_DEBUG_H
+#define _SYNC_DEBUG_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdarg.h>
+#include <semaphore.h>
+
+#ifdef __GNUC__
+#define MAY_NOT_BE_USED __attribute__ ((unused))
+#else
+#define MAY_NOT_BE_USED
+#endif 
+
+
+#define SYNC_DEBUG_SHM_KEY     0xDEAD2012
+#define SHM_MESG_SIZE          ( 1024 * 1024 )
+
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC 1
+#endif
+
+typedef struct {
+       int initialized;
+
+       sem_t sem;
+
+       int count;
+
+       int cur_pos;
+
+       int isLogging;
+
+       int isPrintEnabled;
+
+       unsigned long tvStart;
+
+       int _shmid;
+
+       char debug_msg[0];
+} VSYNC_DEBUG_INFO;
+
+static volatile VSYNC_DEBUG_INFO * _vsync_debug = NULL;
+
+static int
+_vsync_debug_init(void)
+{
+       int shmid = 0;
+
+       struct shmid_ds ds;
+
+       shmid = shmget(SYNC_DEBUG_SHM_KEY, SHM_MESG_SIZE, IPC_CREAT | IPC_RMID);
+       if (shmid < 0)
+       {
+               fprintf(stderr, "\tError : shmget size:%d\n", SHM_MESG_SIZE);
+               goto bail;
+       }
+
+       if (shmctl(shmid, IPC_STAT, &ds) < 0)
+       {
+               fprintf(stderr, "\tError : shmctl\n");
+               goto bail;
+       }
+
+       if (ds.shm_segsz < SHM_MESG_SIZE)
+       {
+               fprintf(stderr, "\tError : size check\n");
+               goto bail;
+       }
+
+       _vsync_debug = shmat(shmid, NULL, 0);
+       if (_vsync_debug == (void *) -1)
+       {
+               fprintf(stderr, "\tError : shmat\n");
+               goto bail;
+       }
+
+       return shmid;
+
+bail:
+       fprintf(stderr, "VSYNC_DEBUG.... Error\n");
+
+       if (_vsync_debug != NULL && _vsync_debug != (void *) -1)
+               shmdt((void*)_vsync_debug);
+
+       return -1;
+}
+
+static unsigned long
+_vsync_debug_get_time(void)
+{
+       struct timespec tp;
+
+       if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+               return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+
+       return 0;               
+}
+
+static void
+_vsync_debug_lock(void)
+{
+       if (sem_wait((sem_t *) &_vsync_debug->sem) < 0)
+               fprintf(stderr, "sem_wait error\n");
+}
+
+
+static void
+_vsync_debug_unlock(void)
+{
+       if (sem_post((sem_t *) &_vsync_debug->sem) < 0)
+               fprintf(stderr, "sem_post error\n");
+}
+
+static void
+_vsync_debug_set_slot(int isSync, const char * format, va_list args)
+{
+       unsigned long cur_time;
+
+       if (_vsync_debug == NULL)
+               _vsync_debug_init();
+
+       if (!_vsync_debug->initialized)
+               return;
+
+       if (! _vsync_debug->isLogging)
+               return;
+
+       if (!_vsync_debug->isPrintEnabled)
+               return;
+
+       if (_vsync_debug->cur_pos > SHM_MESG_SIZE - 1024)
+               return;
+
+       cur_time = _vsync_debug_get_time();
+
+       _vsync_debug_lock();
+
+       if (isSync)
+       {
+               _vsync_debug->count++;
+               _vsync_debug->cur_pos += sprintf((char *) _vsync_debug->debug_msg + _vsync_debug->cur_pos, "\e[32m");
+
+       }
+       _vsync_debug->cur_pos += sprintf((char *) _vsync_debug->debug_msg + _vsync_debug->cur_pos, "%6ld ", cur_time);
+       _vsync_debug->cur_pos += vsprintf((char *) _vsync_debug->debug_msg + _vsync_debug->cur_pos, format, args);
+       _vsync_debug->debug_msg[_vsync_debug->cur_pos++] = '\n';
+       _vsync_debug->debug_msg[_vsync_debug->cur_pos] = '\0';
+
+       if (isSync)
+               _vsync_debug->cur_pos += sprintf((char *) _vsync_debug->debug_msg + _vsync_debug->cur_pos, "\e[0m");
+
+       _vsync_debug_unlock();
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_start(void)
+{
+       if (_vsync_debug == NULL)
+               _vsync_debug_init();
+
+       if (!_vsync_debug->initialized)
+               return;
+
+       _vsync_debug->isLogging = 1;
+       _vsync_debug->tvStart = _vsync_debug_get_time();
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_stop(void)
+{
+       unsigned long tvStop;
+
+       if (_vsync_debug == NULL)
+               _vsync_debug_init();
+
+       if (!_vsync_debug->initialized)
+               return;
+
+       _vsync_debug->isLogging = 0;
+       tvStop = _vsync_debug_get_time();
+       
+       _vsync_debug_lock();
+       if (_vsync_debug->isPrintEnabled)
+       {
+               //Print Debug
+               fprintf(stderr, "VSYNC DEBUG: count:%d, start:%6ld, end:%6ld\n", _vsync_debug->count, _vsync_debug->tvStart, tvStop);
+               fprintf(stderr, "%s\n", _vsync_debug->debug_msg);
+       }
+       _vsync_debug->cur_pos = 0;
+       _vsync_debug->debug_msg[0] = '\0';
+       _vsync_debug_unlock();
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_set_sync(const char * format, ...)
+{
+       va_list args;
+
+       va_start(args, format);
+
+       _vsync_debug_set_slot(1, format, args);
+
+       va_end(args);
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_set_slot(const char * format, ...)
+{
+       va_list args;
+
+       va_start(args, format);
+
+       _vsync_debug_set_slot(0, format, args);
+
+       va_end(args);
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_set_enable(int bEnable)
+{
+       if (_vsync_debug == NULL)
+               _vsync_debug_init();
+
+       if (!_vsync_debug->initialized)
+               return;
+
+       _vsync_debug->isPrintEnabled = bEnable;
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_master_init(void)
+{
+       int shmid = _vsync_debug_init();
+
+       _vsync_debug->_shmid = shmid;
+
+       if (sem_init((sem_t *) &_vsync_debug->sem, 1, 1) < 0)
+       {
+               fprintf(stderr, "\tError : sem_init\n");
+                goto bail;
+       }
+
+       _vsync_debug->initialized = 1;
+
+       return;
+bail:
+       fprintf(stderr, "VSYNC_DEBUG.... master Error\n");
+}
+
+static void MAY_NOT_BE_USED
+vsync_debug_master_close(void)
+{
+       if (_vsync_debug == NULL)
+               return;
+
+       if (shmctl(_vsync_debug->_shmid, IPC_RMID, NULL) < 0)
+       {
+               fprintf(stderr, "\tError : shmctl(IPC_RMID)\n");
+       }
+       if (shmdt((void*)_vsync_debug) < 0)
+       {
+               fprintf(stderr, "\tError : shmdt\n");
+       }
+
+       _vsync_debug = NULL;
+}
+
+#endif /* _SYNC_DEBUG_H */
+
diff --git a/include/vsync_input_protocol.h b/include/vsync_input_protocol.h
new file mode 100755 (executable)
index 0000000..e4c6842
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * 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.
+ */
+
+#ifndef _SYNC_INPUT_LIB_H
+#define _SYNC_INPUT_LIB_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+
+#define SYNC_INPUT_SHM_KEY     0xDEAD2010
+
+typedef struct {
+       /* EVDEVMULTITOUCHh providing functions FBDEV will use */
+       void (*sync)(int vsync_cnt);
+
+       /* FBDEV providing functions EVDEVMULTITOUCHh will use */
+       void * sync_arg;
+       void (*start_sync)(void * sync_arg);
+       void (*stop_sync)(void * sync_arg);
+
+       /* for internal use only */
+       int _shmid;
+
+       int _reserved[16];
+} VSYNC_INPUT_DISPATCH_TABLE;
+
+static volatile VSYNC_INPUT_DISPATCH_TABLE *
+vsync_input_init(void)
+{
+       VSYNC_INPUT_DISPATCH_TABLE * table = NULL;
+       int shmid = 0;
+
+       struct shmid_ds ds;
+       
+       shmid = shmget(SYNC_INPUT_SHM_KEY, sizeof(VSYNC_INPUT_DISPATCH_TABLE), IPC_CREAT);
+       if (shmid < 0)
+               goto bail;
+
+       if (shmctl(shmid, IPC_STAT, &ds) < 0)
+               goto bail;
+
+       if (ds.shm_segsz < sizeof(VSYNC_INPUT_DISPATCH_TABLE))
+               goto bail;
+
+       table = shmat(shmid, NULL, 0);
+       if (table == (void *) -1)
+               goto bail;
+
+       table->_shmid = shmid;
+
+       return table;
+
+bail:
+       if (shmid >= 0)
+               shmctl(shmid, IPC_RMID, NULL);
+
+       if (table != NULL && table != (void *) -1)
+               shmdt(table);
+
+       return NULL;
+}
+
+static int
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+vsync_input_close(volatile VSYNC_INPUT_DISPATCH_TABLE * table)
+{
+       if (table == NULL)
+               return -1;
+
+       shmdt((void *) table);
+
+       return 0;
+}
+
+static int
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+vsync_input_destroy(volatile VSYNC_INPUT_DISPATCH_TABLE * table)
+{
+       if (table == NULL)
+               return -1;
+
+       shmctl(table->_shmid, IPC_RMID, NULL);
+       shmdt((void *) table);
+
+       return 0;
+}
+
+#endif /* _SYNC_INPUT_LIB_H */
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644 (file)
index 0000000..276f2f0
--- /dev/null
@@ -0,0 +1,57 @@
+# 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.
+# 
+
+drivermandir = $(DRIVER_MAN_DIR)
+
+driverman_PRE = @DRIVER_NAME@.man
+
+driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+
+EXTRA_DIST = @DRIVER_NAME@.man
+
+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
+
+.man.$(DRIVER_MAN_SUFFIX):
+       sed $(MAN_SUBSTS) < $< > $@
diff --git a/man/evdevmultitouch.man b/man/evdevmultitouch.man
new file mode 100644 (file)
index 0000000..abd31e2
--- /dev/null
@@ -0,0 +1,231 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH EVDEVMULTITOUCHh __drivermansuffix__ __vendorversion__
+.SH NAME
+evdevmultitouch \- Generic Linux input driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qInputDevice\*q"
+.BI "  Identifier \*q" devname \*q
+.B  "  Driver \*qevdevmultitouch\*q"
+.BI "  Option \*qDevice\*q   \*q" devpath \*q
+.BI "  Option \*qEmulate3Buttons\*q     \*q" True \*q
+.BI "  Option \*qEmulate3Timeout\*q     \*q" 50 \*q
+.BI "  Option \*qGrabDevice\*q     \*q" False \*q
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B evdevmultitouch 
+is an __xservername__ input driver for Linux\'s generic event devices.  It
+therefore supports all input devices that the kernel knows about, including
+most mice and keyboards.
+.PP
+The 
+.B evdevmultitouch
+driver can serve as both a pointer and a keyboard input device, and may be
+used as both the core keyboard and the core pointer.  Multiple input devices
+are supported by multiple instances of this driver, with one Load
+directive for evdevmultitouch in the Module section of your __xconfigfile__ for each
+input device that will use this driver.
+.PP
+.SH SUPPORTED HARDWARE
+In general, any input device that the kernel has a driver for can be accessed
+through the 
+.B evdevmultitouch
+driver.  See the Linux kernel documentation for a complete list.
+.PP
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+details and for options that can be used with all input drivers.  This
+section only covers configuration details specific to this driver.
+.PP
+The following driver 
+.B Options
+are supported:
+.TP 7
+.BI "Option \*qButtonMapping\*q \*q" string \*q
+Sets the button mapping for this device. The mapping is a space-separated list
+of button mappings that correspond in order to the physical buttons on the
+device (i.e. the first number is the mapping for button 1, etc.). The default
+mapping is "1 2 3 ... 32". A mapping of 0 deactivates the button. Multiple
+buttons can have the same mapping.
+For example, a left-handed mouse with deactivated scroll-wheel would use a
+mapping of "3 2 1 0 0". Invalid mappings are ignored and the default mapping
+is used. Buttons not specified in the user's mapping use the default mapping.
+.TP 7
+.BI "Option \*qDevice\*q \*q" string \*q
+Specifies the device through which the device can be accessed.  This will 
+generally be of the form \*q/dev/input/eventX\*q, where X is some integer.
+The mapping from device node to hardware is system-dependent.
+.TP 7
+.BI "Option \*qDragLockButtons\*q \*q" "L1 B2 L3 B4" \*q
+Sets \*qdrag lock buttons\*q that simulate holding a button down, so
+that low dexterity people do not have to hold a button down at the
+same time they move a mouse cursor. Button numbers occur in pairs,
+with the lock button number occurring first, followed by the button
+number that is the target of the lock button. Property: "EvdevMultitouch
+Drag Lock Buttons".
+.TP 7
+.BI "Option \*qDragLockButtons\*q \*q" "M1" \*q
+Sets a \*qmaster drag lock button\*q that acts as a \*qMeta Key\*q
+indicating that the next button pressed is to be
+\*qdrag locked\*q. Property: "EvdevMultitouch Drag Lock Buttons".
+.TP 7
+.TP 7
+.BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
+Enable/disable the emulation of the third (middle) mouse button for mice
+which only have two physical buttons.  The third button is emulated by
+pressing both buttons simultaneously.  Default: on, until a middle mouse
+button event is registered. Property: "EvdevMultitouch Middle Button Emulation".
+.TP 7
+.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
+Sets the timeout (in milliseconds) that the driver waits before deciding
+if two buttons where pressed "simultaneously" when 3 button emulation is
+enabled.  Default: 50. Property: "EvdevMultitouch Middle Button Timeout".
+.BI "Option \*qEmulateWheel\*q \*q" boolean \*q
+Enable/disable "wheel" emulation.  Wheel emulation means emulating button
+press/release events when the mouse is moved while a specific real button
+is pressed.  Wheel button events (typically buttons 4 and 5) are
+usually used for scrolling.  Wheel emulation is useful for getting wheel-like
+behaviour with trackballs.  It can also be useful for mice with 4 or
+more buttons but no wheel.  See the description of the
+.BR EmulateWheelButton ,
+.BR EmulateWheelInertia ,
+.BR EmulateWheelTimeout ,
+.BR XAxisMapping ,
+and
+.B YAxisMapping
+options.  Default: off. Property "EvdevMultitouch Wheel Emulation".
+.TP 7
+.BI "Option \*qEmulateWheelButton\*q \*q" integer \*q
+Specifies which button must be held down to enable wheel emulation mode.
+While this button is down, X and/or Y pointer movement will generate button
+press/release events as specified for the
+.B XAxisMapping
+and
+.B YAxisMapping
+settings. If the button is 0 and
+.BR EmulateWheel
+is on, any motion of the device is converted into wheel events. Default: 4.
+Property: "EvdevMultitouch Wheel Emulation Button".
+.TP 7
+.BI "Option \*qEmulateWheelInertia\*q \*q" integer \*q
+Specifies how far (in pixels) the pointer must move to generate button
+press/release events in wheel emulation mode.  Default: 10. Property: "EvdevMultitouch
+Wheel Emulation Inertia".
+.TP 7
+.BI "Option \*qEmulateWheelTimeout\*q \*q" integer \*q
+Specifies the time in milliseconds the
+.BR EmulateWheelButton
+must be pressed before wheel emulation is started. If the
+.BR EmulateWheelButton
+is released before this timeout, the original button press/release event
+is sent.  Default: 200. Property: "EvdevMultitouch Wheel Emulation Timeout".
+.TP 7
+.BI "Option \*qGrabDevice\*q \*q" boolean \*q
+Force a grab on the event device. Doing so will ensure that no other driver
+can initialise the same device and it will also stop the device from sending
+events to /dev/kbd or /dev/input/mice. Events from this device will not be
+sent to virtual devices (e.g. rfkill or the Macintosh mouse button emulation).
+Default: disabled.
+.TP 7
+.BI "Option \*qInvertX\*q \*q" Bool \*q
+.TP 7
+.BI "Option \*qInvertY\*q \*q" Bool \*q
+Invert the given axis. Default: off. Property: "EvdevMultitouch Axis Inversion".
+.TP 7
+.BI "Option \*qIgnoreRelativeAxes\*q \*q" Bool \*q
+.TP 7
+.BI "Option \*qIgnoreAbsoluteAxes\*q \*q" Bool \*q
+Ignore the specified type of axis. Default: unset. The X server cannot deal
+with devices that have both relative and absolute axes. EvdevMultitouch tries to guess
+wich axes to ignore given the device type and disables absolute axes for
+mice and relative axes for tablets, touchscreens and touchpad. These options
+allow to forcibly disable an axis type. Mouse wheel axes are exempt and will
+work even if relative axes are ignored. No property, this configuration must
+be set in the configuration.
+.br
+If either option is set to False, the driver will not ignore the specified
+axes regardless of the presence of other axes. This may trigger buggy
+behavior and events from this axis are always forwarded. Users are
+discouraged from setting this option.
+.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
+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
+for devices that need to scale to a different coordinate system than
+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
+the transformation. Property: "EvdevMultitouch Axis Calibration".
+.TP 7
+.BI "Option \*qSwapAxes\*q \*q" Bool \*q
+Swap x/y axes. Default: off. Property: "EvdevMultitouch Axes Swap".
+.TP 7
+.BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q
+Specifies which buttons are mapped to motion in the X direction in wheel
+emulation mode.  Button number
+.I N1
+is mapped to the negative X axis motion and button number
+.I N2
+is mapped to the positive X axis motion.  Default: no mapping. Property:
+"EvdevMultitouch Wheel Emulation Axes".
+.TP 7
+.BI "Option \*qYAxisMapping\*q \*q" "N1 N2" \*q
+Specifies which buttons are mapped to motion in the Y direction in wheel
+emulation mode.  Button number
+.I N1
+is mapped to the negative Y axis motion and button number
+.I N2
+is mapped to the positive Y axis motion.  Default: "4 5". Property:
+"EvdevMultitouch Wheel Emulation Axes".
+
+.SH SUPPORTED PROPERTIES
+The following properties are provided by the
+.B evdevmultitouch
+driver.
+.TP 7
+.BI "EvdevMultitouch Axis Calibration"
+4 32-bit values, order min-x, max-x, min-y, max-y or 0 values to disable
+in-driver axis calibration.
+.TP 7
+.BI "EvdevMultitouch Axis Inversion"
+2 boolean values (8 bit, 0 or 1), order X, Y. 1 inverts the axis.
+.TP 7
+.BI "EvdevMultitouch Axes Swap"
+1 boolean value (8 bit, 0 or 1). 1 swaps x/y axes.
+.TP 7
+.BI "EvdevMultitouch Drag Lock Buttons"
+8-bit. Either 1 value or pairs of values. Value range 0-32, 0 disables a
+value.
+.TP 7
+.BI "EvdevMultitouch Middle Button Emulation"
+1 boolean value (8 bit, 0 or 1).
+.TP 7
+.BI "EvdevMultitouch Middle Button Timeout"
+1 16-bit positive value.
+.TP 7
+.BI "EvdevMultitouch Wheel Emulation"
+1 boolean value (8 bit, 0 or 1).
+.TP 7
+.BI "EvdevMultitouch Wheel Emulation Axes"
+4 8-bit values, order X up, X down, Y up, Y down. 0 disables a value.
+.TP 7
+.BI "EvdevMultitouch Wheel Emulation Button"
+1 8-bit value, allowed range 0-32, 0 disables the button.
+.TP 7
+.BI "EvdevMultitouch Wheel Emulation Inertia"
+1 16-bit positive value.
+.TP 7
+.BI "EvdevMultitouch Wheel Emulation Timeout"
+1 16-bit positive value.
+
+.SH AUTHORS
+Kristian Høgsberg.
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__),
+README.mouse.
diff --git a/packaging/xorg-x11-drv-evdev-multitouch.spec b/packaging/xorg-x11-drv-evdev-multitouch.spec
new file mode 100644 (file)
index 0000000..9973f4e
--- /dev/null
@@ -0,0 +1,49 @@
+Name:       xorg-x11-drv-evdev-multitouch
+Summary:    X.Org evdev multitouch input driver.
+Version:    2.3.2
+Release:    1
+Group:      TO_BE/FILLED_IN
+License:    TO BE FILLED IN
+Source0:    xf86-input-evdev-multitouch-%{version}.tar.gz
+BuildRequires:  pkgconfig(xorg-server)
+BuildRequires:  pkgconfig(xproto)
+BuildRequires:  pkgconfig(randrproto)
+BuildRequires:  pkgconfig(inputproto)
+BuildRequires:  pkgconfig(kbproto)
+BuildRequires:  pkgconfig(xkbfile)
+
+%description
+X.Org X server -- evdev input multitouch driver This package provides the driver for input devices using evdev, the Linux
+ kernel's event delivery mechanism.  This driver allows for multiple keyboards
+ and mice to be treated as separate input devices.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xf86-input-evdev driver module.
+
+
+%prep
+%setup -q -n xf86-input-evdev-multitouch-%{version}
+
+%build
+export CFLAGS+=" -Wall -g -D_F_IGNORE_TSP_RESOLUTION_"
+
+
+%autogen --disable-static
+%configure --disable-static
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+
+%files
+/usr/include/xorg/evdevmultitouch-properties.h
+/usr/lib/pkgconfig/xorg-evdev-multitouch.pc
+/usr/lib/xorg/modules/input/evdevmultitouch_drv.so
+/usr/share/man/man4/evdevmultitouch.4.gz
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..16bdf00
--- /dev/null
@@ -0,0 +1,40 @@
+#  Copyright 2005 Adam Jackson.
+#
+#  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
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON 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.
+
+
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -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
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = $(XORG_CFLAGS)
+
+@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
+@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
+@DRIVER_NAME@_drv_ladir = @inputdir@
+
+INCLUDES=-I$(top_srcdir)/include/
+
+@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
+                               @DRIVER_NAME@.h \
+                               emuMB.c \
+                               emuWheel.c \
+                               draglock.c 
+
diff --git a/src/draglock.c b/src/draglock.c
new file mode 100755 (executable)
index 0000000..c7a983d
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ *
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ * Copyright 1993 by David Dawes <dawes@xfree86.org>
+ * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+ * Copyright 1994-2002 by The XFree86 Project, Inc.
+ * Copyright 2002 by Paul Elliott
+ * (Ported from xf86-input-mouse, above copyrights taken from there)
+ * 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
+ * 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 the authors
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  The authors make 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.
+ *
+ */
+
+/* Draglock code */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <X11/Xatom.h>
+#include <exevents.h>
+
+#include <evdevmultitouch-properties.h>
+#include "evdevmultitouch.h"
+
+#ifdef HAVE_PROPERTIES
+static Atom prop_dlock     = 0; /* Drag lock buttons. */
+#endif
+
+void EvdevMultitouchDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
+
+
+/* Setup and configuration code */
+void
+EvdevMultitouchDragLockPreInit(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    char *option_string = NULL;
+    int meta_button = 0;
+    int lock_button = 0;
+    char *next_num = NULL;
+    char *end_str = NULL;
+    BOOL pairs = FALSE;
+
+    option_string = xf86CheckStrOption(pInfo->options, "DragLockButtons",NULL);
+
+    if (!option_string)
+        return;
+
+    next_num = option_string;
+
+    /* Loop until we hit the end of our option string */
+    while (next_num != NULL) {
+        lock_button = 0;
+        meta_button = strtol(next_num, &end_str, 10);
+
+        /* check to see if we found anything */
+        if (next_num != end_str) {
+            /* setup for the next number */
+            next_num = end_str;
+        } else {
+            /* we have nothing more to parse, drop out of the loop */
+            next_num = NULL;
+        }
+
+        /* Check for a button to lock if we have a meta button */
+        if (meta_button != 0 && next_num != NULL ) {
+            lock_button = strtol(next_num, &end_str, 10);
+
+            /* check to see if we found anything */
+            if (next_num != end_str) {
+                /* setup for the next number */
+                next_num = end_str;
+            } else {
+                /* we have nothing more to parse, drop out of the loop */
+                next_num = NULL;
+            }
+        }
+
+        /* Ok, let the user know what we found on this look */
+        if (meta_button != 0) {
+            if (lock_button == 0) {
+                if (!pairs) {
+                    /* We only have a meta button */
+                    pEvdevMultitouch->dragLock.meta = meta_button;
+
+                    xf86Msg(X_CONFIG, "%s: DragLockButtons : "
+                            "%i as meta\n",
+                            pInfo->name, meta_button);
+                } else {
+                    xf86Msg(X_ERROR, "%s: DragLockButtons : "
+                            "Incomplete pair specifying button pairs %s\n",
+                            pInfo->name, option_string);
+                }
+            } else {
+
+                /* Do bounds checking to make sure we don't crash */
+                if ((meta_button <= EVDEVMULTITOUCH_MAXBUTTONS) && (meta_button > 0 ) &&
+                    (lock_button <= EVDEVMULTITOUCH_MAXBUTTONS) && (lock_button >= 0)) {
+
+                    xf86Msg(X_CONFIG, "%s: DragLockButtons : %i -> %i\n",
+                            pInfo->name, meta_button, lock_button);
+
+                    pEvdevMultitouch->dragLock.lock_pair[meta_button - 1] = lock_button;
+                    pairs=TRUE;
+                } else {
+                    /* Let the user know something was wrong
+                       with this pair of buttons */
+                    xf86Msg(X_CONFIG, "%s: DragLockButtons : "
+                            "Invalid button pair %i -> %i\n",
+                            pInfo->name, meta_button, lock_button);
+                }
+            }
+        } else {
+            xf86Msg(X_ERROR, "%s: Found DragLockButtons "
+                    "with  invalid lock button string : '%s'\n",
+                    pInfo->name, option_string);
+
+            /* This should be the case anyhow, just make sure */
+            next_num = NULL;
+        }
+
+        /* Check for end of string, to avoid annoying error */
+        if (next_num != NULL && *next_num == '\0')
+            next_num = NULL;
+    }
+}
+
+/* Updates DragLock button state and fires button event messges */
+void
+EvdevMultitouchDragLockLockButton(InputInfoPtr pInfo, unsigned int button)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    BOOL state = 0;
+
+    /* update button state */
+    state = pEvdevMultitouch->dragLock.lock_state[button - 1] ? FALSE : TRUE;
+    pEvdevMultitouch->dragLock.lock_state[button - 1] = state;
+
+    EvdevMultitouchQueueButtonEvent(pInfo, button, state);
+}
+
+/* Filter button presses looking for either a meta button or the
+ * control of a button pair.
+ *
+ * @param button button number (1 for left, 3 for right)
+ * @param value TRUE if button press, FALSE if release
+ *
+ * @return TRUE if the event was swallowed here, FALSE otherwise.
+ */
+BOOL
+EvdevMultitouchDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+
+    if (button == 0)
+        return FALSE;
+
+    /* Do we have a single meta key or
+       several button pairings? */
+    if (pEvdevMultitouch->dragLock.meta != 0) {
+
+        if (pEvdevMultitouch->dragLock.meta == button) {
+
+            /* setup up for button lock */
+            if (value)
+                pEvdevMultitouch->dragLock.meta_state = TRUE;
+
+            return TRUE;
+        } else if (pEvdevMultitouch->dragLock.meta_state) { /* waiting to lock */
+
+            pEvdevMultitouch->dragLock.meta_state = FALSE;
+
+            EvdevMultitouchDragLockLockButton(pInfo, button);
+
+            return TRUE;
+        }
+    } else if (pEvdevMultitouch->dragLock.lock_pair[button - 1] && value) {
+        /* A meta button in a meta/lock pair was pressed */
+        EvdevMultitouchDragLockLockButton(pInfo, pEvdevMultitouch->dragLock.lock_pair[button - 1]);
+        return TRUE;
+    }
+
+    /* Eat events for buttons that are locked */
+    if (pEvdevMultitouch->dragLock.lock_state[button - 1])
+        return TRUE;
+
+    return FALSE;
+}
+
+#ifdef HAVE_PROPERTIES
+/**
+ * Set the drag lock property.
+ * If only one value is supplied, then this is used as the meta button.
+ * If more than one value is supplied, then each value is the drag lock button
+ * for the pair. 0 disables a pair.
+ * i.e. to set bt 3 to draglock button 1, supply 0,0,1
+ */
+static int
+EvdevMultitouchDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+                         BOOL checkonly)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+
+    if (atom == prop_dlock)
+    {
+        int i;
+
+        if (val->format != 8 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        /* Don't allow changes while a lock is active */
+        if (pEvdevMultitouch->dragLock.meta)
+        {
+            if (pEvdevMultitouch->dragLock.meta_state)
+                return BadAccess;
+        } else
+        {
+            for (i = 0; i < EVDEVMULTITOUCH_MAXBUTTONS; i++)
+                if (pEvdevMultitouch->dragLock.lock_state[i])
+                    return BadValue;
+        }
+
+        if (val->size == 0)
+            return BadMatch;
+        else if (val->size == 1)
+        {
+            int meta = *((CARD8*)val->data);
+            if (meta > EVDEVMULTITOUCH_MAXBUTTONS)
+                return BadValue;
+
+            if (!checkonly)
+            {
+                pEvdevMultitouch->dragLock.meta = meta;
+                memset(pEvdevMultitouch->dragLock.lock_pair, 0, sizeof(pEvdevMultitouch->dragLock.lock_pair));
+            }
+        } else if ((val->size % 2) == 0)
+        {
+            CARD8* vals = (CARD8*)val->data;
+
+            for (i = 0; i < val->size && i < EVDEVMULTITOUCH_MAXBUTTONS; i++)
+                if (vals[i] > EVDEVMULTITOUCH_MAXBUTTONS)
+                    return BadValue;
+
+            if (!checkonly)
+            {
+                pEvdevMultitouch->dragLock.meta = 0;
+                memset(pEvdevMultitouch->dragLock.lock_pair, 0, sizeof(pEvdevMultitouch->dragLock.lock_pair));
+
+                for (i = 0; i < val->size && i < EVDEVMULTITOUCH_MAXBUTTONS; i += 2)
+                    pEvdevMultitouch->dragLock.lock_pair[vals[i] - 1] = vals[i + 1];
+            }
+        } else
+            return BadMatch;
+    }
+
+    return Success;
+}
+
+/**
+ * Initialise property for drag lock buttons setting.
+ */
+void
+EvdevMultitouchDragLockInitProperty(DeviceIntPtr dev)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+
+    if (!dev->button) /* don't init prop for keyboards */
+        return;
+
+    prop_dlock = MakeAtom(EVDEVMULTITOUCH_PROP_DRAGLOCK, strlen(EVDEVMULTITOUCH_PROP_DRAGLOCK), TRUE);
+    if (pEvdevMultitouch->dragLock.meta)
+    {
+        XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8,
+                               PropModeReplace, 1, &pEvdevMultitouch->dragLock.meta,
+                               FALSE);
+    } else {
+        int highest = 0;
+        int i;
+        CARD8 pair[EVDEVMULTITOUCH_MAXBUTTONS] = {0};
+
+        for (i = 0; i < EVDEVMULTITOUCH_MAXBUTTONS; i++)
+        {
+            if (pEvdevMultitouch->dragLock.lock_pair[i])
+                highest = i;
+            pair[i] = pEvdevMultitouch->dragLock.lock_pair[i];
+        }
+
+        XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8, PropModeReplace,
+                               highest + 1, pair, FALSE);
+    }
+
+    XISetDevicePropertyDeletable(dev, prop_dlock, FALSE);
+
+    XIRegisterPropertyHandler(dev, EvdevMultitouchDragLockSetProperty, NULL, NULL);
+}
+
+#endif
diff --git a/src/emuMB.c b/src/emuMB.c
new file mode 100755 (executable)
index 0000000..6d03e83
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ *
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ * Copyright 1993 by David Dawes <dawes@xfree86.org>
+ * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+ * Copyright 1994-2002 by The XFree86 Project, Inc.
+ * Copyright 2002 by Paul Elliott
+ * (Ported from xf86-input-mouse, above copyrights taken from there)
+ * Copyright © 2008 University of South Australia
+ *
+ * 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 the authors
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  The authors make 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.
+ *
+ */
+
+/* Middle mouse button emulation code. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xatom.h>
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+
+#include <evdevmultitouch-properties.h>
+#include "evdevmultitouch.h"
+
+enum {
+    MBEMU_DISABLED = 0,
+    MBEMU_ENABLED,
+    MBEMU_AUTO
+};
+
+#ifdef HAVE_PROPERTIES
+static Atom prop_mbemu     = 0; /* Middle button emulation on/off property */
+static Atom prop_mbtimeout = 0; /* Middle button timeout property */
+#endif
+/*
+ * Lets create a simple finite-state machine for 3 button emulation:
+ *
+ * We track buttons 1 and 3 (left and right).  There are 11 states:
+ *   0 ground           - initial state
+ *   1 delayed left     - left pressed, waiting for right
+ *   2 delayed right    - right pressed, waiting for left
+ *   3 pressed middle   - right and left pressed, emulated middle sent
+ *   4 pressed left     - left pressed and sent
+ *   5 pressed right    - right pressed and sent
+ *   6 released left    - left released after emulated middle
+ *   7 released right   - right released after emulated middle
+ *   8 repressed left   - left pressed after released left
+ *   9 repressed right  - right pressed after released right
+ *  10 pressed both     - both pressed, not emulating middle
+ *
+ * At each state, we need handlers for the following events
+ *   0: no buttons down
+ *   1: left button down
+ *   2: right button down
+ *   3: both buttons down
+ *   4: emulate3Timeout passed without a button change
+ * Note that button events are not deltas, they are the set of buttons being
+ * pressed now.  It's possible (ie, mouse hardware does it) to go from (eg)
+ * left down to right down without anything in between, so all cases must be
+ * handled.
+ *
+ * a handler consists of three values:
+ *   0: action1
+ *   1: action2
+ *   2: new emulation state
+ *
+ * action > 0: ButtonPress
+ * action = 0: nothing
+ * action < 0: ButtonRelease
+ *
+ * The comment preceeding each section is the current emulation state.
+ * The comments to the right are of the form
+ *      <button state> (<events>) -> <new emulation state>
+ * which should be read as
+ *      If the buttons are in <button state>, generate <events> then go to
+ *      <new emulation state>.
+ */
+static signed char stateTab[11][5][3] = {
+/* 0 ground */
+  {
+    {  0,  0,  0 },   /* nothing -> ground (no change) */
+    {  0,  0,  1 },   /* left -> delayed left */
+    {  0,  0,  2 },   /* right -> delayed right */
+    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  0,  0, -1 }    /* timeout N/A */
+  },
+/* 1 delayed left */
+  {
+    {  1, -1,  0 },   /* nothing (left event) -> ground */
+    {  0,  0,  1 },   /* left -> delayed left (no change) */
+    {  1, -1,  2 },   /* right (left event) -> delayed right */
+    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  1,  0,  4 },   /* timeout (left press) -> pressed left */
+  },
+/* 2 delayed right */
+  {
+    {  3, -3,  0 },   /* nothing (right event) -> ground */
+    {  3, -3,  1 },   /* left (right event) -> delayed left (no change) */
+    {  0,  0,  2 },   /* right -> delayed right (no change) */
+    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  3,  0,  5 },   /* timeout (right press) -> pressed right */
+  },
+/* 3 pressed middle */
+  {
+    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    {  0,  0,  7 },   /* left -> released right */
+    {  0,  0,  6 },   /* right -> released left */
+    {  0,  0,  3 },   /* left & right -> pressed middle (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 4 pressed left */
+  {
+    { -1,  0,  0 },   /* nothing (left release) -> ground */
+    {  0,  0,  4 },   /* left -> pressed left (no change) */
+    { -1,  0,  2 },   /* right (left release) -> delayed right */
+    {  3,  0, 10 },   /* left & right (right press) -> pressed both */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 5 pressed right */
+  {
+    { -3,  0,  0 },   /* nothing (right release) -> ground */
+    { -3,  0,  1 },   /* left (right release) -> delayed left */
+    {  0,  0,  5 },   /* right -> pressed right (no change) */
+    {  1,  0, 10 },   /* left & right (left press) -> pressed both */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 6 released left */
+  {
+    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    { -2,  0,  1 },   /* left (middle release) -> delayed left */
+    {  0,  0,  6 },   /* right -> released left (no change) */
+    {  1,  0,  8 },   /* left & right (left press) -> repressed left */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 7 released right */
+  {
+    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    {  0,  0,  7 },   /* left -> released right (no change) */
+    { -2,  0,  2 },   /* right (middle release) -> delayed right */
+    {  3,  0,  9 },   /* left & right (right press) -> repressed right */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 8 repressed left */
+  {
+    { -2, -1,  0 },   /* nothing (middle release, left release) -> ground */
+    { -2,  0,  4 },   /* left (middle release) -> pressed left */
+    { -1,  0,  6 },   /* right (left release) -> released left */
+    {  0,  0,  8 },   /* left & right -> repressed left (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 9 repressed right */
+  {
+    { -2, -3,  0 },   /* nothing (middle release, right release) -> ground */
+    { -3,  0,  7 },   /* left (right release) -> released right */
+    { -2,  0,  5 },   /* right (middle release) -> pressed right */
+    {  0,  0,  9 },   /* left & right -> repressed right (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 10 pressed both */
+  {
+    { -1, -3,  0 },   /* nothing (left release, right release) -> ground */
+    { -3,  0,  4 },   /* left (right release) -> pressed left */
+    { -1,  0,  5 },   /* right (left release) -> pressed right */
+    {  0,  0, 10 },   /* left & right -> pressed both (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+};
+
+
+int
+EvdevMultitouchMBEmuTimer(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    int        sigstate;
+    int id;
+
+    sigstate = xf86BlockSIGIO ();
+
+    pEvdevMultitouch->emulateMB.pending = FALSE;
+    if ((id = stateTab[pEvdevMultitouch->emulateMB.state][4][0]) != 0) {
+        EvdevMultitouchPostButtonEvent(pInfo, abs(id), (id >= 0));
+        pEvdevMultitouch->emulateMB.state =
+            stateTab[pEvdevMultitouch->emulateMB.state][4][2];
+    } else {
+        ErrorF("Got unexpected buttonTimer in state %d\n",
+                pEvdevMultitouch->emulateMB.state);
+    }
+
+    xf86UnblockSIGIO (sigstate);
+    return 0;
+}
+
+
+/**
+ * Emulate a middle button on button press.
+ *
+ * @param code button number (1 for left, 3 for right)
+ * @param press TRUE if press, FALSE if release.
+ *
+ * @return TRUE if event was swallowed by middle mouse button emulation, FALSE
+ * otherwise.
+ */
+BOOL
+EvdevMultitouchMBEmuFilterEvent(InputInfoPtr pInfo, int button, BOOL press)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    int id;
+    int *btstate;
+    int ret = FALSE;
+
+    if (!pEvdevMultitouch->emulateMB.enabled)
+        return ret;
+
+    if (button == 2) {
+        EvdevMultitouchMBEmuEnable(pInfo, FALSE);
+        return ret;
+    }
+
+    /* don't care about other buttons */
+    if (button != 1 && button != 3)
+        return ret;
+
+    btstate = &pEvdevMultitouch->emulateMB.buttonstate;
+    if (press)
+        *btstate |= (button == 1) ? 0x1 : 0x2;
+    else
+        *btstate &= (button == 1) ? ~0x1 : ~0x2;
+
+    if ((id = stateTab[pEvdevMultitouch->emulateMB.state][*btstate][0]) != 0)
+    {
+        EvdevMultitouchQueueButtonEvent(pInfo, abs(id), (id >= 0));
+        ret = TRUE;
+    }
+    if ((id = stateTab[pEvdevMultitouch->emulateMB.state][*btstate][1]) != 0)
+    {
+        EvdevMultitouchQueueButtonEvent(pInfo, abs(id), (id >= 0));
+        ret = TRUE;
+    }
+
+    pEvdevMultitouch->emulateMB.state =
+        stateTab[pEvdevMultitouch->emulateMB.state][*btstate][2];
+
+    if (stateTab[pEvdevMultitouch->emulateMB.state][4][0] != 0) {
+        pEvdevMultitouch->emulateMB.expires = GetTimeInMillis () + pEvdevMultitouch->emulateMB.timeout;
+        pEvdevMultitouch->emulateMB.pending = TRUE;
+        ret = TRUE;
+    } else {
+        pEvdevMultitouch->emulateMB.pending = FALSE;
+    }
+
+    return ret;
+}
+
+
+void EvdevMultitouchMBEmuWakeupHandler(pointer data,
+                             int i,
+                             pointer LastSelectMask)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)data;
+    EvdevMultitouchPtr     pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    int ms;
+
+    if (pEvdevMultitouch->emulateMB.pending)
+    {
+        ms = pEvdevMultitouch->emulateMB.expires - GetTimeInMillis();
+        if (ms <= 0)
+            EvdevMultitouchMBEmuTimer(pInfo);
+    }
+}
+
+void EvdevMultitouchMBEmuBlockHandler(pointer data,
+                            struct timeval **waitTime,
+                            pointer LastSelectMask)
+{
+    InputInfoPtr    pInfo = (InputInfoPtr) data;
+    EvdevMultitouchPtr        pEvdevMultitouch= (EvdevMultitouchPtr) pInfo->private;
+    int             ms;
+
+    if (pEvdevMultitouch->emulateMB.pending)
+    {
+        ms = pEvdevMultitouch->emulateMB.expires - GetTimeInMillis ();
+        if (ms <= 0)
+            ms = 0;
+        AdjustWaitForDelay (waitTime, ms);
+    }
+}
+
+void
+EvdevMultitouchMBEmuPreInit(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    pEvdevMultitouch->emulateMB.enabled = MBEMU_AUTO;
+
+    if (xf86FindOption(pInfo->options, "Emulate3Buttons"))
+    {
+        pEvdevMultitouch->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
+                                                      "Emulate3Buttons",
+                                                      MBEMU_ENABLED);
+        xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation %s.\n",
+                pInfo->name, (pEvdevMultitouch->emulateMB.enabled) ? "on" : "off");
+    }
+
+    pEvdevMultitouch->emulateMB.timeout = xf86SetIntOption(pInfo->options,
+                                                 "Emulate3Timeout", 50);
+}
+
+void
+EvdevMultitouchMBEmuOn(InputInfoPtr pInfo)
+{
+    if (!pInfo->dev->button) /* don't init for keyboards */
+        return;
+
+    RegisterBlockAndWakeupHandlers (EvdevMultitouchMBEmuBlockHandler,
+                                    EvdevMultitouchMBEmuWakeupHandler,
+                                    (pointer)pInfo);
+}
+
+void
+EvdevMultitouchMBEmuFinalize(InputInfoPtr pInfo)
+{
+    if (!pInfo->dev->button) /* don't cleanup for keyboards */
+        return;
+
+    RemoveBlockAndWakeupHandlers (EvdevMultitouchMBEmuBlockHandler,
+                                  EvdevMultitouchMBEmuWakeupHandler,
+                                  (pointer)pInfo);
+
+}
+
+/* Enable/disable middle mouse button emulation. */
+void
+EvdevMultitouchMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    if (pEvdevMultitouch->emulateMB.enabled == MBEMU_AUTO)
+        pEvdevMultitouch->emulateMB.enabled = enable;
+}
+
+
+#ifdef HAVE_PROPERTIES
+static int
+EvdevMultitouchMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+                      BOOL checkonly)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+
+    if (atom == prop_mbemu)
+    {
+        if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+            pEvdevMultitouch->emulateMB.enabled = *((BOOL*)val->data);
+    } else if (atom == prop_mbtimeout)
+    {
+        if (val->format != 32 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+            pEvdevMultitouch->emulateMB.timeout = *((CARD32*)val->data);
+    }
+
+    return Success;
+}
+
+/**
+ * Initialise property for MB emulation on/off.
+ */
+void
+EvdevMultitouchMBEmuInitProperty(DeviceIntPtr dev)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+    int          rc;
+
+    if (!dev->button) /* don't init prop for keyboards */
+        return;
+
+    prop_mbemu = MakeAtom(EVDEVMULTITOUCH_PROP_MIDBUTTON, strlen(EVDEVMULTITOUCH_PROP_MIDBUTTON), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_mbemu, XA_INTEGER, 8,
+                                PropModeReplace, 1,
+                                &pEvdevMultitouch->emulateMB.enabled,
+                                FALSE);
+    if (rc != Success)
+        return;
+    XISetDevicePropertyDeletable(dev, prop_mbemu, FALSE);
+
+    prop_mbtimeout = MakeAtom(EVDEVMULTITOUCH_PROP_MIDBUTTON_TIMEOUT,
+                              strlen(EVDEVMULTITOUCH_PROP_MIDBUTTON_TIMEOUT),
+                              TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_mbtimeout, XA_INTEGER, 32, PropModeReplace, 1,
+                                &pEvdevMultitouch->emulateMB.timeout, FALSE);
+
+    if (rc != Success)
+        return;
+    XISetDevicePropertyDeletable(dev, prop_mbtimeout, FALSE);
+
+    XIRegisterPropertyHandler(dev, EvdevMultitouchMBEmuSetProperty, NULL, NULL);
+}
+#endif
diff --git a/src/emuWheel.c b/src/emuWheel.c
new file mode 100755 (executable)
index 0000000..665fbf0
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+* xserver-xorg-input-evdev-multitouch
+*
+* Contact: Sung-Jin Park <sj76.park@samsung.com>
+*          Sangjin LEE <lsj119@samsung.com>
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+* Copyright 1993 by David Dawes <dawes@xfree86.org>
+* Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+* Copyright 1994-2002 by The XFree86 Project, Inc.
+* Copyright 2002 by Paul Elliott
+* (Ported from xf86-input-mouse, above copyrights taken from there)
+* Copyright 2008 by Chris Salch
+* Copyright © 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 the authors
+* not be used in advertising or publicity pertaining to distribution of the
+* software without specific, written prior permission.  The authors make 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.
+*
+*/
+
+/* Mouse wheel emulation code. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xatom.h>
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+
+#include <evdevmultitouch-properties.h>
+#include "evdevmultitouch.h"
+
+#define WHEEL_NOT_CONFIGURED 0
+
+#ifdef HAVE_PROPERTIES
+static Atom prop_wheel_emu      = 0;
+static Atom prop_wheel_axismap  = 0;
+static Atom prop_wheel_inertia  = 0;
+static Atom prop_wheel_timeout  = 0;
+static Atom prop_wheel_button   = 0;
+#endif
+
+/* Local Funciton Prototypes */
+static BOOL EvdevMultitouchWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char *axis_name);
+static int EvdevMultitouchWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value);
+
+/* Filter mouse button events */
+BOOL
+EvdevMultitouchWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    int ms;
+
+    /* Has wheel emulation been configured to be enabled? */
+    if (!pEvdevMultitouch->emulateWheel.enabled)
+       return FALSE;
+
+    /* Check for EmulateWheelButton */
+    if (pEvdevMultitouch->emulateWheel.button == button) {
+       pEvdevMultitouch->emulateWheel.button_state = value;
+
+        if (value)
+            /* Start the timer when the button is pressed */
+            pEvdevMultitouch->emulateWheel.expires = pEvdevMultitouch->emulateWheel.timeout +
+                                           GetTimeInMillis();
+        else {
+            ms = pEvdevMultitouch->emulateWheel.expires - GetTimeInMillis();
+            if (ms > 0) {
+                /*
+                 * If the button is released early enough emit the button
+                 * press/release events
+                 */
+                EvdevMultitouchQueueButtonClicks(pInfo, button, 1);
+            }
+        }
+
+       return TRUE;
+    }
+
+    /* Don't care about this event */
+    return FALSE;
+}
+
+/* Filter mouse wheel events */
+BOOL
+EvdevMultitouchWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    WheelAxisPtr pAxis = NULL, pOtherAxis = NULL;
+    int value = pEv->value;
+
+    /* Has wheel emulation been configured to be enabled? */
+    if (!pEvdevMultitouch->emulateWheel.enabled)
+       return FALSE;
+
+    /* Handle our motion events if the emuWheel button is pressed
+     * wheel button of 0 means always emulate wheel.
+     */
+    if (pEvdevMultitouch->emulateWheel.button_state || !pEvdevMultitouch->emulateWheel.button) {
+        /* Just return if the timeout hasn't expired yet */
+        if (pEvdevMultitouch->emulateWheel.button)
+        {
+            int ms = pEvdevMultitouch->emulateWheel.expires - GetTimeInMillis();
+            if (ms > 0)
+                return TRUE;
+        }
+
+       /* We don't want to intercept real mouse wheel events */
+       switch(pEv->code) {
+       case REL_X:
+           pAxis = &(pEvdevMultitouch->emulateWheel.X);
+           pOtherAxis = &(pEvdevMultitouch->emulateWheel.Y);
+           break;
+
+       case REL_Y:
+           pAxis = &(pEvdevMultitouch->emulateWheel.Y);
+           pOtherAxis = &(pEvdevMultitouch->emulateWheel.X);
+           break;
+
+       default:
+           break;
+       }
+
+       /* If we found REL_X or REL_Y, emulate a mouse wheel.
+           Reset the inertia of the other axis when a scroll event was sent
+           to avoid the buildup of erroneous scroll events if the user
+           doesn't move in a perfectly straight line.
+         */
+       if (pAxis)
+       {
+           if (EvdevMultitouchWheelEmuInertia(pInfo, pAxis, value))
+               pOtherAxis->traveled_distance = 0;
+       }
+
+       /* Eat motion events while emulateWheel button pressed. */
+       return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* Simulate inertia for our emulated mouse wheel.
+   Returns the number of wheel events generated.
+ */
+static int
+EvdevMultitouchWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    int button;
+    int inertia;
+    int rc = 0;
+
+    /* if this axis has not been configured, just eat the motion */
+    if (!axis->up_button)
+       return rc;
+
+    axis->traveled_distance += value;
+
+    if (axis->traveled_distance < 0) {
+       button = axis->up_button;
+       inertia = -pEvdevMultitouch->emulateWheel.inertia;
+    } else {
+       button = axis->down_button;
+       inertia = pEvdevMultitouch->emulateWheel.inertia;
+    }
+
+    /* Produce button press events for wheel motion */
+    while(abs(axis->traveled_distance) > pEvdevMultitouch->emulateWheel.inertia) {
+       axis->traveled_distance -= inertia;
+       EvdevMultitouchQueueButtonClicks(pInfo, button, 1);
+       rc++;
+    }
+    return rc;
+}
+
+/* Handle button mapping here to avoid code duplication,
+returns true if a button mapping was found. */
+static BOOL
+EvdevMultitouchWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char* axis_name)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    char *option_string;
+
+    pAxis->up_button = WHEEL_NOT_CONFIGURED;
+
+    /* Check to see if there is configuration for this axis */
+    option_string = xf86SetStrOption(pInfo->options, axis_name, NULL);
+    if (option_string) {
+       int up_button = 0;
+       int down_button = 0;
+       char *msg = NULL;
+
+       if ((sscanf(option_string, "%d %d", &up_button, &down_button) == 2) &&
+           ((up_button > 0) && (up_button <= EVDEVMULTITOUCH_MAXBUTTONS)) &&
+           ((down_button > 0) && (down_button <= EVDEVMULTITOUCH_MAXBUTTONS))) {
+
+           /* Use xstrdup to allocate a string for us */
+           msg = xstrdup("buttons XX and YY");
+
+           if (msg)
+               sprintf(msg, "buttons %d and %d", up_button, down_button);
+
+           pAxis->up_button = up_button;
+           pAxis->down_button = down_button;
+
+           /* Update the number of buttons if needed */
+           if (up_button > pEvdevMultitouch->num_buttons) pEvdevMultitouch->num_buttons = up_button;
+           if (down_button > pEvdevMultitouch->num_buttons) pEvdevMultitouch->num_buttons = down_button;
+
+       } else {
+           xf86Msg(X_WARNING, "%s: Invalid %s value:\"%s\"\n",
+                   pInfo->name, axis_name, option_string);
+
+       }
+
+       /* Clean up and log what happened */
+       if (msg) {
+           xf86Msg(X_CONFIG, "%s: %s: %s\n",pInfo->name, axis_name, msg);
+           free(msg);
+           return TRUE;
+       }
+    }
+    return FALSE;
+}
+
+/* Setup the basic configuration options used by mouse wheel emulation */
+void
+EvdevMultitouchWheelEmuPreInit(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = (EvdevMultitouchPtr)pInfo->private;
+    char val[4];
+    int wheelButton;
+    int inertia;
+    int timeout;
+
+    val[0] = 0;
+    val[1] = 0;
+
+    if (xf86SetBoolOption(pInfo->options, "EmulateWheel", FALSE)) {
+       pEvdevMultitouch->emulateWheel.enabled = TRUE;
+    } else
+        pEvdevMultitouch->emulateWheel.enabled = FALSE;
+
+    wheelButton = xf86SetIntOption(pInfo->options, "EmulateWheelButton", 4);
+
+    if ((wheelButton < 0) || (wheelButton > EVDEVMULTITOUCH_MAXBUTTONS)) {
+        xf86Msg(X_WARNING, "%s: Invalid EmulateWheelButton value: %d\n",
+                pInfo->name, wheelButton);
+        xf86Msg(X_WARNING, "%s: Wheel emulation disabled.\n", pInfo->name);
+
+        pEvdevMultitouch->emulateWheel.enabled = FALSE;
+    }
+
+    pEvdevMultitouch->emulateWheel.button = wheelButton;
+
+    inertia = xf86SetIntOption(pInfo->options, "EmulateWheelInertia", 10);
+
+    if (inertia <= 0) {
+        xf86Msg(X_WARNING, "%s: Invalid EmulateWheelInertia value: %d\n",
+                pInfo->name, inertia);
+        xf86Msg(X_WARNING, "%s: Using built-in inertia value.\n",
+                pInfo->name);
+
+        inertia = 10;
+    }
+
+    pEvdevMultitouch->emulateWheel.inertia = inertia;
+
+    timeout = xf86SetIntOption(pInfo->options, "EmulateWheelTimeout", 200);
+
+    if (timeout < 0) {
+        xf86Msg(X_WARNING, "%s: Invalid EmulateWheelTimeout value: %d\n",
+                pInfo->name, timeout);
+        xf86Msg(X_WARNING, "%s: Using built-in timeout value.\n",
+                pInfo->name);
+
+        timeout = 200;
+    }
+
+    pEvdevMultitouch->emulateWheel.timeout = timeout;
+
+    /* Configure the Y axis or default it */
+    if (!EvdevMultitouchWheelEmuHandleButtonMap(pInfo, &(pEvdevMultitouch->emulateWheel.Y),
+                "YAxisMapping")) {
+        /* Default the Y axis to sane values */
+        pEvdevMultitouch->emulateWheel.Y.up_button = 4;
+        pEvdevMultitouch->emulateWheel.Y.down_button = 5;
+
+        /* Simpler to check just the largest value in this case */
+        /* XXX: we should post this to the server */
+        if (5 > pEvdevMultitouch->num_buttons)
+            pEvdevMultitouch->num_buttons = 5;
+
+        /* Display default Configuration */
+        xf86Msg(X_CONFIG, "%s: YAxisMapping: buttons %d and %d\n",
+                pInfo->name, pEvdevMultitouch->emulateWheel.Y.up_button,
+                pEvdevMultitouch->emulateWheel.Y.down_button);
+    }
+
+
+    /* This axis should default to an unconfigured state as most people
+       are not going to expect a Horizontal wheel. */
+    EvdevMultitouchWheelEmuHandleButtonMap(pInfo, &(pEvdevMultitouch->emulateWheel.X),
+            "XAxisMapping");
+
+    /* Used by the inertia code */
+    pEvdevMultitouch->emulateWheel.X.traveled_distance = 0;
+    pEvdevMultitouch->emulateWheel.Y.traveled_distance = 0;
+
+    xf86Msg(X_CONFIG, "%s: EmulateWheelButton: %d, "
+            "EmulateWheelInertia: %d, "
+            "EmulateWheelTimeout: %d\n",
+            pInfo->name, pEvdevMultitouch->emulateWheel.button, inertia, timeout);
+}
+
+#ifdef HAVE_PROPERTIES
+static int
+EvdevMultitouchWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+                         BOOL checkonly)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+
+    if (atom == prop_wheel_emu)
+    {
+        if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+        {
+            pEvdevMultitouch->emulateWheel.enabled = *((BOOL*)val->data);
+            /* Don't enable with zero inertia, otherwise we may get stuck in an
+             * infinite loop */
+            if (pEvdevMultitouch->emulateWheel.inertia <= 0)
+            {
+                pEvdevMultitouch->emulateWheel.inertia = 10;
+                /* We may get here before the property is actually enabled */
+                if (prop_wheel_inertia)
+                    XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER,
+                            16, PropModeReplace, 1,
+                            &pEvdevMultitouch->emulateWheel.inertia, TRUE);
+            }
+        }
+    }
+    else if (atom == prop_wheel_button)
+    {
+        int bt;
+
+        if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        bt = *((CARD8*)val->data);
+
+        if (bt < 0 || bt >= EVDEVMULTITOUCH_MAXBUTTONS)
+            return BadValue;
+
+        if (!checkonly)
+            pEvdevMultitouch->emulateWheel.button = bt;
+    } else if (atom == prop_wheel_axismap)
+    {
+        if (val->format != 8 || val->size != 4 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+        {
+            pEvdevMultitouch->emulateWheel.X.up_button = *((CARD8*)val->data);
+            pEvdevMultitouch->emulateWheel.X.down_button = *(((CARD8*)val->data) + 1);
+            pEvdevMultitouch->emulateWheel.Y.up_button = *(((CARD8*)val->data) + 2);
+            pEvdevMultitouch->emulateWheel.Y.down_button = *(((CARD8*)val->data) + 3);
+        }
+    } else if (atom == prop_wheel_inertia)
+    {
+        int inertia;
+
+        if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        inertia = *((CARD16*)val->data);
+
+        if (inertia < 0)
+            return BadValue;
+
+        if (!checkonly)
+            pEvdevMultitouch->emulateWheel.inertia = inertia;
+    } else if (atom == prop_wheel_timeout)
+    {
+        int timeout;
+
+        if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        timeout = *((CARD16*)val->data);
+
+        if (timeout < 0)
+            return BadValue;
+
+        if (!checkonly)
+            pEvdevMultitouch->emulateWheel.timeout = timeout;
+    }
+    return Success;
+}
+
+void
+EvdevMultitouchWheelEmuInitProperty(DeviceIntPtr dev)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+    int          rc     = TRUE;
+    char         vals[4];
+
+    if (!dev->button) /* don't init prop for keyboards */
+        return;
+
+    prop_wheel_emu = MakeAtom(EVDEVMULTITOUCH_PROP_WHEEL, strlen(EVDEVMULTITOUCH_PROP_WHEEL), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_wheel_emu, XA_INTEGER, 8,
+                                PropModeReplace, 1,
+                                &pEvdevMultitouch->emulateWheel.enabled, FALSE);
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_wheel_emu, FALSE);
+
+    vals[0] = pEvdevMultitouch->emulateWheel.X.up_button;
+    vals[1] = pEvdevMultitouch->emulateWheel.X.down_button;
+    vals[2] = pEvdevMultitouch->emulateWheel.Y.up_button;
+    vals[3] = pEvdevMultitouch->emulateWheel.Y.down_button;
+
+    prop_wheel_axismap = MakeAtom(EVDEVMULTITOUCH_PROP_WHEEL_AXES, strlen(EVDEVMULTITOUCH_PROP_WHEEL_AXES), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_wheel_axismap, XA_INTEGER, 8,
+                                PropModeReplace, 4, vals, FALSE);
+
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_wheel_axismap, FALSE);
+
+    prop_wheel_inertia = MakeAtom(EVDEVMULTITOUCH_PROP_WHEEL_INERTIA, strlen(EVDEVMULTITOUCH_PROP_WHEEL_INERTIA), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_wheel_inertia, XA_INTEGER, 16,
+                                PropModeReplace, 1,
+                                &pEvdevMultitouch->emulateWheel.inertia, FALSE);
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_wheel_inertia, FALSE);
+
+    prop_wheel_timeout = MakeAtom(EVDEVMULTITOUCH_PROP_WHEEL_TIMEOUT, strlen(EVDEVMULTITOUCH_PROP_WHEEL_TIMEOUT), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_wheel_timeout, XA_INTEGER, 16,
+                                PropModeReplace, 1,
+                                &pEvdevMultitouch->emulateWheel.timeout, FALSE);
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_wheel_timeout, FALSE);
+
+    prop_wheel_button = MakeAtom(EVDEVMULTITOUCH_PROP_WHEEL_BUTTON, strlen(EVDEVMULTITOUCH_PROP_WHEEL_BUTTON), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_wheel_button, XA_INTEGER, 8,
+                                PropModeReplace, 1,
+                                &pEvdevMultitouch->emulateWheel.button, FALSE);
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_wheel_button, FALSE);
+
+    XIRegisterPropertyHandler(dev, EvdevMultitouchWheelEmuSetProperty, NULL, NULL);
+}
+#endif
diff --git a/src/evdevmultitouch.c b/src/evdevmultitouch.c
new file mode 100755 (executable)
index 0000000..8c16551
--- /dev/null
@@ -0,0 +1,3976 @@
+/*
+ *
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ *
+ * Authors:
+ *     Kristian Høgsberg (krh@redhat.com)
+ *     Adam Jackson (ajax@redhat.com)
+ *     Peter Hutterer (peter.hutterer@redhat.com)
+ *     Oliver McFadden (oliver.mcfadden@nokia.com)
+ *     Benjamin Tissoires (tissoire@cena.fr)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/keysym.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+#include <xorgVersion.h>
+#include <xkbsrv.h>
+
+#include "evdevmultitouch.h"
+#include "vsync_input_protocol.h"
+#include "vsync_debug_info.h"
+
+#ifdef HAVE_PROPERTIES
+#include <X11/Xatom.h>
+#include <evdevmultitouch-properties.h>
+#include <xserver-properties.h>
+/* 1.6 has properties, but no labels */
+#ifdef AXIS_LABEL_PROP
+#define HAVE_LABELS
+#else
+#undef HAVE_LABELS
+#endif
+
+#endif
+
+#ifndef MAXDEVICES
+#include <inputstr.h> /* for MAX_DEVICES */
+#define MAXDEVICES MAX_DEVICES
+#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])))
+
+#ifndef True
+#define True   TRUE
+#endif
+#ifndef False
+#define False FALSE
+#endif
+
+#define POLL_DISABLE   '0'
+#define POLL_ENABLE            '1'
+#define POLL_REQUEST   '2'
+#define SYSFS_POLL     "/sys/class/input/event2/device/poll"
+
+#define ABS_MT_SLOT             0x2f
+#define ABS_MT_TOUCH_MAJOR     0x30    /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR     0x31    /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR     0x32    /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR     0x33    /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION     0x34    /* Ellipse orientation */
+#define ABS_MT_POSITION_X      0x35    /* Center X ellipse position */
+#define ABS_MT_POSITION_Y      0x36    /* Center Y ellipse position */
+#define ABS_MT_TOOL_TYPE       0x37    /* Type of touching device */
+#define ABS_MT_BLOB_ID         0x38    /* Group a set of packets as a blob */
+#define ABS_MT_TRACKING_ID             0x39    /* Unique ID of initiated contact */
+
+#define SYN_REPORT             0
+#define SYN_CONFIG             1
+#define SYN_MT_REPORT          2
+
+/* evdevmultitouch flags */
+#define EVDEVMULTITOUCH_KEYBOARD_EVENTS        (1 << 0)
+#define EVDEVMULTITOUCH_BUTTON_EVENTS  (1 << 1)
+#define EVDEVMULTITOUCH_RELATIVE_EVENTS        (1 << 2)
+#define EVDEVMULTITOUCH_ABSOLUTE_EVENTS        (1 << 3)
+#define EVDEVMULTITOUCH_TOUCHPAD               (1 << 4)
+#define EVDEVMULTITOUCH_INITIALIZED    (1 << 5) /* WheelInit etc. called already? */
+#define EVDEVMULTITOUCH_TOUCHSCREEN    (1 << 6)
+#define EVDEVMULTITOUCH_CALIBRATED     (1 << 7) /* run-time calibrated? */
+#define EVDEVMULTITOUCH_TABLET         (1 << 8) /* device looks like a tablet? */
+#define EVDEVMULTITOUCH_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
+#define EVDEVMULTITOUCH_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
+#define EVDEVMULTITOUCH_MULTITOUCH (1 << 11) /* device looks like a multi-touch screen? */
+#define EVDEVMULTITOUCH_RESOLUTION (1 << 12) /* device has a resolution setting? */
+
+#define MIN_KEYCODE 8
+#define GLYPHS_PER_KEY 2
+#define AltMask                Mod1Mask
+#define NumLockMask    Mod2Mask
+#define AltLangMask    Mod3Mask
+#define KanaMask       Mod4Mask
+#define ScrollLockMask Mod5Mask
+
+#define CAPSFLAG       1
+#define NUMFLAG                2
+#define SCROLLFLAG     4
+#define MODEFLAG       8
+#define COMPOSEFLAG    16
+
+static const char *evdevmultitouchDefaults[] = {
+    "XkbRules",     "evdevmultitouch",
+    "XkbModel",     "evdevmultitouch",
+    "XkbLayout",    "us",
+    NULL
+};
+
+int poll_control(char cmd);
+void sync_poll(int vsync_counter);
+#ifdef _F_GESTURE_EXTENSION_
+extern void mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e);
+static void EvdevMultitouchFrameSync(InputInfoPtr pInfo, MTSyncType sync);
+#endif//_F_GESTURE_EXTENSION_
+static void EvdevMultitouchOff(DeviceIntPtr device);
+static int EvdevMultitouchOn(DeviceIntPtr);
+static int EvdevMultitouchCacheCompare(InputInfoPtr pInfo, BOOL compare);
+static void EvdevMultitouchKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
+static void EvdevMultitouchProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev);
+static void EvdevMultitouchCopyFromData(InputInfoPtr pInfo, EvdevMultitouchDataMTPtr pData);
+static void EvdevMultitouchReinitPEvdevMultitouch(InputInfoPtr pInfo);
+static void EvdevMultitouchFakeOmittedEvents(InputInfoPtr pInfo);
+static void EvdevMultitouchProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
+static void EvdevMultitouchEndOfMultiTouch(InputInfoPtr pInfo,EvdevMultitouchDataMTPtr pData);
+static void EvdevMultitouchSetMultitouch(InputInfoPtr pInfo, int num_multitouch);
+static void EvdevMultitouchSetUsePoll(InputInfoPtr pInfo, BOOL use_poll);
+static void EvdevMultitouchGetGrabInfo(InputInfoPtr pInfo, BOOL val);
+static void EvdevMultitouchSetResolution(InputInfoPtr pInfo, int num_resolution, int resolution[4]);
+static void EvdevMultitouchSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
+static InputInfoPtr EvdevMultitouchCreateSubDevice(InputInfoPtr pInfo, int id);
+static void EvdevMultitouchDeleteSubDevice(InputInfoPtr pInfo, InputInfoPtr subdev);
+static void EvdevMultitouchSwapAxes(EvdevMultitouchPtr pEvdevMultitouch);
+static void EvdevMultitouchSetTransform(InputInfoPtr pInfo, int num_transform, float *tmatrix);
+
+#ifdef HAVE_PROPERTIES
+static void EvdevMultitouchInitAxesLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms);
+static void EvdevMultitouchInitButtonLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms);
+static void EvdevMultitouchInitProperty(DeviceIntPtr dev);
+static int EvdevMultitouchSetProperty(DeviceIntPtr dev, Atom atom,
+                            XIPropertyValuePtr val, BOOL checkonly);
+static Atom prop_invert = 0;
+static Atom prop_reopen = 0;
+static Atom prop_calibration = 0;
+static Atom prop_swap = 0;
+static Atom prop_axis_label = 0;
+static Atom prop_btn_label = 0;
+static Atom prop_tracking_id = 0;
+static Atom prop_multitouch = 0;
+static Atom prop_use_poll = 0;
+static Atom prop_transform = 0;
+static Atom prop_grabinfo = 0;
+#endif
+
+static InputInfoPtr pCreatorInfo = NULL;
+volatile VSYNC_INPUT_DISPATCH_TABLE *vsync_input_table = NULL;
+
+int g_syspoll_fd = -1;
+int g_pressed = 0;
+float transform[9];
+BOOL use_transform = False;
+struct pixman_transform inv_transform;
+
+int
+poll_control(char cmd)
+{
+       if( g_syspoll_fd < 0 )
+               return 0;
+
+       write(g_syspoll_fd, &cmd, 1);
+
+       return 1;
+}
+
+void
+sync_poll(int vsync_counter)
+{
+       if( g_pressed )
+       {
+               vsync_debug_set_slot("Poll before");
+               poll_control(POLL_REQUEST);
+               vsync_debug_set_slot("Poll after");
+       }
+}
+
+/* All devices the evdevmultitouch driver has allocated and knows about.
+ * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
+ * cannot be used by evdevmultitouch, leaving us with a space of 2 at the end. */
+static EvdevMultitouchPtr evdevmultitouch_devices[MAXDEVICES] = {NULL};
+
+static size_t CountBits(unsigned long *array, size_t nlongs)
+{
+    unsigned int i;
+    size_t count = 0;
+
+    for (i = 0; i < nlongs; i++) {
+        unsigned long x = array[i];
+
+        while (x > 0)
+        {
+            count += (x & 0x1);
+            x >>= 1;
+        }
+    }
+    return count;
+}
+
+static int
+EvdevMultitouchGetMajorMinor(InputInfoPtr pInfo)
+{
+    struct stat st;
+
+    if (fstat(pInfo->fd, &st) == -1)
+    {
+        xf86Msg(X_ERROR, "%s: stat failed (%s). cannot check for duplicates.\n",
+                pInfo->name, strerror(errno));
+        return 0;
+    }
+
+    return st.st_rdev;
+}
+
+static BOOL
+EvdevMultitouchIsCoreDevice(InputInfoPtr pInfo) {
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    return pEvdevMultitouch->core_device == pInfo;
+}
+
+/**
+ * Return TRUE if one of the devices we know about has the same min/maj
+ * number.
+ */
+static BOOL
+EvdevMultitouchIsDuplicate(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    EvdevMultitouchPtr* dev   = evdevmultitouch_devices;
+
+    if (pEvdevMultitouch->min_maj)
+    {
+        while(*dev)
+        {
+            if ((*dev) != pEvdevMultitouch &&
+                (*dev)->min_maj &&
+                (*dev)->min_maj == pEvdevMultitouch->min_maj)
+                return TRUE;
+            dev++;
+        }
+    }
+    return FALSE;
+}
+
+/**
+ * Add to internal device list.
+ */
+static void
+EvdevMultitouchAddDevice(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    EvdevMultitouchPtr* dev = evdevmultitouch_devices;
+
+    while(*dev)
+        dev++;
+
+    *dev = pEvdevMultitouch;
+}
+
+/**
+ * Remove from internal device list.
+ */
+static void
+EvdevMultitouchRemoveDevice(InputInfoPtr pInfo)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    EvdevMultitouchPtr *dev   = evdevmultitouch_devices;
+    int count       = 0;
+
+    while(*dev)
+    {
+        count++;
+        if (*dev == pEvdevMultitouch)
+        {
+            memmove(dev, dev + 1,
+                    sizeof(evdevmultitouch_devices) - (count * sizeof(EvdevMultitouchPtr)));
+            break;
+        }
+        dev++;
+    }
+}
+
+
+static void
+SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
+{
+    char *s;
+
+    if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
+        if (!s[0]) {
+            free(s);
+            *option = NULL;
+        } else {
+            *option = s;
+        }
+    }
+}
+
+static int wheel_up_button = 4;
+static int wheel_down_button = 5;
+static int wheel_left_button = 6;
+static int wheel_right_button = 7;
+
+void
+EvdevMultitouchQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
+{
+    int code = ev->code + MIN_KEYCODE;
+    static char warned[KEY_CNT];
+    EventQueuePtr pQueue;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    /* Filter all repeated events from device.
+       We'll do softrepeat in the server, but only since 1.6 */
+    if (value == 2
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) <= 2
+        && (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
+            ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT ||
+            ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT ||
+            ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA ||
+            ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK ||
+            ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */
+#endif
+            )
+       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 (pEvdevMultitouch->num_queue >= EVDEVMULTITOUCH_MAXQUEUE)
+    {
+        xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
+        return;
+    }
+
+    pQueue = &pEvdevMultitouch->queue[pEvdevMultitouch->num_queue];
+    pQueue->type = EV_QUEUE_KEY;
+    pQueue->key = code;
+    pQueue->val = value;
+    pEvdevMultitouch->num_queue++;
+}
+
+void
+EvdevMultitouchQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
+{
+    EventQueuePtr pQueue;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    if (pEvdevMultitouch->num_queue >= EVDEVMULTITOUCH_MAXQUEUE)
+    {
+        xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
+        return;
+    }
+
+    pQueue = &pEvdevMultitouch->queue[pEvdevMultitouch->num_queue];
+    pQueue->type = EV_QUEUE_BTN;
+    pQueue->key = button;
+    pQueue->val = value;
+    pEvdevMultitouch->num_queue++;
+}
+
+/**
+ * Post button event right here, right now.
+ * Interface for MB emulation since these need to post immediately.
+ */
+void
+EvdevMultitouchPostButtonEvent(InputInfoPtr pInfo, int button, int value)
+{
+    xf86PostButtonEvent(pInfo->dev, 0, button, value, 0, 0);
+}
+
+void
+EvdevMultitouchQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
+{
+    int i;
+
+    for (i = 0; i < count; i++) {
+        EvdevMultitouchQueueButtonEvent(pInfo, button, 1);
+        EvdevMultitouchQueueButtonEvent(pInfo, button, 0);
+    }
+}
+
+/**
+ * 
+ */
+static CARD32
+EvdevMultitouchSubdevTimer(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)arg;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    int i;
+    
+    for (i=0;i<pEvdevMultitouch->num_multitouch;i++) {
+        if (pEvdevMultitouch->vals_mt[i].containsValues) {
+            EvdevMultitouchEndOfMultiTouch(pInfo, &(pEvdevMultitouch->vals_mt[i]));
+        }
+    }
+    
+    return 0;
+    //return pEvdevMultitouch->timeout; /* come back in 100 ms */
+}
+
+/**
+ * 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
+EvdevMultitouchReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)arg;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    do {
+        pInfo->fd = open(pEvdevMultitouch->device, O_RDWR | O_NONBLOCK, 0);
+    } while (pInfo->fd < 0 && errno == EINTR);
+
+    if (pInfo->fd != -1)
+    {
+        if (EvdevMultitouchCacheCompare(pInfo, TRUE) == Success)
+        {
+            xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
+                    pEvdevMultitouch->reopen_attempts - pEvdevMultitouch->reopen_left + 1);
+            EvdevMultitouchOn(pInfo->dev);
+        } else
+        {
+            xf86Msg(X_ERROR, "%s: Device has changed - disabling.\n",
+                    pInfo->name);
+            xf86DisableDevice(pInfo->dev, FALSE);
+            close(pInfo->fd);
+            pInfo->fd = -1;
+            pEvdevMultitouch->min_maj = 0; /* don't hog the device */
+        }
+        pEvdevMultitouch->reopen_left = 0;
+        return 0;
+    }
+
+    pEvdevMultitouch->reopen_left--;
+
+    if (!pEvdevMultitouch->reopen_left)
+    {
+        xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
+                pInfo->name, pEvdevMultitouch->reopen_attempts);
+        xf86DisableDevice(pInfo->dev, FALSE);
+        pEvdevMultitouch->min_maj = 0; /* don't hog the device */
+        return 0;
+    }
+
+    return 100; /* come back in 100 ms */
+}
+
+static CARD32
+EvdevMultitouchMultitouchSettingTimer(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)arg;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    int n_multitouch = xf86SetIntOption(pInfo->options, "MultiTouch", 0);
+
+    if( n_multitouch >= 2 )
+           EvdevMultitouchSetMultitouch(pInfo, n_multitouch);
+    pEvdevMultitouch->multitouch_setting_timer = TimerSet(pEvdevMultitouch->multitouch_setting_timer, 0, 0, NULL, NULL);
+       
+    return 0;
+}
+
+#define ABS_X_VALUE 0x1
+#define ABS_Y_VALUE 0x2
+#define ABS_VALUE   0x4
+#define ABS_MT_X_VALUE   0x8
+#define ABS_MT_Y_VALUE   0x10
+#define ABS_MT_TOUCH_MAJOR_VALUE 0x20
+/**
+ * Take the valuators and process them accordingly.
+ */
+static void
+EvdevMultitouchProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+                      int *first_v)
+{
+    int tmp;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    pixman_vector_t p;
+
+    *num_v = *first_v = 0;
+
+    /* convert to relative motion for touchpads */
+    if (pEvdevMultitouch->abs && (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHPAD)) {
+        if (pEvdevMultitouch->tool) { /* meaning, touch is active */
+            if (pEvdevMultitouch->old_vals[0] != -1)
+                pEvdevMultitouch->delta[REL_X] = pEvdevMultitouch->vals[0] - pEvdevMultitouch->old_vals[0];
+            if (pEvdevMultitouch->old_vals[1] != -1)
+                pEvdevMultitouch->delta[REL_Y] = pEvdevMultitouch->vals[1] - pEvdevMultitouch->old_vals[1];
+            if (pEvdevMultitouch->abs & ABS_X_VALUE)
+                pEvdevMultitouch->old_vals[0] = pEvdevMultitouch->vals[0];
+            if (pEvdevMultitouch->abs & ABS_Y_VALUE)
+                pEvdevMultitouch->old_vals[1] = pEvdevMultitouch->vals[1];
+        } else {
+            pEvdevMultitouch->old_vals[0] = pEvdevMultitouch->old_vals[1] = -1;
+        }
+        pEvdevMultitouch->abs = 0;
+        pEvdevMultitouch->rel = 1;
+    }
+
+    if (pEvdevMultitouch->rel) {
+        int first = REL_CNT, last = 0;
+        int i;
+
+        if (pEvdevMultitouch->swap_axes) {
+            tmp = pEvdevMultitouch->delta[REL_X];
+            pEvdevMultitouch->delta[REL_X] = pEvdevMultitouch->delta[REL_Y];
+            pEvdevMultitouch->delta[REL_Y] = tmp;
+        }
+        if (pEvdevMultitouch->invert_x)
+            pEvdevMultitouch->delta[REL_X] *= -1;
+        if (pEvdevMultitouch->invert_y)
+            pEvdevMultitouch->delta[REL_Y] *= -1;
+
+        for (i = 0; i < REL_CNT; i++)
+        {
+            int map = pEvdevMultitouch->axis_map[i];
+            if (map != -1)
+            {
+                v[map] = pEvdevMultitouch->delta[i];
+                if (map < first)
+                    first = map;
+                if (map > last)
+                    last = map;
+            }
+        }
+
+        *num_v = (last - first + 1);
+        *first_v = first;
+    }
+    /*
+     * Some devices only generate valid abs coords when BTN_DIGI is
+     * pressed.  On wacom tablets, this means that the pen is in
+     * proximity of the tablet.  After the pen is removed, BTN_DIGI is
+     * released, and a (0, 0) absolute event is generated.  Checking
+     * pEvdevMultitouch->digi here, lets us ignore that event.  pEvdevMultitouch is
+     * initialized to 1 so devices that doesn't use this scheme still
+     * just works.
+     */
+    else if (pEvdevMultitouch->abs && pEvdevMultitouch->tool) {
+        memcpy(v, pEvdevMultitouch->vals, sizeof(int) * pEvdevMultitouch->num_vals);
+        if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_CALIBRATED)
+        {
+            v[0] = xf86ScaleAxis(v[0],
+                    pEvdevMultitouch->absinfo[ABS_X].maximum,
+                    pEvdevMultitouch->absinfo[ABS_X].minimum,
+                    pEvdevMultitouch->calibration.max_x, pEvdevMultitouch->calibration.min_x);
+            v[1] = xf86ScaleAxis(v[1],
+                    pEvdevMultitouch->absinfo[ABS_Y].maximum,
+                    pEvdevMultitouch->absinfo[ABS_Y].minimum,
+                    pEvdevMultitouch->calibration.max_y, pEvdevMultitouch->calibration.min_y);
+        }
+
+        if (pEvdevMultitouch->swap_axes) {
+            int tmp = v[0];
+            v[0] = v[1];
+            v[1] = tmp;
+        }
+
+        if (pEvdevMultitouch->invert_x)
+            v[0] = (pEvdevMultitouch->absinfo[ABS_X].maximum - v[0] +
+                    pEvdevMultitouch->absinfo[ABS_X].minimum);
+        if (pEvdevMultitouch->invert_y)
+            v[1] = (pEvdevMultitouch->absinfo[ABS_Y].maximum - v[1] +
+                    pEvdevMultitouch->absinfo[ABS_Y].minimum);
+
+       if( use_transform )
+       {
+               p.vector[0] = pixman_int_to_fixed(v[0]);
+               p.vector[1] = pixman_int_to_fixed(v[1]);
+               p.vector[2] = pixman_int_to_fixed(1);
+
+               pixman_transform_point(&inv_transform, &p);
+
+               v[0] = pixman_fixed_to_int(p.vector[0]);
+               v[1] = pixman_fixed_to_int(p.vector[1]);
+       }
+
+        *num_v = pEvdevMultitouch->num_vals;
+        *first_v = 0;
+    }
+}
+
+/**
+ * Take a button input event and process it accordingly.
+ */
+static void
+EvdevMultitouchProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    unsigned int button;
+    int value;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    button = EvdevMultitouchUtilButtonEventToButtonNumber(pEvdevMultitouch, ev->code);
+
+    /* Get the signed value, earlier kernels had this as unsigned */
+    value = ev->value;
+
+    /* Handle drag lock */
+    if (EvdevMultitouchDragLockFilterEvent(pInfo, button, value))
+        return;
+
+    if (EvdevMultitouchWheelEmuFilterButton(pInfo, button, value))
+        return;
+
+    if (pEvdevMultitouch->num_multitouch)
+        return;
+    
+    if (EvdevMultitouchMBEmuFilterEvent(pInfo, button, value))
+        return;
+
+    if (button)
+        EvdevMultitouchQueueButtonEvent(pInfo, button, value);
+    else
+        EvdevMultitouchQueueKbdEvent(pInfo, ev, value);
+}
+
+/**
+ * Take the relative motion input event and process it accordingly.
+ */
+static void
+EvdevMultitouchProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    static int value;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    /* Get the signed value, earlier kernels had this as unsigned */
+    value = ev->value;
+
+    pEvdevMultitouch->rel = 1;
+
+    switch (ev->code) {
+        case REL_WHEEL:
+            if (value > 0)
+                EvdevMultitouchQueueButtonClicks(pInfo, wheel_up_button, value);
+            else if (value < 0)
+                EvdevMultitouchQueueButtonClicks(pInfo, wheel_down_button, -value);
+            break;
+
+        case REL_DIAL:
+        case REL_HWHEEL:
+            if (value > 0)
+                EvdevMultitouchQueueButtonClicks(pInfo, wheel_right_button, value);
+            else if (value < 0)
+                EvdevMultitouchQueueButtonClicks(pInfo, wheel_left_button, -value);
+            break;
+
+        /* We don't post wheel events as axis motion. */
+        default:
+            /* Ignore EV_REL events if we never set up for them. */
+            if (!(pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS))
+                return;
+
+            /* Handle mouse wheel emulation */
+            if (EvdevMultitouchWheelEmuFilterMotion(pInfo, ev))
+                return;
+
+            pEvdevMultitouch->delta[ev->code] += value;
+            break;
+    }
+}
+
+/**
+ * Take the absolute motion input event and process it accordingly.
+ */
+static void
+EvdevMultitouchProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    static int value;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    /* Get the signed value, earlier kernels had this as unsigned */
+    value = ev->value;
+
+    /* Ignore EV_ABS events if we never set up for them. */
+    if (!(pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS))
+        return;
+
+    if (ev->code > ABS_MAX)
+        return;
+
+    pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ev->code]] = value;
+
+    if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
+    {
+        if(ev->code == ABS_MT_TOUCH_MAJOR)
+        {
+#ifdef _DEBUG_MT_SEQUENCE_
+            ErrorF("[AbsoluteMotionEvent] ABS_MT_TOUCH_MAJOR (value=%d)\n", value);
+#endif
+            pEvdevMultitouch->abs |= ABS_MT_TOUCH_MAJOR_VALUE;
+        }
+        else if (ev->code == ABS_MT_POSITION_X)
+        {
+#ifdef _DEBUG_MT_SEQUENCE_
+            ErrorF("[AbsoluteMotionEvent] ABS_MT_POSITION_X (value=%d)\n", value);
+#endif
+            EvdevMultitouchFakeOmittedEvents(pInfo);
+            pEvdevMultitouch->abs |= ABS_MT_X_VALUE;
+        }
+        else if (ev->code == ABS_MT_POSITION_Y)
+        {
+#ifdef _DEBUG_MT_SEQUENCE_
+            ErrorF("[AbsoluteMotionEvent] ABS_MT_POSITION_Y (value=%d)\n", value);
+#endif
+            EvdevMultitouchFakeOmittedEvents(pInfo);
+            pEvdevMultitouch->abs |= ABS_MT_Y_VALUE;
+        }
+        else
+            pEvdevMultitouch->abs |= ABS_VALUE;
+    }
+    else
+    {
+        if (ev->code == ABS_X)
+        {
+#ifdef _DEBUG_MT_SEQUENCE_
+            ErrorF("[AbsoluteMotionEvent] ABS_X (value=%d)\n", value);
+#endif
+            pEvdevMultitouch->abs |= ABS_X_VALUE;
+        }
+        else if (ev->code == ABS_Y)
+        {
+#ifdef _DEBUG_MT_SEQUENCE_
+            ErrorF("[AbsoluteMotionEvent] ABS_Y (value=%d)\n", value);
+#endif
+            pEvdevMultitouch->abs |= ABS_Y_VALUE;
+        }
+        else
+            pEvdevMultitouch->abs |= ABS_VALUE;
+    }        
+}
+
+/**
+ * Take the key press/release input event and process it accordingly.
+ */
+static void
+EvdevMultitouchProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    static int value;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
+        return;
+
+    /* Get the signed value, earlier kernels had this as unsigned */
+    value = ev->value;
+
+    /* don't repeat mouse buttons */
+    if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
+        if (value == 2)
+            return;
+
+#ifdef _DEBUG_MT_SEQUENCE_
+       if( ev->code == BTN_TOUCH || ev->code == BTN_LEFT )
+               ErrorF("[KeyEvent] BTN_TOUCH (value=%d)\n", value);
+#endif
+
+    switch (ev->code) {
+        case BTN_TOUCH:
+        case BTN_TOOL_PEN:
+        case BTN_TOOL_RUBBER:
+        case BTN_TOOL_BRUSH:
+        case BTN_TOOL_PENCIL:
+        case BTN_TOOL_AIRBRUSH:
+        case BTN_TOOL_FINGER:
+        case BTN_TOOL_MOUSE:
+        case BTN_TOOL_LENS:
+            pEvdevMultitouch->tool = value ? ev->code : 0;
+            if (!(pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHSCREEN || pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH))
+                break;
+            /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
+             * BTN_LEFT. */
+            ev->code = BTN_LEFT;
+            /* Intentional fallthrough! */
+
+        default:
+            EvdevMultitouchProcessButtonEvent(pInfo, ev);
+            break;
+    }
+}
+
+static void EvdevMultitouchEndOfMultiTouch(InputInfoPtr pInfo,EvdevMultitouchDataMTPtr pData)
+{
+    InputInfoPtr pSubdev = pData->pInfo;
+    EvdevMultitouchPtr pEvdevMultitouchSubdev = pSubdev->private;
+    pEvdevMultitouchSubdev->id = -1;
+    pData->containsValues = FALSE;
+    pData->id = -1;
+}
+
+#ifdef _F_GESTURE_EXTENSION_
+static void EvdevMultitouchFrameSync(InputInfoPtr pInfo, MTSyncType sync)
+{
+       AnyEvent event;
+
+       memset(&event, 0, sizeof(event));
+       event.header = ET_Internal;
+       event.type = ET_MTSync;
+       event.length = sizeof(event);
+       event.time = GetTimeInMillis();
+       event.deviceid = pInfo->dev->id;
+       event.sync = sync;
+       mieqEnqueue (pInfo->dev, (InternalEvent*)&event);
+}
+#endif//_F_GESTURE_EXTENSION_
+
+/**
+ * Post the multtouch motion events.
+ */
+static void
+EvdevMultitouchPostMTMotionEvents(InputInfoPtr pInfo,struct input_event *ev)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private, pEvdevMultitouchSubdev;
+    EvdevMultitouchDataMTPtr pData;
+    InputInfoPtr pSubdev;
+    int i;
+    static int num_of_pressed = 0;
+
+    for (i=0;i<pEvdevMultitouch->num_multitouch;++i) {
+        pData = &(pEvdevMultitouch->vals_mt[i]);
+        if (!pData->containsValues) {
+            continue;
+        }
+        pSubdev = pData->pInfo;
+        if (!pSubdev)
+            continue;
+
+        pData->containsValues = FALSE;
+        EvdevMultitouchCopyFromData(pSubdev, pData);
+        pEvdevMultitouchSubdev = pSubdev->private;
+        pEvdevMultitouchSubdev->mt = 0;
+        pEvdevMultitouchSubdev->abs = pData->abs;
+        pEvdevMultitouchSubdev->rel = 0;
+        pEvdevMultitouchSubdev->tool = 1;
+        /* droping of the pressed/released events */
+        memset(pEvdevMultitouchSubdev->queue, 0, sizeof(pEvdevMultitouchSubdev->queue));
+        pEvdevMultitouchSubdev->num_queue = 0;
+
+        /* generate button press/release event */
+        if(pEvdevMultitouchSubdev->abs & ABS_MT_TOUCH_MAJOR_VALUE)
+        {
+            if(pEvdevMultitouchSubdev->vals[pEvdevMultitouchSubdev->axis_map[ABS_MT_TOUCH_MAJOR]] )
+            {
+                if(pEvdevMultitouchSubdev->touch_state == 0)
+                {
+                       num_of_pressed += (pData->id+1);
+                       if( num_of_pressed && !g_pressed )
+                       {
+                          g_pressed = 1;
+#ifdef _F_GESTURE_EXTENSION_
+                          EvdevMultitouchFrameSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
+#endif//_F_GESTURE_EXTENSION_
+                         if(vsync_input_table)
+                        {
+                               vsync_input_table->start_sync(vsync_input_table->sync_arg);
+                               vsync_debug_start();
+                           }
+                       }
+                    EvdevMultitouchQueueButtonEvent(pSubdev, 1, 1);
+                    pEvdevMultitouchSubdev->touch_state = 1;
+                }
+            }
+            else
+            {
+                 num_of_pressed -= (pData->id+1);
+                 /* last finger release */
+                 if( !num_of_pressed )
+                 {
+                       g_pressed = 0;
+                      if(vsync_input_table)
+                       {
+                               vsync_input_table->stop_sync(vsync_input_table->sync_arg);
+                               vsync_debug_stop();
+                       }
+                 }
+                EvdevMultitouchQueueButtonEvent(pSubdev, 1, 0);
+                pEvdevMultitouchSubdev->touch_state = 0;
+                pEvdevMultitouchSubdev->evtime = 0;
+            }
+        }
+        EvdevMultitouchProcessSyncEvent(pSubdev, ev);
+        
+    }
+}
+
+static void
+EvdevMultitouchPostMTMotionEventsBySingle(InputInfoPtr pInfo,struct input_event *ev)
+{
+    EvdevMultitouchPtr pEvdevMultitouch, pEvdevMultitouchSubdev;
+    EvdevMultitouchDataMTPtr pData;
+    InputInfoPtr pSubdev;
+
+    if( !pInfo || !pInfo->private )
+       return;
+
+    pEvdevMultitouch = pInfo->private;
+
+    pData = &(pEvdevMultitouch->vals_mt[0]);
+
+    if (!pData->containsValues) {
+        return;
+    }
+    
+    pSubdev = pInfo;
+    pData->containsValues = FALSE;
+    EvdevMultitouchCopyFromData(pSubdev, pData);
+    pEvdevMultitouchSubdev = pSubdev->private;
+    pEvdevMultitouchSubdev->mt = 0;
+    pEvdevMultitouchSubdev->abs = pData->abs;
+    pEvdevMultitouchSubdev->rel = 0;
+    pEvdevMultitouchSubdev->tool = 1;
+    /* droping of the pressed/released events */
+    memset(pEvdevMultitouchSubdev->queue, 0, sizeof(pEvdevMultitouchSubdev->queue));
+    pEvdevMultitouchSubdev->num_queue = 0;
+
+    /* generate button press/release event */
+    if(pEvdevMultitouchSubdev->abs & ABS_MT_TOUCH_MAJOR_VALUE)
+    {
+        if(pEvdevMultitouchSubdev->vals[pEvdevMultitouchSubdev->axis_map[ABS_MT_TOUCH_MAJOR]] )
+        {
+            if(pEvdevMultitouchSubdev->touch_state == 0)
+            {
+                EvdevMultitouchQueueButtonEvent(pSubdev, 1, 1);
+                pEvdevMultitouchSubdev->touch_state = 1;
+                 g_pressed = 1;
+#ifdef _F_GESTURE_EXTENSION_
+                 EvdevMultitouchFrameSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
+#endif//_F_GESTURE_EXTENSION_
+                 if(vsync_input_table)
+                {
+                       vsync_input_table->start_sync(vsync_input_table->sync_arg);
+                        vsync_debug_start();
+                  }
+            }
+        }
+        else
+        {
+            g_pressed = 0;
+            if(vsync_input_table)
+            {
+                  vsync_input_table->stop_sync(vsync_input_table->sync_arg);
+                   vsync_debug_stop();
+            }
+            EvdevMultitouchQueueButtonEvent(pSubdev, 1, 0);
+            pEvdevMultitouchSubdev->touch_state = 0;
+            pEvdevMultitouchSubdev->evtime = 0;
+        }
+    }
+
+    EvdevMultitouchProcessSyncEvent(pSubdev, ev);
+}
+
+/**
+ * Post the relative motion events.
+ */
+void
+EvdevMultitouchPostRelativeMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
+                              int v[MAX_VALUATORS])
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    if (pEvdevMultitouch->rel) {
+        xf86PostMotionEventP(pInfo->dev, FALSE, *first_v, *num_v, v + *first_v);
+    }
+}
+
+/**
+ * Post the absolute motion events.
+ */
+void
+EvdevMultitouchPostAbsoluteMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
+                              int v[MAX_VALUATORS])
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    /*
+     * Some devices only generate valid abs coords when BTN_DIGI is
+     * pressed.  On wacom tablets, this means that the pen is in
+     * proximity of the tablet.  After the pen is removed, BTN_DIGI is
+     * released, and a (0, 0) absolute event is generated.  Checking
+     * pEvdevMultitouch->digi here, lets us ignore that event.  pEvdevMultitouch is
+     * initialized to 1 so devices that doesn't use this scheme still
+     * just works.
+     */
+    if (pEvdevMultitouch->abs && pEvdevMultitouch->tool) {
+        xf86PostMotionEventP(pInfo->dev, TRUE, *first_v, *num_v, v);
+    }
+}
+
+/**
+ * Post the queued key/button events.
+ */
+static void EvdevMultitouchPostQueuedEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
+                                  int v[MAX_VALUATORS])
+{
+    int i;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    for (i = 0; i < pEvdevMultitouch->num_queue; i++) {
+        switch (pEvdevMultitouch->queue[i].type) {
+        case EV_QUEUE_KEY:
+            xf86PostKeyboardEvent(pInfo->dev, pEvdevMultitouch->queue[i].key,
+                                  pEvdevMultitouch->queue[i].val);
+            break;
+        case EV_QUEUE_BTN:
+            /* FIXME: Add xf86PostButtonEventP to the X server so that we may
+             * pass the valuators on ButtonPress/Release events, too.  Currently
+             * only MotionNotify events contain the pointer position. */
+            xf86PostButtonEvent(pInfo->dev, 0, pEvdevMultitouch->queue[i].key,
+                                pEvdevMultitouch->queue[i].val, 0, 0);
+            break;
+        }
+    }
+}
+static void
+EvdevMultitouchCopyFromData(InputInfoPtr pInfo, EvdevMultitouchDataMTPtr pData) {
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    memcpy(pEvdevMultitouch->vals, pData->vals, MAX_VALUATORS * sizeof(int));
+    /* we drop the buttons/key events */
+}
+
+static void
+EvdevMultitouchStoreMTData(InputInfoPtr pInfo, EvdevMultitouchDataMTPtr pData) {
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    int id,x,y;
+    Time currentTime = GetTimeInMillis();
+
+    id = pEvdevMultitouch->current_id;
+
+    if(pEvdevMultitouch->abs & ABS_MT_X_VALUE)
+        x = pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_POSITION_X]];
+    else
+        x = pData->vals[pEvdevMultitouch->axis_map[ABS_X]]; 
+        
+    if(pEvdevMultitouch->abs & ABS_MT_Y_VALUE)    
+        y = pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_POSITION_Y]];
+    else
+        y = pData->vals[pEvdevMultitouch->axis_map[ABS_Y]];
+
+    {
+        EvdevMultitouchPtr pEvdevMultitouchSub = pData->pInfo->private;
+        pEvdevMultitouchSub->evtime = currentTime;
+    }
+
+    pData->id = id;
+    memcpy(pData->vals, pEvdevMultitouch->vals, MAX_VALUATORS * sizeof(int));
+    pData->vals[pEvdevMultitouch->axis_map[ABS_X]] = x;
+    pData->vals[pEvdevMultitouch->axis_map[ABS_Y]] = y;
+    pData->containsValues = TRUE;
+    pData->expires = currentTime + pEvdevMultitouch->timeout;
+    pData->abs = pEvdevMultitouch->abs;
+
+    return;
+}
+
+/**
+ * Take the synchronization input event and process it accordingly; the motion
+ * notify events are sent first, then any button/key press/release events.
+ */
+static void
+EvdevMultitouchProcessMTSyncReport(InputInfoPtr pInfo, struct input_event *ev)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    int id;
+
+    id = pEvdevMultitouch->current_id;
+    
+    if (id < 0) {
+        EvdevMultitouchReinitPEvdevMultitouch(pInfo);
+        return;
+    }
+
+    if(pEvdevMultitouch->num_multitouch == 0) //Single mode
+    {
+        if(id != 0)
+        {
+            EvdevMultitouchReinitPEvdevMultitouch(pInfo);
+            return;
+        }
+    }
+    else
+    {
+        if (id > pEvdevMultitouch->num_multitouch-1)
+        {
+            EvdevMultitouchReinitPEvdevMultitouch(pInfo);
+            return;
+        }      
+    }
+
+    EvdevMultitouchStoreMTData(pInfo, &(pEvdevMultitouch->vals_mt[id]));
+    EvdevMultitouchReinitPEvdevMultitouch(pInfo);
+    pEvdevMultitouch->mt = 1;
+    pEvdevMultitouch->sync_mt = 1;
+}
+
+static void
+EvdevMultitouchReinitPEvdevMultitouch(InputInfoPtr pInfo) {
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    memset(pEvdevMultitouch->delta, 0, sizeof(pEvdevMultitouch->delta));
+    memset(pEvdevMultitouch->queue, 0, sizeof(pEvdevMultitouch->queue));
+    pEvdevMultitouch->num_queue = 0;
+    pEvdevMultitouch->abs = 0;
+    pEvdevMultitouch->rel = 0;
+    pEvdevMultitouch->mt = 0;
+    pEvdevMultitouch->num_mt = 0;
+    pEvdevMultitouch->current_id = -1;
+    pEvdevMultitouch->sync_mt = 0;
+}
+
+/**
+ * Take the synchronization input event and process it accordingly; the motion
+ * notify events are sent first, then any button/key press/release events.
+ */
+static void
+EvdevMultitouchProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    int num_v = 0, first_v = 0;
+    int v[MAX_VALUATORS];
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    
+    if (ev->code == SYN_MT_REPORT) {
+        EvdevMultitouchProcessMTSyncReport(pInfo, ev);
+        return;
+    }
+
+    if( 0 <= pEvdevMultitouch->current_id && !pEvdevMultitouch->sync_mt )
+    {
+#ifdef _DEBUG_MT_SEQUENCE_
+       if( pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_TOUCH_MAJOR]] )
+               ErrorF("[SyncEvent] Press or Motion !(current->id=%d)\n", pEvdevMultitouch->current_id);
+       else
+               ErrorF("[SyncEvent] Release!(current->id=%d)\n\n", pEvdevMultitouch->current_id);
+#endif
+
+        EvdevMultitouchProcessMTSyncReport(pInfo, ev);
+    }
+
+    if (pEvdevMultitouch->mt) {
+        if(pEvdevMultitouch->num_multitouch > 1)
+        {
+            EvdevMultitouchPostMTMotionEvents(pInfo, ev);
+        }
+        else
+        {
+            EvdevMultitouchPostMTMotionEventsBySingle(pInfo, ev);
+        }
+    } else {
+        EvdevMultitouchProcessValuators(pInfo, v, &num_v, &first_v);
+
+        vsync_debug_set_slot("Input %d %d %d", 1, v[0], v[1]);
+
+        EvdevMultitouchPostRelativeMotionEvents(pInfo, &num_v, &first_v, v);
+        EvdevMultitouchPostAbsoluteMotionEvents(pInfo, &num_v, &first_v, v);
+        EvdevMultitouchPostQueuedEvents(pInfo, &num_v, &first_v, v);
+#ifdef _F_GESTURE_EXTENSION_
+       if( !g_pressed )
+            EvdevMultitouchFrameSync(pInfo, MTOUCH_FRAME_SYNC_END);
+#endif//_F_GESTURE_EXTENSION_
+    }
+    
+    EvdevMultitouchReinitPEvdevMultitouch(pInfo);
+}
+
+/**
+ * Take the trackingID input event and process it accordingly.
+ */
+static void
+EvdevMultitouchProcessTrackingIDEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    // begining of a new touch
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    pEvdevMultitouch->last_slot = pEvdevMultitouch->current_id = ev->value;
+#ifdef _DEBUG_MT_SEQUENCE_
+    ErrorF("[TrackingIDEvent] current_id=%d, last_slot=%d\n", pEvdevMultitouch->current_id, pEvdevMultitouch->last_slot);
+#endif
+}
+
+/**
+ * Process the events from the device; nothing is actually posted to the server
+ * until an EV_SYN event is received.
+ */
+static char* ev_name(int type, int code, int value)
+{
+   static char ename[100];
+
+   char *stype = NULL;
+   char *scode = NULL;
+   char *svalue = NULL;
+
+   char ttype[50];
+   char tcode[50];
+   char tvalue[50];
+   
+   switch(type)
+   {
+   case EV_SYN:
+      stype = "EV_SYNC";
+      switch(code)
+      {
+      case SYN_REPORT:
+         scode = "SYN_REPORT";
+         break;
+      case SYN_CONFIG:
+         scode = "SYN_CONFIG";
+         break;
+      case SYN_MT_REPORT:
+         scode = "SYN_MT_REPORT";
+         break;
+      }
+      break;
+   case EV_KEY:
+      stype = "EV_KEY";
+      break;
+   case EV_REL:
+      stype = "EV_REL";
+      break;
+   case EV_ABS:
+      stype = "EV_ABS";
+      switch(code)
+      {
+      case ABS_X:
+         scode =  "ABS_X";
+         break;
+      case ABS_Y:
+         scode =  "ABS_Y";
+         break;
+      case ABS_PRESSURE:
+         scode =  "ABS_PRESSURE";
+         break;
+      case ABS_MT_TOUCH_MAJOR:
+         scode =  "ABS_MT_TOUCH_MAJOR";
+         break;
+      case ABS_MT_TOUCH_MINOR:
+         scode =  "ABS_MT_TOUCH_MINOR";
+         break;
+      case ABS_MT_WIDTH_MAJOR:
+         scode =  "ABS_MT_WIDTH_MAJOR";
+         break;
+      case ABS_MT_WIDTH_MINOR:
+         scode =  "ABS_MT_WIDTH_MINOR";
+         break;
+      case ABS_MT_ORIENTATION:
+         scode =  "ABS_MT_ORIENTATION";
+         break;
+      case ABS_MT_POSITION_X:
+         scode =  "ABS_MT_POSITION_X";
+         break;
+      case ABS_MT_POSITION_Y:
+         scode =  "ABS_MT_POSITION_Y";
+         break;
+      case ABS_MT_TOOL_TYPE:
+         scode =  "ABS_MT_TOOL_TYPE";
+         break;
+      case ABS_MT_BLOB_ID:
+         scode =  "ABS_MT_BLOB_ID";
+         break;
+      case ABS_MT_TRACKING_ID:
+         scode =  "ABS_MT_TRACKING_ID";
+         break;
+      case ABS_MT_SLOT:
+         scode =  "ABS_MT_SLOT";
+         break;
+      }
+   default:
+      break;
+   }
+
+   if(!stype)
+   {
+      sprintf(ttype, "T(0x%x)", type);
+      stype = ttype;
+   }
+
+   if(!scode)
+   {
+      sprintf(tcode, "C(0x%x)", code);
+      scode = tcode;
+   }
+
+   if(!svalue)
+   {
+      sprintf(tvalue, "V(%d)",value);
+      svalue = tvalue;
+   }
+
+   sprintf(ename, "%s : %s : %s", stype, scode, svalue);
+   return ename;
+}
+
+static void EvdevMultitouchFakeOmittedEvents(InputInfoPtr pInfo)
+{
+       EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+       if( !(pEvdevMultitouch->abs & ABS_MT_TOUCH_MAJOR_VALUE) )
+       {
+               pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_TOUCH_MAJOR]] = 1;
+               pEvdevMultitouch->abs |= ABS_MT_TOUCH_MAJOR_VALUE;
+#ifdef _DEBUG_MT_SEQUENCE_
+               ErrorF("\t...Fake ABS_MT_TOUCH_MAJOR\n");
+#endif
+       }
+
+       if( pEvdevMultitouch->current_id < 0 )
+       {
+               pEvdevMultitouch->current_id = pEvdevMultitouch->last_slot;
+#ifdef _DEBUG_MT_SEQUENCE_
+               ErrorF("\t...Fake ABS_MT_SLOT (current_id=%d)\n", pEvdevMultitouch->current_id);
+#endif
+       }
+}
+
+static void
+EvdevMultitouchProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+       
+    switch (ev->type) {
+        case EV_REL:
+            return;
+            EvdevMultitouchProcessRelativeMotionEvent(pInfo, ev);
+            break;
+        case EV_ABS:
+            switch(ev->code)
+            {
+            case ABS_X:
+            case ABS_Y:
+            case ABS_PRESSURE:
+                return;
+            }
+                       
+            if( ev->code == ABS_MT_TRACKING_ID )
+            {
+#ifdef _DEBUG_MT_SEQUENCE_
+                 ErrorF("[ProcessEvent] ABS_MT_TRACKING_ID (value=%d)\n", ev->value);
+#endif
+
+                 if( pEvdevMultitouch->mt_slot_supported )
+                 {//MT protocol B Type
+                        if( pEvdevMultitouch->current_id < 0 )
+                        {
+                               pEvdevMultitouch->current_id = pEvdevMultitouch->last_slot;
+                        }
+                         
+                        if( 0 > ev->value )//ABS_MT_TRACKING_ID == -1
+                         {
+#ifdef _DEBUG_MT_SEQUENCE_
+                             ErrorF("\t...Fake ABS_MT_TOUCH_MAJOR\n");
+#endif
+                               pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_TOUCH_MAJOR]] = 0;
+                               pEvdevMultitouch->abs |= ABS_MT_TOUCH_MAJOR_VALUE;
+                         }
+                 }
+                 else
+                 {//MT protocol A Type
+                         EvdevMultitouchProcessTrackingIDEvent(pInfo, ev);
+                 }
+            }
+                
+            if (ev->code == ABS_MT_SLOT)
+            {
+#ifdef _DEBUG_MT_SEQUENCE_
+                 ErrorF("[ProcessEvent] ABS_MT_SLOT (value=%d)\n", ev->value);
+#endif
+                EvdevMultitouchProcessTrackingIDEvent(pInfo, ev);
+            }
+            else
+            {
+                EvdevMultitouchProcessAbsoluteMotionEvent(pInfo, ev);
+            }
+            break;
+        case EV_KEY:
+            return;
+            EvdevMultitouchProcessKeyEvent(pInfo, ev);
+            break;
+        case EV_SYN:
+#ifdef _DEBUG_MT_SEQUENCE_
+            if( ev->code == SYN_MT_REPORT )
+               ErrorF("[ProcessEvent] SYN_MT_REPORT (value=%d)\n", ev->value);
+            else
+               ErrorF("[ProcessEvent] SYN_REPORT (value=%d)\n", ev->value);
+#endif
+            EvdevMultitouchProcessSyncEvent(pInfo, ev);
+            break;
+    }
+}
+
+#undef ABS_X_VALUE
+#undef ABS_Y_VALUE
+#undef ABS_VALUE
+
+/* just a magic number to reduce the number of reads */
+#define NUM_EVENTS 16
+
+/**
+ * Empty callback for subdevice.
+ */
+static void
+EvdevMultitouchSubdevReadInput(InputInfoPtr pInfo) {
+    return;
+}
+
+static void
+EvdevMultitouchReadInput(InputInfoPtr pInfo)
+{
+    struct input_event ev[NUM_EVENTS];
+    int i, len = sizeof(ev);
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    while (len == sizeof(ev))
+    {
+        len = read(pInfo->fd, &ev, sizeof(ev));
+        if (len <= 0)
+        {
+            if (errno == ENODEV) /* May happen after resume */
+            {
+                EvdevMultitouchMBEmuFinalize(pInfo);
+                xf86RemoveEnabledDevice(pInfo);
+                close(pInfo->fd);
+                pInfo->fd = -1;
+                if (pEvdevMultitouch->reopen_timer)
+                {
+                    pEvdevMultitouch->reopen_left = pEvdevMultitouch->reopen_attempts;
+                    pEvdevMultitouch->reopen_timer = TimerSet(pEvdevMultitouch->reopen_timer, 0, 100, EvdevMultitouchReopenTimer, pInfo);
+                }
+            } else if (errno != EAGAIN)
+            {
+                /* We use X_NONE here because it doesn't alloc */
+                xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
+                        strerror(errno));
+            }
+            break;
+        }
+
+        /* The kernel promises that we always only read a complete
+         * event, so len != sizeof ev is an error. */
+        if (len % sizeof(ev[0])) {
+            /* We use X_NONE here because it doesn't alloc */
+            xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno));
+            break;
+        }
+
+        for (i = 0; i < len/sizeof(ev[0]); i++)
+            EvdevMultitouchProcessEvent(pInfo, &ev[i]);
+    }
+}
+
+#define TestBit(bit, array) ((array[(bit) / LONG_BITS]) & (1L << ((bit) % LONG_BITS)))
+
+static void
+EvdevMultitouchPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+    /* Nothing to do, dix handles all settings */
+}
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+static KeySym map[] = {
+    /* 0x00 */  NoSymbol,       NoSymbol,
+    /* 0x01 */  XK_Escape,      NoSymbol,
+    /* 0x02 */  XK_1,           XK_exclam,
+    /* 0x03 */  XK_2,           XK_at,
+    /* 0x04 */  XK_3,           XK_numbersign,
+    /* 0x05 */  XK_4,           XK_dollar,
+    /* 0x06 */  XK_5,           XK_percent,
+    /* 0x07 */  XK_6,           XK_asciicircum,
+    /* 0x08 */  XK_7,           XK_ampersand,
+    /* 0x09 */  XK_8,           XK_asterisk,
+    /* 0x0a */  XK_9,           XK_parenleft,
+    /* 0x0b */  XK_0,           XK_parenright,
+    /* 0x0c */  XK_minus,       XK_underscore,
+    /* 0x0d */  XK_equal,       XK_plus,
+    /* 0x0e */  XK_BackSpace,   NoSymbol,
+    /* 0x0f */  XK_Tab,         XK_ISO_Left_Tab,
+    /* 0x10 */  XK_Q,           NoSymbol,
+    /* 0x11 */  XK_W,           NoSymbol,
+    /* 0x12 */  XK_E,           NoSymbol,
+    /* 0x13 */  XK_R,           NoSymbol,
+    /* 0x14 */  XK_T,           NoSymbol,
+    /* 0x15 */  XK_Y,           NoSymbol,
+    /* 0x16 */  XK_U,           NoSymbol,
+    /* 0x17 */  XK_I,           NoSymbol,
+    /* 0x18 */  XK_O,           NoSymbol,
+    /* 0x19 */  XK_P,           NoSymbol,
+    /* 0x1a */  XK_bracketleft, XK_braceleft,
+    /* 0x1b */  XK_bracketright,XK_braceright,
+    /* 0x1c */  XK_Return,      NoSymbol,
+    /* 0x1d */  XK_Control_L,   NoSymbol,
+    /* 0x1e */  XK_A,           NoSymbol,
+    /* 0x1f */  XK_S,           NoSymbol,
+    /* 0x20 */  XK_D,           NoSymbol,
+    /* 0x21 */  XK_F,           NoSymbol,
+    /* 0x22 */  XK_G,           NoSymbol,
+    /* 0x23 */  XK_H,           NoSymbol,
+    /* 0x24 */  XK_J,           NoSymbol,
+    /* 0x25 */  XK_K,           NoSymbol,
+    /* 0x26 */  XK_L,           NoSymbol,
+    /* 0x27 */  XK_semicolon,   XK_colon,
+    /* 0x28 */  XK_quoteright,  XK_quotedbl,
+    /* 0x29 */  XK_quoteleft,  XK_asciitilde,
+    /* 0x2a */  XK_Shift_L,     NoSymbol,
+    /* 0x2b */  XK_backslash,   XK_bar,
+    /* 0x2c */  XK_Z,           NoSymbol,
+    /* 0x2d */  XK_X,           NoSymbol,
+    /* 0x2e */  XK_C,           NoSymbol,
+    /* 0x2f */  XK_V,           NoSymbol,
+    /* 0x30 */  XK_B,           NoSymbol,
+    /* 0x31 */  XK_N,           NoSymbol,
+    /* 0x32 */  XK_M,           NoSymbol,
+    /* 0x33 */  XK_comma,       XK_less,
+    /* 0x34 */  XK_period,      XK_greater,
+    /* 0x35 */  XK_slash,       XK_question,
+    /* 0x36 */  XK_Shift_R,     NoSymbol,
+    /* 0x37 */  XK_KP_Multiply, NoSymbol,
+    /* 0x38 */  XK_Alt_L,      XK_Meta_L,
+    /* 0x39 */  XK_space,       NoSymbol,
+    /* 0x3a */  XK_Caps_Lock,   NoSymbol,
+    /* 0x3b */  XK_F1,          NoSymbol,
+    /* 0x3c */  XK_F2,          NoSymbol,
+    /* 0x3d */  XK_F3,          NoSymbol,
+    /* 0x3e */  XK_F4,          NoSymbol,
+    /* 0x3f */  XK_F5,          NoSymbol,
+    /* 0x40 */  XK_F6,          NoSymbol,
+    /* 0x41 */  XK_F7,          NoSymbol,
+    /* 0x42 */  XK_F8,          NoSymbol,
+    /* 0x43 */  XK_F9,          NoSymbol,
+    /* 0x44 */  XK_F10,         NoSymbol,
+    /* 0x45 */  XK_Num_Lock,    NoSymbol,
+    /* 0x46 */  XK_Scroll_Lock,        NoSymbol,
+    /* These KP keys should have the KP_7 keysyms in the numlock
+     * modifer... ? */
+    /* 0x47 */  XK_KP_Home,    XK_KP_7,
+    /* 0x48 */  XK_KP_Up,      XK_KP_8,
+    /* 0x49 */  XK_KP_Prior,   XK_KP_9,
+    /* 0x4a */  XK_KP_Subtract, NoSymbol,
+    /* 0x4b */  XK_KP_Left,    XK_KP_4,
+    /* 0x4c */  XK_KP_Begin,   XK_KP_5,
+    /* 0x4d */  XK_KP_Right,   XK_KP_6,
+    /* 0x4e */  XK_KP_Add,      NoSymbol,
+    /* 0x4f */  XK_KP_End,     XK_KP_1,
+    /* 0x50 */  XK_KP_Down,    XK_KP_2,
+    /* 0x51 */  XK_KP_Next,    XK_KP_3,
+    /* 0x52 */  XK_KP_Insert,  XK_KP_0,
+    /* 0x53 */  XK_KP_Delete,  XK_KP_Decimal,
+    /* 0x54 */  NoSymbol,      NoSymbol,
+    /* 0x55 */  XK_F13,                NoSymbol,
+    /* 0x56 */  XK_less,       XK_greater,
+    /* 0x57 */  XK_F11,                NoSymbol,
+    /* 0x58 */  XK_F12,                NoSymbol,
+    /* 0x59 */  XK_F14,                NoSymbol,
+    /* 0x5a */  XK_F15,                NoSymbol,
+    /* 0x5b */  XK_F16,                NoSymbol,
+    /* 0x5c */  XK_F17,                NoSymbol,
+    /* 0x5d */  XK_F18,                NoSymbol,
+    /* 0x5e */  XK_F19,                NoSymbol,
+    /* 0x5f */  XK_F20,                NoSymbol,
+    /* 0x60 */  XK_KP_Enter,   NoSymbol,
+    /* 0x61 */  XK_Control_R,  NoSymbol,
+    /* 0x62 */  XK_KP_Divide,  NoSymbol,
+    /* 0x63 */  XK_Print,      XK_Sys_Req,
+    /* 0x64 */  XK_Alt_R,      XK_Meta_R,
+    /* 0x65 */  NoSymbol,      NoSymbol, /* KEY_LINEFEED */
+    /* 0x66 */  XK_Home,       NoSymbol,
+    /* 0x67 */  XK_Up,         NoSymbol,
+    /* 0x68 */  XK_Prior,      NoSymbol,
+    /* 0x69 */  XK_Left,       NoSymbol,
+    /* 0x6a */  XK_Right,      NoSymbol,
+    /* 0x6b */  XK_End,                NoSymbol,
+    /* 0x6c */  XK_Down,       NoSymbol,
+    /* 0x6d */  XK_Next,       NoSymbol,
+    /* 0x6e */  XK_Insert,     NoSymbol,
+    /* 0x6f */  XK_Delete,     NoSymbol,
+    /* 0x70 */  NoSymbol,      NoSymbol, /* KEY_MACRO */
+    /* 0x71 */  NoSymbol,      NoSymbol,
+    /* 0x72 */  NoSymbol,      NoSymbol,
+    /* 0x73 */  NoSymbol,      NoSymbol,
+    /* 0x74 */  NoSymbol,      NoSymbol,
+    /* 0x75 */  XK_KP_Equal,   NoSymbol,
+    /* 0x76 */  NoSymbol,      NoSymbol,
+    /* 0x77 */  NoSymbol,      NoSymbol,
+    /* 0x78 */  XK_F21,                NoSymbol,
+    /* 0x79 */  XK_F22,                NoSymbol,
+    /* 0x7a */  XK_F23,                NoSymbol,
+    /* 0x7b */  XK_F24,                NoSymbol,
+    /* 0x7c */  XK_KP_Separator, NoSymbol,
+    /* 0x7d */  XK_Meta_L,     NoSymbol,
+    /* 0x7e */  XK_Meta_R,     NoSymbol,
+    /* 0x7f */  XK_Multi_key,  NoSymbol,
+    /* 0x80 */  NoSymbol,      NoSymbol,
+    /* 0x81 */  NoSymbol,      NoSymbol,
+    /* 0x82 */  NoSymbol,      NoSymbol,
+    /* 0x83 */  NoSymbol,      NoSymbol,
+    /* 0x84 */  NoSymbol,      NoSymbol,
+    /* 0x85 */  NoSymbol,      NoSymbol,
+    /* 0x86 */  NoSymbol,      NoSymbol,
+    /* 0x87 */  NoSymbol,      NoSymbol,
+    /* 0x88 */  NoSymbol,      NoSymbol,
+    /* 0x89 */  NoSymbol,      NoSymbol,
+    /* 0x8a */  NoSymbol,      NoSymbol,
+    /* 0x8b */  NoSymbol,      NoSymbol,
+    /* 0x8c */  NoSymbol,      NoSymbol,
+    /* 0x8d */  NoSymbol,      NoSymbol,
+    /* 0x8e */  NoSymbol,      NoSymbol,
+    /* 0x8f */  NoSymbol,      NoSymbol,
+    /* 0x90 */  NoSymbol,      NoSymbol,
+    /* 0x91 */  NoSymbol,      NoSymbol,
+    /* 0x92 */  NoSymbol,      NoSymbol,
+    /* 0x93 */  NoSymbol,      NoSymbol,
+    /* 0x94 */  NoSymbol,      NoSymbol,
+    /* 0x95 */  NoSymbol,      NoSymbol,
+    /* 0x96 */  NoSymbol,      NoSymbol,
+    /* 0x97 */  NoSymbol,      NoSymbol,
+    /* 0x98 */  NoSymbol,      NoSymbol,
+    /* 0x99 */  NoSymbol,      NoSymbol,
+    /* 0x9a */  NoSymbol,      NoSymbol,
+    /* 0x9b */  NoSymbol,      NoSymbol,
+    /* 0x9c */  NoSymbol,      NoSymbol,
+    /* 0x9d */  NoSymbol,      NoSymbol,
+    /* 0x9e */  NoSymbol,      NoSymbol,
+    /* 0x9f */  NoSymbol,      NoSymbol,
+    /* 0xa0 */  NoSymbol,      NoSymbol,
+    /* 0xa1 */  NoSymbol,      NoSymbol,
+    /* 0xa2 */  NoSymbol,      NoSymbol,
+    /* 0xa3 */  NoSymbol,      NoSymbol,
+    /* 0xa4 */  NoSymbol,      NoSymbol,
+    /* 0xa5 */  NoSymbol,      NoSymbol,
+    /* 0xa6 */  NoSymbol,      NoSymbol,
+    /* 0xa7 */  NoSymbol,      NoSymbol,
+    /* 0xa8 */  NoSymbol,      NoSymbol,
+    /* 0xa9 */  NoSymbol,      NoSymbol,
+    /* 0xaa */  NoSymbol,      NoSymbol,
+    /* 0xab */  NoSymbol,      NoSymbol,
+    /* 0xac */  NoSymbol,      NoSymbol,
+    /* 0xad */  NoSymbol,      NoSymbol,
+    /* 0xae */  NoSymbol,      NoSymbol,
+    /* 0xaf */  NoSymbol,      NoSymbol,
+    /* 0xb0 */  NoSymbol,      NoSymbol,
+    /* 0xb1 */  NoSymbol,      NoSymbol,
+    /* 0xb2 */  NoSymbol,      NoSymbol,
+    /* 0xb3 */  NoSymbol,      NoSymbol,
+    /* 0xb4 */  NoSymbol,      NoSymbol,
+    /* 0xb5 */  NoSymbol,      NoSymbol,
+    /* 0xb6 */  NoSymbol,      NoSymbol,
+    /* 0xb7 */  NoSymbol,      NoSymbol,
+    /* 0xb8 */  NoSymbol,      NoSymbol,
+    /* 0xb9 */  NoSymbol,      NoSymbol,
+    /* 0xba */  NoSymbol,      NoSymbol,
+    /* 0xbb */  NoSymbol,      NoSymbol,
+    /* 0xbc */  NoSymbol,      NoSymbol,
+    /* 0xbd */  NoSymbol,      NoSymbol,
+    /* 0xbe */  NoSymbol,      NoSymbol,
+    /* 0xbf */  NoSymbol,      NoSymbol,
+    /* 0xc0 */  NoSymbol,      NoSymbol,
+    /* 0xc1 */  NoSymbol,      NoSymbol,
+    /* 0xc2 */  NoSymbol,      NoSymbol,
+    /* 0xc3 */  NoSymbol,      NoSymbol,
+    /* 0xc4 */  NoSymbol,      NoSymbol,
+    /* 0xc5 */  NoSymbol,      NoSymbol,
+    /* 0xc6 */  NoSymbol,      NoSymbol,
+    /* 0xc7 */  NoSymbol,      NoSymbol,
+    /* 0xc8 */  NoSymbol,      NoSymbol,
+    /* 0xc9 */  NoSymbol,      NoSymbol,
+    /* 0xca */  NoSymbol,      NoSymbol,
+    /* 0xcb */  NoSymbol,      NoSymbol,
+    /* 0xcc */  NoSymbol,      NoSymbol,
+    /* 0xcd */  NoSymbol,      NoSymbol,
+    /* 0xce */  NoSymbol,      NoSymbol,
+    /* 0xcf */  NoSymbol,      NoSymbol,
+    /* 0xd0 */  NoSymbol,      NoSymbol,
+    /* 0xd1 */  NoSymbol,      NoSymbol,
+    /* 0xd2 */  NoSymbol,      NoSymbol,
+    /* 0xd3 */  NoSymbol,      NoSymbol,
+    /* 0xd4 */  NoSymbol,      NoSymbol,
+    /* 0xd5 */  NoSymbol,      NoSymbol,
+    /* 0xd6 */  NoSymbol,      NoSymbol,
+    /* 0xd7 */  NoSymbol,      NoSymbol,
+    /* 0xd8 */  NoSymbol,      NoSymbol,
+    /* 0xd9 */  NoSymbol,      NoSymbol,
+    /* 0xda */  NoSymbol,      NoSymbol,
+    /* 0xdb */  NoSymbol,      NoSymbol,
+    /* 0xdc */  NoSymbol,      NoSymbol,
+    /* 0xdd */  NoSymbol,      NoSymbol,
+    /* 0xde */  NoSymbol,      NoSymbol,
+    /* 0xdf */  NoSymbol,      NoSymbol,
+    /* 0xe0 */  NoSymbol,      NoSymbol,
+    /* 0xe1 */  NoSymbol,      NoSymbol,
+    /* 0xe2 */  NoSymbol,      NoSymbol,
+    /* 0xe3 */  NoSymbol,      NoSymbol,
+    /* 0xe4 */  NoSymbol,      NoSymbol,
+    /* 0xe5 */  NoSymbol,      NoSymbol,
+    /* 0xe6 */  NoSymbol,      NoSymbol,
+    /* 0xe7 */  NoSymbol,      NoSymbol,
+    /* 0xe8 */  NoSymbol,      NoSymbol,
+    /* 0xe9 */  NoSymbol,      NoSymbol,
+    /* 0xea */  NoSymbol,      NoSymbol,
+    /* 0xeb */  NoSymbol,      NoSymbol,
+    /* 0xec */  NoSymbol,      NoSymbol,
+    /* 0xed */  NoSymbol,      NoSymbol,
+    /* 0xee */  NoSymbol,      NoSymbol,
+    /* 0xef */  NoSymbol,      NoSymbol,
+    /* 0xf0 */  NoSymbol,      NoSymbol,
+    /* 0xf1 */  NoSymbol,      NoSymbol,
+    /* 0xf2 */  NoSymbol,      NoSymbol,
+    /* 0xf3 */  NoSymbol,      NoSymbol,
+    /* 0xf4 */  NoSymbol,      NoSymbol,
+    /* 0xf5 */  NoSymbol,      NoSymbol,
+    /* 0xf6 */  NoSymbol,      NoSymbol,
+    /* 0xf7 */  NoSymbol,      NoSymbol,
+};
+
+static struct { KeySym keysym; CARD8 mask; } modifiers[] = {
+    { XK_Shift_L,              ShiftMask },
+    { XK_Shift_R,              ShiftMask },
+    { XK_Control_L,            ControlMask },
+    { XK_Control_R,            ControlMask },
+    { XK_Caps_Lock,            LockMask },
+    { XK_Alt_L,                AltMask },
+    { XK_Alt_R,                AltMask },
+    { XK_Meta_L,               Mod4Mask },
+    { XK_Meta_R,               Mod4Mask },
+    { XK_Num_Lock,             NumLockMask },
+    { XK_Scroll_Lock,  ScrollLockMask },
+    { XK_Mode_switch,  AltLangMask }
+};
+
+/* Server 1.6 and earlier */
+static int
+EvdevMultitouchInitKeysyms(DeviceIntPtr device)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+    KeySymsRec keySyms;
+    CARD8 modMap[MAP_LENGTH];
+    KeySym sym;
+    int i, j;
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+     /* Compute the modifier map */
+    memset(modMap, 0, sizeof modMap);
+
+    for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) {
+        sym = map[i * GLYPHS_PER_KEY];
+        for (j = 0; j < ArrayLength(modifiers); j++) {
+            if (modifiers[j].keysym == sym)
+                modMap[i + MIN_KEYCODE] = modifiers[j].mask;
+        }
+    }
+
+    keySyms.map        = map;
+    keySyms.mapWidth   = GLYPHS_PER_KEY;
+    keySyms.minKeyCode = MIN_KEYCODE;
+    keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1;
+
+    XkbSetRulesDflts(pEvdevMultitouch->rmlvo.rules, pEvdevMultitouch->rmlvo.model,
+            pEvdevMultitouch->rmlvo.layout, pEvdevMultitouch->rmlvo.variant,
+            pEvdevMultitouch->rmlvo.options);
+    if (!XkbInitKeyboardDeviceStruct(device, &pEvdevMultitouch->xkbnames,
+                &keySyms, modMap, NULL,
+                EvdevMultitouchKbdCtrl))
+        return 0;
+
+    return 1;
+}
+#endif
+
+static void
+EvdevMultitouchKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+    static struct { int xbit, code; } bits[] = {
+        { CAPSFLAG,    LED_CAPSL },
+        { NUMFLAG,     LED_NUML },
+        { SCROLLFLAG,  LED_SCROLLL },
+        { MODEFLAG,    LED_KANA },
+        { COMPOSEFLAG, LED_COMPOSE }
+    };
+
+    InputInfoPtr pInfo;
+    struct input_event ev[ArrayLength(bits)];
+    int i;
+
+    memset(ev, 0, sizeof(ev));
+
+    pInfo = device->public.devicePrivate;
+    for (i = 0; i < ArrayLength(bits); i++) {
+        ev[i].type = EV_LED;
+        ev[i].code = bits[i].code;
+        ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
+    }
+
+    write(pInfo->fd, ev, sizeof ev);
+}
+
+static int
+EvdevMultitouchAddKeyClass(DeviceIntPtr device)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    /* sorry, no rules change allowed for you */
+    xf86ReplaceStrOption(pInfo->options, "xkb_rules", "evdevmultitouch");
+    SetXkbOption(pInfo, "xkb_rules", &pEvdevMultitouch->rmlvo.rules);
+    SetXkbOption(pInfo, "xkb_model", &pEvdevMultitouch->rmlvo.model);
+    if (!pEvdevMultitouch->rmlvo.model)
+        SetXkbOption(pInfo, "XkbModel", &pEvdevMultitouch->rmlvo.model);
+    SetXkbOption(pInfo, "xkb_layout", &pEvdevMultitouch->rmlvo.layout);
+    if (!pEvdevMultitouch->rmlvo.layout)
+        SetXkbOption(pInfo, "XkbLayout", &pEvdevMultitouch->rmlvo.layout);
+    SetXkbOption(pInfo, "xkb_variant", &pEvdevMultitouch->rmlvo.variant);
+    if (!pEvdevMultitouch->rmlvo.variant)
+        SetXkbOption(pInfo, "XkbVariant", &pEvdevMultitouch->rmlvo.variant);
+    SetXkbOption(pInfo, "xkb_options", &pEvdevMultitouch->rmlvo.options);
+    if (!pEvdevMultitouch->rmlvo.options)
+        SetXkbOption(pInfo, "XkbOptions", &pEvdevMultitouch->rmlvo.options);
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
+    if (!InitKeyboardDeviceStruct(device, &pEvdevMultitouch->rmlvo, NULL, EvdevMultitouchKbdCtrl))
+        return !Success;
+#else
+    if (!EvdevMultitouchInitKeysyms(device))
+        return !Success;
+
+#endif
+
+    pInfo->flags |= XI86_KEYBOARD_CAPABLE;
+
+    return Success;
+}
+
+static int
+EvdevMultitouchAddAbsClass(DeviceIntPtr device)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+    EvdevMultitouchPtr g_pEvdevMultitouch;
+    int num_axes, axis, i = 0;
+    Atom *atoms;
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    g_pEvdevMultitouch = pEvdevMultitouch->core_device->private;
+
+    if (!TestBit(EV_ABS, g_pEvdevMultitouch->bitmask))
+            return !Success;
+
+    num_axes = CountBits(g_pEvdevMultitouch->abs_bitmask, NLONGS(ABS_MAX));
+    if (num_axes < 1)
+        return !Success;
+    pEvdevMultitouch->num_vals = num_axes;
+    memset(pEvdevMultitouch->vals, 0, num_axes * sizeof(int));
+    memset(pEvdevMultitouch->old_vals, -1, num_axes * sizeof(int));
+    atoms = malloc(pEvdevMultitouch->num_vals * sizeof(Atom));
+
+    if( !atoms )
+    {
+        ErrorF("[X11][EvdevMultitouchAddAbsClass] Failed to allocate memory !\n", __FUNCTION__);
+        return !Success;
+    }
+
+    for (axis = ABS_X; axis <= ABS_MAX; axis++) {
+        pEvdevMultitouch->axis_map[axis] = -1;
+        if (!TestBit(axis, pEvdevMultitouch->abs_bitmask))
+            continue;
+        pEvdevMultitouch->axis_map[axis] = i;
+        i++;
+    }
+
+    EvdevMultitouchInitAxesLabels(g_pEvdevMultitouch, g_pEvdevMultitouch->num_vals, atoms);
+
+    if (!InitValuatorClassDeviceStruct(device, num_axes,
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+                                       atoms,
+#endif
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+                                       GetMotionHistory,
+#endif
+                                       GetMotionHistorySize(), Absolute))
+        return !Success;
+
+    for (axis = ABS_X; axis <= ABS_MAX; axis++) {
+        int axnum = g_pEvdevMultitouch->axis_map[axis];
+        if (axnum == -1)
+            continue;
+        xf86InitValuatorAxisStruct(device, axnum,
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+                                   atoms[axnum],
+#endif
+                                   pEvdevMultitouch->absinfo[axis].minimum,
+                                   pEvdevMultitouch->absinfo[axis].maximum,
+                                   10000, 0, 10000);
+        xf86InitValuatorDefaults(device, axnum);
+        pEvdevMultitouch->old_vals[axnum] = -1;
+    }
+
+    free(atoms);
+
+    if (!InitPtrFeedbackClassDeviceStruct(device, EvdevMultitouchPtrCtrlProc))
+        return !Success;
+
+    if ((TestBit(ABS_X, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_Y, pEvdevMultitouch->abs_bitmask)) ||
+        (TestBit(ABS_RX, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_RY, pEvdevMultitouch->abs_bitmask)) ||
+        (TestBit(ABS_HAT0X, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_HAT0Y, pEvdevMultitouch->abs_bitmask)) ||
+        (TestBit(ABS_HAT1X, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_HAT1Y, pEvdevMultitouch->abs_bitmask)) ||
+        (TestBit(ABS_HAT2X, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_HAT2Y, pEvdevMultitouch->abs_bitmask)) ||
+        (TestBit(ABS_HAT3X, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_HAT3Y, pEvdevMultitouch->abs_bitmask)) ||
+        (TestBit(ABS_TILT_X, pEvdevMultitouch->abs_bitmask) &&
+         TestBit(ABS_TILT_Y, pEvdevMultitouch->abs_bitmask)))
+        pInfo->flags |= XI86_POINTER_CAPABLE;
+
+    return Success;
+}
+
+static int
+EvdevMultitouchAddRelClass(DeviceIntPtr device)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+    int num_axes, axis, i = 0;
+    Atom *atoms;
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    if (!TestBit(EV_REL, pEvdevMultitouch->bitmask))
+        return !Success;
+
+    num_axes = CountBits(pEvdevMultitouch->rel_bitmask, NLONGS(REL_MAX));
+    if (num_axes < 1)
+        return !Success;
+
+    /* Wheels are special, we post them as button events. So let's ignore them
+     * in the axes list too */
+    if (TestBit(REL_WHEEL, pEvdevMultitouch->rel_bitmask))
+        num_axes--;
+    if (TestBit(REL_HWHEEL, pEvdevMultitouch->rel_bitmask))
+        num_axes--;
+    if (TestBit(REL_DIAL, pEvdevMultitouch->rel_bitmask))
+        num_axes--;
+
+    if (num_axes <= 0)
+        return !Success;
+
+    pEvdevMultitouch->num_vals = num_axes;
+    memset(pEvdevMultitouch->vals, 0, num_axes * sizeof(int));
+    atoms = malloc(pEvdevMultitouch->num_vals * sizeof(Atom));
+
+    if( !atoms )
+    {
+        ErrorF("[X11][EvdevMultitouchAddRelClass] Failed to allocate memory !\n", __FUNCTION__);
+        return !Success;
+    }
+
+    for (axis = REL_X; axis <= REL_MAX; axis++)
+    {
+        pEvdevMultitouch->axis_map[axis] = -1;
+        /* We don't post wheel events, so ignore them here too */
+        if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL)
+            continue;
+        if (!TestBit(axis, pEvdevMultitouch->rel_bitmask))
+            continue;
+        pEvdevMultitouch->axis_map[axis] = i;
+        i++;
+    }
+
+    EvdevMultitouchInitAxesLabels(pEvdevMultitouch, pEvdevMultitouch->num_vals, atoms);
+
+    if (!InitValuatorClassDeviceStruct(device, num_axes,
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+                                       atoms,
+#endif
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+                                       GetMotionHistory,
+#endif
+                                       GetMotionHistorySize(), Relative))
+        return !Success;
+
+    for (axis = REL_X; axis <= REL_MAX; axis++)
+    {
+        int axnum = pEvdevMultitouch->axis_map[axis];
+
+        if (axnum == -1)
+            continue;
+        xf86InitValuatorAxisStruct(device, axnum,
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+                atoms[axnum],
+#endif
+                -1, -1, 1, 0, 1);
+        xf86InitValuatorDefaults(device, axnum);
+    }
+
+    free(atoms);
+
+    if (!InitPtrFeedbackClassDeviceStruct(device, EvdevMultitouchPtrCtrlProc))
+        return !Success;
+
+    pInfo->flags |= XI86_POINTER_CAPABLE;
+
+    return Success;
+}
+
+static int
+EvdevMultitouchAddButtonClass(DeviceIntPtr device)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+    Atom *labels;
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    labels = malloc(pEvdevMultitouch->num_buttons * sizeof(Atom));
+
+    if( !labels )
+        return !Success;
+
+    EvdevMultitouchInitButtonLabels(pEvdevMultitouch, pEvdevMultitouch->num_buttons, labels);
+
+    if (!InitButtonClassDeviceStruct(device, pEvdevMultitouch->num_buttons,
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+                                     labels,
+#endif
+                                     pEvdevMultitouch->btnmap))
+        return !Success;
+
+    free(labels);
+    return Success;
+}
+
+/**
+ * Init the button mapping for the device. By default, this is a 1:1 mapping,
+ * i.e. Button 1 maps to Button 1, Button 2 to 2, etc.
+ *
+ * If a mapping has been specified, the mapping is the default, with the
+ * user-defined ones overwriting the defaults.
+ * i.e. a user-defined mapping of "3 2 1" results in a mapping of 3 2 1 4 5 6 ...
+ *
+ * Invalid button mappings revert to the default.
+ *
+ * Note that index 0 is unused, button 0 does not exist.
+ * This mapping is initialised for all devices, but only applied if the device
+ * has buttons (in EvdevMultitouchAddButtonClass).
+ */
+static void
+EvdevMultitouchInitButtonMapping(InputInfoPtr pInfo)
+{
+    int         i, nbuttons     = 1;
+    char       *mapping         = NULL;
+    EvdevMultitouchPtr    pEvdevMultitouch          = pInfo->private;
+
+    /* Check for user-defined button mapping */
+    if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
+    {
+        char    *s  = " ";
+        int     btn = 0;
+
+        xf86Msg(X_CONFIG, "%s: ButtonMapping '%s'\n", pInfo->name, mapping);
+        while (s && *s != '\0' && nbuttons < EVDEVMULTITOUCH_MAXBUTTONS)
+        {
+            btn = strtol(mapping, &s, 10);
+
+            if (s == mapping || btn < 0 || btn > EVDEVMULTITOUCH_MAXBUTTONS)
+            {
+                xf86Msg(X_ERROR,
+                        "%s: ... Invalid button mapping. Using defaults\n",
+                        pInfo->name);
+                nbuttons = 1; /* ensure defaults start at 1 */
+                break;
+            }
+
+            pEvdevMultitouch->btnmap[nbuttons++] = btn;
+            mapping = s;
+        }
+    }
+
+    for (i = nbuttons; i < ArrayLength(pEvdevMultitouch->btnmap); i++)
+        pEvdevMultitouch->btnmap[i] = i;
+
+}
+
+static void
+EvdevMultitouchInitAnyClass(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
+{
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS &&
+        EvdevMultitouchAddRelClass(device) == Success)
+        xf86Msg(X_INFO, "%s: initialized for relative axes.\n", device->name);
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS &&
+        EvdevMultitouchAddAbsClass(device) == Success)
+        xf86Msg(X_INFO, "%s: initialized for absolute axes.\n", device->name);
+}
+
+static void
+EvdevMultitouchInitAbsClass(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
+{
+    if (EvdevMultitouchAddAbsClass(device) == Success) {
+
+        xf86Msg(X_INFO,"%s: initialized for absolute axes.\n", device->name);
+
+    } else {
+
+        xf86Msg(X_ERROR,"%s: failed to initialize for absolute axes.\n",
+                device->name);
+
+        pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
+
+    }
+}
+
+static void
+EvdevMultitouchInitRelClass(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
+{
+    int has_abs_axes = pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
+
+    if (EvdevMultitouchAddRelClass(device) == Success) {
+
+        xf86Msg(X_INFO,"%s: initialized for relative axes.\n", device->name);
+
+        if (has_abs_axes) {
+
+            xf86Msg(X_WARNING,"%s: ignoring absolute axes.\n", device->name);
+            pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
+        }
+
+    } else {
+
+        xf86Msg(X_ERROR,"%s: failed to initialize for relative axes.\n",
+                device->name);
+
+        pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_RELATIVE_EVENTS;
+
+        if (has_abs_axes)
+            EvdevMultitouchInitAbsClass(device, pEvdevMultitouch);
+    }
+}
+
+static void
+EvdevMultitouchInitTouchDevice(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
+{
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS) {
+
+        xf86Msg(X_WARNING,"%s: touchpads, tablets and (multi)touchscreens ignore "
+                "relative axes.\n", device->name);
+
+        pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_RELATIVE_EVENTS;
+    }
+
+    EvdevMultitouchInitAbsClass(device, pEvdevMultitouch);
+}
+
+static int
+EvdevMultitouchInit(DeviceIntPtr device)
+{
+    int i;
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    /* clear all axis_map entries */
+    for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
+      pEvdevMultitouch->axis_map[i]=-1;
+
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_KEYBOARD_EVENTS)
+       EvdevMultitouchAddKeyClass(device);
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_BUTTON_EVENTS)
+       EvdevMultitouchAddButtonClass(device);
+
+    /* We don't allow relative and absolute axes on the same device. The
+     * reason is that some devices (MS Optical Desktop 2000) register both
+     * rel and abs axes for x/y.
+     *
+     * The abs axes register min/max; this min/max then also applies to the
+     * relative device (the mouse) and caps it at 0..255 for both axes.
+     * So, unless you have a small screen, you won't be enjoying it much;
+     * consequently, absolute axes are generally ignored.
+     *
+     * However, currenly only a device with absolute axes can be registered
+     * as a touch{pad,screen}. Thus, given such a device, absolute axes are
+     * used and relative axes are ignored.
+     */
+
+    if (pEvdevMultitouch->flags & (EVDEVMULTITOUCH_UNIGNORE_RELATIVE | EVDEVMULTITOUCH_UNIGNORE_ABSOLUTE))
+        EvdevMultitouchInitAnyClass(device, pEvdevMultitouch);
+    else if (pEvdevMultitouch->flags & (EVDEVMULTITOUCH_TOUCHPAD | EVDEVMULTITOUCH_TOUCHSCREEN | EVDEVMULTITOUCH_TABLET | EVDEVMULTITOUCH_MULTITOUCH))
+        EvdevMultitouchInitTouchDevice(device, pEvdevMultitouch);
+    else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS)
+        EvdevMultitouchInitRelClass(device, pEvdevMultitouch);
+    else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS)
+        EvdevMultitouchInitAbsClass(device, pEvdevMultitouch);
+
+#ifdef HAVE_PROPERTIES
+    /* We drop the return value, the only time we ever want the handlers to
+     * unregister is when the device dies. In which case we don't have to
+     * unregister anyway */
+    EvdevMultitouchInitProperty(device);
+    XIRegisterPropertyHandler(device, EvdevMultitouchSetProperty, NULL, NULL);
+    EvdevMultitouchMBEmuInitProperty(device);
+    EvdevMultitouchWheelEmuInitProperty(device);
+    EvdevMultitouchDragLockInitProperty(device);
+#endif
+
+    return Success;
+}
+
+/**
+ * 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
+EvdevMultitouchOn(DeviceIntPtr device)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch;
+    int rc = 0;
+    BOOL finish = False;
+
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    /* If this is an object device,
+     * just add device to subdev list */
+    if (!EvdevMultitouchIsCoreDevice(pInfo)) {
+        finish = True;
+    } else {
+       if (pInfo->fd != -1 && pEvdevMultitouch->grabDevice &&
+            (rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1)))
+        {
+            xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
+                    strerror(errno));
+
+            /* ENODEV - device has disappeared after resume */
+            if (rc && errno == ENODEV)
+            {
+                close(pInfo->fd);
+                pInfo->fd = -1;
+            }
+        }
+
+        if (pInfo->fd == -1)
+        {
+            pEvdevMultitouch->reopen_left = pEvdevMultitouch->reopen_attempts;
+            pEvdevMultitouch->reopen_timer = TimerSet(pEvdevMultitouch->reopen_timer, 0, 100, EvdevMultitouchReopenTimer, pInfo);
+        } else
+        {
+            pEvdevMultitouch->min_maj = EvdevMultitouchGetMajorMinor(pInfo);
+            if (EvdevMultitouchIsDuplicate(pInfo))
+            {
+                xf86Msg(X_WARNING, "%s: Refusing to enable duplicate device.\n",
+                        pInfo->name);
+                
+                return !Success;
+            }
+
+            pEvdevMultitouch->reopen_timer = TimerSet(pEvdevMultitouch->reopen_timer, 0, 0, NULL, NULL);
+
+            xf86FlushInput(pInfo->fd);
+            
+            EvdevMultitouchSetMultitouch(pInfo, pEvdevMultitouch->num_multitouch);
+            
+            finish = True;
+        }
+    }
+
+    if (finish) {
+        if( !strstr(pInfo->name, "subdev" ) )
+       {
+               xf86AddEnabledDevice(pInfo);
+               pEvdevMultitouch->last_slot = 0;
+               EvdevMultitouchReinitPEvdevMultitouch(pInfo);
+       }
+        EvdevMultitouchMBEmuOn(pInfo);
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_INITIALIZED;
+        device->public.on = TRUE;
+
+        pEvdevMultitouch->multitouch_setting_timer = TimerSet(pEvdevMultitouch->multitouch_setting_timer, 0, 100, EvdevMultitouchMultitouchSettingTimer, pInfo);
+    }
+
+    if( pEvdevMultitouch->use_poll != TRUE )
+               return Success;
+
+    EvdevMultitouchSetUsePoll(pInfo, TRUE);
+
+    return Success;
+}
+
+static void
+EvdevMultitouchOff(DeviceIntPtr device)
+{
+       InputInfoPtr pInfo;
+       EvdevMultitouchPtr pEvdevMultitouch;
+
+       pInfo = device->public.devicePrivate;
+       pEvdevMultitouch = pInfo->private;
+
+    if( pEvdevMultitouch->use_poll != TRUE )
+               return;
+
+    EvdevMultitouchSetUsePoll(pInfo, FALSE);
+}
+
+static int
+EvdevMultitouchProc(DeviceIntPtr device, int what)
+{
+    InputInfoPtr pInfo;
+    EvdevMultitouchPtr pEvdevMultitouch, g_pEvdevMultitouch;
+    int i;
+
+
+    pInfo = device->public.devicePrivate;
+    pEvdevMultitouch = pInfo->private;
+
+    switch (what)
+    {
+    case DEVICE_INIT:
+       return EvdevMultitouchInit(device);
+
+    case DEVICE_ON:
+        return EvdevMultitouchOn(device);
+
+    case DEVICE_OFF:
+        EvdevMultitouchOff(device);
+        if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_INITIALIZED)
+            EvdevMultitouchMBEmuFinalize(pInfo);
+        if (EvdevMultitouchIsCoreDevice(pInfo)){
+            EvdevMultitouchSetMultitouch(pInfo, 0);
+            if (pInfo->fd != -1)
+            {
+                if (pEvdevMultitouch->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
+                    xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
+                            strerror(errno));
+                xf86RemoveEnabledDevice(pInfo);
+                close(pInfo->fd);
+                pInfo->fd = -1;
+            }
+            if( pEvdevMultitouch->multitouch_setting_timer )
+            {
+                 TimerFree(pEvdevMultitouch->multitouch_setting_timer);
+                pEvdevMultitouch->multitouch_setting_timer = NULL;
+            }
+            if (pEvdevMultitouch->reopen_timer)
+            {
+                TimerFree(pEvdevMultitouch->reopen_timer);
+                pEvdevMultitouch->reopen_timer = NULL;
+            }
+        } else {
+            /* removing it in the list of the core device */
+            g_pEvdevMultitouch = pEvdevMultitouch->core_device->private;
+            for (i=0; i<MAX_VALUATORS_MT; ++i) {
+                if (g_pEvdevMultitouch->vals_mt[i].pInfo == pInfo) {
+                    g_pEvdevMultitouch->vals_mt[i].pInfo = NULL;
+                    break;
+                }
+            }
+            xf86RemoveEnabledDevice(pInfo);
+        }
+        pEvdevMultitouch->min_maj = 0;
+        pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_INITIALIZED;
+        device->public.on = FALSE;
+    break;
+
+    case DEVICE_CLOSE:
+        xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
+        if (EvdevMultitouchIsCoreDevice(pInfo)) { // master only
+            //EvdevMultitouchDeleteAllSubdevices(pInfo);
+            
+            if (pInfo->fd != -1) {
+                close(pInfo->fd);
+                pInfo->fd = -1;
+            }
+            EvdevMultitouchRemoveDevice(pInfo);
+        }
+        pEvdevMultitouch->min_maj = 0;
+    break;
+    }
+
+    return Success;
+}
+
+/**
+ * Get as much information as we can from the fd and cache it.
+ * If compare is True, then the information retrieved will be compared to the
+ * one already cached. If the information does not match, then this function
+ * returns an error.
+ *
+ * @return Success if the information was cached, or !Success otherwise.
+ */
+static int
+EvdevMultitouchCacheCompare(InputInfoPtr pInfo, BOOL compare)
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    size_t len;
+
+    char name[1024]                  = {0};
+    unsigned long bitmask[NLONGS(EV_CNT)]      = {0};
+    unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0};
+    unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
+    unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
+    unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
+
+    if (ioctl(pInfo->fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
+        xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
+        goto error;
+    }
+
+    if (!compare) {
+        strcpy(pEvdevMultitouch->name, name);
+    } else if (strcmp(pEvdevMultitouch->name, name)) {
+        xf86Msg(X_ERROR, "%s: device name changed: %s != %s\n",
+                pInfo->name, pEvdevMultitouch->name, name);
+        goto error;
+    }
+
+    len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
+    if (len < 0) {
+        xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
+                pInfo->name, strerror(errno));
+        goto error;
+    }
+
+    if (!compare) {
+        memcpy(pEvdevMultitouch->bitmask, bitmask, len);
+    } else if (memcmp(pEvdevMultitouch->bitmask, bitmask, len)) {
+        xf86Msg(X_ERROR, "%s: device bitmask has changed\n", pInfo->name);
+        goto error;
+    }
+
+    len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
+    if (len < 0) {
+        xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
+                pInfo->name, strerror(errno));
+        goto error;
+    }
+
+    if (!compare) {
+        memcpy(pEvdevMultitouch->rel_bitmask, rel_bitmask, len);
+    } else if (memcmp(pEvdevMultitouch->rel_bitmask, rel_bitmask, len)) {
+        xf86Msg(X_ERROR, "%s: device rel_bitmask has changed\n", pInfo->name);
+        goto error;
+    }
+
+    len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
+    if (len < 0) {
+        xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
+                pInfo->name, strerror(errno));
+        goto error;
+    }
+
+#if 1//ABS_MT_SLOT
+    if( TestBit(ABS_MT_SLOT, abs_bitmask) && TestBit(ABS_MT_TRACKING_ID, abs_bitmask) )
+    {
+         ErrorF("[X11] MT Protocol B Type : ABS_MT_SLOT is supported : \n");
+         pEvdevMultitouch->mt_slot_supported = (BOOL)1;
+    }
+    else
+    {
+         ErrorF("[X11] MT Protocol A Type : ABS_MT_SLOT is NOT supported\n");
+         pEvdevMultitouch->mt_slot_supported = (BOOL)0;
+    }
+#endif
+
+    if (!compare) {
+        memcpy(pEvdevMultitouch->abs_bitmask, abs_bitmask, len);
+    } else if (memcmp(pEvdevMultitouch->abs_bitmask, abs_bitmask, len)) {
+        xf86Msg(X_ERROR, "%s: device abs_bitmask has changed\n", pInfo->name);
+        goto error;
+    }
+
+    len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
+    if (len < 0) {
+        xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
+                pInfo->name, strerror(errno));
+        goto error;
+    }
+
+    if (!compare) {
+        memcpy(pEvdevMultitouch->led_bitmask, led_bitmask, len);
+    } else if (memcmp(pEvdevMultitouch->led_bitmask, led_bitmask, len)) {
+        xf86Msg(X_ERROR, "%s: device led_bitmask has changed\n", pInfo->name);
+        goto error;
+    }
+
+    /*
+     * Do not try to validate absinfo data since it is not expected
+     * to be static, always refresh it in evdevmultitouch structure.
+     */
+       if( !xf86CheckStrOption(pInfo->options, "Resolution", NULL) )
+       {
+#ifdef _F_IGNORE_TSP_RESOLUTION_
+           pEvdevMultitouch->absinfo[ABS_X].maximum = 0;
+           pEvdevMultitouch->absinfo[ABS_X].minimum = 0;
+           pEvdevMultitouch->absinfo[ABS_Y].maximum = 0;
+           pEvdevMultitouch->absinfo[ABS_Y].minimum = 0;
+#else//_F_IGNORE_TSP_RESOLUTION_
+           for (i = ABS_X; i <= ABS_MAX; i++) {
+               if (TestBit(i, abs_bitmask)) {
+                   len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdevMultitouch->absinfo[i]);
+                   if (len < 0) {
+                       xf86Msg(X_ERROR, "%s: ioctl EVIOCGABSi(%d) failed: %s\n",
+                               pInfo->name, i, strerror(errno));
+                       goto error;
+                   }
+               }
+           }
+#endif//_F_IGNORE_TSP_RESOLUTION_
+       }
+
+    len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
+    if (len < 0) {
+        xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
+                pInfo->name, strerror(errno));
+        goto error;
+    }
+
+    if (compare) {
+        /*
+         * Keys are special as user can adjust keymap at any time (on
+         * devices that support EVIOCSKEYCODE. However we do not expect
+         * buttons reserved for mice/tablets/digitizers and so on to
+         * appear/disappear so we will check only those in
+         * [BTN_MISC, KEY_OK) range.
+         */
+        size_t start_word = BTN_MISC / LONG_BITS;
+        size_t start_byte = start_word * sizeof(unsigned long);
+        size_t end_word = KEY_OK / LONG_BITS;
+        size_t end_byte = end_word * sizeof(unsigned long);
+
+        if (len >= start_byte &&
+            memcmp(&pEvdevMultitouch->key_bitmask[start_word], &key_bitmask[start_word],
+                   min(len, end_byte) - start_byte + 1)) {
+            xf86Msg(X_ERROR, "%s: device key_bitmask has changed\n", pInfo->name);
+            goto error;
+        }
+    }
+
+    /* Copy the data so we have reasonably up-to-date info */
+    memcpy(pEvdevMultitouch->key_bitmask, key_bitmask, len);
+
+    return Success;
+
+error:
+    return !Success;
+
+}
+
+static int
+EvdevMultitouchProbe(InputInfoPtr pInfo)
+{
+    int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
+    int kernel24 = 0;
+    int ignore_abs = 0, ignore_rel = 0;
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    if (pEvdevMultitouch->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
+        if (errno == EINVAL) {
+            /* keyboards are unsafe in 2.4 */
+            kernel24 = 1;
+            pEvdevMultitouch->grabDevice = 0;
+        } else {
+            xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
+            return 1;
+        }
+    } else if (pEvdevMultitouch->grabDevice) {
+        ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
+    }
+
+    /* Trinary state for ignoring axes:
+       - unset: do the normal thing.
+       - TRUE: explicitly ignore them.
+       - FALSE: unignore axes, use them at all cost if they're present.
+     */
+    if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
+    {
+        if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
+            ignore_rel = TRUE;
+        else
+            pEvdevMultitouch->flags |= EVDEVMULTITOUCH_UNIGNORE_RELATIVE;
+
+    }
+    if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
+    {
+        if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
+           ignore_abs = TRUE;
+        else
+            pEvdevMultitouch->flags |= EVDEVMULTITOUCH_UNIGNORE_ABSOLUTE;
+    }
+
+    has_rel_axes = FALSE;
+    has_abs_axes = FALSE;
+    has_keys = FALSE;
+    has_scroll = FALSE;
+    num_buttons = 0;
+
+    /* count all buttons */
+    for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
+    {
+        int mapping = 0;
+        if (TestBit(i, pEvdevMultitouch->key_bitmask))
+        {
+            mapping = EvdevMultitouchUtilButtonEventToButtonNumber(pEvdevMultitouch, i);
+            if (mapping > num_buttons)
+                num_buttons = mapping;
+        }
+    }
+
+    if (num_buttons)
+    {
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
+        pEvdevMultitouch->num_buttons = num_buttons;
+        xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name,
+                num_buttons);
+    }
+
+    for (i = 0; i < REL_MAX; i++) {
+        if (TestBit(i, pEvdevMultitouch->rel_bitmask)) {
+            has_rel_axes = TRUE;
+            break;
+        }
+    }
+
+    if (has_rel_axes) {
+        if (TestBit(REL_WHEEL, pEvdevMultitouch->rel_bitmask) ||
+            TestBit(REL_HWHEEL, pEvdevMultitouch->rel_bitmask) ||
+            TestBit(REL_DIAL, pEvdevMultitouch->rel_bitmask)) {
+            xf86Msg(X_INFO, "%s: Found scroll wheel(s)\n", pInfo->name);
+            has_scroll = TRUE;
+            if (!num_buttons)
+                xf86Msg(X_INFO, "%s: Forcing buttons for scroll wheel(s)\n",
+                        pInfo->name);
+            num_buttons = (num_buttons < 3) ? 7 : num_buttons + 4;
+            pEvdevMultitouch->num_buttons = num_buttons;
+        }
+
+        if (!ignore_rel)
+        {
+            xf86Msg(X_INFO, "%s: Found relative axes\n", pInfo->name);
+            pEvdevMultitouch->flags |= EVDEVMULTITOUCH_RELATIVE_EVENTS;
+
+            if (TestBit(REL_X, pEvdevMultitouch->rel_bitmask) &&
+                TestBit(REL_Y, pEvdevMultitouch->rel_bitmask)) {
+                xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
+            }
+        } else {
+            xf86Msg(X_INFO, "%s: Relative axes present but ignored.\n", pInfo->name);
+            has_rel_axes = FALSE;
+        }
+    }
+
+    for (i = 0; i < ABS_MAX; i++) {
+        if (TestBit(i, pEvdevMultitouch->abs_bitmask)) {
+            has_abs_axes = TRUE;
+            break;
+        }
+    }
+
+    if (ignore_abs && has_abs_axes)
+    {
+        xf86Msg(X_INFO, "%s: Absolute axes present but ignored.\n", pInfo->name);
+        has_abs_axes = FALSE;
+    } else if (has_abs_axes) {
+        xf86Msg(X_INFO, "%s: Found absolute axes\n", pInfo->name);
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
+
+        if ((TestBit(ABS_X, pEvdevMultitouch->abs_bitmask) &&
+             TestBit(ABS_Y, pEvdevMultitouch->abs_bitmask))) {
+            xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
+            if (TestBit(BTN_TOOL_PEN, pEvdevMultitouch->key_bitmask))
+            {
+                xf86Msg(X_INFO, "%s: Found absolute tablet.\n", pInfo->name);
+                pEvdevMultitouch->flags |= EVDEVMULTITOUCH_TABLET;
+            } else if ((TestBit(ABS_MT_POSITION_X, pEvdevMultitouch->abs_bitmask) &&
+                        TestBit(ABS_MT_POSITION_Y, pEvdevMultitouch->abs_bitmask))) {
+                xf86Msg(X_INFO, "%s: Found absolute multitouch tablet.\n", pInfo->name);
+                pEvdevMultitouch->flags |= EVDEVMULTITOUCH_MULTITOUCH;
+            } else if (TestBit(ABS_PRESSURE, pEvdevMultitouch->abs_bitmask) ||
+                TestBit(BTN_TOUCH, pEvdevMultitouch->key_bitmask)) {
+                if (num_buttons || TestBit(BTN_TOOL_FINGER, pEvdevMultitouch->key_bitmask)) {
+                    xf86Msg(X_INFO, "%s: Found absolute touchpad.\n", pInfo->name);
+                    pEvdevMultitouch->flags |= EVDEVMULTITOUCH_TOUCHPAD;
+                    memset(pEvdevMultitouch->old_vals, -1, sizeof(int) * pEvdevMultitouch->num_vals);
+                } else {
+                    xf86Msg(X_INFO, "%s: Found absolute touchscreen\n", pInfo->name);
+                    pEvdevMultitouch->flags |= EVDEVMULTITOUCH_TOUCHSCREEN;
+                    pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < BTN_MISC; i++) {
+        if (TestBit(i, pEvdevMultitouch->key_bitmask)) {
+            xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name);
+            pEvdevMultitouch->flags |= EVDEVMULTITOUCH_KEYBOARD_EVENTS;
+            has_keys = TRUE;
+            break;
+        }
+    }
+
+    if (has_rel_axes || has_abs_axes || num_buttons) {
+        pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
+                        XI86_CONFIGURED;
+       if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHPAD) {
+           xf86Msg(X_INFO, "%s: Configuring as touchpad\n", pInfo->name);
+           pInfo->type_name = XI_TOUCHPAD;
+       } else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TABLET) {
+           xf86Msg(X_INFO, "%s: Configuring as tablet\n", pInfo->name);
+           pInfo->type_name = XI_TABLET;
+        } else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHSCREEN) {
+            xf86Msg(X_INFO, "%s: Configuring as touchscreen\n", pInfo->name);
+            pInfo->type_name = XI_TOUCHSCREEN;
+        } else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH) {
+            xf86Msg(X_INFO, "%s: Configuring as multitouch screen\n", pInfo->name);
+            pInfo->type_name = "MULTITOUCHSCREEN";
+        } else {
+            xf86Msg(X_INFO, "%s: Configuring as mouse\n", pInfo->name);
+            pInfo->type_name = XI_MOUSE;
+        }
+    }
+
+    if (has_keys) {
+        if (kernel24) {
+            xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n",
+                    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) &&
+        (pInfo->flags & XI86_POINTER_CAPABLE) == 0)
+    {
+        xf86Msg(X_INFO, "%s: Adding scrollwheel support\n", pInfo->name);
+        pInfo->flags  |= XI86_POINTER_CAPABLE;
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_RELATIVE_EVENTS;
+    }
+
+    if ((pInfo->flags & XI86_CONFIGURED) == 0) {
+        xf86Msg(X_WARNING, "%s: Don't know how to use device\n",
+               pInfo->name);
+        return 1;
+    }
+
+    return 0;
+}
+
+static void
+EvdevMultitouchSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    if (num_calibration == 0) {
+        pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_CALIBRATED;
+        pEvdevMultitouch->calibration.min_x = 0;
+        pEvdevMultitouch->calibration.max_x = 0;
+        pEvdevMultitouch->calibration.min_y = 0;
+        pEvdevMultitouch->calibration.max_y = 0;
+    } else if (num_calibration == 4) {
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_CALIBRATED;
+        pEvdevMultitouch->calibration.min_x = calibration[0];
+        pEvdevMultitouch->calibration.max_x = calibration[1];
+        pEvdevMultitouch->calibration.min_y = calibration[2];
+        pEvdevMultitouch->calibration.max_y = calibration[3];
+    }
+}
+
+static void
+EvdevMultitouchSetResolution(InputInfoPtr pInfo, int num_resolution, int resolution[4])
+{
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+
+    if (num_resolution == 0) {
+        pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_RESOLUTION;
+        pEvdevMultitouch->resolution.min_x = 0;
+        pEvdevMultitouch->resolution.max_x = 0;
+        pEvdevMultitouch->resolution.min_y = 0;
+        pEvdevMultitouch->resolution.max_y = 0;
+    } else if (num_resolution == 4) {
+        pEvdevMultitouch->flags |= EVDEVMULTITOUCH_RESOLUTION;
+        pEvdevMultitouch->resolution.min_x = resolution[0];
+        pEvdevMultitouch->resolution.max_x = resolution[1];
+        pEvdevMultitouch->resolution.min_y = resolution[2];
+        pEvdevMultitouch->resolution.max_y = resolution[3];
+    }
+}
+
+static void EvdevMultitouchSetTransform(InputInfoPtr pInfo, int num_transform, float *tmatrix)
+{
+       int x, y;
+       struct pixman_transform tr;
+
+       if( num_transform != 9 )
+       {
+               use_transform = False;
+               return;
+       }
+       use_transform = True;
+
+       memcpy(transform, tmatrix, sizeof(transform));
+       for (y=0; y<3; y++)
+               for (x=0; x<3; x++)
+                       tr.matrix[y][x] = pixman_double_to_fixed((double)*tmatrix++);
+
+       pixman_transform_invert(&inv_transform, &tr);
+}
+
+static void
+EvdevMultitouchSetMultitouch(InputInfoPtr pInfo, int num_multitouch) {
+    EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+    int i, rc;
+
+    if( !(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH) ) 
+    { 
+            ErrorF("[X11][%s] Device is not a multitouch screen !(flags=%d)\n", __FUNCTION__, pEvdevMultitouch->flags); 
+            return; 
+    }
+
+    if (num_multitouch > MAX_VALUATORS_MT)
+        num_multitouch = MAX_VALUATORS_MT;
+    if (num_multitouch < 0)
+        num_multitouch = 0;
+
+    for (i=0;i<num_multitouch;++i) {
+        if (pEvdevMultitouch->vals_mt[i].pInfo == NULL){
+            pEvdevMultitouch->vals_mt[i].containsValues = FALSE;
+            pEvdevMultitouch->vals_mt[i].id = -1;
+            pEvdevMultitouch->vals_mt[i].pInfo = EvdevMultitouchCreateSubDevice(pInfo, i);
+        }
+    }
+    for (i=num_multitouch;i<MAX_VALUATORS_MT;++i) {
+        pEvdevMultitouch->vals_mt[i].containsValues = FALSE;
+        pEvdevMultitouch->vals_mt[i].id = -1;
+        if (pEvdevMultitouch->vals_mt[i].pInfo && pEvdevMultitouch->vals_mt[i].pInfo != pInfo) {
+            EvdevMultitouchDeleteSubDevice(pInfo, pEvdevMultitouch->vals_mt[i].pInfo);
+            pEvdevMultitouch->vals_mt[i].pInfo = NULL;
+        }
+    }
+    
+    pEvdevMultitouch->num_multitouch = num_multitouch;
+
+    rc = XIChangeDeviceProperty(pInfo->dev, prop_multitouch, XA_INTEGER, 8, 
+               PropModeReplace, 1, &pEvdevMultitouch->num_multitouch, FALSE);
+
+    if (rc != Success)
+           ErrorF("[X11][%s] Failed to Change device property !\n", __FUNCTION__);
+}
+
+static void
+EvdevMultitouchSetUsePoll(InputInfoPtr pInfo, BOOL use_poll)
+{
+       EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
+       
+       if( use_poll == TRUE )
+       {
+               if( !EvdevMultitouchIsCoreDevice(pInfo) )//master only
+                       goto out;
+       
+               if( !vsync_input_table)
+               {
+                       vsync_input_table = vsync_input_init();
+                       if( !vsync_input_table )
+                       {
+                               ErrorF("[SetUsePoll] Failed to init vsync input ...\n");
+                               goto out;
+                       }
+               }
+               
+               g_syspoll_fd = open(SYSFS_POLL, O_WRONLY);
+               if( g_syspoll_fd < 0 )
+               {
+                       g_syspoll_fd = -1;
+                       ErrorF("[SetUsePoll] Failed to open %s ...\n", SYSFS_POLL);
+                       goto out;
+               }
+               
+               vsync_input_table->sync = sync_poll;
+               vsync_input_table->stop_sync(vsync_input_table->sync_arg);
+               poll_control(POLL_ENABLE);
+               pEvdevMultitouch->use_poll = use_poll;
+       }
+       else if( use_poll == FALSE )
+       {
+               if( !EvdevMultitouchIsCoreDevice(pInfo) )//master only
+                       goto out;
+               
+               if( !vsync_input_table)
+                       goto out;
+               
+               vsync_input_table->stop_sync(vsync_input_table->sync_arg);
+               vsync_input_table->sync = NULL;
+               vsync_input_close(vsync_input_table);
+               vsync_input_table = NULL;
+               poll_control(POLL_DISABLE);
+               close(g_syspoll_fd);
+               g_syspoll_fd = -1;
+               pEvdevMultitouch->use_poll = use_poll;
+       }
+       else
+               ErrorF("\n[SetUsePoll] Unknown value for use_poll (%d)\n", use_poll);
+
+out:
+       return;
+}
+
+Bool
+IsMaster(DeviceIntPtr dev)
+{
+    return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
+}
+
+DeviceIntPtr
+GetPairedDevice(DeviceIntPtr dev)
+{
+    if (!IsMaster(dev) && dev->u.master)
+        dev = dev->u.master;
+
+    return dev->spriteInfo->paired;
+}
+
+DeviceIntPtr
+GetMaster(DeviceIntPtr dev, int which)
+{
+    DeviceIntPtr master;
+
+    if (IsMaster(dev))
+        master = dev;
+    else
+        master = dev->u.master;
+
+    if (master)
+    {
+        if (which == MASTER_KEYBOARD)
+        {
+            if (master->type != MASTER_KEYBOARD)
+                master = GetPairedDevice(master);
+        } else
+        {
+            if (master->type != MASTER_POINTER)
+                master = GetPairedDevice(master);
+        }
+    }
+
+    return master;
+}
+
+static void
+EvdevMultitouchGetGrabInfo(InputInfoPtr pInfo, BOOL  val)
+{
+       DeviceIntPtr master_pointer;
+
+       if( val == 1 )
+       {
+               if( pInfo->dev->deviceGrab.grab )
+               {
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo] Device id=%d (grabbed) !\n", pInfo->dev->id);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  (event) type=%d\n", pInfo->dev->deviceGrab.grab->type);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  grabtype=%d\n", pInfo->dev->deviceGrab.grab->grabtype);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  resource=0x%x\n", (unsigned int)pInfo->dev->deviceGrab.grab->resource);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  keyboardMode=%d\n", pInfo->dev->deviceGrab.grab->keyboardMode);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  pointerMode=%d\n", pInfo->dev->deviceGrab.grab->pointerMode);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  sync.frozen=%d\n", pInfo->dev->deviceGrab.sync.frozen);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  fromPassiveGrab=%d\n", pInfo->dev->deviceGrab.fromPassiveGrab);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  implicitGrab=%d\n", pInfo->dev->deviceGrab.implicitGrab);
+               }
+               else if( (master_pointer = GetMaster(pInfo->dev, MASTER_POINTER)) && master_pointer->deviceGrab.grab )
+               {
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo] Device id=%d (master_pointer, grabbed) !\n", master_pointer->id);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  (event) type=%d\n", master_pointer->deviceGrab.grab->type);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  grabtype=%d\n", master_pointer->deviceGrab.grab->grabtype);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  resource=0x%x\n", (unsigned int)master_pointer->deviceGrab.grab->resource);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  keyboardMode=%d\n", master_pointer->deviceGrab.grab->keyboardMode);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  pointerMode=%d\n", master_pointer->deviceGrab.grab->pointerMode);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  sync.frozen=%d\n", master_pointer->deviceGrab.sync.frozen);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  fromPassiveGrab=%d\n", master_pointer->deviceGrab.fromPassiveGrab);
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo]  implicitGrab=%d\n", master_pointer->deviceGrab.implicitGrab);
+               }
+               else
+                       ErrorF("[X11][EvdevMultitouchGetGrabInfo] Device id=%d (ungrabbed) !\n", pInfo->dev->id);
+       }
+}
+
+static InputInfoPtr
+EvdevMultitouchPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+{
+    InputInfoPtr pInfo;
+    const char *device, *str;
+    int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
+    int num_resolution = 0, resolution[4] = { 0, 0, 0, 0 };
+    int num_transform = 0; float tr[9];
+    EvdevMultitouchPtr pEvdevMultitouch;
+    char *type;
+
+    if (!(pInfo = xf86AllocateInput(drv, 0)))
+       return NULL;
+
+    /* Initialise the InputInfoRec. */
+    pInfo->name = dev->identifier;
+    pInfo->flags = 0;
+    pInfo->type_name = "UNKNOWN";
+    pInfo->device_control = EvdevMultitouchProc;
+    pInfo->history_size = 0;
+    pInfo->control_proc = NULL;
+    pInfo->close_proc = NULL;
+    pInfo->switch_mode = NULL;
+    pInfo->conversion_proc = NULL;
+    pInfo->reverse_conversion_proc = NULL;
+    pInfo->dev = NULL;
+    pInfo->private_flags = 0;
+    pInfo->always_core_feedback = NULL;
+    pInfo->conf_idev = dev;
+
+    if (!(pEvdevMultitouch = calloc(sizeof(EvdevMultitouchRec), 1)))
+        return pInfo;
+
+    pInfo->private = pEvdevMultitouch;
+
+    xf86CollectInputOptions(pInfo, evdevmultitouchDefaults, NULL);
+    xf86ProcessCommonOptions(pInfo, pInfo->options);
+    pEvdevMultitouch->id = -1;
+     /* If Type == Object, this is a device for an object to use */
+    type = xf86CheckStrOption(dev->commonOptions, "Type", NULL);
+
+    xf86Msg(X_INFO, "%s: EvdevMultitouch Type %s found\n", dev->identifier,type);
+       
+    if (type != NULL && strcmp(type, "Object") == 0) {
+        EvdevMultitouchPtr pCreatorEvdevMultitouch;
+        if (!pCreatorInfo){
+            return pInfo;
+        }
+        pCreatorEvdevMultitouch = pCreatorInfo->private;
+        xf86Msg(X_INFO, "%s: EvdevMultitouch subdevice found\n", dev->identifier);
+        memcpy(pEvdevMultitouch, pCreatorEvdevMultitouch, sizeof(EvdevMultitouchRec));
+        pInfo->read_input = EvdevMultitouchSubdevReadInput;
+        pInfo->flags |= XI86_CONFIGURED;
+        pEvdevMultitouch->associated = FALSE;
+        pInfo->type_name = pCreatorInfo->type_name;
+        pEvdevMultitouch->num_multitouch = 1;
+        //EvdevMultitouchInitButtonMapping(pInfo);
+   } else {
+        pInfo->read_input = EvdevMultitouchReadInput;
+
+        pEvdevMultitouch->core_device = pInfo;
+        pEvdevMultitouch->associated = FALSE;
+
+        memset(pEvdevMultitouch->vals, 0, MAX_VALUATORS * sizeof(int));
+        memset(pEvdevMultitouch->old_vals, -1, MAX_VALUATORS * sizeof(int));
+        
+        /*
+         * We initialize pEvdevMultitouch->tool to 1 so that device that doesn't use
+         * proximity will still report events.
+         */
+        pEvdevMultitouch->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;
+        }
+
+        pEvdevMultitouch->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 evdevmultitouch device \"%s\".\n", device);
+        xf86DeleteInput(pInfo, 0);
+            return NULL;
+        }
+
+        /* Check major/minor of device node to avoid adding duplicate devices. */
+        pEvdevMultitouch->min_maj = EvdevMultitouchGetMajorMinor(pInfo);
+        if (EvdevMultitouchIsDuplicate(pInfo))
+        {
+            xf86Msg(X_WARNING, "%s: device file already in use. Ignoring.\n",
+                    pInfo->name);
+            close(pInfo->fd);
+            xf86DeleteInput(pInfo, 0);
+            return NULL;
+        }
+
+        pEvdevMultitouch->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
+        pEvdevMultitouch->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
+        pEvdevMultitouch->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
+        pEvdevMultitouch->num_multitouch = xf86SetIntOption(pInfo->options, "MultiTouch", 0);
+        pEvdevMultitouch->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
+        pEvdevMultitouch->use_poll = xf86SetBoolOption(pInfo->options, "UsePoll", 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)
+                EvdevMultitouchSetCalibration(pInfo, num_calibration, calibration);
+            else
+                xf86Msg(X_ERROR,
+                        "%s: Insufficient calibration factors (%d). Ignoring calibration\n",
+                        pInfo->name, num_calibration);
+        }
+
+        str = xf86CheckStrOption(pInfo->options, "Resolution", NULL);
+        if (str) {
+            num_resolution = sscanf(str, "%d %d %d %d",
+                                     &resolution[0], &resolution[1],
+                                     &resolution[2], &resolution[3]);
+            if (num_resolution == 4)
+                EvdevMultitouchSetResolution(pInfo, num_resolution, resolution);
+            else
+                xf86Msg(X_ERROR,
+                        "%s: Insufficient resolution factors (%d). Ignoring resolution\n",
+                        pInfo->name, num_resolution);
+        }
+
+        use_transform = False;
+        str = xf86CheckStrOption(pInfo->options, "Transform", NULL);
+        if (str) {
+            num_transform = sscanf(str, "%f %f %f %f %f %f %f %f %f",
+                                     &tr[0], &tr[1], &tr[2],
+                                     &tr[3], &tr[4], &tr[5], 
+                                     &tr[6], &tr[7], &tr[8]);
+            if (num_transform == 9)
+                EvdevMultitouchSetTransform(pInfo, num_transform, tr);
+            else
+            {
+                xf86Msg(X_ERROR,
+                        "%s: Insufficient transform factors (%d). Ignoring transform\n",
+                        pInfo->name, num_transform);
+            }
+        }
+
+        /* Grabbing the event device stops in-kernel event forwarding. In other
+           words, it disables rfkill and the "Macintosh mouse button emulation".
+           Note that this needs a server that sets the console to RAW mode. */
+        pEvdevMultitouch->grabDevice = xf86CheckBoolOption(dev->commonOptions, "GrabDevice", 0);
+
+        /* Get setting for checking wether a point is still alive */
+        pEvdevMultitouch->timeout = xf86CheckIntOption(dev->commonOptions,
+                "SubdevTimeout", DEFAULT_TIMEOUT);
+        if (pEvdevMultitouch->timeout < 1) {
+            pEvdevMultitouch->timeout = 1;
+        }
+        xf86Msg(X_INFO, "%s: SubdevTimeout set to %d\n",
+                dev->identifier, (int)pEvdevMultitouch->timeout);
+
+        EvdevMultitouchInitButtonMapping(pInfo);
+
+        if (EvdevMultitouchCacheCompare(pInfo, FALSE) ||
+            EvdevMultitouchProbe(pInfo)) {
+            close(pInfo->fd);
+            xf86DeleteInput(pInfo, 0);
+            return NULL;
+        }
+        
+        if ((pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH) && !pEvdevMultitouch->num_buttons) {
+            /* absolute multitouch screen :
+             * forcing num_buttons = 1
+             */
+            pEvdevMultitouch->num_buttons = 1;
+            pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
+        }
+
+        if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
+        {
+            pEvdevMultitouch->num_multitouch = 1;
+            pEvdevMultitouch->vals_mt[0].pInfo = pInfo;
+        }
+
+       if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_RESOLUTION)
+       {
+               EvdevMultitouchSwapAxes(pEvdevMultitouch);
+       }
+#ifdef _F_IGNORE_TSP_RESOLUTION_
+       else
+       {
+               pEvdevMultitouch->absinfo[ABS_X].maximum = 0;
+               pEvdevMultitouch->absinfo[ABS_X].minimum = 0;
+               pEvdevMultitouch->absinfo[ABS_Y].maximum = 0;
+               pEvdevMultitouch->absinfo[ABS_Y].minimum = 0;
+       }
+#endif//_F_IGNORE_TSP_RESOLUTION_
+
+        // register only the core device
+        EvdevMultitouchAddDevice(pInfo);
+    }
+
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_BUTTON_EVENTS)
+    {
+        EvdevMultitouchMBEmuPreInit(pInfo);
+        EvdevMultitouchWheelEmuPreInit(pInfo);
+        EvdevMultitouchDragLockPreInit(pInfo);
+    }
+
+    return pInfo;
+}
+
+_X_EXPORT InputDriverRec EVDEVMULTITOUCHh = {
+    1,
+    "evdevmultitouch",
+    NULL,
+    EvdevMultitouchPreInit,
+    NULL,
+    NULL,
+    0
+};
+
+static void
+EvdevMultitouchUnplug(pointer  p)
+{
+}
+
+static pointer
+EvdevMultitouchPlug(pointer    module,
+          pointer      options,
+          int          *errmaj,
+          int          *errmin)
+{
+    xf86AddInputDriver(&EVDEVMULTITOUCHh, module, 0);
+    return module;
+}
+
+static XF86ModuleVersionInfo EvdevMultitouchVersionRec =
+{
+    "evdevmultitouch",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+    ABI_CLASS_XINPUT,
+    ABI_XINPUT_VERSION,
+    MOD_CLASS_XINPUT,
+    {0, 0, 0, 0}
+};
+
+_X_EXPORT XF86ModuleData evdevmultitouchModuleData =
+{
+    &EvdevMultitouchVersionRec,
+    EvdevMultitouchPlug,
+    EvdevMultitouchUnplug
+};
+
+
+/* Return an index value for a given button event code
+ * returns 0 on non-button event.
+ */
+unsigned int
+EvdevMultitouchUtilButtonEventToButtonNumber(EvdevMultitouchPtr pEvdevMultitouch, int code)
+{
+    unsigned int button = 0;
+
+    switch(code) {
+    case BTN_LEFT:
+       button = 1;
+       break;
+
+    case BTN_RIGHT:
+       button = 3;
+       break;
+
+    case BTN_MIDDLE:
+       button = 2;
+       break;
+
+        /* Treat BTN_[0-2] as LMR buttons on devices that do not advertise
+           BTN_LEFT, BTN_MIDDLE, BTN_RIGHT.
+           Otherwise, treat BTN_[0+n] as button 5+n.
+           XXX: This causes duplicate mappings for BTN_0 + n and BTN_SIDE + n
+         */
+    case BTN_0:
+        button = (TestBit(BTN_LEFT, pEvdevMultitouch->key_bitmask)) ?  8 : 1;
+        break;
+    case BTN_1:
+        button = (TestBit(BTN_MIDDLE, pEvdevMultitouch->key_bitmask)) ?  9 : 2;
+        break;
+    case BTN_2:
+        button = (TestBit(BTN_RIGHT, pEvdevMultitouch->key_bitmask)) ?  10 : 3;
+        break;
+
+        /* FIXME: BTN_3.. and BTN_SIDE.. have the same button mapping */
+    case BTN_3:
+    case BTN_4:
+    case BTN_5:
+    case BTN_6:
+    case BTN_7:
+    case BTN_8:
+    case BTN_9:
+       button = (code - BTN_0 + 5);
+        break;
+
+    case BTN_SIDE:
+    case BTN_EXTRA:
+    case BTN_FORWARD:
+    case BTN_BACK:
+    case BTN_TASK:
+       button = (code - BTN_LEFT + 5);
+       break;
+
+    default:
+       if ((code > BTN_TASK) && (code < KEY_OK)) {
+           if (code < BTN_JOYSTICK) {
+                if (code < BTN_MOUSE)
+                    button = (code - BTN_0 + 5);
+                else
+                    button = (code - BTN_LEFT + 5);
+            }
+       }
+    }
+
+    if (button > EVDEVMULTITOUCH_MAXBUTTONS)
+       return 0;
+
+    return button;
+}
+
+#ifdef HAVE_PROPERTIES
+#ifdef HAVE_LABELS
+/* Aligned with linux/input.h.
+   Note that there are holes in the ABS_ range, these are simply replaced with
+   MISC here */
+static char* abs_labels[] = {
+    AXIS_LABEL_PROP_ABS_X,              /* 0x00 */
+    AXIS_LABEL_PROP_ABS_Y,              /* 0x01 */
+    AXIS_LABEL_PROP_ABS_Z,              /* 0x02 */
+    AXIS_LABEL_PROP_ABS_RX,             /* 0x03 */
+    AXIS_LABEL_PROP_ABS_RY,             /* 0x04 */
+    AXIS_LABEL_PROP_ABS_RZ,             /* 0x05 */
+    AXIS_LABEL_PROP_ABS_THROTTLE,       /* 0x06 */
+    AXIS_LABEL_PROP_ABS_RUDDER,         /* 0x07 */
+    AXIS_LABEL_PROP_ABS_WHEEL,          /* 0x08 */
+    AXIS_LABEL_PROP_ABS_GAS,            /* 0x09 */
+    AXIS_LABEL_PROP_ABS_BRAKE,          /* 0x0a */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_HAT0X,          /* 0x10 */
+    AXIS_LABEL_PROP_ABS_HAT0Y,          /* 0x11 */
+    AXIS_LABEL_PROP_ABS_HAT1X,          /* 0x12 */
+    AXIS_LABEL_PROP_ABS_HAT1Y,          /* 0x13 */
+    AXIS_LABEL_PROP_ABS_HAT2X,          /* 0x14 */
+    AXIS_LABEL_PROP_ABS_HAT2Y,          /* 0x15 */
+    AXIS_LABEL_PROP_ABS_HAT3X,          /* 0x16 */
+    AXIS_LABEL_PROP_ABS_HAT3Y,          /* 0x17 */
+    AXIS_LABEL_PROP_ABS_PRESSURE,       /* 0x18 */
+    AXIS_LABEL_PROP_ABS_DISTANCE,       /* 0x19 */
+    AXIS_LABEL_PROP_ABS_TILT_X,         /* 0x1a */
+    AXIS_LABEL_PROP_ABS_TILT_Y,         /* 0x1b */
+    AXIS_LABEL_PROP_ABS_TOOL_WIDTH,     /* 0x1c */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_MISC,           /* undefined */
+    AXIS_LABEL_PROP_ABS_VOLUME          /* 0x20 */
+};
+
+static char* rel_labels[] = {
+    AXIS_LABEL_PROP_REL_X,
+    AXIS_LABEL_PROP_REL_Y,
+    AXIS_LABEL_PROP_REL_Z,
+    AXIS_LABEL_PROP_REL_RX,
+    AXIS_LABEL_PROP_REL_RY,
+    AXIS_LABEL_PROP_REL_RZ,
+    AXIS_LABEL_PROP_REL_HWHEEL,
+    AXIS_LABEL_PROP_REL_DIAL,
+    AXIS_LABEL_PROP_REL_WHEEL,
+    AXIS_LABEL_PROP_REL_MISC
+};
+
+static char* btn_labels[][16] = {
+    { /* BTN_MISC group                 offset 0x100*/
+        BTN_LABEL_PROP_BTN_0,           /* 0x00 */
+        BTN_LABEL_PROP_BTN_1,           /* 0x01 */
+        BTN_LABEL_PROP_BTN_2,           /* 0x02 */
+        BTN_LABEL_PROP_BTN_3,           /* 0x03 */
+        BTN_LABEL_PROP_BTN_4,           /* 0x04 */
+        BTN_LABEL_PROP_BTN_5,           /* 0x05 */
+        BTN_LABEL_PROP_BTN_6,           /* 0x06 */
+        BTN_LABEL_PROP_BTN_7,           /* 0x07 */
+        BTN_LABEL_PROP_BTN_8,           /* 0x08 */
+        BTN_LABEL_PROP_BTN_9            /* 0x09 */
+    },
+    { /* BTN_MOUSE group                offset 0x110 */
+        BTN_LABEL_PROP_BTN_LEFT,        /* 0x00 */
+        BTN_LABEL_PROP_BTN_RIGHT,       /* 0x01 */
+        BTN_LABEL_PROP_BTN_MIDDLE,      /* 0x02 */
+        BTN_LABEL_PROP_BTN_SIDE,        /* 0x03 */
+        BTN_LABEL_PROP_BTN_EXTRA,       /* 0x04 */
+        BTN_LABEL_PROP_BTN_FORWARD,     /* 0x05 */
+        BTN_LABEL_PROP_BTN_BACK,        /* 0x06 */
+        BTN_LABEL_PROP_BTN_TASK         /* 0x07 */
+    },
+    { /* BTN_JOYSTICK group             offset 0x120 */
+        BTN_LABEL_PROP_BTN_TRIGGER,     /* 0x00 */
+        BTN_LABEL_PROP_BTN_THUMB,       /* 0x01 */
+        BTN_LABEL_PROP_BTN_THUMB2,      /* 0x02 */
+        BTN_LABEL_PROP_BTN_TOP,         /* 0x03 */
+        BTN_LABEL_PROP_BTN_TOP2,        /* 0x04 */
+        BTN_LABEL_PROP_BTN_PINKIE,      /* 0x05 */
+        BTN_LABEL_PROP_BTN_BASE,        /* 0x06 */
+        BTN_LABEL_PROP_BTN_BASE2,       /* 0x07 */
+        BTN_LABEL_PROP_BTN_BASE3,       /* 0x08 */
+        BTN_LABEL_PROP_BTN_BASE4,       /* 0x09 */
+        BTN_LABEL_PROP_BTN_BASE5,       /* 0x0a */
+        BTN_LABEL_PROP_BTN_BASE6,       /* 0x0b */
+        NULL,
+        NULL,
+        NULL,
+        BTN_LABEL_PROP_BTN_DEAD         /* 0x0f */
+    },
+    { /* BTN_GAMEPAD group              offset 0x130 */
+        BTN_LABEL_PROP_BTN_A,           /* 0x00 */
+        BTN_LABEL_PROP_BTN_B,           /* 0x01 */
+        BTN_LABEL_PROP_BTN_C,           /* 0x02 */
+        BTN_LABEL_PROP_BTN_X,           /* 0x03 */
+        BTN_LABEL_PROP_BTN_Y,           /* 0x04 */
+        BTN_LABEL_PROP_BTN_Z,           /* 0x05 */
+        BTN_LABEL_PROP_BTN_TL,          /* 0x06 */
+        BTN_LABEL_PROP_BTN_TR,          /* 0x07 */
+        BTN_LABEL_PROP_BTN_TL2,         /* 0x08 */
+        BTN_LABEL_PROP_BTN_TR2,         /* 0x09 */
+        BTN_LABEL_PROP_BTN_SELECT,      /* 0x0a */
+        BTN_LABEL_PROP_BTN_START,       /* 0x0b */
+        BTN_LABEL_PROP_BTN_MODE,        /* 0x0c */
+        BTN_LABEL_PROP_BTN_THUMBL,      /* 0x0d */
+        BTN_LABEL_PROP_BTN_THUMBR       /* 0x0e */
+    },
+    { /* BTN_DIGI group                         offset 0x140 */
+        BTN_LABEL_PROP_BTN_TOOL_PEN,            /* 0x00 */
+        BTN_LABEL_PROP_BTN_TOOL_RUBBER,         /* 0x01 */
+        BTN_LABEL_PROP_BTN_TOOL_BRUSH,          /* 0x02 */
+        BTN_LABEL_PROP_BTN_TOOL_PENCIL,         /* 0x03 */
+        BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH,       /* 0x04 */
+        BTN_LABEL_PROP_BTN_TOOL_FINGER,         /* 0x05 */
+        BTN_LABEL_PROP_BTN_TOOL_MOUSE,          /* 0x06 */
+        BTN_LABEL_PROP_BTN_TOOL_LENS,           /* 0x07 */
+        NULL,
+        NULL,
+        BTN_LABEL_PROP_BTN_TOUCH,               /* 0x0a */
+        BTN_LABEL_PROP_BTN_STYLUS,              /* 0x0b */
+        BTN_LABEL_PROP_BTN_STYLUS2,             /* 0x0c */
+        BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP,      /* 0x0d */
+        BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP       /* 0x0e */
+    },
+    { /* BTN_WHEEL group                        offset 0x150 */
+        BTN_LABEL_PROP_BTN_GEAR_DOWN,           /* 0x00 */
+        BTN_LABEL_PROP_BTN_GEAR_UP              /* 0x01 */
+    }
+};
+
+#endif /* HAVE_LABELS */
+
+static void EvdevMultitouchInitAxesLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms)
+{
+#ifdef HAVE_LABELS
+    Atom atom;
+    int axis;
+    char **labels;
+    int labels_len = 0;
+    char *misc_label;
+
+    if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS)
+    {
+        labels     = abs_labels;
+        labels_len = ArrayLength(abs_labels);
+        misc_label = AXIS_LABEL_PROP_ABS_MISC;
+    } else if ((pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS))
+    {
+        labels     = rel_labels;
+        labels_len = ArrayLength(rel_labels);
+        misc_label = AXIS_LABEL_PROP_REL_MISC;
+    }
+
+    memset(atoms, 0, natoms * sizeof(Atom));
+
+    /* Now fill the ones we know */
+    for (axis = 0; axis < labels_len; axis++)
+    {
+        if (pEvdevMultitouch->axis_map[axis] == -1)
+            continue;
+
+        atom = XIGetKnownProperty(labels[axis]);
+        if (!atom) /* Should not happen */
+            continue;
+
+        atoms[pEvdevMultitouch->axis_map[axis]] = atom;
+    }
+#endif
+}
+
+static void EvdevMultitouchInitButtonLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms)
+{
+#ifdef HAVE_LABELS
+    Atom atom;
+    int button, bmap;
+
+    /* First, make sure all atoms are initialized */
+    atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
+    for (button = 0; button < natoms; button++)
+        atoms[button] = atom;
+
+    for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
+    {
+        if (TestBit(button, pEvdevMultitouch->key_bitmask))
+        {
+            int group = (button % 0x100)/16;
+            int idx = button - ((button/16) * 16);
+
+            if (!btn_labels[group][idx])
+                continue;
+
+            atom = XIGetKnownProperty(btn_labels[group][idx]);
+            if (!atom)
+                continue;
+
+            /* Props are 0-indexed, button numbers start with 1 */
+            bmap = EvdevMultitouchUtilButtonEventToButtonNumber(pEvdevMultitouch, button) - 1;
+            if( bmap >= 0 )
+                atoms[bmap] = atom;
+        }
+    }
+
+    /* wheel buttons, hardcoded anyway */
+    if (natoms > 3)
+        atoms[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
+    if (natoms > 4)
+        atoms[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+    if (natoms > 5)
+        atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+    if (natoms > 6)
+        atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+#endif
+}
+
+static void
+EvdevMultitouchInitProperty(DeviceIntPtr dev)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+    int          rc;
+    int          val;
+    BOOL         invert[2];
+    char         reopen;
+
+    prop_reopen = MakeAtom(EVDEVMULTITOUCH_PROP_REOPEN, strlen(EVDEVMULTITOUCH_PROP_REOPEN),
+            TRUE);
+
+    reopen = pEvdevMultitouch->reopen_attempts;
+    rc = XIChangeDeviceProperty(dev, prop_reopen, XA_INTEGER, 8,
+                                PropModeReplace, 1, &reopen, FALSE);
+    if (rc != Success)
+        return;
+
+    XISetDevicePropertyDeletable(dev, prop_reopen, FALSE);
+
+    if (pEvdevMultitouch->flags & (EVDEVMULTITOUCH_RELATIVE_EVENTS | EVDEVMULTITOUCH_ABSOLUTE_EVENTS))
+    {
+        invert[0] = pEvdevMultitouch->invert_x;
+        invert[1] = pEvdevMultitouch->invert_y;
+
+        prop_invert = MakeAtom(EVDEVMULTITOUCH_PROP_INVERT_AXES, strlen(EVDEVMULTITOUCH_PROP_INVERT_AXES), TRUE);
+
+        rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
+                PropModeReplace, 2,
+                invert, FALSE);
+        if (rc != Success)
+            return;
+
+        XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
+
+        prop_calibration = MakeAtom(EVDEVMULTITOUCH_PROP_CALIBRATION,
+                strlen(EVDEVMULTITOUCH_PROP_CALIBRATION), TRUE);
+        rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER, 32,
+                PropModeReplace, 0, NULL, FALSE);
+        if (rc != Success)
+            return;
+
+        XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
+
+        prop_swap = MakeAtom(EVDEVMULTITOUCH_PROP_SWAP_AXES,
+                strlen(EVDEVMULTITOUCH_PROP_SWAP_AXES), TRUE);
+
+        rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
+                PropModeReplace, 1, &pEvdevMultitouch->swap_axes, FALSE);
+        if (rc != Success)
+            return;
+
+        XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
+        
+        if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
+        {
+            /* tracking ids for mt */
+            prop_tracking_id = MakeAtom(EVDEVMULTITOUCH_PROP_TRACKING_ID,
+                    strlen(EVDEVMULTITOUCH_PROP_TRACKING_ID), TRUE);
+            rc = XIChangeDeviceProperty(dev, prop_tracking_id, XA_INTEGER, 32,
+                    PropModeReplace, 1, &pEvdevMultitouch->id, FALSE);
+            if (rc != Success)
+                return;
+
+            XISetDevicePropertyDeletable(dev, prop_tracking_id, FALSE);
+
+            /* flag to emulate or not a touchscreen for mt */
+            prop_multitouch = MakeAtom(EVDEVMULTITOUCH_PROP_MULTITOUCH_SUBDEVICES,
+                    strlen(EVDEVMULTITOUCH_PROP_MULTITOUCH_SUBDEVICES), TRUE);
+            rc = XIChangeDeviceProperty(dev, prop_multitouch, XA_INTEGER, 8,
+                    PropModeReplace, 1, &pEvdevMultitouch->num_multitouch, FALSE);
+            if (rc != Success)
+                return;
+
+            XISetDevicePropertyDeletable(dev, prop_multitouch, FALSE);
+        }
+
+       //property for checking pointer grab status
+       val = 0;
+       prop_grabinfo = MakeAtom(EVDEVMULTITOUCH_PROP_GRABINFO, strlen(EVDEVMULTITOUCH_PROP_GRABINFO),  TRUE);
+       rc = XIChangeDeviceProperty(dev, prop_grabinfo, XA_INTEGER, 8, PropModeReplace, 1, &val, FALSE);
+
+       if (rc != Success)
+           return;
+
+       XISetDevicePropertyDeletable(dev, prop_grabinfo, FALSE);
+
+       if( EvdevMultitouchIsCoreDevice(pInfo) )//master only
+       {
+               /* flag to use poll */
+               prop_use_poll = MakeAtom(EVDEVMULTITOUCH_PROP_USE_POLL, strlen(EVDEVMULTITOUCH_PROP_USE_POLL), TRUE);
+               rc = XIChangeDeviceProperty(dev, prop_use_poll, XA_INTEGER, 8, PropModeReplace, 1, &pEvdevMultitouch->use_poll, FALSE);
+               if (rc != Success)
+                       return;
+
+               XISetDevicePropertyDeletable(dev, prop_use_poll, FALSE);
+
+               /* matrix to transform */
+               prop_transform = MakeAtom(EVDEVMULTITOUCH_PROP_TRANSFORM, strlen(EVDEVMULTITOUCH_PROP_TRANSFORM),  TRUE);
+               rc = XIChangeDeviceProperty(dev, prop_transform, XIGetKnownProperty(XATOM_FLOAT), 32, PropModeReplace, 9, transform, FALSE);
+
+               if (rc != Success)
+                   return;
+
+               XISetDevicePropertyDeletable(dev, prop_transform, FALSE);
+       }
+
+#ifdef HAVE_LABELS
+        /* Axis labelling */
+        if ((pEvdevMultitouch->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
+        {
+            Atom atoms[pEvdevMultitouch->num_vals];
+            EvdevMultitouchInitAxesLabels(pEvdevMultitouch, pEvdevMultitouch->num_vals, atoms);
+            XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
+                                   PropModeReplace, pEvdevMultitouch->num_vals, atoms, FALSE);
+            XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
+        }
+        /* Button labelling */
+        if ((pEvdevMultitouch->num_buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
+        {
+            Atom atoms[EVDEVMULTITOUCH_MAXBUTTONS];
+            EvdevMultitouchInitButtonLabels(pEvdevMultitouch, EVDEVMULTITOUCH_MAXBUTTONS, atoms);
+            XIChangeDeviceProperty(dev, prop_btn_label, XA_ATOM, 32,
+                                   PropModeReplace, pEvdevMultitouch->num_buttons, atoms, FALSE);
+            XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
+        }
+#endif /* HAVE_LABELS */
+    }
+
+}
+
+static void EvdevMultitouchSwapAxes(EvdevMultitouchPtr pEvdevMultitouch)
+{
+    if(pEvdevMultitouch->swap_axes)
+    {
+       pEvdevMultitouch->absinfo[ABS_Y].maximum = pEvdevMultitouch->resolution.max_x;
+       pEvdevMultitouch->absinfo[ABS_Y].minimum = pEvdevMultitouch->resolution.min_x;
+       pEvdevMultitouch->absinfo[ABS_X].maximum = pEvdevMultitouch->resolution.max_y;
+       pEvdevMultitouch->absinfo[ABS_X].minimum = pEvdevMultitouch->resolution.min_y;
+    }
+    else
+    {
+       pEvdevMultitouch->absinfo[ABS_X].maximum = pEvdevMultitouch->resolution.max_x;
+       pEvdevMultitouch->absinfo[ABS_X].minimum = pEvdevMultitouch->resolution.min_x;
+       pEvdevMultitouch->absinfo[ABS_Y].maximum = pEvdevMultitouch->resolution.max_y;
+       pEvdevMultitouch->absinfo[ABS_Y].minimum = pEvdevMultitouch->resolution.min_y;
+    }
+}
+
+static int
+EvdevMultitouchSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+                 BOOL checkonly)
+{
+    InputInfoPtr pInfo  = dev->public.devicePrivate;
+    EvdevMultitouchPtr     pEvdevMultitouch = pInfo->private;
+
+    if (atom == prop_invert)
+    {
+        BOOL* data;
+        if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+        {
+            data = (BOOL*)val->data;
+            pEvdevMultitouch->invert_x = data[0];
+            pEvdevMultitouch->invert_y = data[1];
+        }
+    } else if (atom == prop_reopen)
+    {
+        if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+            pEvdevMultitouch->reopen_attempts = *((CARD8*)val->data);
+    } else if (atom == prop_calibration)
+    {
+        if (val->format != 32 || val->type != XA_INTEGER)
+            return BadMatch;
+        if (val->size != 4 && val->size != 0)
+            return BadMatch;
+
+        if (!checkonly)
+            EvdevMultitouchSetCalibration(pInfo, val->size, val->data);
+    } else if (atom == prop_swap)
+    {
+        if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+
+        if (!checkonly)
+            pEvdevMultitouch->swap_axes = *((BOOL*)val->data);
+        EvdevMultitouchSwapAxes(pEvdevMultitouch);
+    } else if (atom == prop_axis_label || atom == prop_btn_label)
+        return BadAccess; /* Axis/Button labels can't be changed */
+    else if (atom == prop_tracking_id)
+    {
+        if (val->format != 32 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+
+        if (!checkonly)
+            pEvdevMultitouch->id = *((int*)val->data);
+    } else if (atom == prop_multitouch)
+    {
+        BOOL data;
+        if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+        if (!checkonly) {
+            data = *((BOOL*)val->data);
+            if (pEvdevMultitouch->num_multitouch != data)
+                EvdevMultitouchSetMultitouch(pInfo,data);
+        }
+    } else if (atom == prop_use_poll)
+    {
+        BOOL data;
+        if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+        if (!checkonly) {
+            data = *((BOOL*)val->data);
+            if (pEvdevMultitouch->use_poll != data)
+                 EvdevMultitouchSetUsePoll(pInfo,(BOOL)data);
+        }
+    }
+    else if (atom == prop_transform)
+    {
+        float *f;
+        if (val->format != 32 || val->type != XIGetKnownProperty(XATOM_FLOAT) || val->size != 9)
+            return BadMatch;
+        if (!checkonly) {
+            f = (float*)val->data;
+            EvdevMultitouchSetTransform(pInfo, val->size, f);
+        }
+    }
+    else if (atom == prop_grabinfo)
+    {
+        BOOL data;
+        if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+        if (!checkonly) {
+            data = *((BOOL*)val->data);
+            EvdevMultitouchGetGrabInfo(pInfo, (BOOL)data);
+        }
+    }
+
+    return Success;
+}
+#endif
+
+/* Duplicate xf86 options and convert them to InputOption */
+static InputOption *EvdevMultitouchOptionDupConvert(pointer original)
+{
+    InputOption *iopts = NULL, *new;
+    InputInfoRec dummy;
+
+
+    memset(&dummy, 0, sizeof(dummy));
+    xf86CollectInputOptions(&dummy, NULL, original);
+
+    while(dummy.options)
+    {
+        new = calloc(1, sizeof(InputOption));
+
+        new->key = xf86OptionName(dummy.options);
+        new->value = xf86OptionValue(dummy.options);
+
+        new->next = iopts;
+        iopts = new;
+        dummy.options = xf86NextOption(dummy.options);
+    }
+    return iopts;
+}
+static void EvdevMultitouchFreeInputOpts(InputOption* opts)
+{
+    InputOption *tmp = opts;
+
+    while(opts)
+    {
+        tmp = opts->next;
+        free(opts->key);
+        free(opts->value);
+        free(opts);
+        opts = tmp;
+    }
+}
+static void EvdevMultitouchReplaceOption(InputOption *opts,const char* key, char * value)
+{
+
+    while(opts)
+    {
+        if (xf86NameCmp(opts->key, key) == 0)
+        {
+
+            free(opts->value);
+            opts->value = strdup(value);
+        }
+        opts = opts->next;
+    }
+}
+
+/**
+ * New device creation through xorg/input
+ *
+ * @return 0 if successful, 1 if failure
+ */
+static InputInfoPtr
+EvdevMultitouchCreateSubDevice(InputInfoPtr pInfo, int id) {
+    InputInfoPtr pSubdev;
+
+    DeviceIntPtr dev; /* dummy */
+    InputOption *input_options = NULL;
+    char* name;
+    
+
+    pInfo->options = xf86AddNewOption(pInfo->options, "Type", "core");
+    pInfo->options = xf86AddNewOption(pInfo->options, "SendCoreEvents", "off");
+
+    /* Create new device */
+
+    input_options = EvdevMultitouchOptionDupConvert(pInfo->options);
+
+    EvdevMultitouchReplaceOption(input_options, "type","Object");
+
+    //EvdevMultitouchReplaceOption(input_options, "SendCoreEvents","off"); //FIXME: bug in xserver
+    name = malloc( (strlen(pInfo->name) + strlen(" subdev ") + 20 )*sizeof(char)); // 20 for adding the id
+
+    if( !name )
+    {
+        ErrorF("[X11][%s] Failed to allocate memory !\n", __FUNCTION__);
+        return NULL;
+    }
+
+    sprintf(name, "%s subdev %i", pInfo->name, id);
+    EvdevMultitouchReplaceOption(input_options, "name",name);
+
+    pCreatorInfo = pInfo;
+    NewInputDeviceRequest(input_options, NULL, &dev);//for xserver 1.8.0
+    //NewInputDeviceRequest(input_options, &dev);//for xserver 1.7.1
+    pSubdev = dev->public.devicePrivate;
+    pCreatorInfo = NULL;
+
+    EvdevMultitouchFreeInputOpts(input_options);
+
+    free(name);
+    return pSubdev;
+}
+static void
+EvdevMultitouchDeleteSubDevice(InputInfoPtr pInfo, InputInfoPtr subdev) {
+    /* We need to explicitely flush the events so as not deleting
+     * a device that still has events in queue
+     */
+    xf86Msg(X_INFO, "%s: Removing subdevice %s\n", pInfo->name,subdev->name);
+    DeleteInputDeviceRequest(subdev->dev);
+}
diff --git a/src/evdevmultitouch.h b/src/evdevmultitouch.h
new file mode 100755 (executable)
index 0000000..87014a8
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * xserver-xorg-input-evdev-multitouch
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *
+ * 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 © 2004-2008 Red Hat, Inc.
+ * Copyright © 2008 University of South Australia
+ *
+ * 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.
+ *
+ * Authors:
+ *     Kristian Høgsberg (krh@redhat.com)
+ *     Adam Jackson (ajax@redhat.com)
+ *     Peter Hutterer (peter@cs.unisa.edu.au)
+ *     Oliver McFadden (oliver.mcfadden@nokia.com)
+ *     Benjamin Tissoires (tissoire@cena.fr)
+ */
+
+#ifndef EVDEVMULTITOUCH_H
+#define EVDEVMULTITOUCH_H
+
+#include <linux/input.h>
+#include <linux/types.h>
+
+#include <xf86Xinput.h>
+#include <xf86_OSproc.h>
+#include <xkbstr.h>
+
+#include <math.h>
+#include <pixman.h>
+
+#ifdef _F_GESTURE_EXTENSION_
+typedef enum _MTSyncType
+{
+       MTOUCH_FRAME_SYNC_END,
+       MTOUCH_FRAME_SYNC_BEGIN
+} MTSyncType;
+
+enum EventType
+{
+    ET_MTSync = 0x7E,
+    ET_Internal = 0xFF /* First byte */
+};
+
+typedef struct _AnyEvent AnyEvent;
+struct _AnyEvent
+{
+    unsigned char header; /**< Always ET_Internal */
+    enum EventType type;  /**< One of EventType */
+    int length;           /**< Length in bytes */
+    Time time;            /**< Time in ms */
+    int deviceid;
+    MTSyncType sync;
+    int x;
+    int y;
+};
+
+union _InternalEvent {
+       struct {
+           unsigned char header; /**< Always ET_Internal */
+           enum EventType type;  /**< One of ET_* */
+           int length;           /**< Length in bytes */
+           Time time;            /**< Time in ms. */
+       } any;
+       AnyEvent any_event;
+};
+#endif//_F_GESTURE_EXTENSION_
+
+#ifndef EV_CNT /* linux 2.4 kernels and earlier lack _CNT defines */
+#define EV_CNT (EV_MAX+1)
+#endif
+#ifndef KEY_CNT
+#define KEY_CNT (KEY_MAX+1)
+#endif
+#ifndef REL_CNT
+#define REL_CNT (REL_MAX+1)
+#endif
+#ifndef ABS_CNT
+#define ABS_CNT (ABS_MAX+1)
+#endif
+#ifndef LED_CNT
+#define LED_CNT (LED_MAX+1)
+#endif
+
+#define EVDEVMULTITOUCH_MAXBUTTONS 32
+#define EVDEVMULTITOUCH_MAXQUEUE 32
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
+#define HAVE_PROPERTIES 1
+#endif
+
+#ifndef MAX_VALUATORS
+#define MAX_VALUATORS 36
+#endif
+
+#define MAX_VALUATORS_MT 5 //currently if MAXDEVICES == 40
+
+#define DEFAULT_TIMEOUT 100
+
+#define EVDEVMULTITOUCH_PROP_TRACKING_ID "EvdevMultitouch Tracking ID"
+#define EVDEVMULTITOUCH_PROP_MULTITOUCH_SUBDEVICES "EvdevMultitouch MultiTouch"
+#define EVDEVMULTITOUCH_PROP_USE_POLL  "EvdevMultitouch Use Poll"
+#define EVDEVMULTITOUCH_PROP_TRANSFORM "EvdevMultitouch Transform Matrix"
+#define EVDEVMULTITOUCH_PROP_GRABINFO  "EvdevMultitouch Grab Info"
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+typedef struct {
+    char *rules;
+    char *model;
+    char *layout;
+    char *variant;
+    char *options;
+} XkbRMLVOSet;
+#endif
+
+
+#define LONG_BITS (sizeof(long) * 8)
+
+/* Number of longs needed to hold the given number of bits */
+#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
+
+/* axis specific data for wheel emulation */
+typedef struct {
+    int up_button;
+    int down_button;
+    int traveled_distance;
+} WheelAxis, *WheelAxisPtr;
+
+/* Event queue used to defer keyboard/button events until EV_SYN time. */
+typedef struct {
+    enum {
+        EV_QUEUE_KEY,  /* xf86PostKeyboardEvent() */
+        EV_QUEUE_BTN,  /* xf86PostButtonEvent() */
+    } type;
+    int key;           /* May be either a key code or button number. */
+    int val;           /* State of the key/button; pressed or released. */
+} EventQueueRec, *EventQueuePtr;
+
+typedef struct _EvdevMultitouchDataMTRec{
+    int id;
+    int slot;
+    int abs;
+   BOOL containsValues;
+    Time expires;
+    int vals[MAX_VALUATORS];
+    InputInfoPtr pInfo;
+} EvdevMultitouchDataMTRec, *EvdevMultitouchDataMTPtr;
+
+
+/**
+ * EvdevMultitouch device information, including list of current object
+ */
+typedef struct {
+    const char *device;
+    int grabDevice;         /* grab the event device? */
+
+    int num_vals;           /* number of valuators */
+    int axis_map[max(ABS_CNT, REL_CNT)]; /* Map evdevmultitouch <axis> to index */
+    int vals[MAX_VALUATORS];
+    int old_vals[MAX_VALUATORS]; /* Translate absolute inputs to relative */
+    EvdevMultitouchDataMTRec vals_mt[MAX_VALUATORS_MT];
+
+    int flags;
+    int tool;
+    int num_buttons;            /* number of buttons */
+    BOOL swap_axes;
+    BOOL invert_x;
+    BOOL invert_y;
+    int num_multitouch;
+    OsTimerPtr multitouch_setting_timer;
+
+    int delta[REL_CNT];
+    unsigned int abs, rel, mt;
+
+    /* XKB stuff has to be per-device rather than per-driver */
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+    XkbComponentNamesRec    xkbnames;
+#endif
+    XkbRMLVOSet rmlvo;
+
+    /* Middle mouse button emulation */
+    struct {
+        BOOL                enabled;
+        BOOL                pending;     /* timer waiting? */
+        int                 buttonstate; /* phys. button state */
+        int                 state;       /* state machine (see bt3emu.c) */
+        Time                expires;     /* time of expiry */
+        Time                timeout;
+    } emulateMB;
+    struct {
+       int                 meta;           /* meta key to lock any button */
+       BOOL                meta_state;     /* meta_button state */
+       unsigned int        lock_pair[EVDEVMULTITOUCH_MAXBUTTONS];  /* specify a meta/lock pair */
+       BOOL                lock_state[EVDEVMULTITOUCH_MAXBUTTONS]; /* state of any locked buttons */
+    } dragLock;
+    struct {
+        BOOL                enabled;
+        int                 button;
+        int                 button_state;
+        int                 inertia;
+        WheelAxis           X;
+        WheelAxis           Y;
+        Time                expires;     /* time of expiry */
+        Time                timeout;
+    } emulateWheel;
+    /* run-time calibration */
+    struct {
+        int                 min_x;
+        int                 max_x;
+        int                 min_y;
+        int                 max_y;
+    } calibration;
+
+    struct {
+        int                 min_x;
+        int                 max_x;
+        int                 min_y;
+        int                 max_y;
+    } resolution;
+
+    unsigned char btnmap[32];           /* config-file specified button mapping */
+
+    int reopen_attempts; /* max attempts to re-open after read failure */
+    int reopen_left;     /* number of attempts left to re-open the device */
+    OsTimerPtr reopen_timer;
+
+    /* Cached info from device. */
+    char name[1024];
+    unsigned long bitmask[NLONGS(EV_CNT)];
+    unsigned long key_bitmask[NLONGS(KEY_CNT)];
+    unsigned long rel_bitmask[NLONGS(REL_CNT)];
+    unsigned long abs_bitmask[NLONGS(ABS_CNT)];
+    unsigned long led_bitmask[NLONGS(LED_CNT)];
+    struct input_absinfo absinfo[ABS_CNT];
+
+    /* minor/major number */
+    dev_t min_maj;
+
+    /* Event queue used to defer keyboard/button events until EV_SYN time. */
+    int                     num_queue;
+    EventQueueRec           queue[EVDEVMULTITOUCH_MAXQUEUE];
+
+    Time timeout; /* Maximum difference between consecutive fseq values
+                           that will allow a packet to be dropped */
+    
+    OsTimerPtr subdevice_timer;
+    int current_id;
+    int num_mt;
+    int id;
+    int last_slot;
+#if 1//ABS_MT_SLOT
+    BOOL mt_slot_supported;
+#endif
+    BOOL sync_mt;
+    BOOL associated;
+    BOOL use_poll;//polling_with_vsync
+
+    int touch_state;
+    Time evtime;
+    InputInfoPtr core_device;
+    
+} EvdevMultitouchRec, *EvdevMultitouchPtr;
+
+/* Event posting functions */
+void EvdevMultitouchQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value);
+void EvdevMultitouchQueueButtonEvent(InputInfoPtr pInfo, int button, int value);
+void EvdevMultitouchPostButtonEvent(InputInfoPtr pInfo, int button, int value);
+void EvdevMultitouchQueueButtonClicks(InputInfoPtr pInfo, int button, int count);
+void EvdevMultitouchPostRelativeMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
+                                  int v[MAX_VALUATORS]);
+void EvdevMultitouchPostAbsoluteMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
+                                  int v[MAX_VALUATORS]);
+unsigned int EvdevMultitouchUtilButtonEventToButtonNumber(EvdevMultitouchPtr pEvdevMultitouch, int code);
+
+/* Middle Button emulation */
+int  EvdevMultitouchMBEmuTimer(InputInfoPtr);
+BOOL EvdevMultitouchMBEmuFilterEvent(InputInfoPtr, int, BOOL);
+void EvdevMultitouchMBEmuWakeupHandler(pointer, int, pointer);
+void EvdevMultitouchMBEmuBlockHandler(pointer, struct timeval**, pointer);
+void EvdevMultitouchMBEmuPreInit(InputInfoPtr);
+void EvdevMultitouchMBEmuOn(InputInfoPtr);
+void EvdevMultitouchMBEmuFinalize(InputInfoPtr);
+void EvdevMultitouchMBEmuEnable(InputInfoPtr, BOOL);
+
+/* Mouse Wheel emulation */
+void EvdevMultitouchWheelEmuPreInit(InputInfoPtr pInfo);
+BOOL EvdevMultitouchWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value);
+BOOL EvdevMultitouchWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv);
+
+/* Draglock code */
+void EvdevMultitouchDragLockPreInit(InputInfoPtr pInfo);
+BOOL EvdevMultitouchDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value);
+
+#ifdef HAVE_PROPERTIES
+void EvdevMultitouchMBEmuInitProperty(DeviceIntPtr);
+void EvdevMultitouchWheelEmuInitProperty(DeviceIntPtr);
+void EvdevMultitouchDragLockInitProperty(DeviceIntPtr);
+#endif
+#endif
diff --git a/xorg-evdev-multitouch.pc.in b/xorg-evdev-multitouch.pc.in
new file mode 100644 (file)
index 0000000..cd92664
--- /dev/null
@@ -0,0 +1,6 @@
+sdkdir=@sdkdir@
+
+Name: xorg-evdev-multitouch
+Description: X.Org evdev multitouch input driver.
+Version: @PACKAGE_VERSION@
+Cflags: -I${sdkdir}