summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore76
-rw-r--r--.gitlab-ci.yml98
-rw-r--r--COPYING320
-rw-r--r--ChangeLog17
-rw-r--r--Makefile.am26
-rw-r--r--Makefile.old180
-rw-r--r--NEWS449
-rw-r--r--README.md (renamed from docs/README)125
-rw-r--r--TODO6
-rwxr-xr-xautogen.sh14
-rw-r--r--conf/11-x11-synaptics.fdi40
-rw-r--r--conf/70-synaptics.conf46
-rw-r--r--conf/Makefile.am27
-rw-r--r--configure.ac181
-rw-r--r--docs/COMPATIBILITY309
-rw-r--r--docs/INSTALL130
-rw-r--r--docs/INSTALL.DE103
-rw-r--r--docs/INSTALL.FR105
-rw-r--r--docs/tapndrag.dia584
-rw-r--r--docs/trouble-shooting.txt2
-rw-r--r--include/Makefile.am21
-rw-r--r--include/synaptics-properties.h161
-rw-r--r--man/Makefile.am80
-rw-r--r--man/synaptics.man938
-rw-r--r--man/synclient.1135
-rw-r--r--man/synclient.man46
-rw-r--r--man/syndaemon.166
-rw-r--r--man/syndaemon.man105
-rw-r--r--src/Makefile.am44
-rw-r--r--src/alpscomm.c205
-rw-r--r--src/alpscomm.h27
-rw-r--r--src/eventcomm.c1248
-rw-r--r--src/eventcomm.h57
-rw-r--r--src/properties.c833
-rw-r--r--src/ps2comm.c853
-rw-r--r--src/ps2comm.h85
-rw-r--r--src/psmcomm.c189
-rw-r--r--src/psmcomm.h12
-rw-r--r--src/synaptics.c4156
-rw-r--r--src/synaptics.h253
-rw-r--r--src/synapticsstr.h338
-rw-r--r--src/synclient.c357
-rw-r--r--src/syndaemon.c324
-rw-r--r--src/synproto.c170
-rw-r--r--src/synproto.h134
-rw-r--r--test/test-pad.c121
-rw-r--r--test/testprotocol.c82
-rw-r--r--tools/.gitignore3
-rw-r--r--tools/Makefile.am31
-rw-r--r--tools/synclient.c523
-rw-r--r--tools/syndaemon.c676
-rw-r--r--xorg-synaptics.pc.in6
52 files changed, 8941 insertions, 6176 deletions
diff --git a/.gitignore b/.gitignore
index aa87345..c496323 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,78 @@
-Makefile
-Makefile.in
-*.la
-*.lo
+#
+# X.Org module default exclusion patterns
+# The next section if for module specific patterns
+#
+# Do not edit the following section
+# GNU Build System (Autotools)
aclocal.m4
-autom4te.cache
+autom4te.cache/
+autoscan.log
+ChangeLog
+compile
config.guess
config.h
config.h.in
config.log
+config-ml.in
+config.py
config.status
+config.status.lineno
config.sub
configure
+configure.scan
depcomp
+.deps/
+INSTALL
install-sh
+.libs/
libtool
+libtool.m4
ltmain.sh
+lt~obsolete.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+Makefile
+Makefile.in
+mdate-sh
missing
-stamp-h1
-src/.libs
-src/.deps
-*.o
-synclient
-syndaemon
+mkinstalldirs
+*.pc
+py-compile
+stamp-h?
+symlink-tree
+texinfo.tex
+ylwrap
+
+# Do not edit the following section
+# Edit Compile Debug Document Distribute
+*~
+*.[0-9]
+*.[0-9]x
+*.bak
+*.bin
+core
+*.dll
+*.exe
+*-ISO*.bdf
+*-JIS*.bdf
+*-KOI8*.bdf
+*.kld
+*.ko
+*.ko.cmd
+*.lai
+*.l[oa]
+*.[oa]
+*.obj
+*.patch
+*.so
+*.pcf.gz
+*.pdb
+*.tar.bz2
+*.tar.gz
+#
+# Add & Override patterns for xf86-input-synaptics
+#
+# Edit the following section as needed
+# For example, !report.pc overrides *.pc. See 'man gitignore'
+#
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..a4700b8
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,98 @@
+# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0 filetype=yaml:
+#
+# This CI uses the freedesktop.org ci-templates.
+# Please see the ci-templates documentation for details:
+# https://freedesktop.pages.freedesktop.org/ci-templates/
+
+.templates_sha: &template_sha 25e8e9f020880aa35fffe3d6b259b933f0f9449f # see https://docs.gitlab.com/ee/ci/yaml/#includefile
+
+
+include:
+ # Arch container builder template
+ - project: 'freedesktop/ci-templates'
+ ref: *template_sha
+ file: '/templates/arch.yml'
+ - project: 'freedesktop/ci-templates'
+ ref: *template_sha
+ file: '/templates/ci-fairy.yml'
+ - template: Security/SAST.gitlab-ci.yml
+
+
+stages:
+ - prep # prep work like rebuilding the container images if there is a change
+ - build # for actually building and testing things in a container
+ - test
+ - deploy
+
+
+variables:
+ FDO_UPSTREAM_REPO: 'xorg/driver/xf86-input-synaptics'
+ # The tag should be updated each time the list of packages is updated.
+ # Changing a tag forces the associated image to be rebuilt.
+ # Note: the tag has no meaning, we use a date format purely for readability
+ FDO_DISTRIBUTION_TAG: '2023-10-01.0'
+ FDO_DISTRIBUTION_PACKAGES: 'git gcc pkgconf autoconf automake libtool make xorg-util-macros xorgproto xorg-server-devel pixman libevdev libx11 libxi libxtst'
+
+
+#
+# Verify that commit messages are as expected
+#
+check-commits:
+ extends:
+ - .fdo.ci-fairy
+ stage: prep
+ script:
+ - ci-fairy check-commits --junit-xml=results.xml
+ except:
+ - master@xorg/driver/xf86-input-synaptics
+ variables:
+ GIT_DEPTH: 100
+ artifacts:
+ reports:
+ junit: results.xml
+
+#
+# Verify that the merge request has the allow-collaboration checkbox ticked
+#
+check-merge-request:
+ extends:
+ - .fdo.ci-fairy
+ stage: deploy
+ script:
+ - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
+ artifacts:
+ when: on_failure
+ reports:
+ junit: results.xml
+ allow_failure: true
+
+
+#
+# Build a container with the given tag and the packages pre-installed.
+# This only happens if the tag changes, otherwise the existing image is
+# re-used.
+#
+container-prep:
+ extends:
+ - .fdo.container-build@arch
+ stage: prep
+ variables:
+ GIT_STRATEGY: none
+
+
+#
+# The default build, runs on the image built above.
+#
+build:
+ stage: build
+ extends:
+ - .fdo.distribution-image@arch
+ script:
+ - autoreconf -ivf
+ - mkdir _builddir
+ - pushd _builddir > /dev/null
+ - ../configure --disable-silent-rules
+ - make
+ - make check
+ - make distcheck
+ - popd > /dev/null
diff --git a/COPYING b/COPYING
index c7aea18..8e73894 100644
--- a/COPYING
+++ b/COPYING
@@ -1,280 +1,40 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
+The MIT License
+
+Copyright (c) 1997 C. Scott Ananian
+Copyright (c) 1998-2000 Bruce Kalk
+Copyright (c) 1999 Henry Davies
+Copyright (c) 2008 Fedor P. Goncharov
+Copyright (c) 2001 Stefan Gmeiner
+Copyright (c) 2002 S. Lehner
+Copyright (c) 2002 Linuxcare Inc. David Kennedy
+Copyright (c) 2003 Fred Hucht
+Copyright (c) 2003 Neil Brown
+Copyright (c) 2003 Jörg Bösner
+Copyright (c) 2003 Hartwig Felger
+Copyright (c) 2002-2007 Peter Osterlund
+Copyright (c) 2004 Arne Schwabe
+Copyright (c) 2004 Matthias Ihmig
+Copyright (c) 2004 Alexei Gilchrist
+Copyright (c) 2006-2007 Christian Thaeter
+Copyright (c) 2006 Stefan Bethge
+Copyright (c) 2007 Joseph P. Skudlarek
+Copyright (c) 2007 Florian Loitsch
+Copyright (c) 2008-2012 Red Hat, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+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.
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index bfbc20a..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,17 +0,0 @@
-2008-06-06 Christoph Brill <egore911@egore911.de>
-
- * src/freebsd_mouse.h, src/linux_input.h: drop and use installed
- system headers
- * src/alpscomm.c, src/eventcomm.c, src/ps2comm.c, src/psmcomm.c,
- src/psmcomm.h, src/synaptics.c, src/synclient.c, src/syndaemon.c: Add
- config.h
- * src/eventcomm.c, src/eventcomm.h: Only build on Linux
- * src/psmcomm.c, src/psmcomm.h: Only build on *BSD
- * src/synaptics.c, src/synclient.c: Make it build on the new build
- system
- * src/synaptics.c: Fix build against latest git by replacing all the
- xf86_ansi.h functions by the native ones
-
-2008-06-06 Christoph Brill <egore911@egore911.de>
-
- * src/*.c, src/*.h: move files to a directory
diff --git a/Makefile.am b/Makefile.am
index 7052905..521188e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,5 +18,27 @@
# 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
-SUBDIRS = src man
+# During distcheck, system locations (as provided by pkg-config) may
+# not be writable; provide instead relative locations.
+DISTCHECK_CONFIGURE_FLAGS = \
+ --with-sdkdir='$${includedir}/xorg' \
+ --with-xorg-conf-dir='$${datadir}/X11/xorg.conf.d'
+
+SUBDIRS = include src man tools conf
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xorg-synaptics.pc
+
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+ $(INSTALL_CMD)
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
+
+EXTRA_DIST = README.md
+ACLOCAL_AMFLAGS = -I m4
diff --git a/Makefile.old b/Makefile.old
deleted file mode 100644
index 334f012..0000000
--- a/Makefile.old
+++ /dev/null
@@ -1,180 +0,0 @@
-VER_LEVEL_1=0
-VER_LEVEL_2=14
-VER_LEVEL_3=6
-VERSION=$(VER_LEVEL_1).$(VER_LEVEL_2).$(VER_LEVEL_3)
-VERSION_ID=($(VER_LEVEL_1)*10000+$(VER_LEVEL_2)*100+$(VER_LEVEL_3))
-
-# Define the TOP variable to build using include files from a local source tree.
-#TOP = /usr/src/redhat/BUILD/XFree86-4.3.0/xc
-
-PREFIX ?= /usr/local
-BINDIR = $(DESTDIR)$(PREFIX)/bin
-MANDIR = $(DESTDIR)$(PREFIX)/man
-
-ifeq ($(ARCH),)
- ARCH = $(shell /bin/arch)
-endif
-ifeq ($(ARCH),amd64)
- ARCH = x86_64
-endif
-ifeq ($(ARCH),x86_64)
- ARCH_DEFINES = -D__x86_64__ -D_XSERVER64
- LIBDIR = lib64
-else
- ARCH_DEFINES = -D__i386__
- LIBDIR = lib
-endif
-
-BUILD_MODULAR ?= $(shell pkg-config xorg-server --exists && echo y)
-ifeq ($(BUILD_MODULAR),y)
- # Xorg 7.0 uses /usr/lib/xorg/modules and builds stripped shared objects
- INSTALLED_X = $(shell pkg-config xorg-server --variable=prefix)
- INPUT_MODULE_DIR = $(DESTDIR)$(shell pkg-config xorg-server --variable=moduledir)/input
- SYNAPTICS_DRV = synaptics_drv.so
- LDCOMBINEFLAGS = -shared -lc
- PICFLAG = $(call check_gcc,-fPIC,)
- X_INCLUDES_ROOT = $(INSTALLED_X)
- SDKDIR = $(shell pkg-config xorg-server --variable=sdkdir)
- ALLINCLUDES = -I. -I$(INSTALLED_X)/include/X11 \
- -I$(INSTALLED_X)/include/X11/extensions \
- -I$(SDKDIR)
-else
- INSTALLED_X = /usr/X11R6
- INPUT_MODULE_DIR = $(DESTDIR)/$(INSTALLED_X)/$(LIBDIR)/modules/input
- SYNAPTICS_DRV = synaptics_drv.o
- LDCOMBINEFLAGS = -r
-
- ifeq ($(TOP),)
- # This hack attempts to check if the needed XFree86 header files are installed.
- # It checks for a needed XFree86 4.3.00 SDK header file that is not installed by
- # default. If it is present, then it assumes that all header files are present.
- # If it is not present, then it assumes that all header files are not present
- # and uses the local copy of the XFree86 4.2.0 header files.
- X_INCLUDES_ROOT = $(shell \
- if [ -f $(INSTALLED_X)/$(LIBDIR)/Server/include/xisb.h ] ; then \
- echo -n $(INSTALLED_X) ; \
- else \
- echo -n Xincludes/usr/X11R6 ; \
- fi )
- ALLINCLUDES = -I. -I$(X_INCLUDES_ROOT)/include/X11 \
- -I$(X_INCLUDES_ROOT)/include/X11/extensions \
- -I$(X_INCLUDES_ROOT)/$(LIBDIR)/Server/include
- else
- SERVERSRC = $(TOP)/programs/Xserver
- ALLINCLUDES = -I. \
- -I$(SERVERSRC)/hw/xfree86/common \
- -I$(SERVERSRC)/hw/xfree86/os-support \
- -I$(SERVERSRC)/mi \
- -I$(SERVERSRC)/include \
- -I$(TOP)/include
- X_INCLUDES_ROOT = $(TOP)
- endif
-endif
-
-MODULE_DEFINES = -DIN_MODULE -DXFree86Module
-PROTO_DEFINES = -DFUNCPROTO=15 -DNARROWPROTO
-
-STD_DEFINES = -Dlinux -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_GNU_SOURCE -DSHAPE -DXINPUT -DXKB -DLBX -DXAPPGROUP -DXCSECURITY -DTOGCUP -DDPMSExtension -DPIXPRIV -DPANORAMIX -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER -DXFree86Server -DXF86VIDMODE -DSMART_SCHEDULE -DBUILDDEBUG -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG $(ARCH_DEFINES)
-ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(MODULE_DEFINES)
-
-check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
-
-CCOPTIONS := -pedantic -Wall -Wpointer-arith
-CCOPTIONS += $(call check_gcc,-fno-merge-constants,)
-CDEBUGFLAGS = -O2
-CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(PICFLAG) $(ALLDEFINES) -DVERSION="\"$(VERSION)\"" -DVERSION_ID="$(VERSION_ID)"
-CFLAGSCLIENT = $(CDEBUGFLAGS) $(CCOPTIONS) -DVERSION="\"$(VERSION)\"" -DVERSION_ID="$(VERSION_ID)" -I$(X_INCLUDES_ROOT)/include
-
-CC = gcc
-
-SRCS = synaptics.c ps2comm.c eventcomm.c psmcomm.c alpscomm.c
-OBJS = synaptics.o ps2comm.o eventcomm.o psmcomm.o alpscomm.o
-
-.c.o:
- $(RM) $@
- $(CC) -c $(CFLAGS) $(_NOOP_) $*.c
-
-all:: $(SYNAPTICS_DRV) synclient syndaemon
-
-install: $(BINDIR)/synclient $(BINDIR)/syndaemon $(INPUT_MODULE_DIR)/$(SYNAPTICS_DRV) install-man
-
-install-man: $(MANDIR)/man1/synclient.1 $(MANDIR)/man1/syndaemon.1 $(MANDIR)/man5/synaptics.5
-
-$(MANDIR)/man1/synclient.1: manpages/synclient.1
- install --mode=0644 -D $< $@
-
-$(MANDIR)/man1/syndaemon.1: manpages/syndaemon.1
- install --mode=0644 -D $< $@
-
-$(MANDIR)/man5/synaptics.5: manpages/synaptics.5
- install --mode=0644 -D $< $@
-
-$(BINDIR)/synclient : synclient
- install -D $< $@
-
-$(BINDIR)/syndaemon : syndaemon
- install -D $< $@
-
-$(INPUT_MODULE_DIR)/$(SYNAPTICS_DRV) : $(SYNAPTICS_DRV)
- install --mode=0644 -D $< $@
-
-$(SYNAPTICS_DRV): $(OBJS)
- $(RM) $@
- $(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $@
-
-synclient.o : synclient.c
- $(CC) $(CFLAGSCLIENT) -c -o $@ $<
-
-synclient : synclient.o
- $(CC) -o $@ $< -lm
-
-syndaemon.o : syndaemon.c
- $(CC) $(CFLAGSCLIENT) -c -o $@ $<
-
-syndaemon : syndaemon.o
- $(CC) -o $@ $< -lm -L$(INSTALLED_X)/$(LIBDIR) -lXext -lX11
-
-synaptics.o : synaptics.h synproto.h Makefile
-ps2comm.o : ps2comm.h synproto.h synaptics.h
-eventcomm.o : eventcomm.h linux_input.h synproto.h synaptics.h
-psmcomm.o : freebsd_mouse.h psmcomm.h synproto.h synaptics.h ps2comm.h
-alpscomm.o : alpscomm.h ps2comm.h synproto.h synaptics.h
-synclient.o : synaptics.h Makefile
-syndaemon.o : synaptics.h
-
-clean::
- $(RM) *.CKP *.ln *.BAK *.bak *.o *.so core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut synclient syndaemon "#"* manpages/*~ synaptics-$(VERSION).tar.bz2
-
-tags::
- etags -o TAGS *.c *.h
-
-uninstall::
- $(RM) $(BINDIR)/synclient $(BINDIR)/syndaemon $(INPUT_MODULE_DIR)/$(SYNAPTICS_DRV) $(MANDIR)/man1/synclient.1 $(MANDIR)/man1/syndaemon.1 $(MANDIR)/man5/synaptics.5
-
-distribution : synaptics-$(VERSION).tar.bz2
-
-ALLFILES = COMPATIBILITY FILES INSTALL INSTALL.DE INSTALL.FR LICENSE Makefile \
- NEWS README README.alps TODO Xincludes/ alps.patch linux_input.h \
- pc_keyb.c.diff.2.4.3 trouble-shooting.txt \
- synproto.h ps2comm.c ps2comm.h eventcomm.c eventcomm.h alpscomm.c alpscomm.h \
- psmcomm.c psmcomm.h freebsd_mouse.h \
- synaptics.c synaptics.h synaptics.spec \
- synclient.c syndaemon.c
-
-DST=synaptics-$(VERSION)
-
-synaptics-$(VERSION).tar.bz2 : FORCE
- rm -f $(DST).tar.bz2
- rm -rf $(DST)
- mkdir $(DST) $(DST)/manpages $(DST)/script $(DST)/test $(DST)/docs
- cp -a $(ALLFILES) $(DST)
- cp -a manpages/{synclient.1,syndaemon.1,synaptics.5} $(DST)/manpages/
- cp -a script/{usbmouse,usbhid} $(DST)/script/
- cp -a test/{test-pad.c,testprotocol.c} $(DST)/test/
- cp -a docs/tapndrag.dia $(DST)/docs/
- chmod u+w $(DST)/*
- tar cf $(DST).tar $(DST)
- rm -rf $(DST)
- bzip2 $(DST).tar
-
-.PHONY: FORCE
diff --git a/NEWS b/NEWS
deleted file mode 100644
index 715f916..0000000
--- a/NEWS
+++ /dev/null
@@ -1,449 +0,0 @@
-0.14.6 (2006-07-15)
-- Some small fixes for xorg 7.0 builds.
-- Made the driver work with xorg 7.1.
-- Updated the compatibility list.
-
-0.14.5 (2006-06-04)
-- Added PREFIX support to the Makefile. From Ricardo Garcia.
-- Implemented pressure dependent motion speed. From Stephane Rosi.
-- Minor documentation updates.
-- Implemented two-finger vertical and horizontal scrolling. From
- Stefan Bethge.
-- Some code cleanup.
-- Makefile support for Xorg 7.0. From Mattia Dongili.
-- Added new parameter "SingleTapTimeout" to give greater control over
- tap behavior. From Vaclav Kadlcik.
-- Updated the compatibility list.
-
-0.14.4 (2005-11-06)
-- X header file fix for xorg 6.8.99.15. Patch from Christoph Brill.
-- Fixed some long vs int inconsistencies to make the driver work
- correctly on 64 bit machines.
-- Made the device name change code handle more cases. Patch from Karl
- Tomlinson.
-- Included driver version number in the shared memory segment.
- Suggested by Stefan Kombrink for use in ksynaptics.
-- Vertical/horizontal scrolling was incorrectly stopped then the
- finger left the lower right corner if the scrolling was started from
- within that corner. Reported by Arie Huijzer.
-- Added option to syndaemon to ignore "modifier+another key" combos.
- Patch from Mattia Dongili.
-- Documentation updates.
-- Updated the compatibility list.
-
-0.14.3 (2005-07-22)
-- Added -k switch to syndaemon to make it ignore modifier keys when
- monitoring keyboard activity. Suggested by Harold Aling.
-- Also disable scrolling when the TouchpadOff parameter is set to 2.
- It doesn't make any sense to disable tapping but not scrolling as a
- response to keyboard activity.
-- In the DeviceOn() function, if opening the device node fails, try to
- auto-detect the correct event device again. This fixes some problems
- which occur after a suspend/resume cycle or after rmmod/insmod-ing
- the psmouse kernel driver.
-- Implemented new driver options LeftRightScrolling,
- UpDownScrollRepeat, LeftRightScrollRepeat and ScrollButtonRepeat to
- control the auto-repeat behavior of the scroll buttons. Contributed
- by Sam Barnett-Cormack with some small changes by me.
-- The evdev auto-dev code could incorrectly blame problems on a
- missing evdev driver.
-- If no /dev/input/event* device nodes are found, say so in the log
- file.
-- Documentation updates.
-- Updated the compatibility list.
-
-0.14.2 (2005-05-16)
-- Added a hotplug script that disables the touchpad when a USB mouse
- is connected. (And reenables it again when the USB mouse is
- disconnected.) From Joergen Scheibengruber.
-- Ignore the finger count from synaptics touchpads if the finger
- pressure is below finger_high. Some touchpads (for example, the one
- found on HP Pavilion 2028) report an unreliable finger count when
- the finger pressure is very low.
-- Use better permission modes in "make install". Patch from Mattia
- Dongili.
-- Some documentation updates.
-- Updated the compatibility list.
-
-0.14.1 (2005-03-15)
-- Fix for build problems on Gentoo amd64 systems.
-- Added -p switch to syndaemon to make it record its pid in a pid
- file. This simplifies init scripts. Based on a patch from Maximilian
- Attems.
-- Made the event auto device detection work even if some
- /dev/input/event nodes are missing, which can happen when using a
- udev based system.
-- Fixed alpscomm.c so that the X server doesn't lock up if you
- incorrectly configure the driver to read from an event device using
- protocol "alps".
-- Fixed off by one error in alps_process_byte().
-- Improved the "synclient -h" text when running on a 2.6 linux
- kernel.
-- Some documentation updates.
-- Updated the compatibility list.
-
-0.14.0 (2005-01-06)
-- Configurable palm detection heuristics. From Sean Dilda.
-- Added FastTaps option to make the driver react faster to tapping.
-- Another Makefile fix for x86_64 systems, from the FC3 RPM.
-- Support up to 12 (virtual) mouse buttons.
-- Made the event device auto detection more robust. Check for required
- features instead of relying on the IDs of the input device.
- Suggested by Vojtech Pavlik.
-- Made it possible to disable tapping without disabling mouse
- movements. Added -t switch to syndaemon to disable only tapping in
- response to keyboard activity.
-- Remove the shared memory area when the X server terminates.
-- Improved edge motion behavior. The speed no longer depends on the
- MinSpeed, MaxSpeed and AccelFactor parameters, and it doesn't depend
- on the packet rate from the touchpad hardware. The
- EdgeMotionMinSpeed and EdgeMotionMaxSpeed parameters may have to be
- modified to get the same speed as before this change.
-- Better noise reduction in the x/y delta estimates used for pointer
- motion. This will slow down the pointer movements, so to regain the
- same speed as before, the MinSpeed, MaxSpeed and AccelFactor
- parameters should be multiplied by 1.5.
-- Made it possible to use horizontal circular scrolling by smoothly
- switching from "horizontal" to "horizontal circular" when the finger
- enters the lower left or lower right corners during horizontal
- scrolling.
-- Fixed a bug that made it possible to lock up the X server by setting
- VertScrollDelta, HorizScrollDelta or CircScrollDelta to 0 while the
- touchpad was scrolling.
-- Implemented coasting, ie the ability to automatically continue
- scrolling with the same speed in the same direction when the finger
- leaves the touchpad.
-- Some documentation updates.
-- Updated the compatibility list.
-
-0.13.6 (2004-10-23)
-- Updated the ALPS patch for kernel 2.6.9.
-- Fixed detection of ALPS touchpads with signature 63 03 c8.
-- Some documentation updates.
-- Updated the compatibility list.
-
-0.13.5 (2004-08-07)
-- FreeBSD psm driver update. From Arne Schwabe.
-- Support for ALPS dualpoint touchpads (DELL Latitude CPx, DELL
- Inspiron 8200, DELL Latitude D600). From Alastair M. Robinson.
-- Documentation updates, including a trouble shooting guide.
-- Makefile fix to auto-detect x86_64 systems. From Mattia Dongili.
-- Updated the compatibility list.
-
-0.13.4 (2004-07-27)
-- Fixed X server crash caused by forgetting to remove the timer
- callback in the DeviceOff() function.
-- Fixed a problem with the shared memory area not being accessible
- after logging out from a KDE session and then logging in again
- without restarting the X server.
-- Added support for circular touchpads. From Axel G. Rossberg.
-- Added a true daemon mode to syndaemon. From James Ketrenos.
-- Better default parameters for alps touchpads.
-- Added Dmitry Torokhov's updated alps patch that can do hardware
- auto-detection and also disables hardware tapping.
-- Modified the Makefile to make it easier to build the driver for
- x86_64 systems.
-- Some documentation updates.
-- Updated the compatibility list.
-
-0.13.3 (2004-06-13)
-- Added support for Synaptics cPad devices. (Also requires a 2.6
- kernel patch.) From Jan Steinhoff.
-- Bug fix for touchpads with a middle mouse button.
-- Fixed handling of the repeater device.
-- Fixed compiler warnings when using the xorg sdk include files.
-- Added two parameters:
- * MaxDoubleTapTime makes it easier to do fast double clicks.
- * ClickTime adds a delay between the button down and button up
- events generated in response to a tap event.
-- Updated the alps patch for kernel 2.6.7-rc3.
-- Added -V option to synclient to display the version number.
-- Updated the compatibility list.
-
-0.13.2 (2004-05-09)
-- Fixed middle mouse button emulation, which broke in the 0.13.0
- release.
-- Made double clicks faster, so that they work in xmms and the gtk
- file selector. (They became slower in the 0.13.0 release.)
-- Updated the compatibility list.
-
-0.13.1 (2004-05-03)
-- Fixed detection of ALPS touchpads when using a 2.6 linux kernel.
-- Added more models to the compatibility list.
-- Added a "GuestMouseOff" parameter to disable the pass through
- device. From Moritz Maass.
-
-0.13.0 (2004-04-24)
-- Added back support for the TOP Makefile variable. (Needed when
- compiling for XFree86 < 4.2).
-- Fixed "double tap and drag", which is needed for word selection from
- an xterm.
-- Made it possible to bind the CornerButton and TapButton parameters
- to button values > 3.
-- Locked drags incorrectly generated extra button events in some
- cases.
-- Handle synaptics touchpads with a middle mouse button. Based on a
- 2.6 kernel patch from Dmitry Torokhov.
-- Added (untested) support for the FreeBSD psm mouse driver.
-- If the evdev kernel module seems to be missing, say so in the log
- file. (Very common error situation when using 2.6 kernels.)
-- Added support for ALPS touchpads using the 2.4 linux kernel.
-- Removed "repeater" from the shared memory segment. It's not possible
- to share pointers between different address spaces.
-- Added more models to the compatibility list.
-- Various documentation updates.
-- Some code cleanups.
-
-0.12.5 (2004-03-04)
-- Added more models to the compatibility list.
-- Added support for physical (ie not emulated) middle mouse buttons.
- Some ALPS models have middle mouse buttons.
-- The is_equal() function in synclient.c forgot to check
- multibuttons.
-- Reverted ALPS gesture bit handling to the 0.12.1 state, as the code
- in 0.12.2 breaks tap-and-drag operations on some ALPS touchpads.
-- Added pressure dependent edge motion speed. From Matthias Ihmig.
-- Made it possible to use "edge motion" also when not dragging. From
- Matthias Ihmig.
-- Made it possible to disable vertical and horizontal scrolling by
- setting the corresponding parameter to zero. From Matthias Ihmig.
-- Made it possible to have both circular scrolling and
- vertical/horizontal scrolling enabled at the same time. From
- Matthias Ihmig.
-- Minor documentation updates.
-
-0.12.4 (2004-02-10)
-- Changed suggested default values in the INSTALL file, to get more
- reasonable speed settings and edge parameters.
-- Include time in the "synclient -m" output.
-- Handle touchpads with a scroll region on the right side where very
- large X coordinates (typically 8176=0x1ff0) are reported.
-- Added more models to the compatibility list.
-- Updated the documentation.
-- Added support for circular scrolling. From Alexei Gilchrist.
-- Removed the saved_touchpad_off variable in syndaemon. It's more
- robust to just not disable the touchpad if it already is disabled.
-- Added manpages for synclient and syndaemon. Contributed by Mattia
- Dongili.
-- Added uninstall target to the Makefile. From Paul Bender.
-- Automatically build using the 4.3 SDK if available. Patch from Paul
- Bender.
-- Removed unnecessary local X include files that are available in the
- XFree86-devel package. Patch from Paul Bender.
-- Added a "distribution" target to the Makefile.
-- Added an RPM .spec file. From Giorgio Bellussi.
-
-0.12.3 (2004-01-11)
-- Added more models to the compatibility list.
-- Updated the documentation.
-- Added French translation of the INSTALL file. Contributed by Rigot
- Michel.
-- Removed deprecated use of psmouse_noext in the alps patch. This
- makes the patch work also for recent -mm kernels. (This breaks alps
- support for kernels older than 2.6.1-rc1, but those kernels should
- not be used anyway.)
-
-0.12.2 (2003-12-17)
-- Added more models to the compatibility list.
-- Updated the documentation.
-- Added an fflush() call after the printf in the monitor loop in
- synclient.c. This makes "synclient -m" behave better when the output
- is piped to some other program. From Anders Kaseorg.
-- Added parameter settings to the InputDevice example in README.alps,
- so that the whole thing can be cut and pasted into the XFree86
- config file. Suggestion from Gene Imes.
-- Made syndaemon recognize the '?' option, causing the help message to
- be printed.
-- In the syndaemon help message, print the default disable time.
- Suggestion from Frédéric Bothamy.
-- Only use the -fno-merge-constants compiler flag if the compiler
- understands it.
-- Updated INSTALL.DE. Translation contributed by Markus B.
-- Added pass through support, ie support for guest devices. From David
- Kennedy and Fred Hucht, somewhat cleaned up by me.
-- Updated the alps.patch to handle the gesture bit correctly. From Tom
- Sightler.
-- Made tap processing configurable. Patch from Justin Quek, cleaned up
- somewhat by me.
-
-0.12.1 (2003-11-14)
-- Added more models to the compatibility list.
-- Updated the documentation.
-- Added "syndaemon", a program that monitors keyboard activity and
- disables the touchpad when the keyboard is being used.
-- Some code cleanup.
-- Made the packet checking code less strict, so that the driver works
- also for touchpads that don't strictly follow the synaptics absolute
- protocol. Problem reported by Anders Kaseorg using a PowerPro C 3:16
- laptop.
-- Rediffed the alps patch for kernel 2.6.0-test9-bk16.
-- Removed compatibility code for old (<test6) 2.6 kernels.
-- No longer support installation from a precompiled binary. It should
- be possible for everyone to compile from source.
-
-0.12.0 (2003-10-26)
-- Initial support for ALPS touchpads.
-- Implemented "locked drags" after a suggestion from Karl Kashofer.
-- In the synclient program, use case insensitive string matching for
- parameter names.
-- Report all eight multi buttons in the synclient program.
-- Print the driver version string before other driver messages.
-- Added more models to the compatibility list.
-- Some documentation updates.
-
-0.11.8 (2003-10-08)
-- Initialize the id variable in QueryIsSynaptics(), so that we don't
- print out garbage if the identification fails.
-- Added "Sharp Actius MM10" to the compatibility list.
-- Added X include files so that the driver can be compiled without an
- external XFree86 source tree.
-- Some documentation updates.
-
-0.11.7 (2003-09-28)
-- Added "Acer TravelMate 234LC" to the compatibility list.
-- Added "Gateway 600S" to the compatibility list.
-- When using the Linux 2.6 event device, try to get exclusive access
- to the device, so that touchpad data doesn't leak to
- /dev/input/mice. This should fix problems with recent 2.6 kernels.
-
-0.11.6 (2003-09-26)
-- Updated the config section in INSTALL.DE. Added warning explaining
- that the file is not up to date.
-- Forgot to change the default values for TopEdge and BottomEdge when
- reversing the Y direction in version 0.11.5.
-- Warn about (and fix) mis-configured TopEdge/BottomEdge parameters.
-
-0.11.5 (2003-09-25)
-- Use the EVIOCGID ioctl for synaptics event device auto detection.
- This is much simpler than parsing /proc/bus/input/devices and more
- robust too.
-- Added support for the new 2.6 kernel events ABS_TOOL_WIDTH,
- BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP and BTN_TOOL_TRIPLETAP. Note
- that this swaps the direction of the Y axis internally to match X
- and the linux input subsystem. Because of this, the TopEdge and
- BottomEdge parameters must be modified in the config file. There is
- some backwards compatibility code for old 2.5/2.6 kernels that will
- probably be deleted later.
-
-0.11.4 (2003-09-22)
-- Reset the touchpad if it has been out of sync for too long. (By
- Hartwig Felger, cleaned up somewhat by me.) The synaptics manual
- explains that the touchpad can revert to relative mode after a power
- glitch or electrostatic discharge.
-- Created a helper macro to get rid of all the ugly "#ifdef DEBUG" in
- ps2comm.c.
-- Made "make tags" work for emacs.
-- Changed tab size from 4 to the standard value 8. Reindented code so
- that it still looks sane.
-- Fixed spelling errors.
-- synaptics: Added "Acer 661 LCi" to the compatibility list.
-- Made it possible to disable the touchpad at runtime. (Patch from
- Jörg Bösner.)
-- Clarified description of FingerLow/FingerHigh parameters.
-- Added "DELL Latitude CPi" to the compatibility list.
-- Changed the identifier for the synaptics protocol to match kernel
- 2.6.0-test5-bk8.
-
-0.11.3p11 (2003-07-31)
-- When setting the mode byte, don't set bits that the touchpad doesn't
- understand. Those bits are reserved and setting them can lead to
- weird problems, like the left button not working, as reported by
- Miles Lane.
-- Replaced a few forgotten hardcoded values with symbolic constants.
-- Disable stream mode before trying to identify/initialize the
- touchpad. Otherwise the touchpad can report motion data in the
- middle of the initialization sequence, which will confuse the driver
- and make the initialization fail. (Thanks to Miles Lane for helping
- to debug this problem.)
-- Updated COMPATIBILITY file.
-
-0.11.3p10 (2003-07-30)
-- Improved support for the old-style synaptics protocol.
-- Cleanup: Moved middle mouse button emulation to a separate function.
-- Cleanup: Moved finger detection to a separate function.
-- More robust resynchronization code, after an idea from Hartwig
- Felger. When we realize we are out of sync, only throw away one
- byte, not all bytes already read from the touchpad.
-
-0.11.3p9: (2003-07-29)
-- Added support for the old synaptics protocol. By Hartwig Felger.
-
-0.11.3p8: (2003-07-20)
-- From Hartwig Felger:
- * Added "multi-buttons" to the FEATURES list.
- * Updated NEWS file with data from the web page.
- * More robust parsing of the Handlers= line when doing auto detection
- for 2.6 kernels. ("Handlers=event2 js0" should work now.)
- * Updated synclient program to explain that it can't query hardware
- details when using a 2.6 kernel.
-
-0.11.3p7: (2003-07-17)
-- Added support for touchpads with "multi buttons". (Hartwig Felger)
-- Mention the synclient program in the INSTALL file.
-- Updated COMPATIBILITY file.
-- Implemented protocol "auto-dev" that automatically tries to find the
- proper device node and protocol for the touchpad. This makes it
- possible to have the same XF86Config file for 2.4 and 2.5 kernels.
- (Hartwig Felger)
-
-0.11.3p6: (2003-07-13)
-- Build fix for gentoo linux.
-- Longer timeout in the reset sequence. Experience from the 2.5 kernel
- driver has shown that 4 seconds is needed for some touchpads.
-- Made horizontal wheel replacement buttons work. (Patch from Hartwig
- Felger.)
-- Improved driver initialisation and finalization. From Hartwig
- Felger.
-- Reset the touchpad to relative mode when the X server
- terminates. (So that you can run gpm afterwards for example.)
-- Implemented install target in the Makefile.
-
-0.11.3p5: (2003-07-08)
-- Fixed rare X server hang/crash.
-
-0.11.3p4: (2003-07-05)
-- Workaround for an X server bug that could make the X server crash.
-- Fixed bug that sometimes incorrectly moved the cursor to the upper
- right corner of the screen.
-
-0.11.3p3: (2003-06-19)
-- Added support for linux kernel 2.5.x.
-
-0.11.?
-- Updated the synclient program to make it possible to read and write
- the variables in the shared memory area. This means you can change
- parameter settings without restarting the X server.
-- More reliable implementation of double click simulation using the up
- button. The old implementation incorrectly generated a single click
- instead of a double click for very short clicks of the up button.
-- Configurable timeout (option EmulateMidButtonTime) for middle button
- emulation.
-- Better state machine for handling middle mouse button emulation.
- * Clicks shorter than EmulateMidButtonTime are no longer lost.
- * The middle button event is generated as soon as both the left and
- the right buttons are pressed. The old code waited until the
- timeout had passed before even checking if both buttons were
- pressed.
-- Makefile improvements:
- * Made it possible to build synclient even if an X source tree is
- not available.
- * Added Makefile dependencies so that things get recompiled when a
- header file is changed.
- * synclient.c now includes synaptics.h instead of duplicating the
- shared memory structure definition.
-- The shared memory segment is properly removed when the X server
- exits, so that synclient isn't fooled by a stale segment if the X
- server is later restarted without SHMConfig activated.
-- The code that tried to remove any old shared memory segment at
- startup before creating the new segment didn't work. Therefore, X
- server startup failed if the size of the shared segment had changed.
- (Which was very annoying during development.)
-- Updated the TODO, PARAMETERS and FEATURES files.
-
-
-09.06.02 - Version 0.11.1
-- new packet format for Firmware 5.8 and others; solves problems with some
- models with 6 buttons (S. Lehner <sam_x@bluemail.ch>)
-
-13.10.01 - Version 0.10
-- multifinger taps
diff --git a/docs/README b/README.md
index d45133a..d86c758 100644
--- a/docs/README
+++ b/README.md
@@ -1,88 +1,16 @@
-Synaptics TouchPad driver for XOrg/XFree86
-------------------------------------------
-
-Introduction
-------------
-
-This is a driver for the Synaptics TouchPad for XOrg/XFree86 4.x. A
-Synaptics touchpad by default operates in compatibility mode by
-emulating a standard mouse. However, by using a dedicated driver, more
-advanced features of the touchpad becomes available, such as:
-
-- Movement with adjustable, non-linear acceleration and speed.
-- Button events through short touching of the touchpad.
-- Double-Button events through double short touching of the touchpad.
-- Dragging through short touching and holding down the finger on the
- touchpad.
-- Middle and right button events on the upper and lower corner of
- the touchpad.
-- Vertical scrolling (button four and five events) through moving
- the finger on the right side of the touchpad.
-- The up/down button sends button four/five events.
-- Horizontal scrolling (button six and seven events) through moving
- the finger on the lower side of the touchpad.
-- The multi-buttons send button four/five events, and six/seven
- events for horizontal scrolling.
-- Adjustable finger detection.
-- Multifinger taps: two finger for middle button and three finger
- for right button events. (Needs hardware support. Not all models
- implement this feature.)
-- Pressure dependent motion speed.
-- Trackstick emulation.
-- Run-time configuration using shared memory. This means you can
- change parameter settings without restarting the X server.
-
-Note that depending on the touchpad firmware, some of these features
-might be available even without using the synaptics driver. Note also
-that some functions are not available on all touchpad models, because
-they need support from the touchpad hardware/firmware. (Multifinger
-taps for example.)
-
-
-Installation
-------------
-
-See the INSTALL file for detailed installation instructions.
-
-
-Compatibility
--------------
-
-The driver has been reported to work on a number of different laptop
-computers. See the COMPATIBILITY file for the list. If your computer
-is not listed, please let me (petero2@telia.com) know if the driver
-works on your computer.
-
-
-Parameters
-----------
-
-See the synaptics(5) manual page for a description of the available
-driver parameters.
-
+Synaptics touchpad driver for X.Org
+-----------------------------------
FAQ
---
* Is this free software?
- Yes, the source code is released under the GNU General Public
- License.
+ Yes, the source code is released under the MIT license.
* When will the driver be included in the XOrg distribution?
- This is unlikely to happen because of copyright issues. Although
- the GPL license is compatible with the license used by the XOrg X
- server, the XOrg project doesn't want to include GPL code in their
- source code, because it would effectively make the whole XOrg
- project GPL. The synaptics license can't be changed unless all
- copyright holders agree to change the license, but previous
- attempts to find all copyright holders for the synaptics source
- code have failed.
-
- So unfortunately, the best we can currently hope for is that the
- synaptics driver is included as a separate package by the major
- distributions.
+ It is already.
* How do I use this driver with Linux kernel 2.6.x?
@@ -158,7 +86,7 @@ FAQ
If you are having problems with Mozilla, try this link:
- http://lists.debian.org/debian-laptop/2004/08/msg00167.html
+ https://lists.debian.org/debian-laptop/2004/08/msg00167.html
* Can the driver be used together with gpm?
@@ -171,28 +99,6 @@ FAQ
conflict, because the kernel driver will make sure both user space
drivers receive all events from the touchpad.
-* How do I compile the driver?
-
- Beginning with version 0.11.8, it should be possible to compile
- the driver by simply running "make". This will compile a driver
- for XFree86 4.2.x, which will also work for 4.3.x versions of
- XFree86.
-
- If you have an older version of XFree86, you will need an
- installed X source tree. On an RPM based distribution, you can
- build a suitable source tree by installing the XFree86 source RPM
- and compile it. For example, in RedHat 9, use the following
- commands:
-
- # rpm -vU XFree86-4.3.0-2.src.rpm
- # cd /usr/src/redhat/SPECS
- # rpmbuild -bb XFree86.spec
-
- Then change the TOP variable in the Makefile to match the version
- of XFree86 you are using. In the example above, set
-
- TOP = /usr/src/redhat/BUILD/XFree86-4.3.0/xc
-
* Can I use this driver with an ALPS Glidepoint device?
Yes, see the README.alps file for more information.
@@ -216,4 +122,23 @@ Authors
Many people have contributed to this driver. Look at the top of
synaptics.c and ps2comm.c for details.
-The current maintainer is Peter Osterlund <petero2@telia.com>.
+The current maintainer is X.org development team <xorg-devel@lists.x.org>.
+
+
+Contacts
+--------
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+ https://lists.x.org/mailman/listinfo/xorg
+
+The primary development code repository can be found at:
+
+ https://gitlab.freedesktop.org/xorg/driver/xf86-input-synaptics
+
+Please submit bug reports and requests to merge patches there.
+
+For patch submission instructions, see:
+
+ https://www.x.org/wiki/Development/Documentation/SubmittingPatches
+
diff --git a/TODO b/TODO
deleted file mode 100644
index a0e13c0..0000000
--- a/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-* Use ftok to get shared memory ID.
-* Add an option to disable "double-tap-and-drag" to make it possible
- to get faster double clicks.
-* Better coasting speed estimation. The current algorithm uses a time
- average but over a very short time period, so it's quite easy to
- accidentally start coasting.
diff --git a/autogen.sh b/autogen.sh
index 904cd67..da19622 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,12 +1,18 @@
#! /bin/sh
-srcdir=`dirname $0`
+srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
-cd $srcdir
+cd "$srcdir"
autoreconf -v --install || exit 1
-cd $ORIGDIR || exit $?
+cd "$ORIGDIR" || exit $?
+
+git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
+ git config --local format.subjectPrefix "PATCH xf86-input-synaptics"
+
+if test -z "$NOCONFIGURE"; then
+ exec "$srcdir"/configure "$@"
+fi
-$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/conf/11-x11-synaptics.fdi b/conf/11-x11-synaptics.fdi
new file mode 100644
index 0000000..ab8156d
--- /dev/null
+++ b/conf/11-x11-synaptics.fdi
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- Example fdi file that assigns the synaptics driver to any touchpad in
+ the system.
+
+ DO NOT EDIT THIS FILE, your distribution will likely overwrite
+ it when updating. Copy (and rename) this file into
+ /etc/hal/fdi/policy first before adding options.
+ -->
+<deviceinfo version="0.2">
+ <device>
+ <match key="info.capabilities" contains="input.touchpad">
+ <merge key="input.x11_driver" type="string">synaptics</merge>
+ <!-- Arbitrary options can be passed to the driver using
+ the input.x11_options property since xorg-server-1.5. -->
+ <!-- EXAMPLES:
+ Maximum movement of the finger for detecting a tap
+ <merge key="input.x11_options.MaxTapMove" type="string">2000</merge>
+
+ Enable vertical scrolling when dragging along the right edge
+ <merge key="input.x11_options.VertEdgeScroll" type="string">true</merge>
+
+ Enable vertical scrolling when dragging with two fingers anywhere on the touchpad
+ <merge key="input.x11_options.VertTwoFingerScroll" type="string">true</merge>
+
+ Enable horizontal scrolling when dragging with two fingers anywhere on the touchpad
+ <merge key="input.x11_options.HorizTwoFingerScroll" type="string">true</merge>
+
+ If on, circular scrolling is used
+ <merge key="input.x11_options.CircularScrolling" type="string">true</merge>
+
+ For other possible options, check CONFIGURATION DETAILS in synaptics man page
+ -->
+ <merge key="input.x11_options.SoftButtonAreas" type="string">50% 0 82% 0 0 0 0 0</merge>
+ <merge key="input.x11_options.SecondarySoftButtonAreas" type="string">58% 0 0 8% 42% 58% 0 8%</merge>
+ <match key="info.product" contains="Apple|bcm5974">
+ <merge key="input.x11_options.SoftButtonAreas" type="string">0 0 0 0 0 0 0 0</merge>
+ </match>
+ </match>
+ </device>
+</deviceinfo>
diff --git a/conf/70-synaptics.conf b/conf/70-synaptics.conf
new file mode 100644
index 0000000..aa50456
--- /dev/null
+++ b/conf/70-synaptics.conf
@@ -0,0 +1,46 @@
+# Example xorg.conf.d snippet that assigns the touchpad driver
+# to all touchpads. See xorg.conf.d(5) for more information on
+# InputClass.
+# DO NOT EDIT THIS FILE, your distribution will likely overwrite
+# it when updating. Copy (and rename) this file into
+# /etc/X11/xorg.conf.d first.
+# Additional options may be added in the form of
+# Option "OptionName" "value"
+#
+Section "InputClass"
+ Identifier "touchpad catchall"
+ Driver "synaptics"
+ MatchIsTouchpad "on"
+# This option is recommend on all Linux systems using evdev, but cannot be
+# enabled by default. See the following link for details:
+# http://who-t.blogspot.com/2010/11/how-to-ignore-configuration-errors.html
+# MatchDevicePath "/dev/input/event*"
+EndSection
+
+Section "InputClass"
+ Identifier "touchpad ignore duplicates"
+ MatchIsTouchpad "on"
+ MatchOS "Linux"
+ MatchDevicePath "/dev/input/mouse*"
+ Option "Ignore" "on"
+EndSection
+
+# This option enables the bottom right corner to be a right button on clickpads
+# and the right and middle top areas to be right / middle buttons on clickpads
+# with a top button area.
+# This option is only interpreted by clickpads.
+Section "InputClass"
+ Identifier "Default clickpad buttons"
+ MatchDriver "synaptics"
+ Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0"
+ Option "SecondarySoftButtonAreas" "58% 0 0 15% 42% 58% 0 15%"
+EndSection
+
+# This option disables software buttons on Apple touchpads.
+# This option is only interpreted by clickpads.
+Section "InputClass"
+ Identifier "Disable clickpad buttons on Apple touchpads"
+ MatchProduct "Apple|bcm5974"
+ MatchDriver "synaptics"
+ Option "SoftButtonAreas" "0 0 0 0 0 0 0 0"
+EndSection
diff --git a/conf/Makefile.am b/conf/Makefile.am
new file mode 100644
index 0000000..b883c10
--- /dev/null
+++ b/conf/Makefile.am
@@ -0,0 +1,27 @@
+# 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.
+
+
+if HAS_XORG_CONF_DIR
+dist_config_DATA = 70-synaptics.conf
+else
+fdidir = $(datadir)/hal/fdi/policy/20thirdparty
+dist_fdi_DATA = 11-x11-synaptics.fdi
+endif
diff --git a/configure.ac b/configure.ac
index 16cc04c..a905b72 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,73 +20,150 @@
#
# Process this file with autoconf to produce a configure script
-AC_PREREQ(2.57)
+# Initialize Autoconf
+AC_PREREQ([2.60])
AC_INIT([xf86-input-synaptics],
- 0.15.0,
- [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
- xf86-input-synaptics)
-
+ [1.9.2],
+ [https://gitlab.freedesktop.org/xorg/driver/xf86-input-synaptics/issues],
+ [xf86-input-synaptics])
AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIRS([m4])
AC_CONFIG_AUX_DIR(.)
-AM_INIT_AUTOMAKE([dist-bzip2])
-AM_MAINTAINER_MODE
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-xz])
-DRIVER_NAME=synaptics
-AC_SUBST([DRIVER_NAME])
+# Initialize libtool
+LT_INIT([disable-static])
-AM_CONFIG_HEADER([config.h])
+# Initialize X.Org macros 1.13 or later for XORG_ENABLE_UNIT_TESTS
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.13 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.13)
+XORG_DEFAULT_OPTIONS
+XORG_ENABLE_UNIT_TESTS
-# Checks for programs.
-AC_DISABLE_STATIC
-AC_PROG_LIBTOOL
-AC_PROG_CC
+# Checks for libraries.
+AC_CHECK_LIB([m], [rint])
-AH_TOP([#include "xorg-server.h"])
+# Store the list of server defined optional extensions in REQUIRED_MODULES
+m4_ifndef([XORG_DRIVER_CHECK_EXT],
+ [m4_fatal([must install xorg-server development files before running autoconf/autogen])])
+XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
-#AC_DEFINE(XFree86LOADER,1,[Stub define for loadable drivers])
-#
-#AC_ARG_ENABLE(XINPUT, AS_HELP_STRING([--enable-xinput],
-# [Build XInput support (default: yes)]),
-# [XINPUT=$enableval],[XINPUT=yes])
-#AM_CONDITIONAL(XINPUT, test "x$XINPUT" = "xyes")
-#if test "x$XINPUT" = "xyes" ; then
-# AC_DEFINE(XINPUT,1,[Enable XInput support])
-#fi
-#
-#AC_ARG_ENABLE(XKB, AS_HELP_STRING([--enable-xkb],
-# [Build XKB support (default: yes)]),
-# [XKB=$enableval],[XKB=yes])
-#AM_CONDITIONAL(XKB, test "x$XKB" = "xyes")
-#if test "x$XKB" = "xyes" ; then
-# AC_DEFINE(XKB,1,[Enable XKB support])
-#fi
+# Obtain compiler/linker options for the Synaptics driver dependencies
+PKG_CHECK_MODULES(XORG, [inputproto >= 2.1.99.3] [xorg-server >= 1.12] xproto inputproto $REQUIRED_MODULES)
+
+# X Server SDK location is required to install Synaptics header files
+# This location is also relayed in the xorg-synaptics.pc file
+sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server`
+AC_SUBST([sdkdir])
+# -----------------------------------------------------------------------------
+# Configuration options
+# -----------------------------------------------------------------------------
+# Define a configure option for an alternate input module directory
AC_ARG_WITH(xorg-module-dir,
- AC_HELP_STRING([--with-xorg-module-dir=DIR],
+ AS_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 extensions
-XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
-XORG_DRIVER_CHECK_EXT(XINPUT, inputproto)
-
-# Checks for pkg-config packages
-PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
-sdkdir=$(pkg-config --variable=sdkdir xorg-server)
-
-CFLAGS="$CFLAGS $XORG_CFLAGS "' -I$(top_srcdir)/src'
-AC_SUBST([CFLAGS])
-
-# Checks for libraries.
-
-# Checks for header files.
-AC_HEADER_STDC
-
-XORG_MANPAGE_SECTIONS
-XORG_RELEASE_VERSION
+# Define a configure option for an alternate X Server configuration directory
+sysconfigdir=`$PKG_CONFIG --variable=sysconfigdir xorg-server`
+AC_ARG_WITH(xorg-conf-dir,
+ AS_HELP_STRING([--with-xorg-conf-dir=DIR],
+ [Default xorg.conf.d directory [[default=from $PKG_CONFIG xorg-server]]]),
+ [configdir="$withval"],
+ [configdir="$sysconfigdir"])
+AC_SUBST(configdir)
+AM_CONDITIONAL(HAS_XORG_CONF_DIR, [test "x$sysconfigdir" != "x"])
+
+# Define a configure option to enable code debugging
+AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],
+ [Enable debugging (default: disabled)]),
+ [DEBUGGING=$enableval], [DEBUGGING=no])
+if test "x$DEBUGGING" = xyes; then
+ AC_DEFINE(DEBUG, 1, [Enable debugging code])
+fi
+AM_CONDITIONAL(DEBUG, [test "x$DEBUGGING" = xyes])
+
+# -----------------------------------------------------------------------------
+# Determine which backend, if any, to build
+# -----------------------------------------------------------------------------
+AC_MSG_CHECKING([which optional backends will be build])
+case "${host}" in
+*linux*)
+ AC_MSG_RESULT([ps2comm alpscomm eventcomm])
+ BUILD_PS2COMM="yes"
+ BUILD_EVENTCOMM="yes"
+ ;;
+*freebsd* | *netbsd* | *dragonfly*)
+ AC_MSG_RESULT([ps2comm alpscomm psmcomm])
+ BUILD_PS2COMM="yes"
+ BUILD_PSMCOMM="yes"
+ ;;
+*solaris* | *gnu*)
+ AC_MSG_RESULT([ps2comm alpscomm])
+ BUILD_PS2COMM="yes"
+ ;;
+*)
+ AC_MSG_ERROR([Cannot find suitable backends for this platform.])
+ ;;
+esac
+if test "x$BUILD_EVENTCOMM" = xyes; then
+ AC_DEFINE(BUILD_EVENTCOMM, 1, [Optional backend eventcomm enabled])
+ PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4])
+ SAVE_LIBS="$LIBS"
+ LIBS="$LIBEVDEV_LIBS"
+ AC_CHECK_LIB(evdev, libevdev_set_device_log_function,
+ [AC_DEFINE(HAVE_LIBEVDEV_DEVICE_LOG_FUNCS, 1,
+ [libevdev supports per-device log functions])],
+ [])
+ LIBS="$SAVE_LIBS"
+fi
+if test "x$BUILD_PSMCOMM" = xyes; then
+ AC_DEFINE(BUILD_PSMCOMM, 1, [Optional backend psmcomm enabled])
+fi
+if test "x$BUILD_PS2COMM" = xyes; then
+ AC_DEFINE(BUILD_PS2COMM, 1, [Optional backend ps2comm and alpscomm enabled])
+fi
+AM_CONDITIONAL([BUILD_EVENTCOMM], [test "x${BUILD_EVENTCOMM}" = "xyes"])
+AM_CONDITIONAL([BUILD_PSMCOMM], [test "x${BUILD_PSMCOMM}" = "xyes"])
+AM_CONDITIONAL([BUILD_PS2COMM], [test "x${BUILD_PS2COMM}" = "xyes"])
+
+# -----------------------------------------------------------------------------
+# Dependencies for synclient and syndaemon
+# -----------------------------------------------------------------------------
+# Obtain compiler/linker options for the Synaptics apps dependencies
+PKG_CHECK_MODULES(XI, x11 inputproto [xi >= 1.2])
+
+# The syndaemon program uses an optional XRecord extension implementation
+# If libxtst >= 1.0.99 is installed, Cflags contains the path to record.h
+# If recordproto < 1.13.99.1 is installed, Cflags contains the path to record.h
+PKG_CHECK_MODULES(XTST, xtst recordproto, have_libxtst="yes", have_libxtst="no")
+if test "x$have_libxtst" = "xyes" ; then
+ # Header record.h may come from the xtst or recordproto package, or may be missing
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $XTST_CFLAGS"
+ AC_CHECK_HEADERS([X11/extensions/record.h],,,[#include <X11/Xlib.h>])
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+# -----------------------------------------------------------------------------
+
+# Workaround overriding sdkdir to be able to create a tarball when user has no
+# write permission in sdkdir. See DISTCHECK_CONFIGURE_FLAGS in Makefile.am
+AC_ARG_WITH([sdkdir], [], [sdkdir="$withval"])
+
+AC_CONFIG_FILES([Makefile
+ src/Makefile
+ man/Makefile
+ tools/Makefile
+ conf/Makefile
+ include/Makefile
+ xorg-synaptics.pc])
+AC_OUTPUT
-AC_OUTPUT([Makefile src/Makefile man/Makefile])
diff --git a/docs/COMPATIBILITY b/docs/COMPATIBILITY
deleted file mode 100644
index c71fc34..0000000
--- a/docs/COMPATIBILITY
+++ /dev/null
@@ -1,309 +0,0 @@
-Acer 661 LCi
-Acer Aspire 1353LC
-Acer Aspire 1353XC
-Acer Aspire 1511 LMi
-Acer Aspire 1601LC
-Acer Aspire 1703SM
-Acer Aspire 2000 (Requires 2.6 kernel but *NOT* the ALPS patch)
-Acer Aspire 2010
-Acer Aspire 2020
-Acer Aspire 3003WLMi
-Acer Aspire 3023
-Acer Aspire 5670
-Acer Aspire 5672
-Acer Aspire 9301AWSMi
-Acer Extensa 3001 WLMi
-Acer Ferrari 3000LMi
-Acer Ferrari 3200
-Acer TravelMate 210TEV
-Acer TravelMate 220
-Acer TravelMate 2310
-Acer TravelMate 234LC
-Acer TravelMate 244LM
-Acer TravelMate 2501LC
-Acer TravelMate 280
-Acer TravelMate 290 (ALPS touchpad)
-Acer TravelMate 330T
-Acer TravelMate 340T
-Acer TravelMate 350TE
-Acer TravelMate 420DLC
-Acer TravelMate 451Cli
-Acer TravelMate 4672 WLMi
-Acer TravelMate 521TE
-Acer TravelMate 522TXV
-Acer TravelMate 525TE
-Acer TravelMate 533LCi
-Acer TravelMate 630
-Acer TravelMate 634LCi
-Acer TravelMate 739TL
-Acer TravelMate 800LCI
-Acer TravelMate 8104 WLMi
-Airis Diamond 630
-Airis Pragma 750
-Aopen Openbook 1545/1545D
-Apple iBook G4
-Arima A520-K7
-Aristo Smart 300
-ASUS A1000
-ASUS A2500
-ASUS A3500L
-ASUS A6000G
-ASUS A6Km-Q010H
-ASUS A6VA
-ASUS A7F
-ASUS B1500
-ASUS Degatto D1
-ASUS L2000B
-ASUS L2400D
-ASUS L3500D
-ASUS L3500H
-ASUS L3800C
-ASUS L8400 series
-ASUS M2400A
-ASUS M2400E
-ASUS M2400N
-ASUS M3000N
-ASUS M5N
-ASUS M6700N
-ASUS S1300
-ASUS S5200N
-ASUS Z62J
-ASUS Z71V
-BenQ JoyBook 2100E
-Clevo 5600P
-Clevo M375C
-Clevo M385C
-Compal CL56-15
-COMPAQ Armada 1750 (Requires reset hack)
-COMPAQ Armada M300
-COMPAQ Armada M700
-COMPAQ EVO N1015v
-COMPAQ EVO N1020v
-COMPAQ EVO N160
-COMPAQ EVO N180
-COMPAQ EVO N600c
-COMPAQ EVO N800v
-COMPAQ Presario 1200
-COMPAQ Presario 1213EA
-COMPAQ Presario 12XL125
-COMPAQ Presario 1510US
-COMPAQ Presario 1685
-COMPAQ Presario 1710T
-COMPAQ Presario 1723EA
-COMPAQ Presario 1800
-COMPAQ Presario 1800XL584
-COMPAQ Presario 18XL580
-COMPAQ Presario 2100Z
-COMPAQ Presario 2100US
-COMPAQ Presario 2155US
-COMPAQ Presario 2500
-COMPAQ Presario 2510EA
-COMPAQ Presario 2825EA
-COMPAQ Presario 700 (US/EA)
-COMPAQ Presario 711EA
-COMPAQ Presario 912RSH
-COMPAQ Presario 915US
-COMPAQ Presario R3000 (ALPS touchpad)
-Compaq Presario V5204NR
-DELL Inspiron 1100
-DELL Inspiron 2100
-DELL Inspiron 2200
-DELL Inspiron 2500
-DELL Inspiron 2600
-DELL Inspiron 2650
-DELL Inspiron 300m
-DELL Inspiron 3500
-DELL Inspiron 4000
-DELL Inspiron 4100 (but maybe not every model has a Synaptics touchpad, US models
- seem to have it, the German models don't)
-DELL Inspiron 4150
-DELL Inspiron 5000
-DELL Inspiron 500m (ALPS touchpad)
-DELL Inspiron 5100
-DELL Inspiron 5150
-DELL Inspiron 6000 (ALPS touchpad)
-DELL Inspiron 7000
-DELL Inspiron 7500
-DELL Inspiron 8000
-DELL Inspiron 8100
-DELL Inspiron 8200 (ALPS touchpad)
-DELL Inspiron 8500 (ALPS touchpad)
-DELL Inspiron 8600 (ALPS touchpad)
-DELL Latitude C400
-DELL Latitude C600
-DELL Latitude C610
-DELL Latitude C640
-DELL Latitude C800
-DELL Latitude CSx
-DELL Latitude CPi
-DELL Latitude CPx (ALPS touchpad)
-DELL Latitude D505 (ALPS touchpad)
-DELL Latitude D600 (ALPS touchpad)
-DELL Latitude D610 (ALPS touchpad)
-DELL Latitude D800 (ALPS touchpad)
-DELL Latitude L400
-DELL Latitude LS400
-DELL Latitude X1
-DELL Latitude X300
-Desknote A900
-Desknote A928
-ECS A-530 Transmeta 5600
-ECS Desknote i-Buddie A900
-EMachines M5305
-Fujitsu-Siemens AMILO A1667G
-Fujitsu-Siemens AMILO A 7600 (ALPS touchpad)
-Fujitsu-Siemens AMILO D P4 (FH2)
-Fujitsu-Siemens AMILO D 6800
-Fujitsu-Siemens AMILO D 7830
-Fujitsu-Siemens AMILO L 6810
-Fujitsu-Siemens AMILO L 7300 (ALPS touchpad)
-Fujitsu-Siemens Amilo M 1420
-Fujitsu-Siemens Amilo M 1425
-Fujitsu-Siemens AMILO M 6100
-Fujitsu-Siemens AMILO M 6300
-Fujitsu-Siemens AMILO M-6800
-Fujitsu-Siemens AMILO M-7400
-Fujitsu-Siemens AMILO M-7800
-Fujitsu-Siemens AMILO M-8800
-Fujitsu-Siemens AMILO Pro V2020
-Fujitsu-Siemens AMILO Si1520
-Fujitsu-Siemens LIFEBOOK C-1010 and C-1020
-Fujitsu-Siemens LIFEBOOK E7010 (ALPS touchpad)
-Fujitsu-Siemens LIFEBOOK P7010D
-Fujitsu-Siemens LIFEBOOK P7120D
-Fujitsu-Siemens LIFEBOOK S-2020 (ALPS touchpad)
-Fujitsu-Siemens LIFEBOOK S-4572 (ALPS touchpad)
-Gateway 200X
-Gateway 450XL
-Gateway 600S
-Gateway 7405GX
-Gateway MX 3228
-Gateway Solo 9300
-Gericom A2
-Gericom Cinema XXL
-Gericom Hummer 2430
-Gericom M6T
-Gericom Masterpiece 2030 (works partly)
-Gericom Webboy
-Gericom Webgine
-Gericom X5
-Gericom X5 Force
-HP Compaq NC6000
-HP Compaq nw8240
-HP Compaq NX6110
-HP Compaq NX6120
-HP Compaq NX7000
-HP Compaq NX7010
-HP Compaq NX9000
-HP Compaq NX9010
-HP N6395
-HP NW8000
-HP Omnibook 4150
-HP Omnibook 6000
-HP Omnibook 6100
-HP Omnibook XE3 500
-HP Omnibook XE3 GC (F2397)
-HP Omnibook XE3 GF
-HP Omnibook XE3L (F3446J)
-HP Omnibook XE4400
-HP Omnibook XT1000 (F3433)
-HP Pavilion DV1475EA
-HP Pavilion N3250
-HP Pavilion N3350
-HP Pavilion ZD7000
-HP Pavilion ZD8000
-HP Pavilion ZE4101
-HP Pavilion ZE4125
-HP Pavilion ZE4420us
-HP Pavilion ZE4521ea
-HP Pavilion ZE4610us
-HP Pavilion ZE5400
-HP Pavilion ZT3000
-HP Pavilion ZV5000 (ALPS touchpad)
-HP Special Edition L2000
-IBM ThinkPad R40
-IBM ThinkPad R50
-IBM ThinkPad T30
-IBM ThinkPad T40
-IBM ThinkPad T40p
-IBM ThinkPad T41
-IBM ThinkPad T42
-INote 88EPS
-IPC Powernote S
-Jewel Saffier 1500
-Lenovo 3000 C100
-LG LM50
-Los Alamos LUP4SA2
-MAXDATA Pro 5000X
-MAXDATA Pro 8000X
-MBO N.B.V.O. 1800+ (aka Mitac MiNote 8375)
-Medion 41700
-Medion MD40100
-Medion MD5400
-Medion MD9467 aka ASUS 8400K
-Medion MD9580-F - Aldi (Nord)
-Medion MD9626
-Mitac 6120N
-NEC Versa E400
-NEC Versa M400
-Packard Bell Easy Note E3259SE
-Panasonic CF-R1
-Panasonic CF-R3
-Panasonic Toughbook W2
-PowerPro C 3:16
-Prestigio Nobile 156
-RoverBook F219
-Samsung GT8800DXV
-Samsung P30
-Samsung Q10
-Samsung Q20
-Samsung V20
-Samsung X20
-Sharp Actius MM10
-Sharp Actius UM32W
-Sharp Muramasa PC-MV1-5CA
-Sharp PC-FS2518
-Siemens Nixdorf Scenic Mobile 710
-SONY VAIO FX405 (ALPS touchpad)
-SONY VAIO GR7/K
-SONY VAIO GRX570
-SONY VAIO PCG-FX701 (ALPS touchpad)
-SONY VAIO PCG-GRX650
-SONY VAIO PCG-NV105 (ALPS touchpad)
-SONY VAIO PCG-TR1A (ALPS touchpad)
-SONY VAIO VGN-A115S (ALPS touchpad)
-Sony VAIO VGN-S4XP (ALPS touchpad)
-SONY VAIO VGN-SZ72B (ALPS touchpad)
-SONY VAIO VGN-UX50 (ALPS dualpoint touchpad)
-SONY VAIO Z1 (ALPS touchpad)
-SONY VAIO Z505SX (ALPS touchpad)
-Sotec 3120X
-Targa Visionary Pro
-Targa Visionary XP-210
-Toshiba 1105 (ALPS touchpad)
-Toshiba 1410-303 (ALPS touchpad)
-Toshiba A20 (ALPS touchpad)
-Toshiba A25 (ALPS touchpad)
-Toshiba EX1/524CDET (ALPS touchpad)
-Toshiba Portege 2000 (ALPS touchpad)
-Toshiba Portege 3500 (ALPS touchpad)
-Toshiba Portege A100
-Toshiba Portege R200 (ALPS touchpad)
-Toshiba Qosmio E-15 (ALPS touchpad)
-Toshiba Satellite 1130-Z23 (ALPS touchpad)
-Toshiba Satellite 1400-103 (ALPS touchpad)
-Toshiba Satellite 1800
-Toshiba Satellite 2410 (ALPS touchpad)
-Toshiba Satellite A10 (ALPS touchpad)
-Toshiba Satellite A40 (ALPS touchpad)
-Toshiba Satellite A50-543 (ALPS touchpad)
-Toshiba Satellite A75-S209 (ALPS touchpad)
-Toshiba Satellite M30
-Toshiba Satellite P25-607
-Toshiba Satellite Pro 2100 (ALPS touchpad)
-Toshiba Satellite S3000-514 (ALPS touchpad)
-Toshiba Tecra A3 (ALPS touchpad)
-Toshiba Tecra A4
-Toshiba Tecra A8
-Toshiba Tecra M2 (ALPS touchpad)
-Vobis Highscreen XI 14-C1200 (Same as Yakumo Q5M 1.2GHz)
diff --git a/docs/INSTALL b/docs/INSTALL
deleted file mode 100644
index 900b8c5..0000000
--- a/docs/INSTALL
+++ /dev/null
@@ -1,130 +0,0 @@
-Installation of the Synaptics Touchpad Driver for XOrg/XFree 4.x
-================================================================
-
-Author: Stefan Gmeiner <riddlebox@freesurf.ch>
-
-Requirements
-------------
-
-1. You need X include files. On RPM based systems, they are usually
- included in the XFree86-devel package. On Debian systems, you need
- to install the packages x-dev, libx11-dev and libxext-dev.
-
-2. For use with kernel 2.6.x you need to enable synaptics touchpad
- support when configuring the kernel (CONFIG_MOUSE_PS2). You also
- need support for the evdev interface (CONFIG_INPUT_EVDEV). If you
- compile evdev as a module, make sure it is loaded before starting
- the X server, as it will not be auto-loaded.
-
-3. If you use XFree86 version 4.0 or 4.1, you will need the XFree86
- source code to compile the driver. See the "How do I compile the
- driver?" section in the FAQ in the README file for details.
-
-4. Using with kernel 2.4.x for x < 10 needs a kernel patch
- (pc_keyb.c.diff.2.4.3).
-
-Installing
-----------
-
-1. Type "make" to build the driver "synaptics_drv.o".
-
-2. Copy the driver module "synaptics_drv.o" into the XFree module
- path. This path is usually "/usr/X11R6/lib/modules/input/", and
- running "make install" as root will do this for you. Note though
- that some distributions have a different module path. For example,
- in Gentoo 1.4 (with XFree86 4.3.0), the correct path is
- "/usr/X11R6/lib/modules/drivers".
-
-3. Add the driver to the XFree configuration file (usually called
- /etc/X11/XF86Config-4 or /etc/X11/XF86Config)
-
-Section "Module"
-...
- Load "synaptics"
-...
-EndSection
-
-
-4. Add/Replace in the InputDevice section for the touchpad the
- following lines:
-
-Section "InputDevice"
- Identifier "Synaptics Mouse"
- Driver "synaptics"
- Option "Device" "/dev/psaux"
- Option "Protocol" "auto-dev"
-# enable SHMConfig if you want to enable synclient
-# NB: enabling SHMConfig is insecure, since any user can invoke it
-# Option "SHMConfig" "on"
- Option "LeftEdge" "1700"
- Option "RightEdge" "5300"
- Option "TopEdge" "1700"
- Option "BottomEdge" "4200"
- Option "FingerLow" "25"
- Option "FingerHigh" "30"
- Option "MaxTapTime" "180"
- Option "MaxTapMove" "220"
- Option "VertScrollDelta" "100"
- Option "CornerCoasting" "1"
- Option "CoastingSpeed" "3"
- Option "MinSpeed" "0.09"
- Option "MaxSpeed" "0.18"
- Option "AccelFactor" "0.0015"
-# Option "Repeater" "/dev/ps2mouse"
-EndSection
-
-Change the Identifier to the same name as in the ServerLayout section.
-The Option "Repeater" is at the moment for testing.
-
-5. Add the "CorePointer" option to the InputDevice line at the
- ServerLayout section:
-
- Section "ServerLayout"
- ...
- InputDevice "Synaptics Mouse" "CorePointer"
- ...
-
- Note! You can not have more than one core pointer, so if you want
- to use an external mouse too, you have to set all mouse input
- devices except one to "AlwaysCore" instead of "CorePointer". For
- example:
-
- Section "ServerLayout"
- ...
- InputDevice "Mouse0" "CorePointer"
- InputDevice "Synaptics Mouse" "AlwaysCore"
- ...
- Section "InputDevice"
- ...
- Identifier "Mouse0"
- Option "Device" "/dev/input/mice"
- ...
-
- This also applies if you are using a 2.6 linux kernel and the
- touchpad contains a "pass through" device. Usually a pass through
- device is a touch stick located in the middle of the keyboard, but
- it can also be a separate set of buttons located next to the
- touchpad. If you want the pass through device to be enabled in X,
- the second InputDevice is needed. If there is a line in
- /proc/bus/input/devices that begins with "P: Phys=synaptics-pt" it
- means that the kernel has found a pass through device.
-
-6. Start/Restart the X Server. If the touchpad doesn't work:
- a) Check the XFree log file. This file is usually called
- /var/log/XFree86.0.log.
- b) Try to start the X server with 'startx -- -logverbose 8' for
- more output.
-
-7. If you want to be able to change driver parameters without
- restarting the X server, enable the "SHMConfig" option in the XFree
- configuration file. You can then use the "synclient" program to
- query and modify driver parameters on the fly.
- Note! This is not secure if you are in an untrusted multiuser
- environment. All local users can change the parameters at any
- time.
-
-If you can't get the driver working, check the trouble-shooting.txt
-file for common problems. If that doesn't help, mail the log files and
-the configuration file to petero2@telia.com. If you use a 2.6.x linux
-kernel, also mail the output from dmesg and the output from
-"cat /proc/bus/input/devices".
diff --git a/docs/INSTALL.DE b/docs/INSTALL.DE
deleted file mode 100644
index 6b2e4ed..0000000
--- a/docs/INSTALL.DE
+++ /dev/null
@@ -1,103 +0,0 @@
-Installation des Synaptics Touchpad Treibers für XFree 4.x
-===========================================================
-
-Author: Stefan Gmeiner <riddlebox@freesurf.ch>
-Übersetzer Markus Bajones <bajo@gmx.at>
-
-Voraussetzung:
---------------
-
-- Bei Verwendung eines Kernel 2.4.x wenn x < 10 brauchst du einen Kernel Patch
- (pc_keyb.c.diff.2.4.3).
-
-
-- Bei Verwendung eines 2.6.x Kernels musst du während der Konfiguration
- das Synaptics Touchpad aktivieren (CONFIG_MOUSE_PS2 and
- CONFIG_MOUSE_PS2_SYNAPTICS).
- Weiters benötigst du das evdev Interface (CONFIG_INPUT_EVDEV).
- Falls du evdev als ein Modul kompiliert hast musst du sicherstellen, dass
- es vor dem start des X Server geladen wird, da es nicht automatisch
- geladen wird.
-
-
-- Bei Verwendung mit einem ALPS Touchpads musst du einen 2.6.x Kernel verwenden
- und den alps Patch installieren.
- Lies auch die README.alps für mehr Details.
-
-
-
-Installation:
--------------
-
-1. Gib "make" ein um den Treiber (synaptics_drv.o) zu erstellen.
-
-2. Kopiere das Treiber Modul (synaptics_drv.o) in das XFree Modul Verzeichnis
- (meist zu finden unter /usr/X11R6/lib/modules/input/).
- Wenn du X in /usr/X11R6 installiert hast, kannst du auch als root
- "make install" ausführen, dabei wird der Treiber in das obige Verzeichnis
- kopiert.
-
-3. Um den Treiber zu laden muss in der Konfigurationsdatei Load "synaptics"
- eingefügt werden.
-
-4. In der InputDevice-Section für das Touchpad sind folgende
-Optionen einzufügen/ersetzen:
-
-Section "InputDevice"
- Driver "synaptics"
- Identifier "Mouse[1]"
- Option "Device" "/dev/psaux"
- Option "Protocol" "auto-dev"
- Option "LeftEdge" "1700"
- Option "RightEdge" "5300"
- Option "TopEdge" "1700"
- Option "BottomEdge" "4200"
- Option "FingerLow" "25"
- Option "FingerHigh" "30"
- Option "MaxTapTime" "180"
- Option "MaxTapMove" "220"
- Option "VertScrollDelta" "100"
- Option "MinSpeed" "0.06"
- Option "MaxSpeed" "0.12"
- Option "AccelFactor" "0.0010"
- Option "SHMConfig" "on"
-# Option "Repeater" "/dev/ps2mouse"
-EndSection
-
-Als Identifier muss der gleiche Name wie in der
-ServerLayout-Section verwendet werden.
-
-5. Füge die "CorePointer" Option in die InputDevice Zeile in der ServerLayout Sektion ein:
-
-Section "ServerLayout"
-...
- InputDevice "Mouse[1]" "CorePointer"
-...
-
- Achtung: Du kannst nicht mehr als EINEN "core pointer" verwenden.
- Wenn du also auch eine externe Maus verwenden willst, musst du
- alle "mouse input devices" ausser einem von "CorePointer" auf "Always Core" umstellen.
-
-
-6. Der X-Server ist neu zu starten. Sollte das Touchpad nicht
- funktionieren.
-
- a) Die Ausgaben des XFree-Logfiles anschauen.
- b) Den XServer mit "startx -- -logverbose 8" starten um mehr
- Ausgaben zu erzeugen.
-
-
-7. Wenn du die Einstellungen des Treibers ohne Neustart des X Server ändern willst,
- aktiviere die Option "SHMConfig" in der XFree Konfigurationsdatei.
- Danach kannst du das Programm "synclient" verwenden um die Treiberoptionen
- direkt zu ändern.
-
- Achtung! Wenn du in einer nicht vertraunswürdigen Mehrbenutzer Umgebung bist
- ist dies nicht sicher.
- Alle lokalen Benutzer können jederzeit die Parameter verändern.
-
-
-Falls du den Treiber nicht zum Funktionieren bringst, schicke die Log-Files und
-die Konfigurationsdatei an petero2@telia.com.
-Wenn du einen 2.6.x Linux Kernel verwendest schick auch die Ausgabe von dmesg und
-den Inhalt von /proc/bus/input/devices mit.
diff --git a/docs/INSTALL.FR b/docs/INSTALL.FR
deleted file mode 100644
index 7a73667..0000000
--- a/docs/INSTALL.FR
+++ /dev/null
@@ -1,105 +0,0 @@
-Installation du driver du touchpad Synaptics pour XFree 4.x
-===========================================================
-
-Traduction française: Michel Rigot <michel.rigot@advalvas.be>
-
-Prérequis.
-----------
-
-1. L'utilisation d'un noyau antérieur à la version 2.4.10 nécessite
- un patch (pc_keyb.c.diff.2.4.3).
-
-2. Avec le noyau 2.6.x, vous devez activer le support du touchpad
- synaptics lors de la configuration du noyau
- (CONFIG_MOUSE_PS2 et CONFIG_MOUSE_PS2_SYNAPTICS). Vous avez également
- besoin du support pour l'interface evdev (CONFIG_INPUT_EVDEV).
- Si vous compilez evdev en tant que module, soyez attentif à ce qu'il
- soit chargé avant le démarrage du serveur X. Ceci est important
- puisqu'il ne sera pas chargé automatiquement.
-
-3. Pour son utilisation avec un touchpad ALPS, vous devez utiliser un
- noyau 2.6.x et appliquer le patch alps. Voyez le fichier README.alps
- pour plus de détails.
-
-4. Pour compiler le programme "syndeamon", vous avez besoin des
- fichiers "include" de X. Sur un système basé sur les paquetages RPM,
- ils sont habituellement inclus dans le paquet "XFree86-devel".
-
-Installation.
--------------
-
-1. Taper "make" pour créer le driver "synaptics_drv.o"
-
-2. Copier le driver "synaptics_drv.o" dans le répertoire de modules de
- XFree qui est habituellement "/usr/X11R6/lib/modules/input/".
- Utiliser "make install" en tant que root qui fait celà à votre place.
- Noter cependant que certaines distributions ont un chemin différent
- vers le répertoire de modules. Par example, dans la distribution
- Gentoo 1.4 (avec XFree86 4.3.0), le chemin correcte
- est "/usr/X11R6/lib/modules/drivers/".
-
-3. Charger le driver en ajoutant dans le fichier de configuration de
- XFree la ligne 'Load "synaptics"' dans la secion module.
-
-4. Ajouter ou remplacer les lignes suivantes pour le touchpad dans la
- section "InputDevice"
-
-Section "InputDevice"
- Driver "synaptics"
- Identifier "Mouse[1]"
- Option "Device" "/dev/psaux"
- Option "Protocol" "auto-dev"
- Option "LeftEdge" "1700"
- Option "RightEdge" "5300"
- Option "TopEdge" "1700"
- Option "BottomEdge" "4200"
- Option "FingerLow" "25"
- Option "FingerHigh" "30"
- Option "MaxTapTime" "180"
- Option "MaxTapMove" "220"
- Option "VertScrollDelta" "100"
- Option "MinSpeed" "0.06"
- Option "MaxSpeed" "0.12"
- Option "AccelFactor" "0.0010"
- Option "SHMConfig" "on"
-# Option "Repeater" "/dev/ps2mouse"
-EndSection
-
- Modifier la valeur de "Identifier" pour qu'elle corresponde au nom
- dans la section "ServerLayout".
- L'Option "Repeater" est en test pour le moment.
-
-5. Ajouter l' option "CorePointer" à la ligne "InputDevice" dans la
- section "ServerLayout".
-
-Section "ServerLayout"
- InputDevice "Mouse[1]" "CorePointer"
- ...
-
- Note! Vous ne pouvez avoir plus d'un "core pointer", alors si vous
- voulez utiliser une souris externe en plus du touchpad, vous
- devez placer tous les périphériques d'entrée de type souris
- en tant que "AlwaysCore", et un seul comme "CorePointer".
-
-6. Démarrer ou redémarrer le serveur X. Si le touchpad ne
- fonctionne pas:
-
- a) Vérifier les fichiers log de XFree.
- b) Essayer de démarrerle serveur X de la façon suivante pour obtenir
- plus de renseignements: "startx -- -logverbose 8"
-
-7. Si vous désirez pouvoir changer les paramètres du driver sans
- redémarrer le serveur X, activer l'option "SHMConfig" dans le
- fichier de configuration de XFree. Vous pouvez alors utiliser le
- programme "synclient" pour interroger ou modifier les paramètres
- du driverau vol.
-
- Note! Celà présente un certain danger si vous travaillez dans un
- environnement multi-utilisateurs non sécurisé. En effet,
- tous les utilisateurs locaux ont la possiblitéde changer les
- paramètres à leur guise.
-
-Si vous ne parvenez pas à faire fonctionner le driver, envoyez les
-fichiers log et de configuration à <petero2@telia.com>. Si vous
-utilisez un noyau Linux 2.6.x, envoyez également la sortie de "dmesg"
-et le contenu de "/proc/bus/input/devices".
diff --git a/docs/tapndrag.dia b/docs/tapndrag.dia
index a411572..c8ec9d7 100644
--- a/docs/tapndrag.dia
+++ b/docs/tapndrag.dia
@@ -13,22 +13,22 @@
<dia:string>#A4#</dia:string>
</dia:attribute>
<dia:attribute name="tmargin">
- <dia:real val="2.8222"/>
+ <dia:real val="2.8222000598907471"/>
</dia:attribute>
<dia:attribute name="bmargin">
- <dia:real val="2.8222"/>
+ <dia:real val="2.8222000598907471"/>
</dia:attribute>
<dia:attribute name="lmargin">
- <dia:real val="2.8222"/>
+ <dia:real val="2.8222000598907471"/>
</dia:attribute>
<dia:attribute name="rmargin">
- <dia:real val="2.8222"/>
+ <dia:real val="2.8222000598907471"/>
</dia:attribute>
<dia:attribute name="is_portrait">
<dia:boolean val="true"/>
</dia:attribute>
<dia:attribute name="scaling">
- <dia:real val="0.459"/>
+ <dia:real val="0.45899999141693115"/>
</dia:attribute>
<dia:attribute name="fitto">
<dia:boolean val="false"/>
@@ -62,13 +62,16 @@
</dia:composite>
</dia:attribute>
</dia:diagramdata>
- <dia:layer name="Background" visible="true">
+ <dia:layer name="Background" visible="true" active="true">
<dia:object type="UML - Usecase" version="0" id="O0">
<dia:attribute name="obj_pos">
<dia:point val="10.3763,6.64119"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="10.3763,6.64119;13.6263,8.64119"/>
+ <dia:rectangle val="10.3263,6.59119;13.6763,8.69119"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="10.3763,6.64119"/>
@@ -79,6 +82,9 @@
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -100,10 +106,10 @@
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="12.0013,7.94119"/>
+ <dia:point val="12.0013,7.82119"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -119,7 +125,10 @@
<dia:point val="10.3763,13.1485"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="10.3763,13.1485;13.6263,15.1485"/>
+ <dia:rectangle val="10.3263,13.0985;13.6763,15.1985"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="10.3763,13.1485"/>
@@ -130,6 +139,9 @@
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -151,10 +163,10 @@
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="12.0013,14.4485"/>
+ <dia:point val="12.0013,14.3285"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -170,7 +182,10 @@
<dia:point val="3.81628,19.5885"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="3.81628,19.5885;7.06628,21.5885"/>
+ <dia:rectangle val="3.76628,19.5385;7.11628,21.6385"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="3.81628,19.5885"/>
@@ -181,6 +196,9 @@
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -202,10 +220,10 @@
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="5.44128,20.8885"/>
+ <dia:point val="5.44128,20.7685"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -221,7 +239,10 @@
<dia:point val="10.3763,26.743"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="10.3763,26.743;13.6263,28.743"/>
+ <dia:rectangle val="10.3263,26.693;13.6763,28.793"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="10.3763,26.743"/>
@@ -232,6 +253,9 @@
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -253,10 +277,10 @@
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="12.0013,28.043"/>
+ <dia:point val="12.0013,27.923"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -272,7 +296,10 @@
<dia:point val="19.7687,13.1485"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="19.7687,13.1485;23.0187,15.1485"/>
+ <dia:rectangle val="19.7187,13.0985;23.0687,15.1985"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="19.7687,13.1485"/>
@@ -283,6 +310,9 @@
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -304,10 +334,10 @@
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="21.3937,14.4485"/>
+ <dia:point val="21.3937,14.3285"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -323,7 +353,10 @@
<dia:point val="19.7687,26.743"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="19.7687,26.743;23.0187,28.743"/>
+ <dia:rectangle val="19.7187,26.693;23.0687,28.793"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="19.7687,26.743"/>
@@ -334,6 +367,9 @@
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -355,10 +391,10 @@
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="21.3937,28.043"/>
+ <dia:point val="21.3937,27.923"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -374,7 +410,7 @@
<dia:point val="12.0013,8.64119"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="11.2013,8.59119;12.8013,13.1985"/>
+ <dia:rectangle val="11.5204,8.59119;12.4822,13.2603"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="12.0013,8.64119"/>
@@ -387,10 +423,10 @@
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O0" connection="6"/>
@@ -402,7 +438,7 @@
<dia:point val="12.0013,15.1485"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="11.2013,15.0985;12.8013,19.6885"/>
+ <dia:rectangle val="11.5204,15.0985;12.4822,19.7503"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="12.0013,15.1485"/>
@@ -415,14 +451,14 @@
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O1" connection="6"/>
- <dia:connection handle="1" to="O35" connection="1"/>
+ <dia:connection handle="1" to="O34" connection="1"/>
</dia:connections>
</dia:object>
<dia:object type="Standard - Line" version="0" id="O8">
@@ -430,7 +466,7 @@
<dia:point val="5.44128,21.5885"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="5.37057,21.5178;11.4551,27.6352"/>
+ <dia:rectangle val="5.37057,21.5178;10.9311,27.1152"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="5.44128,21.5885"/>
@@ -443,10 +479,10 @@
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O2" connection="6"/>
@@ -458,7 +494,7 @@
<dia:point val="13.6263,14.1485"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="13.5763,13.3485;19.8187,14.9485"/>
+ <dia:rectangle val="13.5763,13.6676;19.8805,14.6294"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="13.6263,14.1485"/>
@@ -471,10 +507,10 @@
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O1" connection="4"/>
@@ -486,23 +522,23 @@
<dia:point val="21.3937,13.1485"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="12.7045,7.63181;21.4621,13.2169"/>
+ <dia:rectangle val="13.0819,8.25411;21.4621,13.2169"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="21.3937,13.1485"/>
<dia:point val="13.1503,8.3483"/>
</dia:attribute>
<dia:attribute name="curve_distance">
- <dia:real val="0.341908"/>
+ <dia:real val="0.34190799999999999"/>
</dia:attribute>
<dia:attribute name="end_arrow">
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O4" connection="1"/>
@@ -514,7 +550,7 @@
<dia:point val="22.5427,27.0359"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="13.4221,6.84668;26.342,27.1059"/>
+ <dia:rectangle val="13.6263,7.35592;26.3479,27.1059"/>
</dia:attribute>
<dia:attribute name="bez_points">
<dia:point val="22.5427,27.0359"/>
@@ -530,10 +566,10 @@
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O5" connection="2"/>
@@ -542,41 +578,10 @@
</dia:object>
<dia:object type="Standard - BezierLine" version="0" id="O12">
<dia:attribute name="obj_pos">
- <dia:point val="4.29223,19.8814"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.626041,6.83963;10.4778,19.9508"/>
- </dia:attribute>
- <dia:attribute name="bez_points">
- <dia:point val="4.29223,19.8814"/>
- <dia:point val="-3.17884,14.883"/>
- <dia:point val="1.95138,8.18572"/>
- <dia:point val="10.3763,7.64119"/>
- </dia:attribute>
- <dia:attribute name="corner_types">
- <dia:enum val="0"/>
- <dia:enum val="0"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O2" connection="0"/>
- <dia:connection handle="3" to="O0" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - BezierLine" version="0" id="O13">
- <dia:attribute name="obj_pos">
<dia:point val="10.3763,27.743"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="3.43771,20.9027;10.4428,28.2834"/>
+ <dia:rectangle val="3.38587,21.2956;10.4428,28.2854"/>
</dia:attribute>
<dia:attribute name="bez_points">
<dia:point val="10.3763,27.743"/>
@@ -592,31 +597,37 @@
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O3" connection="3"/>
<dia:connection handle="3" to="O2" connection="5"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Note" version="0" id="O14">
+ <dia:object type="UML - Note" version="0" id="O13">
<dia:attribute name="obj_pos">
- <dia:point val="5.49118,39.4412"/>
+ <dia:point val="1.84118,30.7912"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="5.44118,39.3912;17.2912,49.9912"/>
+ <dia:rectangle val="1.79118,30.7412;15.4962,41.3412"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
- <dia:point val="5.49118,39.4412"/>
+ <dia:point val="1.84118,30.7912"/>
</dia:attribute>
<dia:attribute name="elem_width">
- <dia:real val="11.75"/>
+ <dia:real val="13.605"/>
</dia:attribute>
<dia:attribute name="elem_height">
- <dia:real val="10.5"/>
+ <dia:real val="10.500000000000002"/>
+ </dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
</dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
@@ -638,16 +649,16 @@ M : Finger movement
[U]: Generate button up event
[D]: Generate button down event
L : Locked drags enabled
-F : Fast taps enabled#</dia:string>
+TDG: Tap-and-drag gesture enabled#</dia:string>
</dia:attribute>
<dia:attribute name="font">
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="5.84118,40.6912"/>
+ <dia:point val="2.19118,31.9737"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -658,12 +669,12 @@ F : Fast taps enabled#</dia:string>
</dia:composite>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O15">
+ <dia:object type="Standard - Text" version="1" id="O14">
<dia:attribute name="obj_pos">
<dia:point val="11.23,10.8357"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="11.055,10.2357;11.405,11.1857"/>
+ <dia:rectangle val="11.0375,10.3032;11.4225,11.0282"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -674,7 +685,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="11.23,10.8357"/>
@@ -691,12 +702,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O16">
+ <dia:object type="Standard - Text" version="1" id="O15">
<dia:attribute name="obj_pos">
<dia:point val="8.4912,23.1912"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="7.9662,22.5912;9.0162,24.3412"/>
+ <dia:rectangle val="7.9137,22.6587;9.0687,24.1837"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -708,7 +719,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="8.4912,23.1912"/>
@@ -725,12 +736,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O17">
+ <dia:object type="Standard - Text" version="1" id="O16">
<dia:attribute name="obj_pos">
<dia:point val="17.0662,11.0357"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="16.8912,10.4357;17.2412,11.3857"/>
+ <dia:rectangle val="16.8737,10.5032;17.2587,11.2282"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -741,7 +752,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="17.0662,11.0357"/>
@@ -758,12 +769,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O18">
+ <dia:object type="Standard - Line" version="0" id="O17">
<dia:attribute name="obj_pos">
<dia:point val="13.6263,27.743"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="13.5763,26.943;19.8187,28.543"/>
+ <dia:rectangle val="13.5763,27.2621;19.8805,28.2239"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="13.6263,27.743"/>
@@ -776,37 +787,36 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O3" connection="4"/>
<dia:connection handle="1" to="O5" connection="3"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O19">
+ <dia:object type="Standard - Text" version="1" id="O18">
<dia:attribute name="obj_pos">
- <dia:point val="13.73,17.0857"/>
+ <dia:point val="12.9069,17.2258"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="12.33,16.4857;15.13,18.2357"/>
+ <dia:rectangle val="12.7144,16.6933;13.0994,17.4183"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
<dia:attribute name="string">
- <dia:string>#R
-[D] if F#</dia:string>
+ <dia:string>#R#</dia:string>
</dia:attribute>
<dia:attribute name="font">
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="13.73,17.0857"/>
+ <dia:point val="12.9069,17.2258"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -820,12 +830,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O20">
+ <dia:object type="Standard - Text" version="1" id="O19">
<dia:attribute name="obj_pos">
<dia:point val="5.32686,26.1857"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="4.80186,25.5857;5.85186,27.3357"/>
+ <dia:rectangle val="4.74936,25.6532;5.90436,27.1782"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -837,7 +847,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="5.32686,26.1857"/>
@@ -854,12 +864,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O21">
+ <dia:object type="Standard - Text" version="1" id="O20">
<dia:attribute name="obj_pos">
<dia:point val="16.3912,13.6912"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="15.1662,13.0912;17.6162,14.0412"/>
+ <dia:rectangle val="15.0437,13.1587;17.7387,13.8837"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -870,7 +880,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="16.3912,13.6912"/>
@@ -887,26 +897,27 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O22">
+ <dia:object type="Standard - Text" version="1" id="O21">
<dia:attribute name="obj_pos">
- <dia:point val="16.517,27.1577"/>
+ <dia:point val="16.1,28.5375"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="15.292,26.5577;17.742,27.5077"/>
+ <dia:rectangle val="14.3675,28.005;17.8325,29.53"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
<dia:attribute name="string">
- <dia:string>#TO or M#</dia:string>
+ <dia:string>#(TO or M)
+and TDG#</dia:string>
</dia:attribute>
<dia:attribute name="font">
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="16.517,27.1577"/>
+ <dia:point val="16.1,28.5375"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -920,27 +931,27 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O23">
+ <dia:object type="Standard - Text" version="1" id="O22">
<dia:attribute name="obj_pos">
- <dia:point val="1.24118,9.9412"/>
+ <dia:point val="4.54118,17.5412"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="0.36618,9.3412;2.11618,11.0912"/>
+ <dia:rectangle val="3.96368,17.0087;5.11868,18.5337"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
<dia:attribute name="string">
<dia:string>#TO3
-[D,U]#</dia:string>
+[D]#</dia:string>
</dia:attribute>
<dia:attribute name="font">
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="1.24118,9.9412"/>
+ <dia:point val="4.54118,17.5412"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -954,12 +965,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O24">
+ <dia:object type="Standard - Text" version="1" id="O23">
<dia:attribute name="obj_pos">
<dia:point val="24.4912,17.8412"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="23.4412,17.2412;25.5412,18.9912"/>
+ <dia:rectangle val="23.3362,17.3087;25.6462,18.8337"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -971,7 +982,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="24.4912,17.8412"/>
@@ -988,12 +999,15 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="UML - Usecase" version="0" id="O25">
+ <dia:object type="UML - Usecase" version="0" id="O24">
<dia:attribute name="obj_pos">
<dia:point val="19.7687,32.4912"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="19.7687,32.4912;23.0187,34.4912"/>
+ <dia:rectangle val="19.7187,32.4412;23.0687,34.5412"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="19.7687,32.4912"/>
@@ -1004,6 +1018,9 @@ F : Fast taps enabled#</dia:string>
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -1025,10 +1042,10 @@ F : Fast taps enabled#</dia:string>
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="21.3937,33.7912"/>
+ <dia:point val="21.3937,33.6712"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -1039,12 +1056,15 @@ F : Fast taps enabled#</dia:string>
</dia:composite>
</dia:attribute>
</dia:object>
- <dia:object type="UML - Usecase" version="0" id="O26">
+ <dia:object type="UML - Usecase" version="0" id="O25">
<dia:attribute name="obj_pos">
<dia:point val="19.7687,38.0412"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="19.7687,38.0412;23.0187,40.0412"/>
+ <dia:rectangle val="19.7187,37.9912;23.0687,40.0912"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="19.7687,38.0412"/>
@@ -1055,6 +1075,9 @@ F : Fast taps enabled#</dia:string>
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -1076,10 +1099,10 @@ F : Fast taps enabled#</dia:string>
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="21.3937,39.3412"/>
+ <dia:point val="21.3937,39.2212"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -1090,12 +1113,12 @@ F : Fast taps enabled#</dia:string>
</dia:composite>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O27">
+ <dia:object type="Standard - Line" version="0" id="O26">
<dia:attribute name="obj_pos">
<dia:point val="21.3937,28.743"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="20.5937,28.693;22.1937,32.5412"/>
+ <dia:rectangle val="20.9128,28.693;21.8746,32.603"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="21.3937,28.743"/>
@@ -1108,22 +1131,22 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O5" connection="6"/>
- <dia:connection handle="1" to="O25" connection="1"/>
+ <dia:connection handle="1" to="O24" connection="1"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O28">
+ <dia:object type="Standard - Line" version="0" id="O27">
<dia:attribute name="obj_pos">
<dia:point val="21.3937,34.4912"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="20.5937,34.4412;22.1937,38.0912"/>
+ <dia:rectangle val="20.9128,34.4412;21.8746,38.153"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="21.3937,34.4912"/>
@@ -1136,22 +1159,22 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O25" connection="6"/>
- <dia:connection handle="1" to="O26" connection="1"/>
+ <dia:connection handle="0" to="O24" connection="6"/>
+ <dia:connection handle="1" to="O25" connection="1"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O29">
+ <dia:object type="Standard - Text" version="1" id="O28">
<dia:attribute name="obj_pos">
<dia:point val="20.15,30.7875"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="19.275,30.1687;21.0438,31.175"/>
+ <dia:rectangle val="19.1875,30.255;21.1125,30.98"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1162,7 +1185,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="20.15,30.7875"/>
@@ -1179,12 +1202,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O30">
+ <dia:object type="Standard - Text" version="1" id="O29">
<dia:attribute name="obj_pos">
<dia:point val="20.7108,36.3412"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="20.5358,35.7412;20.8858,36.6912"/>
+ <dia:rectangle val="20.5183,35.8087;20.9033,36.5337"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1195,7 +1218,7 @@ F : Fast taps enabled#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="20.7108,36.3412"/>
@@ -1212,12 +1235,12 @@ F : Fast taps enabled#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O31">
+ <dia:object type="Standard - Text" version="1" id="O30">
<dia:attribute name="obj_pos">
<dia:point val="16.7608,32.1912"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="16.392,31.5724;17.1108,34.1787"/>
+ <dia:rectangle val="16.3758,31.6587;17.1458,33.9837"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1230,7 +1253,7 @@ M#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="16.7608,32.1912"/>
@@ -1247,12 +1270,12 @@ M#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - BezierLine" version="0" id="O32">
+ <dia:object type="Standard - BezierLine" version="0" id="O31">
<dia:attribute name="obj_pos">
<dia:point val="20.2447,38.3341"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="17.4488,27.7324;20.6882,38.4036"/>
+ <dia:rectangle val="17.4188,28.4368;20.3142,38.4036"/>
</dia:attribute>
<dia:attribute name="bez_points">
<dia:point val="20.2447,38.3341"/>
@@ -1268,22 +1291,22 @@ M#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O26" connection="0"/>
+ <dia:connection handle="0" to="O25" connection="0"/>
<dia:connection handle="3" to="O5" connection="5"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - BezierLine" version="0" id="O33">
+ <dia:object type="Standard - BezierLine" version="0" id="O32">
<dia:attribute name="obj_pos">
<dia:point val="23.0187,39.0412"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="11.7002,5.51197;30.2716,39.1017"/>
+ <dia:rectangle val="12.0013,5.45917;30.2892,39.1017"/>
</dia:attribute>
<dia:attribute name="bez_points">
<dia:point val="23.0187,39.0412"/>
@@ -1299,22 +1322,22 @@ M#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O26" connection="4"/>
+ <dia:connection handle="0" to="O25" connection="4"/>
<dia:connection handle="3" to="O0" connection="1"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O34">
+ <dia:object type="Standard - Text" version="1" id="O33">
<dia:attribute name="obj_pos">
<dia:point val="31.1912,22.9412"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="30.6662,22.3224;31.735,24.1287"/>
+ <dia:rectangle val="30.6137,22.4087;31.7687,23.9337"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1326,7 +1349,7 @@ M#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="31.1912,22.9412"/>
@@ -1343,12 +1366,15 @@ M#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="UML - Usecase" version="0" id="O35">
+ <dia:object type="UML - Usecase" version="0" id="O34">
<dia:attribute name="obj_pos">
<dia:point val="10.3763,19.6385"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="10.3763,19.6385;13.6263,21.6385"/>
+ <dia:rectangle val="10.3263,19.5885;13.6763,21.6885"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="10.3763,19.6385"/>
@@ -1359,6 +1385,9 @@ M#</dia:string>
<dia:attribute name="elem_height">
<dia:real val="2"/>
</dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
+ </dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
</dia:attribute>
@@ -1380,10 +1409,10 @@ M#</dia:string>
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="12.0013,20.9385"/>
+ <dia:point val="12.0013,20.8185"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -1394,21 +1423,27 @@ M#</dia:string>
</dia:composite>
</dia:attribute>
</dia:object>
- <dia:object type="UML - Usecase" version="0" id="O36">
+ <dia:object type="UML - Usecase" version="0" id="O35">
<dia:attribute name="obj_pos">
<dia:point val="3.36628,12.7652"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="3.36628,12.7652;7.36628,15.4319"/>
+ <dia:rectangle val="3.31628,12.7152;7.59378,15.6002"/>
+ </dia:attribute>
+ <dia:attribute name="meta">
+ <dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="3.36628,12.7652"/>
</dia:attribute>
<dia:attribute name="elem_width">
- <dia:real val="4"/>
+ <dia:real val="4.1775000000000002"/>
</dia:attribute>
<dia:attribute name="elem_height">
- <dia:real val="2.666666666666667"/>
+ <dia:real val="2.7850000000000001"/>
+ </dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000000000001"/>
</dia:attribute>
<dia:attribute name="line_colour">
<dia:color val="#000000"/>
@@ -1432,10 +1467,10 @@ Tap#</dia:string>
<dia:font family="arial" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="5.36628,13.9985"/>
+ <dia:point val="5.45503,13.9377"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -1446,28 +1481,27 @@ Tap#</dia:string>
</dia:composite>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O37">
+ <dia:object type="Standard - Text" version="1" id="O36">
<dia:attribute name="obj_pos">
- <dia:point val="8.11628,16.7357"/>
+ <dia:point val="9.61628,16.9857"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="6.54128,16.1357;9.69128,18.6857"/>
+ <dia:rectangle val="9.03878,16.4532;10.1938,17.9782"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
<dia:attribute name="string">
<dia:string>#TO4
-[U] if F
-[D] if !F#</dia:string>
+[D]#</dia:string>
</dia:attribute>
<dia:attribute name="font">
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="8.11628,16.7357"/>
+ <dia:point val="9.61628,16.9857"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -1481,12 +1515,12 @@ Tap#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O38">
+ <dia:object type="Standard - Line" version="0" id="O37">
<dia:attribute name="obj_pos">
<dia:point val="12.0013,21.6385"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="11.2013,21.5885;12.8013,26.793"/>
+ <dia:rectangle val="11.5204,21.5885;12.4822,26.8548"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="12.0013,21.6385"/>
@@ -1499,22 +1533,22 @@ Tap#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O35" connection="6"/>
+ <dia:connection handle="0" to="O34" connection="6"/>
<dia:connection handle="1" to="O3" connection="1"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O39">
+ <dia:object type="Standard - Text" version="1" id="O38">
<dia:attribute name="obj_pos">
- <dia:point val="12.8407,23.2357"/>
+ <dia:point val="13.2364,23.2857"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="12.3157,22.6357;13.3657,24.3857"/>
+ <dia:rectangle val="12.6589,22.7532;13.8139,24.2782"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1526,10 +1560,10 @@ Tap#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
- <dia:point val="12.8407,23.2357"/>
+ <dia:point val="13.2364,23.2857"/>
</dia:attribute>
<dia:attribute name="color">
<dia:color val="#000000"/>
@@ -1543,12 +1577,12 @@ Tap#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O40">
+ <dia:object type="Standard - Line" version="0" id="O39">
<dia:attribute name="obj_pos">
<dia:point val="5.44128,12.7652"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="5.37093,7.69694;11.3969,12.8356"/>
+ <dia:rectangle val="5.37093,8.2776;10.9389,12.8356"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="5.44128,12.7652"/>
@@ -1561,22 +1595,22 @@ Tap#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O36" connection="1"/>
+ <dia:connection handle="0" to="O35" connection="1"/>
<dia:connection handle="1" to="O0" connection="5"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O41">
+ <dia:object type="Standard - Text" version="1" id="O40">
<dia:attribute name="obj_pos">
<dia:point val="7.37686,9.76072"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="6.85186,9.16072;7.90186,10.9107"/>
+ <dia:rectangle val="6.79936,9.22822;7.95436,10.7532"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1588,7 +1622,7 @@ Tap#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="7.37686,9.76072"/>
@@ -1605,12 +1639,12 @@ Tap#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O42">
+ <dia:object type="Standard - Line" version="0" id="O41">
<dia:attribute name="obj_pos">
<dia:point val="7.51628,14.1485"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="7.46628,13.3485;10.4263,14.9485"/>
+ <dia:rectangle val="7.46628,13.6676;10.4881,14.6294"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="7.51628,14.1485"/>
@@ -1623,22 +1657,22 @@ Tap#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O36" connection="4"/>
+ <dia:connection handle="0" to="O35" connection="4"/>
<dia:connection handle="1" to="O1" connection="3"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O43">
+ <dia:object type="Standard - Text" version="1" id="O42">
<dia:attribute name="obj_pos">
<dia:point val="8.77686,12.9857"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="8.25186,12.3857;9.30186,14.1357"/>
+ <dia:rectangle val="8.19936,12.4532;9.35436,13.9782"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1650,7 +1684,7 @@ Tap#</dia:string>
<dia:font family="courier new" style="0" name="Courier"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="8.77686,12.9857"/>
@@ -1667,40 +1701,40 @@ Tap#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Arc" version="0" id="O44">
+ <dia:object type="Standard - Arc" version="0" id="O43">
<dia:attribute name="obj_pos">
<dia:point val="10.3763,20.6385"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="4.60303,14.6434;10.447,20.7092"/>
+ <dia:rectangle val="6.86308,15.0734;10.4452,20.7074"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="10.3763,20.6385"/>
- <dia:point val="5.21628,15.2319"/>
+ <dia:point val="6.932,15.1423"/>
</dia:attribute>
<dia:attribute name="curve_distance">
- <dia:real val="-1.31629"/>
+ <dia:real val="0.01"/>
</dia:attribute>
<dia:attribute name="end_arrow">
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O35" connection="3"/>
- <dia:connection handle="1" to="O36" connection="6"/>
+ <dia:connection handle="0" to="O34" connection="3"/>
+ <dia:connection handle="1" to="O35" connection="7"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - BezierLine" version="0" id="O45">
+ <dia:object type="Standard - BezierLine" version="0" id="O44">
<dia:attribute name="obj_pos">
<dia:point val="22.5427,32.7841"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="13.0488,6.13252;28.0767,32.8535"/>
+ <dia:rectangle val="13.1503,6.39214;28.0842,32.8535"/>
</dia:attribute>
<dia:attribute name="bez_points">
<dia:point val="22.5427,32.7841"/>
@@ -1716,22 +1750,22 @@ Tap#</dia:string>
<dia:enum val="1"/>
</dia:attribute>
<dia:attribute name="end_arrow_length">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="end_arrow_width">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O25" connection="2"/>
+ <dia:connection handle="0" to="O24" connection="2"/>
<dia:connection handle="3" to="O0" connection="2"/>
</dia:connections>
</dia:object>
- <dia:object type="Standard - Text" version="1" id="O46">
+ <dia:object type="Standard - Text" version="1" id="O45">
<dia:attribute name="obj_pos">
<dia:point val="26.2,27.525"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="26.2,26.9063;27.3188,27.9125"/>
+ <dia:rectangle val="26.2,26.93;27.5025,27.675"/>
</dia:attribute>
<dia:attribute name="text">
<dia:composite type="text">
@@ -1742,7 +1776,7 @@ Tap#</dia:string>
<dia:font family="sans" style="0" name="Helvetica"/>
</dia:attribute>
<dia:attribute name="height">
- <dia:real val="0.8"/>
+ <dia:real val="0.80000000000000004"/>
</dia:attribute>
<dia:attribute name="pos">
<dia:point val="26.2,27.525"/>
@@ -1759,5 +1793,99 @@ Tap#</dia:string>
<dia:enum val="3"/>
</dia:attribute>
</dia:object>
+ <dia:object type="Standard - Arc" version="0" id="O46">
+ <dia:attribute name="obj_pos">
+ <dia:point val="13.1503,27.0359"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="13.1003,14.6561;17.8,27.0859"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="13.1503,27.0359"/>
+ <dia:point val="13.1503,14.8556"/>
+ </dia:attribute>
+ <dia:attribute name="curve_distance">
+ <dia:real val="4.5996514805718602"/>
+ </dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.10000000149011612"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.79999999999999993"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.79999999999999993"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O3" connection="2"/>
+ <dia:connection handle="1" to="O1" connection="7"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="1" id="O47">
+ <dia:attribute name="obj_pos">
+ <dia:point val="19.8272,20.6239"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="18.0947,20.0914;21.5597,22.4164"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#(TO or M)
+and !TDG
+[U]#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="courier new" style="0" name="Courier"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.80000000000000004"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="19.8272,20.6239"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="valign">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O48">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5.44128,19.5885"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="4.97124,15.4384;5.93303,19.6387"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="5.44128,19.5885"/>
+ <dia:point val="5.45503,15.5502"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.79999999999999993"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.79999999999999993"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O2" connection="1"/>
+ <dia:connection handle="1" to="O35" connection="6"/>
+ </dia:connections>
+ </dia:object>
</dia:layer>
</dia:diagram>
diff --git a/docs/trouble-shooting.txt b/docs/trouble-shooting.txt
index 3d2e012..59dd2ff 100644
--- a/docs/trouble-shooting.txt
+++ b/docs/trouble-shooting.txt
@@ -145,7 +145,7 @@ Possible fixes:
On some computers, it is possible to disable the touchpad either with
a special key combination, from the BIOS, or with a special touchpad
on/off button. On some machines, cycling the power doesn't
-automatically reenable the touchpad.
+automatically re-enable the touchpad.
If the touchpad appears to be dead, try to enable it from the BIOS or
using a key combination. One user also reported that he had to remove
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..8234020
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,21 @@
+# 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.
+
+sdk_HEADERS = synaptics-properties.h
diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
new file mode 100644
index 0000000..a0d7524
--- /dev/null
+++ b/include/synaptics-properties.h
@@ -0,0 +1,161 @@
+/*
+ * 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
+ */
+
+#ifndef _SYNAPTICS_PROPERTIES_H_
+#define _SYNAPTICS_PROPERTIES_H_
+
+/**
+ * Properties exported by the synaptics driver. These properties are
+ * recognized by the driver and will change its behavior when modified.
+ * For a description of what each property does, see synaptics.h.
+ */
+
+/* 32 bit, 4 values, left, right, top, bottom */
+#define SYNAPTICS_PROP_EDGES "Synaptics Edges"
+
+/* 32 bit, 3 values, low, high, <deprecated> */
+#define SYNAPTICS_PROP_FINGER "Synaptics Finger"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_TAP_TIME "Synaptics Tap Time"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_TAP_MOVE "Synaptics Tap Move"
+
+/* 32 bit, 3 values, single touch timeout, max tapping time for double
+ * taps, duration of a single click */
+#define SYNAPTICS_PROP_TAP_DURATIONS "Synaptics Tap Durations"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_CLICKPAD "Synaptics ClickPad"
+
+/* 8 bit (BOOL), <deprecated> */
+#define SYNAPTICS_PROP_TAP_FAST "Synaptics Tap FastTap"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_MIDDLE_TIMEOUT "Synaptics Middle Button Timeout"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_TWOFINGER_PRESSURE "Synaptics Two-Finger Pressure"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_TWOFINGER_WIDTH "Synaptics Two-Finger Width"
+
+/* 32 bit, 2 values, vert, horiz */
+#define SYNAPTICS_PROP_SCROLL_DISTANCE "Synaptics Scrolling Distance"
+
+/* 8 bit (BOOL), 3 values, vertical, horizontal, corner */
+#define SYNAPTICS_PROP_SCROLL_EDGE "Synaptics Edge Scrolling"
+
+/* 8 bit (BOOL), 2 values, vertical, horizontal */
+#define SYNAPTICS_PROP_SCROLL_TWOFINGER "Synaptics Two-Finger Scrolling"
+
+/* FLOAT, 4 values, min, max, accel, <deprecated> */
+#define SYNAPTICS_PROP_SPEED "Synaptics Move Speed"
+
+/* 8 bit (BOOL), 2 values, updown, leftright */
+#define SYNAPTICS_PROP_BUTTONSCROLLING "Synaptics Button Scrolling"
+
+/* 8 bit (BOOL), 2 values, updown, leftright */
+#define SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT "Synaptics Button Scrolling Repeat"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_BUTTONSCROLLING_TIME "Synaptics Button Scrolling Time"
+
+/* 8 bit, valid values (0, 1, 2) */
+#define SYNAPTICS_PROP_OFF "Synaptics Off"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_GUESTMOUSE "Synaptics Guestmouse Off"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_LOCKED_DRAGS "Synaptics Locked Drags"
+
+/* 32 bit */
+#define SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT "Synaptics Locked Drags Timeout"
+
+/* 8 bit, up to MAX_TAP values (see synaptics.h), 0 disables an
+ * element. order: RT, RB, LT, LB, F1, F2, F3 */
+#define SYNAPTICS_PROP_TAP_ACTION "Synaptics Tap Action"
+
+/* 8 bit, up to MAX_CLICK values (see synaptics.h), 0 disables an
+ * element. order: Finger 1, 2, 3 */
+#define SYNAPTICS_PROP_CLICK_ACTION "Synaptics Click Action"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_CIRCULAR_SCROLLING "Synaptics Circular Scrolling"
+
+/* FLOAT */
+#define SYNAPTICS_PROP_CIRCULAR_SCROLLING_DIST "Synaptics Circular Scrolling Distance"
+
+/* 8 bit, valid values 0..8 (inclusive)
+ * order: any edge, top, top + right, right, right + bottom, bottom, bottom +
+ * left, left, left + top */
+#define SYNAPTICS_PROP_CIRCULAR_SCROLLING_TRIGGER "Synaptics Circular Scrolling Trigger"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_CIRCULAR_PAD "Synaptics Circular Pad"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_PALM_DETECT "Synaptics Palm Detection"
+
+/* 32 bit, 2 values, width, z */
+#define SYNAPTICS_PROP_PALM_DIMENSIONS "Synaptics Palm Dimensions"
+
+/* FLOAT, 2 values, speed, friction */
+#define SYNAPTICS_PROP_COASTING_SPEED "Synaptics Coasting Speed"
+
+/* CARD32, 2 values, min, max */
+#define SYNAPTICS_PROP_PRESSURE_MOTION "Synaptics Pressure Motion"
+
+/* FLOAT, 2 values, min, max */
+#define SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR "Synaptics Pressure Motion Factor"
+
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_GRAB "Synaptics Grab Event Device"
+
+/* 8 bit (BOOL), 1 value, tap-and-drag */
+#define SYNAPTICS_PROP_GESTURES "Synaptics Gestures"
+
+/* 8 bit (BOOL), 7 values (read-only), has_left, has_middle, has_right,
+ * has_double, has_triple, has_pressure, has_width */
+#define SYNAPTICS_PROP_CAPABILITIES "Synaptics Capabilities"
+
+/* 32 bit unsigned, 2 values, vertical, horizontal in units/millimeter */
+#define SYNAPTICS_PROP_RESOLUTION "Synaptics Pad Resolution"
+
+/* 32 bit, 4 values, left, right, top, bottom */
+#define SYNAPTICS_PROP_AREA "Synaptics Area"
+
+/* 32 bit, 4 values, left, right, top, bottom */
+#define SYNAPTICS_PROP_SOFTBUTTON_AREAS "Synaptics Soft Button Areas"
+
+/* 32 bit, 4 values, left, right, top, bottom */
+#define SYNAPTICS_PROP_SECONDARY_SOFTBUTTON_AREAS "Synaptics Secondary Soft Button Areas"
+
+/* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */
+#define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation"
+
+#endif /* _SYNAPTICS_PROPERTIES_H_ */
diff --git a/man/Makefile.am b/man/Makefile.am
index bf7ec17..24420eb 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,59 +1,47 @@
# $Id$
#
# 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.
-#
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
-drivermandir = $(DRIVER_MAN_DIR)
+synclientmandir = $(APP_MAN_DIR)
+synclientman_PRE = synclient.man
+synclientman_DATA = $(synclientman_PRE:man=@APP_MAN_SUFFIX@)
-driverman_PRE = @DRIVER_NAME@.man
+syndaemonmandir = $(APP_MAN_DIR)
+syndaemonman_PRE = syndaemon.man
+syndaemonman_DATA =$(syndaemonman_PRE:man=@APP_MAN_SUFFIX@)
+drivermandir = $(DRIVER_MAN_DIR)
+driverman_PRE = synaptics.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
+EXTRA_DIST = synaptics.man synclient.man syndaemon.man
-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'
+CLEANFILES = $(driverman_DATA) $(synclientman_DATA) $(syndaemonman_DATA)
SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
.man.$(DRIVER_MAN_SUFFIX):
- sed $(MAN_SUBSTS) < $< > $@
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
+.man.$(APP_MAN_SUFFIX):
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
diff --git a/man/synaptics.man b/man/synaptics.man
index 6e99bd0..4432f01 100644
--- a/man/synaptics.man
+++ b/man/synaptics.man
@@ -1,16 +1,24 @@
-.TH "synaptics" "5" "0.14.6" "" ""
-.SH "NAME"
-.LP
-synaptics - Synaptics touchpad driver for XOrg/XFree86.
-.SH "INTRODUCTION"
-.LP
-This is a driver for the Synaptics TouchPad for XOrg/XFree86 4.x.
-.
-A Synaptics touchpad by default operates in compatibility mode by
-emulating a standard mouse.
-.
-However, by using a dedicated driver, more advanced features of the
-touchpad becomes available, such as:
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH SYNAPTICS __drivermansuffix__ __vendorversion__
+.SH NAME
+synaptics \- touchpad input driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qInputDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qsynaptics\*q"
+.BI " Option \*qDevice\*q \*q" devpath \*q
+.BI " Option \*qPath\*q \*q" path \*q
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B synaptics
+is an __xservername__ input driver for touchpads.
+Even though touchpads can be handled by the normal evdev or mouse drivers,
+this driver allows more advanced features of the
+touchpad to become available. Some benefits would be:
.IP \(bu 4
Movement with adjustable, non-linear acceleration and speed.
.IP \(bu 4
@@ -19,7 +27,7 @@ Button events through short touching of the touchpad.
Double-Button events through double short touching of the touchpad.
.IP \(bu 4
Dragging through short touching and holding down the finger on the
-touchpad.
+touchpad (tap-and-drag gesture).
.IP \(bu 4
Middle and right button events on the upper and lower corner of the
touchpad.
@@ -37,264 +45,302 @@ and button six/seven events for horizontal scrolling.
.IP \(bu 4
Adjustable finger detection.
.IP \(bu 4
-Multifinger taps: two finger for middle button and three finger for
-right button events.
+Multifinger taps: two finger for right button and three finger for
+middle button events.
.
(Needs hardware support.
.
Not all models implement this feature.)
.IP \(bu 4
-Pressure dependent motion speed.
-.IP \(bu 4
-Run-time configuration using shared memory. This means you can change
-parameter settings without restarting the X server.
+Pressure-dependent motion speed.
.LP
Note that depending on the touchpad firmware, some of these features
might be available even without using the synaptics driver. Note also
that some functions are not available on all touchpad models, because
they need support from the touchpad hardware/firmware. (Multifinger
taps for example.)
-.SH "DESCRIPTION"
-.LP
-The driver behavior can be configured with parameters.
-.
-These parameters are options in the InputDevice section in the
-XOrg/XFree86 config file.
-.
-See the INSTALL file for a working example for a synaptics touchpad.
-.
-See the README.alps file for a working example for an ALPS touchpad.
-.
-If you have the SHMConfig parameter enabled, these parameters can also
-be changed at runtime with the synclient(1) program.
-.
-The following parameters are available:
-.TP
-\fBDevice\fR (String)
-Synaptics device.
-.TP
-\fBProtocol\fR (String)
+.PP
+The name "synaptics" is historical and the driver still provides the
+synaptics protocol parsing code. Under Linux however, the hardware-specifics
+are handled by the kernel and this driver will work for any touchpad that
+has a working kernel driver. If your device is recognized as \*qPS/2
+Mouse\*q or similar, the kernel driver does not support your device and this
+driver will only provide limited functionality.
+
+.SH CONFIGURATION OPTIONS
+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 \*qDevice\*q \*q" string \*q
+This option specifies the device file in your \*q/dev\*q directory which will
+be used to access the physical device. Normally you should use something like
+\*q/dev/input/eventX\*q, where X is some integer.
+.TP 7
+.BI "Option \*qProtocol\*q \*q" string \*q
+Specifies which kernel driver will be used by this driver. This is the list of
+supported drivers and their default use scenarios.
.TS
l l.
-auto-dev automatic, default
-psaux raw
-event linux 2.6 kernel events
+auto-dev automatic, default (recommend)
+event Linux 2.6 kernel events
+psaux raw device access (Linux 2.4)
psm FreeBSD psm driver
.TE
-.TP
-\fBSHMConfig\fR (Bool)
-Switch on/off shared memory for configuration.
-.TP
-\fBLeftEdge\fR (Integer)
-X coordinate for left edge.
-.TP
-\fBRightEdge\fR (Integer)
-X coordinate for right edge.
-.TP
-\fBTopEdge\fR (Integer)
-Y coordinate for top edge.
-.TP
-\fBBottomEdge\fR (Integer)
-Y coordinate for bottom edge.
-.TP
-\fBFingerLow\fR (Integer)
+.TP 7
+.BI "Option \*qLeftEdge\*q \*q" integer \*q
+X coordinate for left edge. Property: "Synaptics Edges"
+.TP 7
+.BI "Option \*qRightEdge\*q \*q" integer \*q
+X coordinate for right edge. Property: "Synaptics Edges"
+.TP 7
+.BI "Option \*qTopEdge\*q \*q" integer \*q
+Y coordinate for top edge. Property: "Synaptics Edges"
+.TP 7
+.BI "Option \*qBottomEdge\*q \*q" integer \*q
+Y coordinate for bottom edge. Property: "Synaptics Edges"
+.TP 7
+.BI "Option \*qFingerLow\*q \*q" integer \*q
When finger pressure drops below this value, the driver counts it as a
-release.
-.TP
-\fBFingerHigh\fR (Integer)
-When finger pressure goes above this value, the driver counts it as a
-touch.
-.TP
-\fBFingerPress\fR (Integer)
+release. Property: "Synaptics Finger"
+.TP 7
+.BI "Option \*qFingerHigh\*q \*q" integer \*q
When finger pressure goes above this value, the driver counts it as a
-press.
-.
-Currently a press is equivalent to putting the touchpad in trackstick
-emulation mode.
-.TP
-\fBMaxTapTime\fR (Integer)
-Maximum time (in milliseconds) for detecting a tap.
-.TP
-\fBMaxTapMove\fR (Integer)
-Maximum movement of the finger for detecting a tap.
-.TP
-\fBMaxDoubleTapTime\fR (Integer)
-Maximum time (in milliseconds) for detecting a double tap.
-.TP
-\fBClickTime\fR (Integer)
-The duration of the mouse click generated by tapping.
-.TP
-\fBFastTaps\fR (Bool)
-Makes the driver react faster to a single tap, but also makes double
-clicks caused by double tapping slower.
-.TP
-\fBVertEdgeScroll\fR (Bool)
-Enable vertical scrolling when dragging along the right edge.
-.TP
-\fBHorizEdgeScroll\fR (Bool)
-Enable horizontal scrolling when dragging along the bottom edge.
-.TP
-\fBCornerCoasting\fR (Bool)
+touch. Property: "Synaptics Finger"
+.TP 7
+.BI "Option \*qMaxTapTime\*q \*q" integer \*q
+Maximum time (in milliseconds) for detecting a tap. Property: "Synaptics Tap
+Durations"
+.TP 7
+.BI "Option \*qMaxTapMove\*q \*q" integer \*q
+Maximum movement of the finger for detecting a tap. Property: "Synaptics Tap
+Move"
+.TP 7
+.BI "Option \*qMaxDoubleTapTime\*q \*q" integer \*q
+Maximum time (in milliseconds) for detecting a double tap. Property:
+"Synaptics Tap Durations"
+.TP 7
+.BI "Option \*qClickTime\*q \*q" integer \*q
+The duration of the mouse click generated by tapping. Property: "Synaptics Tap
+Durations"
+.TP 7
+.BI "Option \*qClickPad\*q \*q" boolean \*q
+Whether the device is a click pad. See
+.B ClickPad support
+for more details. Property: "Synaptics ClickPad"
+.TP 7
+.BI "Option \*qVertEdgeScroll\*q \*q" boolean \*q
+Enable vertical scrolling when dragging along the right edge. Property:
+"Synaptics Edge Scrolling"
+.TP 7
+.BI "Option \*qHorizEdgeScroll\*q \*q" boolean \*q
+Enable horizontal scrolling when dragging along the bottom edge. Property:
+"Synaptics Edge Scrolling"
+.TP 7
+.BI "Option \*qCornerCoasting\*q \*q" boolean \*q
Enable edge scrolling to continue while the finger stays in an edge corner.
-.TP
-\fBVertTwoFingerScroll\fR (Bool)
+Property: "Synaptics Edge Scrolling"
+.TP 7
+.BI "Option \*qVertTwoFingerScroll\*q \*q" boolean \*q
Enable vertical scrolling when dragging with two fingers anywhere on
-the touchpad.
-.TP
-\fBHorizTwoFingerScroll\fR (Bool)
+the touchpad. Property: "Synaptics Two-Finger Scrolling"
+.TP 7
+.BI "Option \*qHorizTwoFingerScroll\*q \*q" boolean \*q
Enable horizontal scrolling when dragging with two fingers anywhere on
-the touchpad.
-.TP
-\fBVertScrollDelta\fR (Integer)
-Move distance of the finger for a scroll event.
-.TP
-\fBHorizScrollDelta\fR (Integer)
-Move distance of the finger for a scroll event.
-.TP
-\fBEdgeMotionMinZ\fR (Integer)
-Finger pressure at which minimum edge motion speed is set.
-.TP
-\fBEdgeMotionMaxZ\fR (Integer)
-Finger pressure at which maximum edge motion speed is set.
-.TP
-\fBEdgeMotionMinSpeed\fR (Integer)
-Slowest setting for edge motion speed.
-.TP
-\fBEdgeMotionMaxSpeed\fR (Integer)
-Fastest setting for edge motion speed.
-.TP
-\fBEdgeMotionUseAlways\fR (Bool)
-If on, edge motion is also used for normal movements.
-.
-If off, egde motion is used only when dragging.
-.TP
-\fBRepeater\fR (String)
-Repeater device.
-.TP
-\fBMinSpeed\fR (Float)
-Minimum speed factor.
-.TP
-\fBMaxSpeed\fR (Float)
-Maximum speed factor.
-.TP
-\fBAccelFactor\fR (Float)
-Acceleration factor for normal pointer movements.
-.TP
-\fBTrackstickSpeed\fR (Float)
-Speed scale when in trackstick emulation mode.
-.TP
-\fBPressureMotionMinZ\fR (Integer)
-Finger pressure at which minimum pressure motion factor is applied.
-.TP
-\fBPressureMotionMaxZ\fR (Integer)
-Finger pressure at which maximum pressure motion factor is applied.
-.TP
-\fBPressureMotionMinFactor\fR (Integer)
-Lowest setting for pressure motion factor.
-.TP
-\fBPressureMotionMaxFactor\fR (Integer)
-Greatest setting for pressure motion factor.
-.TP
-\fBUpDownScrolling\fR (Bool)
+the touchpad. Property: "Synaptics Two-Finger Scrolling"
+.TP 7
+.BI "Option \*qVertScrollDelta\*q \*q" integer \*q
+Move distance of the finger for a scroll event. Property: "Synaptics Scrolling
+Distance"
+.TP 7
+.BI "Option \*qHorizScrollDelta\*q \*q" integer \*q
+Move distance of the finger for a scroll event. Property: "Synaptics Scrolling
+Distance"
+.TP
+.BI "Option \*qMinSpeed\*q \*q" float \*q
+Minimum speed factor. Property: "Synaptics Move Speed"
+.TP
+.BI "Option \*qMaxSpeed\*q \*q" float \*q
+Maximum speed factor. Property: "Synaptics Move Speed"
+.TP
+.BI "Option \*qAccelFactor\*q \*q" float \*q
+Acceleration factor for normal pointer movements. Property: "Synaptics Move
+Speed"
+.TP
+.BI "Option \*qPressureMotionMinZ\*q \*q" integer \*q
+Finger pressure at which minimum pressure motion factor is applied. Property:
+"Synaptics Pressure Motion"
+.TP
+.BI "Option \*qPressureMotionMaxZ\*q \*q" integer \*q
+Finger pressure at which maximum pressure motion factor is applied. Property:
+"Synaptics Pressure Motion"
+.TP
+.BI "Option \*qPressureMotionMinFactor\*q \*q" integer \*q
+Lowest setting for pressure motion factor. Property: "Synaptics Pressure
+Motion Factor"
+.TP
+.BI "Option \*qPressureMotionMaxFactor\*q \*q" integer \*q
+Greatest setting for pressure motion factor. Property: "Synaptics Pressure
+Motion Factor"
+.TP
+.BI "Option \*qHorizHysteresis\*q \*q" integer \*q
+The minimum horizontal HW distance required to generate motion events. Can be
+specified as a percentage. Increase if noise motion is a problem for you. Zero
+is disabled.
+Default: 0.5 percent of the diagonal or (in case of evdev) the appropriate
+"fuzz" as advertised by the device.
+.TP
+.BI "Option \*qVertHysteresis\*q \*q" integer \*q
+The minimum vertical HW distance required to generate motion events. See
+\fBHorizHysteresis\fR.
+.TP
+.BI "Option \*qUpDownScrolling\*q \*q" boolean \*q
If on, the up/down buttons generate button 4/5 events.
.
If off, the up button generates a double click and the down button
-generates a button 2 event.
+generates a button 2 event. This option is only available for touchpads with
+physical scroll buttons.
+Property: "Synaptics Button Scrolling"
.TP
-\fBLeftRightScrolling\fR (Bool)
+.BI "Option \*qLeftRightScrolling\*q \*q" boolean \*q
If on, the left/right buttons generate button 6/7 events.
.
If off, the left/right buttons both generate button 2 events.
+This option is only available for touchpads with physical scroll buttons.
+Property: "Synaptics Button Scrolling"
.TP
-\fBUpDownScrollRepeat\fR (Bool)
+.BI "Option \*qUpDownScrollRepeat\*q \*q" boolean \*q
If on, and the up/down buttons are used for scrolling
(\fBUpDownScrolling\fR), these buttons will send auto-repeating 4/5 events,
with the delay between repeats determined by \fBScrollButtonRepeat\fR.
+This option is only available for touchpads with physical scroll buttons.
+Property: "Synaptics Button Scrolling Repeat"
.TP
-\fBLeftRightScrollRepeat\fR (Bool)
+.BI "Option \*qLeftRightScrollRepeat\*q \*q" boolean \*q
If on, and the left/right buttons are used for scrolling
(\fBLeftRightScrolling\fR), these buttons will send auto-repeating 6/7 events,
with the delay between repeats determined by \fBScrollButtonRepeat\fR.
+This option is only available for touchpads with physical scroll buttons.
+Property: "Synaptics Button Scrolling Repeat"
.TP
-\fBScrollButtonRepeat\fR (Integer)
+.BI "Option \*qScrollButtonRepeat\*q \*q" integer \*q
The number of milliseconds between repeats of button events 4-7 from the
up/down/left/right scroll buttons.
-.TP
-\fBEmulateMidButtonTime\fR (Integer)
-Maximum time (in milliseconds) for middle button emulation.
-.TP
-\fBEmulateTwoFingerMinZ\fR (Integer)
-For touchpads not capable of detecting multiple fingers (Alps), this sets the
-Z pressure threshold to emulate a two finger press.
-.TP
-\fBTouchpadOff\fR (Integer)
+This option is only available for touchpads with physical scroll buttons.
+Property: "Synaptics Button Scrolling Time"
+.TP
+.BI "Option \*qEmulateMidButtonTime\*q \*q" integer \*q
+Maximum time (in milliseconds) for middle button emulation. Property:
+"Synaptics Middle Button Timeout"
+.TP
+.BI "Option \*qEmulateTwoFingerMinZ\*q \*q" integer \*q
+For touchpads not capable of detecting multiple fingers but are capable
+of detecting finger pressure and width, this sets the
+Z pressure threshold. When both Z pressure and W width thresholds
+are crossed, a two finger press will be emulated. This defaults
+to a value that disables emulation on touchpads with real two-finger detection
+and defaults to a value that enables emulation on remaining touchpads that
+support pressure and width support.
+Property: "Synaptics Two-Finger Pressure"
+.TP
+.BI "Option \*qEmulateTwoFingerMinW\*q \*q" integer \*q
+For touchpads not capable of detecting multiple fingers but are
+capable of detecting finger width and pressure, this sets the
+W width threshold. When both W width and Z pressure thresholds
+are crossed, a two finger press will be emulated. This feature works best
+with (\fBPalmDetect\fR) off. Property: "Synaptics Two-Finger Width"
+.TP
+.BI "Option \*qTouchpadOff\*q \*q" integer \*q
Switch off the touchpad.
.
Valid values are:
.TS
l l.
0 Touchpad is enabled
-1 Touchpad is switched off
+1 Touchpad is switched off (physical clicks still work)
2 Only tapping and scrolling is switched off
.TE
+When the touchpad is switched off, button events caused by a physical
+button press are still interpreted. On a ClickPad, this includes
+software-emulated middle and right buttons as defined by
+the SoftButtonAreas setting.
.TP
-\fBGuestMouseOff\fR (Bool)
-Switch on/off guest mouse (often a stick).
+Property: "Synaptics Off"
.TP
-\fBLockedDrags\fR (Bool)
-If off, a tap and drag gesture ends when you release the finger.
+.BI "Option \*qLockedDrags\*q \*q" boolean \*q
+If off, a tap-and-drag gesture ends when you release the finger.
.
If on, the gesture is active until you tap a second time, or until
-LockedDragTimeout expires.
+LockedDragTimeout expires. Property: "Synaptics Locked Drags"
.TP
-\fBLockedDragTimeout\fR (Integer)
+.BI "Option \*qLockedDragTimeout\*q \*q" integer \*q
This parameter specifies how long it takes (in milliseconds) for the
LockedDrags mode to be automatically turned off after the finger is
-released from the touchpad.
+released from the touchpad. Property: "Synaptics Locked Drags Timeout"
.TP
-\fBRTCornerButton\fR (Integer)
+.BI "Option \*qRTCornerButton\*q \*q" integer \*q
.
Which mouse button is reported on a right top corner tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
.TP
-\fBRBCornerButton\fR (Integer)
+.BI "Option \*qRBCornerButton\*q \*q" integer \*q
Which mouse button is reported on a right bottom corner tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
.TP
-\fBLTCornerButton\fR (Integer)
+.BI "Option \*qLTCornerButton\*q \*q" integer \*q
Which mouse button is reported on a left top corner tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
.TP
-\fBLBCornerButton\fR (Integer)
+.BI "Option \*qLBCornerButton\*q \*q" integer \*q
Which mouse button is reported on a left bottom corner tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
.TP
-\fBTapButton1\fR (Integer)
+.BI "Option \*qTapButton1\*q \*q" integer \*q
Which mouse button is reported on a non-corner one-finger tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
.TP
-\fBTapButton2\fR (Integer)
+.BI "Option \*qTapButton2\*q \*q" integer \*q
Which mouse button is reported on a non-corner two-finger tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
.TP
-\fBTapButton3\fR (Integer)
+.BI "Option \*qTapButton3\*q \*q" integer \*q
Which mouse button is reported on a non-corner three-finger tap.
.
-Set to 0 to disable.
+Set to 0 to disable. Property: "Synaptics Tap Action"
+.TP
+.BI "Option \*qClickFinger1\*q \*q" integer \*q
+Which mouse button is reported when left-clicking with one finger.
+.
+Set to 0 to disable. Property: "Synaptics Click Action"
+.TP
+.BI "Option \*qClickFinger2\*q \*q" integer \*q
+Which mouse button is reported when left-clicking with two fingers.
+.
+Set to 0 to disable. Property: "Synaptics Click Action"
.TP
-\fBCircularScrolling\fR (Bool)
-If on, circular scrolling is used.
+.BI "Option \*qClickFinger3\*q \*q" integer \*q
+Which mouse button is reported when left-clicking with three fingers.
+.
+Set to 0 to disable. Property: "Synaptics Click Action"
+.TP
+.BI "Option \*qCircularScrolling\*q \*q" boolean \*q
+If on, circular scrolling is used. Property: "Synaptics Circular Scrolling"
.TP
-\fBCircScrollDelta\fR (Float)
-Move angle (radians) of finger to generate a scroll event.
+.BI "Option \*qCircScrollDelta\*q \*q" float \*q
+Move angle (radians) of finger to generate a scroll event. Property: "Synaptics
+Circular Scrolling Distance"
.TP
-\fBCircScrollTrigger\fR (Integer)
+.BI "Option \*qCircScrollTrigger\*q \*q" integer \*q
Trigger region on the touchpad to start circular scrolling
.TS
l l.
@@ -308,35 +354,46 @@ l l.
7 Left Edge
8 Top Left Corner
.TE
+Property: "Synaptics Circular Scrolling Trigger"
.TP
-\fBCircularPad\fR (Bool)
+.BI "Option \*qCircularPad\*q \*q" boolean \*q
.
Instead of being a rectangle, the edge is the ellipse enclosed by the
Left/Right/Top/BottomEdge parameters.
.
-For circular touchpads.
+For circular touchpads. Property: "Synaptics Circular Pad"
.TP
-\fBPalmDetect\fR (Bool)
+.BI "Option \*qPalmDetect\*q \*q" boolean \*q
If palm detection should be enabled.
.
Note that this also requires hardware/firmware support from the
-touchpad.
+touchpad. Property: "Synaptics Palm Detection"
.TP
-\fBPalmMinWidth\fR (Integer)
-Minimum finger width at which touch is considered a palm.
+.BI "Option \*qPalmMinWidth\*q \*q" integer \*q
+Minimum finger width at which touch is considered a palm. Property: "Synaptics
+Palm Dimensions"
.TP
-\fBPalmMinZ\fR (Integer)
-Minimum finger pressure at which touch is considered a palm.
+.BI "Option \*qPalmMinZ\*q \*q" integer \*q
+Minimum finger pressure at which touch is considered a palm. Property:
+"Synaptics Palm Dimensions"
.TP
-\fBCoastingSpeed\fR (Float)
-Coasting threshold scrolling speed.
+.BI "Option \*qCoastingSpeed\*q \*q" float \*q
+Your finger needs to produce this many scrolls per second in order to start
+coasting. The default is 20 which should prevent you from starting coasting
+unintentionally.
.
-0 disables coasting.
+0 disables coasting. Property: "Synaptics Coasting Speed"
.TP
-\fBSingleTapTimeout\fR (Integer)
-Timeout after a tap to recognize it as a single tap.
+.BI "Option \*qCoastingFriction\*q \*q" float \*q
+Number of scrolls/second² to decrease the coasting speed. Default
+is 50.
+Property: "Synaptics Coasting Speed"
.TP
-\fBGrabEventDevice\fR (Bool)
+.BI "Option \*qSingleTapTimeout\*q \*q" integer \*q
+Timeout after a tap to recognize it as a single tap. Property: "Synaptics Tap
+Durations"
+.TP
+.BI "Option \*qGrabEventDevice\*q \*q" boolean \*q
If GrabEventDevice is true, the driver will grab the event device for
exclusive use when using the linux 2.6 event protocol.
.
@@ -351,13 +408,119 @@ from user space.
.
When changing this parameter with the synclient program, the change
will not take effect until the synaptics driver is disabled and
-reenabled.
+re-enabled.
.
This can be achieved by switching to a text console and then switching
back to X.
.
.
-.LP
+.TP
+.BI "Option \*qTapAndDragGesture\*q \*q" boolean \*q
+Switch on/off the tap-and-drag gesture.
+.
+This gesture is an alternative way of dragging.
+.
+It is performed by tapping (touching and releasing the finger), then
+touching again and moving the finger on the touchpad.
+.
+The gesture is enabled by default and can be disabled by setting the
+TapAndDragGesture option to false. Property: "Synaptics Gestures"
+.
+.TP
+.BI "Option \*qVertResolution\*q \*q" integer \*q
+Resolution of X coordinates in units/millimeter. The value is used
+together with HorizResolution to compensate unequal vertical and
+horizontal sensitivity. Setting VertResolution and HorizResolution
+equal values means no compensation. Default value is read from
+the touchpad or set to 1 if value could not be read.
+Property: "Synaptics Pad Resolution"
+.
+.TP
+.BI "Option \*qHorizResolution\*q \*q" integer \*q
+Resolution of Y coordinates in units/millimeter. The value is used
+together with VertResolution to compensate unequal vertical and
+horizontal sensitivity. Setting VertResolution and HorizResolution
+equal values means no compensation. Default value is read from
+the touchpad or set to 1 if value could not be read.
+Property: "Synaptics Pad Resolution"
+.
+.TP
+.BI "Option \*qAreaLeftEdge\*q \*q" integer \*q
+Ignore movements, scrolling and tapping which start left of this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaLeftEdge option to any integer value other than zero. If supported by the
+server (version 1.9 and later), the edge may be specified in percent of
+the total width of the touchpad. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qAreaRightEdge\*q \*q" integer \*q
+Ignore movements, scrolling and tapping which start right of this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaRightEdge option to any integer value other than zero. If supported by the
+server (version 1.9 and later), the edge may be specified in percent of
+the total width of the touchpad. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qAreaTopEdge\*q \*q" integer \*q
+Ignore movements, scrolling and tapping which start above this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaTopEdge option to any integer value other than zero. If supported by the
+server (version 1.9 and later), the edge may be specified in percent of
+the total height of the touchpad. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qAreaBottomEdge\*q \*q" integer \*q
+Ignore movements, scrolling and tapping which start below this edge.
+.
+The option is disabled by default and can be enabled by setting the
+AreaBottomEdge option to any integer value other than zero. If supported by the
+server (version 1.9 and later), the edge may be specified in percent of
+the total height of the touchpad. Property: "Synaptics Area"
+.
+.TP
+.BI "Option \*qSoftButtonAreas\*q \*q" "RBL RBR RBT RBB MBL MBR MBT MBB" \*q
+This option is only available on ClickPad devices.
+Enable soft button click area support on ClickPad devices.
+The first four parameters are the left, right, top, bottom edge of the right
+button, respectively, the second four parameters are the left, right, top,
+bottom edge of the middle button, respectively. Any of the values may be
+given as percentage of the touchpad width or height, whichever applies.
+If any edge is set to 0 (not 0%), the button is assumed to extend to
+infinity in the given direction. Setting all values to 0 (not 0%) disables
+soft button areas. Button areas may not overlap, however it is permitted for two
+buttons to share an edge value.
+Property: "Synaptics Soft Button Areas"
+.
+.TP
+.BI "Option \*qHasSecondarySoftButtons\*q \*q" boolean \*q
+This option is only available on ClickPad devices.
+Enable the secondary software button area support. The exact area must be
+set in option \*qSecondarySoftButtonAreas\*q. See
+.B ClickPad support
+for more details.
+.
+.TP
+.BI "Option \*qSecondarySoftButtonAreas\*q \*q" "RBL RBR RBT RBB MBL MBR MBT MBB" \*q
+This option is only available on ClickPad devices and only if
+.B Option \*qHasSecondarySoftButtons\*q
+is enabled.
+Define the secondary soft button click areas on ClickPad devices (usually on
+top of the device).
+For the allowed values for this option, see
+.B Option \*qSoftButtonAreas\*q.
+Primary and secondary soft button areas must not overlap each other. If they do,
+the behavior of the driver is undefined.
+Property: "Synaptics Secondary Soft Button Areas". This property is only
+initialized if
+.B Option \*qHasSecondarySoftButtons\*q
+is enabled and this option is set in the __xconfigfile__(__filemansuffix__).
+.
+
+.SH CONFIGURATION DETAILS
+.SS Area handling
The LeftEdge, RightEdge, TopEdge and BottomEdge parameters are used to
define the edge and corner areas of the touchpad.
.
@@ -391,12 +554,18 @@ Physical left edge Physical right edge
Coordinates to the left of LeftEdge are part of the left edge (areas
1, 4 and 7), coordinates to the left of LeftEdge and above TopEdge
(area 1) are part of the upper left corner, etc.
-.
-A good way to find appropriate edge parameters is to enable the
-SHMConfig option and run "synclient -m 1" to see the x/y coordinates
-corresponding to different positions on the touchpad.
-.
-.LP
+.PP
+A good way to find appropriate edge parameters is to use evtest(1) on the
+device to see the x/y coordinates corresponding to different positions on
+the touchpad.
+.PP
+The perceived physical edges may be adjusted with the AreaLeftEdge,
+AreaRightEdge, AreaTopEdge, and AreaBottomEdge options. If these values are
+set to something other than the physical edges, input that starts in the
+space between the area edge and the respective physical edge is ignored.
+Note that this reduces the available space on the touchpad to start motions
+in.
+.SS Tapping
A tap event happens when the finger is touched and released in a time
interval shorter than MaxTapTime, and the touch and release
coordinates are less than MaxTapMove units apart.
@@ -422,9 +591,7 @@ A too long value can cause undesirable autorepeat in scroll bars and a
too small value means that visual feedback from the gui application
you are interacting with is harder to see.
.
-For this parameter to have any effect, "FastTaps" has to be disabled.
-.
-.LP
+.SS Acceleration
The MinSpeed, MaxSpeed and AccelFactor parameters control the pointer
motion speed.
.
@@ -447,32 +614,17 @@ effect on scrolling speed.
Scrolling speed is determined solely from the VertScrollDelta and
HorizScrollDelta parameters.
.
-To disable vertical or horizontal scrolling, set VertScrollDelta or
-HorizScrollDelta to zero.
-.
-.LP
-When hitting an egde, movement can be automatically continued.
-.
-If EdgeMotionUseAlways is false, edge motion is only used when
-dragging.
-.
-With EdgeMotionUseAlways set to true, it is also used for normal
-cursor movements.
-.
-.LP
-Edge motion speed is calculated by taking into account the amount of
-pressure applied to the touchpad.
-.
-The sensitivity can be adjusted using the EdgeMotion parameters.
-.
-If the pressure is below EdgeMotionMinZ, EdgeMotionMinSpeed is used,
-and if the pressure is greater than EdgeMotionMaxZ, EdgeMotionMaxSpeed
-is used.
-.
-For a pressure value between EdgeMotionMinZ and EdgeMotionMaxZ, the
-speed is increased linearly.
+To invert the direction of vertical or horizontal scrolling, set
+VertScrollDelta or HorizScrollDelta to a negative value.
.
.LP
+Acceleration is mostly handled outside the driver, thus the driver will
+translate MinSpeed into constant deceleration and adapt MaxSpeed at
+startup time. This ensures you can user the other acceleration profiles, albeit
+without pressure motion. However the numbers at runtime will likely be different
+from any options you may have set.
+
+.SS Pressure motion
When pressure motion is activated, the cursor motion speed depends
on the pressure exerted on the touchpad (the more pressure exerted on
the touchpad, the faster the pointer).
@@ -481,6 +633,7 @@ More precisely the speed is first calculated according to MinSpeed,
MaxSpeed and AccelFactor, and then is multiplied by a sensitivity
factor.
.
+.LP
The sensitivity factor can be adjusted using the PressureMotion
parameters.
.
@@ -488,13 +641,10 @@ If the pressure is below PressureMotionMinZ, PressureMotionMinFactor
is used, and if the pressure is greater than PressureMotionMaxZ,
PressureMotionMaxFactor is used.
.
-By default, PressureMotionMinZ and PressureMotionMaxZ are equal to
-EdgeMotionMinZ and EdgeMotionMaxZ.
-.
For a pressure value between PressureMotionMinZ and
PressureMotionMaxZ, the factor is increased linearly.
.
-.LP
+.SS Middle button emulation
Since most synaptics touchpad models don't have a button that
corresponds to the middle button on a mouse, the driver can emulate
middle mouse button events.
@@ -503,7 +653,7 @@ If you press both the left and right mouse buttons at almost the same
time (no more than EmulateMidButtonTime milliseconds apart) the driver
generates a middle mouse button event.
.
-.LP
+.SS Circular scrolling
Circular scrolling acts like a scrolling wheel on the touchpad.
.
Scrolling is engaged when a drag starts in the given CircScrollTrigger
@@ -522,8 +672,8 @@ large circles for better control.
When used together with vertical scrolling, hitting the upper or lower
right corner will seamlessly switch over from vertical to circular
scrolling.
-.
-.LP
+
+.SS Coasting
Coasting is enabled by setting the CoastingSpeed parameter to a
non-zero value.
.
@@ -559,29 +709,277 @@ CornerCoasting takes precedence over the seamless switch from edge
scrolling to circular scrolling. That is, if CornerCoasting is
active, scrolling will stop, and circular scrolling will not start,
when the finger leaves the corner.
-.
+
+.SS Noise cancellation
+The synaptics has a built-in noise cancellation based on hysteresis. This means
+that incoming coordinates actually shift a box of predefined dimensions such
+that it covers the incoming coordinate, and only the boxes own center is used
+as input. Obviously, the smaller the box the better, but the likelihood of
+noise motion coming through also increases.
+
+.SS ClickPad support
+A click pad device has button(s) integrated into the touchpad surface. The
+user must press downward on the touchpad in order to generated a button
+press. ClickPad support is enabled if the option
+.B ClickPad
+is set or the property is set at runtime. On some platforms, this option
+will be set automatically if the kernel detects a matching device. On Linux,
+the device must have the INPUT_PROP_BUTTONPAD property set.
.LP
-Trackstick emulation mode is entered when pressing the finger hard on
-the touchpad.
-.
-The FingerPress parameter controls the minimum required finger
-pressure.
-.
-If the finger hasn't moved more than MaxTapMove after MaxTapTime has
-elapsed, trackstick mode is entered.
-.
-In this mode, moving the finger slightly in any direction gives a
-speed vector that moves the pointer.
-.
-The TrackstickSpeed parameter controls the ratio between pointer speed
-and finger movement distance.
-.
-Trackstick mode is exited when the finger pressure drops below
-FingerLow or when the finger is moved further than MaxTapMove away
-from the initial position.
+ClickPads do not support middle mouse button emulation. If enabling ClickPad
+support at runime, the user must also set the middle mouse button timeout to
+0. If auto-detected, middle mouse button emulation is disabled by the
+driver.
+.LP
+ClickPads provide software emulated buttons through
+.B Option \*qSoftButtonAreas\*q.
+These buttons enable areas on the touchpad to perform as right or middle
+mouse button. When the user performs a click within a defined soft button
+area, a right or middle click is performed.
+.LP
+Some laptops, most notably the Lenovo T440, T540 and x240 series, provide a
+pointing stick without physical buttons. On those laptops, the top of the
+touchpad acts as software-emulated button area. This area can be enabled
+with
+.B Option \*qHasSecondarySoftButtons\*q
+and configured
+with
+.B Option \*qSecondarySoftButtonAreas\*q.
+On some platforms, this option
+will be set automatically if the kernel detects a matching device. On Linux,
+the device must have the INPUT_PROP_TOPBUTTONPAD property set.
+
+.SH "DEVICE PROPERTIES"
+Synaptics 1.0 and higher support input device properties if the driver is
+running on X server 1.6 or higher. The synclient tool
+shipped with synaptics version 1.1 uses input device properties by default.
+.
+Properties supported:
+.TP 7
+.BI "Synaptics Edges"
+32 bit, 4 values, left, right, top, bottom.
+
+.TP 7
+.BI "Synaptics Finger"
+32 bit, 3 values, low, high, press.
+
+.TP 7
+.BI "Synaptics Tap Time"
+32 bit.
+
+.TP 7
+.BI "Synaptics Tap Move"
+32 bit.
+
+.TP 7
+.BI "Synaptics Tap Durations"
+32 bit, 3 values, single touch timeout, max tapping time for double taps,
+duration of a single click.
+
+.TP 7
+.BI "Synaptics ClickPad"
+8 bit (Bool).
+
+.TP 7
+.BI "Synaptics Middle Button Timeout"
+32 bit.
+
+.TP 7
+.BI "Synaptics Two-Finger Pressure"
+32 bit.
+
+.TP 7
+.BI "Synaptics Two-Finger Width"
+32 bit.
+
+.TP 7
+.BI "Synaptics Scrolling Distance"
+32 bit, 2 values, vert, horiz.
+
+.TP 7
+.BI "Synaptics Edge Scrolling"
+8 bit (BOOL), 3 values, vertical, horizontal, corner.
+
+.TP 7
+.BI "Synaptics Two-Finger Scrolling"
+8 bit (BOOL), 2 values, vertical, horizontal.
+
+.TP 7
+.BI "Synaptics Move Speed"
+FLOAT, 4 values, min, max, accel, <deprecated>
+
+.TP 7
+.BI "Synaptics Button Scrolling"
+8 bit (BOOL), 2 values, updown, leftright.
+
+.TP 7
+.BI "Synaptics Button Scrolling Repeat"
+8 bit (BOOL), 2 values, updown, leftright.
+
+.TP 7
+.BI "Synaptics Button Scrolling Time"
+32 bit.
+
+.TP 7
+.BI "Synaptics Off"
+8 bit, valid values (0, 1, 2).
+
+.TP 7
+.BI "Synaptics Locked Drags"
+8 bit (BOOL).
+
+.TP 7
+.BI "Synaptics Locked Drags Timeout"
+32 bit.
+
+.TP 7
+.BI "Synaptics Tap Action"
+8 bit, up to MAX_TAP values (see synaptics.h), 0 disables an element. order:
+RT, RB, LT, LB, F1, F2, F3.
+
+.TP 7
+.BI "Synaptics Click Action"
+8 bit, up to MAX_CLICK values (see synaptics.h), 0 disables an element.
+order: Finger 1, 2, 3.
+
+.TP 7
+.BI "Synaptics Circular Scrolling"
+8 bit (BOOL).
+
+.TP 7
+.BI "Synaptics Circular Scrolling Distance"
+FLOAT.
+
+.TP 7
+.BI "Synaptics Circular Scrolling Trigger"
+8 bit, valid values 0..8 (inclusive) order: any edge, top, top + right,
+right, right + bottom, bottom, bottom + left, left, left + top.
+
+.TP 7
+.BI "Synaptics Circular Pad"
+8 bit (BOOL).
+
+.TP 7
+.BI "Synaptics Palm Detection"
+8 bit (BOOL).
+
+.TP 7
+.BI "Synaptics Palm Dimensions"
+32 bit, 2 values, width, z.
+
+.TP 7
+.BI "Synaptics Coasting Speed"
+FLOAT, 2 values, speed, friction.
+
+.TP 7
+.BI "Synaptics Pressure Motion"
+32 bit, 2 values, min, max.
+
+.TP 7
+.BI "Synaptics Pressure Motion Factor"
+FLOAT, 2 values, min, max.
+
+.TP 7
+.BI "Synaptics Grab Event Device"
+8 bit (BOOL).
+
+.TP 7
+.BI "Synaptics Gestures"
+8 bit (BOOL), 1 value, tap-and-drag.
+
+.TP 7
+.BI "Synaptics Area"
+The AreaLeftEdge, AreaRightEdge, AreaTopEdge and AreaBottomEdge parameters are used to
+define the edges of the active area of the touchpad. All movements, scrolling and tapping
+which take place outside of this area will be ignored. This property is disabled by
+default.
+
+32 bit, 4 values, left, right, top, bottom. 0 disables an element.
+
+.TP 7
+.BI "Synaptics Soft Button Areas"
+This property is only available on ClickPad devices.
+The Right and middle soft button areas are used to support right and middle
+click actions on a ClickPad device. Providing 0 for all values of a given button
+disables the button area.
+
+32 bit, 8 values, RBL, RBR, RBT, RBB, MBL, MBR, MBT, MBB.
+
+.TP 7
+.BI "Synaptics Capabilities"
+This read-only property expresses the physical capability of the touchpad,
+most notably whether the touchpad hardware supports multi-finger tapping and
+scrolling.
+
+8 bit (BOOL), 7 values (read-only), has left button, has middle button, has
+right button, two-finger detection, three-finger detection, pressure detection, and finger/palm width detection.
+
+.TP 7
+.BI "Synaptics Pad Resolution"
+32 bit unsigned, 2 values (read-only), vertical, horizontal in units/millimeter.
+
+.SH "NOTES"
+Configuration through
+.I InputClass
+sections is recommended in X servers 1.8 and later. See xorg.conf.d(5) for
+more details. An example xorg.conf.d snippet is provided in
+.I ${sourcecode}/conf/70-synaptics.conf
+.LP
+Configuration through hal fdi files is recommended in X servers 1.5, 1.6 and
+1.7. An example hal policy file is provided in
+.I ${sourcecode}/conf/11-x11-synaptics.fdi
+.LP
+If either of
+.BI "Protocol \*q" auto-dev \*q
+(default) or
+.BI "Protocol \*q" event \*q
+is used, the driver initializes defaults based on the capabilities reported by
+the kernel driver. Acceleration, edges and resolution are based on the dimensions
+reported by the kernel. If the kernel reports multi-finger detection, two-finger
+vertical scrolling is enabled, horizontal two-finger scrolling is disabled and
+edge scrolling is disabled. If no multi-finger capabilities are reported,
+edge scrolling is enabled for both horizontal and vertical scrolling.
+Tapping is disabled by default for touchpads with one or more physical buttons.
+To enable it you need to map tap actions to buttons. See the "TapButton1",
+"TapButton2" and "TapButton3" options.
+.LP
+Button mapping for physical buttons is handled in the server.
+If the device is switched to left-handed (an in-server mapping of physical
+buttons 1, 2, 3 to the logical buttons 3, 2, 1, respectively), both physical
+and TapButtons are affected. To counteract this, the TapButtons need to be set
+up in reverse order (TapButton1=3, TapButton2=1).
+
+.SH "REMOVED OPTIONS"
+The following options are no longer part of the driver configuration:
+.TP
+.BI "Option \*qRepeater\*q \*q" string \*q
+.TP
+.BI "Option \*qHistorySize\*q \*q" integer \*q
+.TP
+.BI "Option \*qSpecialScrollAreaRight\*q \*q" boolean \*q
+.TP
+.BI "Option \*qGuestMouseOff\*q \*q" boolean \*q
+.TP
+.BI "Option \*qSHMConfig\*q \*q" boolean \*q
+.TP
+.BI "Option \*qFingerPress\*q \*q" integer \*q
+.TP
+.BI "Option \*qTrackstickSpeed\*q \*q" float \*q
+.TP
+.BI "Option \*qEdgeMotionMinZ\*q \*q" integer \*q
+.TP
+.BI "Option \*qEdgeMotionMaxZ\*q \*q" integer \*q
+.TP
+.BI "Option \*qEdgeMotionMinSpeed\*q \*q" integer \*q
+.TP
+.BI "Option \*qEdgeMotionMaxSpeed\*q \*q" integer \*q
+.TP
+.BI "Option \*qEdgeMotionUseAlways\*q \*q" boolean \*q
+.TP
+
.SH "AUTHORS"
.LP
Peter Osterlund <petero2@telia.com> and many others.
.SH "SEE ALSO"
.LP
-synclient(1), syndaemon(1)
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), synclient(__appmansuffix__), syndaemon(__appmansuffix__)
diff --git a/man/synclient.1 b/man/synclient.1
deleted file mode 100644
index 1159733..0000000
--- a/man/synclient.1
+++ /dev/null
@@ -1,135 +0,0 @@
-.TH "synclient" "1" "0.14.6" "" ""
-.SH "NAME"
-.LP
-synclient \- query and modify Synaptics TouchPad driver for
-XOrg/XFree86 server parameters on the fly.
-.SH "SYNTAX"
-.LP
-synclient [\fI\-m interval\fP]
-.br
-synclient [\fI\-hlV?\fP] [var1=value1 [var2=value2] ...]
-.SH "DESCRIPTION"
-.LP
-This program lets you change your Synaptics TouchPad driver for
-XOrg/XFree86 server parameters while X is running if you enabled
-SHMConfig "on" in your XOrg/XFree86 configuration.
-.TP
-WARNING: This is not secure if you are in an untrusted multiuser
-environment.
-.
-All local users can change the parameters at any time.
-.SH "OPTIONS"
-.LP
-.TP
-\fB\-m interval\fR
-monitor changes to the touchpad state.
-.
-Interval specifies how often (in ms) to poll the touchpad state.
-.
-Whenever a change in the touchpad state is detected, one line of
-output is generated that describes the current state of the touchpad.
-.
-The following data is included in the output.
-.RS
-.TP
-\fBtime\fR
-Time in seconds since the logging was started.
-.TP
-\fBx,y\fR
-The x/y coordinates of the finger on the touchpad.
-.
-The origin is in the upper left corner.
-.TP
-\fBz\fR
-The "pressure" value.
-.
-Pressing the finger harder on the touchpad typically produces a larger
-value.
-.
-Note that most touchpads don't measure the real pressure though.
-.
-Instead, capacitance is usually measured, which is correlated to the
-contact area between the finger and the touchpad.
-.
-Since more pressure usually means a larger contact area, the reported
-pressure value is at least indirectly related to the real pressure.
-.TP
-\fBf\fR
-The number of fingers currently touching the touchpad.
-.
-Note that only some touchpads can report more than one finger.
-.
-Generally, synaptics touchpads can, but ALPS touchpads can't.
-.TP
-\fBw\fR
-The w value is a measurement of the finger width.
-.
-This is only supported by some synaptics touchpads.
-.
-Touchpads that can't measure the finger width typically report a faked
-constant value when a finger is touching the touchpad.
-.TP
-\fBl,r,u,d,m,multi\fR
-The state of the left, right, up, down, middle and multi buttons.
-.
-Zero means not pressed, one means pressed.
-.
-Not all touchpads have all these buttons.
-.
-If a button doesn't exist, the value is always reported as 0.
-.TP
-\fBgl,gm,gr\fR
-Some touchpads have a "guest device".
-.
-This is typically a pointing stick located in the middle of the
-keyboard.
-.
-Some guest devices have physical buttons, or can detect button presses
-when tapping on the pointing stick.
-.
-Such button events are reported as "guest left", "guest middle" or
-"guest right".
-.TP
-\fBgdx,gdy\fR
-Pointer movements from the guest device are reported as relative x/y
-positions, called gdx and gdy.
-.RE
-.TP
-\fB\-h\fR
-Show detected hardware properties.
-.TP
-\fB\-l\fR
-List current user settings.
-.TP
-\fB\-V\fR
-Print version number and exit.
-.TP
-\fB\-?\fR
-Show the help message.
-.TP
-\fBvar=value\fR
-Set user parameter \fIvar\fR to \fIvalue\fR.
-
-
-.SH "FILES"
-.LP
-\fI/etc/X11/xorg.conf\fP
-.LP
-\fI/etc/X11/XF86Config\-4\fP
-.SH "EXAMPLES"
-.LP
-To disable EdgeMotionSpeed:
-.LP
-synclient EdgeMotionSpeed=0
-.LP
-To monitor touchpad events:
-.LP
-synclient \-m 100
-.SH "AUTHORS"
-.LP
-Peter Osterlund <petero2@telia.com> and many others.
-.TP
-This man page was written by Mattia Dongili <malattia@debian.org>
-.SH "SEE ALSO"
-.LP
-syndaemon(1), synaptics(5)
diff --git a/man/synclient.man b/man/synclient.man
new file mode 100644
index 0000000..8eb20de
--- /dev/null
+++ b/man/synclient.man
@@ -0,0 +1,46 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH synclient __appmansuffix__ __vendorversion__
+.SH NAME
+.LP
+synclient \- commandline utility to query and modify Synaptics driver
+options.
+.SH "SYNOPSIS"
+.br
+synclient [\fI\-lV?\fP] [var1=value1 [var2=value2] ...]
+.SH "DESCRIPTION"
+.LP
+This program lets you change your Synaptics TouchPad driver for
+XOrg/XFree86 server parameters while X is running.
+
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-l\fR
+List current user settings. This is the default if no option is given.
+.TP
+\fB\-V\fR
+Print version number and exit.
+.TP
+\fB\-?\fR
+Show the help message.
+.TP
+\fBvar=value\fR
+Set user parameter \fIvar\fR to \fIvalue\fR.
+
+.SH "FILES"
+.LP
+\fI/etc/X11/xorg.conf\fP
+.SH "EXAMPLES"
+.LP
+To disable EdgeMotionMinSpeed:
+.LP
+synclient EdgeMotionMinSpeed=0
+.SH "AUTHORS"
+.LP
+Peter Osterlund <petero2@telia.com> and many others.
+.TP
+This man page was written by Mattia Dongili <malattia@debian.org>
+.SH "SEE ALSO"
+.LP
+__xservername__(__appmansuffix__), syndaemon(__appmansuffix__), synaptics(__drivermansuffix__)
diff --git a/man/syndaemon.1 b/man/syndaemon.1
deleted file mode 100644
index 9a7729d..0000000
--- a/man/syndaemon.1
+++ /dev/null
@@ -1,66 +0,0 @@
-.TH "syndaemon" "1" "0.14.6" "" ""
-.SH "NAME"
-.LP
-syndaemon \- a program that monitors keyboard activity and disables
-the touchpad when the keyboard is being used.
-.SH "SYNTAX"
-.LP
-syndaemon [\fI\-i idle\-time\fP] [\fI\-d\fP] [\fI\-p pid\-file\fP]
-[\fI\-t\fP] [\fI\-k\fP] [\fI\-K\fP]
-.SH "DESCRIPTION"
-.LP
-Disabling the touchpad while typing avoids unwanted movements of the
-pointer that could lead to giving focus to the wrong window.
-.
-This program needs SHMConfig "on" in your XOrg/XFree86 Synaptics
-Touchpad configuration.
-.SH "OPTIONS"
-.LP
-.TP
-\fB\-i\fR <\fIidle\-time\fP>
-How many seconds to wait after the last key press before enabling the
-touchpad.
-.
-(default is 2.0s).
-.LP
-.TP
-\fB\-d\fP
-Start as a daemon, ie in the background.
-.LP
-.TP
-\fB\-p\fR <\fIpid\-file\fP>
-Create a pid file with the specified filename.
-.
-A pid file will only be created if the program is started in daemon
-mode.
-.LP
-.TP
-\fB\-t\fP
-Only disable tapping and scrolling, not mouse movements, in response
-to keyboard activity.
-.LP
-.TP
-\fB\-k\fP
-Ignore modifier keys when monitoring keyboard activity.
-.LP
-.TP
-\fB\-K\fP
-Like \-k but also ignore Modifier+Key combos.
-.SH "ENVIRONMENT VARIABLES"
-.LP
-.TP
-\fBDISPLAY\fP
-Specifies the X server to contact.
-.SH "CAVEATS"
-.LP
-It doesn't make much sense to connect to a remote X server, because
-the daemon will then monitor the remote server for keyboard activity,
-but will disable the touchpad on the local machine.
-.SH "AUTHORS"
-.LP
-Peter Osterlund <petero2@telia.com>.
-.TP
-This man page was written by Mattia Dongili <malattia@debian.org>
-.SH "SEE ALSO"
-.LP
-synclient(1), synaptics(5)
diff --git a/man/syndaemon.man b/man/syndaemon.man
new file mode 100644
index 0000000..87691d8
--- /dev/null
+++ b/man/syndaemon.man
@@ -0,0 +1,105 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH syndaemon __appmansuffix__ __vendorversion__
+.SH NAME
+.LP
+syndaemon \- a program that monitors keyboard activity and disables
+the touchpad when the keyboard is being used.
+.SH "SYNOPSIS"
+.LP
+syndaemon [\fI\-i idle\-time\fP] [\fI\-m poll-inverval\fP] [\fI\-d\fP] [\fI\-p pid\-file\fP]
+[\fI\-t\fP] [\fI\-k\fP] [\fI\-K\fP] [\fI\-R\fP]
+.SH "DESCRIPTION"
+.LP
+Disabling the touchpad while typing avoids unwanted movements of the
+pointer that could lead to giving focus to the wrong window.
+.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-i\fR <\fIidle\-time\fP>
+How many seconds to wait after the last key press before enabling the
+touchpad.
+.
+(default is 2.0s).
+.LP
+.TP
+\fB\-m\fR <\fIpoll\-interval\fP>
+How many milliseconds to wait between two polling intervals. If this value is
+too low, it will cause unnecessary wake-ups. If this value is too high,
+some key presses (press and release happen between two intervals) may not
+be noticed. This switch has no effect when running with
+\fB-R\fP.
+.
+Default is 200ms.
+.LP
+.TP
+\fB\-d\fP
+Start as a daemon, ie in the background.
+.LP
+.TP
+\fB\-p\fR <\fIpid\-file\fP>
+Create a pid file with the specified filename.
+.
+A pid file will only be created if the program is started in daemon
+mode.
+.LP
+.TP
+\fB\-t\fP
+Only disable tapping and scrolling, not mouse movements, in response
+to keyboard activity.
+.LP
+.TP
+\fB\-k\fP
+Ignore modifier keys when monitoring keyboard activity.
+.LP
+.TP
+\fB\-K\fP
+Like \-k but also ignore Modifier+Key combos.
+.LP
+.TP
+\fB\-R\fP
+Use the XRecord extension for detecting keyboard activity instead of polling
+the keyboard state.
+.LP
+.TP
+\fB\-?\fP
+Show the help message.
+.SH "ENVIRONMENT VARIABLES"
+.LP
+.TP
+\fBDISPLAY\fP
+Specifies the X server to contact.
+.SH EXIT CODES
+If syndaemon exists with a return code other than 0, the error encountered
+is as below.
+.LP
+.TP
+\fBExit code 1
+Invalid commandline argument.
+.LP
+.TP
+\fBExit code 2
+The connection to the X sever could not be established or no touchpad device
+could be found.
+.LP
+.TP
+\fBExit code 3
+The fork into daemon mode failed or the pid file could not be created.
+.LP
+.TP
+\fBExit code 4
+XRECORD requested but not available or usable on the server.
+.SH "CAVEATS"
+.LP
+It doesn't make much sense to connect to a remote X server, because
+the daemon will then monitor the remote server for keyboard activity,
+but will disable the touchpad on the local machine.
+.SH "AUTHORS"
+.LP
+Peter Osterlund <petero2@telia.com>.
+.TP
+This man page was written by Mattia Dongili <malattia@debian.org>
+.SH "SEE ALSO"
+.LP
+__xservername__(__appmansuffix__), synclient(__appmansuffix__), synaptics(__drivermansuffix__)
diff --git a/src/Makefile.am b/src/Makefile.am
index 98a14c0..6ac254b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,23 +24,35 @@
# -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.
-@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
-@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
-@DRIVER_NAME@_drv_ladir = @inputdir@
+synaptics_drv_la_LTLIBRARIES = synaptics_drv.la
+synaptics_drv_la_LDFLAGS = -module -avoid-version
+synaptics_drv_ladir = @inputdir@
-@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c @DRIVER_NAME@.h \
- alpscomm.c alpscomm.h \
- eventcomm.c eventcomm.h \
- ps2comm.c ps2comm.h \
- psmcomm.c psmcomm.h \
- synproto.h
+AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS)
-bin_PROGRAMS = \
- synclient \
- syndaemon
+synaptics_drv_la_SOURCES = \
+ synaptics.c \
+ synapticsstr.h \
+ synproto.c \
+ synproto.h \
+ properties.c
-synclient_SOURCES = synclient.c
-synclient_LDFLAGS = -lm
+if BUILD_PS2COMM
+synaptics_drv_la_SOURCES += \
+ alpscomm.c \
+ ps2comm.c ps2comm.h
+endif
-syndaemon_SOURCES = syndaemon.c
-syndaemon_LDFLAGS = -lXi
+if BUILD_EVENTCOMM
+synaptics_drv_la_SOURCES += \
+ eventcomm.c eventcomm.h
+synaptics_drv_la_LIBADD = \
+ $(LIBEVDEV_LIBS)
+AM_CPPFLAGS += $(LIBEVDEV_CFLAGS)
+endif
+
+if BUILD_PSMCOMM
+synaptics_drv_la_SOURCES += \
+ psmcomm.c
+endif
diff --git a/src/alpscomm.c b/src/alpscomm.c
index 955e88f..b19ea6c 100644
--- a/src/alpscomm.c
+++ b/src/alpscomm.c
@@ -1,41 +1,51 @@
-/* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
- *
- * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
- * Copyright (c) 2003-2005,2007 Peter Osterlund <petero2@telia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+/*
+ * Copyright © 2001 Stefan Gmeiner
+ * Copyright © 2003 Neil Brown
+ * Copyright © 2003-2005,2007 Peter Osterlund
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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:
+ * Stefan Gmeiner (riddlebox@freesurf.ch)
+ * Neil Brown (neilb@cse.unsw.edu.au)
+ * Peter Osterlund (petero2@telia.com)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "alpscomm.h"
+#include <xorg-server.h>
#include "synproto.h"
-#include "synaptics.h"
+#include "synapticsstr.h"
+#include "ps2comm.h"
#include <xf86.h>
-
/* Wait for the channel to go silent, which means we're in sync */
static void
ALPS_sync(int fd)
{
byte buffer[64];
+
while (xf86WaitForInput(fd, 250000) > 0) {
- xf86ReadSerial(fd, &buffer, 64);
+ xf86ReadSerial(fd, &buffer, 64);
}
}
@@ -75,20 +85,10 @@ ALPS_initialize(int fd)
ALPS_sync(fd);
}
-static void
-ALPSDeviceOnHook(LocalDevicePtr local, SynapticsSHM *para)
-{
-}
-
-static void
-ALPSDeviceOffHook(LocalDevicePtr local)
-{
-}
-
static Bool
-ALPSQueryHardware(LocalDevicePtr local, struct SynapticsHwInfo *synhw)
+ALPSQueryHardware(InputInfoPtr pInfo)
{
- ALPS_initialize(local->fd);
+ ALPS_initialize(pInfo->fd);
return TRUE;
}
@@ -97,41 +97,40 @@ ALPS_packet_ok(struct CommData *comm)
{
/* ALPS absolute mode packets start with 0b11111mrl */
if ((comm->protoBuf[0] & 0xf8) == 0xf8)
- return TRUE;
+ return TRUE;
return FALSE;
}
static Bool
-ALPS_get_packet(struct CommData *comm, LocalDevicePtr local)
+ALPS_get_packet(struct CommData *comm, InputInfoPtr pInfo)
{
int c;
while ((c = XisbRead(comm->buffer)) >= 0) {
- unsigned char u = (unsigned char)c;
-
- comm->protoBuf[comm->protoBufTail++] = u;
-
- if (comm->protoBufTail == 3) { /* PS/2 packet received? */
- if ((comm->protoBuf[0] & 0xc8) == 0x08) {
- comm->protoBufTail = 0;
- return TRUE;
- }
- }
-
- if (comm->protoBufTail >= 6) { /* Full packet received */
- comm->protoBufTail = 0;
- if (ALPS_packet_ok(comm))
- return TRUE;
- while ((c = XisbRead(comm->buffer)) >= 0)
- ; /* If packet is invalid, re-sync */
- }
+ unsigned char u = (unsigned char) c;
+
+ comm->protoBuf[comm->protoBufTail++] = u;
+
+ if (comm->protoBufTail == 3) { /* PS/2 packet received? */
+ if ((comm->protoBuf[0] & 0xc8) == 0x08) {
+ comm->protoBufTail = 0;
+ return TRUE;
+ }
+ }
+
+ if (comm->protoBufTail >= 6) { /* Full packet received */
+ comm->protoBufTail = 0;
+ if (ALPS_packet_ok(comm))
+ return TRUE;
+ while ((c = XisbRead(comm->buffer)) >= 0); /* If packet is invalid, re-sync */
+ }
}
return FALSE;
}
/*
- * ALPS abolute Mode
+ * ALPS absolute Mode
* byte 0: 1 1 1 1 1 mid0 rig0 lef0
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0
* byte 2: 0 x10 x9 x8 x7 up1 fin ges
@@ -154,70 +153,52 @@ ALPS_process_packet(unsigned char *packet, struct SynapticsHwState *hw)
int left = 0, right = 0, middle = 0;
int i;
- /* Handle guest packets */
- hw->guest_dx = hw->guest_dy = 0;
- if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
- x = packet[1];
- if (packet[0] & 0x10)
- x = x - 256;
- y = packet[2];
- if (packet[0] & 0x20)
- y = y - 256;
- hw->guest_dx = x;
- hw->guest_dy = -y;
- hw->guest_left = (packet[0] & 0x01) ? TRUE : FALSE;
- hw->guest_right = (packet[0] & 0x02) ? TRUE : FALSE;
- return;
- }
+ hw->millis = GetTimeInMillis();
- x = (packet[1] & 0x7f) | ((packet[2] & 0x78) << (7-3));
- y = (packet[4] & 0x7f) | ((packet[3] & 0x70) << (7-4));
+ x = (packet[1] & 0x7f) | ((packet[2] & 0x78) << (7 - 3));
+ y = (packet[4] & 0x7f) | ((packet[3] & 0x70) << (7 - 4));
z = packet[5];
- if (z == 127) { /* DualPoint stick is relative, not absolute */
- if (x > 383)
- x = x - 768;
- if (y > 255)
- y = y - 512;
- hw->guest_dx = x;
- hw->guest_dy = -y;
- hw->left = packet[3] & 1;
- hw->right = (packet[3] >> 1) & 1;
- return;
+ if (z == 127) { /* DualPoint stick is relative, not absolute */
+ hw->left = packet[3] & 1;
+ hw->right = (packet[3] >> 1) & 1;
+ return;
}
/* Handle normal packets */
hw->x = hw->y = hw->z = hw->numFingers = hw->fingerWidth = 0;
hw->left = hw->right = hw->up = hw->down = hw->middle = FALSE;
for (i = 0; i < 8; i++)
- hw->multi[i] = FALSE;
+ hw->multi[i] = FALSE;
if (z > 0) {
- hw->x = x;
- hw->y = y;
+ hw->x = x;
+ hw->y = y;
}
hw->z = z;
hw->numFingers = (z > 0) ? 1 : 0;
hw->fingerWidth = 5;
- left |= (packet[2] ) & 1;
- left |= (packet[3] ) & 1;
+ left |= (packet[2]) & 1;
+ left |= (packet[3]) & 1;
right |= (packet[3] >> 1) & 1;
if (packet[0] == 0xff) {
- int back = (packet[3] >> 2) & 1;
- int forward = (packet[2] >> 2) & 1;
- if (back && forward) {
- middle = 1;
- back = 0;
- forward = 0;
- }
- hw->down = back;
- hw->up = forward;
- } else {
- left |= (packet[0] ) & 1;
- right |= (packet[0] >> 1) & 1;
- middle |= (packet[0] >> 2) & 1;
- middle |= (packet[3] >> 2) & 1;
+ int back = (packet[3] >> 2) & 1;
+ int forward = (packet[2] >> 2) & 1;
+
+ if (back && forward) {
+ middle = 1;
+ back = 0;
+ forward = 0;
+ }
+ hw->down = back;
+ hw->up = forward;
+ }
+ else {
+ left |= (packet[0]) & 1;
+ right |= (packet[0] >> 1) & 1;
+ middle |= (packet[0] >> 2) & 1;
+ middle |= (packet[3] >> 2) & 1;
}
hw->left = left;
@@ -226,32 +207,26 @@ ALPS_process_packet(unsigned char *packet, struct SynapticsHwState *hw)
}
static Bool
-ALPSReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
- struct SynapticsProtocolOperations *proto_ops,
- struct CommData *comm, struct SynapticsHwState *hwRet)
+ALPSReadHwState(InputInfoPtr pInfo,
+ struct CommData *comm, struct SynapticsHwState *hwRet)
{
unsigned char *buf = comm->protoBuf;
- struct SynapticsHwState *hw = &(comm->hwState);
+ struct SynapticsHwState *hw = comm->hwState;
- if (!ALPS_get_packet(comm, local))
- return FALSE;
+ if (!ALPS_get_packet(comm, pInfo))
+ return FALSE;
ALPS_process_packet(buf, hw);
- *hwRet = *hw;
+ SynapticsCopyHwState(hwRet, hw);
return TRUE;
}
-static Bool
-ALPSAutoDevProbe(LocalDevicePtr local)
-{
- return FALSE;
-}
-
struct SynapticsProtocolOperations alps_proto_operations = {
- ALPSDeviceOnHook,
- ALPSDeviceOffHook,
+ NULL,
+ NULL,
ALPSQueryHardware,
ALPSReadHwState,
- ALPSAutoDevProbe
+ NULL,
+ NULL
};
diff --git a/src/alpscomm.h b/src/alpscomm.h
deleted file mode 100644
index 52ec8ba..0000000
--- a/src/alpscomm.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * ALPS touchpad PS/2 mouse driver
- *
- * Copyright (c) 2004 Peter Osterlund <petero2@telia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _ALPSCOMM_H_
-#define _ALPSCOMM_H_
-
-#include "ps2comm.h"
-
-
-#endif /* _ALPSCOMM_H_ */
diff --git a/src/eventcomm.c b/src/eventcomm.c
index 5adfe26..b24ed21 100644
--- a/src/eventcomm.c
+++ b/src/eventcomm.c
@@ -1,39 +1,62 @@
/*
- * Copyright 2004-2007 Peter Osterlund <petero2@telia.com>
+ * Copyright © 2004-2007 Peter Osterlund
+ * Copyright © 2008-2012 Red Hat, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * 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.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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 Osterlund (petero2@telia.com)
*/
-#ifdef __LINUX
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <xorg-server.h>
+#include <xserver-properties.h>
#include "eventcomm.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
#include <stdio.h>
+#include <time.h>
#include "synproto.h"
-#define SYNAPTICS_PRIVATE
-#include "synaptics.h"
+#include "synapticsstr.h"
#include <xf86.h>
+#include <libevdev/libevdev.h>
+#ifndef INPUT_PROP_BUTTONPAD
+#define INPUT_PROP_BUTTONPAD 0x02
+#endif
+#ifndef INPUT_PROP_SEMI_MT
+#define INPUT_PROP_SEMI_MT 0x03
+#endif
+#ifndef INPUT_PROP_TOPBUTTONPAD
+#define INPUT_PROP_TOPBUTTONPAD 0x04
+#endif
+#ifndef ABS_MT_TOOL_Y
+#define ABS_MT_TOOL_Y 0x3d
+#endif
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
@@ -41,288 +64,1014 @@
#define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define OFF(x) ((x) % LONG_BITS)
#define LONG(x) ((x) / LONG_BITS)
-#define TEST_BIT(bit, array) (array[LONG(bit)] & (1 << OFF(bit)))
+#define TEST_BIT(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
-/*****************************************************************************
- * Function Definitions
- ****************************************************************************/
+#define ABS_MT_MIN ABS_MT_SLOT
+#define ABS_MT_MAX ABS_MT_TOOL_Y
+#define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1)
+
+/**
+ * Protocol-specific data.
+ */
+struct eventcomm_proto_data {
+ /**
+ * Do we need to grab the event device?
+ * Note that in the current flow, this variable is always false and
+ * exists for readability of the code.
+ */
+ BOOL need_grab;
+ int st_to_mt_offset[2];
+ double st_to_mt_scale[2];
+ int axis_map[ABS_MT_CNT];
+ int cur_slot;
+ ValuatorMask **last_mt_vals;
+ int num_touches;
+ struct libevdev *evdev;
+ enum libevdev_read_flag read_flag;
+
+ int have_monotonic_clock;
+};
+
+#ifdef HAVE_LIBEVDEV_DEVICE_LOG_FUNCS
static void
-EventDeviceOnHook(LocalDevicePtr local, SynapticsSHM *para)
+libevdev_log_func(const struct libevdev *dev,
+ enum libevdev_log_priority priority,
+ void *data,
+ const char *file, int line, const char *func,
+ const char *format, va_list args)
+_X_ATTRIBUTE_PRINTF(7, 0);
+
+static void
+libevdev_log_func(const struct libevdev *dev,
+ enum libevdev_log_priority priority,
+ void *data,
+ const char *file, int line, const char *func,
+ const char *format, va_list args)
{
- if (para->grab_event_device) {
- /* Try to grab the event device so that data don't leak to /dev/input/mice */
- int ret;
- SYSCALL(ret = ioctl(local->fd, EVIOCGRAB, (pointer)1));
- if (ret < 0) {
- xf86Msg(X_WARNING, "%s can't grab event device, errno=%d\n",
- local->name, errno);
- }
+ int verbosity;
+
+ switch(priority) {
+ case LIBEVDEV_LOG_ERROR: verbosity = 0; break;
+ case LIBEVDEV_LOG_INFO: verbosity = 4; break;
+ case LIBEVDEV_LOG_DEBUG:
+ default:
+ verbosity = 10;
+ break;
}
+
+ LogVMessageVerbSigSafe(X_NOTICE, verbosity, format, args);
+}
+#endif
+
+struct eventcomm_proto_data *
+EventProtoDataAlloc(int fd)
+{
+ struct eventcomm_proto_data *proto_data;
+ int rc;
+
+
+ proto_data = calloc(1, sizeof(struct eventcomm_proto_data));
+ if (!proto_data)
+ return NULL;
+
+ proto_data->st_to_mt_scale[0] = 1;
+ proto_data->st_to_mt_scale[1] = 1;
+
+ proto_data->evdev = libevdev_new();
+ if (!proto_data->evdev) {
+ rc = -1;
+ goto out;
+ }
+
+#ifdef HAVE_LIBEVDEV_DEVICE_LOG_FUNCS
+ libevdev_set_device_log_function(proto_data->evdev, libevdev_log_func,
+ LIBEVDEV_LOG_DEBUG, NULL);
+#endif
+
+ rc = libevdev_set_fd(proto_data->evdev, fd);
+ if (rc < 0) {
+ goto out;
+ }
+
+ proto_data->read_flag = LIBEVDEV_READ_FLAG_NORMAL;
+
+out:
+ if (rc < 0) {
+ if (proto_data && proto_data->evdev)
+ libevdev_free(proto_data->evdev);
+ free(proto_data);
+ proto_data = NULL;
+ }
+
+ return proto_data;
}
static void
-EventDeviceOffHook(LocalDevicePtr local)
+UninitializeTouch(InputInfoPtr pInfo)
{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data =
+ (struct eventcomm_proto_data *) priv->proto_data;
+
+ if (!priv->has_touch)
+ return;
+
+ if (proto_data->last_mt_vals) {
+ int i;
+
+ for (i = 0; i < priv->num_slots; i++)
+ valuator_mask_free(&proto_data->last_mt_vals[i]);
+ free(proto_data->last_mt_vals);
+ proto_data->last_mt_vals = NULL;
+ }
+
+ proto_data->num_touches = 0;
}
static void
-event_query_abs_params(LocalDevicePtr local, int fd)
+InitializeTouch(InputInfoPtr pInfo)
{
- int ret;
- SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
- struct input_absinfo absinfo;
- SYSCALL(ret = ioctl(fd, EVIOCGABS(ABS_X), &absinfo));
- if (ret < 0)
- return;
-
- priv->minx = absinfo.minimum;
- priv->maxx = absinfo.maximum;
-
- SYSCALL(ret = ioctl(fd, EVIOCGABS(ABS_Y), &absinfo));
- if (ret < 0)
- return;
-
- priv->miny = absinfo.minimum;
- priv->maxy = absinfo.maximum;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data =
+ (struct eventcomm_proto_data *) priv->proto_data;
+ int i;
+
+ if (!priv->has_touch)
+ return;
+
+ proto_data->cur_slot = libevdev_get_current_slot(proto_data->evdev);
+ proto_data->num_touches = 0;
+
+ proto_data->last_mt_vals = calloc(priv->num_slots, sizeof(ValuatorMask *));
+ if (!proto_data->last_mt_vals) {
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "failed to allocate MT last values mask array\n");
+ UninitializeTouch(pInfo);
+ return;
+ }
+
+ for (i = 0; i < priv->num_slots; i++) {
+ int j;
+
+ proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes);
+ if (!proto_data->last_mt_vals[i]) {
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "failed to allocate MT last values mask\n");
+ UninitializeTouch(pInfo);
+ return;
+ }
+
+ /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X
+ * and Y. */
+ valuator_mask_set(proto_data->last_mt_vals[i], 0, 0);
+ valuator_mask_set(proto_data->last_mt_vals[i], 1, 0);
+ for (j = 0; j < priv->num_mt_axes; j++)
+ valuator_mask_set(proto_data->last_mt_vals[i], 4 + j, 0);
+ }
}
static Bool
-event_query_is_touchpad(int fd)
+EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters * para)
{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data =
+ (struct eventcomm_proto_data *) priv->proto_data;
int ret;
- unsigned long evbits[NBITS(KEY_MAX)];
+ if (libevdev_get_fd(proto_data->evdev) != -1) {
+ struct input_event ev;
+
+ libevdev_change_fd(proto_data->evdev, pInfo->fd);
+
+ /* re-sync libevdev's state, but we don't care about the actual
+ events here */
+ libevdev_next_event(proto_data->evdev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
+ while (libevdev_next_event(proto_data->evdev,
+ LIBEVDEV_READ_FLAG_SYNC, &ev) == LIBEVDEV_READ_STATUS_SYNC)
+ ;
+
+ } else
+ libevdev_set_fd(proto_data->evdev, pInfo->fd);
+
+
+ if (para->grab_event_device) {
+ /* Try to grab the event device so that data don't leak to /dev/input/mice */
+
+ ret = libevdev_grab(proto_data->evdev, LIBEVDEV_GRAB);
+ if (ret < 0) {
+ xf86IDrvMsg(pInfo, X_WARNING, "can't grab event device, errno=%d\n",
+ -ret);
+ return FALSE;
+ }
+ }
+
+ proto_data->need_grab = FALSE;
+
+ ret = libevdev_set_clock_id(proto_data->evdev, CLOCK_MONOTONIC);
+ proto_data->have_monotonic_clock = (ret == 0);
+
+ InitializeTouch(pInfo);
+
+ return TRUE;
+}
+
+static Bool
+EventDeviceOffHook(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+
+ UninitializeTouch(pInfo);
+ libevdev_grab(proto_data->evdev, LIBEVDEV_UNGRAB);
+ libevdev_set_log_function(NULL, NULL);
+ libevdev_set_log_priority(LIBEVDEV_LOG_INFO); /* reset to default */
+
+ return Success;
+}
+
+/**
+ * Test if the device on the file descriptor is recognized as touchpad
+ * device. Required bits for touchpad recognition are:
+ * - ABS_X + ABS_Y for absolute axes
+ * - ABS_PRESSURE or BTN_TOUCH
+ * - BTN_TOOL_FINGER
+ * - BTN_TOOL_PEN is _not_ set
+ *
+ * @param evdev Libevdev handle
+ *
+ * @return TRUE if the device is a touchpad or FALSE otherwise.
+ */
+static Bool
+event_query_is_touchpad(struct libevdev *evdev)
+{
/* Check for ABS_X, ABS_Y, ABS_PRESSURE and BTN_TOOL_FINGER */
+ if (!libevdev_has_event_type(evdev, EV_SYN) ||
+ !libevdev_has_event_type(evdev, EV_ABS) ||
+ !libevdev_has_event_type(evdev, EV_KEY))
+ return FALSE;
+
+ if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) ||
+ !libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
+ return FALSE;
- SYSCALL(ret = ioctl(fd, EVIOCGBIT(0, EV_MAX), evbits));
- if (ret < 0)
- return FALSE;
- if (!TEST_BIT(EV_SYN, evbits) ||
- !TEST_BIT(EV_ABS, evbits) ||
- !TEST_BIT(EV_KEY, evbits))
- return FALSE;
-
- SYSCALL(ret = ioctl(fd, EVIOCGBIT(EV_ABS, KEY_MAX), evbits));
- if (ret < 0)
- return FALSE;
- if (!TEST_BIT(ABS_X, evbits) ||
- !TEST_BIT(ABS_Y, evbits) ||
- !TEST_BIT(ABS_PRESSURE, evbits))
- return FALSE;
-
- SYSCALL(ret = ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX), evbits));
- if (ret < 0)
- return FALSE;
- if (!TEST_BIT(BTN_TOOL_FINGER, evbits))
- return FALSE;
- if (TEST_BIT(BTN_TOOL_PEN, evbits))
- return FALSE; /* Don't match wacom tablets */
+ /* we expect touchpad either report raw pressure or touches */
+ if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH) &&
+ !libevdev_has_event_code(evdev, EV_ABS, ABS_PRESSURE))
+ return FALSE;
+
+ /* all Synaptics-like touchpad report BTN_TOOL_FINGER */
+ if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) ||
+ libevdev_has_event_code(evdev, EV_ABS, BTN_TOOL_PEN)) /* Don't match wacom tablets */
+ return FALSE;
+
+ if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT)) {
+ if (libevdev_get_num_slots(evdev) == -1)
+ return FALSE; /* Ignore fake MT devices */
+
+ if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ||
+ !libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
+ return FALSE;
+ }
return TRUE;
}
+#define PRODUCT_ANY 0x0000
+
+struct model_lookup_t {
+ short vendor;
+ short product_start;
+ short product_end;
+ enum TouchpadModel model;
+};
+
+
+static struct model_lookup_t model_lookup_table[] = {
+ {0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS},
+ {0x0002, 0x0008, 0x0008, MODEL_ALPS},
+ {0x05ac, PRODUCT_ANY, 0x222, MODEL_APPLETOUCH},
+ {0x05ac, 0x223, 0x228, MODEL_UNIBODY_MACBOOK},
+ {0x05ac, 0x229, 0x22b, MODEL_APPLETOUCH},
+ {0x05ac, 0x22c, PRODUCT_ANY, MODEL_UNIBODY_MACBOOK},
+ {0x0002, 0x000e, 0x000e, MODEL_ELANTECH},
+ {0x0, 0x0, 0x0, 0x0}
+};
+
+/**
+ * Check for the vendor/product id on the file descriptor and compare
+ * with the built-in model LUT. This information is used in synaptics.c to
+ * initialize model-specific dimensions.
+ *
+ * @param fd The file descriptor to a event device.
+ * @param[out] model_out The type of touchpad model detected.
+ *
+ * @return TRUE on success or FALSE otherwise.
+ */
static Bool
-EventQueryHardware(LocalDevicePtr local, struct SynapticsHwInfo *synhw)
+event_query_model(struct libevdev *evdev, enum TouchpadModel *model_out,
+ unsigned short *vendor_id, unsigned short *product_id)
{
- if (event_query_is_touchpad(local->fd)) {
- xf86Msg(X_PROBED, "%s touchpad found\n", local->name);
- return TRUE;
+ int vendor, product;
+ struct model_lookup_t *model_lookup;
+
+ vendor = libevdev_get_id_vendor(evdev);
+ product = libevdev_get_id_product(evdev);
+
+ for (model_lookup = model_lookup_table; model_lookup->vendor;
+ model_lookup++) {
+ if (model_lookup->vendor == vendor &&
+ (model_lookup->product_start == PRODUCT_ANY ||
+ model_lookup->product_start <= product) &&
+ (model_lookup->product_end == PRODUCT_ANY ||
+ model_lookup->product_end >= product))
+ *model_out = model_lookup->model;
}
- return FALSE;
+ *vendor_id = vendor;
+ *product_id = product;
+
+ return TRUE;
+}
+
+/**
+ * Get absinfo information from the given file descriptor for the given
+ * ABS_FOO code and store the information in min, max, fuzz and res.
+ *
+ * @param fd File descriptor to an event device
+ * @param code Event code (e.g. ABS_X)
+ * @param[out] min Minimum axis range
+ * @param[out] max Maximum axis range
+ * @param[out] fuzz Fuzz of this axis. If NULL, fuzz is ignored.
+ * @param[out] res Axis resolution. If NULL or the current kernel does not
+ * support the resolution field, res is ignored
+ *
+ * @return Zero on success, or errno otherwise.
+ */
+static int
+event_get_abs(struct libevdev *evdev, int code,
+ int *min, int *max, int *fuzz, int *res)
+{
+ const struct input_absinfo *abs;
+
+ abs = libevdev_get_abs_info(evdev, code);
+ *min = abs->minimum;
+ *max = abs->maximum;
+
+ /* We don't trust a zero fuzz as it probably is just a lazy value */
+ if (fuzz && abs->fuzz > 0)
+ *fuzz = abs->fuzz;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
+ if (res)
+ *res = abs->resolution;
+#endif
+
+ return 0;
+}
+
+/* Query device for axis ranges */
+static void
+event_query_axis_ranges(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+ char buf[256] = { 0 };
+
+ /* The kernel's fuzziness concept seems a bit weird, but it can more or
+ * less be applied as hysteresis directly, i.e. no factor here. */
+ event_get_abs(proto_data->evdev, ABS_X, &priv->minx, &priv->maxx,
+ &priv->synpara.hyst_x, &priv->resx);
+
+ event_get_abs(proto_data->evdev, ABS_Y, &priv->miny, &priv->maxy,
+ &priv->synpara.hyst_y, &priv->resy);
+
+ if (priv->minx == priv->maxx || priv->miny == priv->maxy) {
+ xf86IDrvMsg(pInfo, X_ERROR, "Kernel bug: min == max on ABS_X/Y\n");
+ return;
+ }
+
+ priv->has_pressure = libevdev_has_event_code(proto_data->evdev, EV_ABS, ABS_PRESSURE);
+ priv->has_width = libevdev_has_event_code(proto_data->evdev, EV_ABS, ABS_TOOL_WIDTH);
+
+ if (priv->has_pressure)
+ event_get_abs(proto_data->evdev, ABS_PRESSURE, &priv->minp, &priv->maxp,
+ NULL, NULL);
+
+ if (priv->has_width)
+ event_get_abs(proto_data->evdev, ABS_TOOL_WIDTH,
+ &priv->minw, &priv->maxw, NULL, NULL);
+
+ if (priv->has_touch) {
+ int st_minx = priv->minx;
+ int st_maxx = priv->maxx;
+ int st_miny = priv->miny;
+ int st_maxy = priv->maxy;
+
+ event_get_abs(proto_data->evdev, ABS_MT_POSITION_X, &priv->minx,
+ &priv->maxx, &priv->synpara.hyst_x, &priv->resx);
+ event_get_abs(proto_data->evdev, ABS_MT_POSITION_Y, &priv->miny,
+ &priv->maxy, &priv->synpara.hyst_y, &priv->resy);
+
+ if (priv->minx == priv->maxx || priv->miny == priv->maxy) {
+ xf86IDrvMsg(pInfo, X_ERROR, "Kernel bug: min == max on ABS_MT_POSITION_X/Y\n");
+ return;
+ }
+
+ proto_data->st_to_mt_offset[0] = priv->minx - st_minx;
+ proto_data->st_to_mt_scale[0] =
+ (priv->maxx - priv->minx) / (st_maxx - st_minx);
+ proto_data->st_to_mt_offset[1] = priv->miny - st_miny;
+ proto_data->st_to_mt_scale[1] =
+ (priv->maxy - priv->miny) / (st_maxy - st_miny);
+ }
+
+ priv->has_left = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_LEFT);
+ priv->has_right = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_RIGHT);
+ priv->has_middle = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_MIDDLE);
+ priv->has_double = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_TOOL_DOUBLETAP);
+ priv->has_triple = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_TOOL_TRIPLETAP);
+
+ if (libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_0) ||
+ libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_1) ||
+ libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_2) ||
+ libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_3))
+ priv->has_scrollbuttons = 1;
+
+ /* Now print the device information */
+ xf86IDrvMsg(pInfo, X_PROBED, "x-axis range %d - %d (res %d)\n",
+ priv->minx, priv->maxx, priv->resx);
+ xf86IDrvMsg(pInfo, X_PROBED, "y-axis range %d - %d (res %d)\n",
+ priv->miny, priv->maxy, priv->resy);
+ if (priv->has_pressure)
+ xf86IDrvMsg(pInfo, X_PROBED, "pressure range %d - %d\n",
+ priv->minp, priv->maxp);
+ else
+ xf86IDrvMsg(pInfo, X_INFO,
+ "device does not report pressure, will use touch data.\n");
+ if (priv->has_width)
+ xf86IDrvMsg(pInfo, X_PROBED, "finger width range %d - %d\n",
+ priv->minw, priv->maxw);
+ else
+ xf86IDrvMsg(pInfo, X_INFO, "device does not report finger width.\n");
+
+ if (priv->has_left)
+ strcat(buf, " left");
+ if (priv->has_right)
+ strcat(buf, " right");
+ if (priv->has_middle)
+ strcat(buf, " middle");
+ if (priv->has_double)
+ strcat(buf, " double");
+ if (priv->has_triple)
+ strcat(buf, " triple");
+ if (priv->has_scrollbuttons)
+ strcat(buf, " scroll-buttons");
+
+ xf86IDrvMsg(pInfo, X_PROBED, "buttons:%s\n", buf);
}
static Bool
-SynapticsReadEvent(struct CommData *comm, struct input_event *ev)
+EventQueryHardware(InputInfoPtr pInfo)
{
- int i, c;
- unsigned char *pBuf, u;
-
- for (i = 0; i < sizeof(struct input_event); i++) {
- if ((c = XisbRead(comm->buffer)) < 0)
- return FALSE;
- u = (unsigned char)c;
- pBuf = (unsigned char *)ev;
- pBuf[i] = u;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+
+ if (!event_query_is_touchpad(proto_data->evdev))
+ return FALSE;
+
+ xf86IDrvMsg(pInfo, X_PROBED, "touchpad found\n");
+
+ return TRUE;
+}
+
+static Bool
+SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+ int rc;
+ static struct timeval last_event_time;
+
+ rc = libevdev_next_event(proto_data->evdev, proto_data->read_flag, ev);
+ if (rc < 0) {
+ if (rc != -EAGAIN) {
+ LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error %d\n", pInfo->name,
+ errno);
+ xf86RemoveEnabledDevice(pInfo);
+ } else if (proto_data->read_flag == LIBEVDEV_READ_FLAG_SYNC) {
+ proto_data->read_flag = LIBEVDEV_READ_FLAG_NORMAL;
+ return SynapticsReadEvent(pInfo, ev);
+ }
+
+ return FALSE;
}
+
+ /* SYN_DROPPED received in normal mode. Create a normal EV_SYN
+ so we process what's in the queue atm, then ensure we sync
+ next time */
+ if (rc == LIBEVDEV_READ_STATUS_SYNC &&
+ proto_data->read_flag == LIBEVDEV_READ_FLAG_NORMAL) {
+ proto_data->read_flag = LIBEVDEV_READ_FLAG_SYNC;
+ ev->type = EV_SYN;
+ ev->code = SYN_REPORT;
+ ev->value = 0;
+ ev->input_event_sec = last_event_time.tv_sec;
+ ev->input_event_usec = last_event_time.tv_usec;
+ } else if (ev->type == EV_SYN) {
+ last_event_time.tv_sec = ev->input_event_sec;
+ last_event_time.tv_usec = ev->input_event_usec;
+ }
+
return TRUE;
}
static Bool
-EventReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
- struct SynapticsProtocolOperations *proto_ops,
- struct CommData *comm, struct SynapticsHwState *hwRet)
+EventTouchSlotPreviouslyOpen(SynapticsPrivate * priv, int slot)
+{
+ int i;
+
+ for (i = 0; i < priv->num_active_touches; i++)
+ if (priv->open_slots[i] == slot)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+EventProcessTouchEvent(InputInfoPtr pInfo, struct SynapticsHwState *hw,
+ struct input_event *ev)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+
+ if (!priv->has_touch)
+ return;
+
+ if (ev->code == ABS_MT_SLOT) {
+ proto_data->cur_slot = ev->value;
+ }
+ else {
+ int slot_index = proto_data->cur_slot;
+
+ if (slot_index < 0)
+ return;
+
+ if (hw->slot_state[slot_index] == SLOTSTATE_OPEN_EMPTY)
+ hw->slot_state[slot_index] = SLOTSTATE_UPDATE;
+ if (ev->code == ABS_MT_TRACKING_ID) {
+ if (ev->value >= 0) {
+ hw->slot_state[slot_index] = SLOTSTATE_OPEN;
+ proto_data->num_touches++;
+ valuator_mask_copy(hw->mt_mask[slot_index],
+ proto_data->last_mt_vals[slot_index]);
+ }
+ else if (hw->slot_state[slot_index] != SLOTSTATE_EMPTY) {
+ hw->slot_state[slot_index] = SLOTSTATE_CLOSE;
+ proto_data->num_touches--;
+ }
+
+ /* When there are no fingers on the touchpad, set width and
+ * pressure to zero as ABS_MT_TOUCH_MAJOR and ABS_MT_PRESSURE
+ * are not zero when fingers are released. */
+ if (proto_data->num_touches == 0) {
+ hw->fingerWidth = 0;
+ hw->z = 0;
+ }
+ }
+ else {
+ ValuatorMask *mask = proto_data->last_mt_vals[slot_index];
+ int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR];
+ int last_val = valuator_mask_get(mask, map);
+
+ valuator_mask_set(hw->mt_mask[slot_index], map, ev->value);
+ if (EventTouchSlotPreviouslyOpen(priv, slot_index)) {
+ if (ev->code == ABS_MT_POSITION_X)
+ hw->cumulative_dx += ev->value - last_val;
+ else if (ev->code == ABS_MT_POSITION_Y)
+ hw->cumulative_dy += ev->value - last_val;
+ else if (ev->code == ABS_MT_TOUCH_MAJOR &&
+ priv->has_mt_palm_detect)
+ hw->fingerWidth = ev->value;
+ else if (ev->code == ABS_MT_PRESSURE &&
+ priv->has_mt_palm_detect)
+ hw->z = ev->value;
+ }
+
+ valuator_mask_set(mask, map, ev->value);
+ }
+ }
+}
+
+/**
+ * Count the number of fingers based on the CommData information.
+ * The CommData struct contains the event information based on previous
+ * struct input_events, now we're just counting based on that.
+ *
+ * @param comm Assembled information from previous events.
+ * @return The number of fingers currently set.
+ */
+static int
+count_fingers(InputInfoPtr pInfo, const struct CommData *comm)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+ int fingers = 0;
+
+ if (comm->oneFinger)
+ fingers = 1;
+ else if (comm->twoFingers)
+ fingers = 2;
+ else if (comm->threeFingers)
+ fingers = 3;
+
+ if (priv->has_touch && proto_data->num_touches > fingers)
+ fingers = proto_data->num_touches;
+
+ return fingers;
+}
+
+static inline double
+apply_st_scaling(struct eventcomm_proto_data *proto_data, int value, int axis)
+{
+ return value * proto_data->st_to_mt_scale[axis] +
+ proto_data->st_to_mt_offset[axis];
+}
+
+Bool
+EventReadHwState(InputInfoPtr pInfo,
+ struct CommData *comm, struct SynapticsHwState *hwRet)
{
struct input_event ev;
Bool v;
- struct SynapticsHwState *hw = &(comm->hwState);
-
- while (SynapticsReadEvent(comm, &ev)) {
- switch (ev.type) {
- case EV_SYN:
- switch (ev.code) {
- case SYN_REPORT:
- if (comm->oneFinger)
- hw->numFingers = 1;
- else if (comm->twoFingers)
- hw->numFingers = 2;
- else if (comm->threeFingers)
- hw->numFingers = 3;
- else
- hw->numFingers = 0;
- *hwRet = *hw;
- hw->guest_dx = hw->guest_dy = 0;
- return TRUE;
- }
- case EV_KEY:
- v = (ev.value ? TRUE : FALSE);
- switch (ev.code) {
- case BTN_LEFT:
- hw->left = v;
- break;
- case BTN_RIGHT:
- hw->right = v;
- break;
- case BTN_MIDDLE:
- hw->middle = v;
- break;
- case BTN_FORWARD:
- hw->up = v;
- break;
- case BTN_BACK:
- hw->down = v;
- break;
- case BTN_0:
- hw->multi[0] = v;
- break;
- case BTN_1:
- hw->multi[1] = v;
- break;
- case BTN_2:
- hw->multi[2] = v;
- break;
- case BTN_3:
- hw->multi[3] = v;
- break;
- case BTN_4:
- hw->multi[4] = v;
- break;
- case BTN_5:
- hw->multi[5] = v;
- break;
- case BTN_6:
- hw->multi[6] = v;
- break;
- case BTN_7:
- hw->multi[7] = v;
- break;
- case BTN_TOOL_FINGER:
- comm->oneFinger = v;
- break;
- case BTN_TOOL_DOUBLETAP:
- comm->twoFingers = v;
- break;
- case BTN_TOOL_TRIPLETAP:
- comm->threeFingers = v;
- break;
- case BTN_A:
- hw->guest_left = v;
- break;
- case BTN_B:
- hw->guest_right = v;
- break;
- }
- break;
- case EV_ABS:
- switch (ev.code) {
- case ABS_X:
- hw->x = ev.value;
- break;
- case ABS_Y:
- hw->y = ev.value;
- break;
- case ABS_PRESSURE:
- hw->z = ev.value;
- break;
- case ABS_TOOL_WIDTH:
- hw->fingerWidth = ev.value;
- break;
- }
- break;
- case EV_REL:
- switch (ev.code) {
- case REL_X:
- hw->guest_dx = ev.value;
- break;
- case REL_Y:
- hw->guest_dy = ev.value;
- break;
- }
- break;
- }
+ struct SynapticsHwState *hw = comm->hwState;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ SynapticsParameters *para = &priv->synpara;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+ Bool sync_cumulative = FALSE;
+
+ SynapticsResetTouchHwState(hw, FALSE);
+
+ /* Reset cumulative values if buttons were not previously pressed and no
+ * two-finger scrolling is ongoing, or no finger was previously present. */
+ if (((!hw->left && !hw->right && !hw->middle) &&
+ !(priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on)) ||
+ hw->z < para->finger_low) {
+ hw->cumulative_dx = hw->x;
+ hw->cumulative_dy = hw->y;
+ sync_cumulative = TRUE;
+ }
+
+ while (SynapticsReadEvent(pInfo, &ev)) {
+ switch (ev.type) {
+ case EV_SYN:
+ switch (ev.code) {
+ case SYN_REPORT:
+ hw->numFingers = count_fingers(pInfo, comm);
+ if (proto_data->have_monotonic_clock)
+ hw->millis = 1000 * ev.input_event_sec + ev.input_event_usec / 1000;
+ else
+ hw->millis = GetTimeInMillis();
+ SynapticsCopyHwState(hwRet, hw);
+ return TRUE;
+ }
+ break;
+ case EV_KEY:
+ /* ignore hw repeat events */
+ if (ev.value > 1)
+ break;
+
+ v = (ev.value ? TRUE : FALSE);
+ switch (ev.code) {
+ case BTN_LEFT:
+ hw->left = v;
+ break;
+ case BTN_RIGHT:
+ hw->right = v;
+ break;
+ case BTN_MIDDLE:
+ hw->middle = v;
+ break;
+ case BTN_FORWARD:
+ hw->up = v;
+ break;
+ case BTN_BACK:
+ hw->down = v;
+ break;
+ case BTN_0:
+ hw->multi[0] = v;
+ break;
+ case BTN_1:
+ hw->multi[1] = v;
+ break;
+ case BTN_2:
+ hw->multi[2] = v;
+ break;
+ case BTN_3:
+ hw->multi[3] = v;
+ break;
+ case BTN_4:
+ hw->multi[4] = v;
+ break;
+ case BTN_5:
+ hw->multi[5] = v;
+ break;
+ case BTN_6:
+ hw->multi[6] = v;
+ break;
+ case BTN_7:
+ hw->multi[7] = v;
+ break;
+ case BTN_TOOL_FINGER:
+ comm->oneFinger = v;
+ break;
+ case BTN_TOOL_DOUBLETAP:
+ comm->twoFingers = v;
+ break;
+ case BTN_TOOL_TRIPLETAP:
+ comm->threeFingers = v;
+ break;
+ case BTN_TOUCH:
+ if (!priv->has_pressure)
+ hw->z = v ? para->finger_high + 1 : 0;
+ break;
+ }
+ break;
+ case EV_ABS:
+ if (ev.code < ABS_MT_SLOT) {
+ switch (ev.code) {
+ case ABS_X:
+ hw->x = apply_st_scaling(proto_data, ev.value, 0);
+ if (sync_cumulative)
+ hw->cumulative_dx = hw->x;
+ break;
+ case ABS_Y:
+ hw->y = apply_st_scaling(proto_data, ev.value, 1);
+ if (sync_cumulative)
+ hw->cumulative_dy = hw->y;
+ break;
+ case ABS_PRESSURE:
+ hw->z = ev.value;
+ break;
+ case ABS_TOOL_WIDTH:
+ hw->fingerWidth = ev.value;
+ break;
+ }
+ }
+ else
+ EventProcessTouchEvent(pInfo, hw, &ev);
+ break;
+ }
}
return FALSE;
}
+/* filter for the AutoDevProbe scandir on /dev/input */
+static int
+EventDevOnly(const struct dirent *dir)
+{
+ return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
+}
+
+static void
+event_query_touch(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ SynapticsParameters *para = &priv->synpara;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+ struct libevdev *dev = proto_data->evdev;
+ int axis;
+
+ priv->max_touches = 0;
+ priv->num_mt_axes = 0;
+
+#ifdef EVIOCGPROP
+ if (libevdev_has_property(dev, INPUT_PROP_SEMI_MT)) {
+ xf86IDrvMsg(pInfo, X_INFO,
+ "ignoring touch events for semi-multitouch device\n");
+ priv->has_semi_mt = TRUE;
+ }
+
+ if (libevdev_has_property(dev, INPUT_PROP_BUTTONPAD)) {
+ xf86IDrvMsg(pInfo, X_INFO, "found clickpad property\n");
+ para->clickpad = TRUE;
+ }
+
+ if (libevdev_has_property(dev, INPUT_PROP_TOPBUTTONPAD)) {
+ xf86IDrvMsg(pInfo, X_INFO, "found top buttonpad property\n");
+ para->has_secondary_buttons = TRUE;
+ }
+#endif
+
+
+ if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
+ for (axis = ABS_MT_SLOT + 1; axis <= ABS_MT_MAX; axis++) {
+ if (!libevdev_has_event_code(dev, EV_ABS, axis))
+ continue;
+
+ priv->has_touch = TRUE;
+
+ /* X and Y axis info is handled by synaptics already and we don't
+ expose the tracking ID */
+ if (axis == ABS_MT_POSITION_X ||
+ axis == ABS_MT_POSITION_Y ||
+ axis == ABS_MT_TRACKING_ID)
+ continue;
+
+ priv->num_mt_axes++;
+ }
+ }
+
+ if (priv->has_touch) {
+ int axnum;
+
+ static const char *labels[ABS_MT_MAX] = {
+ AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR,
+ AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR,
+ AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR,
+ AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR,
+ AXIS_LABEL_PROP_ABS_MT_ORIENTATION,
+ AXIS_LABEL_PROP_ABS_MT_POSITION_X,
+ AXIS_LABEL_PROP_ABS_MT_POSITION_Y,
+ AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE,
+ AXIS_LABEL_PROP_ABS_MT_BLOB_ID,
+ AXIS_LABEL_PROP_ABS_MT_TRACKING_ID,
+ AXIS_LABEL_PROP_ABS_MT_PRESSURE,
+ AXIS_LABEL_PROP_ABS_MT_DISTANCE,
+ AXIS_LABEL_PROP_ABS_MT_TOOL_X,
+ AXIS_LABEL_PROP_ABS_MT_TOOL_Y,
+ };
+
+ priv->max_touches = libevdev_get_num_slots(dev);
+ priv->touch_axes = malloc(priv->num_mt_axes *
+ sizeof(SynapticsTouchAxisRec));
+ if (!priv->touch_axes) {
+ priv->has_touch = FALSE;
+ return;
+ }
+
+ if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_TOUCH_MAJOR) &&
+ libevdev_has_event_code(dev, EV_ABS, ABS_MT_PRESSURE))
+ priv->has_mt_palm_detect = TRUE;
+
+ axnum = 0;
+ for (axis = ABS_MT_SLOT + 1; axis <= ABS_MT_MAX; axis++) {
+ int axis_idx = axis - ABS_MT_TOUCH_MAJOR;
+
+ if (!libevdev_has_event_code(dev, EV_ABS, axis))
+ continue;
+
+ switch (axis) {
+ /* X and Y axis info is handled by synaptics already, we just
+ * need to map the evdev codes to the valuator numbers */
+ case ABS_MT_POSITION_X:
+ proto_data->axis_map[axis_idx] = 0;
+ break;
+
+ case ABS_MT_POSITION_Y:
+ proto_data->axis_map[axis_idx] = 1;
+ break;
+
+ /* Skip tracking ID info */
+ case ABS_MT_TRACKING_ID:
+ break;
+
+ default:
+ if (axis_idx >= sizeof(labels)/sizeof(labels[0])) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "Axis %d out of label range. This is a bug\n",
+ axis);
+ priv->touch_axes[axnum].label = NULL;
+ } else
+ priv->touch_axes[axnum].label = labels[axis_idx];
+ priv->touch_axes[axnum].min = libevdev_get_abs_minimum(dev, axis);
+ priv->touch_axes[axnum].max = libevdev_get_abs_maximum(dev, axis);
+ /* Kernel provides units/mm, X wants units/m */
+ priv->touch_axes[axnum].res = libevdev_get_abs_resolution(dev, axis) * 1000;
+ /* Valuators 0-3 are used for X, Y, and scrolling */
+ proto_data->axis_map[axis_idx] = 4 + axnum;
+ axnum++;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Probe the open device for dimensions.
+ */
+static void
+EventReadDevDimensions(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct eventcomm_proto_data *proto_data = priv->proto_data;
+ int i;
+
+ proto_data = EventProtoDataAlloc(pInfo->fd);
+ priv->proto_data = proto_data;
+
+ for (i = 0; i < ABS_MT_CNT; i++)
+ proto_data->axis_map[i] = -1;
+ proto_data->cur_slot = -1;
+
+ if (event_query_is_touchpad(proto_data->evdev)) {
+ event_query_touch(pInfo);
+ event_query_axis_ranges(pInfo);
+ }
+ event_query_model(proto_data->evdev, &priv->model, &priv->id_vendor,
+ &priv->id_product);
+
+ xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
+ priv->id_vendor, priv->id_product);
+}
+
static Bool
-EventAutoDevProbe(LocalDevicePtr local)
+EventAutoDevProbe(InputInfoPtr pInfo, const char *device)
{
/* We are trying to find the right eventX device or fall back to
the psaux protocol and the given device from XF86Config */
int i;
- Bool have_evdev;
- int noent_cnt;
- const int max_skip = 10;
- int wait = 0;
- const int max_wait = 2000;
-
- while (wait <= max_wait) {
- have_evdev = FALSE;
- noent_cnt = 0;
- for (i = 0; ; i++) {
- char fname[64];
- int fd = -1;
- Bool is_touchpad;
-
- sprintf(fname, "%s/%s%d", DEV_INPUT_EVENT, EVENT_DEV_NAME, i);
- SYSCALL(fd = open(fname, O_RDONLY));
- if (fd < 0) {
- if (errno == ENOENT) {
- if (++noent_cnt >= max_skip)
- break;
- else
- continue;
- } else {
- continue;
- }
- }
- noent_cnt = 0;
- have_evdev = TRUE;
- is_touchpad = event_query_is_touchpad(fd);
- if (is_touchpad) {
- xf86Msg(X_PROBED, "%s auto-dev sets device to %s (waited %d msec)\n",
- local->name, fname, wait);
- xf86ReplaceStrOption(local->options, "Device", fname);
- event_query_abs_params(local, fd);
- SYSCALL(close(fd));
- return TRUE;
- }
- SYSCALL(close(fd));
+ Bool touchpad_found = FALSE;
+ struct dirent **namelist;
+
+ if (device) {
+ int fd = -1;
+
+ if (pInfo->flags & XI86_SERVER_FD)
+ fd = pInfo->fd;
+ else
+ SYSCALL(fd = open(device, O_RDONLY));
+
+ if (fd >= 0) {
+ int rc;
+ struct libevdev *evdev;
+
+ rc = libevdev_new_from_fd(fd, &evdev);
+ if (rc >= 0) {
+ touchpad_found = event_query_is_touchpad(evdev);
+ libevdev_free(evdev);
+ }
+
+ if (!(pInfo->flags & XI86_SERVER_FD))
+ SYSCALL(close(fd));
+ }
+
+ /* if a device is set and not a touchpad (or already grabbed),
+ * we must return FALSE. Otherwise, we'll add a device that
+ * wasn't requested for and repeat
+ * f5687a6741a19ef3081e7fd83ac55f6df8bcd5c2. */
+ return touchpad_found;
}
- ErrorF("%s waiting 100 msec to become devices ready\n", local->name);
- usleep(100*1000);
- wait += 100;
- ErrorF("%s waiting time total: %d\n", local->name, wait);
+
+ i = scandir(DEV_INPUT_EVENT, &namelist, EventDevOnly, alphasort);
+ if (i < 0) {
+ xf86IDrvMsg(pInfo, X_ERROR, "Couldn't open %s\n", DEV_INPUT_EVENT);
+ return FALSE;
}
- ErrorF("%s no synaptics event device found (checked %d nodes)\n",
- local->name, i + 1);
- if (i <= max_skip)
- ErrorF("%s The /dev/input/event* device nodes seem to be missing\n",
- local->name);
- if (i > max_skip && !have_evdev)
- ErrorF("%s The evdev kernel module seems to be missing\n", local->name);
- return FALSE;
+ else if (i == 0) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "The /dev/input/event* device nodes seem to be missing\n");
+ free(namelist);
+ return FALSE;
+ }
+
+ while (i--) {
+ char fname[64];
+ int fd = -1;
+
+ if (!touchpad_found) {
+ int rc;
+ struct libevdev *evdev;
+
+ sprintf(fname, "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
+ SYSCALL(fd = open(fname, O_RDONLY));
+ if (fd < 0)
+ continue;
+
+ rc = libevdev_new_from_fd(fd, &evdev);
+ if (rc >= 0) {
+ touchpad_found = event_query_is_touchpad(evdev);
+ libevdev_free(evdev);
+ if (touchpad_found) {
+ xf86IDrvMsg(pInfo, X_PROBED, "auto-dev sets device to %s\n",
+ fname);
+ pInfo->options = xf86ReplaceStrOption(pInfo->options,
+ "Device",
+ fname);
+ }
+ }
+ SYSCALL(close(fd));
+ }
+ free(namelist[i]);
+ }
+
+ free(namelist);
+
+ if (!touchpad_found) {
+ xf86IDrvMsg(pInfo, X_ERROR, "no synaptics event device found\n");
+ return FALSE;
+ }
+
+ return TRUE;
}
struct SynapticsProtocolOperations event_proto_operations = {
@@ -330,7 +1079,6 @@ struct SynapticsProtocolOperations event_proto_operations = {
EventDeviceOffHook,
EventQueryHardware,
EventReadHwState,
- EventAutoDevProbe
+ EventAutoDevProbe,
+ EventReadDevDimensions
};
-
-#endif
diff --git a/src/eventcomm.h b/src/eventcomm.h
index 93bf34d..4cd283d 100644
--- a/src/eventcomm.h
+++ b/src/eventcomm.h
@@ -1,32 +1,57 @@
/*
- * Copyright 2004 Peter Osterlund <petero2@telia.com>
+ * Copyright © 2004 Peter Osterlund
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * 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.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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 Osterlund (petero2@telia.com)
*/
+
#ifndef _EVENTCOMM_H_
#define _EVENTCOMM_H_
-#ifdef __LINUX
+#include <xorg-server.h>
#include <linux/input.h>
+#include <linux/version.h>
+#include <xf86Xinput.h>
+#include "synproto.h"
+
+#ifndef input_event_sec
+#define input_event_sec time.tv_sec
+#endif
+
+#ifndef input_event_usec
+#define input_event_usec time.tv_usec
+#endif
/* for auto-dev: */
#define DEV_INPUT_EVENT "/dev/input"
#define EVENT_DEV_NAME "event"
-#endif
+struct eventcomm_proto_data;
+
+extern struct eventcomm_proto_data *EventProtoDataAlloc(int fd);
+
+extern Bool
+EventReadHwState(InputInfoPtr pInfo,
+ struct CommData *comm, struct SynapticsHwState *hwRet);
-#endif /* _EVENTCOMM_H_ */
+#endif /* _EVENTCOMM_H_ */
diff --git a/src/properties.c b/src/properties.c
new file mode 100644
index 0000000..c210086
--- /dev/null
+++ b/src/properties.c
@@ -0,0 +1,833 @@
+/*
+ * Copyright © 2008-2012 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+#include "xf86Module.h"
+
+#include <X11/Xatom.h>
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+
+#include "synapticsstr.h"
+#include "synaptics-properties.h"
+
+#ifndef XATOM_FLOAT
+#define XATOM_FLOAT "FLOAT"
+#endif
+
+#ifndef XI_PROP_PRODUCT_ID
+#define XI_PROP_PRODUCT_ID "Device Product ID"
+#endif
+
+#ifndef XI_PROP_DEVICE_NODE
+#define XI_PROP_DEVICE_NODE "Device Node"
+#endif
+
+static Atom float_type;
+
+Atom prop_edges = 0;
+Atom prop_finger = 0;
+Atom prop_tap_time = 0;
+Atom prop_tap_move = 0;
+Atom prop_tap_durations = 0;
+Atom prop_clickpad = 0;
+Atom prop_middle_timeout = 0;
+Atom prop_twofinger_pressure = 0;
+Atom prop_twofinger_width = 0;
+Atom prop_scrolldist = 0;
+Atom prop_scrolledge = 0;
+Atom prop_scrolltwofinger = 0;
+Atom prop_speed = 0;
+Atom prop_edgemotion_pressure = 0;
+Atom prop_edgemotion_speed = 0;
+Atom prop_edgemotion_always = 0;
+Atom prop_buttonscroll = 0;
+Atom prop_buttonscroll_repeat = 0;
+Atom prop_buttonscroll_time = 0;
+Atom prop_off = 0;
+Atom prop_lockdrags = 0;
+Atom prop_lockdrags_time = 0;
+Atom prop_tapaction = 0;
+Atom prop_clickaction = 0;
+Atom prop_circscroll = 0;
+Atom prop_circscroll_dist = 0;
+Atom prop_circscroll_trigger = 0;
+Atom prop_circpad = 0;
+Atom prop_palm = 0;
+Atom prop_palm_dim = 0;
+Atom prop_coastspeed = 0;
+Atom prop_pressuremotion = 0;
+Atom prop_pressuremotion_factor = 0;
+Atom prop_grab = 0;
+Atom prop_gestures = 0;
+Atom prop_capabilities = 0;
+Atom prop_resolution = 0;
+Atom prop_area = 0;
+Atom prop_softbutton_areas = 0;
+Atom prop_secondary_softbutton_areas = 0;
+Atom prop_noise_cancellation = 0;
+Atom prop_product_id = 0;
+Atom prop_device_node = 0;
+
+static Atom
+InitTypedAtom(DeviceIntPtr dev, const char *name, Atom type, int format,
+ int nvalues, int *values)
+{
+ int i;
+ Atom atom;
+ uint8_t val_8[9]; /* we never have more than 9 values in an atom */
+ uint16_t val_16[9];
+ uint32_t val_32[9];
+ pointer converted;
+
+ for (i = 0; i < nvalues; i++) {
+ switch (format) {
+ case 8:
+ val_8[i] = values[i];
+ break;
+ case 16:
+ val_16[i] = values[i];
+ break;
+ case 32:
+ val_32[i] = values[i];
+ break;
+ }
+ }
+
+ switch (format) {
+ case 8:
+ converted = val_8;
+ break;
+ case 16:
+ converted = val_16;
+ break;
+ case 32:
+ default:
+ converted = val_32;
+ break;
+ }
+
+ atom = MakeAtom(name, strlen(name), TRUE);
+ XIChangeDeviceProperty(dev, atom, type, format, PropModeReplace, nvalues,
+ converted, FALSE);
+ XISetDevicePropertyDeletable(dev, atom, FALSE);
+ return atom;
+}
+
+static Atom
+InitAtom(DeviceIntPtr dev, const char *name, int format,
+ int nvalues, int *values)
+{
+ return InitTypedAtom(dev, name, XA_INTEGER, format, nvalues, values);
+}
+
+static Atom
+InitFloatAtom(DeviceIntPtr dev, const char *name, int nvalues, float *values)
+{
+ Atom atom;
+
+ atom = MakeAtom(name, strlen(name), TRUE);
+ XIChangeDeviceProperty(dev, atom, float_type, 32, PropModeReplace,
+ nvalues, values, FALSE);
+ XISetDevicePropertyDeletable(dev, atom, FALSE);
+ return atom;
+}
+
+static void
+InitSoftButtonProperty(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ SynapticsParameters *para = &priv->synpara;
+ int values[8];
+
+ values[0] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][LEFT];
+ values[1] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][RIGHT];
+ values[2] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][TOP];
+ values[3] = para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA][BOTTOM];
+ values[4] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][LEFT];
+ values[5] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][RIGHT];
+ values[6] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][TOP];
+ values[7] = para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA][BOTTOM];
+ prop_softbutton_areas =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 8, values);
+
+ if (!para->has_secondary_buttons)
+ return;
+
+ values[0] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][LEFT];
+ values[1] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][RIGHT];
+ values[2] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][TOP];
+ values[3] = para->softbutton_areas[TOP_RIGHT_BUTTON_AREA][BOTTOM];
+ values[4] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][LEFT];
+ values[5] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][RIGHT];
+ values[6] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][TOP];
+ values[7] = para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA][BOTTOM];
+
+ if (values[0] || values[1] || values[2] || values[4] ||
+ values[5] || values[6] || values[7])
+ prop_secondary_softbutton_areas =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_SECONDARY_SOFTBUTTON_AREAS, 32, 8, values);
+}
+
+void
+InitDeviceProperties(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ SynapticsParameters *para = &priv->synpara;
+ int values[9]; /* we never have more than 9 values in an atom */
+ float fvalues[4]; /* never have more than 4 float values */
+
+ float_type = XIGetKnownProperty(XATOM_FLOAT);
+ if (!float_type) {
+ float_type = MakeAtom(XATOM_FLOAT, strlen(XATOM_FLOAT), TRUE);
+ if (!float_type) {
+ xf86IDrvMsg(pInfo, X_ERROR, "Failed to init float atom. "
+ "Disabling property support.\n");
+ return;
+ }
+ }
+
+ values[0] = para->left_edge;
+ values[1] = para->right_edge;
+ values[2] = para->top_edge;
+ values[3] = para->bottom_edge;
+
+ prop_edges = InitAtom(pInfo->dev, SYNAPTICS_PROP_EDGES, 32, 4, values);
+
+ values[0] = para->finger_low;
+ values[1] = para->finger_high;
+ values[2] = 0;
+
+ prop_finger = InitAtom(pInfo->dev, SYNAPTICS_PROP_FINGER, 32, 3, values);
+ prop_tap_time =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_TAP_TIME, 32, 1, &para->tap_time);
+ prop_tap_move =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_TAP_MOVE, 32, 1, &para->tap_move);
+
+ values[0] = para->single_tap_timeout;
+ values[1] = para->tap_time_2;
+ values[2] = para->click_time;
+
+ prop_tap_durations =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_TAP_DURATIONS, 32, 3, values);
+ prop_clickpad =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_CLICKPAD, 8, 1, &para->clickpad);
+ prop_middle_timeout =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_MIDDLE_TIMEOUT, 32, 1,
+ &para->emulate_mid_button_time);
+ prop_twofinger_pressure =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_TWOFINGER_PRESSURE, 32, 1,
+ &para->emulate_twofinger_z);
+ prop_twofinger_width =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_TWOFINGER_WIDTH, 32, 1,
+ &para->emulate_twofinger_w);
+
+ values[0] = para->scroll_dist_vert;
+ values[1] = para->scroll_dist_horiz;
+ prop_scrolldist =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 2, values);
+
+ values[0] = para->scroll_edge_vert;
+ values[1] = para->scroll_edge_horiz;
+ values[2] = para->scroll_edge_corner;
+ prop_scrolledge =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_SCROLL_EDGE, 8, 3, values);
+ values[0] = para->scroll_twofinger_vert;
+ values[1] = para->scroll_twofinger_horiz;
+ prop_scrolltwofinger =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 2, values);
+
+ fvalues[0] = para->min_speed;
+ fvalues[1] = para->max_speed;
+ fvalues[2] = para->accl;
+ fvalues[3] = 0;
+ prop_speed = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_SPEED, 4, fvalues);
+
+ if (priv->has_scrollbuttons) {
+ values[0] = para->updown_button_scrolling;
+ values[1] = para->leftright_button_scrolling;
+ prop_buttonscroll =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 2, values);
+
+ values[0] = para->updown_button_repeat;
+ values[1] = para->leftright_button_repeat;
+ prop_buttonscroll_repeat =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT, 8, 2,
+ values);
+ prop_buttonscroll_time =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_BUTTONSCROLLING_TIME, 32, 1,
+ &para->scroll_button_repeat);
+ }
+
+ prop_off =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_OFF, 8, 1, &para->touchpad_off);
+ prop_lockdrags =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_LOCKED_DRAGS, 8, 1,
+ &para->locked_drags);
+ prop_lockdrags_time =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT, 32, 1,
+ &para->locked_drag_time);
+
+ memcpy(values, para->tap_action, MAX_TAP * sizeof(int));
+ prop_tapaction =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_TAP_ACTION, 8, MAX_TAP, values);
+
+ memcpy(values, para->click_action, MAX_CLICK * sizeof(int));
+ prop_clickaction =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_CLICK_ACTION, 8, MAX_CLICK, values);
+
+ prop_circscroll =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_CIRCULAR_SCROLLING, 8, 1,
+ &para->circular_scrolling);
+
+ fvalues[0] = para->scroll_dist_circ;
+ prop_circscroll_dist =
+ InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_CIRCULAR_SCROLLING_DIST, 1,
+ fvalues);
+
+ prop_circscroll_trigger =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_CIRCULAR_SCROLLING_TRIGGER, 8, 1,
+ &para->circular_trigger);
+ prop_circpad =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_CIRCULAR_PAD, 8, 1,
+ &para->circular_pad);
+ prop_palm =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_PALM_DETECT, 8, 1,
+ &para->palm_detect);
+
+ values[0] = para->palm_min_width;
+ values[1] = para->palm_min_z;
+
+ prop_palm_dim =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 2, values);
+
+ fvalues[0] = para->coasting_speed;
+ fvalues[1] = para->coasting_friction;
+ prop_coastspeed =
+ InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_COASTING_SPEED, 2, fvalues);
+
+ values[0] = para->press_motion_min_z;
+ values[1] = para->press_motion_max_z;
+ prop_pressuremotion =
+ InitTypedAtom(pInfo->dev, SYNAPTICS_PROP_PRESSURE_MOTION, XA_CARDINAL,
+ 32, 2, values);
+
+ fvalues[0] = para->press_motion_min_factor;
+ fvalues[1] = para->press_motion_max_factor;
+
+ prop_pressuremotion_factor =
+ InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 2,
+ fvalues);
+
+ prop_grab =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_GRAB, 8, 1,
+ &para->grab_event_device);
+
+ values[0] = para->tap_and_drag_gesture;
+ prop_gestures = InitAtom(pInfo->dev, SYNAPTICS_PROP_GESTURES, 8, 1, values);
+
+ values[0] = priv->has_left;
+ values[1] = priv->has_middle;
+ values[2] = priv->has_right;
+ values[3] = priv->has_double;
+ values[4] = priv->has_triple;
+ values[5] = priv->has_pressure;
+ values[6] = priv->has_width;
+ prop_capabilities =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_CAPABILITIES, 8, 7, values);
+
+ values[0] = para->resolution_vert;
+ values[1] = para->resolution_horiz;
+ prop_resolution =
+ InitAtom(pInfo->dev, SYNAPTICS_PROP_RESOLUTION, 32, 2, values);
+
+ values[0] = para->area_left_edge;
+ values[1] = para->area_right_edge;
+ values[2] = para->area_top_edge;
+ values[3] = para->area_bottom_edge;
+ prop_area = InitAtom(pInfo->dev, SYNAPTICS_PROP_AREA, 32, 4, values);
+
+ if (para->clickpad)
+ InitSoftButtonProperty(pInfo);
+
+ values[0] = para->hyst_x;
+ values[1] = para->hyst_y;
+ prop_noise_cancellation = InitAtom(pInfo->dev,
+ SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 2,
+ values);
+
+ /* only init product_id property if we actually know them */
+ if (priv->id_vendor || priv->id_product) {
+ values[0] = priv->id_vendor;
+ values[1] = priv->id_product;
+ prop_product_id =
+ InitAtom(pInfo->dev, XI_PROP_PRODUCT_ID, 32, 2, values);
+ }
+
+ if (priv->device) {
+ prop_device_node =
+ MakeAtom(XI_PROP_DEVICE_NODE, strlen(XI_PROP_DEVICE_NODE), TRUE);
+ XIChangeDeviceProperty(pInfo->dev, prop_device_node, XA_STRING, 8,
+ PropModeReplace, strlen(priv->device),
+ (pointer) priv->device, FALSE);
+ XISetDevicePropertyDeletable(pInfo->dev, prop_device_node, FALSE);
+ }
+
+}
+
+int
+SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
+ BOOL checkonly)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ SynapticsParameters *para = &priv->synpara;
+ SynapticsParameters tmp;
+
+ /* If checkonly is set, no parameters may be changed. So just let the code
+ * change temporary variables and forget about it. */
+ if (checkonly) {
+ tmp = *para;
+ para = &tmp;
+ }
+
+ if (property == prop_edges) {
+ INT32 *edges;
+
+ if (prop->size != 4 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ edges = (INT32 *) prop->data;
+ if (edges[0] > edges[1] || edges[2] > edges[3])
+ return BadValue;
+
+ para->left_edge = edges[0];
+ para->right_edge = edges[1];
+ para->top_edge = edges[2];
+ para->bottom_edge = edges[3];
+
+ }
+ else if (property == prop_finger) {
+ INT32 *finger;
+
+ if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ finger = (INT32 *) prop->data;
+ if (finger[0] > finger[1])
+ return BadValue;
+
+ para->finger_low = finger[0];
+ para->finger_high = finger[1];
+ }
+ else if (property == prop_tap_time) {
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->tap_time = *(INT32 *) prop->data;
+
+ }
+ else if (property == prop_tap_move) {
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->tap_move = *(INT32 *) prop->data;
+ }
+ else if (property == prop_tap_durations) {
+ INT32 *timeouts;
+
+ if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ timeouts = (INT32 *) prop->data;
+
+ para->single_tap_timeout = timeouts[0];
+ para->tap_time_2 = timeouts[1];
+ para->click_time = timeouts[2];
+ }
+ else if (property == prop_clickpad) {
+ BOOL value;
+
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ value = *(BOOL *) prop->data;
+ if (!para->clickpad && value && !prop_softbutton_areas)
+ InitSoftButtonProperty(pInfo);
+ else if (para->clickpad && !value && prop_softbutton_areas) {
+ XIDeleteDeviceProperty(dev, prop_softbutton_areas, FALSE);
+ prop_softbutton_areas = 0;
+ }
+
+ para->clickpad = *(BOOL *) prop->data;
+ }
+ else if (property == prop_middle_timeout) {
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->emulate_mid_button_time = *(INT32 *) prop->data;
+ }
+ else if (property == prop_twofinger_pressure) {
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->emulate_twofinger_z = *(INT32 *) prop->data;
+ }
+ else if (property == prop_twofinger_width) {
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->emulate_twofinger_w = *(INT32 *) prop->data;
+ }
+ else if (property == prop_scrolldist) {
+ INT32 *dist;
+
+ if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ dist = (INT32 *) prop->data;
+ if (dist[0] == 0 || dist[1] == 0)
+ return BadValue;
+
+ if (para->scroll_dist_vert != dist[0]) {
+ para->scroll_dist_vert = dist[0];
+ SetScrollValuator(dev, priv->scroll_axis_vert, SCROLL_TYPE_VERTICAL,
+ para->scroll_dist_vert, 0);
+ }
+ if (para->scroll_dist_horiz != dist[1]) {
+ para->scroll_dist_horiz = dist[1];
+ SetScrollValuator(dev, priv->scroll_axis_horiz,
+ SCROLL_TYPE_HORIZONTAL, para->scroll_dist_horiz,
+ 0);
+ }
+ }
+ else if (property == prop_scrolledge) {
+ CARD8 *edge;
+
+ if (prop->size != 3 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ edge = (BOOL *) prop->data;
+ para->scroll_edge_vert = edge[0];
+ para->scroll_edge_horiz = edge[1];
+ para->scroll_edge_corner = edge[2];
+ }
+ else if (property == prop_scrolltwofinger) {
+ CARD8 *twofinger;
+
+ if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ twofinger = (BOOL *) prop->data;
+ para->scroll_twofinger_vert = twofinger[0];
+ para->scroll_twofinger_horiz = twofinger[1];
+ }
+ else if (property == prop_speed) {
+ float *speed;
+
+ if (prop->size != 4 || prop->format != 32 || prop->type != float_type)
+ return BadMatch;
+
+ speed = (float *) prop->data;
+ para->min_speed = speed[0];
+ para->max_speed = speed[1];
+ para->accl = speed[2];
+ }
+ else if (property == prop_buttonscroll) {
+ BOOL *scroll;
+
+ if (!priv->has_scrollbuttons)
+ return BadMatch;
+
+ if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ scroll = (BOOL *) prop->data;
+ para->updown_button_scrolling = scroll[0];
+ para->leftright_button_scrolling = scroll[1];
+
+ }
+ else if (property == prop_buttonscroll_repeat) {
+ BOOL *repeat;
+
+ if (!priv->has_scrollbuttons)
+ return BadMatch;
+
+ if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ repeat = (BOOL *) prop->data;
+ para->updown_button_repeat = repeat[0];
+ para->leftright_button_repeat = repeat[1];
+ }
+ else if (property == prop_buttonscroll_time) {
+ if (!priv->has_scrollbuttons)
+ return BadMatch;
+
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->scroll_button_repeat = *(INT32 *) prop->data;
+
+ }
+ else if (property == prop_off) {
+ CARD8 off;
+
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ off = *(CARD8 *) prop->data;
+
+ if (off > 2)
+ return BadValue;
+
+ para->touchpad_off = off;
+ }
+ else if (property == prop_gestures) {
+ BOOL *gestures;
+
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ gestures = (BOOL *) prop->data;
+ para->tap_and_drag_gesture = gestures[0];
+ }
+ else if (property == prop_lockdrags) {
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->locked_drags = *(BOOL *) prop->data;
+ }
+ else if (property == prop_lockdrags_time) {
+ if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->locked_drag_time = *(INT32 *) prop->data;
+ }
+ else if (property == prop_tapaction) {
+ int i;
+ CARD8 *action;
+
+ if (prop->size > MAX_TAP || prop->format != 8 ||
+ prop->type != XA_INTEGER)
+ return BadMatch;
+
+ action = (CARD8 *) prop->data;
+
+ for (i = 0; i < MAX_TAP; i++)
+ para->tap_action[i] = action[i];
+ }
+ else if (property == prop_clickaction) {
+ int i;
+ CARD8 *action;
+
+ if (prop->size > MAX_CLICK || prop->format != 8 ||
+ prop->type != XA_INTEGER)
+ return BadMatch;
+
+ action = (CARD8 *) prop->data;
+
+ for (i = 0; i < MAX_CLICK; i++)
+ para->click_action[i] = action[i];
+ }
+ else if (property == prop_circscroll) {
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->circular_scrolling = *(BOOL *) prop->data;
+
+ }
+ else if (property == prop_circscroll_dist) {
+ float circdist;
+
+ if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
+ return BadMatch;
+
+ circdist = *(float *) prop->data;
+ if (circdist == 0)
+ return BadValue;
+
+ para->scroll_dist_circ = circdist;
+ }
+ else if (property == prop_circscroll_trigger) {
+ int trigger;
+
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ trigger = *(CARD8 *) prop->data;
+ if (trigger > 8)
+ return BadValue;
+
+ para->circular_trigger = trigger;
+
+ }
+ else if (property == prop_circpad) {
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->circular_pad = *(BOOL *) prop->data;
+ }
+ else if (property == prop_palm) {
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->palm_detect = *(BOOL *) prop->data;
+ }
+ else if (property == prop_palm_dim) {
+ INT32 *dim;
+
+ if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ dim = (INT32 *) prop->data;
+
+ para->palm_min_width = dim[0];
+ para->palm_min_z = dim[1];
+ }
+ else if (property == prop_coastspeed) {
+ float *coast_speeds;
+
+ if (prop->size != 2 || prop->format != 32 || prop->type != float_type)
+ return BadMatch;
+
+ coast_speeds = (float *) prop->data;
+ para->coasting_speed = coast_speeds[0];
+ para->coasting_friction = coast_speeds[1];
+ }
+ else if (property == prop_pressuremotion) {
+ CARD32 *press;
+
+ if (prop->size != 2 || prop->format != 32 || prop->type != XA_CARDINAL)
+ return BadMatch;
+
+ press = (CARD32 *) prop->data;
+ if (press[0] > press[1])
+ return BadValue;
+
+ para->press_motion_min_z = press[0];
+ para->press_motion_max_z = press[1];
+ }
+ else if (property == prop_pressuremotion_factor) {
+ float *press;
+
+ if (prop->size != 2 || prop->format != 32 || prop->type != float_type)
+ return BadMatch;
+
+ press = (float *) prop->data;
+ if (press[0] > press[1])
+ return BadValue;
+
+ para->press_motion_min_factor = press[0];
+ para->press_motion_max_factor = press[1];
+ }
+ else if (property == prop_grab) {
+ if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ para->grab_event_device = *(BOOL *) prop->data;
+ }
+ else if (property == prop_capabilities) {
+ /* read-only */
+ return BadValue;
+ }
+ else if (property == prop_resolution) {
+ /* read-only */
+ return BadValue;
+ }
+ else if (property == prop_area) {
+ INT32 *area;
+
+ if (prop->size != 4 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ area = (INT32 *) prop->data;
+ if ((((area[0] != 0) && (area[1] != 0)) && (area[0] > area[1])) ||
+ (((area[2] != 0) && (area[3] != 0)) && (area[2] > area[3])))
+ return BadValue;
+
+ para->area_left_edge = area[0];
+ para->area_right_edge = area[1];
+ para->area_top_edge = area[2];
+ para->area_bottom_edge = area[3];
+ }
+ else if (property == prop_softbutton_areas) {
+ int *areas;
+
+ if (prop->size != 8 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ areas = (int *) prop->data;
+ if (!SynapticsIsSoftButtonAreasValid(areas))
+ return BadValue;
+
+ memcpy(para->softbutton_areas[BOTTOM_RIGHT_BUTTON_AREA], areas, 4 * sizeof(int));
+ memcpy(para->softbutton_areas[BOTTOM_MIDDLE_BUTTON_AREA], areas + 4, 4 * sizeof(int));
+ }
+ else if (property == prop_secondary_softbutton_areas) {
+ int *areas;
+
+ if (prop->size != 8 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ areas = (int *) prop->data;
+ if (!SynapticsIsSoftButtonAreasValid(areas))
+ return BadValue;
+
+ memcpy(para->softbutton_areas[TOP_RIGHT_BUTTON_AREA], areas, 4 * sizeof(int));
+ memcpy(para->softbutton_areas[TOP_MIDDLE_BUTTON_AREA], areas + 4, 4 * sizeof(int));
+ }
+ else if (property == prop_noise_cancellation) {
+ INT32 *hyst;
+
+ if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
+ return BadMatch;
+
+ hyst = (INT32 *) prop->data;
+ if (hyst[0] < 0 || hyst[1] < 0)
+ return BadValue;
+ para->hyst_x = hyst[0];
+ para->hyst_y = hyst[1];
+ }
+ else if (property == prop_product_id || property == prop_device_node)
+ return BadValue; /* read-only */
+ else { /* unknown property */
+ if (strcmp(SYNAPTICS_PROP_SOFTBUTTON_AREAS, NameForAtom(property)) == 0)
+ {
+ prop_softbutton_areas = property;
+ if (SetProperty(dev, property, prop, checkonly) != Success)
+ prop_softbutton_areas = 0;
+ else if (!checkonly)
+ XISetDevicePropertyDeletable(dev, property, FALSE);
+ }
+ }
+
+ return Success;
+}
diff --git a/src/ps2comm.c b/src/ps2comm.c
index c805785..887e2e0 100644
--- a/src/ps2comm.c
+++ b/src/ps2comm.c
@@ -1,40 +1,59 @@
-/* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
- *
- * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
- * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
- * code für the special synaptics commands (from the tpconfig-source)
- *
- * Synaptics Passthrough Support
- * Copyright (c) 2002 Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
- * adapted to version 0.12.1
- * Copyright (c) 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+/*
+ * Copyright © 1997 C. Scott Ananian
+ * Copyright © 1998-2000 Bruce Kalk
+ * Copyright © 2001 Stefan Gmeiner
+ * Copyright © 2002 Linuxcare Inc. David Kennedy
+ * Copyright © 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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:
+ * Stefan Gmeiner (riddlebox@freesurf.ch)
+ * C. Scott Ananian (cananian@alumni.priceton.edu)
+ * Bruce Kalk (kall@compass.com)
+ * Linuxcare Inc. David Kennedy (dkennedy@linuxcare.com)
+ * Fred Hucht (fred@thp.Uni-Duisburg.de)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "ps2comm.h"
+#include <xorg-server.h>
#include "synproto.h"
-#include "synaptics.h"
+#include "synapticsstr.h"
+#include "ps2comm.h"
#include <xf86.h>
-#define MAX_UNSYNC_PACKETS 10 /* i.e. 10 to 60 bytes */
+#define MAX_UNSYNC_PACKETS 10 /* i.e. 10 to 60 bytes */
+/*
+ * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
+ * section 2.3.2, which says that they should be valid regardless of the
+ * actual size of the sensor.
+ */
+#define XMIN_NOMINAL 1472
+#define XMAX_NOMINAL 5472
+#define YMIN_NOMINAL 1408
+#define YMAX_NOMINAL 4448
+
+#define XMAX_VALID 6143
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
@@ -56,16 +75,10 @@
#define PS2_RES_RESOLUTION(r) (((r) >> 8) & 0x03)
#define PS2_RES_SAMPLE_RATE(r) ((r) & 0xff)
-/* #define DEBUG */
-
#ifdef DEBUG
-#define PS2DBG(x) (x)
+#define PS2DBG(...) ErrorF(__VA_ARGS__)
#else
-#define PS2DBG(x)
-#endif
-
-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 1
-#define DBG(a,b)
+#define PS2DBG(...)
#endif
/*****************************************************************************
@@ -77,17 +90,17 @@
* Read a byte from the ps/2 port
*/
static Bool
-ps2_getbyte(int fd, byte *b)
+ps2_getbyte(int fd, byte * b)
{
if (xf86WaitForInput(fd, 50000) > 0) {
- if (xf86ReadSerial(fd, b, 1) != 1) {
- PS2DBG(ErrorF("ps2_getbyte: No byte read\n"));
- return FALSE;
- }
- PS2DBG(ErrorF("ps2_getbyte: byte %02X read\n", *b));
- return TRUE;
+ if (xf86ReadSerial(fd, b, 1) != 1) {
+ PS2DBG("ps2_getbyte: No byte read\n");
+ return FALSE;
+ }
+ PS2DBG("ps2_getbyte: byte %02X read\n", *b);
+ return TRUE;
}
- PS2DBG(ErrorF("ps2_getbyte: timeout xf86WaitForInput\n"));
+ PS2DBG("ps2_getbyte: timeout xf86WaitForInput\n");
return FALSE;
}
@@ -100,17 +113,17 @@ ps2_putbyte(int fd, byte b)
byte ack;
if (xf86WriteSerial(fd, &b, 1) != 1) {
- PS2DBG(ErrorF("ps2_putbyte: error xf86WriteSerial\n"));
- return FALSE;
+ PS2DBG("ps2_putbyte: error xf86WriteSerial\n");
+ return FALSE;
}
- PS2DBG(ErrorF("ps2_putbyte: byte %02X send\n", b));
+ PS2DBG("ps2_putbyte: byte %02X send\n", b);
/* wait for an ACK */
if (!ps2_getbyte(fd, &ack)) {
- return FALSE;
+ return FALSE;
}
if (ack != PS2_ACK) {
- PS2DBG(ErrorF("ps2_putbyte: wrong acknowledge 0x%02x\n", ack));
- return FALSE;
+ PS2DBG("ps2_putbyte: wrong acknowledge 0x%02x\n", ack);
+ return FALSE;
}
return TRUE;
}
@@ -128,14 +141,14 @@ ps2_special_cmd(int fd, byte cmd)
/* initialize with 'inert' command */
if (!ps2_putbyte(fd, PS2_CMD_SET_SCALING_1_1))
- return FALSE;
+ return FALSE;
/* send 4x 2-bits with set resolution command */
for (i = 0; i < 4; i++) {
- if (!ps2_putbyte(fd, PS2_CMD_SET_RESOLUTION) ||
- !ps2_putbyte(fd, (cmd >> 6) & 0x3))
- return FALSE;
- cmd <<= 2;
+ if (!ps2_putbyte(fd, PS2_CMD_SET_RESOLUTION) ||
+ !ps2_putbyte(fd, (cmd >> 6) & 0x3))
+ return FALSE;
+ cmd <<= 2;
}
return TRUE;
}
@@ -146,64 +159,8 @@ ps2_special_cmd(int fd, byte cmd)
static Bool
ps2_send_cmd(int fd, byte c)
{
- PS2DBG(ErrorF("send command: 0x%02X\n", c));
- return (ps2_special_cmd(fd, c) &&
- ps2_putbyte(fd, PS2_CMD_STATUS_REQUEST));
-}
-
-/*****************************************************************************
- * Synaptics passthrough functions
- ****************************************************************************/
-
-static Bool
-ps2_getbyte_passthrough(int fd, byte *response)
-{
- byte ack;
- int timeout_count;
-#define MAX_RETRY_COUNT 30
-
- /* Getting a response back through the passthrough could take some time.
- * Spin a little for the first byte */
- for (timeout_count = 0;
- !ps2_getbyte(fd, &ack) && (timeout_count <= MAX_RETRY_COUNT);
- timeout_count++)
- ;
- /* Do some sanity checking */
- if ((ack & 0xfc) != 0x84) {
- PS2DBG(ErrorF("ps2_getbyte_passthrough: expected 0x84 and got: %02x\n",
- ack & 0xfc));
- return FALSE;
- }
-
- ps2_getbyte(fd, response);
- ps2_getbyte(fd, &ack);
- ps2_getbyte(fd, &ack);
- if ((ack & 0xcc) != 0xc4) {
- PS2DBG(ErrorF("ps2_getbyte_passthrough: expected 0xc4 and got: %02x\n",
- ack & 0xcc));
- return FALSE;
- }
- ps2_getbyte(fd, &ack);
- ps2_getbyte(fd, &ack);
-
- return TRUE;
-}
-
-static Bool
-ps2_putbyte_passthrough(int fd, byte c)
-{
- byte ack;
-
- ps2_special_cmd(fd, c);
- ps2_putbyte(fd, 0xF3);
- ps2_putbyte(fd, 0x28);
-
- ps2_getbyte_passthrough(fd, &ack);
- if (ack != PS2_ACK) {
- PS2DBG(ErrorF("ps2_putbyte_passthrough: wrong acknowledge 0x%02x\n", ack));
- return FALSE;
- }
- return TRUE;
+ PS2DBG("send command: 0x%02X\n", c);
+ return (ps2_special_cmd(fd, c) && ps2_putbyte(fd, PS2_CMD_STATUS_REQUEST));
}
/*****************************************************************************
@@ -216,10 +173,9 @@ ps2_putbyte_passthrough(int fd, byte c)
static Bool
ps2_synaptics_set_mode(int fd, byte mode)
{
- PS2DBG(ErrorF("set mode byte to: 0x%02X\n", mode));
+ PS2DBG("set mode byte to: 0x%02X\n", mode);
return (ps2_special_cmd(fd, mode) &&
- ps2_putbyte(fd, PS2_CMD_SET_SAMPLE_RATE) &&
- ps2_putbyte(fd, 0x14));
+ ps2_putbyte(fd, PS2_CMD_SET_SAMPLE_RATE) && ps2_putbyte(fd, 0x14));
}
/*
@@ -231,71 +187,47 @@ ps2_synaptics_reset(int fd)
byte r[2];
xf86FlushInput(fd);
- PS2DBG(ErrorF("Reset the Touchpad...\n"));
+ PS2DBG("Reset the Touchpad...\n");
if (!ps2_putbyte(fd, PS2_CMD_RESET)) {
- PS2DBG(ErrorF("...failed\n"));
- return FALSE;
+ PS2DBG("...failed\n");
+ return FALSE;
}
xf86WaitForInput(fd, 4000000);
if (ps2_getbyte(fd, &r[0]) && ps2_getbyte(fd, &r[1])) {
- if (r[0] == 0xAA && r[1] == 0x00) {
- PS2DBG(ErrorF("...done\n"));
- return TRUE;
- } else {
- PS2DBG(ErrorF("...failed. Wrong reset ack 0x%02x, 0x%02x\n", r[0], r[1]));
- return FALSE;
- }
+ if (r[0] == 0xAA && r[1] == 0x00) {
+ PS2DBG("...done\n");
+ return TRUE;
+ }
+ else {
+ PS2DBG("...failed. Wrong reset ack 0x%02x, 0x%02x\n", r[0], r[1]);
+ return FALSE;
+ }
}
- PS2DBG(ErrorF("...failed\n"));
+ PS2DBG("...failed\n");
return FALSE;
}
-static Bool
-ps2_synaptics_reset_passthrough(int fd)
-{
- byte ack;
-
- /* send reset */
- ps2_putbyte_passthrough(fd, 0xff);
- ps2_getbyte_passthrough(fd, &ack);
- if (ack != 0xaa) {
- PS2DBG(ErrorF("ps2_synaptics_reset_passthrough: ack was %02x not 0xaa\n", ack));
- return FALSE;
- }
- ps2_getbyte_passthrough(fd, &ack);
- if (ack != 0x00) {
- PS2DBG(ErrorF("ps2_synaptics_reset_passthrough: ack was %02x not 0x00\n", ack));
- return FALSE;
- }
-
- /* set defaults, turn on streaming, and enable the mouse */
- return (ps2_putbyte_passthrough(fd, 0xf6) &&
- ps2_putbyte_passthrough(fd, 0xea) &&
- ps2_putbyte_passthrough(fd, 0xf4));
-}
-
/*
* Read the model-id bytes from the touchpad
* see also SYN_MODEL_* macros
*/
static Bool
-ps2_synaptics_model_id(int fd, struct SynapticsHwInfo *synhw)
+ps2_synaptics_model_id(int fd, struct PS2SynapticsHwInfo *synhw)
{
byte mi[3];
- PS2DBG(ErrorF("Read mode id...\n"));
+ PS2DBG("Read mode id...\n");
synhw->model_id = 0;
if (ps2_send_cmd(fd, SYN_QUE_MODEL) &&
- ps2_getbyte(fd, &mi[0]) &&
- ps2_getbyte(fd, &mi[1]) &&
- ps2_getbyte(fd, &mi[2])) {
- synhw->model_id = (mi[0] << 16) | (mi[1] << 8) | mi[2];
- PS2DBG(ErrorF("mode-id %06X\n", synhw->model_id));
- PS2DBG(ErrorF("...done.\n"));
- return TRUE;
+ ps2_getbyte(fd, &mi[0]) &&
+ ps2_getbyte(fd, &mi[1]) && ps2_getbyte(fd, &mi[2])) {
+ synhw->model_id = (mi[0] << 16) | (mi[1] << 8) | mi[2];
+ PS2DBG("model-id %06X\n", synhw->model_id);
+ PS2DBG("...done.\n");
+ return TRUE;
}
- PS2DBG(ErrorF("...failed.\n"));
+ PS2DBG("...failed.\n");
return FALSE;
}
@@ -304,38 +236,37 @@ ps2_synaptics_model_id(int fd, struct SynapticsHwInfo *synhw)
* see also the SYN_CAP_* macros
*/
static Bool
-ps2_synaptics_capability(int fd, struct SynapticsHwInfo *synhw)
+ps2_synaptics_capability(int fd, struct PS2SynapticsHwInfo *synhw)
{
byte cap[3];
- PS2DBG(ErrorF("Read capabilites...\n"));
+ PS2DBG("Read capabilites...\n");
synhw->capabilities = 0;
synhw->ext_cap = 0;
if (ps2_send_cmd(fd, SYN_QUE_CAPABILITIES) &&
- ps2_getbyte(fd, &cap[0]) &&
- ps2_getbyte(fd, &cap[1]) &&
- ps2_getbyte(fd, &cap[2])) {
- synhw->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
- PS2DBG(ErrorF("capabilities %06X\n", synhw->capabilities));
- if (SYN_CAP_VALID(*synhw)) {
- if (SYN_EXT_CAP_REQUESTS(*synhw)) {
- if (ps2_send_cmd(fd, SYN_QUE_EXT_CAPAB) &&
- ps2_getbyte(fd, &cap[0]) &&
- ps2_getbyte(fd, &cap[1]) &&
- ps2_getbyte(fd, &cap[2])) {
- synhw->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
- PS2DBG(ErrorF("ext-capability %06X\n", synhw->ext_cap));
- } else {
- PS2DBG(ErrorF("synaptics says, that it has extended-capabilities, "
- "but I cannot read them."));
- }
- }
- PS2DBG(ErrorF("...done.\n"));
- return TRUE;
- }
+ ps2_getbyte(fd, &cap[0]) &&
+ ps2_getbyte(fd, &cap[1]) && ps2_getbyte(fd, &cap[2])) {
+ synhw->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
+ PS2DBG("capabilities %06X\n", synhw->capabilities);
+ if (SYN_CAP_VALID(synhw)) {
+ if (SYN_EXT_CAP_REQUESTS(synhw)) {
+ if (ps2_send_cmd(fd, SYN_QUE_EXT_CAPAB) &&
+ ps2_getbyte(fd, &cap[0]) &&
+ ps2_getbyte(fd, &cap[1]) && ps2_getbyte(fd, &cap[2])) {
+ synhw->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
+ PS2DBG("ext-capability %06X\n", synhw->ext_cap);
+ }
+ else {
+ PS2DBG("synaptics says, that it has extended-capabilities, "
+ "but I cannot read them.");
+ }
+ }
+ PS2DBG("...done.\n");
+ return TRUE;
+ }
}
- PS2DBG(ErrorF("...failed.\n"));
+ PS2DBG("...failed.\n");
return FALSE;
}
@@ -344,25 +275,24 @@ ps2_synaptics_capability(int fd, struct SynapticsHwInfo *synhw)
* See also the SYN_ID_* macros
*/
static Bool
-ps2_synaptics_identify(int fd, struct SynapticsHwInfo *synhw)
+ps2_synaptics_identify(int fd, struct PS2SynapticsHwInfo *synhw)
{
byte id[3];
- PS2DBG(ErrorF("Identify Touchpad...\n"));
+ PS2DBG("Identify Touchpad...\n");
synhw->identity = 0;
if (ps2_send_cmd(fd, SYN_QUE_IDENTIFY) &&
- ps2_getbyte(fd, &id[0]) &&
- ps2_getbyte(fd, &id[1]) &&
- ps2_getbyte(fd, &id[2])) {
- synhw->identity = (id[0] << 16) | (id[1] << 8) | id[2];
- PS2DBG(ErrorF("ident %06X\n", synhw->identity));
- if (SYN_ID_IS_SYNAPTICS(*synhw)) {
- PS2DBG(ErrorF("...done.\n"));
- return TRUE;
- }
+ ps2_getbyte(fd, &id[0]) &&
+ ps2_getbyte(fd, &id[1]) && ps2_getbyte(fd, &id[2])) {
+ synhw->identity = (id[0] << 16) | (id[1] << 8) | id[2];
+ PS2DBG("ident %06X\n", synhw->identity);
+ if (SYN_ID_IS_SYNAPTICS(synhw)) {
+ PS2DBG("...done.\n");
+ return TRUE;
+ }
}
- PS2DBG(ErrorF("...failed.\n"));
+ PS2DBG("...failed.\n");
return FALSE;
}
@@ -380,124 +310,115 @@ ps2_synaptics_disable_device(int fd)
}
static Bool
-ps2_query_is_synaptics(int fd)
+ps2_query_is_synaptics(InputInfoPtr pInfo, int fd,
+ struct PS2SynapticsHwInfo *synhw)
{
- struct SynapticsHwInfo synhw;
int i;
for (i = 0; i < 3; i++) {
- if (ps2_synaptics_disable_device(fd))
- break;
+ if (ps2_synaptics_disable_device(fd))
+ break;
}
xf86WaitForInput(fd, 20000);
xf86FlushInput(fd);
- if (ps2_synaptics_identify(fd, &synhw)) {
- return TRUE;
- } else {
- ErrorF("Query no Synaptics: %06X\n", synhw.identity);
- return FALSE;
+ if (ps2_synaptics_identify(fd, synhw)) {
+ return TRUE;
+ }
+ else {
+ xf86IDrvMsg(pInfo, X_ERROR, "Query no Synaptics: %06X\n",
+ synhw->identity);
+ return FALSE;
}
}
void
-ps2_print_ident(const struct SynapticsHwInfo *synhw)
+ps2_print_ident(InputInfoPtr pInfo, const struct PS2SynapticsHwInfo *synhw)
{
- xf86Msg(X_PROBED, " Synaptics Touchpad, model: %d\n", SYN_ID_MODEL(*synhw));
- xf86Msg(X_PROBED, " Firmware: %d.%d\n", SYN_ID_MAJOR(*synhw),
- SYN_ID_MINOR(*synhw));
-
- if (SYN_MODEL_ROT180(*synhw))
- xf86Msg(X_PROBED, " 180 degree mounted touchpad\n");
- if (SYN_MODEL_PORTRAIT(*synhw))
- xf86Msg(X_PROBED, " portrait touchpad\n");
- xf86Msg(X_PROBED, " Sensor: %d\n", SYN_MODEL_SENSOR(*synhw));
- if (SYN_MODEL_NEWABS(*synhw))
- xf86Msg(X_PROBED, " new absolute packet format\n");
- if (SYN_MODEL_PEN(*synhw))
- xf86Msg(X_PROBED, " pen detection\n");
-
- if (SYN_CAP_EXTENDED(*synhw)) {
- xf86Msg(X_PROBED, " Touchpad has extended capability bits\n");
- if (SYN_CAP_MULTI_BUTTON_NO(*synhw))
- xf86Msg(X_PROBED, " -> %d multi buttons, i.e. besides standard buttons\n",
- (int)(SYN_CAP_MULTI_BUTTON_NO(*synhw)));
- if (SYN_CAP_MIDDLE_BUTTON(*synhw))
- xf86Msg(X_PROBED, " -> middle button\n");
- if (SYN_CAP_FOUR_BUTTON(*synhw))
- xf86Msg(X_PROBED, " -> four buttons\n");
- if (SYN_CAP_MULTIFINGER(*synhw))
- xf86Msg(X_PROBED, " -> multifinger detection\n");
- if (SYN_CAP_PALMDETECT(*synhw))
- xf86Msg(X_PROBED, " -> palm detection\n");
- if (SYN_CAP_PASSTHROUGH(*synhw))
- xf86Msg(X_PROBED, " -> pass-through port\n");
+ xf86IDrvMsg(pInfo, X_PROBED, " Synaptics Touchpad, model: %d\n",
+ SYN_ID_MODEL(synhw));
+ xf86IDrvMsg(pInfo, X_PROBED, " Firmware: %d.%d\n", SYN_ID_MAJOR(synhw),
+ SYN_ID_MINOR(synhw));
+
+ if (SYN_MODEL_ROT180(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " 180 degree mounted touchpad\n");
+ if (SYN_MODEL_PORTRAIT(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " portrait touchpad\n");
+ xf86IDrvMsg(pInfo, X_PROBED, " Sensor: %d\n", SYN_MODEL_SENSOR(synhw));
+ if (SYN_MODEL_NEWABS(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " new absolute packet format\n");
+ if (SYN_MODEL_PEN(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " pen detection\n");
+
+ if (SYN_CAP_EXTENDED(synhw)) {
+ xf86IDrvMsg(pInfo, X_PROBED,
+ " Touchpad has extended capability bits\n");
+ if (SYN_CAP_MULTI_BUTTON_NO(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED,
+ " -> %d multi buttons, i.e. besides standard buttons\n",
+ (int) (SYN_CAP_MULTI_BUTTON_NO(synhw)));
+ if (SYN_CAP_MIDDLE_BUTTON(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " -> middle button\n");
+ if (SYN_CAP_FOUR_BUTTON(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " -> four buttons\n");
+ if (SYN_CAP_MULTIFINGER(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " -> multifinger detection\n");
+ if (SYN_CAP_PALMDETECT(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " -> palm detection\n");
+ if (SYN_CAP_PASSTHROUGH(synhw))
+ xf86IDrvMsg(pInfo, X_PROBED, " -> pass-through port\n");
}
}
-
-static void
-PS2DeviceOnHook(LocalDevicePtr local, SynapticsSHM* para)
+static Bool
+PS2DeviceOffHook(InputInfoPtr pInfo)
{
-}
+ ps2_synaptics_reset(pInfo->fd);
+ ps2_synaptics_enable_device(pInfo->fd);
-static void
-PS2DeviceOffHook(LocalDevicePtr local)
-{
- ps2_synaptics_reset(local->fd);
- ps2_synaptics_enable_device(local->fd);
+ return TRUE;
}
static Bool
-PS2QueryHardware(LocalDevicePtr local, struct SynapticsHwInfo *synhw)
+PS2QueryHardware(InputInfoPtr pInfo)
{
int mode;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ struct PS2SynapticsHwInfo *synhw;
+
+ if (!priv->proto_data)
+ priv->proto_data = calloc(1, sizeof(struct PS2SynapticsHwInfo));
+ synhw = (struct PS2SynapticsHwInfo *) priv->proto_data;
/* is the synaptics touchpad active? */
- if (!ps2_query_is_synaptics(local->fd))
- return FALSE;
+ if (!ps2_query_is_synaptics(pInfo, pInfo->fd, synhw))
+ return FALSE;
- xf86Msg(X_PROBED, "%s synaptics touchpad found\n", local->name);
+ xf86IDrvMsg(pInfo, X_PROBED, "synaptics touchpad found\n");
- if (!ps2_synaptics_reset(local->fd))
- xf86Msg(X_ERROR, "%s reset failed\n", local->name);
+ if (!ps2_synaptics_reset(pInfo->fd))
+ xf86IDrvMsg(pInfo, X_ERROR, "reset failed\n");
- if (!ps2_synaptics_identify(local->fd, synhw))
- return FALSE;
+ if (!ps2_synaptics_identify(pInfo->fd, synhw))
+ return FALSE;
- if (!ps2_synaptics_model_id(local->fd, synhw))
- return FALSE;
+ if (!ps2_synaptics_model_id(pInfo->fd, synhw))
+ return FALSE;
- if (!ps2_synaptics_capability(local->fd, synhw))
- return FALSE;
+ if (!ps2_synaptics_capability(pInfo->fd, synhw))
+ return FALSE;
mode = SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
- if (SYN_ID_MAJOR(*synhw) >= 4)
- mode |= SYN_BIT_DISABLE_GESTURE;
- if (SYN_CAP_EXTENDED(*synhw))
- mode |= SYN_BIT_W_MODE;
- if (!ps2_synaptics_set_mode(local->fd, mode))
- return FALSE;
-
- /* Check to see if the host mouse supports a guest */
- synhw->hasGuest = FALSE;
- if (SYN_CAP_PASSTHROUGH(*synhw)) {
- synhw->hasGuest = TRUE;
-
- /* Enable the guest mouse. Set it to relative mode, three byte
- * packets */
-
- /* Disable the host to talk to the guest */
- ps2_synaptics_disable_device(local->fd);
- /* Reset it, set defaults, streaming and enable it */
- if (!ps2_synaptics_reset_passthrough(local->fd)) {
- synhw->hasGuest = FALSE;
- }
- }
+ if (SYN_ID_MAJOR(synhw) >= 4)
+ mode |= SYN_BIT_DISABLE_GESTURE;
+ if (SYN_CAP_EXTENDED(synhw))
+ mode |= SYN_BIT_W_MODE;
+ if (!ps2_synaptics_set_mode(pInfo->fd, mode))
+ return FALSE;
- ps2_synaptics_enable_device(local->fd);
+ ps2_synaptics_enable_device(pInfo->fd);
- ps2_print_ident(synhw);
+ ps2_print_ident(pInfo, synhw);
return TRUE;
}
@@ -506,250 +427,246 @@ PS2QueryHardware(LocalDevicePtr local, struct SynapticsHwInfo *synhw)
* Decide if the current packet stored in priv->protoBuf is valid.
*/
static Bool
-ps2_packet_ok(struct SynapticsHwInfo *synhw, struct CommData *comm)
+ps2_packet_ok(struct PS2SynapticsHwInfo *synhw, struct CommData *comm)
{
unsigned char *buf = comm->protoBuf;
- int newabs = SYN_MODEL_NEWABS(*synhw);
+ int newabs = SYN_MODEL_NEWABS(synhw);
if (newabs ? ((buf[0] & 0xC0) != 0x80) : ((buf[0] & 0xC0) != 0xC0)) {
- DBG(4, ErrorF("Synaptics driver lost sync at 1st byte\n"));
- return FALSE;
+ PS2DBG("Synaptics driver lost sync at 1st byte\n");
+ return FALSE;
}
if (!newabs && ((buf[1] & 0x60) != 0x00)) {
- DBG(4, ErrorF("Synaptics driver lost sync at 2nd byte\n"));
- return FALSE;
+ PS2DBG("Synaptics driver lost sync at 2nd byte\n");
+ return FALSE;
}
if ((newabs ? ((buf[3] & 0xC0) != 0xC0) : ((buf[3] & 0xC0) != 0x80))) {
- DBG(4, ErrorF("Synaptics driver lost sync at 4th byte\n"));
- return FALSE;
+ PS2DBG("Synaptics driver lost sync at 4th byte\n");
+ return FALSE;
}
if (!newabs && ((buf[4] & 0x60) != 0x00)) {
- DBG(4, ErrorF("Synaptics driver lost sync at 5th byte\n"));
- return FALSE;
+ PS2DBG("Synaptics driver lost sync at 5th byte\n");
+ return FALSE;
}
return TRUE;
}
static Bool
-ps2_synaptics_get_packet(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
- struct SynapticsProtocolOperations *proto_ops,
- struct CommData *comm)
+ps2_synaptics_get_packet(InputInfoPtr pInfo, struct PS2SynapticsHwInfo *synhw,
+ struct SynapticsProtocolOperations *proto_ops,
+ struct CommData *comm)
{
int count = 0;
int c;
unsigned char u;
while ((c = XisbRead(comm->buffer)) >= 0) {
- u = (unsigned char)c;
-
- /* test if there is a reset sequence received */
- if ((c == 0x00) && (comm->lastByte == 0xAA)) {
- if (xf86WaitForInput(local->fd, 50000) == 0) {
- DBG(7, ErrorF("Reset received\n"));
- proto_ops->QueryHardware(local, synhw);
- } else
- DBG(3, ErrorF("faked reset received\n"));
- }
- comm->lastByte = u;
-
- /* to avoid endless loops */
- if (count++ > 30) {
- ErrorF("Synaptics driver lost sync... got gigantic packet!\n");
- return FALSE;
- }
-
- comm->protoBuf[comm->protoBufTail++] = u;
-
- /* Check that we have a valid packet. If not, we are out of sync,
- so we throw away the first byte in the packet.*/
- if (comm->protoBufTail >= 6) {
- if (!ps2_packet_ok(synhw, comm)) {
- int i;
- for (i = 0; i < comm->protoBufTail - 1; i++)
- comm->protoBuf[i] = comm->protoBuf[i + 1];
- comm->protoBufTail--;
- comm->outOfSync++;
- if (comm->outOfSync > MAX_UNSYNC_PACKETS) {
- comm->outOfSync = 0;
- DBG(3, ErrorF("Synaptics synchronization lost too long -> reset touchpad.\n"));
- proto_ops->QueryHardware(local, synhw); /* including a reset */
- continue;
- }
- }
- }
-
- if (comm->protoBufTail >= 6) { /* Full packet received */
- if (comm->outOfSync > 0) {
- comm->outOfSync = 0;
- DBG(4, ErrorF("Synaptics driver resynced.\n"));
- }
- comm->protoBufTail = 0;
- return TRUE;
- }
+ u = (unsigned char) c;
+
+ /* test if there is a reset sequence received */
+ if ((c == 0x00) && (comm->lastByte == 0xAA)) {
+ if (xf86WaitForInput(pInfo->fd, 50000) == 0) {
+ PS2DBG("Reset received\n");
+ proto_ops->QueryHardware(pInfo);
+ }
+ else
+ PS2DBG("faked reset received\n");
+ }
+ comm->lastByte = u;
+
+ /* to avoid endless loops */
+ if (count++ > 30) {
+ LogMessageVerbSigSafe(X_ERROR, 0,
+ "Synaptics driver lost sync... got gigantic packet!\n");
+ return FALSE;
+ }
+
+ comm->protoBuf[comm->protoBufTail++] = u;
+
+ /* Check that we have a valid packet. If not, we are out of sync,
+ so we throw away the first byte in the packet. */
+ if (comm->protoBufTail >= 6) {
+ if (!ps2_packet_ok(synhw, comm)) {
+ int i;
+
+ for (i = 0; i < comm->protoBufTail - 1; i++)
+ comm->protoBuf[i] = comm->protoBuf[i + 1];
+ comm->protoBufTail--;
+ comm->outOfSync++;
+ if (comm->outOfSync > MAX_UNSYNC_PACKETS) {
+ comm->outOfSync = 0;
+ PS2DBG("Synaptics synchronization lost too long -> reset touchpad.\n");
+ proto_ops->QueryHardware(pInfo); /* including a reset */
+ continue;
+ }
+ }
+ }
+
+ if (comm->protoBufTail >= 6) { /* Full packet received */
+ if (comm->outOfSync > 0) {
+ comm->outOfSync = 0;
+ PS2DBG("Synaptics driver resynced.\n");
+ }
+ comm->protoBufTail = 0;
+ return TRUE;
+ }
}
return FALSE;
}
-static Bool
-PS2ReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
- struct SynapticsProtocolOperations *proto_ops,
- struct CommData *comm, struct SynapticsHwState *hwRet)
+Bool
+PS2ReadHwStateProto(InputInfoPtr pInfo,
+ struct SynapticsProtocolOperations *proto_ops,
+ struct CommData *comm, struct SynapticsHwState *hwRet)
{
- int newabs = SYN_MODEL_NEWABS(*synhw);
unsigned char *buf = comm->protoBuf;
- struct SynapticsHwState *hw = &(comm->hwState);
+ struct SynapticsHwState *hw = comm->hwState;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ SynapticsParameters *para = &priv->synpara;
+ struct PS2SynapticsHwInfo *synhw;
+ int newabs;
int w, i;
- if (!ps2_synaptics_get_packet(local, synhw, proto_ops, comm))
- return FALSE;
-
- /* Handle guest packets */
- hw->guest_dx = hw->guest_dy = 0;
- if (newabs && synhw->hasGuest) {
- w = (((buf[0] & 0x30) >> 2) |
- ((buf[0] & 0x04) >> 1) |
- ((buf[3] & 0x04) >> 2));
- if (w == 3) { /* If w is 3, this is a guest packet */
- if (buf[4] != 0)
- hw->guest_dx = buf[4] - ((buf[1] & 0x10) ? 256 : 0);
- if (buf[5] != 0)
- hw->guest_dy = -(buf[5] - ((buf[1] & 0x20) ? 256 : 0));
- hw->guest_left = (buf[1] & 0x01) ? TRUE : FALSE;
- hw->guest_mid = (buf[1] & 0x04) ? TRUE : FALSE;
- hw->guest_right = (buf[1] & 0x02) ? TRUE : FALSE;
- *hwRet = *hw;
- return TRUE;
- }
+ synhw = (struct PS2SynapticsHwInfo *) priv->proto_data;
+ if (!synhw) {
+ LogMessageVerbSigSafe(X_ERROR, 0,
+ "PS2ReadHwState, synhw is NULL. This is a bug.\n");
+ return FALSE;
}
+ newabs = SYN_MODEL_NEWABS(synhw);
+
+ if (!ps2_synaptics_get_packet(pInfo, synhw, proto_ops, comm))
+ return FALSE;
+
/* Handle normal packets */
hw->x = hw->y = hw->z = hw->numFingers = hw->fingerWidth = 0;
hw->left = hw->right = hw->up = hw->down = hw->middle = FALSE;
for (i = 0; i < 8; i++)
- hw->multi[i] = FALSE;
-
- if (newabs) { /* newer protos...*/
- DBG(7, ErrorF("using new protocols\n"));
- hw->x = (((buf[3] & 0x10) << 8) |
- ((buf[1] & 0x0f) << 8) |
- buf[4]);
- hw->y = (((buf[3] & 0x20) << 7) |
- ((buf[1] & 0xf0) << 4) |
- buf[5]);
-
- hw->z = buf[2];
- w = (((buf[0] & 0x30) >> 2) |
- ((buf[0] & 0x04) >> 1) |
- ((buf[3] & 0x04) >> 2));
-
- hw->left = (buf[0] & 0x01) ? 1 : 0;
- hw->right = (buf[0] & 0x02) ? 1 : 0;
-
- if (SYN_CAP_EXTENDED(*synhw)) {
- if (SYN_CAP_MIDDLE_BUTTON(*synhw)) {
- hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
- }
- if (SYN_CAP_FOUR_BUTTON(*synhw)) {
- hw->up = ((buf[3] & 0x01)) ? 1 : 0;
- if (hw->left)
- hw->up = !hw->up;
- hw->down = ((buf[3] & 0x02)) ? 1 : 0;
- if (hw->right)
- hw->down = !hw->down;
- }
- if (SYN_CAP_MULTI_BUTTON_NO(*synhw)) {
- if ((buf[3] & 2) ? !hw->right : hw->right) {
- switch (SYN_CAP_MULTI_BUTTON_NO(*synhw) & ~0x01) {
- default:
- break;
- case 8:
- hw->multi[7] = ((buf[5] & 0x08)) ? 1 : 0;
- hw->multi[6] = ((buf[4] & 0x08)) ? 1 : 0;
- case 6:
- hw->multi[5] = ((buf[5] & 0x04)) ? 1 : 0;
- hw->multi[4] = ((buf[4] & 0x04)) ? 1 : 0;
- case 4:
- hw->multi[3] = ((buf[5] & 0x02)) ? 1 : 0;
- hw->multi[2] = ((buf[4] & 0x02)) ? 1 : 0;
- case 2:
- hw->multi[1] = ((buf[5] & 0x01)) ? 1 : 0;
- hw->multi[0] = ((buf[4] & 0x01)) ? 1 : 0;
- }
- }
- }
- }
- } else { /* old proto...*/
- DBG(7, ErrorF("using old protocol\n"));
- hw->x = (((buf[1] & 0x1F) << 8) |
- buf[2]);
- hw->y = (((buf[4] & 0x1F) << 8) |
- buf[5]);
-
- hw->z = (((buf[0] & 0x30) << 2) |
- (buf[3] & 0x3F));
- w = (((buf[1] & 0x80) >> 4) |
- ((buf[0] & 0x04) >> 1));
-
- hw->left = (buf[0] & 0x01) ? 1 : 0;
- hw->right = (buf[0] & 0x02) ? 1 : 0;
+ hw->multi[i] = FALSE;
+
+ if (newabs) { /* newer protos... */
+ PS2DBG("using new protocols\n");
+ hw->x = (((buf[3] & 0x10) << 8) | ((buf[1] & 0x0f) << 8) | buf[4]);
+ hw->y = (((buf[3] & 0x20) << 7) | ((buf[1] & 0xf0) << 4) | buf[5]);
+
+ hw->z = buf[2];
+ w = (((buf[0] & 0x30) >> 2) |
+ ((buf[0] & 0x04) >> 1) | ((buf[3] & 0x04) >> 2));
+
+ hw->left = (buf[0] & 0x01) ? 1 : 0;
+ hw->right = (buf[0] & 0x02) ? 1 : 0;
+
+ if (SYN_CAP_EXTENDED(synhw)) {
+ if (SYN_CAP_MIDDLE_BUTTON(synhw)) {
+ hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
+ }
+ if (SYN_CAP_FOUR_BUTTON(synhw)) {
+ hw->up = ((buf[3] & 0x01)) ? 1 : 0;
+ if (hw->left)
+ hw->up = !hw->up;
+ hw->down = ((buf[3] & 0x02)) ? 1 : 0;
+ if (hw->right)
+ hw->down = !hw->down;
+ }
+ if (SYN_CAP_MULTI_BUTTON_NO(synhw)) {
+ if ((buf[3] & 2) ? !hw->right : hw->right) {
+ switch (SYN_CAP_MULTI_BUTTON_NO(synhw) & ~0x01) {
+ default:
+ break;
+ case 8:
+ hw->multi[7] = ((buf[5] & 0x08)) ? 1 : 0;
+ hw->multi[6] = ((buf[4] & 0x08)) ? 1 : 0;
+ /* fallthrough */
+ case 6:
+ hw->multi[5] = ((buf[5] & 0x04)) ? 1 : 0;
+ hw->multi[4] = ((buf[4] & 0x04)) ? 1 : 0;
+ /* fallthrough */
+ case 4:
+ hw->multi[3] = ((buf[5] & 0x02)) ? 1 : 0;
+ hw->multi[2] = ((buf[4] & 0x02)) ? 1 : 0;
+ /* fallthrough */
+ case 2:
+ hw->multi[1] = ((buf[5] & 0x01)) ? 1 : 0;
+ hw->multi[0] = ((buf[4] & 0x01)) ? 1 : 0;
+ }
+ }
+ }
+ }
}
+ else { /* old proto... */
+ PS2DBG("using old protocol\n");
+ hw->x = (((buf[1] & 0x1F) << 8) | buf[2]);
+ hw->y = (((buf[4] & 0x1F) << 8) | buf[5]);
- hw->y = YMAX_NOMINAL + YMIN_NOMINAL - hw->y;
+ hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F));
+ w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1));
- if (hw->z > 0) {
- int w_ok = 0;
- /*
- * Use capability bits to decide if the w value is valid.
- * If not, set it to 5, which corresponds to a finger of
- * normal width.
- */
- if (SYN_CAP_EXTENDED(*synhw)) {
- if ((w >= 0) && (w <= 1)) {
- w_ok = SYN_CAP_MULTIFINGER(*synhw);
- } else if (w == 2) {
- w_ok = SYN_MODEL_PEN(*synhw);
- } else if ((w >= 4) && (w <= 15)) {
- w_ok = SYN_CAP_PALMDETECT(*synhw);
- }
- }
- if (!w_ok)
- w = 5;
-
- switch (w) {
- case 0:
- hw->numFingers = 2;
- hw->fingerWidth = 5;
- break;
- case 1:
- hw->numFingers = 3;
- hw->fingerWidth = 5;
- break;
- default:
- hw->numFingers = 1;
- hw->fingerWidth = w;
- break;
- }
+ hw->left = (buf[0] & 0x01) ? 1 : 0;
+ hw->right = (buf[0] & 0x02) ? 1 : 0;
}
- *hwRet = *hw;
+ hw->y = YMAX_NOMINAL + YMIN_NOMINAL - hw->y;
+
+ if (hw->z >= para->finger_high) {
+ int w_ok = 0;
+
+ /*
+ * Use capability bits to decide if the w value is valid.
+ * If not, set it to 5, which corresponds to a finger of
+ * normal width.
+ */
+ if (SYN_CAP_EXTENDED(synhw)) {
+ if ((w >= 0) && (w <= 1)) {
+ w_ok = SYN_CAP_MULTIFINGER(synhw);
+ }
+ else if (w == 2) {
+ w_ok = SYN_MODEL_PEN(synhw);
+ }
+ else if ((w >= 4) && (w <= 15)) {
+ w_ok = SYN_CAP_PALMDETECT(synhw);
+ }
+ }
+ if (!w_ok)
+ w = 5;
+
+ switch (w) {
+ case 0:
+ hw->numFingers = 2;
+ hw->fingerWidth = 5;
+ break;
+ case 1:
+ hw->numFingers = 3;
+ hw->fingerWidth = 5;
+ break;
+ default:
+ hw->numFingers = 1;
+ hw->fingerWidth = w;
+ break;
+ }
+ }
+ hw->millis = GetTimeInMillis();
+ SynapticsCopyHwState(hwRet, hw);
return TRUE;
}
static Bool
-PS2AutoDevProbe(LocalDevicePtr local)
+PS2ReadHwState(InputInfoPtr pInfo,
+ struct CommData *comm, struct SynapticsHwState *hwRet)
{
- return FALSE;
+ return PS2ReadHwStateProto(pInfo, &psaux_proto_operations, comm, hwRet);
}
struct SynapticsProtocolOperations psaux_proto_operations = {
- PS2DeviceOnHook,
+ NULL,
PS2DeviceOffHook,
PS2QueryHardware,
PS2ReadHwState,
- PS2AutoDevProbe
+ NULL,
+ NULL
};
diff --git a/src/ps2comm.h b/src/ps2comm.h
index 4a1a051..fa71d10 100644
--- a/src/ps2comm.h
+++ b/src/ps2comm.h
@@ -1,12 +1,35 @@
+/*
+ * 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 _PS2COMM_H_
#define _PS2COMM_H_
+#include <xorg-server.h>
+
#include <unistd.h>
#include <sys/ioctl.h>
#include "xf86_OSproc.h"
/* acknowledge for commands and parameter */
-#define PS2_ACK 0xFA
+#define PS2_ACK 0xFA
#define PS2_ERROR 0xFC
/* standard PS/2 commands */
@@ -35,26 +58,26 @@
#define SYN_BIT_W_MODE (1 << 0)
/* synaptics model ID bits */
-#define SYN_MODEL_ROT180(synhw) ((synhw).model_id & (1 << 23))
-#define SYN_MODEL_PORTRAIT(synhw) ((synhw).model_id & (1 << 22))
-#define SYN_MODEL_SENSOR(synhw) (((synhw).model_id >> 16) & 0x3f)
-#define SYN_MODEL_HARDWARE(synhw) (((synhw).model_id >> 9) & 0x7f)
-#define SYN_MODEL_NEWABS(synhw) ((synhw).model_id & (1 << 7))
-#define SYN_MODEL_PEN(synhw) ((synhw).model_id & (1 << 6))
-#define SYN_MODEL_SIMPLIC(synhw) ((synhw).model_id & (1 << 5))
-#define SYN_MODEL_GEOMETRY(synhw) ((synhw).model_id & 0x0f)
+#define SYN_MODEL_ROT180(synhw) ((synhw)->model_id & (1 << 23))
+#define SYN_MODEL_PORTRAIT(synhw) ((synhw)->model_id & (1 << 22))
+#define SYN_MODEL_SENSOR(synhw) (((synhw)->model_id >> 16) & 0x3f)
+#define SYN_MODEL_HARDWARE(synhw) (((synhw)->model_id >> 9) & 0x7f)
+#define SYN_MODEL_NEWABS(synhw) ((synhw)->model_id & (1 << 7))
+#define SYN_MODEL_PEN(synhw) ((synhw)->model_id & (1 << 6))
+#define SYN_MODEL_SIMPLIC(synhw) ((synhw)->model_id & (1 << 5))
+#define SYN_MODEL_GEOMETRY(synhw) ((synhw)->model_id & 0x0f)
/* synaptics capability bits */
-#define SYN_CAP_EXTENDED(synhw) ((synhw).capabilities & (1 << 23))
-#define SYN_CAP_MIDDLE_BUTTON(synhw) ((synhw).capabilities & (1 << 18))
-#define SYN_CAP_PASSTHROUGH(synhw) ((synhw).capabilities & (1 << 7))
-#define SYN_CAP_SLEEP(synhw) ((synhw).capabilities & (1 << 4))
-#define SYN_CAP_FOUR_BUTTON(synhw) ((synhw).capabilities & (1 << 3))
-#define SYN_CAP_MULTIFINGER(synhw) ((synhw).capabilities & (1 << 1))
-#define SYN_CAP_PALMDETECT(synhw) ((synhw).capabilities & (1 << 0))
-#define SYN_CAP_VALID(synhw) ((((synhw).capabilities & 0x00ff00) >> 8) == 0x47)
-#define SYN_EXT_CAP_REQUESTS(synhw) (((synhw).capabilities & 0x700000) == 0x100000)
-#define SYN_CAP_MULTI_BUTTON_NO(synhw) (((synhw).ext_cap & 0x00f000) >> 12)
+#define SYN_CAP_EXTENDED(synhw) ((synhw)->capabilities & (1 << 23))
+#define SYN_CAP_MIDDLE_BUTTON(synhw) ((synhw)->capabilities & (1 << 18))
+#define SYN_CAP_PASSTHROUGH(synhw) ((synhw)->capabilities & (1 << 7))
+#define SYN_CAP_SLEEP(synhw) ((synhw)->capabilities & (1 << 4))
+#define SYN_CAP_FOUR_BUTTON(synhw) ((synhw)->capabilities & (1 << 3))
+#define SYN_CAP_MULTIFINGER(synhw) ((synhw)->capabilities & (1 << 1))
+#define SYN_CAP_PALMDETECT(synhw) ((synhw)->capabilities & (1 << 0))
+#define SYN_CAP_VALID(synhw) ((((synhw)->capabilities & 0x00ff00) >> 8) == 0x47)
+#define SYN_EXT_CAP_REQUESTS(synhw) (((synhw)->capabilities & 0x700000) != 0)
+#define SYN_CAP_MULTI_BUTTON_NO(synhw) (((synhw)->ext_cap & 0x00f000) >> 12)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
@@ -66,17 +89,25 @@
#define SYN_MODE_VALID(m) (((m) & 0xffff00) == 0x3B47)
/* synaptics identify query bits */
-#define SYN_ID_MODEL(synhw) (((synhw).identity >> 4) & 0x0f)
-#define SYN_ID_MAJOR(synhw) ((synhw).identity & 0x0f)
-#define SYN_ID_MINOR(synhw) (((synhw).identity >> 16) & 0xff)
-#define SYN_ID_IS_SYNAPTICS(synhw) ((((synhw).identity >> 8) & 0xff) == 0x47)
+#define SYN_ID_MODEL(synhw) (((synhw)->identity >> 4) & 0x0f)
+#define SYN_ID_MAJOR(synhw) ((synhw)->identity & 0x0f)
+#define SYN_ID_MINOR(synhw) (((synhw)->identity >> 16) & 0xff)
+#define SYN_ID_IS_SYNAPTICS(synhw) ((((synhw)->identity >> 8) & 0xff) == 0x47)
typedef unsigned char byte;
+struct PS2SynapticsHwInfo {
+ unsigned int model_id; /* Model-ID */
+ unsigned int capabilities; /* Capabilities */
+ unsigned int ext_cap; /* Extended Capabilities */
+ unsigned int identity; /* Identification */
+};
Bool ps2_putbyte(int fd, byte b);
+void ps2_print_ident(InputInfoPtr pInfo,
+ const struct PS2SynapticsHwInfo *synhw);
+Bool PS2ReadHwStateProto(InputInfoPtr pInfo,
+ struct SynapticsProtocolOperations *proto_ops,
+ struct CommData *comm, struct SynapticsHwState *hwRet);
-struct SynapticsHwInfo;
-void ps2_print_ident(const struct SynapticsHwInfo *synhw);
-
-#endif /* _PS2COMM_H_ */
+#endif /* _PS2COMM_H_ */
diff --git a/src/psmcomm.c b/src/psmcomm.c
index cf995b1..0bf9877 100644
--- a/src/psmcomm.c
+++ b/src/psmcomm.c
@@ -1,45 +1,52 @@
-/* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
- *
- * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu>
- * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
- * code für the special synaptics commands (from the tpconfig-source)
- *
- * Synaptics Passthrough Support
- * Copyright (c) 2002 Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
- * adapted to version 0.12.1
- * Copyright (c) 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
- *
- * Copyright (c) 2004 Arne Schwabe <schwabe@uni-paderborn.de>
- * FreeBSD Support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+/*
+ * Copyright © 1997 C. Scott Ananian
+ * Copyright © 1998-2000 Bruce Kalk
+ * Copyright © 2001 Stefan Gmeiner
+ * Copyright © 2002 Linuxcare Inc. David Kennedy
+ * Copyright © 2003 Fred Hucht
+ * Copyright © 2004 Arne Schwabe
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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:
+ * Stefan Gmeiner (riddlebox@freesurf.ch)
+ * C. Scott Ananian (cananian@alumni.priceton.edu)
+ * Bruce Kalk (kall@compass.com)
+ * Linuxcare Inc. David Kennedy (dkennedy@linuxcare.com)
+ * Fred Hucht (fred@thp.Uni-Duisburg.de)
+ * Arne Schwabe <schwabe@uni-paderborn.de>
*/
-#if defined(__FreeBSD) || defined(__NetBSD__) || defined(__OpenBSD)
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "psmcomm.h"
+#include <xorg-server.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mouse.h>
#include <errno.h>
#include <string.h>
#include "synproto.h"
-#include "synaptics.h"
-#include "ps2comm.h" /* ps2_print_ident() */
+#include "synapticsstr.h"
+#include "ps2comm.h" /* ps2_print_ident() */
#include <xf86.h>
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
@@ -49,22 +56,22 @@
* See also the SYN_ID_* macros
*/
static Bool
-psm_synaptics_identify(int fd, synapticshw_t *ident)
+psm_synaptics_identify(int fd, synapticshw_t * ident)
{
int ret;
SYSCALL(ret = ioctl(fd, MOUSE_SYN_GETHWINFO, ident));
if (ret == 0)
- return TRUE;
+ return TRUE;
else
- return FALSE;
+ return FALSE;
}
/* This define is used in a ioctl but not in mouse.h :/ */
#define PSM_LEVEL_NATIVE 2
static Bool
-PSMQueryIsSynaptics(LocalDevicePtr local)
+PSMQueryIsSynaptics(InputInfoPtr pInfo)
{
int ret;
int level = PSM_LEVEL_NATIVE;
@@ -74,106 +81,94 @@ PSMQueryIsSynaptics(LocalDevicePtr local)
* Otherwise HWINFO will not return the right id
* And we will need native mode anyway ...
*/
- SYSCALL(ret = ioctl(local->fd, MOUSE_SETLEVEL, &level));
+ SYSCALL(ret = ioctl(pInfo->fd, MOUSE_SETLEVEL, &level));
if (ret != 0) {
- xf86Msg(X_ERROR, "%s Can't set native mode\n", local->name);
- return FALSE;
+ xf86IDrvMsg(pInfo, X_ERROR, "%s Can't set native mode\n", pInfo->name);
+ return FALSE;
}
- SYSCALL(ret = ioctl(local->fd, MOUSE_GETHWINFO, &mhw));
+ SYSCALL(ret = ioctl(pInfo->fd, MOUSE_GETHWINFO, &mhw));
if (ret != 0) {
- xf86Msg(X_ERROR, "%s Can't get hardware info\n", local->name);
- return FALSE;
+ xf86IDrvMsg(pInfo, X_ERROR, "%s Can't get hardware info\n",
+ pInfo->name);
+ return FALSE;
}
if (mhw.model == MOUSE_MODEL_SYNAPTICS) {
- return TRUE;
- } else {
- xf86Msg(X_ERROR, "%s Found no Synaptics, found Mouse model %d instead\n",
- local->name, mhw.model);
- return FALSE;
+ return TRUE;
+ }
+ else {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "%s Found no Synaptics, found Mouse model %d instead\n",
+ pInfo->name, mhw.model);
+ return FALSE;
}
}
static void
-PSMDeviceOnHook(LocalDevicePtr local, SynapticsSHM *para)
-{
-}
-
-static void
-PSMDeviceOffHook(LocalDevicePtr local)
-{
-}
-
-static void
-convert_hw_info(const synapticshw_t *psm_ident, struct SynapticsHwInfo *synhw)
+convert_hw_info(const synapticshw_t * psm_ident,
+ struct PS2SynapticsHwInfo *synhw)
{
memset(synhw, 0, sizeof(*synhw));
synhw->model_id = ((psm_ident->infoRot180 << 23) |
- (psm_ident->infoPortrait << 22) |
- (psm_ident->infoSensor << 16) |
- (psm_ident->infoHardware << 9) |
- (psm_ident->infoNewAbs << 7) |
- (psm_ident->capPen << 6) |
- (psm_ident->infoSimplC << 5) |
- (psm_ident->infoGeometry));
+ (psm_ident->infoPortrait << 22) |
+ (psm_ident->infoSensor << 16) |
+ (psm_ident->infoHardware << 9) |
+ (psm_ident->infoNewAbs << 7) |
+ (psm_ident->capPen << 6) |
+ (psm_ident->infoSimplC << 5) |
+ (psm_ident->infoGeometry));
synhw->capabilities = ((psm_ident->capExtended << 23) |
- (psm_ident->capPassthrough << 7) |
- (psm_ident->capSleep << 4) |
- (psm_ident->capFourButtons << 3) |
- (psm_ident->capMultiFinger << 1) |
- (psm_ident->capPalmDetect));
+ (psm_ident->capPassthrough << 7) |
+ (psm_ident->capSleep << 4) |
+ (psm_ident->capFourButtons << 3) |
+ (psm_ident->capMultiFinger << 1) |
+ (psm_ident->capPalmDetect));
synhw->ext_cap = 0;
synhw->identity = ((psm_ident->infoMajor) |
- (0x47 << 8) |
- (psm_ident->infoMinor << 16));
+ (0x47 << 8) | (psm_ident->infoMinor << 16));
}
static Bool
-PSMQueryHardware(LocalDevicePtr local, struct SynapticsHwInfo *synhw)
+PSMQueryHardware(InputInfoPtr pInfo)
{
synapticshw_t psm_ident;
+ struct PS2SynapticsHwInfo *synhw;
+ SynapticsPrivate *priv;
+
+ priv = (SynapticsPrivate *) pInfo->private;
+
+ if (!priv->proto_data)
+ priv->proto_data = calloc(1, sizeof(struct PS2SynapticsHwInfo));
+ synhw = (struct PS2SynapticsHwInfo *) priv->proto_data;
/* is the synaptics touchpad active? */
- if (!PSMQueryIsSynaptics(local))
- return FALSE;
+ if (!PSMQueryIsSynaptics(pInfo))
+ return FALSE;
- xf86Msg(X_PROBED, "%s synaptics touchpad found\n", local->name);
+ xf86IDrvMsg(pInfo, X_PROBED, "synaptics touchpad found\n");
- if (!psm_synaptics_identify(local->fd, &psm_ident))
- return FALSE;
+ if (!psm_synaptics_identify(pInfo->fd, &psm_ident))
+ return FALSE;
convert_hw_info(&psm_ident, synhw);
- /* Check to see if the host mouse supports a guest */
- synhw->hasGuest = FALSE;
- if (psm_ident.capPassthrough) {
- synhw->hasGuest = TRUE;
- }
-
- ps2_print_ident(synhw);
+ ps2_print_ident(pInfo, synhw);
return TRUE;
}
static Bool
-PSMReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
- struct SynapticsProtocolOperations *proto_ops,
- struct CommData *comm, struct SynapticsHwState *hwRet)
-{
- return psaux_proto_operations.ReadHwState(local, synhw, proto_ops, comm, hwRet);
-}
-
-static Bool PSMAutoDevProbe(LocalDevicePtr local)
+PSMReadHwState(InputInfoPtr pInfo,
+ struct CommData *comm, struct SynapticsHwState *hwRet)
{
- return FALSE;
+ return PS2ReadHwStateProto(pInfo, &psm_proto_operations, comm, hwRet);
}
struct SynapticsProtocolOperations psm_proto_operations = {
- PSMDeviceOnHook,
- PSMDeviceOffHook,
+ NULL,
+ NULL,
PSMQueryHardware,
PSMReadHwState,
- PSMAutoDevProbe
+ NULL,
+ NULL
};
-
-#endif
diff --git a/src/psmcomm.h b/src/psmcomm.h
deleted file mode 100644
index 72aaf83..0000000
--- a/src/psmcomm.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _PSMCOMM_H_
-#define _PSMCOMM_H_
-
-#if defined(__FreeBSD) || defined(__NetBSD__) || defined(__OpenBSD)
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <freebsd/mouse.h>
-
-#endif
-
-#endif /* _PSMCOMM_H_ */
diff --git a/src/synaptics.c b/src/synaptics.c
index 78ca633..70d8809 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -1,104 +1,84 @@
/*
- * Copyright 2007 Joseph P. Skudlarek <Jskud@Jskud.com>
- * patch for corner coasting (originally called corner edge scrolling)
+ * Copyright © 1999 Henry Davies
+ * Copyright © 2001 Stefan Gmeiner
+ * Copyright © 2002 S. Lehner
+ * Copyright © 2002 Peter Osterlund
+ * Copyright © 2002 Linuxcare Inc. David Kennedy
+ * Copyright © 2003 Hartwig Felger
+ * Copyright © 2003 Jörg Bösner
+ * Copyright © 2003 Fred Hucht
+ * Copyright © 2004 Alexei Gilchrist
+ * Copyright © 2004 Matthias Ihmig
+ * Copyright © 2006 Stefan Bethge
+ * Copyright © 2006 Christian Thaeter
+ * Copyright © 2007 Joseph P. Skudlarek
+ * Copyright © 2008 Fedor P. Goncharov
+ * Copyright © 2008-2012 Red Hat, Inc.
+ * Copyright © 2011 The Chromium OS Authors
*
- * Copyright 2006 Christian Thaeter <chth@gmx.net>
- * patch for Trackstick mode
+ * 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.
*
- * Copyright 2006 Stefan Bethge <stefan.bethge@web.de>
- * patch for two-fingered scrolling
- *
- * Copyright 2004 Matthias Ihmig <m.ihmig@gmx.net>
- * patch for pressure dependent EdgeMotion speed
- *
- * Copyright 2004 Alexei Gilchrist <alexei@physics.uq.edu.au>
- * patch for circular scrolling
- *
- * Copyright 2003 Jörg Bösner <ich@joerg-boesner.de>
- * patch for switching the touchpad off (for example, when a
- * USB mouse is connected)
- *
- * Copyright 2003 Hartwig Felger <hgfelger@hgfelger.de>
- * patch to make the horizontal wheel replacement buttons work.
- *
- * Copyright 2002 Peter Osterlund <petero2@telia.com>
- * patches for fast scrolling, palm detection, edge motion,
- * horizontal scrolling
- *
- * Copyright 2002 S. Lehner <sam_x@bluemail.ch>
- * for newer Firmware (5.8) protocol changes for 3rd to 6th button
- *
- * Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
- * start merging tpconfig and gpm code to an xfree input module
- * adding some changes and extensions (ex. 3rd and 4th button)
- *
- * Copyright (c) 1999 Henry Davies <hdavies@ameritech.net> for the
- * absolute to relative translation code (from the gpm source)
- * and some other ideas
- *
- * Synaptics Passthrough Support
- * Copyright (c) 2002 Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
- * adapted to version 0.12.1
- * Copyright (c) 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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:
+ * Joseph P. Skudlarek <Jskud@Jskud.com>
+ * Christian Thaeter <chth@gmx.net>
+ * Stefan Bethge <stefan.bethge@web.de>
+ * Matthias Ihmig <m.ihmig@gmx.net>
+ * Alexei Gilchrist <alexei@physics.uq.edu.au>
+ * Jörg Bösner <ich@joerg-boesner.de>
+ * Hartwig Felger <hgfelger@hgfelger.de>
+ * Peter Osterlund <petero2@telia.com>
+ * S. Lehner <sam_x@bluemail.ch>
+ * Stefan Gmeiner <riddlebox@freesurf.ch>
+ * Henry Davies <hdavies@ameritech.net> for the
+ * Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
+ * Fred Hucht <fred@thp.Uni-Duisburg.de>
+ * Fedor P. Goncharov <fedgo@gorodok.net>
+ * Simon Thum <simon.thum@gmx.de>
*
* Trademarks are the property of their respective owners.
- *
*/
-
-/*****************************************************************************
- * Standard Headers
- ****************************************************************************/
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <xorg-server.h>
#include <unistd.h>
-#include <sys/ioctl.h>
#include <misc.h>
#include <xf86.h>
-#include <sys/shm.h>
-#include <sys/ipc.h>
-#include <sys/stat.h>
-#include <errno.h>
+#include <math.h>
+#include <stdio.h>
#include <xf86_OSproc.h>
#include <xf86Xinput.h>
-#include "mipointer.h"
-#ifdef XFREE_4_0_3
-#include <xf86Optrec.h> /* needed for Options */
-#endif
+#include <exevents.h>
-/*****************************************************************************
- * Local Headers
- ****************************************************************************/
-#define SYNAPTICS_PRIVATE
-#include "synaptics.h"
+#include <X11/Xatom.h>
+#include <X11/extensions/XI2.h>
+#include <xserver-properties.h>
+#include <ptrveloc.h>
-/*****************************************************************************
- * Variables without includable headers
- ****************************************************************************/
+#include "synapticsstr.h"
+#include "synaptics-properties.h"
-/*****************************************************************************
- * Local Variables and Types
- ****************************************************************************/
-
-typedef enum {
+enum EdgeType {
+ NO_EDGE = 0,
BOTTOM_EDGE = 1,
TOP_EDGE = 2,
LEFT_EDGE = 4,
@@ -107,12 +87,26 @@ typedef enum {
RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE,
RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE,
LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE
-} edge_type;
+};
+
+/*
+ * We expect to be receiving a steady 80 packets/sec (which gives 40
+ * reports/sec with more than one finger on the pad, as Advanced Gesture Mode
+ * requires two PS/2 packets per report). Instead of a random scattering of
+ * magic 13 and 20ms numbers scattered throughout the driver, introduce
+ * POLL_MS as 14ms, which is slightly less than 80Hz. 13ms is closer to
+ * 80Hz, but if the kernel event reporting was even slightly delayed,
+ * we would produce synthetic motion followed immediately by genuine
+ * motion, so use 14.
+ *
+ * We use this to call back at a constant rate to at least produce the
+ * illusion of smooth motion. It works a lot better than you'd expect.
+*/
+#define POLL_MS 14
#define MAX(a, b) (((a)>(b))?(a):(b))
#define MIN(a, b) (((a)<(b))?(a):(b))
#define TIME_DIFF(a, b) ((int)((a)-(b)))
-#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
#define SQR(x) ((x) * (x))
@@ -120,59 +114,75 @@ typedef enum {
#define M_PI 3.14159265358979323846
#endif
-#ifndef M_SQRT1_2
-#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
-#endif
-
-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 1
-#define DBG(a,b)
-#endif
+#define INPUT_BUFFER_SIZE 200
/*****************************************************************************
* Forward declaration
****************************************************************************/
-static InputInfoPtr SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
+static int SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
+static void SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
static Bool DeviceControl(DeviceIntPtr, int);
-static void ReadInput(LocalDevicePtr);
-static int HandleState(LocalDevicePtr, struct SynapticsHwState*);
-static int ControlProc(LocalDevicePtr, xDeviceCtl*);
-static void CloseProc(LocalDevicePtr);
+static void ReadInput(InputInfoPtr);
+static int HandleState(InputInfoPtr, struct SynapticsHwState *, CARD32 now,
+ Bool from_timer);
+static int ControlProc(InputInfoPtr, xDeviceCtl *);
static int SwitchMode(ClientPtr, DeviceIntPtr, int);
-static Bool ConvertProc(LocalDevicePtr, int, int, int, int, int, int, int, int, int*, int*);
-static Bool DeviceInit(DeviceIntPtr);
-static Bool DeviceOn(DeviceIntPtr);
-static Bool DeviceOff(DeviceIntPtr);
-static Bool DeviceClose(DeviceIntPtr);
-static Bool QueryHardware(LocalDevicePtr);
-
+static int DeviceInit(DeviceIntPtr);
+static int DeviceOn(DeviceIntPtr);
+static int DeviceOff(DeviceIntPtr);
+static int DeviceClose(DeviceIntPtr);
+static Bool QueryHardware(InputInfoPtr);
+static void ReadDevDimensions(InputInfoPtr);
+#ifndef NO_DRIVER_SCALING
+static void ScaleCoordinates(SynapticsPrivate * priv,
+ struct SynapticsHwState *hw);
+static void CalculateScalingCoeffs(SynapticsPrivate * priv);
+#endif
+static void SanitizeDimensions(InputInfoPtr pInfo);
+
+const static struct {
+ const char *name;
+ struct SynapticsProtocolOperations *proto_ops;
+} protocols[] = {
+#ifdef BUILD_EVENTCOMM
+ { "event", &event_proto_operations },
+#endif
+#ifdef BUILD_PSMCOMM
+ { "psm", &psm_proto_operations },
+#endif
+#ifdef BUILD_PS2COMM
+ { "psaux", &psaux_proto_operations },
+ { "alps", &alps_proto_operations },
+#endif
+ { NULL, NULL }
+};
InputDriverRec SYNAPTICS = {
1,
"synaptics",
NULL,
SynapticsPreInit,
- /*SynapticsUnInit*/ NULL,
+ SynapticsUnInit,
+ NULL,
NULL,
- 0
+#ifdef XI86_DRV_CAP_SERVER_FD
+ XI86_DRV_CAP_SERVER_FD
+#endif
};
-#ifdef XFree86LOADER
-
static XF86ModuleVersionInfo VersionRec = {
"synaptics",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
- XF86_VERSION_CURRENT,
- 1, 0, 0,
+ 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} /* signature, to be patched into the file by
- * a tool */
+ {0, 0, 0, 0}
};
-
static pointer
SetupProc(pointer module, pointer options, int *errmaj, int *errmin)
{
@@ -180,367 +190,784 @@ SetupProc(pointer module, pointer options, int *errmaj, int *errmin)
return module;
}
-XF86ModuleData synapticsModuleData = {&VersionRec, &SetupProc, NULL };
-
-#endif /* XFree86LOADER */
-
+_X_EXPORT XF86ModuleData synapticsModuleData = {
+ &VersionRec,
+ &SetupProc,
+ NULL
+};
/*****************************************************************************
* Function Definitions
****************************************************************************/
+static inline void
+SynapticsCloseFd(InputInfoPtr pInfo)
+{
+ if (pInfo->fd > -1 && !(pInfo->flags & XI86_SERVER_FD)) {
+ xf86CloseSerial(pInfo->fd);
+ pInfo->fd = -1;
+ }
+}
+/**
+ * Fill in default dimensions for backends that cannot query the hardware.
+ * Eventually, we want the edges to be 1900/5400 for x, 1900/4000 for y.
+ * These values are based so that calculate_edge_widths() will give us the
+ * right values.
+ *
+ * The default values 1900, etc. come from the dawn of time, when men where
+ * men, or possibly apes.
+ */
static void
-SetDeviceAndProtocol(LocalDevicePtr local)
-{
- char *str_par;
- SynapticsPrivate *priv = local->private;
- enum SynapticsProtocol proto = SYN_PROTO_PSAUX;
-
- str_par = xf86FindOptionValue(local->options, "Protocol");
- if (str_par && !strcmp(str_par, "psaux")) {
- /* Already set up */
- } else if (str_par && !strcmp(str_par, "event")) {
- proto = SYN_PROTO_EVENT;
- } else if (str_par && !strcmp(str_par, "psm")) {
- proto = SYN_PROTO_PSM;
- } else if (str_par && !strcmp(str_par, "alps")) {
- proto = SYN_PROTO_ALPS;
- } else { /* default to auto-dev */
- if (event_proto_operations.AutoDevProbe(local))
- proto = SYN_PROTO_EVENT;
- }
- switch (proto) {
- case SYN_PROTO_PSAUX:
- priv->proto_ops = &psaux_proto_operations;
- break;
- case SYN_PROTO_EVENT:
- priv->proto_ops = &event_proto_operations;
- break;
- case SYN_PROTO_PSM:
- priv->proto_ops = &psm_proto_operations;
- break;
- case SYN_PROTO_ALPS:
- priv->proto_ops = &alps_proto_operations;
- break;
+SanitizeDimensions(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+
+ if (priv->minx >= priv->maxx) {
+ priv->minx = 1615;
+ priv->maxx = 5685;
+ priv->resx = 0;
+
+ xf86IDrvMsg(pInfo, X_PROBED,
+ "invalid x-axis range. defaulting to %d - %d\n",
+ priv->minx, priv->maxx);
+ }
+
+ if (priv->miny >= priv->maxy) {
+ priv->miny = 1729;
+ priv->maxy = 4171;
+ priv->resy = 0;
+
+ xf86IDrvMsg(pInfo, X_PROBED,
+ "invalid y-axis range. defaulting to %d - %d\n",
+ priv->miny, priv->maxy);
+ }
+
+ if (priv->minp >= priv->maxp) {
+ priv->minp = 0;
+ priv->maxp = 255;
+
+ xf86IDrvMsg(pInfo, X_PROBED,
+ "invalid pressure range. defaulting to %d - %d\n",
+ priv->minp, priv->maxp);
+ }
+
+ if (priv->minw >= priv->maxw) {
+ priv->minw = 0;
+ priv->maxw = 15;
+
+ xf86IDrvMsg(pInfo, X_PROBED,
+ "invalid finger width range. defaulting to %d - %d\n",
+ priv->minw, priv->maxw);
}
}
-/*
- * Allocate and initialize memory for the SynapticsSHM data to hold driver
- * parameter settings.
- * The function will allocate shared memory if priv->shm_config is TRUE.
- * The allocated data is initialized from priv->synpara_default.
- */
static Bool
-alloc_param_data(LocalDevicePtr local)
-{
- int shmid;
- SynapticsPrivate *priv = local->private;
-
- if (priv->synpara)
- return TRUE; /* Already allocated */
-
- if (priv->shm_config) {
- if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
- shmctl(shmid, IPC_RMID, NULL);
- if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM),
- 0777 | IPC_CREAT)) == -1) {
- xf86Msg(X_ERROR, "%s error shmget\n", local->name);
- return FALSE;
- }
- if ((priv->synpara = (SynapticsSHM*)shmat(shmid, NULL, 0)) == NULL) {
- xf86Msg(X_ERROR, "%s error shmat\n", local->name);
- return FALSE;
- }
- } else {
- priv->synpara = xcalloc(1, sizeof(SynapticsSHM));
- if (!priv->synpara)
- return FALSE;
- }
-
- *(priv->synpara) = priv->synpara_default;
- return TRUE;
+SetDeviceAndProtocol(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = pInfo->private;
+ char *proto, *device;
+ int i;
+
+ proto = xf86SetStrOption(pInfo->options, "Protocol", NULL);
+ device = xf86SetStrOption(pInfo->options, "Device", NULL);
+
+ /* If proto is auto-dev, unset and let the code do the rest */
+ if (proto && !strcmp(proto, "auto-dev")) {
+ free(proto);
+ proto = NULL;
+ }
+
+ for (i = 0; protocols[i].name; i++) {
+ if ((!device || !proto) &&
+ protocols[i].proto_ops->AutoDevProbe &&
+ protocols[i].proto_ops->AutoDevProbe(pInfo, device))
+ break;
+ else if (proto && !strcmp(proto, protocols[i].name))
+ break;
+ }
+ free(proto);
+ free(device);
+
+ priv->proto_ops = protocols[i].proto_ops;
+
+ return (priv->proto_ops != NULL);
}
-/*
- * Free SynapticsSHM data previously allocated by alloc_param_data().
- */
static void
-free_param_data(SynapticsPrivate *priv)
+calculate_edge_widths(SynapticsPrivate * priv, int *l, int *r, int *t, int *b)
{
- int shmid;
+ int width, height;
+ int ewidth, eheight; /* edge width/height */
- if (!priv->synpara)
- return;
+ width = abs(priv->maxx - priv->minx);
+ height = abs(priv->maxy - priv->miny);
- if (priv->shm_config) {
- if ((shmid = xf86shmget(SHM_SYNAPTICS, 0, 0)) != -1)
- shmctl(shmid, IPC_RMID, NULL);
- } else {
- xfree(priv->synpara);
+ if (priv->model == MODEL_SYNAPTICS) {
+ ewidth = width * .07;
+ eheight = height * .07;
+ }
+ else if (priv->model == MODEL_ALPS) {
+ ewidth = width * .15;
+ eheight = height * .15;
+ }
+ else if (priv->model == MODEL_APPLETOUCH ||
+ priv->model == MODEL_UNIBODY_MACBOOK) {
+ ewidth = width * .085;
+ eheight = height * .085;
+ }
+ else {
+ ewidth = width * .04;
+ eheight = height * .054;
}
- priv->synpara = NULL;
+ *l = priv->minx + ewidth;
+ *r = priv->maxx - ewidth;
+ *t = priv->miny + eheight;
+ *b = priv->maxy - eheight;
}
-static double
-synSetFloatOption(pointer options, const char *optname, double default_value)
+static void
+calculate_tap_hysteresis(SynapticsPrivate * priv, int range,
+ int *fingerLow, int *fingerHigh)
{
- char *str_par;
- double value;
- str_par = xf86FindOptionValue(options, optname);
- if ((!str_par) || (xf86sscanf(str_par, "%lf", &value) != 1))
- return default_value;
- return value;
+ switch (priv->model) {
+ case MODEL_ELANTECH:
+ /* All Elantech touchpads don't need the Z filtering to get the
+ * number of fingers correctly. See Documentation/elantech.txt
+ * in the kernel.
+ */
+ *fingerLow = priv->minp + 1;
+ *fingerHigh = priv->minp + 1;
+ break;
+ case MODEL_UNIBODY_MACBOOK:
+ *fingerLow = 70;
+ *fingerHigh = 75;
+ break;
+ default:
+ *fingerLow = priv->minp + range * (25.0 / 256);
+ *fingerHigh = priv->minp + range * (30.0 / 256);
+ break;
+ }
}
-/*
- * called by the module loader for initialization
+/* Area options support both percent values and absolute values. This is
+ * awkward. The xf86Set* calls will print to the log, but they'll
+ * also print an error if we request a percent value but only have an
+ * int. So - check first for percent, then call xf86Set* again to get
+ * the log message.
*/
-static InputInfoPtr
-SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+static int
+set_percent_option(pointer options, const char *optname,
+ const int range, const int offset, const int default_value)
{
- LocalDevicePtr local;
- SynapticsPrivate *priv;
-#ifdef XFREE_4_0_3
- XF86OptionPtr optList;
-#else
- pointer optList;
-#endif
- SynapticsSHM *pars;
- char *repeater;
- pointer opts;
- int status;
+ int result;
+ double percent = xf86CheckPercentOption(options, optname, -1);
- /* allocate memory for SynapticsPrivateRec */
- priv = xcalloc(1, sizeof(SynapticsPrivate));
- if (!priv)
- return NULL;
-
- /* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */
- local = xf86AllocateInput(drv, 0);
- if (!local) {
- xfree(priv);
- return NULL;
- }
-
- /* initialize the InputInfoRec */
- local->name = dev->identifier;
- local->type_name = XI_MOUSE; /* XI_TOUCHPAD and KDE killed the X Server at startup ? */
- local->device_control = DeviceControl;
- local->read_input = ReadInput;
- local->control_proc = ControlProc;
- local->close_proc = CloseProc;
- local->switch_mode = SwitchMode;
- local->conversion_proc = ConvertProc;
- local->reverse_conversion_proc = NULL;
- local->dev = NULL;
- local->private = priv;
- local->private_flags = 0;
- local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
- local->conf_idev = dev;
-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
- local->motion_history_proc = xf86GetMotionEvents;
- local->history_size = 0;
-#endif
- local->always_core_feedback = 0;
+ if (percent >= 0.0) {
+ percent = xf86SetPercentOption(options, optname, -1);
+ result = percent / 100.0 * range + offset;
+ } else
+ result = xf86SetIntOption(options, optname, default_value);
- xf86Msg(X_INFO, "Synaptics touchpad driver version %s\n", PACKAGE_VERSION);
+ return result;
+}
- xf86CollectInputOptions(local, NULL, NULL);
+Bool
+SynapticsIsSoftButtonAreasValid(int *values)
+{
+ Bool right_disabled = FALSE;
+ Bool middle_disabled = FALSE;
+
+ enum {
+ /* right button left, right, top, bottom */
+ RBL = 0,
+ RBR = 1,
+ RBT = 2,
+ RBB = 3,
+ /* middle button left, right, top, bottom */
+ MBL = 4,
+ MBR = 5,
+ MBT = 6,
+ MBB = 7,
+ };
+
+ /* Check right button area */
+ if ((((values[RBL] != 0) && (values[RBR] != 0)) && (values[RBL] > values[RBR])) ||
+ (((values[RBT] != 0) && (values[RBB] != 0)) && (values[RBT] > values[RBB])))
+ return FALSE;
+
+ /* Check middle button area */
+ if ((((values[MBL] != 0) && (values[MBR] != 0)) && (values[MBL] > values[MBR])) ||
+ (((values[MBT] != 0) && (values[MBB] != 0)) && (values[MBT] > values[MBB])))
+ return FALSE;
+
+ if (values[RBL] == 0 && values[RBR] == 0 && values[RBT] == 0 && values[RBB] == 0)
+ right_disabled = TRUE;
+
+ if (values[MBL] == 0 && values[MBR] == 0 && values[MBT] == 0 && values[MBB] == 0)
+ middle_disabled = TRUE;
+
+ if (!right_disabled &&
+ ((values[RBL] && values[RBL] == values[RBR]) ||
+ (values[RBT] && values[RBT] == values[RBB])))
+ return FALSE;
+
+ if (!middle_disabled &&
+ ((values[MBL] && values[MBL] == values[MBR]) ||
+ (values[MBT] && values[MBT] == values[MBB])))
+ return FALSE;
+
+ /* Check for overlapping button areas */
+ if (!right_disabled && !middle_disabled) {
+ int right_left = values[RBL] ? values[RBL] : INT_MIN;
+ int right_right = values[RBR] ? values[RBR] : INT_MAX;
+ int right_top = values[RBT] ? values[RBT] : INT_MIN;
+ int right_bottom = values[RBB] ? values[RBB] : INT_MAX;
+ int middle_left = values[MBL] ? values[MBL] : INT_MIN;
+ int middle_right = values[MBR] ? values[MBR] : INT_MAX;
+ int middle_top = values[MBT] ? values[MBT] : INT_MIN;
+ int middle_bottom = values[MBB] ? values[MBB] : INT_MAX;
+
+ /* If areas overlap in the Y axis */
+ if ((right_bottom <= middle_bottom && right_bottom >= middle_top) ||
+ (right_top <= middle_bottom && right_top >= middle_top)) {
+ /* Check for overlapping left edges */
+ if ((right_left < middle_left && right_right > middle_left) ||
+ (middle_left < right_left && middle_right > right_left))
+ return FALSE;
+
+ /* Check for overlapping right edges */
+ if ((right_right > middle_right && right_left < middle_right) ||
+ (middle_right > right_right && middle_left < right_right))
+ return FALSE;
+ }
+
+ /* If areas overlap in the X axis */
+ if ((right_left >= middle_left && right_left <= middle_right) ||
+ (right_right >= middle_left && right_right <= middle_right)) {
+ /* Check for overlapping top edges */
+ if ((right_top < middle_top && right_bottom > middle_top) ||
+ (middle_top < right_top && middle_bottom > right_top))
+ return FALSE;
+
+ /* Check for overlapping bottom edges */
+ if ((right_bottom > middle_bottom && right_top < middle_bottom) ||
+ (middle_bottom > right_bottom && middle_top < right_bottom))
+ return FALSE;
+ }
+ }
- opts = local->options;
+ return TRUE;
+}
- xf86OptionListReport(opts);
+static void
+set_softbutton_areas_option(InputInfoPtr pInfo, const char *option_name, int offset)
+{
+ SynapticsPrivate *priv = pInfo->private;
+ SynapticsParameters *pars = &priv->synpara;
+ int values[8];
+ int in_percent = 0; /* bitmask for which ones are in % */
+ char *option_string;
+ char *next_num;
+ char *end_str;
+ int i;
+ int width, height;
- SetDeviceAndProtocol(local);
+ if (!pars->clickpad)
+ return;
- /* open the touchpad device */
- local->fd = xf86OpenSerial(opts);
- if (local->fd == -1) {
- ErrorF("Synaptics driver unable to open device\n");
- goto SetupProc_fail;
+ option_string = xf86SetStrOption(pInfo->options, option_name, NULL);
+ if (!option_string)
+ return;
+
+ next_num = option_string;
+
+ for (i = 0; i < 8 && *next_num != '\0'; i++) {
+ long int value = strtol(next_num, &end_str, 0);
+
+ if (value > INT_MAX || value < -INT_MAX)
+ goto fail;
+
+ values[i] = value;
+
+ if (next_num != end_str) {
+ if (*end_str == '%') {
+ in_percent |= 1 << i;
+ end_str++;
+ }
+ next_num = end_str;
+ }
+ else
+ goto fail;
}
- xf86ErrorFVerb(6, "port opened successfully\n");
- /* initialize variables */
- priv->timer = NULL;
- priv->repeatButtons = 0;
- priv->nextRepeat = 0;
- priv->count_packet_finger = 0;
- priv->tap_state = TS_START;
- priv->tap_button = 0;
- priv->tap_button_state = TBS_BUTTON_UP;
- priv->touch_on.millis = 0;
+ if (i < 8 || *next_num != '\0')
+ goto fail;
+
+ width = priv->maxx - priv->minx;
+ height = priv->maxy - priv->miny;
+
+ for (i = 0; in_percent && i < 8; i++) {
+ int base, size;
+
+ if ((in_percent & (1 << i)) == 0 || values[i] == 0)
+ continue;
+
+ size = ((i % 4) < 2) ? width : height;
+ base = ((i % 4) < 2) ? priv->minx : priv->miny;
+ values[i] = base + size * values[i] / 100.0;
+ }
+
+ if (!SynapticsIsSoftButtonAreasValid(values))
+ goto fail;
+
+ memcpy(pars->softbutton_areas[offset], values, 4 * sizeof(int));
+ memcpy(pars->softbutton_areas[offset + 1], values + 4, 4 * sizeof(int));
+
+ free(option_string);
+
+ return;
+
+ fail:
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "invalid %s value '%s', keeping defaults\n",
+ option_name, option_string);
+ free(option_string);
+}
+
+static void
+set_primary_softbutton_areas_option(InputInfoPtr pInfo)
+{
+ set_softbutton_areas_option(pInfo, "SoftButtonAreas", BOTTOM_BUTTON_AREA);
+}
+
+static void
+set_secondary_softbutton_areas_option(InputInfoPtr pInfo)
+{
+ set_softbutton_areas_option(pInfo, "SecondarySoftButtonAreas", TOP_BUTTON_AREA);
+}
+
+static void
+set_default_parameters(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = pInfo->private; /* read-only */
+ pointer opts = pInfo->options; /* read-only */
+ SynapticsParameters *pars = &priv->synpara; /* modified */
+
+ int horizScrollDelta, vertScrollDelta; /* pixels */
+ int tapMove; /* pixels */
+ int l, r, t, b; /* left, right, top, bottom */
+ double accelFactor; /* 1/pixels */
+ int fingerLow, fingerHigh; /* pressure */
+ int emulateTwoFingerMinZ; /* pressure */
+ int emulateTwoFingerMinW; /* width */
+ int pressureMotionMinZ, pressureMotionMaxZ; /* pressure */
+ int palmMinWidth, palmMinZ; /* pressure */
+ int tapButton1, tapButton2, tapButton3;
+ int clickFinger1, clickFinger2, clickFinger3;
+ Bool vertEdgeScroll, horizEdgeScroll;
+ Bool vertTwoFingerScroll, horizTwoFingerScroll;
+ int horizResolution = 1;
+ int vertResolution = 1;
+ int width, height, diag, range;
+ int horizHyst, vertHyst;
+ int middle_button_timeout;
+ int grab_event_device = 0;
+ const char *source;
+
+ /* The synaptics specs specify typical edge widths of 4% on x, and 5.4% on
+ * y (page 7) [Synaptics TouchPad Interfacing Guide, 510-000080 - A
+ * Second Edition, http://www.synaptics.com/support/dev_support.cfm, 8 Sep
+ * 2008]. We use 7% for both instead for synaptics devices, and 15% for
+ * ALPS models.
+ * http://bugs.freedesktop.org/show_bug.cgi?id=21214
+ *
+ * If the range was autodetected, apply these edge widths to all four
+ * sides.
+ */
+
+ width = abs(priv->maxx - priv->minx);
+ height = abs(priv->maxy - priv->miny);
+ diag = sqrt(width * width + height * height);
+
+ calculate_edge_widths(priv, &l, &r, &t, &b);
+
+ /* Again, based on typical x/y range and defaults */
+ horizScrollDelta = diag * .020;
+ vertScrollDelta = diag * .020;
+ tapMove = diag * .044;
+ accelFactor = 200.0 / diag; /* trial-and-error */
+
+ /* hysteresis, assume >= 0 is a detected value (e.g. evdev fuzz) */
+ horizHyst = pars->hyst_x >= 0 ? pars->hyst_x : diag * 0.005;
+ vertHyst = pars->hyst_y >= 0 ? pars->hyst_y : diag * 0.005;
+
+ range = priv->maxp - priv->minp + 1;
+
+ calculate_tap_hysteresis(priv, range, &fingerLow, &fingerHigh);
+
+ /* scaling based on defaults and a pressure of 256 */
+ emulateTwoFingerMinZ = priv->minp + range * (282.0 / 256);
+ pressureMotionMinZ = priv->minp + range * (30.0 / 256);
+ pressureMotionMaxZ = priv->minp + range * (160.0 / 256);
+ palmMinZ = priv->minp + range * (200.0 / 256);
+
+ range = priv->maxw - priv->minw + 1;
- /* install shared memory or normal memory for parameters */
- priv->shm_config = xf86SetBoolOption(opts, "SHMConfig", FALSE);
-
- /* read the parameters */
- pars = &priv->synpara_default;
- pars->version = (PACKAGE_VERSION_MAJOR*10000+PACKAGE_VERSION_MINOR*100+PACKAGE_VERSION_PATCHLEVEL);
-
- if (priv->maxx && priv->maxy) {
- int xsize = priv->maxx - priv->minx;
- int ysize = priv->maxy - priv->miny;
- int xedgesize = xsize * 0.1;
- int yedgesize = ysize * 0.1;
-
- pars->left_edge = xf86SetIntOption(opts, "LeftEdge", priv->minx +
- xedgesize);
- pars->right_edge = xf86SetIntOption(opts, "RightEdge", priv->maxx -
- xedgesize);
- pars->top_edge = xf86SetIntOption(opts, "TopEdge", priv->miny +
- yedgesize);
- pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge",
- priv->maxy - yedgesize);
- pars->scroll_dist_vert = xf86SetIntOption(opts, "VertScrollDelta",
- 0.02*ysize);
- pars->scroll_dist_horiz = xf86SetIntOption(opts,
- "HorizScrollDelta",
- 0.02*xsize);
- pars->edge_motion_min_speed = xf86SetIntOption(opts,
- "EdgeMotionMinSpeed", 1);
- pars->edge_motion_max_speed = xf86SetIntOption(opts,
- "EdgeMotionMaxSpeed", ysize * 0.1);
- pars->min_speed = synSetFloatOption(opts, "MinSpeed", 250.0 / ysize);
- pars->max_speed = synSetFloatOption(opts, "MaxSpeed", 600.0 / ysize);
- pars->accl = synSetFloatOption(opts, "AccelFactor", 5.0 / ysize);
- } else {
- pars->left_edge = xf86SetIntOption(opts, "LeftEdge", 1900);
- pars->right_edge = xf86SetIntOption(opts, "RightEdge", 5400);
- pars->top_edge = xf86SetIntOption(opts, "TopEdge", 1900);
- pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", 4000);
- pars->scroll_dist_vert = xf86SetIntOption(opts, "VertScrollDelta",
- 100);
- pars->scroll_dist_horiz = xf86SetIntOption(opts,
- "HorizScrollDelta",
- 100);
- pars->edge_motion_min_speed = xf86SetIntOption(opts,
- "EdgeMotionMinSpeed", 1);
- pars->edge_motion_max_speed = xf86SetIntOption(opts,
- "EdgeMotionMaxSpeed", 400);
- pars->min_speed = synSetFloatOption(opts, "MinSpeed", 0.09);
- pars->max_speed = synSetFloatOption(opts, "MaxSpeed", 0.18);
- pars->accl = synSetFloatOption(opts, "AccelFactor", 0.0015);
- }
- pars->finger_low = xf86SetIntOption(opts, "FingerLow", 25);
- pars->finger_high = xf86SetIntOption(opts, "FingerHigh", 30);
- pars->finger_press = xf86SetIntOption(opts, "FingerPress", 256);
+ /* scaling based on defaults below and a tool width of 16 */
+ palmMinWidth = priv->minw + range * (10.0 / 16);
+ emulateTwoFingerMinW = priv->minw + range * (7.0 / 16);
+
+ /* Enable tap if we don't have a phys left button */
+ tapButton1 = priv->has_left ? 0 : 1;
+ tapButton2 = priv->has_left ? 0 : 3;
+ tapButton3 = priv->has_left ? 0 : 2;
+
+ /* Enable multifinger-click if only have one physical button,
+ otherwise clickFinger is always button 1. */
+ clickFinger1 = 1;
+ clickFinger2 = (priv->has_right || priv->has_middle) ? 1 : 3;
+ clickFinger3 = (priv->has_right || priv->has_middle) ? 1 : 2;
+
+ /* Enable vert edge scroll if we can't detect doubletap */
+ vertEdgeScroll = priv->has_double ? FALSE : TRUE;
+ horizEdgeScroll = FALSE;
+
+ /* Enable twofinger scroll if we can detect doubletap */
+ vertTwoFingerScroll = priv->has_double ? TRUE : FALSE;
+ horizTwoFingerScroll = FALSE;
+
+ /* Use resolution reported by hardware if available */
+ if ((priv->resx > 0) && (priv->resy > 0)) {
+ horizResolution = priv->resx;
+ vertResolution = priv->resy;
+ }
+
+ /* set the parameters */
+ pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l);
+ pars->right_edge = xf86SetIntOption(opts, "RightEdge", r);
+ pars->top_edge = xf86SetIntOption(opts, "TopEdge", t);
+ pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", b);
+
+ pars->area_top_edge =
+ set_percent_option(opts, "AreaTopEdge", height, priv->miny, 0);
+ pars->area_bottom_edge =
+ set_percent_option(opts, "AreaBottomEdge", height, priv->miny, 0);
+ pars->area_left_edge =
+ set_percent_option(opts, "AreaLeftEdge", width, priv->minx, 0);
+ pars->area_right_edge =
+ set_percent_option(opts, "AreaRightEdge", width, priv->minx, 0);
+
+ pars->hyst_x =
+ set_percent_option(opts, "HorizHysteresis", width, 0, horizHyst);
+ pars->hyst_y =
+ set_percent_option(opts, "VertHysteresis", height, 0, vertHyst);
+
+ pars->finger_low = xf86SetIntOption(opts, "FingerLow", fingerLow);
+ pars->finger_high = xf86SetIntOption(opts, "FingerHigh", fingerHigh);
pars->tap_time = xf86SetIntOption(opts, "MaxTapTime", 180);
- pars->tap_move = xf86SetIntOption(opts, "MaxTapMove", 220);
+ pars->tap_move = xf86SetIntOption(opts, "MaxTapMove", tapMove);
pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180);
pars->click_time = xf86SetIntOption(opts, "ClickTime", 100);
- pars->fast_taps = xf86SetIntOption(opts, "FastTaps", FALSE);
- pars->emulate_mid_button_time = xf86SetIntOption(opts,
- "EmulateMidButtonTime", 75);
- pars->emulate_twofinger_z = xf86SetIntOption(opts, "EmulateTwoFingerMinZ", 257);
- pars->scroll_edge_vert = xf86SetBoolOption(opts, "VertEdgeScroll", TRUE);
- pars->scroll_edge_horiz = xf86SetBoolOption(opts, "HorizEdgeScroll", TRUE);
+ pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad); /* Probed */
+ if (pars->clickpad)
+ pars->has_secondary_buttons = xf86SetBoolOption(opts,
+ "HasSecondarySoftButtons",
+ pars->has_secondary_buttons);
+ pars->clickpad_ignore_motion_time = 100; /* ms */
+ /* middle mouse button emulation on a clickpad? nah, you're joking */
+ middle_button_timeout = pars->clickpad ? 0 : 75;
+ pars->emulate_mid_button_time =
+ xf86SetIntOption(opts, "EmulateMidButtonTime", middle_button_timeout);
+ pars->emulate_twofinger_z =
+ xf86SetIntOption(opts, "EmulateTwoFingerMinZ", emulateTwoFingerMinZ);
+ pars->emulate_twofinger_w =
+ xf86SetIntOption(opts, "EmulateTwoFingerMinW", emulateTwoFingerMinW);
+ pars->scroll_dist_vert =
+ xf86SetIntOption(opts, "VertScrollDelta", vertScrollDelta);
+ pars->scroll_dist_horiz =
+ xf86SetIntOption(opts, "HorizScrollDelta", horizScrollDelta);
+ pars->scroll_edge_vert =
+ xf86SetBoolOption(opts, "VertEdgeScroll", vertEdgeScroll);
+ pars->scroll_edge_horiz =
+ xf86SetBoolOption(opts, "HorizEdgeScroll", horizEdgeScroll);
pars->scroll_edge_corner = xf86SetBoolOption(opts, "CornerCoasting", FALSE);
- pars->scroll_twofinger_vert = xf86SetBoolOption(opts, "VertTwoFingerScroll", FALSE);
- pars->scroll_twofinger_horiz = xf86SetBoolOption(opts, "HorizTwoFingerScroll", FALSE);
- pars->edge_motion_min_z = xf86SetIntOption(opts, "EdgeMotionMinZ", 30);
- pars->edge_motion_max_z = xf86SetIntOption(opts, "EdgeMotionMaxZ", 160);
- pars->edge_motion_use_always = xf86SetBoolOption(opts, "EdgeMotionUseAlways", FALSE);
- repeater = xf86SetStrOption(opts, "Repeater", NULL);
- pars->updown_button_scrolling = xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
- pars->leftright_button_scrolling = xf86SetBoolOption(opts, "LeftRightScrolling", TRUE);
- pars->updown_button_repeat = xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE);
- pars->leftright_button_repeat = xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE);
- pars->scroll_button_repeat = xf86SetIntOption(opts,"ScrollButtonRepeat", 100);
- pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", 0);
- pars->guestmouse_off = xf86SetBoolOption(opts, "GuestMouseOff", FALSE);
+ pars->scroll_twofinger_vert =
+ xf86SetBoolOption(opts, "VertTwoFingerScroll", vertTwoFingerScroll);
+ pars->scroll_twofinger_horiz =
+ xf86SetBoolOption(opts, "HorizTwoFingerScroll", horizTwoFingerScroll);
+ pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", TOUCHPAD_ON);
+
+ if (priv->has_scrollbuttons) {
+ pars->updown_button_scrolling =
+ xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
+ pars->leftright_button_scrolling =
+ xf86SetBoolOption(opts, "LeftRightScrolling", TRUE);
+ pars->updown_button_repeat =
+ xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE);
+ pars->leftright_button_repeat =
+ xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE);
+ }
+ pars->scroll_button_repeat =
+ xf86SetIntOption(opts, "ScrollButtonRepeat", 100);
+
pars->locked_drags = xf86SetBoolOption(opts, "LockedDrags", FALSE);
pars->locked_drag_time = xf86SetIntOption(opts, "LockedDragTimeout", 5000);
- pars->tap_action[RT_TAP] = xf86SetIntOption(opts, "RTCornerButton", 2);
- pars->tap_action[RB_TAP] = xf86SetIntOption(opts, "RBCornerButton", 3);
+ pars->tap_action[RT_TAP] = xf86SetIntOption(opts, "RTCornerButton", 0);
+ pars->tap_action[RB_TAP] = xf86SetIntOption(opts, "RBCornerButton", 0);
pars->tap_action[LT_TAP] = xf86SetIntOption(opts, "LTCornerButton", 0);
pars->tap_action[LB_TAP] = xf86SetIntOption(opts, "LBCornerButton", 0);
- pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1", 1);
- pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2", 2);
- pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3", 3);
- pars->circular_scrolling = xf86SetBoolOption(opts, "CircularScrolling", FALSE);
- pars->circular_trigger = xf86SetIntOption(opts, "CircScrollTrigger", 0);
- pars->circular_pad = xf86SetBoolOption(opts, "CircularPad", FALSE);
- pars->palm_detect = xf86SetBoolOption(opts, "PalmDetect", TRUE);
- pars->palm_min_width = xf86SetIntOption(opts, "PalmMinWidth", 10);
- pars->palm_min_z = xf86SetIntOption(opts, "PalmMinZ", 200);
+ pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1", tapButton1);
+ pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2", tapButton2);
+ pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3", tapButton3);
+ pars->click_action[F1_CLICK1] =
+ xf86SetIntOption(opts, "ClickFinger1", clickFinger1);
+ pars->click_action[F2_CLICK1] =
+ xf86SetIntOption(opts, "ClickFinger2", clickFinger2);
+ pars->click_action[F3_CLICK1] =
+ xf86SetIntOption(opts, "ClickFinger3", clickFinger3);
+ pars->circular_scrolling =
+ xf86SetBoolOption(opts, "CircularScrolling", FALSE);
+ pars->circular_trigger = xf86SetIntOption(opts, "CircScrollTrigger", 0);
+ pars->circular_pad = xf86SetBoolOption(opts, "CircularPad", FALSE);
+ pars->palm_detect = xf86SetBoolOption(opts, "PalmDetect", FALSE);
+ pars->palm_min_width = xf86SetIntOption(opts, "PalmMinWidth", palmMinWidth);
+ pars->palm_min_z = xf86SetIntOption(opts, "PalmMinZ", palmMinZ);
pars->single_tap_timeout = xf86SetIntOption(opts, "SingleTapTimeout", 180);
- pars->press_motion_min_z = xf86SetIntOption(opts, "PressureMotionMinZ", pars->edge_motion_min_z);
- pars->press_motion_max_z = xf86SetIntOption(opts, "PressureMotionMaxZ", pars->edge_motion_max_z);
+ pars->press_motion_min_z =
+ xf86SetIntOption(opts, "PressureMotionMinZ", pressureMotionMinZ);
+ pars->press_motion_max_z =
+ xf86SetIntOption(opts, "PressureMotionMaxZ", pressureMotionMaxZ);
+
+ pars->min_speed = xf86SetRealOption(opts, "MinSpeed", 0.4);
+ pars->max_speed = xf86SetRealOption(opts, "MaxSpeed", 0.7);
+ pars->accl = xf86SetRealOption(opts, "AccelFactor", accelFactor);
+ pars->scroll_dist_circ = xf86SetRealOption(opts, "CircScrollDelta", 0.1);
+ pars->coasting_speed = xf86SetRealOption(opts, "CoastingSpeed", 20.0);
+ pars->coasting_friction = xf86SetRealOption(opts, "CoastingFriction", 50);
+ pars->press_motion_min_factor =
+ xf86SetRealOption(opts, "PressureMotionMinFactor", 1.0);
+ pars->press_motion_max_factor =
+ xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0);
+
+ /* Only grab the device by default if it's not coming from a config
+ backend. This way we avoid the device being added twice and sending
+ duplicate events.
+ */
+ source = xf86CheckStrOption(opts, "_source", NULL);
+ if (source == NULL || strncmp(source, "server/", 7) != 0)
+ grab_event_device = TRUE;
+ pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", grab_event_device);
+
+ pars->tap_and_drag_gesture =
+ xf86SetBoolOption(opts, "TapAndDragGesture", TRUE);
+ pars->resolution_horiz =
+ xf86SetIntOption(opts, "HorizResolution", horizResolution);
+ pars->resolution_vert =
+ xf86SetIntOption(opts, "VertResolution", vertResolution);
+ if (pars->resolution_horiz <= 0) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "Invalid X resolution, using 1 instead.\n");
+ pars->resolution_horiz = 1;
+ }
+ if (pars->resolution_vert <= 0) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "Invalid Y resolution, using 1 instead.\n");
+ pars->resolution_vert = 1;
+ }
+
+ /* Touchpad sampling rate is too low to detect all movements.
+ A user may lift one finger and put another one down within the same
+ EV_SYN or even between samplings so the driver doesn't notice at all.
+
+ We limit the movement to 20 mm within one event, that is more than
+ recordings showed is needed (17mm on a T440).
+ */
+ if (pars->resolution_horiz > 1 &&
+ pars->resolution_vert > 1)
+ pars->maxDeltaMM = 20;
+ else {
+ /* on devices without resolution set the vector length to 0.25 of
+ the touchpad diagonal */
+ pars->maxDeltaMM = diag * 0.25;
+ }
- pars->trackstick_speed = synSetFloatOption(opts, "TrackstickSpeed", 40);
- pars->scroll_dist_circ = synSetFloatOption(opts, "CircScrollDelta", 0.1);
- pars->coasting_speed = synSetFloatOption(opts, "CoastingSpeed", 0.0);
- pars->press_motion_min_factor = synSetFloatOption(opts, "PressureMotionMinFactor", 1.0);
- pars->press_motion_max_factor = synSetFloatOption(opts, "PressureMotionMaxFactor", 1.0);
- pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", TRUE);
/* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
if (pars->top_edge > pars->bottom_edge) {
- int tmp = pars->top_edge;
- pars->top_edge = pars->bottom_edge;
- pars->bottom_edge = tmp;
- xf86Msg(X_WARNING, "%s: TopEdge is bigger than BottomEdge. Fixing.\n",
- local->name);
+ int tmp = pars->top_edge;
+
+ pars->top_edge = pars->bottom_edge;
+ pars->bottom_edge = tmp;
+ xf86IDrvMsg(pInfo, X_WARNING,
+ "TopEdge is bigger than BottomEdge. Fixing.\n");
}
- priv->largest_valid_x = MIN(pars->right_edge, XMAX_NOMINAL);
+ set_primary_softbutton_areas_option(pInfo);
+ if (pars->has_secondary_buttons)
+ set_secondary_softbutton_areas_option(pInfo);
+}
- if (!alloc_param_data(local))
- goto SetupProc_fail;
+static double
+SynapticsAccelerationProfile(DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ double velocity, double thr, double acc)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ SynapticsParameters *para = &priv->synpara;
- priv->comm.buffer = XisbNew(local->fd, 200);
- DBG(9, XisbTrace(priv->comm.buffer, 1));
+ double accelfct;
- priv->fifofd = -1;
- if (repeater) {
- /* create repeater fifo */
- status = mknod(repeater, 666, S_IFIFO);
- if ((status != 0) && (status != EEXIST)) {
- xf86Msg(X_ERROR, "%s can't create repeater fifo\n", local->name);
- } else {
- /* open the repeater fifo */
- optList = xf86NewOption("Device", repeater);
- if ((priv->fifofd = xf86OpenSerial(optList)) == -1) {
- xf86Msg(X_ERROR, "%s repeater device open failed\n", local->name);
- }
- }
- free(repeater);
+ /*
+ * synaptics accel was originally base on device coordinate based
+ * velocity, which we recover this way so para->accl retains its scale.
+ */
+ velocity /= vel->const_acceleration;
+
+ /* speed up linear with finger velocity */
+ accelfct = velocity * para->accl;
+
+ /* clip acceleration factor */
+ if (accelfct > para->max_speed * acc)
+ accelfct = para->max_speed * acc;
+ else if (accelfct < para->min_speed)
+ accelfct = para->min_speed;
+
+ /* modify speed according to pressure */
+ if (priv->moving_state == MS_TOUCHPAD_RELATIVE) {
+ int minZ = para->press_motion_min_z;
+ int maxZ = para->press_motion_max_z;
+ double minFctr = para->press_motion_min_factor;
+ double maxFctr = para->press_motion_max_factor;
+
+ if (priv->hwState->z <= minZ) {
+ accelfct *= minFctr;
+ }
+ else if (priv->hwState->z >= maxZ) {
+ accelfct *= maxFctr;
+ }
+ else {
+ accelfct *=
+ minFctr + (priv->hwState->z - minZ) * (maxFctr -
+ minFctr) / (maxZ - minZ);
+ }
}
- if (!QueryHardware(local)) {
- xf86Msg(X_ERROR, "%s Unable to query/initialize Synaptics hardware.\n", local->name);
- goto SetupProc_fail;
+ return accelfct;
+}
+
+static int
+SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+ SynapticsPrivate *priv;
+
+ /* allocate memory for SynapticsPrivateRec */
+ priv = calloc(1, sizeof(SynapticsPrivate));
+ if (!priv)
+ return BadAlloc;
+
+ pInfo->type_name = XI_TOUCHPAD;
+ pInfo->device_control = DeviceControl;
+ pInfo->read_input = ReadInput;
+ pInfo->control_proc = ControlProc;
+ pInfo->switch_mode = SwitchMode;
+ pInfo->private = priv;
+
+ /* allocate now so we don't allocate in the signal handler */
+ priv->timer = TimerSet(NULL, 0, 0, NULL, NULL);
+ if (!priv->timer) {
+ free(priv);
+ return BadAlloc;
+ }
+
+ /* may change pInfo->options */
+ if (!SetDeviceAndProtocol(pInfo)) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "Synaptics driver unable to detect protocol\n");
+ goto SetupProc_fail;
}
- xf86ProcessCommonOptions(local, opts);
- local->flags |= XI86_CONFIGURED;
+ priv->device = xf86FindOptionValue(pInfo->options, "Device");
- if (local->fd != -1) {
- if (priv->comm.buffer) {
- XisbFree(priv->comm.buffer);
- priv->comm.buffer = NULL;
- }
- xf86CloseSerial(local->fd);
+ /* open the touchpad device */
+ pInfo->fd = xf86OpenSerial(pInfo->options);
+ if (pInfo->fd == -1) {
+ xf86IDrvMsg(pInfo, X_ERROR, "Synaptics driver unable to open device\n");
+ goto SetupProc_fail;
}
- local->fd = -1;
- return local;
+ xf86ErrorFVerb(6, "port opened successfully\n");
- SetupProc_fail:
- if (local->fd >= 0) {
- xf86CloseSerial(local->fd);
- local->fd = -1;
+ /* initialize variables */
+ priv->repeatButtons = 0;
+ priv->nextRepeat = 0;
+ priv->count_packet_finger = 0;
+ priv->tap_state = TS_START;
+ priv->tap_button = 0;
+ priv->tap_button_state = TBS_BUTTON_UP;
+ priv->touch_on.millis = 0;
+ priv->synpara.hyst_x = -1;
+ priv->synpara.hyst_y = -1;
+
+ /* read hardware dimensions */
+ ReadDevDimensions(pInfo);
+
+ set_default_parameters(pInfo);
+
+#ifndef NO_DRIVER_SCALING
+ CalculateScalingCoeffs(priv);
+#endif
+
+
+ priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE);
+
+ if (!QueryHardware(pInfo)) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "Unable to query/initialize Synaptics hardware.\n");
+ goto SetupProc_fail;
}
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+ if (priv->comm.buffer) {
+ XisbFree(priv->comm.buffer);
+ priv->comm.buffer = NULL;
+ }
+ SynapticsCloseFd(pInfo);
+
+ return Success;
+
+ SetupProc_fail:
+ SynapticsCloseFd(pInfo);
+
if (priv->comm.buffer)
- XisbFree(priv->comm.buffer);
- free_param_data(priv);
- /* Freeing priv makes the X server crash. Don't know why.
- xfree(priv);
- */
- return local;
+ XisbFree(priv->comm.buffer);
+ free(priv->proto_data);
+ free(priv->timer);
+ free(priv);
+ pInfo->private = NULL;
+ return BadAlloc;
+}
+
+/*
+ * Uninitialize the device.
+ */
+static void
+SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+ SynapticsPrivate *priv = ((SynapticsPrivate *) pInfo->private);
+
+ if (priv && priv->timer)
+ free(priv->timer);
+ if (priv && priv->proto_data)
+ free(priv->proto_data);
+ if (priv && priv->scroll_events_mask)
+ valuator_mask_free(&priv->scroll_events_mask);
+ if (priv && priv->open_slots)
+ free(priv->open_slots);
+ free(pInfo->private);
+ pInfo->private = NULL;
+ xf86DeleteInput(pInfo, 0);
}
/*
@@ -548,161 +975,389 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
* protocol values are handled by dix.
*/
static void
-SynapticsCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
+SynapticsCtrl(DeviceIntPtr device, PtrCtrl * ctrl)
{
- DBG(3, ErrorF("SynapticsCtrl called.\n"));
- /*
- pInfo = device->public.devicePrivate;
- pMse = pInfo->private;
-
- pMse->num = ctrl->num;
- pMse->den = ctrl->den;
- pMse->threshold = ctrl->threshold;
- */
}
-static Bool
+static int
DeviceControl(DeviceIntPtr dev, int mode)
{
Bool RetValue;
switch (mode) {
case DEVICE_INIT:
- RetValue = DeviceInit(dev);
- break;
+ RetValue = DeviceInit(dev);
+ break;
case DEVICE_ON:
- RetValue = DeviceOn(dev);
- break;
+ RetValue = DeviceOn(dev);
+ break;
case DEVICE_OFF:
- RetValue = DeviceOff(dev);
- break;
+ RetValue = DeviceOff(dev);
+ break;
case DEVICE_CLOSE:
- RetValue = DeviceClose(dev);
- break;
+ RetValue = DeviceClose(dev);
+ break;
default:
- RetValue = BadValue;
+ RetValue = BadValue;
}
return RetValue;
}
-static Bool
+static int
DeviceOn(DeviceIntPtr dev)
{
- LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
- SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- DBG(3, ErrorF("Synaptics DeviceOn called\n"));
+ DBG(3, "Synaptics DeviceOn called\n");
- SetDeviceAndProtocol(local);
- local->fd = xf86OpenSerial(local->options);
- if (local->fd == -1) {
- xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name);
- return !Success;
+ pInfo->fd = xf86OpenSerial(pInfo->options);
+ if (pInfo->fd == -1) {
+ xf86IDrvMsg(pInfo, X_WARNING, "cannot open input device\n");
+ return !Success;
}
- priv->proto_ops->DeviceOnHook(local, priv->synpara);
+ if (priv->proto_ops->DeviceOnHook &&
+ !priv->proto_ops->DeviceOnHook(pInfo, &priv->synpara))
+ goto error;
- priv->comm.buffer = XisbNew(local->fd, 64);
- if (!priv->comm.buffer) {
- xf86CloseSerial(local->fd);
- local->fd = -1;
- return !Success;
- }
+ priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE);
+ if (!priv->comm.buffer)
+ goto error;
- xf86FlushInput(local->fd);
+ xf86FlushInput(pInfo->fd);
/* reinit the pad */
- QueryHardware(local);
- xf86AddEnabledDevice(local);
+ if (!QueryHardware(pInfo))
+ goto error;
+
+ xf86AddEnabledDevice(pInfo);
dev->public.on = TRUE;
return Success;
+
+error:
+ if (priv->comm.buffer) {
+ XisbFree(priv->comm.buffer);
+ priv->comm.buffer = NULL;
+ }
+ SynapticsCloseFd(pInfo);
+ return !Success;
}
-static Bool
-DeviceOff(DeviceIntPtr dev)
+static void
+SynapticsReset(SynapticsPrivate * priv)
{
- LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
- SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
+ int i;
+
+ SynapticsResetHwState(priv->hwState);
+ SynapticsResetHwState(priv->local_hw_state);
+ SynapticsResetHwState(priv->comm.hwState);
+
+ memset(priv->move_hist, 0, sizeof(priv->move_hist));
+ priv->hyst_center_x = 0;
+ priv->hyst_center_y = 0;
+ memset(&priv->scroll, 0, sizeof(priv->scroll));
+ priv->count_packet_finger = 0;
+ priv->finger_state = FS_UNTOUCHED;
+ priv->last_motion_millis = 0;
+ priv->clickpad_click_millis = 0;
+ priv->last_button_area = NO_BUTTON_AREA;
+ priv->tap_state = TS_START;
+ priv->tap_button = 0;
+ priv->tap_button_state = TBS_BUTTON_UP;
+ priv->moving_state = MS_FALSE;
+ priv->vert_scroll_edge_on = FALSE;
+ priv->horiz_scroll_edge_on = FALSE;
+ priv->vert_scroll_twofinger_on = FALSE;
+ priv->horiz_scroll_twofinger_on = FALSE;
+ priv->circ_scroll_on = FALSE;
+ priv->circ_scroll_vert = FALSE;
+ priv->mid_emu_state = MBE_OFF;
+ priv->nextRepeat = 0;
+ priv->lastButtons = 0;
+ priv->prev_z = 0;
+ priv->prevFingers = 0;
+ priv->num_active_touches = 0;
- DBG(3, ErrorF("Synaptics DeviceOff called\n"));
+ for (i = 0; i < priv->num_slots; i++)
+ priv->open_slots[i] = -1;
+}
- if (local->fd != -1) {
- TimerFree(priv->timer);
- priv->timer = NULL;
- xf86RemoveEnabledDevice(local);
- priv->proto_ops->DeviceOffHook(local);
- if (priv->comm.buffer) {
- XisbFree(priv->comm.buffer);
- priv->comm.buffer = NULL;
- }
- xf86CloseSerial(local->fd);
+static int
+DeviceOff(DeviceIntPtr dev)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ Bool rc = Success;
+
+ DBG(3, "Synaptics DeviceOff called\n");
+
+ if (pInfo->fd != -1) {
+ TimerCancel(priv->timer);
+ xf86RemoveEnabledDevice(pInfo);
+ SynapticsReset(priv);
+
+ if (priv->proto_ops->DeviceOffHook &&
+ !priv->proto_ops->DeviceOffHook(pInfo))
+ rc = !Success;
+ if (priv->comm.buffer) {
+ XisbFree(priv->comm.buffer);
+ priv->comm.buffer = NULL;
+ }
+ SynapticsCloseFd(pInfo);
}
dev->public.on = FALSE;
- return Success;
+ return rc;
}
-static Bool
+static int
DeviceClose(DeviceIntPtr dev)
{
Bool RetValue;
- LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
- SynapticsPrivate *priv = (SynapticsPrivate *) local->private;
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
RetValue = DeviceOff(dev);
- free_param_data(priv);
+ TimerFree(priv->timer);
+ priv->timer = NULL;
+ free(priv->touch_axes);
+ priv->touch_axes = NULL;
+ SynapticsHwStateFree(&priv->hwState);
+ SynapticsHwStateFree(&priv->local_hw_state);
+ SynapticsHwStateFree(&priv->comm.hwState);
return RetValue;
}
-static Bool
+static void
+InitAxesLabels(Atom *labels, int nlabels, const SynapticsPrivate * priv)
+{
+ int i;
+
+ memset(labels, 0, nlabels * sizeof(Atom));
+ switch (nlabels) {
+ default:
+ case 4:
+ labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
+ case 3:
+ labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+ case 2:
+ labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+ case 1:
+ labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+ break;
+ }
+
+ for (i = 0; i < priv->num_mt_axes; i++) {
+ SynapticsTouchAxisRec *axis = &priv->touch_axes[i];
+ int axnum = nlabels - priv->num_mt_axes + i;
+
+ labels[axnum] = XIGetKnownProperty(axis->label);
+ }
+}
+
+static void
+InitButtonLabels(Atom *labels, int nlabels)
+{
+ memset(labels, 0, nlabels * sizeof(Atom));
+ switch (nlabels) {
+ default:
+ case 7:
+ labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+ case 6:
+ labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+ case 5:
+ labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+ case 4:
+ labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
+ case 3:
+ labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+ case 2:
+ labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+ case 1:
+ labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+ break;
+ }
+}
+
+static void
+DeviceInitTouch(DeviceIntPtr dev, Atom *axes_labels)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+
+ if (!priv->has_touch)
+ return;
+
+ priv->num_slots =
+ priv->max_touches ? priv->max_touches : SYNAPTICS_MAX_TOUCHES;
+
+ priv->open_slots = malloc(priv->num_slots * sizeof(int));
+ if (!priv->open_slots) {
+ xf86IDrvMsg(pInfo, X_ERROR,
+ "failed to allocate open touch slots array\n");
+ priv->has_touch = 0;
+ priv->num_slots = 0;
+ }
+}
+
+static int
DeviceInit(DeviceIntPtr dev)
{
- LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ Atom float_type, prop;
+ float tmpf;
unsigned char map[SYN_MAX_BUTTONS + 1];
int i;
+ int min, max;
+ int num_axes = 2;
+ Atom btn_labels[SYN_MAX_BUTTONS] = { 0 };
+ Atom *axes_labels;
+ DeviceVelocityPtr pVel;
- DBG(3, ErrorF("Synaptics DeviceInit called\n"));
+ num_axes += 2;
+
+ num_axes += priv->num_mt_axes;
+
+ axes_labels = calloc(num_axes, sizeof(Atom));
+ if (!axes_labels) {
+ xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate axis labels\n");
+ return !Success;
+ }
+
+ InitAxesLabels(axes_labels, num_axes, priv);
+ InitButtonLabels(btn_labels, SYN_MAX_BUTTONS);
+
+ DBG(3, "Synaptics DeviceInit called\n");
for (i = 0; i <= SYN_MAX_BUTTONS; i++)
- map[i] = i;
+ map[i] = i;
dev->public.on = FALSE;
- InitPointerDeviceStruct((DevicePtr)dev, map,
- SYN_MAX_BUTTONS,
-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
- miPointerGetMotionEvents,
-#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
- GetMotionHistory,
-#endif
- SynapticsCtrl,
-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
- miPointerGetMotionBufferSize()
-#else
- GetMotionHistorySize(), 2
-#endif
- );
+ InitPointerDeviceStruct((DevicePtr) dev, map,
+ SYN_MAX_BUTTONS,
+ btn_labels,
+ SynapticsCtrl,
+ GetMotionHistorySize(), num_axes, axes_labels);
+
+ /*
+ * setup dix acceleration to match legacy synaptics settings, and
+ * etablish a device-specific profile to do stuff like pressure-related
+ * acceleration.
+ */
+ if (NULL != (pVel = GetDevicePredictableAccelData(dev))) {
+ SetDeviceSpecificAccelerationProfile(pVel,
+ SynapticsAccelerationProfile);
+
+ /* float property type */
+ float_type = XIGetKnownProperty(XATOM_FLOAT);
+
+ /* translate MinAcc to constant deceleration.
+ * May be overridden in xf86InitValuatorDefaults */
+ tmpf = 1.0 / priv->synpara.min_speed;
+
+ xf86IDrvMsg(pInfo, X_CONFIG,
+ "(accel) MinSpeed is now constant deceleration " "%.1f\n",
+ tmpf);
+ prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
+ XIChangeDeviceProperty(dev, prop, float_type, 32,
+ PropModeReplace, 1, &tmpf, FALSE);
+
+ /* adjust accordingly */
+ priv->synpara.max_speed /= priv->synpara.min_speed;
+ priv->synpara.min_speed = 1.0;
+
+ /* synaptics seems to report 80 packet/s, but dix scales for
+ * 100 packet/s by default. */
+ pVel->corr_mul = 12.5f; /*1000[ms]/80[/s] = 12.5 */
+
+ xf86IDrvMsg(pInfo, X_CONFIG, "(accel) MaxSpeed is now %.2f\n",
+ priv->synpara.max_speed);
+ xf86IDrvMsg(pInfo, X_CONFIG, "(accel) AccelFactor is now %.3f\n",
+ priv->synpara.accl);
+
+ prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
+ i = AccelProfileDeviceSpecific;
+ XIChangeDeviceProperty(dev, prop, XA_INTEGER, 32,
+ PropModeReplace, 1, &i, FALSE);
+ }
+
/* X valuator */
- xf86InitValuatorAxisStruct(dev, 0, 0, -1, 1, 0, 1);
+ if (priv->minx < priv->maxx) {
+ min = priv->minx;
+ max = priv->maxx;
+ }
+ else {
+ min = 0;
+ max = -1;
+ }
+
+ xf86InitValuatorAxisStruct(dev, 0, axes_labels[0], min, max,
+ priv->resx * 1000, 0, priv->resx * 1000,
+ Relative);
xf86InitValuatorDefaults(dev, 0);
+
/* Y valuator */
- xf86InitValuatorAxisStruct(dev, 1, 0, -1, 1, 0, 1);
+ if (priv->miny < priv->maxy) {
+ min = priv->miny;
+ max = priv->maxy;
+ }
+ else {
+ min = 0;
+ max = -1;
+ }
+
+ xf86InitValuatorAxisStruct(dev, 1, axes_labels[1], min, max,
+ priv->resy * 1000, 0, priv->resy * 1000,
+ Relative);
xf86InitValuatorDefaults(dev, 1);
-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
- xf86MotionHistoryAllocate(local);
-#endif
- if (!alloc_param_data(local))
- return !Success;
+ xf86InitValuatorAxisStruct(dev, 2, axes_labels[2], 0, -1, 0, 0, 0,
+ Relative);
+ priv->scroll_axis_horiz = 2;
+ xf86InitValuatorAxisStruct(dev, 3, axes_labels[3], 0, -1, 0, 0, 0,
+ Relative);
+ priv->scroll_axis_vert = 3;
+ priv->scroll_events_mask = valuator_mask_new(MAX_VALUATORS);
+ if (!priv->scroll_events_mask) {
+ free(axes_labels);
+ return !Success;
+ }
+
+ SetScrollValuator(dev, priv->scroll_axis_horiz, SCROLL_TYPE_HORIZONTAL,
+ priv->synpara.scroll_dist_horiz, 0);
+ SetScrollValuator(dev, priv->scroll_axis_vert, SCROLL_TYPE_VERTICAL,
+ priv->synpara.scroll_dist_vert, 0);
+
+ DeviceInitTouch(dev, axes_labels);
+
+ free(axes_labels);
+
+ priv->hwState = SynapticsHwStateAlloc(priv);
+ if (!priv->hwState)
+ goto fail;
+
+ priv->local_hw_state = SynapticsHwStateAlloc(priv);
+ if (!priv->local_hw_state)
+ goto fail;
+
+ priv->comm.hwState = SynapticsHwStateAlloc(priv);
+
+ InitDeviceProperties(pInfo);
+ XIRegisterPropertyHandler(pInfo->dev, SetProperty, NULL, NULL);
+
+ SynapticsReset(priv);
return Success;
-}
-static int
-move_distance(int dx, int dy)
-{
- return xf86sqrt(SQR(dx) + SQR(dy));
+ fail:
+ free(priv->local_hw_state);
+ free(priv->hwState);
+ free(priv->open_slots);
+ return !Success;
}
/*
@@ -711,122 +1366,256 @@ move_distance(int dx, int dy)
* right/lower edge.
*/
static void
-relative_coords(SynapticsPrivate *priv, int x, int y,
- double *relX, double *relY)
+relative_coords(SynapticsPrivate * priv, int x, int y,
+ double *relX, double *relY)
{
- int minX = priv->synpara->left_edge;
- int maxX = priv->synpara->right_edge;
- int minY = priv->synpara->top_edge;
- int maxY = priv->synpara->bottom_edge;
+ int minX = priv->synpara.left_edge;
+ int maxX = priv->synpara.right_edge;
+ int minY = priv->synpara.top_edge;
+ int maxY = priv->synpara.bottom_edge;
double xCenter = (minX + maxX) / 2.0;
double yCenter = (minY + maxY) / 2.0;
if ((maxX - xCenter > 0) && (maxY - yCenter > 0)) {
- *relX = (x - xCenter) / (maxX - xCenter);
- *relY = (y - yCenter) / (maxY - yCenter);
- } else {
- *relX = 0;
- *relY = 0;
+ *relX = (x - xCenter) / (maxX - xCenter);
+ *relY = (y - yCenter) / (maxY - yCenter);
+ }
+ else {
+ *relX = 0;
+ *relY = 0;
}
}
/* return angle of point relative to center */
static double
-angle(SynapticsPrivate *priv, int x, int y)
+angle(SynapticsPrivate * priv, int x, int y)
{
- double xCenter = (priv->synpara->left_edge + priv->synpara->right_edge) / 2.0;
- double yCenter = (priv->synpara->top_edge + priv->synpara->bottom_edge) / 2.0;
+ double xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2.0;
+ double yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2.0;
- return xf86atan2(-(y - yCenter), x - xCenter);
+ return atan2(-(y - yCenter), x - xCenter);
}
/* return angle difference */
static double
diffa(double a1, double a2)
{
- double da = xf86fmod(a2 - a1, 2 * M_PI);
+ double da = fmod(a2 - a1, 2 * M_PI);
+
if (da < 0)
- da += 2 * M_PI;
+ da += 2 * M_PI;
if (da > M_PI)
- da -= 2 * M_PI;
+ da -= 2 * M_PI;
return da;
}
-static edge_type
-circular_edge_detection(SynapticsPrivate *priv, int x, int y)
+static enum EdgeType
+circular_edge_detection(SynapticsPrivate * priv, int x, int y)
{
- edge_type edge = 0;
+ enum EdgeType edge = 0;
double relX, relY, relR;
relative_coords(priv, x, y, &relX, &relY);
relR = SQR(relX) + SQR(relY);
if (relR > 1) {
- /* we are outside the ellipse enclosed by the edge parameters */
- if (relX > M_SQRT1_2)
- edge |= RIGHT_EDGE;
- else if (relX < -M_SQRT1_2)
- edge |= LEFT_EDGE;
-
- if (relY < -M_SQRT1_2)
- edge |= TOP_EDGE;
- else if (relY > M_SQRT1_2)
- edge |= BOTTOM_EDGE;
+ /* we are outside the ellipse enclosed by the edge parameters */
+ if (relX > M_SQRT1_2)
+ edge |= RIGHT_EDGE;
+ else if (relX < -M_SQRT1_2)
+ edge |= LEFT_EDGE;
+
+ if (relY < -M_SQRT1_2)
+ edge |= TOP_EDGE;
+ else if (relY > M_SQRT1_2)
+ edge |= BOTTOM_EDGE;
}
return edge;
}
-static edge_type
-edge_detection(SynapticsPrivate *priv, int x, int y)
+static enum EdgeType
+edge_detection(SynapticsPrivate * priv, int x, int y)
{
- edge_type edge = 0;
+ enum EdgeType edge = NO_EDGE;
- if (priv->synpara->circular_pad)
- return circular_edge_detection(priv, x, y);
+ if (priv->synpara.circular_pad)
+ return circular_edge_detection(priv, x, y);
- if (x > priv->synpara->right_edge)
- edge |= RIGHT_EDGE;
- else if (x < priv->synpara->left_edge)
- edge |= LEFT_EDGE;
+ if (x > priv->synpara.right_edge)
+ edge |= RIGHT_EDGE;
+ else if (x < priv->synpara.left_edge)
+ edge |= LEFT_EDGE;
- if (y < priv->synpara->top_edge)
- edge |= TOP_EDGE;
- else if (y > priv->synpara->bottom_edge)
- edge |= BOTTOM_EDGE;
+ if (y < priv->synpara.top_edge)
+ edge |= TOP_EDGE;
+ else if (y > priv->synpara.bottom_edge)
+ edge |= BOTTOM_EDGE;
return edge;
}
+/* Checks whether coordinates are in the Synaptics Area
+ * or not. If no Synaptics Area is defined (i.e. if
+ * priv->synpara.area_{left|right|top|bottom}_edge are
+ * all set to zero), the function returns TRUE.
+ */
+static Bool
+is_inside_active_area(SynapticsPrivate * priv, int x, int y)
+{
+ Bool inside_area = TRUE;
+
+ /* If a finger is down, then it must have started inside the active_area,
+ allow the motion to complete using the entire area */
+ if (priv->finger_state >= FS_TOUCHED)
+ return TRUE;
+
+ if ((priv->synpara.area_left_edge != 0) &&
+ (x < priv->synpara.area_left_edge))
+ inside_area = FALSE;
+ else if ((priv->synpara.area_right_edge != 0) &&
+ (x > priv->synpara.area_right_edge))
+ inside_area = FALSE;
+
+ if ((priv->synpara.area_top_edge != 0) && (y < priv->synpara.area_top_edge))
+ inside_area = FALSE;
+ else if ((priv->synpara.area_bottom_edge != 0) &&
+ (y > priv->synpara.area_bottom_edge))
+ inside_area = FALSE;
+
+ return inside_area;
+}
+
+static Bool
+is_inside_button_area(SynapticsParameters * para, int which, int x, int y)
+{
+ Bool inside_area = TRUE;
+
+ if (para->softbutton_areas[which][LEFT] == 0 &&
+ para->softbutton_areas[which][RIGHT] == 0 &&
+ para->softbutton_areas[which][TOP] == 0 &&
+ para->softbutton_areas[which][BOTTOM] == 0)
+ return FALSE;
+
+ if (para->softbutton_areas[which][LEFT] &&
+ x < para->softbutton_areas[which][LEFT])
+ inside_area = FALSE;
+ else if (para->softbutton_areas[which][RIGHT] &&
+ x > para->softbutton_areas[which][RIGHT])
+ inside_area = FALSE;
+ else if (para->softbutton_areas[which][TOP] &&
+ y < para->softbutton_areas[which][TOP])
+ inside_area = FALSE;
+ else if (para->softbutton_areas[which][BOTTOM] &&
+ y > para->softbutton_areas[which][BOTTOM])
+ inside_area = FALSE;
+
+ return inside_area;
+}
+
+static Bool
+is_inside_rightbutton_area(SynapticsParameters * para, int x, int y)
+{
+ return is_inside_button_area(para, BOTTOM_RIGHT_BUTTON_AREA, x, y);
+}
+
+static Bool
+is_inside_middlebutton_area(SynapticsParameters * para, int x, int y)
+{
+ return is_inside_button_area(para, BOTTOM_MIDDLE_BUTTON_AREA, x, y);
+}
+
+static Bool
+is_inside_sec_rightbutton_area(SynapticsParameters * para, int x, int y)
+{
+ return is_inside_button_area(para, TOP_RIGHT_BUTTON_AREA, x, y);
+}
+
+static Bool
+is_inside_sec_middlebutton_area(SynapticsParameters * para, int x, int y)
+{
+ return is_inside_button_area(para, TOP_MIDDLE_BUTTON_AREA, x, y);
+}
+
+static Bool
+is_inside_top_or_bottom_button_area(SynapticsParameters * para, int offset,
+ int x, int y)
+{
+ Bool inside_area = TRUE;
+ Bool right_valid, middle_valid;
+ int top, bottom;
+
+ /* We don't have a left button area, so we only check the y axis */
+ right_valid = para->softbutton_areas[offset][TOP] ||
+ para->softbutton_areas[offset][BOTTOM];
+ middle_valid = para->softbutton_areas[offset + 1][TOP] ||
+ para->softbutton_areas[offset + 1][BOTTOM];
+
+ if (!right_valid && !middle_valid)
+ return FALSE;
+
+ /* Check both buttons are horizontally aligned */
+ if (right_valid && middle_valid && (
+ para->softbutton_areas[offset][TOP] !=
+ para->softbutton_areas[offset + 1][TOP] ||
+ para->softbutton_areas[offset][BOTTOM] !=
+ para->softbutton_areas[offset + 1][BOTTOM]))
+ return FALSE;
+
+ if (right_valid) {
+ top = para->softbutton_areas[offset][TOP];
+ bottom = para->softbutton_areas[offset][BOTTOM];
+ }
+ else {
+ top = para->softbutton_areas[offset + 1][TOP];
+ bottom = para->softbutton_areas[offset + 1][BOTTOM];
+ }
+
+ if (top && y < top)
+ inside_area = FALSE;
+ else if (bottom && y > bottom)
+ inside_area = FALSE;
+
+ return inside_area;
+}
+
+static enum SoftButtonAreas
+current_button_area(SynapticsParameters * para, int x, int y)
+{
+ if (is_inside_top_or_bottom_button_area(para, BOTTOM_BUTTON_AREA, x, y))
+ return BOTTOM_BUTTON_AREA;
+ else if (is_inside_top_or_bottom_button_area(para, TOP_BUTTON_AREA, x, y))
+ return TOP_BUTTON_AREA;
+ else
+ return NO_BUTTON_AREA;
+}
+
static CARD32
timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
{
- LocalDevicePtr local = (LocalDevicePtr) (arg);
- SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
- struct SynapticsHwState hw;
+ InputInfoPtr pInfo = arg;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ struct SynapticsHwState *hw = priv->local_hw_state;
int delay;
- int sigstate;
- CARD32 wakeUpTime;
-
- sigstate = xf86BlockSIGIO();
-
- hw = priv->hwState;
- hw.guest_dx = hw.guest_dy = 0;
- hw.millis = now;
- delay = HandleState(local, &hw);
+#if !HAVE_THREADED_INPUT
+ int sigstate = xf86BlockSIGIO();
+#else
+ input_lock();
+#endif
- /*
- * Workaround for wraparound bug in the TimerSet function. This bug is already
- * fixed in CVS, but this driver needs to work with XFree86 versions 4.2.x and
- * 4.3.x too.
- */
- wakeUpTime = now + delay;
- if (wakeUpTime <= now)
- wakeUpTime = 0xffffffffL;
+ priv->hwState->millis += now - priv->timer_time;
+ SynapticsCopyHwState(hw, priv->hwState);
+ SynapticsResetTouchHwState(hw, FALSE);
+ delay = HandleState(pInfo, hw, hw->millis, TRUE);
- priv->timer = TimerSet(priv->timer, TimerAbsolute, wakeUpTime, timerFunc, local);
+ priv->timer_time = now;
+ priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
+#if !HAVE_THREADED_INPUT
xf86UnblockSIGIO(sigstate);
+#else
+ input_unlock();
+#endif
return 0;
}
@@ -835,453 +1624,534 @@ static int
clamp(int val, int min, int max)
{
if (val < min)
- return min;
+ return min;
else if (val < max)
- return val;
+ return val;
else
- return max;
+ return max;
}
static Bool
-SynapticsGetHwState(LocalDevicePtr local, SynapticsPrivate *priv,
- struct SynapticsHwState *hw)
+SynapticsGetHwState(InputInfoPtr pInfo, SynapticsPrivate * priv,
+ struct SynapticsHwState *hw)
{
- if (priv->fifofd >= 0) {
- /* when there is no synaptics touchpad pipe the data to the repeater fifo */
- int count = 0;
- int c;
- while ((c = XisbRead(priv->comm.buffer)) >= 0) {
- unsigned char u = (unsigned char)c;
- xf86write(priv->fifofd, &u, 1);
- if (++count >= 3)
- break;
- }
- return FALSE;
- }
- return priv->proto_ops->ReadHwState(local, &priv->synhw, priv->proto_ops,
- &priv->comm, hw);
+ return priv->proto_ops->ReadHwState(pInfo, &priv->comm, hw);
}
/*
* called for each full received packet from the touchpad
*/
static void
-ReadInput(LocalDevicePtr local)
+ReadInput(InputInfoPtr pInfo)
{
- SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
- struct SynapticsHwState hw;
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ struct SynapticsHwState *hw = priv->local_hw_state;
int delay = 0;
Bool newDelay = FALSE;
- while (SynapticsGetHwState(local, priv, &hw)) {
- hw.millis = GetTimeInMillis();
- priv->hwState = hw;
- delay = HandleState(local, &hw);
- newDelay = TRUE;
+ SynapticsResetTouchHwState(hw, FALSE);
+
+ while (SynapticsGetHwState(pInfo, priv, hw)) {
+ /* Semi-mt device touch slots do not track touches. When there is a
+ * change in the number of touches, we must disregard the temporary
+ * motion changes. */
+ if (priv->has_semi_mt && hw->numFingers != priv->hwState->numFingers) {
+ hw->cumulative_dx = priv->hwState->cumulative_dx;
+ hw->cumulative_dy = priv->hwState->cumulative_dy;
+ }
+
+ /* timer may cause actual events to lag behind (#48777) */
+ if (priv->hwState->millis > hw->millis)
+ hw->millis = priv->hwState->millis;
+
+ SynapticsCopyHwState(priv->hwState, hw);
+ delay = HandleState(pInfo, hw, hw->millis, FALSE);
+ newDelay = TRUE;
}
- if (newDelay)
- priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, local);
+ if (newDelay) {
+ priv->timer_time = GetTimeInMillis();
+ priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
+ }
}
static int
-HandleMidButtonEmulation(SynapticsPrivate *priv, struct SynapticsHwState *hw, int *delay)
+HandleMidButtonEmulation(SynapticsPrivate * priv, struct SynapticsHwState *hw,
+ CARD32 now, int *delay)
{
- SynapticsSHM *para = priv->synpara;
+ SynapticsParameters *para = &priv->synpara;
Bool done = FALSE;
int timeleft;
int mid = 0;
+ if (para->emulate_mid_button_time <= 0)
+ return mid;
+
while (!done) {
- switch (priv->mid_emu_state) {
- case MBE_OFF:
- priv->button_delay_millis = hw->millis;
- if (hw->left) {
- priv->mid_emu_state = MBE_LEFT;
- } else if (hw->right) {
- priv->mid_emu_state = MBE_RIGHT;
- } else {
- done = TRUE;
- }
- break;
- case MBE_LEFT:
- timeleft = TIME_DIFF(priv->button_delay_millis + para->emulate_mid_button_time,
- hw->millis);
- if (timeleft > 0)
- *delay = MIN(*delay, timeleft);
- if (!hw->left || (timeleft <= 0)) {
- hw->left = TRUE;
- priv->mid_emu_state = MBE_TIMEOUT;
- done = TRUE;
- } else if (hw->right) {
- priv->mid_emu_state = MBE_MID;
- } else {
- hw->left = FALSE;
- done = TRUE;
- }
- break;
- case MBE_RIGHT:
- timeleft = TIME_DIFF(priv->button_delay_millis + para->emulate_mid_button_time,
- hw->millis);
- if (timeleft > 0)
- *delay = MIN(*delay, timeleft);
- if (!hw->right || (timeleft <= 0)) {
- hw->right = TRUE;
- priv->mid_emu_state = MBE_TIMEOUT;
- done = TRUE;
- } else if (hw->left) {
- priv->mid_emu_state = MBE_MID;
- } else {
- hw->right = FALSE;
- done = TRUE;
- }
- break;
- case MBE_MID:
- if (!hw->left && !hw->right) {
- priv->mid_emu_state = MBE_OFF;
- } else {
- mid = TRUE;
- hw->left = hw->right = FALSE;
- done = TRUE;
- }
- break;
- case MBE_TIMEOUT:
- if (!hw->left && !hw->right) {
- priv->mid_emu_state = MBE_OFF;
- } else {
- done = TRUE;
- }
- }
+ switch (priv->mid_emu_state) {
+ case MBE_LEFT_CLICK:
+ case MBE_RIGHT_CLICK:
+ case MBE_OFF:
+ priv->button_delay_millis = now;
+ if (hw->left) {
+ priv->mid_emu_state = MBE_LEFT;
+ }
+ else if (hw->right) {
+ priv->mid_emu_state = MBE_RIGHT;
+ }
+ else {
+ done = TRUE;
+ }
+ break;
+ case MBE_LEFT:
+ timeleft =
+ TIME_DIFF(priv->button_delay_millis +
+ para->emulate_mid_button_time, now);
+ if (timeleft > 0)
+ *delay = MIN(*delay, timeleft);
+
+ /* timeout, but within the same ReadInput cycle! */
+ if ((timeleft <= 0) && !hw->left) {
+ priv->mid_emu_state = MBE_LEFT_CLICK;
+ done = TRUE;
+ }
+ else if ((!hw->left) || (timeleft <= 0)) {
+ hw->left = TRUE;
+ priv->mid_emu_state = MBE_TIMEOUT;
+ done = TRUE;
+ }
+ else if (hw->right) {
+ priv->mid_emu_state = MBE_MID;
+ }
+ else {
+ hw->left = FALSE;
+ done = TRUE;
+ }
+ break;
+ case MBE_RIGHT:
+ timeleft =
+ TIME_DIFF(priv->button_delay_millis +
+ para->emulate_mid_button_time, now);
+ if (timeleft > 0)
+ *delay = MIN(*delay, timeleft);
+
+ /* timeout, but within the same ReadInput cycle! */
+ if ((timeleft <= 0) && !hw->right) {
+ priv->mid_emu_state = MBE_RIGHT_CLICK;
+ done = TRUE;
+ }
+ else if (!hw->right || (timeleft <= 0)) {
+ hw->right = TRUE;
+ priv->mid_emu_state = MBE_TIMEOUT;
+ done = TRUE;
+ }
+ else if (hw->left) {
+ priv->mid_emu_state = MBE_MID;
+ }
+ else {
+ hw->right = FALSE;
+ done = TRUE;
+ }
+ break;
+ case MBE_MID:
+ if (!hw->left && !hw->right) {
+ priv->mid_emu_state = MBE_OFF;
+ }
+ else {
+ mid = TRUE;
+ hw->left = hw->right = FALSE;
+ done = TRUE;
+ }
+ break;
+ case MBE_TIMEOUT:
+ if (!hw->left && !hw->right) {
+ priv->mid_emu_state = MBE_OFF;
+ }
+ else {
+ done = TRUE;
+ }
+ }
}
return mid;
}
-static int
-SynapticsDetectFinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
+static enum FingerState
+SynapticsDetectFinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
{
- SynapticsSHM *para = priv->synpara;
- int finger;
+ SynapticsParameters *para = &priv->synpara;
+ enum FingerState finger;
/* finger detection thru pressure and threshold */
- finger = ((hw->z > para->finger_press) && priv->finger_state < FS_PRESSED) ? FS_PRESSED
- : ((hw->z > para->finger_high) && priv->finger_state < FS_TOUCHED) ? FS_TOUCHED
- : ((hw->z < para->finger_low) && priv->finger_state > FS_UNTOUCHED) ? FS_UNTOUCHED
- : priv->finger_state;
+ if (hw->z < para->finger_low)
+ return FS_UNTOUCHED;
+
+ if (priv->finger_state == FS_BLOCKED)
+ return FS_BLOCKED;
+
+ if (hw->z > para->finger_high && priv->finger_state == FS_UNTOUCHED)
+ finger = FS_TOUCHED;
+ else
+ finger = priv->finger_state;
if (!para->palm_detect)
- return finger;
+ return finger;
/* palm detection */
- if (finger) {
- if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width))
- priv->palm = TRUE;
- } else {
- priv->palm = FALSE;
- }
- if (hw->x == 0)
- priv->avg_width = 0;
+
+ if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width))
+ return FS_BLOCKED;
+
+ if (priv->has_mt_palm_detect)
+ return finger;
+
+ if (hw->x == 0 || priv->finger_state == FS_UNTOUCHED)
+ priv->avg_width = 0;
else
- priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
- if (finger && !priv->finger_state) {
- int safe_width = MAX(hw->fingerWidth, priv->avg_width);
- if (hw->numFingers > 1)
- finger = TRUE; /* more than one finger -> not a palm */
- else if ((safe_width < 6) && (priv->prev_z < para->finger_high))
- finger = TRUE; /* thin finger, distinct touch -> not a palm */
- else if ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))
- finger = TRUE; /* thin finger, distinct touch -> not a palm */
- else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */
- finger = FALSE;
- else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */
- finger = FALSE;
- else if (hw->z > para->palm_min_z) /* z too large -> probably palm */
- finger = FALSE;
- else if (hw->fingerWidth > para->palm_min_width) /* finger width too large -> probably palm */
- finger = FALSE;
+ priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
+
+ if (finger != FS_UNTOUCHED && priv->finger_state == FS_UNTOUCHED) {
+ int safe_width = MAX(hw->fingerWidth, priv->avg_width);
+
+ if (hw->numFingers > 1 || /* more than one finger -> not a palm */
+ ((safe_width < 6) && (priv->prev_z < para->finger_high)) || /* thin finger, distinct touch -> not a palm */
+ ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))) { /* thin finger, distinct touch -> not a palm */
+ /* leave finger value as is */
+ }
+ else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */
+ finger = FS_UNTOUCHED;
+ else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */
+ finger = FS_UNTOUCHED;
+ else if (hw->fingerWidth > para->palm_min_width) /* finger width too large -> probably palm */
+ finger = FS_UNTOUCHED;
}
priv->prev_z = hw->z;
- if (priv->palm)
- finger = FALSE;
-
return finger;
}
static void
-SelectTapButton(SynapticsPrivate *priv, edge_type edge)
+SelectTapButton(SynapticsPrivate * priv, enum EdgeType edge)
{
- TapEvent tap;
+ enum TapEvent tap;
- if (priv->synpara->touchpad_off == 2) {
- priv->tap_button = 0;
- return;
+ if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF) {
+ priv->tap_button = 0;
+ return;
}
switch (priv->tap_max_fingers) {
case 1:
- default:
- switch (edge) {
- case RIGHT_TOP_EDGE:
- DBG(7, ErrorF("right top edge\n"));
- tap = RT_TAP;
- break;
- case RIGHT_BOTTOM_EDGE:
- DBG(7, ErrorF("right bottom edge\n"));
- tap = RB_TAP;
- break;
- case LEFT_TOP_EDGE:
- DBG(7, ErrorF("left top edge\n"));
- tap = LT_TAP;
- break;
- case LEFT_BOTTOM_EDGE:
- DBG(7, ErrorF("left bottom edge\n"));
- tap = LB_TAP;
- break;
- default:
- DBG(7, ErrorF("no edge\n"));
- tap = F1_TAP;
- break;
- }
- break;
+ switch (edge) {
+ case RIGHT_TOP_EDGE:
+ DBG(7, "right top edge\n");
+ tap = RT_TAP;
+ break;
+ case RIGHT_BOTTOM_EDGE:
+ DBG(7, "right bottom edge\n");
+ tap = RB_TAP;
+ break;
+ case LEFT_TOP_EDGE:
+ DBG(7, "left top edge\n");
+ tap = LT_TAP;
+ break;
+ case LEFT_BOTTOM_EDGE:
+ DBG(7, "left bottom edge\n");
+ tap = LB_TAP;
+ break;
+ default:
+ DBG(7, "no edge\n");
+ tap = F1_TAP;
+ break;
+ }
+ break;
case 2:
- DBG(7, ErrorF("two finger tap\n"));
- tap = F2_TAP;
- break;
+ DBG(7, "two finger tap\n");
+ tap = F2_TAP;
+ break;
case 3:
- DBG(7, ErrorF("three finger tap\n"));
- tap = F3_TAP;
- break;
+ DBG(7, "three finger tap\n");
+ tap = F3_TAP;
+ break;
+ default:
+ priv->tap_button = 0;
+ return;
}
- priv->tap_button = priv->synpara->tap_action[tap];
+ priv->tap_button = priv->synpara.tap_action[tap];
priv->tap_button = clamp(priv->tap_button, 0, SYN_MAX_BUTTONS);
}
static void
-SetTapState(SynapticsPrivate *priv, enum TapState tap_state, int millis)
+SetTapState(SynapticsPrivate * priv, enum TapState tap_state, CARD32 millis)
{
- SynapticsSHM *para = priv->synpara;
- DBG(7, ErrorF("SetTapState - %d -> %d (millis:%d)\n", priv->tap_state, tap_state, millis));
+ DBG(3, "SetTapState - %d -> %d (millis:%u)\n", priv->tap_state, tap_state,
+ millis);
switch (tap_state) {
case TS_START:
- priv->tap_button_state = TBS_BUTTON_UP;
- priv->tap_max_fingers = 0;
- break;
+ priv->tap_button_state = TBS_BUTTON_UP;
+ priv->tap_max_fingers = 0;
+ break;
case TS_1:
- priv->tap_button_state = TBS_BUTTON_UP;
- break;
+ priv->tap_button_state = TBS_BUTTON_UP;
+ break;
case TS_2A:
- if (para->fast_taps)
- priv->tap_button_state = TBS_BUTTON_DOWN;
- else
- priv->tap_button_state = TBS_BUTTON_UP;
- break;
- case TS_2B:
priv->tap_button_state = TBS_BUTTON_UP;
- break;
+ break;
+ case TS_2B:
+ priv->tap_button_state = TBS_BUTTON_UP;
+ break;
case TS_3:
- priv->tap_button_state = TBS_BUTTON_DOWN;
- break;
+ priv->tap_button_state = TBS_BUTTON_DOWN;
+ break;
case TS_SINGLETAP:
- if (para->fast_taps)
- priv->tap_button_state = TBS_BUTTON_UP;
- else
- priv->tap_button_state = TBS_BUTTON_DOWN;
- priv->touch_on.millis = millis;
- break;
+ priv->tap_button_state = TBS_BUTTON_DOWN;
+ priv->touch_on.millis = millis;
+ break;
default:
- break;
+ break;
}
priv->tap_state = tap_state;
}
static void
-SetMovingState(SynapticsPrivate *priv, enum MovingState moving_state, int millis)
+SetMovingState(SynapticsPrivate * priv, enum MovingState moving_state,
+ CARD32 millis)
{
- DBG(7, ErrorF("SetMovingState - %d -> %d center at %d/%d (millis:%d)\n", priv->moving_state,
- moving_state,priv->hwState.x, priv->hwState.y, millis));
+ DBG(7, "SetMovingState - %d -> %d center at %d/%d (millis:%u)\n",
+ priv->moving_state, moving_state, priv->hwState->x, priv->hwState->y,
+ millis);
- if (moving_state == MS_TRACKSTICK) {
- priv->trackstick_neutral_x = priv->hwState.x;
- priv->trackstick_neutral_y = priv->hwState.y;
- }
priv->moving_state = moving_state;
}
static int
-GetTimeOut(SynapticsPrivate *priv)
+GetTimeOut(SynapticsPrivate * priv)
{
- SynapticsSHM *para = priv->synpara;
+ SynapticsParameters *para = &priv->synpara;
switch (priv->tap_state) {
case TS_1:
case TS_3:
case TS_5:
- return para->tap_time;
+ return para->tap_time;
case TS_SINGLETAP:
- return para->click_time;
+ return para->click_time;
case TS_2A:
- return para->single_tap_timeout;
+ return para->single_tap_timeout;
case TS_2B:
- return para->tap_time_2;
+ return para->tap_time_2;
case TS_4:
- return para->locked_drag_time;
+ return para->locked_drag_time;
default:
- return -1; /* No timeout */
+ return -1; /* No timeout */
}
}
static int
-HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw,
- edge_type edge, enum FingerState finger)
+HandleTapProcessing(SynapticsPrivate * priv, struct SynapticsHwState *hw,
+ CARD32 now, enum FingerState finger,
+ Bool inside_active_area)
{
- SynapticsSHM *para = priv->synpara;
- Bool touch, release, is_timeout, move;
+ SynapticsParameters *para = &priv->synpara;
+ Bool touch, release, is_timeout, move, press;
int timeleft, timeout;
+ enum EdgeType edge;
int delay = 1000000000;
- if (priv->palm)
- return delay;
-
- touch = finger && !priv->finger_state;
- release = !finger && priv->finger_state;
- move = ((priv->tap_max_fingers <= 1) &&
- ((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
- (abs(hw->y - priv->touch_on.y) >= para->tap_move)));
+ if (para->touchpad_off == TOUCHPAD_OFF ||
+ priv->finger_state == FS_BLOCKED)
+ return delay;
+
+ touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED;
+ release = finger == FS_UNTOUCHED && priv->finger_state >= FS_TOUCHED;
+ move = (finger >= FS_TOUCHED &&
+ (priv->tap_max_fingers <=
+ ((priv->horiz_scroll_twofinger_on ||
+ priv->vert_scroll_twofinger_on) ? 2 : 1)) &&
+ (priv->prevFingers == hw->numFingers &&
+ ((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
+ (abs(hw->y - priv->touch_on.y) >= para->tap_move))));
+ press = (hw->left || hw->right || hw->middle);
if (touch) {
- priv->touch_on.x = hw->x;
- priv->touch_on.y = hw->y;
- priv->touch_on.millis = hw->millis;
- } else if (release) {
- priv->touch_on.millis = hw->millis;
+ priv->touch_on.x = hw->x;
+ priv->touch_on.y = hw->y;
+ priv->touch_on.millis = now;
+ }
+ else if (release) {
+ priv->touch_on.millis = now;
}
if (hw->z > para->finger_high)
- if (priv->tap_max_fingers < hw->numFingers)
- priv->tap_max_fingers = hw->numFingers;
+ if (priv->tap_max_fingers < hw->numFingers)
+ priv->tap_max_fingers = hw->numFingers;
timeout = GetTimeOut(priv);
- timeleft = TIME_DIFF(priv->touch_on.millis + timeout, hw->millis);
+ timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
is_timeout = timeleft <= 0;
restart:
switch (priv->tap_state) {
case TS_START:
- if (touch)
- SetTapState(priv, TS_1, hw->millis);
- break;
+ if (touch)
+ SetTapState(priv, TS_1, now);
+ break;
case TS_1:
- if (move) {
- SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis);
- SetTapState(priv, TS_MOVE, hw->millis);
- goto restart;
- } else if (is_timeout) {
- if (finger == FS_TOUCHED) {
- SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis);
- } else if (finger == FS_PRESSED) {
- SetMovingState(priv, MS_TRACKSTICK, hw->millis);
- }
- SetTapState(priv, TS_MOVE, hw->millis);
- goto restart;
- } else if (release) {
- SelectTapButton(priv, edge);
- SetTapState(priv, TS_2A, hw->millis);
- }
- break;
+ if (para->clickpad && press) {
+ SetTapState(priv, TS_CLICKPAD_MOVE, now);
+ goto restart;
+ }
+ if (move) {
+ SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
+ SetTapState(priv, TS_MOVE, now);
+ goto restart;
+ }
+ else if (is_timeout) {
+ if (finger == FS_TOUCHED) {
+ SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
+ }
+ SetTapState(priv, TS_MOVE, now);
+ goto restart;
+ }
+ else if (release) {
+ edge = edge_detection(priv, priv->touch_on.x, priv->touch_on.y);
+ SelectTapButton(priv, edge);
+ /* Disable taps outside of the active area */
+ if (!inside_active_area) {
+ priv->tap_button = 0;
+ }
+ SetTapState(priv, TS_2A, now);
+ }
+ break;
case TS_MOVE:
- if (move && priv->moving_state == MS_TRACKSTICK) {
- SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis);
- }
- if (release) {
- SetMovingState(priv, MS_FALSE, hw->millis);
- SetTapState(priv, TS_START, hw->millis);
- }
- break;
+ if (para->clickpad && press) {
+ SetTapState(priv, TS_CLICKPAD_MOVE, now);
+ goto restart;
+ }
+ if (release) {
+ SetMovingState(priv, MS_FALSE, now);
+ SetTapState(priv, TS_START, now);
+ }
+ break;
case TS_2A:
- if (touch)
- SetTapState(priv, TS_3, hw->millis);
- else if (is_timeout)
- SetTapState(priv, TS_SINGLETAP, hw->millis);
- break;
+ if (touch)
+ SetTapState(priv, TS_3, now);
+ else if (is_timeout)
+ SetTapState(priv, TS_SINGLETAP, now);
+ break;
case TS_2B:
- if (touch) {
- SetTapState(priv, TS_3, hw->millis);
- } else if (is_timeout) {
- SetTapState(priv, TS_START, hw->millis);
- priv->tap_button_state = TBS_BUTTON_DOWN_UP;
- }
- break;
+ if (touch)
+ SetTapState(priv, TS_3, now);
+ else if (is_timeout)
+ SetTapState(priv, TS_SINGLETAP, now);
+ break;
case TS_SINGLETAP:
- if (touch)
- SetTapState(priv, TS_1, hw->millis);
- else if (is_timeout)
- SetTapState(priv, TS_START, hw->millis);
- break;
+ if (touch)
+ SetTapState(priv, TS_1, now);
+ else if (is_timeout)
+ SetTapState(priv, TS_START, now);
+ break;
case TS_3:
- if (move) {
- SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis);
- SetTapState(priv, TS_DRAG, hw->millis);
- goto restart;
- } else if (is_timeout) {
- if (finger == FS_TOUCHED) {
- SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis);
- } else if (finger == FS_PRESSED) {
- SetMovingState(priv, MS_TRACKSTICK, hw->millis);
- }
- SetTapState(priv, TS_DRAG, hw->millis);
- goto restart;
- } else if (release) {
- SetTapState(priv, TS_2B, hw->millis);
- }
- break;
+ if (move) {
+ if (para->tap_and_drag_gesture) {
+ SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
+ SetTapState(priv, TS_DRAG, now);
+ }
+ else {
+ SetTapState(priv, TS_1, now);
+ }
+ goto restart;
+ }
+ else if (is_timeout) {
+ if (para->tap_and_drag_gesture) {
+ if (finger == FS_TOUCHED) {
+ SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
+ }
+ SetTapState(priv, TS_DRAG, now);
+ }
+ else {
+ SetTapState(priv, TS_1, now);
+ }
+ goto restart;
+ }
+ else if (release) {
+ SetTapState(priv, TS_2B, now);
+ }
+ break;
case TS_DRAG:
- if (move)
- SetMovingState(priv, MS_TOUCHPAD_RELATIVE, hw->millis);
- if (release) {
- SetMovingState(priv, MS_FALSE, hw->millis);
- if (para->locked_drags) {
- SetTapState(priv, TS_4, hw->millis);
- } else {
- SetTapState(priv, TS_START, hw->millis);
- }
- }
- break;
+ if (para->clickpad && press) {
+ SetTapState(priv, TS_CLICKPAD_MOVE, now);
+ goto restart;
+ }
+ if (move)
+ SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
+ if (release) {
+ SetMovingState(priv, MS_FALSE, now);
+ if (para->locked_drags) {
+ SetTapState(priv, TS_4, now);
+ }
+ else {
+ SetTapState(priv, TS_START, now);
+ }
+ }
+ break;
case TS_4:
- if (is_timeout) {
- SetTapState(priv, TS_START, hw->millis);
- goto restart;
- }
- if (touch)
- SetTapState(priv, TS_5, hw->millis);
- break;
+ if (is_timeout) {
+ SetTapState(priv, TS_START, now);
+ goto restart;
+ }
+ if (touch)
+ SetTapState(priv, TS_5, now);
+ break;
case TS_5:
- if (is_timeout || move) {
- SetTapState(priv, TS_DRAG, hw->millis);
- goto restart;
- } else if (release) {
- SetMovingState(priv, MS_FALSE, hw->millis);
- SetTapState(priv, TS_START, hw->millis);
- }
- break;
+ if (is_timeout || move) {
+ SetTapState(priv, TS_DRAG, now);
+ goto restart;
+ }
+ else if (release) {
+ SetMovingState(priv, MS_FALSE, now);
+ SetTapState(priv, TS_START, now);
+ }
+ break;
+ case TS_CLICKPAD_MOVE:
+ /* Disable scrolling once a button is pressed on a clickpad */
+ priv->vert_scroll_edge_on = FALSE;
+ priv->horiz_scroll_edge_on = FALSE;
+ priv->vert_scroll_twofinger_on = FALSE;
+ priv->horiz_scroll_twofinger_on = FALSE;
+
+ /* Assume one touch is only for holding the clickpad button down */
+ if (hw->numFingers > 1)
+ hw->numFingers--;
+ SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
+ if (!press) {
+ SetMovingState(priv, MS_FALSE, now);
+ SetTapState(priv, TS_MOVE, now);
+ priv->count_packet_finger = 0;
+ }
+ break;
}
timeout = GetTimeOut(priv);
if (timeout >= 0) {
- timeleft = TIME_DIFF(priv->touch_on.millis + timeout, hw->millis);
- delay = clamp(timeleft, 1, delay);
+ timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
+ delay = clamp(timeleft, 1, delay);
}
return delay;
}
#define HIST(a) (priv->move_hist[((priv->hist_index - (a) + SYNAPTICS_MOVE_HISTORY) % SYNAPTICS_MOVE_HISTORY)])
+#define HIST_DELTA(a, b, e) ((HIST((a)).e) - (HIST((b)).e))
static void
-store_history(SynapticsPrivate *priv, int x, int y, unsigned int millis)
+store_history(SynapticsPrivate * priv, int x, int y, CARD32 millis)
{
int idx = (priv->hist_index + 1) % SYNAPTICS_MOVE_HISTORY;
+
priv->move_hist[idx].x = x;
priv->move_hist[idx].y = y;
priv->move_hist[idx].millis = millis;
priv->hist_index = idx;
+ if (priv->count_packet_finger < SYNAPTICS_MOVE_HISTORY)
+ priv->count_packet_finger++;
}
/*
@@ -1295,732 +2165,1078 @@ estimate_delta(double x0, double x1, double x2, double x3)
return x0 * 0.3 + x1 * 0.1 - x2 * 0.1 - x3 * 0.3;
}
+/**
+ * Applies hysteresis. center is shifted such that it is in range with
+ * in by the margin again. The new center is returned.
+ * @param in the current value
+ * @param center the current center
+ * @param margin the margin to center in which no change is applied
+ * @return the new center (which might coincide with the previous)
+ */
static int
-ComputeDeltas(SynapticsPrivate *priv, struct SynapticsHwState *hw,
- edge_type edge, int *dxP, int *dyP)
+hysteresis(int in, int center, int margin)
+{
+ int diff = in - center;
+
+ if (abs(diff) <= margin) {
+ diff = 0;
+ }
+ else if (diff > margin) {
+ diff -= margin;
+ }
+ else if (diff < -margin) {
+ diff += margin;
+ }
+ return center + diff;
+}
+
+static void
+get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
+ enum EdgeType edge, double *dx, double *dy)
+{
+ *dx = hw->x - HIST(0).x;
+ *dy = hw->y - HIST(0).y;
+}
+
+/* Vector length, but not sqrt'ed, we only need it for comparison */
+static inline double
+vlenpow2(double x, double y)
+{
+ return x * x + y * y;
+}
+
+/**
+ * Compute relative motion ('deltas') including edge motion.
+ */
+static int
+ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw,
+ enum EdgeType edge, int *dxP, int *dyP, Bool inside_area)
{
- SynapticsSHM *para = priv->synpara;
enum MovingState moving_state;
- int dist;
double dx, dy;
- double speed, integral;
+ double vlen;
int delay = 1000000000;
dx = dy = 0;
moving_state = priv->moving_state;
if (moving_state == MS_FALSE) {
- switch (priv->tap_state) {
- case TS_MOVE:
- case TS_DRAG:
- moving_state = MS_TOUCHPAD_RELATIVE;
- break;
- case TS_1:
- case TS_3:
- case TS_5:
- if (hw->numFingers == 1)
- moving_state = MS_TOUCHPAD_RELATIVE;
- break;
- default:
- break;
- }
- }
- if (moving_state && !priv->palm &&
- !priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on &&
- !priv->vert_scroll_twofinger_on && !priv->horiz_scroll_twofinger_on &&
- !priv->circ_scroll_on) {
- delay = MIN(delay, 13);
- if (priv->count_packet_finger > 3) { /* min. 3 packets */
- double tmpf;
- int x_edge_speed = 0;
- int y_edge_speed = 0;
- double dtime = (hw->millis - HIST(0).millis) / 1000.0;
-
- if (priv->moving_state == MS_TRACKSTICK) {
- dx = (hw->x - priv->trackstick_neutral_x);
- dy = (hw->y - priv->trackstick_neutral_y);
-
- dx = dx * dtime * para->trackstick_speed;
- dy = dy * dtime * para->trackstick_speed;
- } else if (moving_state == MS_TOUCHPAD_RELATIVE) {
- dx = estimate_delta(hw->x, HIST(0).x, HIST(1).x, HIST(2).x);
- dy = estimate_delta(hw->y, HIST(0).y, HIST(1).y, HIST(2).y);
-
- if ((priv->tap_state == TS_DRAG) || para->edge_motion_use_always) {
- int minZ = para->edge_motion_min_z;
- int maxZ = para->edge_motion_max_z;
- int minSpd = para->edge_motion_min_speed;
- int maxSpd = para->edge_motion_max_speed;
- int edge_speed;
-
- if (hw->z <= minZ) {
- edge_speed = minSpd;
- } else if (hw->z >= maxZ) {
- edge_speed = maxSpd;
- } else {
- edge_speed = minSpd + (hw->z - minZ) * (maxSpd - minSpd) / (maxZ - minZ);
- }
- if (!priv->synpara->circular_pad) {
- /* on rectangular pad */
- if (edge & RIGHT_EDGE) {
- x_edge_speed = edge_speed;
- } else if (edge & LEFT_EDGE) {
- x_edge_speed = -edge_speed;
- }
- if (edge & TOP_EDGE) {
- y_edge_speed = -edge_speed;
- } else if (edge & BOTTOM_EDGE) {
- y_edge_speed = edge_speed;
- }
- } else if (edge) {
- /* at edge of circular pad */
- double relX, relY;
-
- relative_coords(priv, hw->x, hw->y, &relX, &relY);
- x_edge_speed = (int)(edge_speed * relX);
- y_edge_speed = (int)(edge_speed * relY);
- }
- }
- }
-
- /* speed depending on distance/packet */
- dist = move_distance(dx, dy);
- speed = dist * para->accl;
- if (speed > para->max_speed) { /* set max speed factor */
- speed = para->max_speed;
- } else if (speed < para->min_speed) { /* set min speed factor */
- speed = para->min_speed;
- }
-
- /* modify speed according to pressure */
- if (priv->moving_state == MS_TOUCHPAD_RELATIVE) {
- int minZ = para->press_motion_min_z;
- int maxZ = para->press_motion_max_z;
- double minFctr = para->press_motion_min_factor;
- double maxFctr = para->press_motion_max_factor;
-
- if (hw->z <= minZ) {
- speed *= minFctr;
- } else if (hw->z >= maxZ) {
- speed *= maxFctr;
- } else {
- speed *= minFctr + (hw->z - minZ) * (maxFctr - minFctr) / (maxZ - minZ);
- }
- }
-
- /* save the fraction, report the integer part */
- tmpf = dx * speed + x_edge_speed * dtime + priv->frac_x;
- priv->frac_x = xf86modf(tmpf, &integral);
- dx = integral;
- tmpf = dy * speed + y_edge_speed * dtime + priv->frac_y;
- priv->frac_y = xf86modf(tmpf, &integral);
- dy = integral;
- }
-
- priv->count_packet_finger++;
- } else { /* reset packet counter */
- priv->count_packet_finger = 0;
- }
-
- /* Add guest device movements */
- if (!para->guestmouse_off) {
- dx += hw->guest_dx;
- dy += hw->guest_dy;
+ switch (priv->tap_state) {
+ case TS_MOVE:
+ case TS_DRAG:
+ moving_state = MS_TOUCHPAD_RELATIVE;
+ break;
+ case TS_1:
+ case TS_3:
+ case TS_5:
+ moving_state = MS_TOUCHPAD_RELATIVE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!inside_area || !moving_state || priv->finger_state == FS_BLOCKED ||
+ priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
+ priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
+ priv->circ_scroll_on || priv->prevFingers != hw->numFingers ||
+ (moving_state == MS_TOUCHPAD_RELATIVE && hw->numFingers != 1)) {
+ /* reset packet counter. */
+ priv->count_packet_finger = 0;
+ goto out;
+ }
+
+ /* To create the illusion of fluid motion, call back at roughly the report
+ * rate, even in the absence of new hardware events; see comment above
+ * POLL_MS declaration. */
+ delay = MIN(delay, POLL_MS);
+
+ if (priv->count_packet_finger <= 1)
+ goto out; /* skip the lot */
+
+ if (moving_state == MS_TOUCHPAD_RELATIVE)
+ get_delta(priv, hw, edge, &dx, &dy);
+
+ out:
+ priv->prevFingers = hw->numFingers;
+
+ vlen = vlenpow2(dx/priv->synpara.resolution_horiz,
+ dy/priv->synpara.resolution_vert);
+
+ if (vlen > priv->synpara.maxDeltaMM * priv->synpara.maxDeltaMM) {
+ dx = 0;
+ dy = 0;
}
*dxP = dx;
*dyP = dy;
- /* generate a history of the absolute positions */
- store_history(priv, hw->x, hw->y, hw->millis);
-
return delay;
}
-struct ScrollData {
- int left, right, up, down;
-};
+static double
+estimate_delta_circ(SynapticsPrivate * priv)
+{
+ double a1 = angle(priv, HIST(3).x, HIST(3).y);
+ double a2 = angle(priv, HIST(2).x, HIST(2).y);
+ double a3 = angle(priv, HIST(1).x, HIST(1).y);
+ double a4 = angle(priv, HIST(0).x, HIST(0).y);
+ double d1 = diffa(a2, a1);
+ double d2 = d1 + diffa(a3, a2);
+ double d3 = d2 + diffa(a4, a3);
+
+ return estimate_delta(d3, d2, d1, 0);
+}
+/* vert and horiz are to know which direction to start coasting
+ * circ is true if the user had been circular scrolling.
+ */
static void
-start_coasting(SynapticsPrivate *priv, struct SynapticsHwState *hw, edge_type edge,
- Bool vertical)
-{
- SynapticsSHM *para = priv->synpara;
-
- priv->autoscroll_y = 0.0;
- priv->autoscroll_x = 0.0;
-
- if ((priv->scroll_packet_count > 3) && (para->coasting_speed > 0.0)) {
- double pkt_time = (HIST(0).millis - HIST(3).millis) / 1000.0;
- if (vertical) {
- double dy = estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
- int sdelta = para->scroll_dist_vert;
- if ((edge & RIGHT_EDGE) && pkt_time > 0 && sdelta > 0) {
- double scrolls_per_sec = dy / pkt_time / sdelta;
- if (fabs(scrolls_per_sec) >= para->coasting_speed) {
- priv->autoscroll_yspd = scrolls_per_sec;
- priv->autoscroll_y = (hw->y - priv->scroll_y) / (double)sdelta;
- }
- }
- } else {
- double dx = estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
- int sdelta = para->scroll_dist_horiz;
- if ((edge & BOTTOM_EDGE) && pkt_time > 0 && sdelta > 0) {
- double scrolls_per_sec = dx / pkt_time / sdelta;
- if (fabs(scrolls_per_sec) >= para->coasting_speed) {
- priv->autoscroll_xspd = scrolls_per_sec;
- priv->autoscroll_x = (hw->x - priv->scroll_x) / (double)sdelta;
- }
- }
- }
- }
- priv->scroll_packet_count = 0;
+start_coasting(SynapticsPrivate * priv, struct SynapticsHwState *hw,
+ Bool vert, Bool horiz, Bool circ)
+{
+ SynapticsParameters *para = &priv->synpara;
+
+ priv->scroll.coast_delta_y = 0.0;
+ priv->scroll.coast_delta_x = 0.0;
+
+ if ((priv->scroll.packets_this_scroll > 3) && (para->coasting_speed > 0.0)) {
+ double pkt_time = HIST_DELTA(0, 3, millis) / 1000.0;
+
+ if (vert && !circ) {
+ double dy =
+ estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
+ if (pkt_time > 0) {
+ double scrolls_per_sec = (dy / abs(para->scroll_dist_vert)) / pkt_time;
+
+ if (fabs(scrolls_per_sec) >= para->coasting_speed) {
+ priv->scroll.coast_speed_y = scrolls_per_sec;
+ priv->scroll.coast_delta_y = (hw->y - priv->scroll.last_y);
+ }
+ }
+ }
+ if (horiz && !circ) {
+ double dx =
+ estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
+ if (pkt_time > 0) {
+ double scrolls_per_sec = (dx / abs(para->scroll_dist_vert)) / pkt_time;
+
+ if (fabs(scrolls_per_sec) >= para->coasting_speed) {
+ priv->scroll.coast_speed_x = scrolls_per_sec;
+ priv->scroll.coast_delta_x = (hw->x - priv->scroll.last_x);
+ }
+ }
+ }
+ if (circ) {
+ double da = estimate_delta_circ(priv);
+
+ if (pkt_time > 0) {
+ double scrolls_per_sec = (da / para->scroll_dist_circ) / pkt_time;
+
+ if (fabs(scrolls_per_sec) >= para->coasting_speed) {
+ if (vert) {
+ priv->scroll.coast_speed_y = scrolls_per_sec;
+ priv->scroll.coast_delta_y =
+ diffa(priv->scroll.last_a,
+ angle(priv, hw->x, hw->y));
+ }
+ else if (horiz) {
+ priv->scroll.coast_speed_x = scrolls_per_sec;
+ priv->scroll.coast_delta_x =
+ diffa(priv->scroll.last_a,
+ angle(priv, hw->x, hw->y));
+ }
+ }
+ }
+ }
+ }
+ priv->scroll.packets_this_scroll = 0;
}
static void
-stop_coasting(SynapticsPrivate *priv)
+stop_coasting(SynapticsPrivate * priv)
{
- priv->autoscroll_xspd = 0;
- priv->autoscroll_yspd = 0;
- priv->scroll_packet_count = 0;
+ priv->scroll.coast_speed_x = 0;
+ priv->scroll.coast_speed_y = 0;
+ priv->scroll.packets_this_scroll = 0;
}
static int
-HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
- edge_type edge, Bool finger, struct ScrollData *sd)
+HandleScrolling(SynapticsPrivate * priv, struct SynapticsHwState *hw,
+ enum EdgeType edge, Bool finger)
{
- SynapticsSHM *para = priv->synpara;
+ SynapticsParameters *para = &priv->synpara;
int delay = 1000000000;
- sd->left = sd->right = sd->up = sd->down = 0;
-
- if (priv->synpara->touchpad_off == 2) {
- stop_coasting(priv);
- priv->circ_scroll_on = FALSE;
- priv->vert_scroll_edge_on = FALSE;
- priv->horiz_scroll_edge_on = FALSE;
- priv->vert_scroll_twofinger_on = FALSE;
- priv->horiz_scroll_twofinger_on = FALSE;
- return delay;
+ if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF ||
+ priv->synpara.touchpad_off == TOUCHPAD_OFF ||
+ priv->finger_state == FS_BLOCKED) {
+ stop_coasting(priv);
+ priv->circ_scroll_on = FALSE;
+ priv->vert_scroll_edge_on = FALSE;
+ priv->horiz_scroll_edge_on = FALSE;
+ priv->vert_scroll_twofinger_on = FALSE;
+ priv->horiz_scroll_twofinger_on = FALSE;
+ return delay;
}
/* scroll detection */
- if (finger && !priv->finger_state) {
- stop_coasting(priv);
- if (para->circular_scrolling) {
- if ((para->circular_trigger == 0 && edge) ||
- (para->circular_trigger == 1 && edge & TOP_EDGE) ||
- (para->circular_trigger == 2 && edge & TOP_EDGE && edge & RIGHT_EDGE) ||
- (para->circular_trigger == 3 && edge & RIGHT_EDGE) ||
- (para->circular_trigger == 4 && edge & RIGHT_EDGE && edge & BOTTOM_EDGE) ||
- (para->circular_trigger == 5 && edge & BOTTOM_EDGE) ||
- (para->circular_trigger == 6 && edge & BOTTOM_EDGE && edge & LEFT_EDGE) ||
- (para->circular_trigger == 7 && edge & LEFT_EDGE) ||
- (para->circular_trigger == 8 && edge & LEFT_EDGE && edge & TOP_EDGE)) {
- priv->circ_scroll_on = TRUE;
- priv->circ_scroll_vert = TRUE;
- priv->scroll_a = angle(priv, hw->x, hw->y);
- DBG(7, ErrorF("circular scroll detected on edge\n"));
- }
- }
+ if (finger && priv->finger_state == FS_UNTOUCHED) {
+ stop_coasting(priv);
+ priv->scroll.delta_y = 0;
+ priv->scroll.delta_x = 0;
+ if (para->circular_scrolling) {
+ if ((para->circular_trigger == 0 && edge) ||
+ (para->circular_trigger == 1 && edge & TOP_EDGE) ||
+ (para->circular_trigger == 2 && edge & TOP_EDGE &&
+ edge & RIGHT_EDGE) || (para->circular_trigger == 3 &&
+ edge & RIGHT_EDGE) ||
+ (para->circular_trigger == 4 && edge & RIGHT_EDGE &&
+ edge & BOTTOM_EDGE) || (para->circular_trigger == 5 &&
+ edge & BOTTOM_EDGE) ||
+ (para->circular_trigger == 6 && edge & BOTTOM_EDGE &&
+ edge & LEFT_EDGE) || (para->circular_trigger == 7 &&
+ edge & LEFT_EDGE) ||
+ (para->circular_trigger == 8 && edge & LEFT_EDGE &&
+ edge & TOP_EDGE)) {
+ priv->circ_scroll_on = TRUE;
+ priv->circ_scroll_vert = TRUE;
+ priv->scroll.last_a = angle(priv, hw->x, hw->y);
+ DBG(7, "circular scroll detected on edge\n");
+ }
+ }
}
if (!priv->circ_scroll_on) {
- if (finger) {
- if (hw->numFingers == 2) {
- if (!priv->vert_scroll_twofinger_on &&
- (para->scroll_twofinger_vert) && (para->scroll_dist_vert != 0)) {
- priv->vert_scroll_twofinger_on = TRUE;
- priv->vert_scroll_edge_on = FALSE;
- priv->scroll_y = hw->y;
- DBG(7, ErrorF("vert two-finger scroll detected\n"));
- }
- if (!priv->horiz_scroll_twofinger_on &&
- (para->scroll_twofinger_horiz) && (para->scroll_dist_horiz != 0)) {
- priv->horiz_scroll_twofinger_on = TRUE;
- priv->horiz_scroll_edge_on = FALSE;
- priv->scroll_x = hw->x;
- DBG(7, ErrorF("horiz two-finger scroll detected\n"));
- }
- }
- }
- if (finger && !priv->finger_state) {
- if (!priv->vert_scroll_twofinger_on && !priv->horiz_scroll_twofinger_on) {
- if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
- (edge & RIGHT_EDGE)) {
- priv->vert_scroll_edge_on = TRUE;
- priv->scroll_y = hw->y;
- DBG(7, ErrorF("vert edge scroll detected on right edge\n"));
- }
- if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0) &&
- (edge & BOTTOM_EDGE)) {
- priv->horiz_scroll_edge_on = TRUE;
- priv->scroll_x = hw->x;
- DBG(7, ErrorF("horiz edge scroll detected on bottom edge\n"));
- }
- }
- }
+ if (finger) {
+ if (hw->numFingers == 2) {
+ if (!priv->vert_scroll_twofinger_on &&
+ (para->scroll_twofinger_vert) &&
+ (para->scroll_dist_vert != 0)) {
+ stop_coasting(priv);
+ priv->vert_scroll_twofinger_on = TRUE;
+ priv->vert_scroll_edge_on = FALSE;
+ priv->scroll.last_y = hw->y;
+ DBG(7, "vert two-finger scroll detected\n");
+ }
+ if (!priv->horiz_scroll_twofinger_on &&
+ (para->scroll_twofinger_horiz) &&
+ (para->scroll_dist_horiz != 0)) {
+ stop_coasting(priv);
+ priv->horiz_scroll_twofinger_on = TRUE;
+ priv->horiz_scroll_edge_on = FALSE;
+ priv->scroll.last_x = hw->x;
+ DBG(7, "horiz two-finger scroll detected\n");
+ }
+ }
+ }
+ if (finger && priv->finger_state == FS_UNTOUCHED) {
+ if (!priv->vert_scroll_twofinger_on &&
+ !priv->horiz_scroll_twofinger_on) {
+ if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
+ (edge & RIGHT_EDGE)) {
+ priv->vert_scroll_edge_on = TRUE;
+ priv->scroll.last_y = hw->y;
+ DBG(7, "vert edge scroll detected on right edge\n");
+ }
+ if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0)
+ && (edge & BOTTOM_EDGE)) {
+ priv->horiz_scroll_edge_on = TRUE;
+ priv->scroll.last_x = hw->x;
+ DBG(7, "horiz edge scroll detected on bottom edge\n");
+ }
+ }
+ }
}
{
- Bool oldv = priv->vert_scroll_edge_on || (priv->circ_scroll_on && priv->circ_scroll_vert);
- Bool oldh = priv->horiz_scroll_edge_on || (priv->circ_scroll_on && !priv->circ_scroll_vert);
- if (priv->circ_scroll_on && !finger) {
- /* circular scroll locks in until finger is raised */
- DBG(7, ErrorF("cicular scroll off\n"));
- priv->circ_scroll_on = FALSE;
- }
-
- if (hw->numFingers < 2) {
- if (priv->vert_scroll_twofinger_on) {
- DBG(7, ErrorF("vert two-finger scroll off\n"));
- priv->vert_scroll_twofinger_on = FALSE;
- }
- if (priv->horiz_scroll_twofinger_on) {
- DBG(7, ErrorF("horiz two-finger scroll off\n"));
- priv->horiz_scroll_twofinger_on = FALSE;
- }
- }
-
- if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) {
- DBG(7, ErrorF("vert edge scroll off\n"));
- priv->vert_scroll_edge_on = FALSE;
- }
- if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) {
- DBG(7, ErrorF("horiz edge scroll off\n"));
- priv->horiz_scroll_edge_on = FALSE;
- }
- /* If we were corner edge scrolling (coasting),
- * but no longer in corner or raised a finger, then stop coasting. */
- if (para->scroll_edge_corner && (priv->autoscroll_xspd || priv->autoscroll_yspd)) {
- Bool is_in_corner =
- ((edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) ||
- ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) ;
- if (!is_in_corner || !finger) {
- DBG(7, ErrorF("corner edge scroll off\n"));
- stop_coasting(priv);
- }
- }
- /* if we were scrolling, but couldn't corner edge scroll,
- * and are no longer scrolling, then start coasting */
- if ((oldv || oldh) && !para->scroll_edge_corner &&
- !(priv->circ_scroll_on || priv->vert_scroll_edge_on ||
- priv->horiz_scroll_edge_on)) {
- start_coasting(priv, hw, edge, oldv);
- }
+ Bool oldv = priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on
+ || (priv->circ_scroll_on && priv->circ_scroll_vert);
+
+ Bool oldh = priv->horiz_scroll_twofinger_on ||
+ priv->horiz_scroll_edge_on || (priv->circ_scroll_on &&
+ !priv->circ_scroll_vert);
+
+ Bool oldc = priv->circ_scroll_on;
+
+ if (priv->circ_scroll_on && !finger) {
+ /* circular scroll locks in until finger is raised */
+ DBG(7, "cicular scroll off\n");
+ priv->circ_scroll_on = FALSE;
+ }
+
+ if (!finger || hw->numFingers != 2) {
+ if (priv->vert_scroll_twofinger_on) {
+ DBG(7, "vert two-finger scroll off\n");
+ priv->vert_scroll_twofinger_on = FALSE;
+ }
+ if (priv->horiz_scroll_twofinger_on) {
+ DBG(7, "horiz two-finger scroll off\n");
+ priv->horiz_scroll_twofinger_on = FALSE;
+ }
+ }
+
+ if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) {
+ DBG(7, "vert edge scroll off\n");
+ priv->vert_scroll_edge_on = FALSE;
+ }
+ if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) {
+ DBG(7, "horiz edge scroll off\n");
+ priv->horiz_scroll_edge_on = FALSE;
+ }
+ /* If we were corner edge scrolling (coasting),
+ * but no longer in corner or raised a finger, then stop coasting. */
+ if (para->scroll_edge_corner &&
+ (priv->scroll.coast_speed_x || priv->scroll.coast_speed_y)) {
+ Bool is_in_corner = ((edge & RIGHT_EDGE) &&
+ (edge & (TOP_EDGE | BOTTOM_EDGE))) ||
+ ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE)));
+ if (!is_in_corner || !finger) {
+ DBG(7, "corner edge scroll off\n");
+ stop_coasting(priv);
+ }
+ }
+ /* if we were scrolling, but couldn't corner edge scroll,
+ * and are no longer scrolling, then start coasting */
+ oldv = oldv && !(priv->vert_scroll_twofinger_on ||
+ priv->vert_scroll_edge_on || (priv->circ_scroll_on &&
+ priv->circ_scroll_vert));
+
+ oldh = oldh && !(priv->horiz_scroll_twofinger_on ||
+ priv->horiz_scroll_edge_on || (priv->circ_scroll_on &&
+ !priv->
+ circ_scroll_vert));
+
+ oldc = oldc && !priv->circ_scroll_on;
+
+ if ((oldv || oldh) && !para->scroll_edge_corner) {
+ start_coasting(priv, hw, oldv, oldh, oldc);
+ }
}
/* if hitting a corner (top right or bottom right) while vertical
* scrolling is active, consider starting corner edge scrolling or
* switching over to circular scrolling smoothly */
if (priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on &&
- (edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) {
- if (para->scroll_edge_corner) {
- if (priv->autoscroll_yspd == 0) {
- /* FYI: We can generate multiple start_coasting requests if
- * we're in the corner, but we were moving so slowly when we
- * got here that we didn't actually start coasting. */
- DBG(7, ErrorF("corner edge scroll on\n"));
- start_coasting(priv, hw, edge, TRUE);
- }
- } else if (para->circular_scrolling) {
- priv->vert_scroll_edge_on = FALSE;
- priv->circ_scroll_on = TRUE;
- priv->circ_scroll_vert = TRUE;
- priv->scroll_a = angle(priv, hw->x, hw->y);
- DBG(7, ErrorF("switching to circular scrolling\n"));
- }
+ (edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) {
+ if (para->scroll_edge_corner) {
+ if (priv->scroll.coast_speed_y == 0) {
+ /* FYI: We can generate multiple start_coasting requests if
+ * we're in the corner, but we were moving so slowly when we
+ * got here that we didn't actually start coasting. */
+ DBG(7, "corner edge scroll on\n");
+ start_coasting(priv, hw, TRUE, FALSE, FALSE);
+ }
+ }
+ else if (para->circular_scrolling) {
+ priv->vert_scroll_edge_on = FALSE;
+ priv->circ_scroll_on = TRUE;
+ priv->circ_scroll_vert = TRUE;
+ priv->scroll.last_a = angle(priv, hw->x, hw->y);
+ DBG(7, "switching to circular scrolling\n");
+ }
}
/* Same treatment for horizontal scrolling */
if (priv->horiz_scroll_edge_on && !priv->vert_scroll_edge_on &&
- (edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) {
- if (para->scroll_edge_corner) {
- if (priv->autoscroll_xspd == 0) {
- /* FYI: We can generate multiple start_coasting requests if
- * we're in the corner, but we were moving so slowly when we
- * got here that we didn't actually start coasting. */
- DBG(7, ErrorF("corner edge scroll on\n"));
- start_coasting(priv, hw, edge, FALSE);
- }
- } else if (para->circular_scrolling) {
- priv->horiz_scroll_edge_on = FALSE;
- priv->circ_scroll_on = TRUE;
- priv->circ_scroll_vert = FALSE;
- priv->scroll_a = angle(priv, hw->x, hw->y);
- DBG(7, ErrorF("switching to circular scrolling\n"));
- }
+ (edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) {
+ if (para->scroll_edge_corner) {
+ if (priv->scroll.coast_speed_x == 0) {
+ /* FYI: We can generate multiple start_coasting requests if
+ * we're in the corner, but we were moving so slowly when we
+ * got here that we didn't actually start coasting. */
+ DBG(7, "corner edge scroll on\n");
+ start_coasting(priv, hw, FALSE, TRUE, FALSE);
+ }
+ }
+ else if (para->circular_scrolling) {
+ priv->horiz_scroll_edge_on = FALSE;
+ priv->circ_scroll_on = TRUE;
+ priv->circ_scroll_vert = FALSE;
+ priv->scroll.last_a = angle(priv, hw->x, hw->y);
+ DBG(7, "switching to circular scrolling\n");
+ }
}
if (priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
- priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
- priv->circ_scroll_on) {
- priv->scroll_packet_count++;
+ priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
+ priv->circ_scroll_on) {
+ priv->scroll.packets_this_scroll++;
}
if (priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on) {
- /* + = down, - = up */
- int delta = para->scroll_dist_vert;
- if (delta > 0) {
- while (hw->y - priv->scroll_y > delta) {
- sd->down++;
- priv->scroll_y += delta;
- }
- while (hw->y - priv->scroll_y < -delta) {
- sd->up++;
- priv->scroll_y -= delta;
- }
- }
+ /* + = down, - = up */
+ if (para->scroll_dist_vert != 0 && hw->y != priv->scroll.last_y) {
+ priv->scroll.delta_y += (hw->y - priv->scroll.last_y);
+ priv->scroll.last_y = hw->y;
+ }
}
if (priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on) {
- /* + = right, - = left */
- int delta = para->scroll_dist_horiz;
- if (delta > 0) {
- while (hw->x - priv->scroll_x > delta) {
- sd->right++;
- priv->scroll_x += delta;
- }
- while (hw->x - priv->scroll_x < -delta) {
- sd->left++;
- priv->scroll_x -= delta;
- }
- }
+ /* + = right, - = left */
+ if (para->scroll_dist_horiz != 0 && hw->x != priv->scroll.last_x) {
+ priv->scroll.delta_x += (hw->x - priv->scroll.last_x);
+ priv->scroll.last_x = hw->x;
+ }
}
if (priv->circ_scroll_on) {
- /* + = counter clockwise, - = clockwise */
- double delta = para->scroll_dist_circ;
- if (delta >= 0.005) {
- while (diffa(priv->scroll_a, angle(priv, hw->x, hw->y)) > delta) {
- if (priv->circ_scroll_vert)
- sd->up++;
- else
- sd->right++;
- priv->scroll_a += delta;
- if (priv->scroll_a > M_PI)
- priv->scroll_a -= 2 * M_PI;
- }
- while (diffa(priv->scroll_a, angle(priv, hw->x, hw->y)) < -delta) {
- if (priv->circ_scroll_vert)
- sd->down++;
- else
- sd->left++;
- priv->scroll_a -= delta;
- if (priv->scroll_a < -M_PI)
- priv->scroll_a += 2 * M_PI;
- }
- }
- }
-
- if (priv->autoscroll_yspd) {
- double dtime = (hw->millis - HIST(0).millis) / 1000.0;
- priv->autoscroll_y += priv->autoscroll_yspd * dtime;
- delay = MIN(delay, 20);
- while (priv->autoscroll_y > 1.0) {
- sd->down++;
- priv->autoscroll_y -= 1.0;
- }
- while (priv->autoscroll_y < -1.0) {
- sd->up++;
- priv->autoscroll_y += 1.0;
- }
- }
- if (priv->autoscroll_xspd) {
- double dtime = (hw->millis - HIST(0).millis) / 1000.0;
- priv->autoscroll_x += priv->autoscroll_xspd * dtime;
- delay = MIN(delay, 20);
- while (priv->autoscroll_x > 1.0) {
- sd->right++;
- priv->autoscroll_x -= 1.0;
- }
- while (priv->autoscroll_x < -1.0) {
- sd->left++;
- priv->autoscroll_x += 1.0;
- }
+ /* + = counter clockwise, - = clockwise */
+ double delta = para->scroll_dist_circ;
+ double diff = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y));
+
+ if (delta >= 0.005 && diff != 0.0) {
+ if (priv->circ_scroll_vert)
+ priv->scroll.delta_y -= diff / delta * para->scroll_dist_vert;
+ else
+ priv->scroll.delta_x -= diff / delta * para->scroll_dist_horiz;
+ priv->scroll.last_a = angle(priv, hw->x, hw->y);
+ }
+ }
+
+ if (priv->scroll.coast_speed_y) {
+ double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
+ double ddy = para->coasting_friction * dtime;
+
+ priv->scroll.delta_y += priv->scroll.coast_speed_y * dtime * abs(para->scroll_dist_vert);
+ delay = MIN(delay, POLL_MS);
+ if (fabs(priv->scroll.coast_speed_y) < ddy) {
+ priv->scroll.coast_speed_y = 0;
+ priv->scroll.packets_this_scroll = 0;
+ }
+ else {
+ priv->scroll.coast_speed_y +=
+ (priv->scroll.coast_speed_y < 0 ? ddy : -ddy);
+ }
+ }
+
+ if (priv->scroll.coast_speed_x) {
+ double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
+ double ddx = para->coasting_friction * dtime;
+ priv->scroll.delta_x += priv->scroll.coast_speed_x * dtime * abs(para->scroll_dist_horiz);
+ delay = MIN(delay, POLL_MS);
+ if (fabs(priv->scroll.coast_speed_x) < ddx) {
+ priv->scroll.coast_speed_x = 0;
+ priv->scroll.packets_this_scroll = 0;
+ }
+ else {
+ priv->scroll.coast_speed_x +=
+ (priv->scroll.coast_speed_x < 0 ? ddx : -ddx);
+ }
}
return delay;
}
-/*
- * React on changes in the hardware state. This function is called every time
- * the hardware state changes. The return value is used to specify how many
- * milliseconds to wait before calling the function again if no state change
- * occurs.
+/**
+ * Check if any 2+ fingers are close enough together to assume this is a
+ * ClickFinger action.
*/
static int
-HandleState(LocalDevicePtr local, struct SynapticsHwState *hw)
+clickpad_guess_clickfingers(SynapticsPrivate * priv,
+ struct SynapticsHwState *hw)
{
- SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
- SynapticsSHM *para = priv->synpara;
- int finger;
- int dx, dy, buttons, rep_buttons, id;
- edge_type edge;
- int change;
- struct ScrollData scroll;
- int double_click, repeat_delay;
- int delay = 1000000000;
- int timeleft;
- int i;
+ int nfingers = 0;
+ uint32_t close_point = 0; /* 1 bit for each point close to another one */
+ int i, j;
+
+ BUG_RETURN_VAL(hw->num_mt_mask > sizeof(close_point) * 8, 0);
+
+ for (i = 0; i < hw->num_mt_mask - 1; i++) {
+ ValuatorMask *f1;
+
+ if (hw->slot_state[i] == SLOTSTATE_EMPTY ||
+ hw->slot_state[i] == SLOTSTATE_CLOSE)
+ continue;
+
+ f1 = hw->mt_mask[i];
+
+ for (j = i + 1; j < hw->num_mt_mask; j++) {
+ ValuatorMask *f2;
+ double x1, x2, y1, y2;
+
+ if (hw->slot_state[j] == SLOTSTATE_EMPTY ||
+ hw->slot_state[j] == SLOTSTATE_CLOSE)
+ continue;
+
+ f2 = hw->mt_mask[j];
+
+ x1 = valuator_mask_get_double(f1, 0);
+ y1 = valuator_mask_get_double(f1, 1);
+
+ x2 = valuator_mask_get_double(f2, 0);
+ y2 = valuator_mask_get_double(f2, 1);
+
+ /* FIXME: fingers closer together than 30% of touchpad width, but
+ * really, this should be dependent on the touchpad size. Also,
+ * you'll need to find a touchpad that doesn't lie about it's
+ * size. Good luck. */
+ if (fabs(x1 - x2) < (priv->maxx - priv->minx) * .3 &&
+ fabs(y1 - y2) < (priv->maxy - priv->miny) * .3) {
+ close_point |= (1 << j);
+ close_point |= (1 << i);
+ }
+ }
+ }
+
+ while (close_point > 0) {
+ nfingers += close_point & 0x1;
+ close_point >>= 1;
+ }
+
+ /* Some trackpads touchpad only track two touchpoints but announce
+ * BTN_TOOL_TRIPLETAP (which sets hw->numFingers to 3), when this happens
+ * the user likely intents to do a 3 finger click, so handle it as such.
+ */
+ if (hw->numFingers >= 3 && hw->num_mt_mask < 3)
+ nfingers = 3;
+
+ return nfingers;
+}
+
+static void
+handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
+{
+ SynapticsParameters *para = &priv->synpara;
+ int action = 0;
+ int nfingers = hw->numFingers;
+
+ /* if this is a clickpad, clickfinger handling is:
+ * one finger down: no action, this is a normal click
+ * two fingers down: F2_CLICK
+ * three fingers down: F3_CLICK
+ */
- /* update hardware state in shared memory */
- para->x = hw->x;
- para->y = hw->y;
- para->z = hw->z;
- para->numFingers = hw->numFingers;
- para->fingerWidth = hw->fingerWidth;
- para->left = hw->left;
- para->right = hw->right;
- para->up = hw->up;
- para->down = hw->down;
- for (i = 0; i < 8; i++)
- para->multi[i] = hw->multi[i];
- para->middle = hw->middle;
- para->guest_left = hw->guest_left;
- para->guest_mid = hw->guest_mid;
- para->guest_right = hw->guest_right;
- para->guest_dx = hw->guest_dx;
- para->guest_dy = hw->guest_dy;
-
- /* If touchpad is switched off, we skip the whole thing and return delay */
- if (para->touchpad_off == 1)
- return delay;
+ if (para->clickpad)
+ nfingers = clickpad_guess_clickfingers(priv, hw);
+
+ switch (nfingers) {
+ case 1:
+ action = para->click_action[F1_CLICK1];
+ break;
+ case 2:
+ action = para->click_action[F2_CLICK1];
+ break;
+ case 3:
+ action = para->click_action[F3_CLICK1];
+ break;
+ }
+ switch (action) {
+ case 1:
+ hw->left = 1 | BTN_EMULATED_FLAG;
+ break;
+ case 2:
+ hw->left = 0;
+ hw->middle = 1 | BTN_EMULATED_FLAG;
+ break;
+ case 3:
+ hw->left = 0;
+ hw->right = 1 | BTN_EMULATED_FLAG;
+ break;
+ }
+}
+
+/* Adjust the hardware state according to the extra buttons (if the touchpad
+ * has any and not many touchpads do these days). These buttons are up/down
+ * tilt buttons and/or left/right buttons that then map into a specific
+ * function (or scrolling into).
+ */
+static Bool
+adjust_state_from_scrollbuttons(const InputInfoPtr pInfo,
+ struct SynapticsHwState *hw)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ SynapticsParameters *para = &priv->synpara;
+ Bool double_click = FALSE;
+
+ if (!para->updown_button_scrolling) {
+ if (hw->down) { /* map down button to middle button */
+ hw->middle = TRUE;
+ }
+
+ if (hw->up) { /* up button generates double click */
+ if (!priv->prev_up)
+ double_click = TRUE;
+ }
+ priv->prev_up = hw->up;
+
+ /* reset up/down button events */
+ hw->up = hw->down = FALSE;
+ }
+
+ /* Left/right button scrolling, or middle clicks */
+ if (!para->leftright_button_scrolling) {
+ if (hw->multi[2] || hw->multi[3])
+ hw->middle = TRUE;
+
+ /* reset left/right button events */
+ hw->multi[2] = hw->multi[3] = FALSE;
+ }
+
+ return double_click;
+}
+
+static void
+update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw,
+ CARD32 now, int *delay)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ SynapticsParameters *para = &priv->synpara;
/* Treat the first two multi buttons as up/down for now. */
hw->up |= hw->multi[0];
hw->down |= hw->multi[1];
- if (!para->guestmouse_off) {
- hw->left |= hw->guest_left;
- hw->middle |= hw->guest_mid;
- hw->right |= hw->guest_right;
+ /* 3rd button emulation */
+ hw->middle |= HandleMidButtonEmulation(priv, hw, now, delay);
+
+ /* If this is a clickpad and the user clicks in a soft button area, press
+ * the soft button instead. */
+ if (para->clickpad) {
+ /* hw->left is down, but no other buttons were already down */
+ if (!(priv->lastButtons & 7) && hw->left && !hw->right && !hw->middle) {
+ /* If the finger down event is delayed, the x and y
+ * coordinates are stale so we delay processing the click */
+ if (hw->z < para->finger_low) {
+ hw->left = 0;
+ goto out;
+ }
+ if (is_inside_rightbutton_area(para, hw->x, hw->y)) {
+ hw->left = 0;
+ hw->right = 1;
+ }
+ else if (is_inside_sec_rightbutton_area(para, hw->x, hw->y)) {
+ hw->left = 0;
+ hw->right = 1;
+ }
+ else if (is_inside_middlebutton_area(para, hw->x, hw->y)) {
+ hw->left = 0;
+ hw->middle = 1;
+ }
+ else if (is_inside_sec_middlebutton_area(para, hw->x, hw->y)) {
+ hw->left = 0;
+ hw->middle = 1;
+ }
+ priv->clickpad_click_millis = now;
+ }
+ else if (hw->left) {
+ hw->left = (priv->lastButtons & 1) ? 1 : 0;
+ hw->middle = (priv->lastButtons & 2) ? 1 : 0;
+ hw->right = (priv->lastButtons & 4) ? 1 : 0;
+ }
}
- /* 3rd button emulation */
- hw->middle |= HandleMidButtonEmulation(priv, hw, &delay);
+ /* Fingers emulate other buttons. ClickFinger can only be
+ triggered on transition, when left is pressed
+ */
+ if (hw->left && !(priv->lastButtons & 7) && hw->numFingers >= 1)
+ handle_clickfinger(priv, hw);
+out:
/* Two finger emulation */
- if (hw->z >= para->emulate_twofinger_z && hw->numFingers == 1) {
- hw->numFingers = 2;
+ if (hw->numFingers == 1 && hw->z >= para->emulate_twofinger_z &&
+ hw->fingerWidth >= para->emulate_twofinger_w) {
+ hw->numFingers = 2;
}
+}
- /* Up/Down button scrolling or middle/double click */
- double_click = FALSE;
- if (!para->updown_button_scrolling) {
- if (hw->down) { /* map down button to middle button */
- hw->middle = TRUE;
- }
+static void
+post_button_click(const InputInfoPtr pInfo, const int button)
+{
+ xf86PostButtonEvent(pInfo->dev, FALSE, button, TRUE, 0, 0);
+ xf86PostButtonEvent(pInfo->dev, FALSE, button, FALSE, 0, 0);
+}
- if (hw->up) { /* up button generates double click */
- if (!priv->prev_up)
- double_click = TRUE;
- }
- priv->prev_up = hw->up;
+static void
+post_scroll_events(const InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
- /* reset up/down button events */
- hw->up = hw->down = FALSE;
+ valuator_mask_zero(priv->scroll_events_mask);
+
+ if (priv->scroll.delta_y != 0.0) {
+ valuator_mask_set_double(priv->scroll_events_mask,
+ priv->scroll_axis_vert, priv->scroll.delta_y);
+ priv->scroll.delta_y = 0;
+ }
+ if (priv->scroll.delta_x != 0.0) {
+ valuator_mask_set_double(priv->scroll_events_mask,
+ priv->scroll_axis_horiz, priv->scroll.delta_x);
+ priv->scroll.delta_x = 0;
}
+ if (valuator_mask_num_valuators(priv->scroll_events_mask))
+ xf86PostMotionEventM(pInfo->dev, FALSE, priv->scroll_events_mask);
+}
- /* Left/right button scrolling, or middle clicks */
- if (!para->leftright_button_scrolling) {
- if (hw->multi[2] || hw->multi[3])
- hw->middle = TRUE;
+static inline int
+repeat_scrollbuttons(const InputInfoPtr pInfo,
+ const struct SynapticsHwState *hw,
+ int buttons, CARD32 now, int delay)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ SynapticsParameters *para = &priv->synpara;
+ int repeat_delay, timeleft;
+ int rep_buttons = 0;
+
+ if (para->updown_button_repeat)
+ rep_buttons |= (1 << (4 - 1)) | (1 << (5 - 1));
+ if (para->leftright_button_repeat)
+ rep_buttons |= (1 << (6 - 1)) | (1 << (7 - 1));
- /* reset left/right button events */
- hw->multi[2] = hw->multi[3] = FALSE;
+ /* Handle auto repeat buttons */
+ repeat_delay = clamp(para->scroll_button_repeat, SBR_MIN, SBR_MAX);
+ if (((hw->up || hw->down) && para->updown_button_repeat &&
+ para->updown_button_scrolling) ||
+ ((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat &&
+ para->leftright_button_scrolling)) {
+ priv->repeatButtons = buttons & rep_buttons;
+ if (!priv->nextRepeat) {
+ priv->nextRepeat = now + repeat_delay * 2;
+ }
+ }
+ else {
+ priv->repeatButtons = 0;
+ priv->nextRepeat = 0;
}
- /*
- * Some touchpads have a scroll wheel region where a very large X
- * coordinate is reported. For such touchpads, we adjust the X
- * coordinate to eliminate the discontinuity.
- */
- if (hw->x <= XMAX_VALID) {
- if (priv->largest_valid_x < hw->x)
- priv->largest_valid_x = hw->x;
- } else {
- hw->x = priv->largest_valid_x;
+ if (priv->repeatButtons) {
+ timeleft = TIME_DIFF(priv->nextRepeat, now);
+ if (timeleft > 0)
+ delay = MIN(delay, timeleft);
+ if (timeleft <= 0) {
+ int change, id;
+
+ change = priv->repeatButtons;
+ while (change) {
+ id = ffs(change);
+ change &= ~(1 << (id - 1));
+ if (id == 4)
+ priv->scroll.delta_y -= para->scroll_dist_vert;
+ else if (id == 5)
+ priv->scroll.delta_y += para->scroll_dist_vert;
+ else if (id == 6)
+ priv->scroll.delta_x -= para->scroll_dist_horiz;
+ else if (id == 7)
+ priv->scroll.delta_x += para->scroll_dist_horiz;
+ }
+
+ priv->nextRepeat = now + repeat_delay;
+ delay = MIN(delay, repeat_delay);
+ }
}
- edge = edge_detection(priv, hw->x, hw->y);
+ return delay;
+}
- finger = SynapticsDetectFinger(priv, hw);
+/* Update the open slots and number of active touches */
+static void
+UpdateTouchState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
+ int i;
- /* tap and drag detection */
- timeleft = HandleTapProcessing(priv, hw, edge, finger);
- if (timeleft > 0)
- delay = MIN(delay, timeleft);
+ for (i = 0; i < hw->num_mt_mask; i++) {
+ if (hw->slot_state[i] == SLOTSTATE_OPEN) {
+ priv->open_slots[priv->num_active_touches] = i;
+ priv->num_active_touches++;
+ BUG_WARN(priv->num_active_touches > priv->num_slots);
+ }
+ else if (hw->slot_state[i] == SLOTSTATE_CLOSE) {
+ Bool found = FALSE;
+ int j;
+
+ for (j = 0; j < priv->num_active_touches - 1; j++) {
+ if (priv->open_slots[j] == i)
+ found = TRUE;
+
+ if (found)
+ priv->open_slots[j] = priv->open_slots[j + 1];
+ }
+
+ BUG_WARN(priv->num_active_touches == 0);
+ if (priv->num_active_touches > 0)
+ priv->num_active_touches--;
+ }
+ }
- timeleft = HandleScrolling(priv, hw, edge, finger, &scroll);
- if (timeleft > 0)
- delay = MIN(delay, timeleft);
+ SynapticsResetTouchHwState(hw, FALSE);
+}
- timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy);
- delay = MIN(delay, timeleft);
+static void
+filter_jitter(SynapticsPrivate * priv, int *x, int *y)
+{
+ SynapticsParameters *para = &priv->synpara;
+
+ priv->hyst_center_x = hysteresis(*x, priv->hyst_center_x, para->hyst_x);
+ priv->hyst_center_y = hysteresis(*y, priv->hyst_center_y, para->hyst_y);
+ *x = priv->hyst_center_x;
+ *y = priv->hyst_center_y;
+}
+
+static void
+reset_hw_state(struct SynapticsHwState *hw)
+{
+ hw->x = 0;
+ hw->y = 0;
+ hw->z = 0;
+ hw->numFingers = 0;
+ hw->fingerWidth = 0;
+}
- rep_buttons = ((para->updown_button_repeat ? 0x18 : 0) |
- (para->leftright_button_repeat ? 0x60 : 0));
-
- buttons = ((hw->left ? 0x01 : 0) |
- (hw->middle ? 0x02 : 0) |
- (hw->right ? 0x04 : 0) |
- (hw->up ? 0x08 : 0) |
- (hw->down ? 0x10 : 0) |
- (hw->multi[2] ? 0x20 : 0) |
- (hw->multi[3] ? 0x40 : 0));
-
- if (priv->tap_button > 0) {
- int tap_mask = 1 << (priv->tap_button - 1);
- if (priv->tap_button_state == TBS_BUTTON_DOWN_UP) {
- if (tap_mask != (priv->lastButtons & tap_mask)) {
- xf86PostButtonEvent(local->dev, FALSE, priv->tap_button, TRUE, 0, 0);
- priv->lastButtons |= tap_mask;
- }
- priv->tap_button_state = TBS_BUTTON_UP;
- }
- if (priv->tap_button_state == TBS_BUTTON_DOWN)
- buttons |= tap_mask;
+/*
+ * React on changes in the hardware state. This function is called every time
+ * the hardware state changes. The return value is used to specify how many
+ * milliseconds to wait before calling the function again if no state change
+ * occurs.
+ *
+ * from_timer denotes if HandleState was triggered from a timer (e.g. to
+ * generate fake motion events, or for the tap-to-click state machine), rather
+ * than from having received a motion event.
+ */
+static int
+HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
+ Bool from_timer)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
+ SynapticsParameters *para = &priv->synpara;
+ enum FingerState finger = FS_UNTOUCHED;
+ int dx = 0, dy = 0, buttons, id;
+ enum EdgeType edge = NO_EDGE;
+ int change;
+ int double_click = FALSE;
+ int delay = 1000000000;
+ int timeleft;
+ Bool inside_active_area;
+ Bool using_cumulative_coords = FALSE;
+ Bool ignore_motion;
+
+ /* We need both and x/y, the driver can't handle just one of the two
+ * yet. But since it's possible to hit a phys button on non-clickpads
+ * without ever getting motion data first, we must continue with 0/0 for
+ * that case. */
+ if (hw->x == INT_MIN || hw->y == INT_MAX) {
+ if (para->clickpad)
+ return delay;
+ else if (hw->left || hw->right || hw->middle) {
+ hw->x = (hw->x == INT_MIN) ? 0 : hw->x;
+ hw->y = (hw->y == INT_MIN) ? 0 : hw->y;
+ }
}
- /* Post events */
- if (dx || dy)
- xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy);
+ /* If a physical button is pressed on a clickpad or a two-finger scrolling
+ * is ongoing, use cumulative relative touch movements for motion */
+ if (para->clickpad &&
+ ((priv->lastButtons & 7) ||
+ (priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on)) &&
+ priv->last_button_area != TOP_BUTTON_AREA) {
+ hw->x = hw->cumulative_dx;
+ hw->y = hw->cumulative_dy;
+ using_cumulative_coords = TRUE;
+ }
- change = buttons ^ priv->lastButtons;
- while (change) {
- id = ffs(change); /* number of first set bit 1..32 is returned */
- change &= ~(1 << (id - 1));
- xf86PostButtonEvent(local->dev, FALSE, id, (buttons & (1 << (id - 1))), 0, 0);
+ /* apply hysteresis before doing anything serious. This cancels
+ * out a lot of noise which might surface in strange phenomena
+ * like flicker in scrolling or noise motion. */
+ filter_jitter(priv, &hw->x, &hw->y);
+
+ inside_active_area = is_inside_active_area(priv, hw->x, hw->y);
+
+ /* Ignore motion *starting* inside softbuttonareas */
+ if (priv->finger_state < FS_TOUCHED)
+ priv->last_button_area = current_button_area(para, hw->x, hw->y);
+ /* If we already have a finger down, clear last_button_area if it goes
+ outside of the softbuttonareas */
+ else if (priv->last_button_area != NO_BUTTON_AREA &&
+ current_button_area(para, hw->x, hw->y) == NO_BUTTON_AREA)
+ priv->last_button_area = NO_BUTTON_AREA;
+
+ ignore_motion = para->touchpad_off == TOUCHPAD_OFF ||
+ (!using_cumulative_coords && priv->last_button_area != NO_BUTTON_AREA);
+
+ /* these two just update hw->left, right, etc. */
+ update_hw_button_state(pInfo, hw, now, &delay);
+ if (priv->has_scrollbuttons)
+ double_click = adjust_state_from_scrollbuttons(pInfo, hw);
+
+ /* Ignore motion the first X ms after a clickpad click */
+ if (priv->clickpad_click_millis) {
+ if(TIME_DIFF(priv->clickpad_click_millis +
+ para->clickpad_ignore_motion_time, now) > 0)
+ ignore_motion = TRUE;
+ else
+ priv->clickpad_click_millis = 0;
}
- while (scroll.up-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 4, !hw->up, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 4, hw->up, 0, 0);
+ /* now we know that these _coordinates_ aren't in the area.
+ invalid are: x, y, z, numFingers, fingerWidth
+ valid are: millis, left/right/middle/up/down/etc.
+ */
+ if (!inside_active_area)
+ reset_hw_state(hw);
+
+ /* no edge or finger detection outside of area */
+ if (inside_active_area) {
+ edge = edge_detection(priv, hw->x, hw->y);
+ if (!from_timer)
+ finger = SynapticsDetectFinger(priv, hw);
+ else
+ finger = priv->finger_state;
}
- while (scroll.down-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 5, !hw->down, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 5, hw->down, 0, 0);
+
+ /* tap and drag detection. Needs to be performed even if the finger is in
+ * the dead area to reset the state. */
+ timeleft = HandleTapProcessing(priv, hw, now, finger, inside_active_area);
+ if (timeleft > 0)
+ delay = MIN(delay, timeleft);
+
+ if (inside_active_area) {
+ /* Don't bother about scrolling in the dead area of the touchpad. */
+ timeleft = HandleScrolling(priv, hw, edge, (finger >= FS_TOUCHED));
+ if (timeleft > 0)
+ delay = MIN(delay, timeleft);
+
+ /*
+ * Compensate for unequal x/y resolution. This needs to be done after
+ * calculations that require unadjusted coordinates, for example edge
+ * detection.
+ */
+#ifndef NO_DRIVER_SCALING
+ ScaleCoordinates(priv, hw);
+#endif
}
- while (scroll.left-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 6, TRUE, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 6, FALSE, 0, 0);
+
+ dx = dy = 0;
+
+ timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy, inside_active_area);
+ delay = MIN(delay, timeleft);
+
+ buttons = ((hw->left ? 0x01 : 0) |
+ (hw->middle ? 0x02 : 0) |
+ (hw->right ? 0x04 : 0) |
+ (hw->up ? 0x08 : 0) |
+ (hw->down ? 0x10 : 0) |
+ (hw->multi[2] ? 0x20 : 0) | (hw->multi[3] ? 0x40 : 0));
+
+ if (priv->tap_button > 0 && priv->tap_button_state == TBS_BUTTON_DOWN)
+ buttons |= 1 << (priv->tap_button - 1);
+
+ /* Post events */
+ if (finger >= FS_TOUCHED && (dx || dy) && !ignore_motion)
+ xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
+
+ if (priv->mid_emu_state == MBE_LEFT_CLICK) {
+ post_button_click(pInfo, 1);
+ priv->mid_emu_state = MBE_OFF;
}
- while (scroll.right-- > 0) {
- xf86PostButtonEvent(local->dev, FALSE, 7, TRUE, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 7, FALSE, 0, 0);
+ else if (priv->mid_emu_state == MBE_RIGHT_CLICK) {
+ post_button_click(pInfo, 3);
+ priv->mid_emu_state = MBE_OFF;
}
- if (double_click) {
- int i;
- for (i = 0; i < 2; i++) {
- xf86PostButtonEvent(local->dev, FALSE, 1, !hw->left, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, 1, hw->left, 0, 0);
- }
+
+ change = buttons ^ priv->lastButtons;
+ while (change) {
+ id = ffs(change); /* number of first set bit 1..32 is returned */
+ change &= ~(1 << (id - 1));
+ xf86PostButtonEvent(pInfo->dev, FALSE, id, (buttons & (1 << (id - 1))),
+ 0, 0);
}
- /* Handle auto repeat buttons */
- repeat_delay = clamp(para->scroll_button_repeat, SBR_MIN, SBR_MAX);
- if (((hw->up || hw->down) && para->updown_button_repeat &&
- para->updown_button_scrolling) ||
- ((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat &&
- para->leftright_button_scrolling)) {
- priv->repeatButtons = buttons & rep_buttons;
- if (!priv->nextRepeat) {
- priv->nextRepeat = hw->millis + repeat_delay * 2;
- }
- } else {
- priv->repeatButtons = 0;
- priv->nextRepeat = 0;
+ if (priv->has_scrollbuttons)
+ delay = repeat_scrollbuttons(pInfo, hw, buttons, now, delay);
+
+ /* Process scroll events only if coordinates are
+ * in the Synaptics Area
+ */
+ if (inside_active_area &&
+ (priv->scroll.delta_x != 0.0 || priv->scroll.delta_y != 0.0)) {
+ post_scroll_events(pInfo);
+ priv->scroll.last_millis = hw->millis;
}
- if (priv->repeatButtons) {
- timeleft = TIME_DIFF(priv->nextRepeat, hw->millis);
- if (timeleft > 0)
- delay = MIN(delay, timeleft);
- if (timeleft <= 0) {
- int change, id;
- change = priv->repeatButtons;
- while (change) {
- id = ffs(change);
- change &= ~(1 << (id - 1));
- xf86PostButtonEvent(local->dev, FALSE, id, FALSE, 0, 0);
- xf86PostButtonEvent(local->dev, FALSE, id, TRUE, 0, 0);
- }
-
- priv->nextRepeat = hw->millis + repeat_delay;
- delay = MIN(delay, repeat_delay);
- }
+ if (double_click) {
+ post_button_click(pInfo, 1);
+ post_button_click(pInfo, 1);
}
+ UpdateTouchState(pInfo, hw);
+
/* Save old values of some state variables */
priv->finger_state = finger;
priv->lastButtons = buttons;
+ /* generate a history of the absolute positions */
+ if (inside_active_area)
+ store_history(priv, hw->x, hw->y, hw->millis);
+
return delay;
}
static int
-ControlProc(LocalDevicePtr local, xDeviceCtl * control)
+ControlProc(InputInfoPtr pInfo, xDeviceCtl * control)
{
- DBG(3, ErrorF("Control Proc called\n"));
+ DBG(3, "Control Proc called\n");
return Success;
}
-
-static void
-CloseProc(LocalDevicePtr local)
-{
- DBG(3, ErrorF("Close Proc called\n"));
-}
-
static int
SwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
{
- ErrorF("SwitchMode called\n");
- return Success;
+ DBG(3, "SwitchMode called\n");
+
+ return XI_BadMode;
}
-static Bool
-ConvertProc(LocalDevicePtr local,
- int first,
- int num,
- int v0,
- int v1,
- int v2,
- int v3,
- int v4,
- int v5,
- int *x,
- int *y)
-{
- if (first != 0 || num != 2)
- return FALSE;
-
- *x = v0;
- *y = v1;
+static void
+ReadDevDimensions(InputInfoPtr pInfo)
+{
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
- return TRUE;
-}
+ if (priv->proto_ops->ReadDevDimensions)
+ priv->proto_ops->ReadDevDimensions(pInfo);
+ SanitizeDimensions(pInfo);
+}
static Bool
-QueryHardware(LocalDevicePtr local)
+QueryHardware(InputInfoPtr pInfo)
{
- SynapticsPrivate *priv = (SynapticsPrivate *) local->private;
- SynapticsSHM *para = priv->synpara;
+ SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
priv->comm.protoBufTail = 0;
- if (priv->proto_ops->QueryHardware(local, &priv->synhw)) {
- para->synhw = priv->synhw;
- if (priv->fifofd != -1) {
- xf86CloseSerial(priv->fifofd);
- priv->fifofd = -1;
- }
- return TRUE;
+ if (!priv->proto_ops->QueryHardware(pInfo)) {
+ xf86IDrvMsg(pInfo, X_PROBED, "no supported touchpad found\n");
+ if (priv->proto_ops->DeviceOffHook)
+ priv->proto_ops->DeviceOffHook(pInfo);
+ return FALSE;
}
- if (priv->fifofd == -1) {
- xf86Msg(X_ERROR, "%s no synaptics touchpad detected and no repeater device\n",
- local->name);
- return FALSE;
- }
- xf86Msg(X_PROBED, "%s no synaptics touchpad, data piped to repeater fifo\n", local->name);
- priv->proto_ops->DeviceOffHook(local);
return TRUE;
}
+
+#ifndef NO_DRIVER_SCALING
+static void
+ScaleCoordinates(SynapticsPrivate * priv, struct SynapticsHwState *hw)
+{
+ int xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2;
+ int yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2;
+
+ hw->x = (hw->x - xCenter) * priv->horiz_coeff + xCenter;
+ hw->y = (hw->y - yCenter) * priv->vert_coeff + yCenter;
+}
+
+void
+CalculateScalingCoeffs(SynapticsPrivate * priv)
+{
+ int vertRes = priv->synpara.resolution_vert;
+ int horizRes = priv->synpara.resolution_horiz;
+
+ if ((horizRes > vertRes) && (horizRes > 0)) {
+ priv->horiz_coeff = vertRes / (double) horizRes;
+ priv->vert_coeff = 1;
+ }
+ else if ((horizRes < vertRes) && (vertRes > 0)) {
+ priv->horiz_coeff = 1;
+ priv->vert_coeff = horizRes / (double) vertRes;
+ }
+ else {
+ priv->horiz_coeff = 1;
+ priv->vert_coeff = 1;
+ }
+}
+#endif
diff --git a/src/synaptics.h b/src/synaptics.h
deleted file mode 100644
index f780849..0000000
--- a/src/synaptics.h
+++ /dev/null
@@ -1,253 +0,0 @@
-#ifndef _SYNAPTICS_H_
-#define _SYNAPTICS_H_
-
-#include <X11/Xdefs.h>
-
-/******************************************************************************
- * Public definitions.
- * Used by driver and the shared memory configurator
- *****************************************************************************/
-typedef enum {
- RT_TAP = 0, /* Right top corner */
- RB_TAP, /* Right bottom corner */
- LT_TAP, /* Left top corner */
- LB_TAP, /* Left bottom corner */
- F1_TAP, /* Non-corner tap, one finger */
- F2_TAP, /* Non-corner tap, two fingers */
- F3_TAP, /* Non-corner tap, three fingers */
- MAX_TAP
-} TapEvent;
-
-#define SYN_MAX_BUTTONS 12 /* Max number of mouse buttons */
-
-struct SynapticsHwInfo {
- unsigned int model_id; /* Model-ID */
- unsigned int capabilities; /* Capabilities */
- unsigned int ext_cap; /* Extended Capabilities */
- unsigned int identity; /* Identification */
- Bool hasGuest; /* Has a guest mouse */
-};
-
-
-#define SHM_SYNAPTICS 23947
-typedef struct _SynapticsSHM
-{
- int version; /* Driver version */
-
- /* Current device state */
- int x, y; /* actual x, y coordinates */
- int z; /* pressure value */
- int numFingers; /* number of fingers */
- int fingerWidth; /* finger width value */
- int left, right, up, down; /* left/right/up/down buttons */
- Bool multi[8];
- Bool middle;
- int guest_left, guest_mid, guest_right; /* guest device buttons */
- int guest_dx, guest_dy; /* guest device movement */
-
- /* Probed hardware properties */
- struct SynapticsHwInfo synhw;
-
- /* Parameter data */
- int left_edge, right_edge, top_edge, bottom_edge; /* edge coordinates absolute */
- int finger_low, finger_high, finger_press; /* finger detection values in Z-values */
- int tap_time;
- int tap_move; /* max. tapping time and movement in packets and coord. */
- int single_tap_timeout; /* timeout to recognize a single tap */
- int tap_time_2; /* max. tapping time for double taps */
- int click_time; /* The duration of a single click */
- Bool fast_taps; /* Faster reaction to single taps */
- int emulate_mid_button_time; /* Max time between left and right button presses to
- emulate a middle button press. */
- int emulate_twofinger_z; /* pressure threshold to emulate two finger touch (for Alps) */
- int scroll_dist_vert; /* Scrolling distance in absolute coordinates */
- int scroll_dist_horiz; /* Scrolling distance in absolute coordinates */
- Bool scroll_edge_vert; /* Enable/disable vertical scrolling on right edge */
- Bool scroll_edge_horiz; /* Enable/disable horizontal scrolling on left edge */
- Bool scroll_edge_corner; /* Enable/disable continuous edge scrolling when in the corner */
- Bool scroll_twofinger_vert; /* Enable/disable vertical two-finger scrolling */
- Bool scroll_twofinger_horiz; /* Enable/disable horizontal two-finger scrolling */
- double min_speed, max_speed, accl; /* movement parameters */
- double trackstick_speed; /* trackstick mode speed */
- int edge_motion_min_z; /* finger pressure at which minimum edge motion speed is set */
- int edge_motion_max_z; /* finger pressure at which maximum edge motion speed is set */
- int edge_motion_min_speed; /* slowest setting for edge motion speed */
- int edge_motion_max_speed; /* fastest setting for edge motion speed */
- Bool edge_motion_use_always; /* If false, egde motion is used only when dragging */
-
- Bool updown_button_scrolling; /* Up/Down-Button scrolling or middle/double-click */
- Bool leftright_button_scrolling; /* Left/right-button scrolling, or two lots of middle button */
- Bool updown_button_repeat; /* If up/down button being used to scroll, auto-repeat?*/
- Bool leftright_button_repeat; /* If left/right button being used to scroll, auto-repeat? */
- int scroll_button_repeat; /* time, in milliseconds, between scroll events being
- * sent when holding down scroll buttons */
- int touchpad_off; /* Switches the touchpad off
- * 0 : Not off
- * 1 : Off
- * 2 : Only tapping and scrolling off
- */
- Bool guestmouse_off; /* Switches the guest mouse off */
- Bool locked_drags; /* Enable locked drags */
- int locked_drag_time; /* timeout for locked drags */
- int tap_action[MAX_TAP]; /* Button to report on tap events */
- Bool circular_scrolling; /* Enable circular scrolling */
- double scroll_dist_circ; /* Scrolling angle radians */
- int circular_trigger; /* Trigger area for circular scrolling */
- Bool circular_pad; /* Edge has an oval or circular shape */
- Bool palm_detect; /* Enable Palm Detection */
- int palm_min_width; /* Palm detection width */
- int palm_min_z; /* Palm detection depth */
- double coasting_speed; /* Coasting threshold scrolling speed */
- int press_motion_min_z; /* finger pressure at which minimum pressure motion factor is applied */
- int press_motion_max_z; /* finger pressure at which maximum pressure motion factor is applied */
- double press_motion_min_factor; /* factor applied on speed when finger pressure is at minimum */
- double press_motion_max_factor; /* factor applied on speed when finger pressure is at minimum */
- Bool grab_event_device; /* grab event device for exclusive use? */
-} SynapticsSHM;
-
-/*
- * Minimum and maximum values for scroll_button_repeat
- */
-#define SBR_MIN 10
-#define SBR_MAX 1000
-
-/*
- * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
- * section 2.3.2, which says that they should be valid regardless of the
- * actual size of the sensor.
- */
-#define XMIN_NOMINAL 1472
-#define XMAX_NOMINAL 5472
-#define YMIN_NOMINAL 1408
-#define YMAX_NOMINAL 4448
-
-#define XMAX_VALID 6143
-
-
-#ifdef SYNAPTICS_PRIVATE
-
-#include "synproto.h"
-
-/******************************************************************************
- * Definitions
- * structs, typedefs, #defines, enums
- *****************************************************************************/
-#define SYNAPTICS_MOVE_HISTORY 5
-
-typedef struct _SynapticsMoveHist
-{
- int x, y;
- int millis;
-} SynapticsMoveHistRec;
-
-enum FingerState { /* Note! The order matters. Compared with < operator. */
- FS_UNTOUCHED,
- FS_TOUCHED,
- FS_PRESSED
-};
-
-enum MovingState {
- MS_FALSE,
- MS_TOUCHPAD_RELATIVE,
- MS_TRACKSTICK /* trackstick is always relative */
-};
-
-enum MidButtonEmulation {
- MBE_OFF, /* No button pressed */
- MBE_LEFT, /* Left button pressed, waiting for right button or timeout */
- MBE_RIGHT, /* Right button pressed, waiting for left button or timeout */
- MBE_MID, /* Left and right buttons pressed, waiting for both buttons
- to be released */
- MBE_TIMEOUT /* Waiting for both buttons to be released. */
-};
-
-/* See docs/tapndrag.dia for a state machine diagram */
-enum TapState {
- TS_START, /* No tap/drag in progress */
- TS_1, /* After first touch */
- TS_MOVE, /* Pointer movement enabled */
- TS_2A, /* After first release */
- TS_2B, /* After second/third/... release */
- TS_SINGLETAP, /* After timeout after first release */
- TS_3, /* After second touch */
- TS_DRAG, /* Pointer drag enabled */
- TS_4, /* After release when "locked drags" enabled */
- TS_5 /* After touch when "locked drags" enabled */
-};
-
-enum TapButtonState {
- TBS_BUTTON_UP, /* "Virtual tap button" is up */
- TBS_BUTTON_DOWN, /* "Virtual tap button" is down */
- TBS_BUTTON_DOWN_UP /* Send button down event + set up state */
-};
-
-typedef struct _SynapticsPrivateRec
-{
- SynapticsSHM synpara_default; /* Default parameter settings, read from
- the X config file */
- SynapticsSHM *synpara; /* Current parameter settings. Will point to
- shared memory if shm_config is true */
- struct SynapticsProtocolOperations* proto_ops;
-
- struct SynapticsHwState hwState;
-
- struct SynapticsHwInfo synhw; /* Data read from the touchpad */
- Bool shm_config; /* True when shared memory area allocated */
-
- OsTimerPtr timer; /* for up/down-button repeat, tap processing, etc */
-
- struct CommData comm;
- int fifofd; /* fd for fifo */
-
- SynapticsMoveHistRec move_hist[SYNAPTICS_MOVE_HISTORY]; /* movement history */
- int hist_index; /* Last added entry in move_hist[] */
- int largest_valid_x; /* Largest valid X coordinate seen so far */
- int scroll_y; /* last y-scroll position */
- int scroll_x; /* last x-scroll position */
- double scroll_a; /* last angle-scroll position */
- int count_packet_finger; /* packet counter with finger on the touchpad */
- int button_delay_millis; /* button delay for 3rd button emulation */
- Bool prev_up; /* Previous up button value, for double click emulation */
- enum FingerState finger_state; /* previous finger state */
-
- enum TapState tap_state; /* State of tap processing */
- int tap_max_fingers; /* Max number of fingers seen since entering start state */
- int tap_button; /* Which button started the tap processing */
- enum TapButtonState tap_button_state; /* Current tap action */
- SynapticsMoveHistRec touch_on; /* data when the touchpad is touched/released */
-
- enum MovingState moving_state; /* previous moving state */
- Bool vert_scroll_edge_on; /* Keeps track of currently active scroll modes */
- Bool horiz_scroll_edge_on; /* Keeps track of currently active scroll modes */
- Bool vert_scroll_twofinger_on; /* Keeps track of currently active scroll modes */
- Bool horiz_scroll_twofinger_on; /* Keeps track of currently active scroll modes */
- Bool circ_scroll_on; /* Keeps track of currently active scroll modes */
- Bool circ_scroll_vert; /* True: Generate vertical scroll events
- False: Generate horizontal events */
- int trackstick_neutral_x; /* neutral x position for trackstick mode */
- int trackstick_neutral_y; /* neutral y position for trackstick mode */
- double autoscroll_xspd; /* Horizontal coasting speed */
- double autoscroll_yspd; /* Vertical coasting speed */
- double autoscroll_x; /* Accumulated horizontal coasting scroll */
- double autoscroll_y; /* Accumulated vertical coasting scroll */
- int scroll_packet_count; /* Scroll duration */
- double frac_x, frac_y; /* absolute -> relative fraction */
- enum MidButtonEmulation mid_emu_state; /* emulated 3rd button */
- int repeatButtons; /* buttons for repeat */
- int nextRepeat; /* Time when to trigger next auto repeat event */
- int lastButtons; /* last state of the buttons */
- int palm; /* Set to true when palm detected, reset to false when
- palm/finger contact disappears */
- int prev_z; /* previous z value, for palm detection */
- int avg_width; /* weighted average of previous fingerWidth values */
- int minx;
- int maxx;
- int miny;
- int maxy;
-} SynapticsPrivate;
-
-
-#endif /* SYNAPTICS_PRIVATE */
-
-
-#endif /* _SYNAPTICS_H_ */
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
new file mode 100644
index 0000000..a6513db
--- /dev/null
+++ b/src/synapticsstr.h
@@ -0,0 +1,338 @@
+/*
+ * 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 _SYNAPTICSSTR_H_
+#define _SYNAPTICSSTR_H_
+
+#include "synproto.h"
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 18
+#define LogMessageVerbSigSafe xf86MsgVerb
+#endif
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) > 19
+#define NO_DRIVER_SCALING 1
+#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 19 && GET_ABI_MINOR(ABI_XINPUT_VERSION) >= 2
+/* as of 19.2, the server takes device resolution into account when scaling
+ relative events from abs device, so we must not scale in synaptics. */
+#define NO_DRIVER_SCALING 1
+#endif
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 23
+#define HAVE_THREADED_INPUT 1
+#endif
+
+#ifdef DBG
+#undef DBG
+#endif
+
+#ifdef DEBUG
+#define DBG(verb, ...) \
+ xf86MsgVerb(X_INFO, verb, __VA_ARGS__)
+#else
+#define DBG(verb, msg, ...) /* */
+#endif
+
+/******************************************************************************
+ * Definitions
+ * structs, typedefs, #defines, enums
+ *****************************************************************************/
+#define SYNAPTICS_MOVE_HISTORY 5
+#define SYNAPTICS_MAX_TOUCHES 10
+#define SYN_MAX_BUTTONS 12 /* Max number of mouse buttons */
+
+/* Minimum and maximum values for scroll_button_repeat */
+#define SBR_MIN 10
+#define SBR_MAX 1000
+
+enum OffState {
+ TOUCHPAD_ON = 0,
+ TOUCHPAD_OFF = 1,
+ TOUCHPAD_TAP_OFF = 2,
+};
+
+enum TapEvent {
+ RT_TAP = 0, /* Right top corner */
+ RB_TAP, /* Right bottom corner */
+ LT_TAP, /* Left top corner */
+ LB_TAP, /* Left bottom corner */
+ F1_TAP, /* Non-corner tap, one finger */
+ F2_TAP, /* Non-corner tap, two fingers */
+ F3_TAP, /* Non-corner tap, three fingers */
+ MAX_TAP
+};
+
+enum ClickFingerEvent {
+ F1_CLICK1 = 0, /* Click left, one finger */
+ F2_CLICK1, /* Click left, two fingers */
+ F3_CLICK1, /* Click left, three fingers */
+ MAX_CLICK
+};
+
+
+typedef struct _SynapticsMoveHist {
+ int x, y;
+ CARD32 millis;
+} SynapticsMoveHistRec;
+
+typedef struct _SynapticsTouchAxis {
+ const char *label;
+ int min;
+ int max;
+ int res;
+} SynapticsTouchAxisRec;
+
+enum FingerState { /* Note! The order matters. Compared with < operator. */
+ FS_BLOCKED = -1,
+ FS_UNTOUCHED = 0, /* this is 0 so it's the initialized value. */
+ FS_TOUCHED = 1,
+ FS_PRESSED = 2,
+};
+
+enum MovingState {
+ MS_FALSE,
+ MS_TOUCHPAD_RELATIVE,
+};
+
+enum MidButtonEmulation {
+ MBE_OFF, /* No button pressed */
+ MBE_LEFT, /* Left button pressed, waiting for right button or timeout */
+ MBE_RIGHT, /* Right button pressed, waiting for left button or timeout */
+ MBE_MID, /* Left and right buttons pressed, waiting for both buttons
+ to be released */
+ MBE_TIMEOUT, /* Waiting for both buttons to be released. */
+ MBE_LEFT_CLICK, /* Emulate left button click. */
+ MBE_RIGHT_CLICK, /* Emulate right button click. */
+};
+
+/* See docs/tapndrag.dia for a state machine diagram */
+enum TapState {
+ TS_START, /* No tap/drag in progress */
+ TS_1, /* After first touch */
+ TS_MOVE, /* Pointer movement enabled */
+ TS_2A, /* After first release */
+ TS_2B, /* After second/third/... release */
+ TS_SINGLETAP, /* After timeout after first release */
+ TS_3, /* After second touch */
+ TS_DRAG, /* Pointer drag enabled */
+ TS_4, /* After release when "locked drags" enabled */
+ TS_5, /* After touch when "locked drags" enabled */
+ TS_CLICKPAD_MOVE, /* After left button press on a clickpad */
+};
+
+enum TapButtonState {
+ TBS_BUTTON_UP, /* "Virtual tap button" is up */
+ TBS_BUTTON_DOWN, /* "Virtual tap button" is down */
+};
+
+enum TouchpadModel {
+ MODEL_UNKNOWN = 0,
+ MODEL_SYNAPTICS,
+ MODEL_ALPS,
+ MODEL_APPLETOUCH,
+ MODEL_ELANTECH,
+ MODEL_UNIBODY_MACBOOK
+};
+
+enum SoftButtonAreas {
+ NO_BUTTON_AREA = -1,
+ BOTTOM_BUTTON_AREA = 0,
+ BOTTOM_RIGHT_BUTTON_AREA = 0,
+ BOTTOM_MIDDLE_BUTTON_AREA = 1,
+ TOP_BUTTON_AREA = 2,
+ TOP_RIGHT_BUTTON_AREA = 2,
+ TOP_MIDDLE_BUTTON_AREA = 3
+};
+
+enum SoftButtonAreaEdges {
+ LEFT = 0,
+ RIGHT = 1,
+ TOP = 2,
+ BOTTOM = 3
+};
+
+typedef struct _SynapticsParameters {
+ /* Parameter data */
+ int left_edge, right_edge, top_edge, bottom_edge; /* edge coordinates absolute */
+ int finger_low, finger_high, finger_press; /* finger detection values in Z-values */
+ int tap_time;
+ int tap_move; /* max. tapping time and movement in packets and coord. */
+ int single_tap_timeout; /* timeout to recognize a single tap */
+ int tap_time_2; /* max. tapping time for double taps */
+ int click_time; /* The duration of a single click */
+ Bool clickpad; /* Device is a has integrated buttons */
+ Bool has_secondary_buttons; /* Device has a top soft-button area */
+ int clickpad_ignore_motion_time; /* Ignore motion for X ms after a click */
+ int emulate_mid_button_time; /* Max time between left and right button presses to
+ emulate a middle button press. */
+ int emulate_twofinger_z; /* pressure threshold to emulate two finger touch (for Alps) */
+ int emulate_twofinger_w; /* Finger width threshold to emulate two finger touch */
+ int scroll_dist_vert; /* Scrolling distance in absolute coordinates */
+ int scroll_dist_horiz; /* Scrolling distance in absolute coordinates */
+ Bool scroll_edge_vert; /* Enable/disable vertical scrolling on right edge */
+ Bool scroll_edge_horiz; /* Enable/disable horizontal scrolling on left edge */
+ Bool scroll_edge_corner; /* Enable/disable continuous edge scrolling when in the corner */
+ Bool scroll_twofinger_vert; /* Enable/disable vertical two-finger scrolling */
+ Bool scroll_twofinger_horiz; /* Enable/disable horizontal two-finger scrolling */
+ double min_speed, max_speed, accl; /* movement parameters */
+
+ Bool updown_button_scrolling; /* Up/Down-Button scrolling or middle/double-click */
+ Bool leftright_button_scrolling; /* Left/right-button scrolling, or two lots of middle button */
+ Bool updown_button_repeat; /* If up/down button being used to scroll, auto-repeat? */
+ Bool leftright_button_repeat; /* If left/right button being used to scroll, auto-repeat? */
+ int scroll_button_repeat; /* time, in milliseconds, between scroll events being
+ * sent when holding down scroll buttons */
+ int touchpad_off; /* Switches the touchpad off
+ * 0 : Not off
+ * 1 : Off
+ * 2 : Only tapping and scrolling off
+ */
+ Bool locked_drags; /* Enable locked drags */
+ int locked_drag_time; /* timeout for locked drags */
+ int tap_action[MAX_TAP]; /* Button to report on tap events */
+ int click_action[MAX_CLICK]; /* Button to report on click with fingers */
+ Bool circular_scrolling; /* Enable circular scrolling */
+ double scroll_dist_circ; /* Scrolling angle radians */
+ int circular_trigger; /* Trigger area for circular scrolling */
+ Bool circular_pad; /* Edge has an oval or circular shape */
+ Bool palm_detect; /* Enable Palm Detection */
+ int palm_min_width; /* Palm detection width */
+ int palm_min_z; /* Palm detection depth */
+ double coasting_speed; /* Coasting threshold scrolling speed in scrolls/s */
+ double coasting_friction; /* Number of scrolls per second per second to change coasting speed */
+ int press_motion_min_z; /* finger pressure at which minimum pressure motion factor is applied */
+ int press_motion_max_z; /* finger pressure at which maximum pressure motion factor is applied */
+ double press_motion_min_factor; /* factor applied on speed when finger pressure is at minimum */
+ double press_motion_max_factor; /* factor applied on speed when finger pressure is at minimum */
+ Bool grab_event_device; /* grab event device for exclusive use? */
+ Bool tap_and_drag_gesture; /* Switches the tap-and-drag gesture on/off */
+ unsigned int resolution_horiz; /* horizontal resolution of touchpad in units/mm */
+ unsigned int resolution_vert; /* vertical resolution of touchpad in units/mm */
+ int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */
+ int softbutton_areas[4][4]; /* soft button area coordinates, 0 => right, 1 => middle , 2 => secondary right, 3 => secondary middle button */
+ int hyst_x, hyst_y; /* x and y width of hysteresis box */
+
+ int maxDeltaMM; /* maximum delta movement (vector length) in mm */
+} SynapticsParameters;
+
+struct _SynapticsPrivateRec {
+ SynapticsParameters synpara; /* Default parameter settings, read from
+ the X config file */
+ struct SynapticsProtocolOperations *proto_ops;
+ void *proto_data; /* protocol-specific data */
+
+ struct SynapticsHwState *hwState;
+
+ const char *device; /* device node */
+ CARD32 timer_time; /* when timer last fired */
+ OsTimerPtr timer; /* for up/down-button repeat, tap processing, etc */
+
+ struct CommData comm;
+
+ struct SynapticsHwState *local_hw_state; /* used in place of local hw state variables */
+
+ SynapticsMoveHistRec move_hist[SYNAPTICS_MOVE_HISTORY]; /* movement history */
+ int hist_index; /* Last added entry in move_hist[] */
+ int hyst_center_x; /* center x of hysteresis */
+ int hyst_center_y; /* center y of hysteresis */
+ struct {
+ int last_x; /* last x-scroll position */
+ int last_y; /* last y-scroll position */
+ double delta_x; /* accumulated horiz scroll delta */
+ double delta_y; /* accumulated vert scroll delta */
+ double last_a; /* last angle-scroll position */
+ CARD32 last_millis; /* time last scroll event posted */
+ double coast_speed_x; /* Horizontal coasting speed in scrolls/s */
+ double coast_speed_y; /* Vertical coasting speed in scrolls/s */
+ double coast_delta_x; /* Accumulated horizontal coast delta */
+ double coast_delta_y; /* Accumulated vertical coast delta */
+ int packets_this_scroll; /* Events received for this scroll */
+ } scroll;
+ int count_packet_finger; /* packet counter with finger on the touchpad */
+ int button_delay_millis; /* button delay for 3rd button emulation */
+ Bool prev_up; /* Previous up button value, for double click emulation */
+ enum FingerState finger_state; /* previous finger state */
+ CARD32 last_motion_millis; /* time of the last motion */
+ enum SoftButtonAreas last_button_area; /* Last button area we were in */
+ int clickpad_click_millis; /* Time of last clickpad click */
+
+ enum TapState tap_state; /* State of tap processing */
+ int tap_max_fingers; /* Max number of fingers seen since entering start state */
+ int tap_button; /* Which button started the tap processing */
+ enum TapButtonState tap_button_state; /* Current tap action */
+ SynapticsMoveHistRec touch_on; /* data when the touchpad is touched/released */
+
+ enum MovingState moving_state; /* previous moving state */
+ Bool vert_scroll_edge_on; /* Keeps track of currently active scroll modes */
+ Bool horiz_scroll_edge_on; /* Keeps track of currently active scroll modes */
+ Bool vert_scroll_twofinger_on; /* Keeps track of currently active scroll modes */
+ Bool horiz_scroll_twofinger_on; /* Keeps track of currently active scroll modes */
+ Bool circ_scroll_on; /* Keeps track of currently active scroll modes */
+ Bool circ_scroll_vert; /* True: Generate vertical scroll events
+ False: Generate horizontal events */
+ enum MidButtonEmulation mid_emu_state; /* emulated 3rd button */
+ int repeatButtons; /* buttons for repeat */
+ int nextRepeat; /* Time when to trigger next auto repeat event */
+ int lastButtons; /* last state of the buttons */
+ int prev_z; /* previous z value, for palm detection */
+ int prevFingers; /* previous numFingers, for transition detection */
+ int avg_width; /* weighted average of previous fingerWidth values */
+#ifndef NO_DRIVER_SCALING
+ double horiz_coeff; /* normalization factor for x coordinates */
+ double vert_coeff; /* normalization factor for y coordinates */
+#endif
+
+ int minx, maxx, miny, maxy; /* min/max dimensions as detected */
+ int minp, maxp, minw, maxw; /* min/max pressure and finger width as detected */
+ int resx, resy; /* resolution of coordinates as detected in units/mm */
+ Bool has_left; /* left button detected for this device */
+ Bool has_right; /* right button detected for this device */
+ Bool has_middle; /* middle button detected for this device */
+ Bool has_double; /* double click detected for this device */
+ Bool has_triple; /* triple click detected for this device */
+ Bool has_pressure; /* device reports pressure */
+ Bool has_width; /* device reports finger width */
+ Bool has_scrollbuttons; /* device has physical scrollbuttons */
+ Bool has_semi_mt; /* device is only semi-multitouch capable */
+ Bool has_mt_palm_detect; /* device reports per finger width and pressure */
+
+ enum TouchpadModel model; /* The detected model */
+ unsigned short id_vendor; /* vendor id */
+ unsigned short id_product; /* product id */
+
+ int scroll_axis_horiz; /* Horizontal smooth-scrolling axis */
+ int scroll_axis_vert; /* Vertical smooth-scrolling axis */
+ ValuatorMask *scroll_events_mask; /* ValuatorMask for smooth-scrolling */
+
+ Bool has_touch; /* Device has multitouch capabilities */
+ int max_touches; /* Number of touches supported */
+ int num_mt_axes; /* Number of multitouch axes other than X, Y */
+ SynapticsTouchAxisRec *touch_axes; /* Touch axis information other than X, Y */
+ int num_slots; /* Number of touch slots allocated */
+ int *open_slots; /* Array of currently open touch slots */
+ int num_active_touches; /* Number of active touches on device */
+};
+
+void InitDeviceProperties(InputInfoPtr pInfo);
+int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
+ BOOL checkonly);
+
+#endif /* _SYNAPTICSSTR_H_ */
diff --git a/src/synclient.c b/src/synclient.c
deleted file mode 100644
index 3834f38..0000000
--- a/src/synclient.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright 2002-2005,2007 Peter Osterlund <petero2@telia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <string.h>
-#include <stddef.h>
-#include <math.h>
-
-#include <X11/Xdefs.h>
-#include "synaptics.h"
-
-enum ParaType {
- PT_INT,
- PT_BOOL,
- PT_DOUBLE
-};
-
-struct Parameter {
- char *name; /* Name of parameter */
- int offset; /* Offset in shared memory area */
- enum ParaType type; /* Type of parameter */
- double min_val; /* Minimum allowed value */
- double max_val; /* Maximum allowed value */
-};
-
-#define DEFINE_PAR(name, memb, type, min_val, max_val) \
-{ name, offsetof(SynapticsSHM, memb), (type), (min_val), (max_val) }
-
-static struct Parameter params[] = {
- DEFINE_PAR("LeftEdge", left_edge, PT_INT, 0, 10000),
- DEFINE_PAR("RightEdge", right_edge, PT_INT, 0, 10000),
- DEFINE_PAR("TopEdge", top_edge, PT_INT, 0, 10000),
- DEFINE_PAR("BottomEdge", bottom_edge, PT_INT, 0, 10000),
- DEFINE_PAR("FingerLow", finger_low, PT_INT, 0, 255),
- DEFINE_PAR("FingerHigh", finger_high, PT_INT, 0, 255),
- DEFINE_PAR("FingerPress", finger_press, PT_INT, 0, 256),
- DEFINE_PAR("MaxTapTime", tap_time, PT_INT, 0, 1000),
- DEFINE_PAR("MaxTapMove", tap_move, PT_INT, 0, 2000),
- DEFINE_PAR("MaxDoubleTapTime", tap_time_2, PT_INT, 0, 1000),
- DEFINE_PAR("SingleTapTimeout", single_tap_timeout, PT_INT, 0, 1000),
- DEFINE_PAR("ClickTime", click_time, PT_INT, 0, 1000),
- DEFINE_PAR("FastTaps", fast_taps, PT_BOOL, 0, 1),
- DEFINE_PAR("EmulateMidButtonTime", emulate_mid_button_time, PT_INT, 0, 1000),
- DEFINE_PAR("EmulateTwoFingerMinZ", emulate_twofinger_z, PT_INT, 0, 1000),
- DEFINE_PAR("VertScrollDelta", scroll_dist_vert, PT_INT, 0, 1000),
- DEFINE_PAR("HorizScrollDelta", scroll_dist_horiz, PT_INT, 0, 1000),
- DEFINE_PAR("VertEdgeScroll", scroll_edge_vert, PT_BOOL, 0, 1),
- DEFINE_PAR("HorizEdgeScroll", scroll_edge_horiz, PT_BOOL, 0, 1),
- DEFINE_PAR("CornerCoasting", scroll_edge_corner, PT_BOOL, 0, 1),
- DEFINE_PAR("VertTwoFingerScroll", scroll_twofinger_vert, PT_BOOL, 0, 1),
- DEFINE_PAR("HorizTwoFingerScroll", scroll_twofinger_horiz, PT_BOOL, 0, 1),
- DEFINE_PAR("MinSpeed", min_speed, PT_DOUBLE, 0, 1.0),
- DEFINE_PAR("MaxSpeed", max_speed, PT_DOUBLE, 0, 1.0),
- DEFINE_PAR("AccelFactor", accl, PT_DOUBLE, 0, 0.2),
- DEFINE_PAR("TrackstickSpeed", trackstick_speed, PT_DOUBLE, 0, 200.0),
- DEFINE_PAR("EdgeMotionMinZ", edge_motion_min_z, PT_INT, 1, 255),
- DEFINE_PAR("EdgeMotionMaxZ", edge_motion_max_z, PT_INT, 1, 255),
- DEFINE_PAR("EdgeMotionMinSpeed", edge_motion_min_speed, PT_INT, 0, 1000),
- DEFINE_PAR("EdgeMotionMaxSpeed", edge_motion_max_speed, PT_INT, 0, 1000),
- DEFINE_PAR("EdgeMotionUseAlways", edge_motion_use_always, PT_BOOL, 0, 1),
- DEFINE_PAR("UpDownScrolling", updown_button_scrolling, PT_BOOL, 0, 1),
- DEFINE_PAR("LeftRightScrolling", leftright_button_scrolling, PT_BOOL, 0, 1),
- DEFINE_PAR("UpDownScrollRepeat", updown_button_repeat, PT_BOOL, 0, 1),
- DEFINE_PAR("LeftRightScrollRepeat",leftright_button_repeat, PT_BOOL, 0, 1),
- DEFINE_PAR("ScrollButtonRepeat", scroll_button_repeat, PT_INT, SBR_MIN , SBR_MAX),
- DEFINE_PAR("TouchpadOff", touchpad_off, PT_INT, 0, 2),
- DEFINE_PAR("GuestMouseOff", guestmouse_off, PT_BOOL, 0, 1),
- DEFINE_PAR("LockedDrags", locked_drags, PT_BOOL, 0, 1),
- DEFINE_PAR("LockedDragTimeout", locked_drag_time, PT_INT, 0, 30000),
- DEFINE_PAR("RTCornerButton", tap_action[RT_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("RBCornerButton", tap_action[RB_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("LTCornerButton", tap_action[LT_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("LBCornerButton", tap_action[LB_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("TapButton1", tap_action[F1_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("TapButton2", tap_action[F2_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("TapButton3", tap_action[F3_TAP], PT_INT, 0, SYN_MAX_BUTTONS),
- DEFINE_PAR("CircularScrolling", circular_scrolling, PT_BOOL, 0, 1),
- DEFINE_PAR("CircScrollDelta", scroll_dist_circ, PT_DOUBLE, .01, 3),
- DEFINE_PAR("CircScrollTrigger", circular_trigger, PT_INT, 0, 8),
- DEFINE_PAR("CircularPad", circular_pad, PT_BOOL, 0, 1),
- DEFINE_PAR("PalmDetect", palm_detect, PT_BOOL, 0, 1),
- DEFINE_PAR("PalmMinWidth", palm_min_width, PT_INT, 0, 15),
- DEFINE_PAR("PalmMinZ", palm_min_z, PT_INT, 0, 255),
- DEFINE_PAR("CoastingSpeed", coasting_speed, PT_DOUBLE, 0, 20),
- DEFINE_PAR("PressureMotionMinZ", press_motion_min_z, PT_INT, 1, 255),
- DEFINE_PAR("PressureMotionMaxZ", press_motion_max_z, PT_INT, 1, 255),
- DEFINE_PAR("PressureMotionMinFactor", press_motion_min_factor, PT_DOUBLE, 0, 10.0),
- DEFINE_PAR("PressureMotionMaxFactor", press_motion_max_factor, PT_DOUBLE, 0, 10.0),
- DEFINE_PAR("GrabEventDevice", grab_event_device, PT_BOOL, 0, 1),
- { 0, 0, 0, 0, 0 }
-};
-
-static void
-show_hw_info(SynapticsSHM *synshm)
-{
- printf("Hardware properties:\n");
- if (synshm->synhw.model_id) {
- printf(" Model Id = %08x\n", synshm->synhw.model_id);
- printf(" Capabilities = %08x\n", synshm->synhw.capabilities);
- printf(" Identity = %08x\n", synshm->synhw.identity);
- } else {
- printf(" Can't detect hardware properties.\n");
- printf(" This is normal if you are running linux kernel 2.6.\n");
- printf(" Check the kernel log for touchpad hardware information.\n");
- }
- printf("Driver version: %d\n", (PACKAGE_VERSION_MAJOR*10000+PACKAGE_VERSION_MINOR*100+PACKAGE_VERSION_PATCHLEVEL));
-}
-
-static void
-show_settings(SynapticsSHM *synshm)
-{
- int i;
-
- printf("Parameter settings:\n");
- for (i = 0; params[i].name; i++) {
- struct Parameter* par = &params[i];
- switch (par->type) {
- case PT_INT:
- printf(" %-23s = %d\n", par->name, *(int*)((char*)synshm + par->offset));
- break;
- case PT_BOOL:
- printf(" %-23s = %d\n", par->name, *(Bool*)((char*)synshm + par->offset));
- break;
- case PT_DOUBLE:
- printf(" %-23s = %g\n", par->name, *(double*)((char*)synshm + par->offset));
- break;
- }
- }
-}
-
-static void
-set_variables(SynapticsSHM *synshm, int argc, char *argv[], int first_cmd)
-{
- int i;
- for (i = first_cmd; i < argc; i++) {
- char *cmd = argv[i];
- char *eqp = index(cmd, '=');
- if (eqp) {
- int j;
- int found = 0;
- *eqp = 0;
- for (j = 0; params[j].name; j++) {
- if (strcasecmp(cmd, params[j].name) == 0) {
- found = 1;
- break;
- }
- }
- if (found) {
- double val = atof(&eqp[1]);
- struct Parameter* par = &params[j];
-
- if (val < par->min_val)
- val = par->min_val;
- if (val > par->max_val)
- val = par->max_val;
-
- switch (par->type) {
- case PT_INT:
- *(int*)((char*)synshm + par->offset) = (int)rint(val);
- break;
- case PT_BOOL:
- *(Bool*)((char*)synshm + par->offset) = (Bool)rint(val);
- break;
- case PT_DOUBLE:
- *(double*)((char*)synshm + par->offset) = val;
- break;
- }
- } else {
- printf("Unknown parameter %s\n", cmd);
- }
- } else {
- printf("Invalid command: %s\n", cmd);
- }
- }
-}
-
-static int
-is_equal(SynapticsSHM *s1, SynapticsSHM *s2)
-{
- int i;
-
- if ((s1->x != s2->x) ||
- (s1->y != s2->y) ||
- (s1->z != s2->z) ||
- (s1->numFingers != s2->numFingers) ||
- (s1->fingerWidth != s2->fingerWidth) ||
- (s1->left != s2->left) ||
- (s1->right != s2->right) ||
- (s1->up != s2->up) ||
- (s1->down != s2->down) ||
- (s1->middle != s2->middle) ||
- (s1->guest_left != s2->guest_left) ||
- (s1->guest_mid != s2->guest_mid) ||
- (s1->guest_right != s2->guest_right) ||
- (s1->guest_dx != s2->guest_dx) ||
- (s1->guest_dy != s2->guest_dy))
- return 0;
-
- for (i = 0; i < 8; i++)
- if (s1->multi[i] != s2->multi[i])
- return 0;
-
- return 1;
-}
-
-static double
-get_time()
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec + tv.tv_usec / 1000000.0;
-}
-
-static void
-monitor(SynapticsSHM *synshm, int delay)
-{
- int header = 0;
- SynapticsSHM old;
- double t0 = get_time();
-
- memset(&old, 0, sizeof(SynapticsSHM));
- old.x = -1; /* Force first equality test to fail */
-
- while (1) {
- SynapticsSHM cur = *synshm;
- if (!is_equal(&old, &cur)) {
- if (!header) {
- printf("%8s %4s %4s %3s %s %2s %2s %s %s %s %s %8s "
- "%2s %2s %2s %3s %3s\n",
- "time", "x", "y", "z", "f", "w", "l", "r", "u", "d", "m",
- "multi", "gl", "gm", "gr", "gdx", "gdy");
- header = 20;
- }
- header--;
- printf("%8.3f %4d %4d %3d %d %2d %2d %d %d %d %d %d%d%d%d%d%d%d%d "
- "%2d %2d %2d %3d %3d\n",
- get_time() - t0,
- cur.x, cur.y, cur.z, cur.numFingers, cur.fingerWidth,
- cur.left, cur.right, cur.up, cur.down, cur.middle,
- cur.multi[0], cur.multi[1], cur.multi[2], cur.multi[3],
- cur.multi[4], cur.multi[5], cur.multi[6], cur.multi[7],
- cur.guest_left, cur.guest_mid, cur.guest_right,
- cur.guest_dx, cur.guest_dy);
- fflush(stdout);
- old = cur;
- }
- usleep(delay * 1000);
- }
-}
-
-static void
-usage()
-{
- fprintf(stderr, "Usage: synclient [-m interval] [-h] [-l] [-V] [-?] [var1=value1 [var2=value2] ...]\n");
- fprintf(stderr, " -m monitor changes to the touchpad state.\n"
- " interval specifies how often (in ms) to poll the touchpad state\n");
- fprintf(stderr, " -h Show detected hardware properties\n");
- fprintf(stderr, " -l List current user settings\n");
- fprintf(stderr, " -V Print synclient version string and exit\n");
- fprintf(stderr, " -? Show this help message\n");
- fprintf(stderr, " var=value Set user parameter 'var' to 'value'.\n");
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- SynapticsSHM *synshm;
- int shmid;
-
- int c;
- int delay = -1;
- int do_monitor = 0;
- int dump_hw = 0;
- int dump_settings = 0;
- int first_cmd;
-
- /* Parse command line parameters */
- while ((c = getopt(argc, argv, "m:hlV")) != -1) {
- switch (c) {
- case 'm':
- do_monitor = 1;
- if ((delay = atoi(optarg)) < 0)
- usage();
- break;
- case 'h':
- dump_hw = 1;
- break;
- case 'l':
- dump_settings = 1;
- break;
- case 'V':
- printf("%s\n", VERSION);
- exit(0);
- default:
- usage();
- }
- }
- first_cmd = optind;
- if (!do_monitor && !dump_hw && !dump_settings && first_cmd == argc)
- usage();
-
- /* Connect to the shared memory area */
- if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM), 0)) == -1) {
- if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) == -1) {
- fprintf(stderr, "Can't access shared memory area. SHMConfig disabled?\n");
- exit(1);
- } else {
- fprintf(stderr, "Incorrect size of shared memory area. Incompatible driver version?\n");
- exit(1);
- }
- }
- if ((synshm = (SynapticsSHM*) shmat(shmid, NULL, 0)) == NULL) {
- perror("shmat");
- exit(1);
- }
-
- /* Perform requested actions */
- if (dump_hw) {
- show_hw_info(synshm);
- }
- set_variables(synshm, argc, argv, first_cmd);
- if (dump_settings) {
- show_settings(synshm);
- }
- if (do_monitor) {
- monitor(synshm, delay);
- }
-
- exit(0);
-}
diff --git a/src/syndaemon.c b/src/syndaemon.c
deleted file mode 100644
index c72977a..0000000
--- a/src/syndaemon.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2003-2004 Peter Osterlund <petero2@telia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <X11/Xlib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-
-#include "synaptics.h"
-
-static SynapticsSHM *synshm;
-static int pad_disabled;
-static int disable_taps_only;
-static int ignore_modifier_combos;
-static int background;
-static const char *pid_file;
-
-#define KEYMAP_SIZE 32
-static unsigned char keyboard_mask[KEYMAP_SIZE];
-
-static void
-usage()
-{
- fprintf(stderr, "Usage: syndaemon [-i idle-time] [-d] [-t] [-k]\n");
- fprintf(stderr, " -i How many seconds to wait after the last key press before\n");
- fprintf(stderr, " enabling the touchpad. (default is 2.0s)\n");
- fprintf(stderr, " -d Start as a daemon, ie in the background.\n");
- fprintf(stderr, " -p Create a pid file with the specified name.\n");
- fprintf(stderr, " -t Only disable tapping and scrolling, not mouse movements.\n");
- fprintf(stderr, " -k Ignore modifier keys when monitoring keyboard activity.\n");
- fprintf(stderr, " -K Like -k but also ignore Modifier+Key combos.\n");
- exit(1);
-}
-
-static int
-enable_touchpad()
-{
- int ret = 0;
- if (pad_disabled) {
- synshm->touchpad_off = 0;
- pad_disabled = 0;
- ret = 1;
- }
- return ret;
-}
-
-static void
-signal_handler(int signum)
-{
- enable_touchpad();
- if (pid_file)
- unlink(pid_file);
- kill(getpid(), signum);
-}
-
-static void
-install_signal_handler()
-{
- static int signals[] = {
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
- SIGBUS, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
- SIGALRM, SIGTERM, SIGPWR
- };
- int i;
- struct sigaction act;
- sigset_t set;
-
- sigemptyset(&set);
- act.sa_handler = signal_handler;
- act.sa_mask = set;
- act.sa_flags = SA_ONESHOT;
-
- for (i = 0; i < sizeof(signals) / sizeof(int); i++) {
- if (sigaction(signals[i], &act, 0) == -1) {
- perror("sigaction");
- exit(2);
- }
- }
-}
-
-/**
- * Return non-zero if the keyboard state has changed since the last call.
- */
-static int
-keyboard_activity(Display *display)
-{
- static unsigned char old_key_state[KEYMAP_SIZE];
- unsigned char key_state[KEYMAP_SIZE];
- int i;
- int ret = 0;
-
- XQueryKeymap(display, (char*)key_state);
-
- for (i = 0; i < KEYMAP_SIZE; i++) {
- if ((key_state[i] & ~old_key_state[i]) & keyboard_mask[i]) {
- ret = 1;
- break;
- }
- }
- if (ignore_modifier_combos) {
- for (i = 0; i < KEYMAP_SIZE; i++) {
- if (key_state[i] & ~keyboard_mask[i]) {
- ret = 0;
- break;
- }
- }
- }
- for (i = 0; i < KEYMAP_SIZE; i++)
- old_key_state[i] = key_state[i];
- return ret;
-}
-
-/**
- * Return non-zero if any physical touchpad button is currently pressed.
- */
-static int
-touchpad_buttons_active()
-{
- int i;
-
- if (synshm->left || synshm->right || synshm->up || synshm->down)
- return 1;
- for (i = 0; i < 8; i++)
- if (synshm->multi[i])
- return 1;
- if (synshm->guest_left || synshm->guest_mid || synshm->guest_right)
- return 1;
- return 0;
-}
-
-static double
-get_time()
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec + tv.tv_usec / 1000000.0;
-}
-
-static void
-main_loop(Display *display, double idle_time)
-{
- const int poll_delay = 20000; /* 20 ms */
- double last_activity = 0.0;
- double current_time;
-
- pad_disabled = 0;
- keyboard_activity(display);
-
- for (;;) {
- current_time = get_time();
- if (keyboard_activity(display))
- last_activity = current_time;
- if (touchpad_buttons_active())
- last_activity = 0.0;
-
- if (current_time > last_activity + idle_time) { /* Enable touchpad */
- if (enable_touchpad()) {
- if (!background)
- printf("Enable\n");
- }
- } else { /* Disable touchpad */
- if (!pad_disabled && !synshm->touchpad_off) {
- if (!background)
- printf("Disable\n");
- pad_disabled = 1;
- if (disable_taps_only)
- synshm->touchpad_off = 2;
- else
- synshm->touchpad_off = 1;
- }
- }
-
- usleep(poll_delay);
- }
-}
-
-static void
-clear_bit(unsigned char *ptr, int bit)
-{
- int byte_num = bit / 8;
- int bit_num = bit % 8;
- ptr[byte_num] &= ~(1 << bit_num);
-}
-
-static void
-setup_keyboard_mask(Display *display, int ignore_modifier_keys)
-{
- XModifierKeymap *modifiers;
- int i;
-
- for (i = 0; i < KEYMAP_SIZE; i++)
- keyboard_mask[i] = 0xff;
-
- if (ignore_modifier_keys) {
- modifiers = XGetModifierMapping(display);
- for (i = 0; i < 8 * modifiers->max_keypermod; i++) {
- KeyCode kc = modifiers->modifiermap[i];
- if (kc != 0)
- clear_bit(keyboard_mask, kc);
- }
- XFreeModifiermap(modifiers);
- }
-}
-
-int
-main(int argc, char *argv[])
-{
- double idle_time = 2.0;
- Display *display;
- int c;
- int shmid;
- int ignore_modifier_keys = 0;
-
- /* Parse command line parameters */
- while ((c = getopt(argc, argv, "i:dtp:kK?")) != EOF) {
- switch(c) {
- case 'i':
- idle_time = atof(optarg);
- break;
- case 'd':
- background = 1;
- break;
- case 't':
- disable_taps_only = 1;
- break;
- case 'p':
- pid_file = optarg;
- break;
- case 'k':
- ignore_modifier_keys = 1;
- break;
- case 'K':
- ignore_modifier_combos = 1;
- ignore_modifier_keys = 1;
- break;
- default:
- usage();
- break;
- }
- }
- if (idle_time <= 0.0)
- usage();
-
- /* Open a connection to the X server */
- display = XOpenDisplay(NULL);
- if (!display) {
- fprintf(stderr, "Can't open display.\n");
- exit(2);
- }
-
- /* Connect to the shared memory area */
- if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM), 0)) == -1) {
- if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) == -1) {
- fprintf(stderr, "Can't access shared memory area. SHMConfig disabled?\n");
- exit(2);
- } else {
- fprintf(stderr, "Incorrect size of shared memory area. Incompatible driver version?\n");
- exit(2);
- }
- }
- if ((synshm = (SynapticsSHM*) shmat(shmid, NULL, 0)) == NULL) {
- perror("shmat");
- exit(2);
- }
-
- /* Install a signal handler to restore synaptics parameters on exit */
- install_signal_handler();
-
- if (background) {
- pid_t pid;
- if ((pid = fork()) < 0) {
- perror("fork");
- exit(3);
- } else if (pid != 0)
- exit(0);
-
- /* Child (daemon) is running here */
- setsid(); /* Become session leader */
- chdir("/"); /* In case the file system gets unmounted */
- umask(0); /* We don't want any surprises */
- if (pid_file) {
- FILE *fd = fopen(pid_file, "w");
- if (!fd) {
- perror("Can't create pid file");
- exit(2);
- }
- fprintf(fd, "%d\n", getpid());
- fclose(fd);
- }
- }
-
- setup_keyboard_mask(display, ignore_modifier_keys);
-
- /* Run the main loop */
- main_loop(display, idle_time);
-
- return 0;
-}
diff --git a/src/synproto.c b/src/synproto.c
new file mode 100644
index 0000000..143160c
--- /dev/null
+++ b/src/synproto.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright © 2012 Canonical, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "synproto.h"
+#include "synapticsstr.h"
+
+static int
+HwStateAllocTouch(struct SynapticsHwState *hw, SynapticsPrivate * priv)
+{
+ int num_vals;
+ int i = 0;
+
+ hw->num_mt_mask = priv->num_slots;
+ hw->mt_mask = malloc(hw->num_mt_mask * sizeof(ValuatorMask *));
+ if (!hw->mt_mask)
+ goto fail;
+
+ num_vals = 2; /* x and y */
+ num_vals += 2; /* scroll axes */
+ num_vals += priv->num_mt_axes;
+
+ for (; i < hw->num_mt_mask; i++) {
+ hw->mt_mask[i] = valuator_mask_new(num_vals);
+ if (!hw->mt_mask[i])
+ goto fail;
+ }
+
+ hw->slot_state = calloc(hw->num_mt_mask, sizeof(enum SynapticsSlotState));
+ if (!hw->slot_state)
+ goto fail;
+
+ return Success;
+
+ fail:
+ for (i--; i >= 0; i--)
+ valuator_mask_free(&hw->mt_mask[i]);
+ free(hw->mt_mask);
+ hw->mt_mask = NULL;
+ return BadAlloc;
+}
+
+struct SynapticsHwState *
+SynapticsHwStateAlloc(SynapticsPrivate * priv)
+{
+ struct SynapticsHwState *hw;
+
+ hw = calloc(1, sizeof(struct SynapticsHwState));
+ if (!hw)
+ return NULL;
+
+ if (HwStateAllocTouch(hw, priv) != Success) {
+ free(hw);
+ return NULL;
+ }
+
+ return hw;
+}
+
+void
+SynapticsHwStateFree(struct SynapticsHwState **hw)
+{
+ int i;
+
+ if (!*hw)
+ return;
+
+ free((*hw)->slot_state);
+ for (i = 0; i < (*hw)->num_mt_mask; i++)
+ valuator_mask_free(&(*hw)->mt_mask[i]);
+ free((*hw)->mt_mask);
+
+ free(*hw);
+ *hw = NULL;
+}
+
+void
+SynapticsCopyHwState(struct SynapticsHwState *dst,
+ const struct SynapticsHwState *src)
+{
+ int i;
+
+ dst->millis = src->millis;
+ dst->x = src->x;
+ dst->y = src->y;
+ dst->z = src->z;
+ dst->cumulative_dx = src->cumulative_dx;
+ dst->cumulative_dy = src->cumulative_dy;
+ dst->numFingers = src->numFingers;
+ dst->fingerWidth = src->fingerWidth;
+ dst->left = src->left & BTN_EMULATED_FLAG ? 0 : src->left;
+ dst->right = src->right & BTN_EMULATED_FLAG ? 0 : src->right;
+ dst->up = src->up;
+ dst->down = src->down;
+ memcpy(dst->multi, src->multi, sizeof(dst->multi));
+ dst->middle = src->middle & BTN_EMULATED_FLAG ? 0 : src->middle;
+ for (i = 0; i < dst->num_mt_mask && i < src->num_mt_mask; i++)
+ valuator_mask_copy(dst->mt_mask[i], src->mt_mask[i]);
+ memcpy(dst->slot_state, src->slot_state,
+ dst->num_mt_mask * sizeof(enum SynapticsSlotState));
+}
+
+void
+SynapticsResetHwState(struct SynapticsHwState *hw)
+{
+ hw->millis = 0;
+ hw->x = INT_MIN;
+ hw->y = INT_MIN;
+ hw->z = 0;
+ hw->cumulative_dx = 0;
+ hw->cumulative_dy = 0;
+ hw->numFingers = 0;
+ hw->fingerWidth = 0;
+
+ hw->left = 0;
+ hw->right = 0;
+ hw->up = 0;
+ hw->down = 0;
+
+ hw->middle = 0;
+ memset(hw->multi, 0, sizeof(hw->multi));
+
+ SynapticsResetTouchHwState(hw, TRUE);
+}
+
+void
+SynapticsResetTouchHwState(struct SynapticsHwState *hw, Bool set_slot_empty)
+{
+ int i;
+
+ for (i = 0; i < hw->num_mt_mask; i++) {
+ int j;
+
+ /* Leave x and y valuators in case we need to restart touch */
+ for (j = 2; j < valuator_mask_num_valuators(hw->mt_mask[i]); j++)
+ valuator_mask_unset(hw->mt_mask[i], j);
+
+ switch (hw->slot_state[i]) {
+ case SLOTSTATE_OPEN:
+ case SLOTSTATE_OPEN_EMPTY:
+ case SLOTSTATE_UPDATE:
+ hw->slot_state[i] =
+ set_slot_empty ? SLOTSTATE_EMPTY : SLOTSTATE_OPEN_EMPTY;
+ break;
+
+ default:
+ hw->slot_state[i] = SLOTSTATE_EMPTY;
+ break;
+ }
+ }
+}
diff --git a/src/synproto.h b/src/synproto.h
index ebb44f3..6ba6740 100644
--- a/src/synproto.h
+++ b/src/synproto.h
@@ -1,37 +1,71 @@
/*
- * Copyright 2004 Peter Osterlund <petero2@telia.com>
+ * Copyright © 2004 Peter Osterlund
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * 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.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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 Osterlund (petero2@telia.com)
*/
+
#ifndef _SYNPROTO_H_
#define _SYNPROTO_H_
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+
#include <unistd.h>
#include <sys/ioctl.h>
#include <xf86Xinput.h>
#include <xisb.h>
+#ifndef XI86_SERVER_FD
+#define XI86_SERVER_FD 0x20
+#endif
+
+struct _SynapticsPrivateRec;
+typedef struct _SynapticsPrivateRec SynapticsPrivate;
+
+enum SynapticsSlotState {
+ SLOTSTATE_EMPTY = 0, /* no slot in this cycle */
+ SLOTSTATE_OPEN, /* tracking ID received */
+ SLOTSTATE_CLOSE, /* tracking ID -1 received */
+ SLOTSTATE_OPEN_EMPTY, /* previously had tracking id, no events in this read cycle */
+ SLOTSTATE_UPDATE, /* had tracking id, other events in this cycle */
+};
+
+/* used to mark emulated hw button state */
+#define BTN_EMULATED_FLAG 0x80
+
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
struct SynapticsHwState {
- int millis; /* Timestamp in milliseconds */
- int x; /* X position of finger */
- int y; /* Y position of finger */
- int z; /* Finger pressure */
+ CARD32 millis; /* Timestamp in milliseconds */
+ int x; /* X position of finger */
+ int y; /* Y position of finger */
+ int z; /* Finger pressure */
+ int cumulative_dx; /* Cumulative delta X for clickpad dragging */
+ int cumulative_dy; /* Cumulative delta Y for clickpad dragging */
int numFingers;
int fingerWidth;
@@ -41,55 +75,61 @@ struct SynapticsHwState {
Bool down;
Bool multi[8];
- Bool middle; /* Some ALPS touchpads have a middle button */
+ Bool middle; /* Some ALPS touchpads have a middle button */
- Bool guest_left; /* guest device */
- Bool guest_mid;
- Bool guest_right;
- int guest_dx;
- int guest_dy;
+ int num_mt_mask;
+ ValuatorMask **mt_mask;
+ enum SynapticsSlotState *slot_state;
};
struct CommData {
XISBuffer *buffer;
- unsigned char protoBuf[6]; /* Buffer for Packet */
- unsigned char lastByte; /* Last read byte. Use for reset sequence detection. */
- int outOfSync; /* How many consecutive incorrect packets we
- have received */
+ unsigned char protoBuf[6]; /* Buffer for Packet */
+ unsigned char lastByte; /* Last read byte. Use for reset sequence detection. */
+ int outOfSync; /* How many consecutive incorrect packets we
+ have received */
int protoBufTail;
/* Used for keeping track of partial HwState updates. */
- struct SynapticsHwState hwState;
+ struct SynapticsHwState *hwState;
Bool oneFinger;
Bool twoFingers;
Bool threeFingers;
};
-enum SynapticsProtocol {
- SYN_PROTO_PSAUX, /* Raw psaux device */
- SYN_PROTO_EVENT, /* Linux kernel event interface */
- SYN_PROTO_PSM, /* FreeBSD psm driver */
- SYN_PROTO_ALPS /* ALPS touchpad protocol */
-};
-
-struct _SynapticsSHM;
-struct SynapticsHwInfo;
-struct CommData;
+struct _SynapticsParameters;
struct SynapticsProtocolOperations {
- void (*DeviceOnHook)(LocalDevicePtr local, struct _SynapticsSHM *para);
- void (*DeviceOffHook)(LocalDevicePtr local);
- Bool (*QueryHardware)(LocalDevicePtr local, struct SynapticsHwInfo *synhw);
- Bool (*ReadHwState)(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
- struct SynapticsProtocolOperations *proto_ops,
- struct CommData *comm, struct SynapticsHwState *hwRet);
- Bool (*AutoDevProbe)(LocalDevicePtr local);
+ Bool (*DeviceOnHook) (InputInfoPtr pInfo,
+ struct _SynapticsParameters * para);
+ Bool (*DeviceOffHook) (InputInfoPtr pInfo);
+ Bool (*QueryHardware) (InputInfoPtr pInfo);
+ Bool (*ReadHwState) (InputInfoPtr pInfo,
+ struct CommData * comm,
+ struct SynapticsHwState * hwRet);
+ Bool (*AutoDevProbe) (InputInfoPtr pInfo, const char *device);
+ void (*ReadDevDimensions) (InputInfoPtr pInfo);
};
+#ifdef BUILD_PS2COMM
extern struct SynapticsProtocolOperations psaux_proto_operations;
+extern struct SynapticsProtocolOperations alps_proto_operations;
+#endif /* BUILD_PS2COMM */
+#ifdef BUILD_EVENTCOMM
extern struct SynapticsProtocolOperations event_proto_operations;
+#endif /* BUILD_EVENTCOMM */
+#ifdef BUILD_PSMCOMM
extern struct SynapticsProtocolOperations psm_proto_operations;
-extern struct SynapticsProtocolOperations alps_proto_operations;
+#endif /* BUILD_PSMCOMM */
+
+extern struct SynapticsHwState *SynapticsHwStateAlloc(SynapticsPrivate * priv);
+extern void SynapticsHwStateFree(struct SynapticsHwState **hw);
+extern void SynapticsCopyHwState(struct SynapticsHwState *dst,
+ const struct SynapticsHwState *src);
+extern void SynapticsResetHwState(struct SynapticsHwState *hw);
+extern void SynapticsResetTouchHwState(struct SynapticsHwState *hw,
+ Bool set_slot_empty);
+extern Bool SynapticsIsSoftButtonAreasValid(int *values);
-#endif /* _SYNPROTO_H_ */
+#endif /* _SYNPROTO_H_ */
diff --git a/test/test-pad.c b/test/test-pad.c
deleted file mode 100644
index f4c27e9..0000000
--- a/test/test-pad.c
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-int
-getbyte(int fd, unsigned char *b)
-{
- return(read(fd, b, 1) == 1);
-}
-
-int
-putbyte(int fd, unsigned char b)
-{
- unsigned char ack;
-
- printf("write %02X\n", b);
- if (write(fd, &b, 1) != 1) {
- fprintf(stderr, "error write: %s\n", strerror(errno));
- return 0;
- }
-
- if (!getbyte(fd, &ack)) {
- fprintf(stderr, "error read: %s\n", strerror(errno));
- return 0;
- }
- printf("read %02X\n", ack);
-
- if (ack != 0xFA) {
- fprintf(stderr, "error ack\n");
- return 0;
- }
-
- return 1;
-}
-
-int
-special_cmd(int fd, unsigned char cmd)
-{
- int i;
-
- if (putbyte(fd, 0xE6))
- for (i = 0; i < 4; i++) {
- printf("special_cmd %i\n", i);
- if ((!putbyte(fd, 0xE8)) || (!putbyte(fd, (cmd>>6)&0x3)))
- return 0;
- cmd<<=2;
- }
- else
- return 0;
- return 1;
-}
-
-int
-send_cmd(int fd, unsigned char cmd)
-{
- return (special_cmd(fd, cmd) &&
- putbyte(fd, 0xE9));
-}
-
-int
-identify(int fd, unsigned long int *ident)
-{
- unsigned char id[3];
-
- if (send_cmd(fd, 0x00) &&
- getbyte(fd, &id[0]) &&
- getbyte(fd, &id[1]) &&
- getbyte(fd, &id[2])) {
- *ident = (id[0]<<16)|(id[1]<<8)|id[2];
- printf("ident %06X\n", *ident);
- return 1;
- } else {
- fprintf(stderr, "error identify\n");
- return 0;
- }
-}
-
-int
-reset(int fd)
-{
- unsigned char r[2];
-
- if (!putbyte(fd, 0xFF)) {
- fprintf(stderr, "error reset\n");
- return 0;
- }
-
- sleep(5);
-
- if (getbyte(fd, &r[0]) && getbyte(fd, &r[1]))
- if (r[0] == 0xAA && r[1] == 0x00) {
- fprintf(stderr, "reset done\n");
- return 1;
- }
- fprintf(stderr, "error reset ack\n");
- return 0;
-}
-
-int
-main(int argc, char* argv[])
-{
- int fd;
- unsigned long int ident;
-
- fd = open("/dev/psaux", O_RDWR);
- if (fd == -1) {
- fprintf(stderr, "error open: %s\n", strerror(errno));
- exit(0);
- }
-
- reset(fd);
- identify(fd, &ident);
-
- close(fd);
-
- exit(0);
-}
diff --git a/test/testprotocol.c b/test/testprotocol.c
deleted file mode 100644
index 178dc96..0000000
--- a/test/testprotocol.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-
-static int outputformat = 0;
-
-void
-SynapticsReadPacket(int fd)
-{
- int count = 0;
- int inSync = 0;
- unsigned char pBuf[7], u;
-
- while (read(fd,&u, 1) == 1) {
- pBuf[count++] = u;
-
- /* check first byte */
- if ((count == 1) && ((u & 0xC8) != 0x80)) {
- inSync = 0;
- count = 0;
- printf("Synaptics driver lost sync at 1st byte\n");
- continue;
- }
-
- /* check 4th byte */
- if ((count == 4) && ((u & 0xc8) != 0xc0)) {
- inSync = 0;
- count = 0;
- printf("Synaptics driver lost sync at 4th byte\n");
- continue;
- }
-
- if (count >= 6) { /* Full packet received */
- if (!inSync) {
- inSync = 1;
- printf("Synaptics driver resynced.\n");
- }
- count = 0;
- switch (outputformat) {
- case 1:
- printf("Paket:%02X-%02X-%02X-%02X-%02X-%02X\n",
- pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5]);
- break;
- case 2:
- printf("x = %i, y = %i, z = %i, w = %i, l = %i, r = %i\n",
- ((pBuf[3] & 0x10) << 8) | ((pBuf[1] & 0x0f) << 8) | pBuf[4],
- ((pBuf[3] & 0x20) << 7) | ((pBuf[1] & 0xf0) << 4) | pBuf[5],
- ((pBuf[0] & 0x30) >> 2) | ((pBuf[0] & 0x04) >> 1) | ((pBuf[3] & 0x04) >> 2),
- ((pBuf[0] & 0x30) >> 2) | ((pBuf[0] & 0x04) >> 1) | ((pBuf[3] & 0x04) >> 2),
- (pBuf[0] & 0x01) ? 1 : 0,
- (pBuf[0] & 0x2) ? 1 : 0);
- break;
- default:
- break;
- }
- }
- }
-}
-
-int
-main(int argc, char* argv[])
-{
- int fd;
-
- if (argc > 1)
- outputformat = atoi(argv[1]);
-
-
- fd = open("/dev/psaux", O_RDONLY);
- if (fd == -1) {
- printf("Error opening /dev/psaux\n");
- exit(1);
- }
-
- SynapticsReadPacket(fd);
-
- close(fd);
-
- exit(0);
-}
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 0000000..f3b80fc
--- /dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,3 @@
+# Add & Override for this directory and it's subdirectories
+synclient
+syndaemon
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..99316c2
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,31 @@
+# Copyright 2008 Red Hat, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# 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.
+
+bin_PROGRAMS = synclient syndaemon
+
+AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CFLAGS = $(CWARNFLAGS) $(XI_CFLAGS)
+AM_LDFLAGS = $(XI_LIBS)
+
+synclient_SOURCES = synclient.c
+
+syndaemon_SOURCES = syndaemon.c
+syndaemon_CFLAGS = $(AM_CFLAGS) $(XTST_CFLAGS)
+syndaemon_LDFLAGS = $(AM_LDFLAGS) $(XTST_LIBS)
diff --git a/tools/synclient.c b/tools/synclient.c
new file mode 100644
index 0000000..3bb9618
--- /dev/null
+++ b/tools/synclient.c
@@ -0,0 +1,523 @@
+/*
+ * Copyright © 2002-2005,2007 Peter Osterlund
+ *
+ * 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 Osterlund (petero2@telia.com)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include <math.h>
+#include <limits.h>
+
+#include <X11/Xdefs.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XInput.h>
+#include "synaptics-properties.h"
+
+#ifndef XATOM_FLOAT
+#define XATOM_FLOAT "FLOAT"
+#endif
+
+#define SYN_MAX_BUTTONS 12
+#define SBR_MIN 10
+#define SBR_MAX 1000
+
+union flong { /* Xlibs 64-bit property handling madness */
+ long l;
+ float f;
+};
+
+enum ParaType {
+ PT_INT,
+ PT_BOOL,
+ PT_DOUBLE
+};
+
+struct Parameter {
+ const char *name; /* Name of parameter */
+ enum ParaType type; /* Type of parameter */
+ double min_val; /* Minimum allowed value */
+ double max_val; /* Maximum allowed value */
+ const char *prop_name; /* Property name */
+ int prop_format; /* Property format (0 for floats) */
+ int prop_offset; /* Offset inside property */
+};
+
+static struct Parameter params[] = {
+ {"LeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 0},
+ {"RightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 1},
+ {"TopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 2},
+ {"BottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 3},
+ {"FingerLow", PT_INT, 0, 255, SYNAPTICS_PROP_FINGER, 32, 0},
+ {"FingerHigh", PT_INT, 0, 255, SYNAPTICS_PROP_FINGER, 32, 1},
+ {"MaxTapTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_TIME, 32, 0},
+ {"MaxTapMove", PT_INT, 0, 2000, SYNAPTICS_PROP_TAP_MOVE, 32, 0},
+ {"MaxDoubleTapTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 1},
+ {"SingleTapTimeout", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 0},
+ {"ClickTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 2},
+ {"EmulateMidButtonTime", PT_INT, 0, 1000, SYNAPTICS_PROP_MIDDLE_TIMEOUT,32, 0},
+ {"EmulateTwoFingerMinZ", PT_INT, 0, 1000, SYNAPTICS_PROP_TWOFINGER_PRESSURE, 32, 0},
+ {"EmulateTwoFingerMinW", PT_INT, 0, 15, SYNAPTICS_PROP_TWOFINGER_WIDTH, 32, 0},
+ {"VertScrollDelta", PT_INT, -1000, 1000, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 0},
+ {"HorizScrollDelta", PT_INT, -1000, 1000, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 1},
+ {"VertEdgeScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 0},
+ {"HorizEdgeScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 1},
+ {"CornerCoasting", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 2},
+ {"VertTwoFingerScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 0},
+ {"HorizTwoFingerScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 1},
+ {"MinSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 0},
+ {"MaxSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 1},
+ {"AccelFactor", PT_DOUBLE, 0, 1.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 2},
+ {"UpDownScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 0},
+ {"LeftRightScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING, 8, 1},
+ {"UpDownScrollRepeat", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT, 8, 0},
+ {"LeftRightScrollRepeat", PT_BOOL, 0, 1, SYNAPTICS_PROP_BUTTONSCROLLING_REPEAT, 8, 1},
+ {"ScrollButtonRepeat", PT_INT, SBR_MIN , SBR_MAX, SYNAPTICS_PROP_BUTTONSCROLLING_TIME, 32, 0},
+ {"TouchpadOff", PT_INT, 0, 2, SYNAPTICS_PROP_OFF, 8, 0},
+ {"LockedDrags", PT_BOOL, 0, 1, SYNAPTICS_PROP_LOCKED_DRAGS, 8, 0},
+ {"LockedDragTimeout", PT_INT, 0, 30000, SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT, 32, 0},
+ {"RTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 0},
+ {"RBCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 1},
+ {"LTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 2},
+ {"LBCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 3},
+ {"TapButton1", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 4},
+ {"TapButton2", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 5},
+ {"TapButton3", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 6},
+ {"ClickFinger1", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 0},
+ {"ClickFinger2", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 1},
+ {"ClickFinger3", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 2},
+ {"CircularScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_CIRCULAR_SCROLLING, 8, 0},
+ {"CircScrollDelta", PT_DOUBLE, .01, 3, SYNAPTICS_PROP_CIRCULAR_SCROLLING_DIST, 0 /* float */, 0},
+ {"CircScrollTrigger", PT_INT, 0, 8, SYNAPTICS_PROP_CIRCULAR_SCROLLING_TRIGGER, 8, 0},
+ {"CircularPad", PT_BOOL, 0, 1, SYNAPTICS_PROP_CIRCULAR_PAD, 8, 0},
+ {"PalmDetect", PT_BOOL, 0, 1, SYNAPTICS_PROP_PALM_DETECT, 8, 0},
+ {"PalmMinWidth", PT_INT, 0, 15, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 0},
+ {"PalmMinZ", PT_INT, 0, 255, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 1},
+ {"CoastingSpeed", PT_DOUBLE, 0, 255, SYNAPTICS_PROP_COASTING_SPEED, 0 /* float*/, 0},
+ {"CoastingFriction", PT_DOUBLE, 0, 255, SYNAPTICS_PROP_COASTING_SPEED, 0 /* float*/, 1},
+ {"PressureMotionMinZ", PT_INT, 1, 255, SYNAPTICS_PROP_PRESSURE_MOTION, 32, 0},
+ {"PressureMotionMaxZ", PT_INT, 1, 255, SYNAPTICS_PROP_PRESSURE_MOTION, 32, 1},
+ {"PressureMotionMinFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 0},
+ {"PressureMotionMaxFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 1},
+ {"GrabEventDevice", PT_BOOL, 0, 1, SYNAPTICS_PROP_GRAB, 8, 0},
+ {"TapAndDragGesture", PT_BOOL, 0, 1, SYNAPTICS_PROP_GESTURES, 8, 0},
+ {"AreaLeftEdge", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_AREA, 32, 0},
+ {"AreaRightEdge", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_AREA, 32, 1},
+ {"AreaTopEdge", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_AREA, 32, 2},
+ {"AreaBottomEdge", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_AREA, 32, 3},
+ {"HorizHysteresis", PT_INT, 0, 10000, SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 0},
+ {"VertHysteresis", PT_INT, 0, 10000, SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 1},
+ {"ClickPad", PT_BOOL, 0, 1, SYNAPTICS_PROP_CLICKPAD, 8, 0},
+ {"RightButtonAreaLeft", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 0},
+ {"RightButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 1},
+ {"RightButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 2},
+ {"RightButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 3},
+ {"MiddleButtonAreaLeft", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 4},
+ {"MiddleButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 5},
+ {"MiddleButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 6},
+ {"MiddleButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 7},
+ { NULL, 0, 0, 0, 0 }
+};
+
+static double
+parse_cmd(char *cmd, struct Parameter **par)
+{
+ char *eqp = strchr(cmd, '=');
+
+ *par = NULL;
+
+ if (eqp) {
+ int j;
+ int found = 0;
+
+ *eqp = 0;
+ for (j = 0; params[j].name; j++) {
+ if (strcasecmp(cmd, params[j].name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ double val = atof(&eqp[1]);
+
+ *par = &params[j];
+
+ if (val < (*par)->min_val)
+ val = (*par)->min_val;
+ if (val > (*par)->max_val)
+ val = (*par)->max_val;
+
+ return val;
+ }
+ else {
+ printf("Unknown parameter %s\n", cmd);
+ }
+ }
+ else {
+ printf("Invalid command: %s\n", cmd);
+ }
+
+ return 0;
+}
+
+/** Init display connection or NULL on error */
+static Display *
+dp_init(void)
+{
+ Display *dpy = NULL;
+ XExtensionVersion *v = NULL;
+ Atom touchpad_type = 0;
+ Atom synaptics_property = 0;
+ int error = 0;
+
+ dpy = XOpenDisplay(NULL);
+ if (!dpy) {
+ fprintf(stderr, "Failed to connect to X Server.\n");
+ error = 1;
+ goto unwind;
+ }
+
+ v = XGetExtensionVersion(dpy, INAME);
+ if (!v->present ||
+ (v->major_version * 1000 + v->minor_version) <
+ (XI_Add_DeviceProperties_Major * 1000 +
+ XI_Add_DeviceProperties_Minor)) {
+ fprintf(stderr, "X server supports X Input %d.%d. I need %d.%d.\n",
+ v->major_version, v->minor_version,
+ XI_Add_DeviceProperties_Major, XI_Add_DeviceProperties_Minor);
+ error = 1;
+ goto unwind;
+ }
+
+ /* We know synaptics sets XI_TOUCHPAD for all the devices. */
+ touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True);
+ if (!touchpad_type) {
+ fprintf(stderr, "XI_TOUCHPAD not initialised.\n");
+ error = 1;
+ goto unwind;
+ }
+
+ synaptics_property = XInternAtom(dpy, SYNAPTICS_PROP_EDGES, True);
+ if (!synaptics_property) {
+ fprintf(stderr, "Couldn't find synaptics properties. No synaptics "
+ "driver loaded?\n");
+ error = 1;
+ goto unwind;
+ }
+
+ unwind:
+ XFree(v);
+ if (error && dpy) {
+ XCloseDisplay(dpy);
+ dpy = NULL;
+ }
+ return dpy;
+}
+
+static XDevice *
+dp_get_device(Display * dpy)
+{
+ XDevice *dev = NULL;
+ XDeviceInfo *info = NULL;
+ int ndevices = 0;
+ Atom touchpad_type = 0;
+ Atom synaptics_property = 0;
+ Atom *properties = NULL;
+ int nprops = 0;
+ int error = 0;
+
+ touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True);
+ synaptics_property = XInternAtom(dpy, SYNAPTICS_PROP_EDGES, True);
+ info = XListInputDevices(dpy, &ndevices);
+
+ while (ndevices--) {
+ if (info[ndevices].type == touchpad_type) {
+ dev = XOpenDevice(dpy, info[ndevices].id);
+ if (!dev) {
+ fprintf(stderr, "Failed to open device '%s'.\n",
+ info[ndevices].name);
+ error = 1;
+ goto unwind;
+ }
+
+ properties = XListDeviceProperties(dpy, dev, &nprops);
+ if (!properties || !nprops) {
+ fprintf(stderr, "No properties on device '%s'.\n",
+ info[ndevices].name);
+ error = 1;
+ goto unwind;
+ }
+
+ while (nprops--) {
+ if (properties[nprops] == synaptics_property)
+ break;
+ }
+ if (!nprops) {
+ fprintf(stderr, "No synaptics properties on device '%s'.\n",
+ info[ndevices].name);
+ error = 1;
+ goto unwind;
+ }
+
+ break; /* Yay, device is suitable */
+ }
+ }
+
+ unwind:
+ XFree(properties);
+ XFreeDeviceList(info);
+ if (!dev)
+ fprintf(stderr, "Unable to find a synaptics device.\n");
+ else if (error && dev) {
+ XCloseDevice(dpy, dev);
+ dev = NULL;
+ }
+ return dev;
+}
+
+static void
+dp_set_variables(Display * dpy, XDevice * dev, int argc, char *argv[],
+ int first_cmd)
+{
+ int i;
+ double val;
+ struct Parameter *par;
+ Atom prop, type, float_type;
+ int format;
+ unsigned char *data;
+ unsigned long nitems, bytes_after;
+
+ union flong *f;
+ long *n;
+ char *b;
+
+ float_type = XInternAtom(dpy, XATOM_FLOAT, True);
+ if (!float_type)
+ fprintf(stderr, "Float properties not available.\n");
+
+ for (i = first_cmd; i < argc; i++) {
+ val = parse_cmd(argv[i], &par);
+ if (!par)
+ continue;
+
+ prop = XInternAtom(dpy, par->prop_name, True);
+ if (!prop) {
+ fprintf(stderr, "Property for '%s' not available. Skipping.\n",
+ par->name);
+ continue;
+
+ }
+
+ XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, AnyPropertyType,
+ &type, &format, &nitems, &bytes_after, &data);
+
+ if (type == None) {
+ fprintf(stderr, "Property for '%s' not available. Skipping.\n",
+ par->name);
+ continue;
+ }
+
+ switch (par->prop_format) {
+ case 8:
+ if (format != par->prop_format || type != XA_INTEGER) {
+ fprintf(stderr, " %-23s = format mismatch (%d)\n",
+ par->name, format);
+ break;
+ }
+ b = (char *) data;
+ b[par->prop_offset] = rint(val);
+ break;
+ case 32:
+ if (format != par->prop_format ||
+ (type != XA_INTEGER && type != XA_CARDINAL)) {
+ fprintf(stderr, " %-23s = format mismatch (%d)\n",
+ par->name, format);
+ break;
+ }
+ n = (long *) data;
+ n[par->prop_offset] = rint(val);
+ break;
+ case 0: /* float */
+ if (!float_type)
+ continue;
+ if (format != 32 || type != float_type) {
+ fprintf(stderr, " %-23s = format mismatch (%d)\n",
+ par->name, format);
+ break;
+ }
+ f = (union flong *) data;
+ f[par->prop_offset].f = val;
+ break;
+ }
+
+ XChangeDeviceProperty(dpy, dev, prop, type, format,
+ PropModeReplace, data, nitems);
+ XFlush(dpy);
+ }
+}
+
+/* FIXME: horribly inefficient. */
+static void
+dp_show_settings(Display * dpy, XDevice * dev)
+{
+ int j;
+ Atom a, type, float_type;
+ int format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ int len;
+
+ union flong *f;
+ long *i;
+ char *b;
+
+ float_type = XInternAtom(dpy, XATOM_FLOAT, True);
+ if (!float_type)
+ fprintf(stderr, "Float properties not available.\n");
+
+ printf("Parameter settings:\n");
+ for (j = 0; params[j].name; j++) {
+ struct Parameter *par = &params[j];
+
+ a = XInternAtom(dpy, par->prop_name, True);
+ if (!a)
+ continue;
+
+ len =
+ 1 +
+ ((par->prop_offset * (par->prop_format ? par->prop_format : 32) /
+ 8)) / 4;
+
+ XGetDeviceProperty(dpy, dev, a, 0, len, False,
+ AnyPropertyType, &type, &format,
+ &nitems, &bytes_after, &data);
+ if (type == None)
+ continue;
+
+ switch (par->prop_format) {
+ case 8:
+ if (format != par->prop_format || type != XA_INTEGER) {
+ fprintf(stderr, " %-23s = format mismatch (%d)\n",
+ par->name, format);
+ break;
+ }
+
+ b = (char *) data;
+ printf(" %-23s = %d\n", par->name, b[par->prop_offset]);
+ break;
+ case 32:
+ if (format != par->prop_format ||
+ (type != XA_INTEGER && type != XA_CARDINAL)) {
+ fprintf(stderr, " %-23s = format mismatch (%d)\n",
+ par->name, format);
+ break;
+ }
+
+ i = (long *) data;
+ printf(" %-23s = %ld\n", par->name, i[par->prop_offset]);
+ break;
+ case 0: /* Float */
+ if (!float_type)
+ continue;
+ if (format != 32 || type != float_type) {
+ fprintf(stderr, " %-23s = format mismatch (%d)\n",
+ par->name, format);
+ break;
+ }
+
+ f = (union flong *) data;
+ printf(" %-23s = %g\n", par->name, f[par->prop_offset].f);
+ break;
+ }
+
+ XFree(data);
+ }
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: synclient [-h] [-l] [-V] [-?] [var1=value1 [var2=value2] ...]\n");
+ fprintf(stderr, " -l List current user settings\n");
+ fprintf(stderr, " -V Print synclient version string and exit\n");
+ fprintf(stderr, " -? Show this help message\n");
+ fprintf(stderr, " var=value Set user parameter 'var' to 'value'.\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ int dump_settings = 0;
+ int first_cmd;
+
+ Display *dpy;
+ XDevice *dev;
+
+ if (argc == 1)
+ dump_settings = 1;
+
+ /* Parse command line parameters */
+ while ((c = getopt(argc, argv, "lV?")) != -1) {
+ switch (c) {
+ case 'l':
+ dump_settings = 1;
+ break;
+ case 'V':
+ printf("%s\n", VERSION);
+ exit(0);
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ first_cmd = optind;
+ if (!dump_settings && first_cmd == argc)
+ usage();
+
+ dpy = dp_init();
+ if (!dpy || !(dev = dp_get_device(dpy)))
+ return 1;
+
+ dp_set_variables(dpy, dev, argc, argv, first_cmd);
+ if (dump_settings)
+ dp_show_settings(dpy, dev);
+
+ XCloseDevice(dpy, dev);
+ XCloseDisplay(dpy);
+
+ return 0;
+}
diff --git a/tools/syndaemon.c b/tools/syndaemon.c
new file mode 100644
index 0000000..9c86a5c
--- /dev/null
+++ b/tools/syndaemon.c
@@ -0,0 +1,676 @@
+/*
+ * Copyright © 2003-2004 Peter Osterlund
+ *
+ * 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 Osterlund (petero2@telia.com)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XInput.h>
+#ifdef HAVE_X11_EXTENSIONS_RECORD_H
+#include <X11/Xproto.h>
+#include <X11/extensions/record.h>
+#endif /* HAVE_X11_EXTENSIONS_RECORD_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include "synaptics-properties.h"
+
+enum KeyboardActivity {
+ ActivityNew,
+ ActivityNone,
+ ActivityReset
+};
+
+enum TouchpadState {
+ TouchpadOn = 0,
+ TouchpadOff = 1,
+ TappingOff = 2
+};
+
+static Bool pad_disabled
+ /* internal flag, this does not correspond to device state */ ;
+static int ignore_modifier_combos;
+static int ignore_modifier_keys;
+static int background;
+static const char *pid_file;
+static Display *display;
+static XDevice *dev;
+static Atom touchpad_off_prop;
+static enum TouchpadState previous_state;
+static enum TouchpadState disable_state = TouchpadOff;
+static int verbose;
+
+#define KEYMAP_SIZE 32
+static unsigned char keyboard_mask[KEYMAP_SIZE];
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage: syndaemon [-i idle-time] [-m poll-delay] [-d] [-t] [-k]\n");
+ fprintf(stderr,
+ " -i How many seconds to wait after the last key press before\n");
+ fprintf(stderr, " enabling the touchpad. (default is 2.0s)\n");
+ fprintf(stderr, " -m How many milli-seconds to wait until next poll.\n");
+ fprintf(stderr, " (default is 200ms)\n");
+ fprintf(stderr, " -d Start as a daemon, i.e. in the background.\n");
+ fprintf(stderr, " -p Create a pid file with the specified name.\n");
+ fprintf(stderr,
+ " -t Only disable tapping and scrolling, not mouse movements.\n");
+ fprintf(stderr,
+ " -k Ignore modifier keys when monitoring keyboard activity.\n");
+ fprintf(stderr, " -K Like -k but also ignore Modifier+Key combos.\n");
+ fprintf(stderr, " -R Use the XRecord extension.\n");
+ fprintf(stderr, " -v Print diagnostic messages.\n");
+ fprintf(stderr, " -? Show this help message.\n");
+ exit(1);
+}
+
+static void
+store_current_touchpad_state(void)
+{
+ Atom real_type;
+ int real_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+
+ if ((XGetDeviceProperty(display, dev, touchpad_off_prop, 0, 1, False,
+ XA_INTEGER, &real_type, &real_format, &nitems,
+ &bytes_after, &data) == Success) &&
+ (real_type != None)) {
+ previous_state = data[0];
+ }
+}
+
+/**
+ * Toggle touchpad enabled/disabled state, decided by value.
+ */
+static void
+toggle_touchpad(Bool enable)
+{
+ unsigned char data;
+
+ if (pad_disabled && enable) {
+ data = previous_state;
+ pad_disabled = False;
+ if (verbose)
+ printf("Enable\n");
+ }
+ else if (!pad_disabled && !enable &&
+ previous_state != disable_state && previous_state != TouchpadOff) {
+ store_current_touchpad_state();
+ pad_disabled = True;
+ data = disable_state;
+ if (verbose)
+ printf("Disable\n");
+ }
+ else
+ return;
+
+ /* This potentially overwrites a different client's setting, but ... */
+ XChangeDeviceProperty(display, dev, touchpad_off_prop, XA_INTEGER, 8,
+ PropModeReplace, &data, 1);
+ XFlush(display);
+}
+
+static void
+signal_handler(int signum)
+{
+ toggle_touchpad(True);
+
+ if (pid_file)
+ unlink(pid_file);
+ kill(getpid(), signum);
+}
+
+static void
+install_signal_handler(void)
+{
+ static int signals[] = {
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
+ SIGBUS, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
+ SIGALRM, SIGTERM,
+#ifdef SIGPWR
+ SIGPWR
+#endif
+ };
+ int i;
+ struct sigaction act;
+ sigset_t set;
+
+ sigemptyset(&set);
+ act.sa_handler = signal_handler;
+ act.sa_mask = set;
+#ifdef SA_RESETHAND
+ act.sa_flags = SA_RESETHAND;
+#else
+ act.sa_flags = 0;
+#endif
+
+ for (i = 0; i < sizeof(signals) / sizeof(int); i++) {
+ if (sigaction(signals[i], &act, NULL) == -1) {
+ perror("sigaction");
+ exit(2);
+ }
+ }
+}
+
+static enum KeyboardActivity
+keyboard_activity(Display * display)
+{
+ static unsigned char old_key_state[KEYMAP_SIZE];
+ unsigned char key_state[KEYMAP_SIZE];
+ int i;
+ int ret = ActivityNone;
+
+ XQueryKeymap(display, (char *) key_state);
+
+ for (i = 0; i < KEYMAP_SIZE; i++) {
+ if ((key_state[i] & ~old_key_state[i]) & keyboard_mask[i]) {
+ ret = ActivityNew;
+ break;
+ }
+ }
+ if (ignore_modifier_combos) {
+ for (i = 0; i < KEYMAP_SIZE; i++) {
+ if (key_state[i] & ~keyboard_mask[i]) {
+ if (old_key_state[i] & ~keyboard_mask[i])
+ ret = ActivityNone;
+ else
+ ret = ActivityReset;
+ break;
+ }
+ }
+ }
+ for (i = 0; i < KEYMAP_SIZE; i++)
+ old_key_state[i] = key_state[i];
+ return ret;
+}
+
+static double
+get_time(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+static void
+main_loop(Display * display, double idle_time, int poll_delay)
+{
+ double last_activity = 0.0;
+ double current_time;
+
+ keyboard_activity(display);
+
+ for (;;) {
+ current_time = get_time();
+ switch (keyboard_activity(display)) {
+ case ActivityNew:
+ last_activity = current_time;
+ break;
+ case ActivityNone:
+ /* NOP */;
+ break;
+ case ActivityReset:
+ last_activity = 0.0;
+ break;
+ }
+
+ /* If system times goes backwards, touchpad can get locked. Make
+ * sure our last activity wasn't in the future and reset if it was. */
+ if (last_activity > current_time)
+ last_activity = current_time - idle_time - 1;
+
+ if (current_time > last_activity + idle_time) { /* Enable touchpad */
+ toggle_touchpad(True);
+ }
+ else { /* Disable touchpad */
+ toggle_touchpad(False);
+ }
+
+ usleep(poll_delay);
+ }
+}
+
+static void
+clear_bit(unsigned char *ptr, int bit)
+{
+ int byte_num = bit / 8;
+ int bit_num = bit % 8;
+
+ ptr[byte_num] &= ~(1 << bit_num);
+}
+
+static void
+setup_keyboard_mask(Display * display, int ignore_modifier_keys)
+{
+ XModifierKeymap *modifiers;
+ int i;
+
+ for (i = 0; i < KEYMAP_SIZE; i++)
+ keyboard_mask[i] = 0xff;
+
+ if (ignore_modifier_keys) {
+ modifiers = XGetModifierMapping(display);
+ for (i = 0; i < 8 * modifiers->max_keypermod; i++) {
+ KeyCode kc = modifiers->modifiermap[i];
+
+ if (kc != 0)
+ clear_bit(keyboard_mask, kc);
+ }
+ XFreeModifiermap(modifiers);
+ }
+}
+
+/* ---- the following code is for using the xrecord extension ----- */
+#ifdef HAVE_X11_EXTENSIONS_RECORD_H
+
+#define MAX_MODIFIERS 16
+
+/* used for exchanging information with the callback function */
+struct xrecord_callback_results {
+ XModifierKeymap *modifiers;
+ Bool key_event;
+ Bool non_modifier_event;
+ KeyCode pressed_modifiers[MAX_MODIFIERS];
+};
+
+/* test if the xrecord extension is found */
+static Bool
+check_xrecord(Display * display)
+{
+
+ Bool found;
+ Status status;
+ int major_opcode, minor_opcode, first_error;
+ int version[2];
+
+ found = XQueryExtension(display,
+ "RECORD",
+ &major_opcode, &minor_opcode, &first_error);
+
+ status = XRecordQueryVersion(display, version, version + 1);
+ if (verbose && status) {
+ printf("X RECORD extension version %d.%d\n", version[0], version[1]);
+ }
+ return found;
+}
+
+/* called by XRecordProcessReplies() */
+static void
+xrecord_callback(XPointer closure, XRecordInterceptData * recorded_data)
+{
+
+ struct xrecord_callback_results *cbres;
+ xEvent *xev;
+ int nxev;
+
+ cbres = (struct xrecord_callback_results *) closure;
+
+ if (recorded_data->category != XRecordFromServer) {
+ XRecordFreeData(recorded_data);
+ return;
+ }
+
+ nxev = recorded_data->data_len / 8;
+ xev = (xEvent *) recorded_data->data;
+ while (nxev--) {
+
+ if ((xev->u.u.type == KeyPress) || (xev->u.u.type == KeyRelease)) {
+ int i;
+ int is_modifier = 0;
+
+ cbres->key_event = 1; /* remember, a key was pressed or released. */
+
+ /* test if it was a modifier */
+ for (i = 0; i < 8 * cbres->modifiers->max_keypermod; i++) {
+ KeyCode kc = cbres->modifiers->modifiermap[i];
+
+ if (kc == xev->u.u.detail) {
+ is_modifier = 1; /* yes, it is a modifier. */
+ break;
+ }
+ }
+
+ if (is_modifier) {
+ if (xev->u.u.type == KeyPress) {
+ for (i = 0; i < MAX_MODIFIERS; ++i)
+ if (!cbres->pressed_modifiers[i]) {
+ cbres->pressed_modifiers[i] = xev->u.u.detail;
+ break;
+ }
+ }
+ else { /* KeyRelease */
+ for (i = 0; i < MAX_MODIFIERS; ++i)
+ if (cbres->pressed_modifiers[i] == xev->u.u.detail)
+ cbres->pressed_modifiers[i] = 0;
+ }
+
+ }
+ else {
+ /* remember, a non-modifier was pressed. */
+ cbres->non_modifier_event = 1;
+ }
+ }
+
+ xev++;
+ }
+
+ XRecordFreeData(recorded_data); /* cleanup */
+}
+
+static int
+is_modifier_pressed(const struct xrecord_callback_results *cbres)
+{
+ int i;
+
+ for (i = 0; i < MAX_MODIFIERS; ++i)
+ if (cbres->pressed_modifiers[i])
+ return 1;
+
+ return 0;
+}
+
+static void
+record_main_loop(Display * display, double idle_time)
+{
+
+ struct xrecord_callback_results cbres;
+ XRecordContext context;
+ XRecordClientSpec cspec = XRecordAllClients;
+ Display *dpy_data;
+ XRecordRange *range;
+ int i;
+
+ dpy_data = XOpenDisplay(NULL); /* we need an additional data connection. */
+ range = XRecordAllocRange();
+
+ range->device_events.first = KeyPress;
+ range->device_events.last = KeyRelease;
+
+ context = XRecordCreateContext(dpy_data, 0, &cspec, 1, &range, 1);
+
+ XRecordEnableContextAsync(dpy_data, context, xrecord_callback,
+ (XPointer) & cbres);
+
+ cbres.modifiers = XGetModifierMapping(display);
+ /* clear list of modifiers */
+ for (i = 0; i < MAX_MODIFIERS; ++i)
+ cbres.pressed_modifiers[i] = 0;
+
+ while (1) {
+
+ int fd = ConnectionNumber(dpy_data);
+ fd_set read_fds;
+ int ret;
+ int disable_event = 0;
+ int modifier_event = 0;
+ struct timeval timeout;
+
+ FD_ZERO(&read_fds);
+ FD_SET(fd, &read_fds);
+
+ ret = select(fd + 1 /* =(max descriptor in read_fds) + 1 */ ,
+ &read_fds, NULL, NULL,
+ pad_disabled ? &timeout : NULL
+ /* timeout only required for enabling */ );
+
+ if (FD_ISSET(fd, &read_fds)) {
+
+ cbres.key_event = 0;
+ cbres.non_modifier_event = 0;
+
+ XRecordProcessReplies(dpy_data);
+
+ /* If there are any events left over, they are in error. Drain them
+ * from the connection queue so we don't get stuck. */
+ while (XEventsQueued(dpy_data, QueuedAlready) > 0) {
+ XEvent event;
+
+ XNextEvent(dpy_data, &event);
+ fprintf(stderr, "bad event received, major opcode %d\n",
+ event.type);
+ }
+
+ if (!ignore_modifier_keys && cbres.key_event) {
+ disable_event = 1;
+ }
+
+ if (cbres.non_modifier_event) {
+ if (ignore_modifier_combos && is_modifier_pressed(&cbres)) {
+ modifier_event = 1;
+ } else {
+ disable_event = 1;
+ }
+ } else if (ignore_modifier_keys) {
+ modifier_event = 1;
+ }
+ }
+
+ if (disable_event) {
+ /* adjust the enable_time */
+ timeout.tv_sec = (int) idle_time;
+ timeout.tv_usec = (idle_time - (double) timeout.tv_sec) * 1.e6;
+
+ toggle_touchpad(False);
+ }
+
+ if (modifier_event && pad_disabled) {
+ toggle_touchpad(True);
+ }
+
+ if (ret == 0 && pad_disabled) { /* timeout => enable event */
+ toggle_touchpad(True);
+ }
+ } /* end while(1) */
+
+ XFreeModifiermap(cbres.modifiers);
+}
+#endif /* HAVE_X11_EXTENSIONS_RECORD_H */
+
+static XDevice *
+dp_get_device(Display * dpy)
+{
+ XDevice *dev = NULL;
+ XDeviceInfo *info = NULL;
+ int ndevices = 0;
+ Atom touchpad_type = 0;
+ Atom *properties = NULL;
+ int nprops = 0;
+ int error = 0;
+
+ touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True);
+ touchpad_off_prop = XInternAtom(dpy, SYNAPTICS_PROP_OFF, True);
+ info = XListInputDevices(dpy, &ndevices);
+
+ while (ndevices--) {
+ if (info[ndevices].type == touchpad_type) {
+ dev = XOpenDevice(dpy, info[ndevices].id);
+ if (!dev) {
+ fprintf(stderr, "Failed to open device '%s'.\n",
+ info[ndevices].name);
+ error = 1;
+ goto unwind;
+ }
+
+ properties = XListDeviceProperties(dpy, dev, &nprops);
+ if (!properties || !nprops) {
+ fprintf(stderr, "No properties on device '%s'.\n",
+ info[ndevices].name);
+ error = 1;
+ goto unwind;
+ }
+
+ while (nprops--) {
+ if (properties[nprops] == touchpad_off_prop)
+ break;
+ }
+ if (nprops < 0) {
+ fprintf(stderr, "No synaptics properties on device '%s'.\n",
+ info[ndevices].name);
+ error = 1;
+ goto unwind;
+ }
+
+ break; /* Yay, device is suitable */
+ }
+ }
+
+ unwind:
+ XFree(properties);
+ XFreeDeviceList(info);
+ if (!dev)
+ fprintf(stderr, "Unable to find a synaptics device.\n");
+ else if (error && dev) {
+ XCloseDevice(dpy, dev);
+ dev = NULL;
+ }
+ return dev;
+}
+
+int
+main(int argc, char *argv[])
+{
+ double idle_time = 2.0;
+ int poll_delay = 200000; /* 200 ms */
+ int c;
+ int use_xrecord = 0;
+
+ /* Parse command line parameters */
+ while ((c = getopt(argc, argv, "i:m:dtp:kKR?v")) != EOF) {
+ switch (c) {
+ case 'i':
+ idle_time = atof(optarg);
+ break;
+ case 'm':
+ poll_delay = atoi(optarg) * 1000;
+ break;
+ case 'd':
+ background = 1;
+ break;
+ case 't':
+ disable_state = TappingOff;
+ break;
+ case 'p':
+ pid_file = optarg;
+ break;
+ case 'k':
+ ignore_modifier_keys = 1;
+ break;
+ case 'K':
+ ignore_modifier_combos = 1;
+ ignore_modifier_keys = 1;
+ break;
+ case 'R':
+ use_xrecord = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+ if (idle_time <= 0.0)
+ usage();
+
+ /* Open a connection to the X server */
+ display = XOpenDisplay(NULL);
+ if (!display) {
+ fprintf(stderr, "Can't open display.\n");
+ exit(2);
+ }
+
+ if (!(dev = dp_get_device(display)))
+ exit(2);
+
+ /* Install a signal handler to restore synaptics parameters on exit */
+ install_signal_handler();
+
+ if (background) {
+ pid_t pid;
+
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(3);
+ }
+ else if (pid != 0)
+ exit(0);
+
+ /* Child (daemon) is running here */
+ setsid(); /* Become session leader */
+ chdir("/"); /* In case the file system gets unmounted */
+ umask(0); /* We don't want any surprises */
+ if (pid_file) {
+ FILE *fd = fopen(pid_file, "w");
+
+ if (!fd) {
+ perror("Can't create pid file");
+ exit(3);
+ }
+ fprintf(fd, "%d\n", getpid());
+ fclose(fd);
+ }
+ }
+
+ pad_disabled = False;
+ store_current_touchpad_state();
+
+#ifdef HAVE_X11_EXTENSIONS_RECORD_H
+ if (use_xrecord) {
+ if (check_xrecord(display))
+ record_main_loop(display, idle_time);
+ else {
+ fprintf(stderr, "Use of XRecord requested, but failed to "
+ " initialize.\n");
+ exit(4);
+ }
+ }
+ else
+#endif /* HAVE_X11_EXTENSIONS_RECORD_H */
+ {
+ setup_keyboard_mask(display, ignore_modifier_keys);
+
+ /* Run the main loop */
+ main_loop(display, idle_time, poll_delay);
+ }
+ return 0;
+}
+
+/* vim: set noexpandtab tabstop=8 shiftwidth=4: */
diff --git a/xorg-synaptics.pc.in b/xorg-synaptics.pc.in
new file mode 100644
index 0000000..159cfbf
--- /dev/null
+++ b/xorg-synaptics.pc.in
@@ -0,0 +1,6 @@
+sdkdir=@sdkdir@
+
+Name: synaptics
+Description: X.Org synaptics input driver.
+Version: @PACKAGE_VERSION@
+Cflags: -I${sdkdir}