summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS20
-rw-r--r--ChangeLog238
-rw-r--r--GPL62
-rw-r--r--LGPL504
-rw-r--r--Makefile.am9
-rw-r--r--NEWS10
-rw-r--r--README113
-rwxr-xr-xbootstrap9
-rw-r--r--configure.in1152
-rw-r--r--docs/docs.html6064
-rw-r--r--docs/docs.txt2221
-rw-r--r--src/Makefile.am109
-rw-r--r--src/hid-core.c1386
-rw-r--r--src/hid-input.c434
-rw-r--r--src/hiddev.c686
-rw-r--r--src/usbmouse.c230
-rw-r--r--src/wacdump.c716
-rw-r--r--src/wacom.c690
-rw-r--r--src/wacscrn.c39
-rw-r--r--src/wacscrn.h32
-rw-r--r--src/wacserial.c966
-rw-r--r--src/wacserial.h115
-rw-r--r--src/wcm-beta.c618
-rw-r--r--src/wcm-beta.h67
-rw-r--r--src/xf86Wacom.c4070
25 files changed, 15031 insertions, 5529 deletions
diff --git a/AUTHORS b/AUTHORS
index da4a955..aebcb81 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,18 +1,4 @@
-There are a number of authors - just check the ChangeLog.
-
-Special thanks go to:
-
-John E. Joganic <jej@j-arkadia.com> for establishing this project;
-
-Magnus Vigerlöf <wigge@bigfoot.com> for fixing bugs, adding new
-features, and supporting user requests.
-
-Jens Georg <listen@jensgeorg.de> for being active and supportive
-in discussion and development groups.
-
-Andrew Zabolotny <zap@homelink.ru> for adding new features.
-
-This project is being maintained by:
-
-Ping Cheng <pingc@wacom.com>.
+There are a number of authors- just check the source files. Currently,
+this package is being maintained by:
+John E. Joganic <jej@j-arkadia.com>
diff --git a/ChangeLog b/ChangeLog
index 2cb1662..f8d17ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,221 +1,43 @@
-2009-07-30 Ping Cheng <pingc@wacom.com>
- * Support Nvidia non-TwinView setting
- * Updated webpages and man page
- * Fixed bug 2789354 for Graphire
- * Label 0.8.4
+2002-12-21 John E. Joganic <john@joganic.com>
-2009-06-28 Ping Cheng <pingc@wacom.com>
- * Added support for DFT720a
- * Fixed DFT720 and DTF521 product ID swapped issue in wacom_wac.c
- * Added ABS_Z out-prox event for the newer kernels
- * Support kernel 2.6.31
- * Label 0.8.3-6
+ * Moved project to SourceForge as linuxwacom.
-2009-05-22 Ping Cheng <pingc@wacom.com>
- * Fixed a menu strip out-prox issue in wacom_wac.c (Sylvain Giasson)
- * Fixed a relative mode button issue for ExpressKeys
- * Updated --enable-quirk-tablet-rescale support
- * Split TOOLSEIAL from SERIAL for xsetwacom
- * Support boundary cases of "usbParse: Exceeded channel" (Stefan Schimanski)
- * Label 0.8.3-5
+2002-12-21 John E. Joganic <john@joganic.com>
-2009-05-01 Ping Cheng <pingc@wacom.com>
- * Updated web pages and docs
- * Fixed a tool index bug in wacom_wac.c (Sylvain Giasson)
- * Updated configure.in for Xorg earlier than 7.0
- * Label 0.8.3-4
+ * Added serial code to wacdump
+ * Added serial protocols IV 1.0 - 1.4.
+ * Added serial protocol V 1.0 - 1.1.
+ * Intuos mouse wheels are now positive when rolled backwards per PS/2
+ Intellimouse convention
+ * Added Intuos2 to xf86Wacom.c
-2009-04-23 Ping Cheng <pingc@wacom.com>
- * Updated README
- * Updated GPL to version 2
- * Updated wacom_wac.c
- * Brought configure.in and inlcude files in-sync with Fedora 10/11
- * Fixed a few button and in-prox/out-prox issues
- * Label 0.8.3-3
+2002-12-17 John E. Joganic <john@joganic.com>
-2009-04-03 Ping Cheng <pingc@wacom.com>
- * Support kernels 2.6.28 and 2.6.29
- * Added 10-linuxwacom.fdi from Peter Hutterer
- * Updated install/uninstall and util/Makefile.am to support HAL
- * Patch 2653689 from Peter Hutterer
- * Label 0.8.3-2
+ * Merged code from 2.4.20 hid-core.c
+ * Added configuration code to handle kernels still at 2.4.19
+ * Split wacdump curses code into wacscrn.c to solve namespace collision
+ * Added volito to wacom.c
-2009-03-26 Ping Cheng <pingc@wacom.com>
- * Patch "Don't touch the button map" from Thomas Jaeger
- * Patch 2653696 from Matthew Garret
- * Patch 2653697 from Peter Hutterer
- * Removed kernels 2.4.x and 2.6.8 support
- * Updated TwinView and Xinerama mapping
- * Bug 2517856 fixed by Calvin Walton
- * Fixed bug 2578477
- * Support Intuos4
- * Label 0.8.3
+2002-12-15 John E. Joganic <john@joganic.com>
-2009-01-19 Ping Cheng <pingc@wacom.com>
- * Patch to support Xorg server 1.6 from Alexia Death
- * Patch for "usbParse: Exceeded channel" workaround from Markus Gaugusch
- * Fixed Bug #2499414
- * Label 0.8.2-2
+ * Last minute fix to debugging level on 4D mouse wheel
+ * Added framework for new driver
+ * Added code for 4D mouse wheel in xf86Wacom.c
-2008-12-31 Ping Cheng <pingc@wacom.com>
- * Updated patch 1998051 for none KP buttons
- * Updated wcmUSB.c to ignore unparsed data
- * Updated wacom_wac.c with Bartosz' suggestion
- * Fixed bug 2432258
- * Support Xorg 1.6.0
- * Label 0.8.2-1
+2002-12-13 John E. Joganic <john@joganic.com>
-2008-12-01 Ping Cheng <pingc@wacom.com>
- * Added workaround for X Server 1.5 to send beep
- * Patch from Vicenç (vicencb@gmail.com)
- * Patch from Rene van Paassen (rene.vanpaassen@gmail.com)
- * web pages updated
- * Label 0.8.2
+ * Added pen model numbers for Intuos2 grip pen and Intuos pen
+ * Added wcm-beta.c and wcm-beta.h shell
+ * Added relative events to wacdump
+ * Added relative bit to Intuos and Intuos2 reporting in wacom.c
+ * Fixed relative 2D mouse wheel reporting in wacom.c
-2008-10-23 Ping Cheng <pingc@wacom.com>
- * Fixed a configure.in bug (Bartosz Fabianowski)
- * Added kernel 2.6.27 support
- * Use BTN_TOOL_DOUBLETAP for USB Tablet PC touch event
- * Unified USB BTN_TOUCH event for mousedev before X server starts
- * Label 0.8.1-6
+2002-11-27 John E. Joganic <john@joganic.com>
-2008-10-08 Ping Cheng <pingc@wacom.com>
- * Updated configure.in for Xorg 1.5
- * USB Tablet PC 0x90, 0x93, 0x9A are supported
- * Merged Danny's xf86Config patch
- * Updated wacomcpl for touch w/o capacity
- * Label 0.8.1-5
+ * Added exp subdirectory for experimental work
+ * Isolated xf86Wacom.c declarations to header file
-2008-09-01 Ping Cheng <pingc@wacom.com>
- * Support Xorg 7.3 or newer in wacomcpl
- * Modified wacom_sys.c according to Bartosz Fabianowski's suggestion
- * Added a link to Bartosz Fabianowski's FreeBSD Wacom driver download page
- * Merged bug 2074297 fix (Mike Auty)
- * Fixed a few minor bugs
- * Label 0.8.1-4
+2002-11-24 John E. Joganic <john@joganic.com>
-2008-08-11 Ping Cheng <pingc@wacom.com>
- * Merged patch 1994583 (Craig Wiegert) for wacom_sys.c
- * Merged patch 2035856 (Trifon Trifonov) for Uninit on Xorg 7.3 and later
- * Modified configure.in for Danny's patch
- * Added serial Tablet PC with capacitive touch
- * Label 0.8.1-3
-
-2008-08-01 Ping Cheng <pingc@wacom.com>
- * Added kernel 2.6.26 support
- * Updated USB Tablet PC pressure data in kernel
- * Merged patches from Danny Kukawka for wacomcpl and xsetwacom
- * Merged patch 1998051 (Yuri Shchedov) for keystroke
- * Label 0.8.1-2
-
-2008-07-21 Ping Cheng <pingc@wacom.com>
- * Updated USB and serial Tablet PC with touch support
- * Label 0.8.1-1
-
-2008-07-08 Ping Cheng <pingc@wacom.com>
- * Merged USB Tablet PC patch 1949610 (Andrew Zappacky)
- * Label 0.8.1
-
-2008-05-23 Ping Cheng <pingc@wacom.com>
- * Fixed an issue in configure.in (Ron and Magnus)
- * Fixed an issue in wcmISDV4.c
- * Label 0.8.0-3
-
-2008-05-14 Ping Cheng <pingc@wacom.com>
- * Fixed rotation issue
- * Label 0.8.0-2
-
-2008-05-09 Ping Cheng <pingc@wacom.com>
- * Updated xidump for Xserver 1.4 or later
- * Fixed no eraser calibration issue for LCD tablets
- * Fixed serial Tablet PC baudrate issue
- * Label 0.8.0-1
-
-2008-04-25 Ping Cheng <pingc@wacom.com>
- * Updated wacom.4x
- * Update ~/.xsession from wacomcpl for KDE system
- * Added IsXExtensionKeyboard check for Xserver 1.4 or later in wacomcfg.c
- * Label 0.8.0
-
-2008-04-11 Ping Cheng <pingc@wacom.com>
- * Excluded dixScreenOrigins call for Xorg 6.8.x
- * Synchronized databases
- * Updated webpages
- * Label 0.7.9-11
-
-2008-04-03 Ping Cheng <pingc@wacom.com>
- * Minor fixes in kernel and wacomcpl
- * Removed debug statement in wcmSerial.c
- * Label 0.7.9-10
-
-2008-03-30 Ping Cheng <pingc@wacom.com>
- * Updated configure.in for keystrokes (Magnus Vigerlöf)
- * Added touch support for serial TabletPC (ISDv4)
- * Added autoprobe patch (Matthias Hopf @ Suse)
- * Label 0.7.9-9
-
-2008-03-07 Ping Cheng <pingc@wacom.com>
- * Updated wacomcpl for keystrokes
- * Excluded keystroke support for XFree86
- * Introduced wacom defined keymap (Magnus Vigerlöf)
- * Support building outside the source-directory (Magnus Vigerlöf)
-
-2008-02-28 Ping Cheng <pingc@wacom.com>
- * Added support for Cintiq 20WSX
- * Fixed Bug 1875050 (Kovid Goyal)
- * Incorporated patch 1901778 (Steven Seed)
-
-2008-02-23 Magnus Vigerlöf <Magnus.Vigerlof@ipbo.se>
- * The rescaling patch is now in X.org master database
- * Updated configure.in
- * Added 2.6.24 support
- * Updated kernel 2.4 make file
-
-2008-01-22 Ping Cheng <pingc@wacom.com>
- * Updarted xsetwacom for Cintiq 12WX, Bamboo1, and BambooFun
- * Regrouped the routines for coming Xorg 7.3 hot-plug support (Magnus Vigerlöf)
- * refer to http://git.debian.org/?p=collab-maint/linux-wacom.git;a=summary for detailed changes
- * Label 0.7.9-7
-
-2008-01-10 Ping Cheng <pingc@wacom.com>
- * Label 0.7.9-6
-
-2008-01-02 Ping Cheng <pingc@wacom.com>
- * Updated build and configure scripts (Magnus Vigerlöf)
- * Support Xorg 7.3 with multimonitors
- * Unified screen, tablet, and cordinate initialization
-
-2007-12-19 Ping Cheng <pingc@wacom.com>
- * Support multimonitor setup on 4 directions
-
-2007-12-13 Ping Cheng <pingc@wacom.com>
- * Updated wacomcpl
- * Incorporated Xorg 7.3 workaround from Magnus Vigerlöf
- * Label 0.7.9-4
-
-2007-11-28 Ping Cheng <pingc@wacom.com>
- * Clean support of outbound tracking for Bamboo, etc
- * Updated kernel 2.4.x code
- * Label 0.7.9-3
-
-2007-11-28 Ping Cheng <pingc@wacom.com>
- * Updated TwinView support to eliminate the unnecessary tvoffset (bug 1812593)
- * Incorporated Bartosz Fabianowski's patch (bug 1831998)
- * Patch 1818295 from Alexander V. Inyukhin
- * Patch 1834712 from Magnus Vigerlöf
- * Fixed bug 1791005 (protocol 4 tablets don't support serial numbers)
- * Patch 1839008 from Magnus Vigerlöf
-
-2007-11-12 Ping Cheng <pingc@wacom.com>
- * Support legacy kernels
- * Label 0.7.9-2
-
-2007-11-08 Ping Cheng <pingc@wacom.com>
- * Added support for BambooFun, Bamboo1 and Hummingbird
- * Support multimonitors horizontally and vertically in the same configuration
-
-2007-10-24 Ping Cheng <pingc@wacom.com>
- * Added support for 2.6.22
- * Temporary workaround for Xorg 7.3 (Magnus and Ron)
- * Support up to 8 screens in xsetwacom
- * Label 0.7.9
+ * Branched at 0.2.0
+ * Created configure-based build environment
diff --git a/GPL b/GPL
index c7aea18..d60c31a 100644
--- a/GPL
+++ b/GPL
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -278,3 +278,63 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/LGPL b/LGPL
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/LGPL
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/Makefile.am b/Makefile.am
index 3d11a39..148f1b7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,9 +1,2 @@
SUBDIRS = src
-
-noinst_SCRIPT = wrapitup
-
-x-includes:
- @sh mkxincludes
-
-EXTRA_DIST = docs/docs.html GPL prebuilt/wacom_drv.o \
- docs/docs_files/null.gif docs/docs_files/sflogo.png
+EXTRA_DIST = docs/docs.txt docs/docs.html GPL prebuilt/wacom_drv.o
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e221ed2
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,10 @@
+December 22, 2002 - John E. Joganic
+
+The wacpack project is being hosted on SourceForge as the Linux Wacom Project.
+This build is now distributed under linuxwacom.
+
+November 24, 2002 - John E. Joganic
+
+This marks the first release of wacpack with a configure-based build
+environment. Though it will not install anything, it is capable of
+building all the major drivers including wacom.o and wacom_drv.o.
diff --git a/README b/README
index e85c974..3f178ab 100644
--- a/README
+++ b/README
@@ -1,41 +1,34 @@
README
-April 23, 2009
+November 24, 2002
-==============================================================================
-Most end users would probably only need to update the /etc/X11/xorg.conf file
-and sometime probably the Wacom X driver as well to use the rich features that
-Wacom tablets offer. The steps could be as simple as:
+This package is not currently sanctioned by the original driver developers
+although several attempts to contact them have been made. Hopefully, this
+work will be rolled back into the main development trees. Until that time,
+I will be taking responsibility for this code. If you have any questions,
+comments, problems, patches, or complaints, send them to jej@j-arkadia.com.
+Please include the word WACOM in the subject to help me differentiate your
+email from the spam I usually receive.
- $ su
- # cp /etc/X11/xorg.conf /etc/X11/xorg.conf.bak
- # gedit /etc/X11/xorg.conf
+John E.Joganic
+jej@j-arkadia.com
-then follow the step listed at http://linuxwacom.sourceforge.net/index.php/howto/x11
-or "man wacom" if you don't have network access to add sections for Wacom device.
+==============================================================================
-If by some reason your distribution doesn't have include Wacom driver or you want to
-to use the newer release, you can download the package then
+BUILDING FROM CVS:
- $ bunzip2 linuxwacom.tar.bz2
- $ tar xvf linuxwacom.tar
- $ cd linuxwacom/prebuilt
- $ su
- # yum remove linuxwacom
- # ./uninstall
- # ./install
- # reboot
+You should run bootstrap from the main directory to correctly initialize
+the project. From there, run configure as you would normally. Installation
+is not automatic so there is no make install target. Configure options are
+explained below.
-==============================================================================
-
-However, if you have a USB tablet which is newer than your running kernel, i.e.,
-the tablet is not supported by your running kernel, or you are a developer who is
-willing to build the driver from the source, there are extra work waiting for you.
+ $ ./bootstrap && ./configure && make
==============================================================================
BUILDING FROM TARBALL:
-As you would expect, run configure and make. Configure options are explained below.
+As you would expect, run configure and make. Installation is not automatic
+so there is no make install target. Configure options are explained below.
$ ./configure && make
@@ -43,27 +36,61 @@ As you would expect, run configure and make. Configure options are explained be
CONFIGURE OPTIONS:
-This file contains hints for building the sources. There are a number of build
- targets, some of which are not built automatically. Here is the
-breakdown:
+This file contains hints for building the sources. There are a number of
+build targets, some of which are not built automatically. Here is the
+breakdown.
- wacom.o: not built by default (--enable-wacom, --disable-wacom)
+ wacom.o: built by default (--enable-wacom, --disable-wacom)
wacdump: built by default (--enable-wacdump, --disable-wacdump)
- xidump: built by default (--enable-xidump, --disable-xidump)
- xsetwacom: built by default (--enable-xsetwacom, --disable-xsetwacom)
- hid.o: not built by default (--enable-hid, --disable-hid; Only kernels 2.6.18 or older need it.)
- wacom_drv.o: built by default (--enable-wacomdrv, --disable-wacomdrv)
+ hid.o: not built by default (--enable-hid, --disable-hid)
+ usbmouse.o: not built by default (--enable-usbmouse, --disable-usbmouse)
+ wacom_drv.o: not built by default (--enable-wacomdrv, --disable-wacomdrv)
-There are many options, and configure will attempt to guess the correct
-values for most of them. By default, only wacomcpl, xsetwacom, wacom_drv.o,
-xidump, and wacdump program are built.
+BUILDING:
-Please surf the HOWTO page at http://linuxwacom.sf.net/index.php/howto/main
-(or the miniHOWTO at http://linuxwacom.sourceforge.net/index.php/minihowto if
-you run a Fedora system) to find the proper options if the default building
-environment doesn't work for you.
+Generally, you run the configure script followed by make. This package
+will not attempt to install the drivers. Please see the documentation on
+the website for more information on where specific drivers belong.
-==============================================================================
+ [root@haku linuxwacom-dev] # ./configure
+ [root@haku linuxwacom-dev] # make
+
+There are many options, and configure will attempt to guess the correct
+values for most of them. By default, only the kernel driver and wacdump
+program are built.
+
+REQUIREMENTS:
+
+wacom.o, hid.o, and usbmouse are kernel modules and require the kernel
+sources to be present. On a Redhat 8.0 system with the kernel-sources
+RPM installed, the source directory is located at /usr/src/linux-2.4.
+The wacdump configuration script will search for this directory
+automatically as well as /usr/src/linux. You can override the directory
+using the --with-kernel=<directory> option.
+
+wacom_drv.o requires the XFree86 sources as well as a functional XF86
+build environment. Since this is a more complicated setup and few people
+are going to want to rebuild this driver from source, the wacom_drv.o file
+is supplied with the wacdump package in the prebuilt directory. It is
+compiled with gcc 3.2 under Redhat 8.0. If the prebuilt wacom_drv.o module
+will not work for you, see the section "Building wacom_drv.o From Scratch."
+
+BUILDING wacom_drv.o FROM SCRATCH
+
+You will need the XFree86 source code, and you will need to actually build
+it. The file xf86Version.h is generated during the build process and is a
+required dependency for building wacom_drv.o. The configure script will
+*not* attempt to build wacom-drv.o by default, but if you provide the
+--enable-wacomdrv and --with-xf86=<xf86_directory> options, configure will
+build wacom_drv.o during the normal build process.
+
+If the xf86Version.h file is located at:
+ /usr/local/src/XFree86-4.2.0/xc/programs/Xserver/include/xf86Version.h
+
+Then the correct configure options would be:
+ --enable-wacomdrv --with-xf86=/usr/local/src/XFree86-4.2.0
-WEBSITE: http://linuxwacom.sf.net
+==============================================================================
+WEBSITE: http://linux.joganic.com/wacom
+ HELP: jej@j-arkadia.com
diff --git a/bootstrap b/bootstrap
index cb69525..6c5591c 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,9 +1,4 @@
-#! /bin/sh
-
aclocal
-if test $? != 0; then exit; fi
-libtoolize --force --copy
-if test $? != 0; then exit; fi
-automake --foreign --add-missing
-if test $? != 0; then exit; fi
+autoheader
autoconf
+automake --foreign --add-missing
diff --git a/configure.in b/configure.in
index a4f5fbb..333adfb 100644
--- a/configure.in
+++ b/configure.in
@@ -1,1010 +1,262 @@
-AC_PREREQ(2.58)
-AC_INIT(linuxwacom, 0.8.3)
-AM_INIT_AUTOMAKE
+AC_INIT(src/wacom.c)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(linuxwacom, 0.3.4-beta)
AM_MAINTAINER_MODE
-
-AM_CONFIG_HEADER(src/include/xdrv-config.h)
-AM_CONFIG_HEADER(src/include/kernel-config.h)
-AM_CONFIG_HEADER(src/include/util-config.h)
-
AC_PROG_CC
AC_PROG_AWK
-AC_PROG_LIBTOOL
-PKG_PROG_PKG_CONFIG
-dnl Library versions
-WCM_LIBWACOMCFG_VER="0:1:0"
-AC_SUBST(WCM_LIBWACOMCFG_VER)
+XF86SUBDIR=xc/programs/Xserver
dnl Targets
-WCM_PROGS=
-WCM_LIBS=
-WCM_MODULES=
-WCM_XF86MODULES=
-
-WCM_TCLLIBS=""
-WCM_TCLPKGS=""
-WCM_XSERVER64=""
-
-dnl Configuration
-WCM_MODVER=
-WCM_ENV_XFREE86=no
-WCM_ENV_XORGSDK=no
-WCM_XDRIVER_QUIRKS=
-
-#dnl Check for HAL
-have_hal=no
-PKG_CHECK_MODULES(HAL, hal >= 0.5.0, have_hal=yes, have_hal=no)
-if test "x$have_hal" = "xyes"; then
- AC_SUBST([HAL_CFLAGS])
- AC_SUBST([HAL_LIBS])
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS hal"
-fi
-AM_CONDITIONAL(WCM_HAVE_HAL, test "x$have_hal" = "xyes")
-
-dnl Setup paths based on configuration parameters
-WCM_PREFIX=$prefix
-test "$WCM_PREFIX" = NONE && WCM_PREFIX=$ac_default_prefix
-
-dnl =======================================================
-dnl Check architecture we compile for
-AC_MSG_CHECKING(for arch type)
-AC_ARG_WITH(arch,
- AC_HELP_STRING([--with-arch], [Use specified architecture]),
-[ WCM_ARCHITECTURE=$withval ],
-[
- dnl Try the compiler for the build arch first.
- dnl We may be cross compiling or building for
- dnl a 32bit system with a 64 bit kernel etc.
- WCM_ARCHITECTURE=`$CC -dumpmachine 2>/dev/null`
- test $? = 0 || WCM_ARCHITECTURE=`uname -m`
-])
-AC_MSG_RESULT($WCM_ARCHITECTURE)
-WCM_ARCH="`echo $WCM_ARCHITECTURE | cut -d- -f 1`"
-
-dnl =======================================================
-dnl Check if we should be compiling for linux
-AC_MSG_CHECKING(for kernel type)
-WCM_KERNEL=`uname -s`
-AC_MSG_RESULT($WCM_KERNEL)
-
-AC_MSG_CHECKING(for linux-based kernel)
-WCM_ISLINUX=no
-if echo $WCM_KERNEL | grep -i linux >/dev/null; then
- WCM_ISLINUX=yes
-fi
-AC_MSG_RESULT($WCM_ISLINUX)
-
-dnl Check for 64bit XServer
-WCM_OPTION_XSERVER64=no
-AC_ARG_ENABLE(xserver64,
- AC_HELP_STRING([--enable-xserver64], [Use 64bit XServer [[default=usually]]]),
- [ WCM_OPTION_XSERVER64=$enableval ],
- [ echo $WCM_ARCHITECTURE | grep "64" >/dev/null && WCM_OPTION_XSERVER64=yes ])
-
-dnl Check for linux kernel override
-AC_ARG_WITH(linux,
- AS_HELP_STRING([--with-linux], [Override linux kernel check]),
- [ WCM_ISLINUX=$withval ])
-
-dnl Enable linux specific features if linux kernel is detected.
-dnl kernel source, module versioning, etc
-WCM_OPTION_WACOM=no
-WCM_OPTION_HID=no
-WCM_OPTION_MODVER=no
-WCM_PATCH_HID=
-WCM_ENV_KERNEL=no
-WCM_KERNEL_DIR=
-WCM_KERNEL_VER=
-WCM_KSTACK=
-if test "$WCM_ISLINUX" != yes; then
- WCM_PATCH_WACDUMP="(no USB)"
- WCM_PATCH_WACOMDRV="(no USB)"
-else
- AC_DEFINE(WCM_ENABLE_LINUXINPUT,,[Enable the Linux Input subsystem])
- WCM_PATCH_WACDUMP=
- WCM_PATCH_WACOMDRV=
-
- dnl Check for kernel build environment
- AC_ARG_WITH(kernel,
- AS_HELP_STRING([--with-kernel=dir], [Specify kernel source directory]),
- [WCM_KERNEL_DIR="$withval"])
-
- AC_MSG_CHECKING(for kernel source/headers)
- if test "$WCM_KERNEL_DIR" = "yes" -o -z "$WCM_KERNEL_DIR"; then
- WCM_KERNEL_DIR=
- dnl Kernel source not specified, guess where it is
- for i in /lib/modules/`uname -r`/source /lib/modules/`uname -r`/build \
- /usr/src/linux /usr/src/linux-`uname -r` \
- /usr/src/linux-2.6; do
- if test -f "$i/include/linux/input.h"; then
- WCM_KERNEL_DIR=$i
- WCM_ENV_KERNEL=yes
- AC_MSG_RESULT($WCM_KERNEL_DIR)
- break
- fi
- done
- if test -z "$WCM_KERNEL_DIR"; then
- AC_MSG_RESULT(not found)
- echo "***"
- echo "*** WARNING:"
- echo "*** Unable to guess kernel source directory"
- echo "*** Looked at /lib/modules/`uname -r`/source, /lib/modules/`uname -r`/build,"
- echo "*** /usr/src/linux, /usr/src/linux-`uname -r`, and"
- echo "*** /usr/src/linux-2.6"
- echo "*** Kernel modules will not be built"
- echo "***"
- fi
- elif test "$WCM_KERNEL_DIR" != "no"; then
- if test -f "$WCM_KERNEL_DIR/include/linux/input.h"; then
- WCM_ENV_KERNEL=yes
- AC_MSG_RESULT([yes, $WCM_KERNEL_DIR])
- else
- AC_MSG_ERROR([Provided kernel path is invalid])
- fi
+WAC_PROGS=""
+WAC_MODULES=""
+WAC_XF86PROGS=""
+WAC_XF86MODULES=""
+WAC_EXPPROGS=""
+WAC_EXPMODULES=""
+WAC_PATCH_HID=""
+
+dnl Check architecture
+AC_MSG_CHECKING(for processor type)
+WAC_ARCH=`uname -m`
+AC_MSG_RESULT($WAC_ARCH)
+
+dnl Guess modversioning
+WAC_OPTION_MODVER=no
+AC_MSG_CHECKING(for kernel module versioning)
+kernelrel=`uname -r`
+moddir="/lib/modules/$kernelrel/kernel/drivers/usb"
+if test -f "$moddir/hid.o"; then
+ printk=`nm $moddir/hid.o | grep printk_R`
+ if test -n "$printk"; then
+ WAC_OPTION_MODVER=yes
+ AC_MSG_RESULT(yes)
else
- WCM_KERNEL_DIR=
- AC_MSG_RESULT(no)
- fi
-
- dnl Check which version of the driver we should compile
- if test -n "$WCM_KERNEL_DIR"; then
- AC_MSG_CHECKING(kernel version)
- MODUTS=
- for a in "$WCM_KERNEL_DIR/include/linux/version.h" \
- "$WCM_KERNEL_DIR/include/linux/utsrelease.h"; do
- MODUTS=`grep UTS_RELEASE $a | sed -e 's/^[[^"]]*"\([[^"]]*\).*$/\1/g'`
- test -n "$MODUTS" && break
- done
- if test -z "$MODUTS"; then
- AC_MSG_WARN(unable to identify kernel version)
- else
- AC_MSG_RESULT([$MODUTS])
- MINOR=`echo $MODUTS | sed 's/[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\).*/\1/'`
- if echo $MODUTS | grep "^2.4" >/dev/null; then
- AC_MSG_WARN([support for kernel 2.4.x has been dropped after 0.8.2])
- elif echo $MODUTS | grep "^2.6" >/dev/null; then
- if test $MINOR -ge 9; then
- case $MINOR in
- 9) WCM_KERNEL_VER="2.6.9";;
- 10) WCM_KERNEL_VER="2.6.10";;
- 11|12) WCM_KERNEL_VER="2.6.11";;
- 13) WCM_KERNEL_VER="2.6.13";;
- 14) WCM_KERNEL_VER="2.6.14";;
- 15) WCM_KERNEL_VER="2.6.15";;
- 16|17) WCM_KERNEL_VER="2.6.16";;
- 18) WCM_KERNEL_VER="2.6.18";;
- 19|20|21) WCM_KERNEL_VER="2.6.19";;
- 22|23) WCM_KERNEL_VER="2.6.22";;
- 24|25) WCM_KERNEL_VER="2.6.24";;
- 26) WCM_KERNEL_VER="2.6.26";;
- 27) WCM_KERNEL_VER="2.6.27";;
- 28|29|30) WCM_KERNEL_VER="2.6.28";;
- *) WCM_KERNEL_VER="2.6.31";;
- esac
- else
- AC_MSG_WARN([support for kernels older than 2.6.9 has been dropped after 0.8.2])
- fi
- else
- AC_MSG_WARN(kernel version $MODUTS not supported)
- fi
- fi
- fi
-
- dnl Check if we have support for modules in the kernel, needed if
- dnl we are compiling any kernel modules.
- if test -n "$WCM_KERNEL_DIR"; then
- AC_MSG_CHECKING(for kernel module support)
- if grep CONFIG_MODULES $WCM_KERNEL_DIR/include/linux/autoconf.h >/dev/null 2>&1; then
- AC_MSG_RESULT(yes)
- else
+ printk=`nm $moddir/hid.o | grep printk`
+ if test -n "$printk"; then
AC_MSG_RESULT(no)
- WCM_KERNEL_VER=
- fi
- fi
-
- if test -n "$WCM_KERNEL_VER"; then
- dnl Check for kernel module build
- AC_ARG_ENABLE(wacom,
- AC_HELP_STRING([--enable-wacom], [Enable building wacom.o [[default=no]]]),
- WCM_OPTION_WACOM=$enable_wacom)
- AC_ARG_ENABLE(hid,
- AC_HELP_STRING([--enable-hid], [Enable building hid.o [[default=no]]]),
- WCM_OPTION_HID=$enable_hid)
-
- if test "$WCM_OPTION_WACOM" = yes; then
- WCM_MODULES="$WCM_MODULES wacom.o"
- fi
- if echo $WCM_KERNEL_VER | grep "^2.6" >/dev/null 2>&1; then
- MINOR=`echo $WCM_KERNEL_VER | cut -f 3 -d.`
- if test $MINOR -ge 18; then
- WCM_OPTION_HID=no
- else
- WCM_MODULES="$WCM_MODULES hid.o"
- fi
- fi
- fi
-fi
-
-dnl =======================================================
-dnl Check for Xlib
-WCM_CLEVEL=-ansi
-WCM_ENV_XLIB=no
-WCM_ENV_XF86CONFIG=no
-WCM_XLIB_DIR=
-WCM_XSERVER64=
-AC_ARG_WITH(xlib,
- AS_HELP_STRING([--with-xlib=dir], [uses a specified X11R6 directory]),
- [WCM_XLIB_DIR=$withval])
-if test -z "$WCM_XLIB_DIR" -o "$WCM_XLIB_DIR" = "yes"; then
- PKG_CHECK_MODULES(Xlib,[x11],
- [
- dnl Found it with pkg-config, use that information
- WCM_XLIB_DIR="`$PKG_CONFIG --variable=libdir x11`"
- WCM_ENV_XLIB=yes
- ],
- [
- AC_MSG_CHECKING(for X lib directory)
- WCM_XLIBDIR_DEFAULT=/usr/X11R6/lib
- WCM_XLIBDIR_DEFAULT2=/usr/lib
- if test "$WCM_OPTION_XSERVER64" = "yes"; then
- WCM_XLIBDIR_DEFAULT=/usr/X11R6/lib64
- test -d /usr/lib64 && WCM_XLIBDIR_DEFAULT2=/usr/lib64
- fi
-
- if test -f $WCM_XLIBDIR_DEFAULT/libX11.so; then
- WCM_ENV_XLIB=yes
- WCM_XLIB_DIR=$WCM_XLIBDIR_DEFAULT
- AC_MSG_RESULT([found, $WCM_XLIB_DIR])
- elif test -d $WCM_XLIBDIR_DEFAULT2; then
- WCM_ENV_XLIB=yes
- WCM_XLIB_DIR=$WCM_XLIBDIR_DEFAULT2
- AC_MSG_RESULT([found, $WCM_XLIB_DIR])
else
- WCM_ENV_XLIB=no
- AC_MSG_RESULT([not found, tried $WCM_XLIBDIR_DEFAULT and $WCM_XLIBDIR_DEFAULT2])
+ AC_MSG_RESULT(confused; assuming no)
+ WAC_OPTION_MODVER="unknown"
+ echo "***"; echo "*** WARNING:"
+ echo "*** printk symbol in hid.o not present"
+ echo "***"
fi
- ])
-elif test "$WCM_XLIB_DIR" != "no"; then
- AC_MSG_CHECKING(for X lib directory)
- if test -f $WCM_XLIB_DIR/libX11.so; then
- AC_MSG_RESULT([found, $WCM_XLIB_DIR])
- WCM_ENV_XLIB=yes
- else
- AC_MSG_ERROR([Provided Xlib-path is invalid])
fi
else
- WCM_ENV_XLIB=no
-fi
-if test "$WCM_ENV_XLIB" = yes; then
- if test "$WCM_OPTION_XSERVER64" = "yes"; then
- CFLAGS="$CFLAGS -D__amd64__"
- WCM_XSERVER64="-D_XSERVER64"
- fi
+ AC_MSG_RESULT(unknown; assuming no)
+ WAC_OPTION_MODVER="unknown"
fi
-dnl =======================================================
-dnl Check for XFree86 source or X.org SDK
-test -d "x-include" && WCM_XFREE86_DIR="x-include"
-AC_ARG_WITH(x-src,
- AS_HELP_STRING([--with-x-src=dir], [Specify X driver build directory]),
- WCM_XFREE86_DIR="$withval")
-if test -n "$WCM_XFREE86_DIR"; then
- XFREE86SUBDIR=programs/Xserver/hw/xfree86
- AC_MSG_CHECKING(for valid XFree86/X.org build environment)
- if test -f $WCM_XFREE86_DIR/xc/$XFREE86SUBDIR/xf86Version.h; then
- WCM_ENV_XFREE86=yes
- WCM_XFREE86_DIR="$WCM_XFREE86_DIR/xc"
- AC_MSG_RESULT([ok, $WCM_XFREE86_DIR])
- elif test -f $WCM_XFREE86_DIR/$XFREE86SUBDIR/xf86Version.h; then
- WCM_ENV_XFREE86=yes
- AC_MSG_RESULT([ok, $WCM_XFREE86_DIR])
+dnl Check for kernel build environment
+WAC_ENV_KERNEL=no
+AC_ARG_WITH(kernel,
+[ --with-kernel=dir Specify kernel source directory],
+[
+ WAC_KERNELDIR="$withval"
+ AC_MSG_CHECKING(for valid kernel source tree)
+ if test -f "$WAC_KERNELDIR/include/linux/input.h"; then
+ AC_MSG_RESULT(ok)
+ WAC_ENV_KERNEL=yes
else
- WCM_ENV_XFREE86=no
- WCM_XFREE86_DIR=
- AC_MSG_RESULT(xf86Version.h missing)
- AC_MSG_RESULT(Tried $WCM_XFREE86_DIR/$XFREE86SUBDIR and $WCM_XFREE86_DIR/xc/$XFREE86SUBDIR)
- fi
- if test "$WCM_ENV_XFREE86" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS libc-wrapper"
-
- dnl Xfree86 > 4.2 support sending keyevents
- AC_MSG_CHECKING([if XFree86 support sending keys])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XFREE86_DIR $CFLAGS"
- AC_TRY_COMPILE([
-#include <programs/Xserver/hw/xfree86/xf86Version.h>
-#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4, 3, 0, 0, 0)
-# error "XFree86 < 4.3 doesn't support sending keys"
-#endif
-], , [WCM_SEND_KEYS=yes], [WCM_SEND_KEYS=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_SEND_KEYS)
- if test "$WCM_SEND_KEYS" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS key-events"
- AC_DEFINE(WCM_KEY_SENDING_SUPPORT, 1,
- [The X-driver can send key events for a button])
- fi
-
- dnl Only Xorg has progressed >= 1.0
- AC_DEFINE(WCM_XINPUTABI_MAJOR, 0,
- [Slightly diffent abi in XINPUT >= 1.0])
+ AC_MSG_RESULT(missing input.h)
+ AC_MSG_ERROR("Unable to find $WAC_KERNELDIR/include/linux/input.h")
fi
-fi
-if test "$WCM_ENV_XFREE86" = yes; then
- AM_CONDITIONAL(WCM_ENV_XFREE86, true)
- AC_DEFINE(WCM_XFREE86,1,[Compiling for XFree86])
- AC_MSG_CHECKING([if XFREE86 defines dixScreenOrigins])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XFREE86_DIR/programs/Xserver/include -I$WCM_XFREE86_DIR/include $CFLAGS"
- AC_TRY_COMPILE([#include <globals.h>], [return dixScreenOrigins[0].x;],
- [WCM_HAVE_DIXSCREENORIGINS=yes], [WCM_HAVE_DIXSCREENORIGINS=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_HAVE_DIXSCREENORIGINS)
- if test "$WCM_HAVE_DIXSCREENORIGINS" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS dixScreenOrigins"
- AC_DEFINE(WCM_HAVE_DIXSCREENORIGINS,1,
- [Later XFree86 version uses dixScreenOrigins for screen positions and sizes])
- fi
-else
- AM_CONDITIONAL(WCM_ENV_XFREE86, false)
-fi
-
-dnl Check for X.org SDK
-if test "$WCM_ENV_XFREE86" != yes; then
- AC_ARG_WITH(xorg-sdk,
- AS_HELP_STRING([--with-xorg-sdk=dir], [Specify Xorg SDK directory]),
- WCM_XORGSDK_DIR="$withval")
-
- if test "$WCM_XORGSDK_DIR" = "yes" -o -z "$WCM_XORGSDK_DIR"; then
- PKG_CHECK_MODULES(XSERVER,[xorg-server],
- [
- dnl Found it with pkg-config, use that information
- WCM_ENV_XORGSDK=yes
- WCM_XORGSDK_DIR="`$PKG_CONFIG --variable=sdkdir xorg-server`"
- WCM_XORGSDK_VER="`$PKG_CONFIG --modversion xorg-server`"
- ],
- [
- AC_MSG_CHECKING(for valid Xorg SDK)
- WCM_XORGSDK_DEFAULT="$WCM_XLIB_DIR/Server"
- test -d "$WCM_XORGSDK_DEFAULT" || WCM_XORGSDK_DEFAULT="/usr"
- for a in include include/xorg xc/include; do
- if test -f $WCM_XORGSDK_DEFAULT/$a/xf86Version.h; then
- WCM_ENV_XORGSDK=yes
- WCM_XORGSDK_DIR=$WCM_XORGSDK_DEFAULT/$a
- AC_MSG_RESULT([found, $WCM_XORGSDK_DIR])
- break
- fi
- done
- if test -z "$WCM_XORGSDK_DIR"; then
- AC_MSG_RESULT("xf86Version.h missing")
- AC_MSG_RESULT([Tried $WCM_XORGSDK_DEFAULT/include, $WCM_XORGSDK_DEFAULT/include/xorg, and $WCM_XORGSDK_DEFAULT/xc/include])
- fi
- ])
- elif test "$WCM_XORGSDK_DIR" != "no"; then
- AC_MSG_CHECKING(for valid Xorg SDK)
- if test -f $WCM_XORGSDK_DIR/xf86Version.h; then
- AC_MSG_RESULT(ok)
- WCM_ENV_XORGSDK=yes
- else
- AC_MSG_ERROR("provided path for Xorg SDK invalid")
- fi
- fi
- if test -n "$WCM_XORGSDK_DIR"; then
- AC_DEFINE(WCM_XORG,1,[Compiling for X.org])
- AC_MSG_CHECKING([for xserver libc-wrapper header-files])
- if test -f "$WCM_XORGSDK_DIR/xf86_libc.h"; then
- AC_MSG_RESULT(yes)
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS libc-wrapper"
- else
- AC_MSG_RESULT(no)
- AC_DEFINE(WCM_NO_LIBCWRAPPER,1,[The xserver have no wraps around libc-functions])
- fi
-
- WCM_TABLET_SCALING=
- AC_ARG_ENABLE(quirk-tablet-rescale,
- AC_HELP_STRING([--enable-quirk-tablet-rescale],
- [Enable tablet to screen rescale code [[default=when_needed]]]),
- WCM_TABLET_SCALING=$enableval)
- if test -z "$WCM_TABLET_SCALING"; then
- AC_MSG_CHECKING([if scaling tablet to screen size is needed])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS"
- AC_TRY_COMPILE([
-#include <xorg-server.h>
-#include <xorgVersion.h>
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 4, 0, 0, 0)
-# error "X.org < 1.4 doesn't need rescaling code"
-#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 4, 1, 0, 0)
-# error "X.org >= 1.4.1 doesn't need rescaling code"
-#endif
-], , [WCM_TABLET_SCALING=yes], [WCM_TABLET_SCALING=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_TABLET_SCALING)
- fi
- if test "$WCM_TABLET_SCALING" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS tablet-screen-scaling"
- AC_DEFINE(WCM_XORG_TABLET_SCALING,1,
- [Some X.org versions require that the events are scaled to screen size])
- fi
- WCM_UNINIT_CALLED=
- AC_ARG_ENABLE(quirk-Uninit-called,
- AC_HELP_STRING([--enable-quirk-Uninit-called],
- [Enable Uninit called [[default=when_needed]]]),
- WCM_UNINIT_CALLED=$enableval)
- if test -z "$WCM_UNINIT_CALLED"; then
- AC_MSG_CHECKING([if Uninit is called])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS"
- AC_TRY_COMPILE([
-#include <xorg-server.h>
-#include <xorgVersion.h>
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 4, 0, 0, 0)
-# error "Xserver < 1.4 doesn't call Uninit"
-#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(6, 0, 0, 0, 0)
-# error "X.org < 7.3 doesn't call Uninit"
-#endif
-], , [WCM_UNINIT_CALLED=yes], [WCM_UNINIT_CALLED=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_UNINIT_CALLED)
- fi
- if test "$WCM_UNINIT_CALLED" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS Uninit-called"
- AC_DEFINE(WCM_XORG_XSERVER_1_4,1,
- [Xserver versions 1.4 and later call Uninit before closing a device])
- fi
- AC_MSG_CHECKING([if Xorg is version 1.6 or later])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS"
- AC_TRY_COMPILE([
-#include <xorg-server.h>
-#include <xorgVersion.h>
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 6, 0, 0, 0)
-# error "X.org < 1.6 doesn't need new routines"
-#endif
-], , [WCM_XORG_XSERVER_1_6=yes], [WCM_XORG_XSERVER_1_6=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_XORG_XSERVER_1_6)
- if test "$WCM_XORG_XSERVER_1_6" = "yes"; then
- AC_DEFINE(WCM_XORG_XSERVER_1_6, 1,
- [Using version 1.6 or later of X.org])
- fi
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS"
- AC_TRY_COMPILE([
-#include <X11/extensions/XI.h>
-#ifndef IsXExtensionPointer
-# error "X.org SDK does not define IsXExtensionPointer"
-#endif
-], , [WCM_ISXEXTENSIONPOINTER=yes], [WCM_ISXEXTENSIONPOINTER=no])
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_ISXEXTENSIONPOINTER)
- if test "$WCM_ISXEXTENSIONPOINTER" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS IsXExtensionPointer"
- AC_DEFINE(WCM_ISXEXTENSIONPOINTER,1,
- [IsXExtensionPointer is only defined in later X.org releases])
- fi
-
- dnl All X.org versions support sending key-events
- AC_DEFINE(WCM_KEY_SENDING_SUPPORT, 1,
- [The X-driver can send key events for a button])
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS key-events"
-
- AC_MSG_CHECKING([if Xorg SDK defines dixScreenOrigins])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XORGSDK_DIR $XSERVER_CFLAGS $CFLAGS"
- AC_TRY_COMPILE([#include <globals.h>], [return dixScreenOrigins[0].x;],
- [WCM_HAVE_DIXSCREENORIGINS=yes], [WCM_HAVE_DIXSCREENORIGINS=no])
- AC_TRY_COMPILE([
-#include <xorg-server.h>
-#include <xorgVersion.h>
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(0, 0, 0, 0, 0)
-# error "Invalid X.org version"
-#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(8, 0, 0, 0, 0)
-# error "Invalid X.org version"
-#endif
-], , [WCM_INVALID_ORIGINS=no], [WCM_INVALID_ORIGINS=yes])
- # Xorg 6.8.x doesn't support dixScreenOrigins. But globals.h included it.
- # And its XORG_VERSION_CURRENT is invalid somehow.
- if test "$WCM_INVALID_ORIGINS" = "yes"; then
- WCM_HAVE_DIXSCREENORIGINS=no
- fi
- CFLAGS="$save_CFLAGS"
- AC_MSG_RESULT($WCM_HAVE_DIXSCREENORIGINS)
- if test "$WCM_HAVE_DIXSCREENORIGINS" = "yes"; then
- WCM_XDRIVER_QUIRKS="$WCM_XDRIVER_QUIRKS dixScreenOrigins"
- AC_DEFINE(WCM_HAVE_DIXSCREENORIGINS,1,
- [Later X.org version uses dixScreenOrigins for screen positions and sizes])
- fi
-
- AC_MSG_CHECKING([XInput extension version])
- save_CFLAGS="$CFLAGS"
- CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS"
- AC_TRY_COMPILE([
-#include <xf86Module.h>
-#if ABI_XINPUT_VERSION < SET_ABI_VERSION(1, 0)
-# error "XInput extension < 1.0"
-#endif
-], , [WCM_XINPUT_MAJOR=1], [WCM_XINPUT_MAJOR=0])
- if test "$WCM_XINPUT_MAJOR" = "0"; then
- AC_MSG_RESULT([< 1.0])
- AC_DEFINE(WCM_XINPUTABI_MAJOR, 0,
- [Slightly diffent abi in XINPUT >= 1.0])
+],
+[
+ dnl guess directory
+ AC_MSG_CHECKING(for kernel sources)
+ WAC_KERNELDIR="/usr/src/linux-2.4"
+ if test -f "$WAC_KERNELDIR/include/linux/input.h"; then
+ WAC_ENV_KERNEL=yes
+ AC_MSG_RESULT($WAC_KERNELDIR)
+ else
+ WAC_KERNELDIR="/usr/src/linux"
+ if test -f "$WAC_KERNELDIR/include/linux/input.h"; then
+ WAC_ENV_KERNEL=yes
+ AC_MSG_RESULT($WAC_KERNELDIR)
else
- AC_TRY_COMPILE([
-#include <xf86Module.h>
-#if ABI_XINPUT_VERSION < SET_ABI_VERSION(2, 0)
-# error "XInput extension < 2.0"
-#endif
-], , [WCM_XINPUT_MAJOR=2], [WCM_XINPUT_MAJOR=1])
- if test "$WCM_XINPUT_MAJOR" = "1"; then
- AC_MSG_RESULT([>= 1.0 && < 2.0])
- AC_DEFINE(WCM_XINPUTABI_MAJOR, 1,
- [Slightly diffent abi in XINPUT >= 1.0])
- else
- AC_MSG_RESULT([>= 2.0])
- AC_DEFINE(WCM_XINPUTABI_MAJOR, 2,
- [Slightly diffent abi in XINPUT >= 1.0])
- fi
- fi
- CFLAGS="$save_CFLAGS"
-
- dnl Try to get rid of a few warnings, X.org 1.4 need c99
- case "$WCM_XORGSDK_VER" in
- 1.0*|1.1*|1.2*|1.3*)
- ;;
- 1.*|2*)
- WCM_CLEVEL=-std=c99;;
- *)
- ;;
- esac
- fi
-fi
-AM_CONDITIONAL(WCM_ENV_XORGSDK, [test "$WCM_ENV_XORGSDK" = yes])
-
-AC_MSG_CHECKING(for lib xf86config)
-if test -f $WCM_XLIB_DIR/libxf86config.a -o -f $WCM_XLIB_DIR/libxf86config.so; then
- if test -f $WCM_XFREE86_DIR/$XFREE86SUBDIR/xf86Parser.h; then
- AC_MSG_RESULT([found, $WCM_XFREE86_DIR/$XFREE86SUBDIR])
- WCM_ENV_XF86CONFIG=yes
- CFLAGS="$CFLAGS -I$WCM_XFREE86_DIR/$XFREE86SUBDIR"
- elif test -f $WCM_XORGSDK_DIR/xf86Parser.h; then
- AC_MSG_RESULT([found, $WCM_XORGSDK_DIR])
- WCM_ENV_XF86CONFIG=yes
- elif test -f $WCM_XLIB_DIR/../include/xf86Parser.h; then
- AC_MSG_RESULT([found, $WCM_XLIB_DIR/../include])
- WCM_ENV_XF86CONFIG=yes
- CFLAGS="$CFLAGS -I$WCM_XLIB_DIR/../include"
- fi
-fi
-
-if test "$WCM_ENV_XFREE86" != yes -o "$WCM_XORG_XSERVER_1_4" != yes; then
- PKG_CHECK_MODULES(XORG, [xorg-server])
- AC_SUBST([XORG_CFLAGS])
-fi
-
-# Define X_CFLAGS, X_LIBS, X_EXTRA_LIBS and X_PRELIBS as required if X
-# is found, else defines X_DISPLAY_MISSING. We need at least X_CFLAGS.
-AC_PATH_XTRA
-
-dnl =======================================================
-dnl Check for TCL development environment
-WCM_ENV_TCL=no
-WCM_TCL_DIR=
-WCM_TCL_CFLAGS=
-dnl get tcl version
-AC_PATH_PROG([TCLSH],[tclsh],[no])
-if test "x$TCLSH" != "xno"; then
- AC_MSG_CHECKING([for tcl version])
- version=$(echo ["puts [set tcl_version]"] | $TCLSH)
- AC_MSG_RESULT([$version])
-fi
-
-AC_ARG_WITH(tcl,
- AS_HELP_STRING([--with-tcl=dir], [uses the specified tcl directory]),
- [ WCM_TCL_DIR=$withval ])
-if test "$WCM_TCL_DIR" = yes -o -z "$WCM_TCL_DIR"; then
- AC_MSG_CHECKING([for tcl header files])
- for i in /usr/include /usr/include/tcl "/usr/include/tcl$version"; do
- if test -f "$i/tcl.h"; then
- AC_MSG_RESULT([found, $i])
- WCM_ENV_TCL=yes
- WCM_TCL_DIR="$i"
- WCM_TCL_CFLAGS="-I$WCM_TCL_DIR"
- CFLAGS="$CFLAGS $WCM_TCL_CFLAGS"
- break
- fi
- done
- if test "$WCM_ENV_TCL" != yes; then
- AC_MSG_WARN([not found; tried /usr/include, tcl, and tcl$version; ])
- fi
-elif test "$WCM_TCL_DIR" != no; then
- AC_MSG_CHECKING([for tcl header files])
- for i in include .; do
- if test -f "$WCM_TCL_DIR/$i/tcl.h"; then
- AC_MSG_RESULT([found, ])
- WCM_ENV_TCL=yes
- if test "$WCM_TCL_DIR" != "/usr"; then
- WCM_TCL_CFLAGS="-I$WCM_TCL_DIR/$i"
- CFLAGS="$CFLAGS $WCM_TCL_CFLAGS"
- fi
- fi
- done
- if test "$WCM_ENV_TCL" != yes; then
- AC_MSG_RESULT([not found; tried $WCM_TCL_DIR/include/tcl.h and $WCM_TCL_DIR/tcl.h])
- WCM_TCL_DIR=
- fi
-fi
-if test "$WCM_ENV_TCL" != yes; then
- echo "***"
- echo "*** The tcl development environment can not be found."
- echo "*** The header file tcl.h does not appear at the normal"
- echo "*** (or provided) include path. Some build features"
- echo "*** will be unavailable."
- echo "***"
-fi
-
-dnl =======================================================
-dnl Check for TK development environment
-WCM_ENV_TK=no
-WCM_TK_DIR=
-WCM_TK_CFLAGS=
-AC_ARG_WITH(tk,
- AS_HELP_STRING([--with-tk=dir], [uses a specified tk directory ]),
- [ WCM_TK_DIR=$withval ])
-if test "$WCM_TK_DIR" = yes -o -z "$WCM_TK_DIR"; then
- AC_MSG_CHECKING([for tk header files])
- for i in $WCM_TCL_DIR /usr/include ; do
- if test -f "$i/tk.h"; then
- AC_MSG_RESULT([found, $i])
- WCM_ENV_TK=yes
- WCM_TK_DIR="$i"
- if test "$WCM_TCL_DIR" != "$WCM_TK_DIR" -a "$WCM_TK_DIR" != "/usr"; then
- WCM_TK_CFLAGS="-I$WCM_TK_DIR"
- CFLAGS="$CFLAGS $WCM_TK_CFLAGS"
- fi
- break
- fi
- done
- if test "$WCM_ENV_TK" != yes; then
- AC_MSG_WARN([not found; tried $WCM_TCL_DIR/tk.h and /usr/include/tk.h])
- fi
-elif test "$WCM_TK_DIR" != no; then
- AC_MSG_CHECKING([for tk header files])
-
- for i in "$WCM_TK_DIR/include" "$WCM_TK_DIR"; do
- if test -f "$i/tk.h"; then
- AC_MSG_RESULT([found, $i])
- WCM_ENV_TK=yes
- WCM_TK_DIR="$i"
- if test "$WCM_TCL_DIR" != "$WCM_TK_DIR" -a "$WCM_TK_DIR" != "/usr"; then
- WCM_TK_CFLAGS="-I$WCM_TK_DIR"
- CFLAGS="$CFLAGS $WCM_TK_CFLAGS"
- fi
- break
+ AC_MSG_RESULT(not found)
+ echo "***"
+ echo "*** WARNING:"
+ echo "*** Unable to guess kernel source directory"
+ echo "*** Looked at /usr/src/linux-2.4"
+ echo "*** Looked at /usr/src/linux"
+ echo "*** Kernel modules will not be built"
+ echo "***"
fi
- done
- if test "$WCM_ENV_TK" != yes; then
- AC_MSG_WARN([not found; tried $WCM_TK_DIR/tk.h and $WCM_TK_DIR/include/tk.h])
- WCM_TK_DIR=
fi
-fi
-if test "$WCM_ENV_TK" != yes; then
- echo "***"
- echo "*** The tk development environment can not be found."
- echo "*** The header file tk.h does not appear at the normal"
- echo "*** (or provided) include path. Some build features"
- echo "*** will be unavailable."
- echo "***"
-fi
-
-dnl =======================================================
-dnl Check for ncurses development environment
-WCM_ENV_NCURSES=no
-AC_CHECK_HEADER(ncurses.h, [WCM_ENV_NCURSES=yes])
-if test "$WCM_ENV_NCURSES" != yes; then
- AC_CHECK_HEADER(ncurses/ncurses.h, [WCM_ENV_NCURSES=yes])
-fi
-if test "$WCM_ENV_NCURSES" != yes; then
- AC_MSG_WARN([ncurses not available, ncurses UI disabled])
- AC_DEFINE(WCM_ENABLE_NCURSES,0,[ncurses header files available])
- AM_CONDITIONAL(WCM_ENV_NCURSES, false)
-else
- AC_DEFINE(WCM_ENABLE_NCURSES,1,[ncurses header files available])
- AM_CONDITIONAL(WCM_ENV_NCURSES, true)
-fi
+])
-dnl =======================================================
-dnl Check for libwacomcfg build
-AC_MSG_CHECKING([if libwacomcfg should/can be built])
-WCM_OPTION_LIBWACOMCFG=no
-AC_ARG_ENABLE(libwacomcfg,
- AC_HELP_STRING([--enable-libwacomcfg], [Enable building libwacomcfg [[default=yes]]]),
- , enable_libwacomcfg=yes)
-if test "$enable_libwacomcfg" != no; then
- if test "$WCM_ENV_XLIB" = yes; then
- AC_MSG_RESULT(yes)
- WCM_OPTION_LIBWACOMCFG=yes
- WCM_LIBWACOMCFG_LIBS="-L$WCM_XLIB_DIR -lX11 -lXi"
- WCM_LIBS="$WCM_LIBS libwacomcfg.la"
- if test "$WCM_ENV_XF86CONFIG" = yes; then
- AC_DEFINE(WCM_XF86CONFIG,1,[libxf86config is included])
- WCM_LIBWACOMCFG_LIBS="$WCM_LIBWACOMCFG_LIBS -lxf86config -lm"
- else
- AC_DEFINE(WCM_XF86CONFIG,0,[libxf86config isn't included])
- fi
+dnl Check for XFree86 build environment
+WAC_ENV_XF86=no
+AC_ARG_WITH(xf86,
+[ --with-xf86=dir Specify XF86 build directory],
+[
+ WAC_XF86DIR="$withval";
+ AC_MSG_CHECKING(for valid XFree86 build environment)
+ if test -f $WAC_XF86DIR/$XF86SUBDIR/include/xf86Version.h; then
+ WAC_ENV_XF86=yes
+ AC_MSG_RESULT(ok)
else
- AC_MSG_WARN([XLib environment missing, libwacomcfg not built])
+ AC_MSG_RESULT("xf86Version.h missing")
+ AC_MSG_ERROR("Unable to find $WAC_XF86DIR/$XF86SUBDIR/include/xf86Version.h")
fi
-else
- AC_MSG_RESULT(no)
-fi
+ WAC_XF86DIR=`(cd $WAC_XF86DIR; pwd)`
+])
-dnl =======================================================
-dnl Check for libwacomxi build
-AC_MSG_CHECKING([if libwacomxi should/can be built])
-WCM_TCLLIBS=
-WCM_TCLPKGS=
-WCM_OPTION_LIBWACOMXI=no
-AC_ARG_ENABLE(libwacomxi,
- AC_HELP_STRING([--enable-libwacomxi], [Enable building libwacomxi [[default=yes]]]),
- , enable_libwacomxi=yes)
-if test "$enable_libwacomxi" != no; then
- if test "$WCM_ENV_XLIB" != yes; then
- AC_MSG_WARN([XLib environment missing, libwacomxi not built])
- elif test "$WCM_ENV_TCL" != yes; then
- AC_MSG_WARN([tcl environment missing, libwacomxi not built])
- elif test "$WCM_ENV_TK" != yes; then
- AC_MSG_WARN([tk environment missing, libwacomxi not built])
+dnl Check for wacom build
+WAC_OPTION_WACOM=no
+AC_ARG_ENABLE(wacom,
+[ --enable-wacom Enable building wacom.o default=yes],
+ , enable_wacom=yes)
+if test "$enable_wacom" != "no"; then
+ if test "$WAC_ENV_KERNEL" != "yes"; then
+ echo "***"; echo "*** WARNING:";
+ echo "*** Unable to compile wacom.o without kernel build environment"
+ echo "*** wacom.o will not be built"
+ echo "***"
else
- AC_MSG_RESULT(yes)
- WCM_OPTION_LIBWACOMXI=yes
- WCM_WACOMXI_LIBS="-L$WCM_XLIB_DIR -lX11 -lXi"
- WCM_TCLLIBS="libwacomxi.la"
- WCM_TCLPKGS="pkgIndex.tcl"
+ WAC_OPTION_WACOM=yes
+ WAC_MODULES="$WAC_MODULES wacom.o"
fi
-else
- AC_MSG_RESULT(no)
fi
-AM_CONDITIONAL(WACOMXI_INSTALL, [test "$WCM_OPTION_LIBWACOMXI" = yes] )
-dnl =======================================================
dnl Check for wacdump build
-AC_MSG_CHECKING([if wacdump should/can be built])
-WCM_OPTION_WACDUMP=no
+WAC_OPTION_WACDUMP=no
AC_ARG_ENABLE(wacdump,
- AC_HELP_STRING([--enable-wacdump], [Enable building wacdump [[default=yes]]]),
+[ --enable-wacdump Enable building wacdump default=yes],
, enable_wacdump=yes)
if test "$enable_wacdump" != "no"; then
- if test "$WCM_ENV_NCURSES" = yes; then
- AC_MSG_RESULT(yes)
- WCM_OPTION_WACDUMP=yes
- WCM_PROGS="$WCM_PROGS wacdump"
+ WAC_OPTION_WACDUMP=yes
+ WAC_PROGS="$WAC_PROGS wacdump"
+fi
+
+dnl Check for hid build
+WAC_OPTION_HID=no
+AC_ARG_ENABLE(hid,
+[ --enable-hid Enable building hid.o default=no],
+ , enable_hid=no)
+if test "$enable_hid" != "no"; then
+ if test "$WAC_ENV_KERNEL" != "yes"; then
+ echo "***"; echo "*** WARNING:";
+ echo "*** Unable to compile hid.o without kernel build environment"
+ echo "*** hid.o will not be built"
+ echo "***"
else
- AC_MSG_WARN([ncurses environment missing, wacdump not built])
+ WAC_OPTION_HID=yes
+ WAC_MODULES="$WAC_MODULES hid.o"
fi
fi
-dnl =======================================================
-dnl Check for xidump build
-AC_MSG_CHECKING([if xidump should/can be built])
-WCM_PATCH_XIDUMP=
-WCM_OPTION_XIDUMP=no
-AC_ARG_ENABLE(xidump,
- AC_HELP_STRING([--enable-xidump], [Enable building xidump [[default=yes]]]),
- , enable_xidump=yes)
-if test "$enable_xidump" != "no"; then
- if test "$WCM_ENV_XLIB" != yes; then
- AC_MSG_WARN([XLib environment missing, xidump not built])
+dnl Check for usbmouse build
+WAC_OPTION_USBMOUSE=no
+AC_ARG_ENABLE(usbmouse,
+[ --enable-usbmouse Enable building usbmouse.o default=no],
+ , enable_usbmouse=no)
+if test "$enable_usbmouse" != "no"; then
+ if test "$WAC_ENV_KERNEL" != "yes"; then
+ echo "***"; echo "*** WARNING:";
+ echo "*** Unable to compile usbmouse.o without kernel build environment"
+ echo "*** usbmouse.o will not be built"
+ echo "***"
else
- if test "$WCM_ENV_NCURSES" != yes; then
- AC_MSG_RESULT([yes, no ncurses])
- WCM_PATCH_XIDUMP="(no ncurses)"
- else
- AC_MSG_RESULT(yes)
- fi
- WCM_OPTION_XIDUMP=yes
- WCM_XIDUMP_LIBS="-L$WCM_XLIB_DIR -lX11 -lXi -lm"
- WCM_PROGS="$WCM_PROGS xidump"
+ WAC_OPTION_USBMOUSE=yes
+ WAC_MODULES="$WAC_MODULES usbmouse.o"
fi
-else
- AC_MSG_RESULT(no)
fi
-dnl =======================================================
-dnl Check for xsetwacom build
-AC_MSG_CHECKING([if xsetwacom should be built])
-WCM_OPTION_XSETWACOM=no
-AC_ARG_ENABLE(xsetwacom,
- AC_HELP_STRING([--enable-xsetwacom], [Enable building xsetwacom [[default=yes]]]),
- , enable_xsetwacom=yes)
-if test "$enable_xsetwacom" != "no"; then
- if test "$WCM_OPTION_LIBWACOMCFG" != yes; then
- AC_MSG_WARN([requires libwacomcfg, xsetwacom not built])
+dnl Check for wacomdrv build
+WAC_OPTION_WACOMDRV=no
+AC_ARG_ENABLE(wacomdrv,
+[ --enable-wacomdrv Enable building wacom_drv.o default=no],
+ , enable_wacomdrv=no)
+if test "$enable_wacomdrv" != "no"; then
+ if test "$WAC_ENV_XF86" != "yes"; then
+ echo "***"; echo "*** WARNING:";
+ echo "*** Unable to compile wacom_drv.o without XF86 build environment"
+ echo "*** wacom_drv.o will not be built"
+ echo "***"
else
- AC_MSG_RESULT(yes)
- WCM_OPTION_XSETWACOM=yes
- WCM_XSETWACOM_LIBS="-L$WCM_XLIB_DIR -lX11 -lXi"
- WCM_PROGS="$WCM_PROGS xsetwacom"
+ WAC_OPTION_WACOMDRV=yes
+ WAC_XF86MODULES="$WAC_XF86MODULES wacom_drv.o"
+ WAC_EXPMODULES="$WAC_EXPMODULES wacom_drv.o"
fi
fi
-dnl =======================================================
-dnl Check for xmoduledir
-AC_MSG_CHECKING(for Wacom X driver module path)
-WCM_MODDIR=
-AC_ARG_WITH(xmoduledir,
- AC_HELP_STRING([--with-xmoduledir], [Specify wacom_drv path explicitly. Implies --enable-dlloader]),
- WCM_MODDIR="$withval")
-if test -z "$WCM_MODDIR"; then
- if test -d $WCM_XLIB_DIR/xorg/modules/input; then
- WCM_MODDIR=$WCM_XLIB_DIR/xorg/modules/input
- elif test -d $WCM_XLIB_DIR/modules/input; then
- WCM_MODDIR=$WCM_XLIB_DIR/modules/input
- fi
-fi
-AC_MSG_RESULT($WCM_MODDIR)
+dnl Check for arch
+AC_ARG_WITH(arch,
+[ --with-arch Use specified architecture],
+[
+ WAC_ARCH=$withval
+])
-dnl =======================================================
-dnl Check for dlloader
-AC_MSG_CHECKING(for dynamic driver loading support)
-if test -n "$WCM_MODDIR"; then
- WCM_OPTION_DLLOADER=yes
+dnl Check for modver
+AC_ARG_ENABLE(modver,
+[ --enable-modver Enable kernel module versioning default=usually],
+ , enable_modver=$WAC_MODVER)
+if test "$enable_modver" = "no"; then
+ WAC_OPTION_MODVER=no
+ WAC_MODVER=""
+elif test "$enable-modver" = "yes"; then
+ WAC_OPTION_MODVER=yes
+ WAC_MODVER="-DCONFIG_MODVERSIONS"
else
- WCM_OPTION_DLLOADER=no
-fi
-AC_ARG_ENABLE(dlloader,
- AC_HELP_STRING([--enable-dlloader], [Use dlloader [[default=usually]]]),
- WCM_OPTION_DLLOADER=$enableval)
-#don't enable dlloader when there is a wacom_drv.o under $WCM_MODDIR
-if test "$WCM_OPTION_DLLOADER" = yes; then
- if test -f $WCM_MODDIR/wacom_drv.o; then
- WCM_OPTION_DLLOADER=no
- fi
+ dnl not explicitly set, go with default
+ WAC_MODVER=""
fi
-AC_MSG_RESULT($WCM_OPTION_DLLOADER)
-AM_CONDITIONAL(WCM_DLLOADER, test "$WCM_OPTION_DLLOADER" = "yes")
-dnl =======================================================
-dnl Check for wacomdrv build
-AC_MSG_CHECKING([if wacom_drv.{o,so} should be compiled])
-WCM_OPTION_WACOMDRV=yes
-AC_ARG_ENABLE(wacomdrv,
- AC_HELP_STRING([--enable-wacomdrv], [Enable building wacom_drv.{o,so} [[default=yes]]]),
- WCM_OPTION_WACOMDRV=$enableval)
-if test "$WCM_OPTION_WACOMDRV" != "no"; then
- if test "$WCM_ENV_XFREE86" != "yes" -a "$WCM_ENV_XORGSDK" != "yes"; then
- AC_MSG_WARN([requires Xorg SDK or XFree86 build environment, wacom_drv not built])
- WCM_OPTION_WACOMDRV=no
- else
- AC_MSG_RESULT(yes)
- WCM_OPTION_WACOMDRV=yes
- if test "$WCM_OPTION_DLLOADER" = "yes" ; then
- WCM_XF86MODULES="wacom_drv.so"
+dnl Check for changed field names in hid-core.c
+if test "$WAC_OPTION_HID" = "yes"; then
+ AC_MSG_CHECKING(for updated field names in hid-core.c)
+ HIDCORE="$WAC_KERNELDIR/drivers/usb/hid-core.c"
+ if test -f "$HIDCORE"; then
+ PATCH_DRVALUE=`grep 'dr\\.wValue' "$HIDCORE" | wc -l`
+ if test "$PATCH_DRVALUE" -gt 0; then
+ AC_MSG_RESULT([yes, using 2.4.20])
+ AC_DEFINE(WAC_PATCH_DRVALUE,1,[Need the dr.wValue patch])
+ WAC_PATCH_HID="(value_patch) $WAC_PATCH_HID"
else
- WCM_XF86MODULES="wacom_drv.o"
+ AC_MSG_RESULT([no, using 2.4.19])
+ AC_DEFINE(WAC_PATCH_DRVALUE,0,[Do not need the dr.wValue patch])
fi
+ else
+ AC_MSG_RESULT([missing, using 2.4.19])
+ AC_DEFINE(WAC_PATCH_DRVALUE,0,[Do not need the dr.wValue patch])
+ echo "***"
+ echo "*** Warning: unable to find hid-core.c in kernel tree"
+ echo "*** It was not possible to detect whether patches needed to be"
+ echo "*** applied. If the hid-core.c in this project does not build"
+ echo "*** correctly, you should resolve this problem first."
+ echo "***"
fi
-else
- AC_MSG_RESULT(no)
-fi
-
-dnl =======================================================
-dnl Check for depflags
-WCM_DEPFLAGS=
-AC_ARG_ENABLE(mkxincludes,
- AC_HELP_STRING([--enable-mkxincludes], [Enable mkxincludes, XFree86 dependency builder [[default=no]]]),
- [ test "$enable_mkxincludes" = yes && WCM_DEPFLAGS="-MMD" ])
-
-dnl =======================================================
-dnl Check for compiler flags if using gcc
-if test "$GCC" = yes; then
- OLD_CFLAGS="$CFLAGS"
- AC_MSG_CHECKING(if gcc accepts -fno-merge-constants)
- CFLAGS="$OLD_CFLAGS -fno-merge-constants"
- AC_TRY_COMPILE(, "int main(void) { return 0; }",
- [WCM_NO_MERGE_CONSTANTS="-fno-merge-constants"; AC_MSG_RESULT(yes)],
- [WCM_NO_MERGE_CONSTANTS=; AC_MSG_RESULT(no)])
-
- AC_MSG_CHECKING(if gcc accepts -fno-stack-protector)
- CFLAGS="$OLD_CFLAGS -fno-stack-protector"
- AC_TRY_COMPILE(, "int main(void) { return 0; }",
- [WCM_NO_STACK_PROTECTOR="-fno-stack-protector"; AC_MSG_RESULT(yes)],
- [WCM_NO_STACK_PROTECTOR=; AC_MSG_RESULT(no)])
- CFLAGS=$OLD_CFLAGS
fi
-dnl =======================================================
-dnl Set default defines in src/include/xdrv-config.h (moved from cmd-line)
-AC_DEFINE(IN_MODULE,,[cmdline substitute])
-AC_DEFINE(XFree86LOADER,,[cmdline substitute])
-AC_DEFINE(XINPUT,,[cmdline substitute])
-AC_DEFINE(XKB,,[cmdline substitute])
+AC_SUBST(WAC_PROGS)
+AC_SUBST(WAC_MODULES)
+AC_SUBST(WAC_XF86PROGS)
+AC_SUBST(WAC_XF86MODULES)
+AC_SUBST(WAC_EXPPROGS)
+AC_SUBST(WAC_EXPMODULES)
+AC_SUBST(WAC_ARCH)
+AC_SUBST(WAC_MODVER)
+AC_SUBST(WAC_KERNELDIR)
+AC_SUBST(WAC_XF86DIR)
-dnl Separate test output from file-generation output
-echo
-
-AC_SUBST(WCM_PROGS)
-AC_SUBST(WCM_LIBS)
-AC_SUBST(WCM_TCLLIBS)
-AC_SUBST(WCM_TCLPKGS)
-AC_SUBST(WCM_MODULES)
-AC_SUBST(WCM_XF86MODULES)
-AC_SUBST(WCM_ARCH)
-AC_SUBST(WCM_KSTACK)
-AC_SUBST(WCM_MODVER)
-AC_SUBST(WCM_KERNEL_DIR)
-AC_SUBST(WCM_KERNEL_VER)
-AC_SUBST(WCM_XFREE86_DIR)
-AC_SUBST(WCM_XORGSDK_DIR)
-AC_SUBST(WCM_MODDIR)
-AC_SUBST(WCM_XSERVER64)
-AC_SUBST(WCM_NO_MERGE_CONSTANTS)
-AC_SUBST(WCM_NO_STACK_PROTECTOR)
-AC_SUBST(WCM_CLEVEL)
-AC_SUBST(WCM_XIDUMP_LIBS)
-AC_SUBST(WCM_LIBWACOMCFG_LIBS)
-AC_SUBST(WCM_WACOMXI_LIBS)
-AC_SUBST(WCM_PREFIX)
-AC_SUBST(WCM_XSETWACOM_LIBS)
-AC_SUBST(WCM_DEPFLAGS)
-AC_SUBST(WCM_OPTION_WACOM)
-AC_SUBST(WCM_OPTION_HID)
-
-AC_OUTPUT(Makefile
- mkxincludes
- src/Makefile
- src/util/Makefile
- src/xdrv/Makefile
- src/2.6.9/Makefile
- src/2.6.10/Makefile
- src/2.6.11/Makefile
- src/2.6.13/Makefile
- src/2.6.14/Makefile
- src/2.6.15/Makefile
- src/2.6.16/Makefile
- src/2.6.18/Makefile
- src/2.6.19/Makefile
- src/2.6.22/Makefile
- src/2.6.24/Makefile
- src/2.6.26/Makefile
- src/2.6.27/Makefile
- src/2.6.28/Makefile
- src/2.6.31/Makefile
- src/wacomxi/Makefile
- src/wacomxi/wacomcpl)
+AC_OUTPUT(Makefile src/Makefile)
echo ""
echo "----------------------------------------"
echo " BUILD ENVIRONMENT:"
-echo " architecture - $WCM_ARCHITECTURE"
-echo " linux kernel - $WCM_ISLINUX $WCM_KERNEL_VER"
-echo " module versioning - $WCM_OPTION_MODVER $WCM_MODVER"
-echo " kernel source - $WCM_ENV_KERNEL $WCM_KERNEL_DIR"
-echo " XFree86 source - $WCM_ENV_XFREE86 $WCM_XFREE86_DIR"
-echo " Xorg SDK - $WCM_ENV_XORGSDK $WCM_XORGSDK_DIR"
-echo " XSERVER64 - $WCM_OPTION_XSERVER64"
-echo " dlloader - $WCM_OPTION_DLLOADER"
-echo " XLib - $WCM_ENV_XLIB $WCM_XLIB_DIR"
-echo " xf86config - $WCM_ENV_XF86CONFIG"
-echo " TCL - $WCM_ENV_TCL $WCM_TCL_DIR"
-echo " TK - $WCM_ENV_TK $WCM_TK_DIR"
-echo " ncurses - $WCM_ENV_NCURSES"
+echo " architecture - $WAC_ARCH"
+echo " module versioning - $WAC_OPTION_MODVER"
+echo " kernel - $WAC_ENV_KERNEL"
+echo " XFree86 - $WAC_ENV_XF86"
echo ""
echo " BUILD OPTIONS:"
-echo " wacom.o - $WCM_OPTION_WACOM"
-echo " wacdump - $WCM_OPTION_WACDUMP $WCM_PATCH_WACDUMP"
-echo " xidump - $WCM_OPTION_XIDUMP $WCM_PATCH_XIDUMP"
-echo " libwacomcfg - $WCM_OPTION_LIBWACOMCFG"
-echo " libwacomxi - $WCM_OPTION_LIBWACOMXI"
-echo " xsetwacom - $WCM_OPTION_XSETWACOM"
-echo " hid.o - $WCM_OPTION_HID $WCM_PATCH_HID"
-if test "$WCM_OPTION_DLLOADER" = "yes" ; then
-echo " wacom_drv.so - $WCM_OPTION_WACOMDRV $WCM_MODDIR $WCM_PATCH_WACOMDRV"
-echo " wacom_drv.o - no"
-else
-echo " wacom_drv.so - no"
-echo " wacom_drv.o - $WCM_OPTION_WACOMDRV $WCM_MODDIR $WCM_PATCH_WACOMDRV"
-fi
-echo " wacom*_drv quirks -$WCM_XDRIVER_QUIRKS"
+echo " wacom.o - $WAC_OPTION_WACOM"
+echo " wacdump - $WAC_OPTION_WACDUMP"
+echo " hid.o - $WAC_OPTION_HID $WAC_PATCH_HID"
+echo " usbmouse.o - $WAC_OPTION_USBMOUSE"
+echo " wacom_drv.o - $WAC_OPTION_WACOMDRV"
echo "----------------------------------------"
diff --git a/docs/docs.html b/docs/docs.html
index 4214b00..adbd29c 100644
--- a/docs/docs.html
+++ b/docs/docs.html
@@ -1,166 +1,439 @@
-<html><head>
-<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
-
-<title>The Linux Wacom Project</title>
-<style><!--
- BODY { background: #FFFFFF; font: 10pt helvetica; color: black }
- .motd { font:12pt helvetica; color: navy }
- .allhead { font: bold 24pt helvetica; }
- .allsub { font: bold 16pt helvetica; }
- .tit { font: bold 24pt helvetica; color: navy }
+<HTML>
+<HEAD>
+<TITLE>John's Linux USB Wacom Page</TITLE>
+</HEAD>
+<STYLE>
.diff { background: #EEEEFF }
.nav { background: #EEEEEE }
- DIV.copy { font: 8pt helvetica; color: gray }
- TD.blkhead { font: bold 10pt helvetica; color: gray }
- TD.blkbody { font: 10pt helvetica; color: black }
- TD.head { background: #000000 }
- .title { font: bold 16pt helvetica; color: white }
- .menu { font: bold 8pt helvetica; color: white; background: #000066 }
- A.menu { text-decoration: none }
- A.menu:link { color: #FFFFFF }
- A.menu:hover { color: #FFFF00 }
- A.copy:link { color: gray }
- A.copy:visited { color: gray }
- /* Support /PRE scalability. For details, refer to */
- /* http://www.longren.org/2006/09/27/wrapping-text-inside-pre-tags */
- pre {
- white-space: pre; /* CSS2 */
- white-space: pre-wrap; /* css 2.1 */
- white-space: pre-line; /* CSS3 (and 2.1 as well, actually) */
- white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
- white-space: -pre-wrap; /* Opera 4-6 */
- white-space: -o-pre-wrap; /* Opera 7 */
- word-wrap: break-word; /* IE 5.5+ */
- /* IE only to re-specify in addition to word-wrap */
- _white-space: pre;
- width: 99%;
- }
---></style>
-</head><body topmargin="0" leftmargin="0" rightmargin="0" marginheight="0" marginwidth="0">
-<table border="0" cellpadding="0" cellspacing="0" width="100%">
-<tbody><tr><td class="head" align="center" valign="middle">
-<div class="title">The Linux Wacom Project </div>
-
-</td><td class="head" align="right" valign="middle" width="125"><a href="http://sourceforge.net/"><img src="docs_files/sflogo.png" alt="SourceForge.net Logo" border="0" height="37" width="125"></a></td></tr>
-</tbody></table>
-<table border="0" cellpadding="0" cellspacing="0" width="100%">
-<tbody><tr><td colspan="2" bgcolor="white"><img src="docs_files/null.gif" height="1" width="1"></td></tr>
-<tr><td colspan="2" bgcolor="#000066"><img src="docs_files/null.gif" height="4" width="1"></td></tr>
-<tr><td class="menu" align="center">
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/main">Main</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/news">News</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/faq">FAQ</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/dl">Downloads</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/help">Help</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://sourceforge.net/projects/linuxwacom">Development</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/toc">TOC</a>&nbsp;&nbsp; |
- &nbsp;&nbsp;<a class="menu" href="http://linuxwacom.sourceforge.net/index.php/all">All</a>&nbsp;&nbsp;
-</td><td class="menu" align="right">Apr 29, 2009</td></tr>
-<tr><td colspan="2" bgcolor="#000066"><img src="docs_files/null.gif" height="4" width="1"></td></tr>
-<tr><td colspan="2" bgcolor="#aaaaaa"><img src="docs_files/null.gif" height="2" width="1"></td></tr>
-</tbody></table>
-
-<br>
-
-<center><table border="0" width="80%"><tbody><tr><td>
-<center><h1>Linux Wacom Project HOWTO</h1></center><br><center class="nav">Navigation:
-<a href="http://linuxwacom.sourceforge.net/index.php/howto/main">MAIN</a>&nbsp;&nbsp;&nbsp;<a href="http://linuxwacom.sourceforge.net/index.php/howto/copy">NEXT</a>&nbsp;&nbsp;&nbsp;<a href="http://linuxwacom.sourceforge.net/index.php/howto/toc">INDEX</a>&nbsp;&nbsp;&nbsp;<a href="http://linuxwacom.sourceforge.net/index.php/howto/all"><b>ALL</b></a>&nbsp;&nbsp;&nbsp;</center><br><br>
-<a name="copy">
-</a><center>
-<a name="copy">Copyright (C) 2002-2009 - LinuxWacom<br>
-<br>
-Permission is granted to copy, distribute and/or modify this document<br>
-under the terms of the GNU GENERAL PUBLIC LICENSE as published by the<br>
-Free Software Foundation; either version 2 of the License, or <br>
-(at your option) any later version. A copy of the license is <br>
-included in the section entitled
-</a><a href="#lic">GNU Free Documentation License</a>.<br>
-</center>
-<br>
-<br>
-<a name="intro">
-</a><h1><a name="intro">1.0 - Introduction</a></h1>
-<p><a name="intro">This document began in November 2002 as a HOWTO for setting up a USB
-Wacom Intuos2 on Redhat 8.0. It has since grown to cover all Wacom
-tablets, USB and serial, running on various different Linux
-distributions. As of December 2002, this project has transformed into
-the Linux Wacom Project. Work on this
-document is on-going so if you find an error, have a question, or have
-something to add, please send an email to:
-</a><a href="mailto:linuxwacom-discuss@lists.sf.net?subject=LinuxWacom">linuxwacom-discuss@lists.sf.net</a>.<a name="howto">
-</a></p><h2><a name="howto">1.1 - How To Use This Document</a></h2>
-<p><a name="howto">In terms of document organization, if you have not figured it out already,
-you can browse the document one page at a time, or you can click on the
-</a><a href="http://linuxwacom.sourceforge.net/index.php/howto/all">ALL</a> link and view the entire
-thing in one long page.
-
-</p><blockquote><div class="diff">
+</STYLE>
+<BODY>
+<CENTER><H1>John's Linux USB Wacom Page</H1>Last Modified: December 22, 2002 18:12<BR><A HREF="#changelog">Changelog</A></CENTER><BR><CENTER CLASS=nav>Navigation:
+<A HREF="/wacom/index.php/id/book">MAIN</A>&nbsp;&nbsp;&nbsp;<A HREF="/wacom/index.php/id/intro">NEXT</A>&nbsp;&nbsp;&nbsp;<A HREF="/wacom/index.php/toc">INDEX</A>&nbsp;&nbsp;&nbsp;<A HREF="/wacom/index.php/all"><B>ALL</B></A>&nbsp;&nbsp;&nbsp;</CENTER><BR><BR>
+<A NAME="intro">
+<H1>1.0 - Introduction</H1>
+<P>This document was written for three reasons: 1) to remind myself
+how I got my brand-new Wacom Intuos2 running on my Redhat 8.0 Linux box in
+case I have to do it again from scratch, 2) to help other people do the same,
+and 3) to help de-mystify the process by explaining why things work as they
+do, and where to look when things seem to be going wrong.
+
+<P>If you find an error, have a question, or have something to add, please
+contact me directly at
+<A HREF="mailto:jej@j-arkadia.com?subject=WACOM">jej@j-arkadia.com</A>.
+Furthermore, please add the word "WACOM" to the subject line. I get hundreds
+of messages a day, so that'll help me see your message amidst the spam.
+<A NAME="expect">
+<H2>1.1 - Expectations</H2>
+<H2>What You Can Expect Today</H2>
+
+<P>Depending on whether you are using serial or USB tablets, your experience
+will differ, but for the moment at least, the serial tablets have a generally
+simpler configuration. This document currently addresses only the USB
+tablets, but that will change in the future. Mr. Lepied's
+<A HREF="http://people.mandrakesoft.com/~flepied/projects/wacom/">XInput driver for XFree86</A> web page
+has a good description of the serial configuration process. The goal of
+this website is to make configuration and use of both tablet types as
+simple as possible. Here is what you can expect now:
+
+<H3>You Should Be Able to Get Your Tablet Working</H3>
+
+<P>Most all serial and USB tablets are working to a reasonably functional
+degree. I have an old ArtPad (1997) that does not initialize with the
+XFree86 driver, and USB Cintiq users are having a little trouble with the
+kernel drivers. Everyone else should be up and running, namely:
+
+<UL>
+<LI>PenPartner,
+<LI>Graphire,
+<LI>Graphire2,
+<LI>Intuos, and
+<LI>Intuos2
+</UL>
+
+<H3>All Your Fancy Styluses and Pointers Should Work</H3>
+
+<P>I have a collection of pointers, pens, and brushes to test; all of them
+work completely as one would expect. Users have reported success with
+their tools as well. I have not tested the airbrush yet, but presumably
+it works just fine. Tools that are known to work include:
+
+<UL>
+<LI>Graphire2 2D mouse (EC-120-0K),
+<LI>Intuos Pen (GP-300E-01H),
+<LI>Intuos2 2D mouse,
+<LI>Intuos2 4D mouse,
+<LI>Intuos2 Lens cursor,
+<LI>Intuos2 grip pen (XP-501E-00A),
+<LI>Intuos2 stroke pen (XP-120-00A),
+<LI>Intuos2 ink pen (XP-110-00A),
+</UL>
+
+<H3>You Will Need to Modify Your XF86Config File</H3>
+
+<P>This project is actively working to become a turn-key system. It will be
+awhile before major distributions like Redhat include these settings
+automatically for you. Until that time, you will need to make some changes
+to your XFree86 configuration files by hand.
+
+<H3>You May Need to Update Your Kernel</H3>
+
+<P>This project assumes that you have a kernel version of at least 2.4.18.
+While it may be possible to use this document with older kernels, the
+likelihood of success diminishes the farther back you go. Redhat 8.0
+ships with this kernel, and most of the major distributions are already
+past this point.
+
+<H3>You Will Need to Work With the Command Line</H3>
+
+<P>This document details a step-by-step process for setting up and diagnosing
+the tablet. There are no GUI tools to help you through this process- at
+least not today. Some familiarity with the command line is recommended
+since I provide enough information to get the task accomplished, but I do
+not explain how the command line itself operates. Any good book on UNIX
+will do, and I use the bash shell for all my work. If you are not using
+bash, you presumably know what you are doing already.
+
+<H2>What You Can Expect Soon</H2>
+
+<P>I have a near-term design goal to get all the tablets and their respective
+tools functioning using the original driver design. This currently includes
+the airbrush (which may work already), the Cintiq, and if possible and time
+permits, the lowly ArtPad. If there are any outstanding problems with the
+original driver, I will take care of them as they come up.
+
+<P>While the current way of configuring the tablet is sub-par in my opinion,
+it is also the established way of doing things. Merging large-scale changes
+back into either the Linux kernel or the XFree86 code tree will be difficult,
+if for no other reason than insufficient multi-platform testing. To solve
+this problem, the new functionality described below will be implemented in
+a separate project and accessed through the original driver as an advanced
+option. This will allow all the various platforms to use the new code or not
+depending on their own constraints and circumstances. It also allows for
+people to write their own tablet libraries without mucking around in the
+XFree86 code.
+
+<H2>The Next Steps</H2>
+
+<P>First and foremost, the tablet needs to be configurable without restarting
+X. By separating the tablet code from the low-level X code, it will be
+possible to talk directly to the tablet engine without interfering
+with the X server's operation. Additionally, it will be possible to use
+either the XInput configuration API or the tablet engine's API to access
+that functionality. The preferred way would probably be an X server
+extension, but today at least, that is outside of the scope of my interest.
+Ask me again in another month.
+
+<P>The next issue is plug and play. The USB tablets have the
+unfriendly habit of being unaccessible when they are unplugged and replugged.
+Since the X server holds the device open, the tablets cannot reconnect to
+their original position and get bumped to another event slot. The new
+tablet engine will address the problem, and can probably even auto-probe
+for the USB tablets.
+
+<P>Third, a GUI-based configuration tool should cap things off nicely. I
+intend to replicate the functionality of the Windows configuration tool.
+This includes diagnostics, pressure mappings, button settings, keyboard
+mappings, etc.
+
+<H2>Your Role</H2>
+
+I have some expectations as well. If you have a Wacom tablet and you
+use this code, I would appreciate it if you could test the beta releases
+whenever a feature or issue that might affect you comes up. The sooner
+that problems are resolved, the less likely you will be impacted by a
+buggy production release. If you only use the stable builds, none of
+the new features will be available to you until after they have been
+thoroughly hammered out which could be awhile. Of course, nothing is
+stopping you from using the stable builds; they are purposefully
+made available for people and companies who need the tablet drivers as
+stable as possible.
+<A NAME="updates">
+<H2>1.2 - Most Recent Updates</H2>
+
+<P>This is a list of the updates for the past month or so. The <A HREF="#changelog">Changelog</A> has a more complete
+list.
+
+<P>December 22, 2002 - Added support for the serial Intuos2 under xf86Wacom.c.
+Fixed the sign convention on the mouse wheel for USB Intuos mice. Graphire
+should be fixed, too. Added preliminary support for Volito to kernel driver.
+Cleaned up wacdump and hid-core to compile on Debian Woody without
+warnings. Added build help for Debian Stable users. Added ability to read
+serial devices using wacdump. New package is 0.3.3-beta.
+
+<P>December 15, 2002 - Added initial framework for new driver code. Fixed
+the mouse wheel for 4D mice. Fairly responsive, almost too responsive, in
+fact. (Updated: quick fix to xf86Wacom.c to remove some debugging code that
+got left in accidentally; new driver version is 0.3.2a, but the package is
+the same.)
+
+<P>December 13, 2002 - Added development page. New beta build has fix for
+2D mouse wheel. Wacdump displays relative data now. Build environment for
+wacom_drv.o set up for new code.
+
+<P>December 9, 2002 - Added more information about the parameters accepted
+by the InputDevice section, including the man pages.
+
+<P>November 24, 2002 - Moved beta tree to version 0.2.0. Added complete
+configure-based environment. wacom.o and wacdump are built by default;
+wacom_drv.o is available in binary and source form.
+
+<A NAME="success">
+<H2>1.3 - Success Stories</H2>
+<P>Originally, this document dealt only with Redhat 8.0. I will extend this
+to cover as many different distributions as possible, but I can personally
+only test on machines at my disposal. At present, that means Redhat 7.2 and
+8.0. If you have success stories for a distribution or version not mentioned,
+let me know so I can update the document.
+
+<UL>
+ <LI> Redhat
+ <UL>
+ <LI> Redhat 8.0 - tested on kernel 2.4.18-18.8.0
+ <LI> Redhat 8.0 - tested on kernel 2.4.18-17.8.0
+ <LI> Redhat 7.3 - tested on kernel 2.4.18-17.7.x
+ <LI> Redhat 7.2 - tested on kernel 2.4.18-17.7.x
+ </UL>
+ <LI> Mandrake
+ <UL>
+ <LI> Mandrake 9.0 - tested on ???
+ </UL>
+ <LI> Gentoo
+ <UL>
+ <LI> Gentoo 1.4rc - tested on 2.4.19 kernel, gcc3.2, XFree86 4.2.0
+ </UL>
+ <LI> Debian
+ <UL>
+ <LI>Debian Woody - XFree86 4.2 on 2.4.20
+ <LI>Debian Stable - XFree86 4.1 (see
+ <A HREF="#debwcmdrv">Building wacom_drv.o On Debian Stable</A>)
+ </UL>
+ <LI> Slackware
+ <UL>
+ <LI>Slackware 8.1, (standard release)
+ </UL>
+ <LI> SuSE
+ <UL>
+ <LI>Suse Linux 8.0, kernel 2.4.18, XFree 4.2
+ </UL>
+</UL>
+<A NAME="howto">
+<H2>1.4 - How To Use This Document</H2>
+<BLOCKQUOTE><DIV CLASS=diff>
Where the guide differs between distributions or packages, I have added a
-comment which appears indented with a light blue background.
-</div></blockquote>
-
-<p>Also, it bears mentioning since it's a detail often missed: there are
-two drivers in the Linux Wacom Project- wacom.o and wacom_drv.o. The first
-driver is the USB kernel driver. The second driver is the XFree86 Wacom
-driver. Serial users need only be concerned with the wacom_drv.o driver.
-USB users need both. If you try to use the wacom_drv.o driver in place of
-the wacom.o kernel driver or visa-versa, things generally won't work.
-
-</p><p>Next, this document was written with the assumption that you are starting
-from scratch with a relatively recent distribution of the Linux kernel. Also,
-if you have already added lines to your XFree86/Xorg configuration file
-(XF86Config/XF86Config-4 or xorg.conf), you should comment them out and
-restart X. Since we'll be stepping through the entire process, we need X to
-ignore the tablet until we're ready. Otherwise, X will just get in the way.
-
-</p><p>Finally, if you know what you're doing, you can leave your X settings
-intact, print this out, switch to runlevel 3, and follow along from the
-console. An HTML version of this document can be found in the docs directory at <a href="http://linuxwacom.cvs.sourceforge.net/linuxwacom/linuxwacom-dev/docs/">docs.html</a>.
-<a name="theory">
-</a></p><h2><a name="theory">1.2 - Wacom Driver Theory of Operation</a></h2>
-<p><a name="theory">Wacom tablets are available in serial and USB configurations. They are
-also sold as embedded products in certain tablet PC's. I will cover all
-three types, but the serial case is the most straightforward,
-so we'll start there.
-
-<br><br>
-
-</a></p><p><a name="theory"><b>Serial Tablet Operation - The Short Story</b>
-
-</a></p><p><a name="theory">When a Wacom serial tablet is connected to a COM port, software can
-interact with it directly by opening the appropriate device, usually
-/dev/ttyS0. The XFree86 Wacom driver (wacom_drv.o) does precisely this,
-and all stylus movements are converted into XInput events for programs
-like the Gimp to turn into fluid brush strokes.
-
-</a></p><p><a name="theory">Wacom tablets are capable of handling a number of different data
-protocols, and the Linux Wacom Project code currently utilitizes two,
-Wacom Protocol IV and Protocol V. Each operates with a fixed-sized
-packet, the length of which depends on the model and ROM version.
+comment like this to help distinguish between versions.
+</DIV></BLOCKQUOTE>
-</a></p><p><a name="theory">When the serial tablet is reset, it defaults to a standard baud rate,
-often 9600 baud. From there, the device type can be queried, and if the
-tablet supports it, the baud rate increased to a higher value. Additionally,
-model parameters like tablet size can be queried directly to determine
-which features are available.
-
-</a></p><p><a name="theory">Once configured, the tablet streams data back to the application as
-tools are brought into and out of proximity, are pressed against the
-tablet surface, or are tilted or inverted.
-
-<br><br>
+<P>In terms of document organization, if you have not figured it out already,
+you can browse the document one page at a time, or you can click on the
+ALL link and view the entire thing in one long page.
-</a></p><p><a name="theory"><b>USB Tablet Operation - The Long Story</b>
+<P>Next, this document was written with the
+assumption that you are starting from
+scratch with a relatively recent distribution of the Linux kernel. Also,
+if you have already added lines to your X11 configuration file (XF86Config),
+you should comment them out and restart X. Since we'll be stepping through
+the entire process, we need X to ignore the tablet until we're ready.
+Otherwise, X will just get in the way.
-</a></p><p><a name="theory">Initially at least, the USB Wacom tablet is an HID compliant device, and when
+<P>Finally, if you know what you're doing, you can leave your X settings
+intact, print this out, switch to runlevel 3, and follow along from the
+console. The newer packages should have an HTML and text version of this
+document in the documentation directory. And of course, there's always
+<A HREF=http://lynx.isc.org/>lynx</A> for the gurus out there, which is
+why this document is written out in plain vanilla HTML.
+<A NAME="resources">
+<H2>1.5 - Resources and References</H2>
+
+<TABLE BORDER=0 CELLSPACING=5>
+<TR><TD VALIGN=TOP><A HREF="http://people.mandrakesoft.com/~flepied/projects/wacom/">Lepied's Wacom XInput driver for XFree86</A></TD><TD>This page contains the original driver and help for serial tablet users.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://www.lepied.com/archive_wacom.html">Lepied's Wacom Mailing List Archive</A></TD><TD>This is an archive of Lepied's driver mailing list.
+<I>Warning: posting directly to the mailing list page does not mail
+to the list. Many posts are missed this way.</I></TD></TR>
+<TR><TD VALIGN=TOP><A HREF="mailto:wacom-subscribe@lepied.com">Subscribe to Lepied's Wacom Mailing List</A></TD><TD>If you want to post to the list and receive notifications about driver updates, this link will subscribe you.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://www.runkel-it.de/wacom_tablet_howto.html">Stefan Runkel's Wacom Tablet HOWTO</A></TD><TD>This page is a bit old, but it covers a lot of details that I mention only briefly. Good reading, even if it is possibly outdated.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://www.wacom.com">Wacom Webpage</A></TD><TD>The Wacom web site contains little information about the Linux drivers, but you
+can look at their nifty new tablets.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://www.pxh.de/fs/graphire/">pxh: Graphire USB</A></TD><TD>This page is devoted to a Graphire-specific XFree86 driver.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://homepages.feis.herts.ac.uk/~bt7al/wcm/">A Webpage Dealing with Cintiq (Wacom PL-500 in particular) on Linux</A></TD><TD>This website deals with getting the Cintiq running; I will be merging this code into
+the kernel soon.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://sem.best.vwh.net/linux/wacom/">Wacom Intuos USB Micro-HOWTO</A></TD><TD>An older webpage which may not be relevent anymore,
+but was useful to me when I got started.</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="http://www.ecn.wfu.edu/~cottrell/thinkpad/tpa21m/wacom.html">Wacom Intuos USB on Linux</A></TD><TD>Another page that was useful to
+me when I started.</TD></TR>
+<TR><TD><A HREF="http://www.wacomeng.com/devsupport/index.html">Wacom Software Developer Support</A></TD><TD>This page contains some documentation for the
+older tablets.</TD></TR>
+</TABLE>
+<A NAME="faq">
+<H2>1.6 - Frequently Asked Questions</H2>
+
+<P>This FAQ is based on the questions that I receive in email. If you have
+a question that is not answered here, <A HREF="mailto:jej@j-arkadia.com?subject=WACOM">send me email directly.</A> Please add
+the word "WACOM" to the subject line to help me distinguish your message from
+the spam I normally receive.</P>
+
+<H2>Index</H2>
+<UL>
+<LI><A HREF=#WHO>Who is responsible for this code?</A>
+<LI><A HREF=#SUPPORT>Is my tablet supported? What about my special stylus?</A>
+<LI><A HREF=#OTHERS>What about my Penpartner/Graphire/Cintiq?</A>
+<LI><A HREF=#SPURIOUS>How do I get my stylus to stop clicking randomly whenever I use it?</A>
+<LI><A HREF=#FILTER>The old drivers had filtering, how do I enable it now?</A>
+<LI><A HREF=#FEATURE>What happened to feature XYZ?</A>
+<LI><A HREF=#BUSTED>How do I get the special features of my stylus to work?</A>
+</UL>
+
+<BR>
+<BR>
+<BR>
+
+<A NAME=WHO>
+<H3>Who is responsible for this code?</H3>
+
+<P>We are. That is, Linux users with Wacom tablets are responsible for
+the development of this code. The source code
+was written by at least two dozen individuals, none of whom still seem to
+be directly involved in the project. I, John Joganic, took up the code in
+November of 2002, largely to satisfy my own needs, but also because I believe
+Linux needs to be more useful in the graphic and video industries. What I
+ask of you, is to use the drivers and report the problems you encounter.
+
+<A NAME=SUPPORT>
+<H3>Is my tablet supported? What about my special stylus?</H3>
+
+<P>Most recent tablets are supported as well all the styluses. The
+<A HREF="#expect">Expectations</A> page has a
+list of all the tablets and styluses that are known to work as well
+as what you can expect out of these drivers now and in the future.
+
+<A NAME=OTHERS>
+<H3>What about my Penpartner/Graphire/Cintiq?</H3>
+
+The USB kernel driver currently seems to support Penpartner, Graphire,
+Graphire2, Intuos, Intuos2, and PL400-800. Based on user reports, the
+Cintiqs may identify themselves as PL series tablets.
+There is no kernel driver necessary for serial tablets.
+The XFree86 wacom driver supports both USB and serial devices. It has
+support for all the USB devices as well as virtually all of the older
+tablet models as well. Depending on how the Cintiq identifies itself,
+it may potentially work with the XFree86 driver as a serial device. There
+are no guarantees as of yet, so I would not buy one (currently over $3000
+USD) on the assumption that it will work without doing some actual research.
+
+<A NAME=SPURIOUS>
+<H3>How do I get my stylus to stop clicking randomly whenever I use it?</H3>
+
+<P>The "Threshold" setting in the InputDevice section of the XFree86
+configuration file determines the minimum pressure value before a touch
+event is detected. Wacdump can show you what pressure values are actually
+being received from the tablet, and setting the threshold to a value higher
+than that should solve the problem. My stylus oscillates between 0 and 6,
+even if the stylus is not touching the tablet. I use a threshold of 10.</P>
+
+<A NAME=FILTER>
+<H3>The old drivers had filtering, how do I enable it now?</H3>
+
+<P>At some point, the maintainers of the wacom kernel driver ripped out
+all the good features and moved them into the xf86Wacom driver. Not
+everything works as well as one might like. The "Suppress" setting in
+the InputDevice section specifies the tablet sensitivity.
+
+<A NAME=FEATURE>
+<H3>What happened to feature XYZ?</H3>
+
+<P>As mentioned above, many of the features in the original kernel driver
+were removed and transferred to the xf86Wacom driver. Not all the features
+made the trip. The goal of this website is to have all the original features
+working again as well as all the features available for the windows driver.
+If your favorite feature is not working, drop me a line. I prioritize my
+work based on my perception of user need.
+
+<A NAME=BUSTED>
+<H3>How do I get the special features of my stylus to work?</H3>
+
+<P>There are many different types of stylus, mice, and cursors. All of them
+work to varying degrees, so if you are running into trouble, send me email.
+There are presently known issues with the mouse wheel on 2D mice (fixed in
+0.3.1-beta), and some of the extra buttons on the 4D mice. While the values
+are generally reported correctly to the driver, the xf86Wacom driver does not
+interpret the information properly. The 4D mouse wheel for instance behaves
+completely contrary to expectation (fixed in 0.3.2-beta). These problems will
+be addressed in future production releases (and are available now in the beta
+releases).
+
+<P>I do not have an airbrush tool at my disposal. If you have one and it
+does not work for you, let me know. You could be beta-testing the code that
+gets this working.
+<A NAME="dev">
+<H2>1.7 - Development</H2>
+<H2>CURRENT DEVELOPMENT</H2>
+
+<TABLE BORDER=0>
+<TR><TD ALIGN=RIGHT>Date:&nbsp;&nbsp;</TD>
+<TD>2002-12-22 (Sunday)</TD></TR>
+<TR><TD ALIGN=RIGHT>Status:&nbsp;&nbsp;</TD>
+<TD>Moving over to SourceForge, and testing new serial driver.
+</TD></TR>
+<TR><TD ALIGN=RIGHT>Estimated Time:&nbsp;&nbsp;</TD>
+<TD>Ready on 2002-12-29 (Sunday)</TD></TR>
+</TABLE>
+
+<H3>Completed</H3>
+<UL>
+<LI>Added Intuos2 serial to xf86Wacom.c.
+<LI>Added serial tablet code to wacdump.c.
+<LI>Added experimental Volito code to kernel.
+<LI>Split ncurses and Linux input code to avoid namespace collision on Debian.
+<LI>Corrected wheel sign for USB mice.
+</UL>
+
+<H3>Immediate</H3>
+<UL>
+<LI>Get code onto SourceForge.
+<LI>Intuos2 2D mouse does not work correctly under xf86Wacom.c
+</UL>
+
+<H3>Secondary</H3>
+<UL>
+<LI>Getting test application for XF86 driver together
+<LI>Testing ability to create new pointer devices on the fly
+<LI>Testing ability to fork out new server process
+</UL>
+
+<BR><BR><BR>
+
+<H2>KNOWN ISSUES</H2>
+
+There are plenty of known issues. If you have one, and it is not listed,
+check the FAQ, and if it's not there either, let me know.
+
+<H3>wacom.o</H3>
+
+<UL>
+<LI>2002-12-13: Tablet does not reinitialize properly when replugged (report #1).
+</UL>
+
+<H3>wacdump</H3>
+
+<UL>
+<LI>Nothing outstanding.
+</UL>
+
+<H3>wacom_drv.o</H3>
+
+<UL>
+<LI>2002-12-22: Intuos2 2D mouse does not work correctly under xf86Wacom.c
+</UL>
+<A NAME="theory">
+<H2>1.8 - Wacom Driver Theory of Operation</H2>
+<P>Initially at least, the Wacom tablet is an HID compliant device, and when
first connected to the computer, will identify itself as such.
Unfortunately, this is not what you want because in this mode, you will not
-get any of the fancy features. The hid-core.c, mousedev.c, and usbmouse.c kernel
-drivers contain exceptions for the wacom; when the device is detected, they ignore
-the tablet. In this way, the more sophisticated wacom driver has the
-opportunity to assume control.
+get any of the fancy features. The hid-core.c and usbmouse.c files contain
+exceptions for the wacom; when the device is detected, they ignore the
+tablet. In this way, the more sophisticated wacom driver
+has the opportunity to assume control.
-</a></p><p><a name="theory">The first thing that the driver does is register itself with the USB
+<P>The first thing that the driver does is register itself with the USB
subsystem and wait for work to do. When the user plugs the device in, or
the device is first detected, the USB subsystem shops the vendor and
device identifier around, checking it against different drivers. The
@@ -171,1750 +444,979 @@ allows for values like pressure, Z rotation,
and tilt. As information arrives, the wacom driver dutifully converts
the data into real-world values and hands it on to the event system.
-</a></p><p><a name="theory">From here, any usermode application can get access to the event data
+<P>From here, any usermode application can get access to the event data
by opening /dev/input/event0. A stream of events including mouse movements,
-clicks, and proximity updates can be read from the device. Similar to the
-serial case, XFree86's Wacom driver (wacom_drv.o) has the ability to read
-this device, and performs filtering on the data before convert the Linux
-input events into XInput events.
-
-</a></p><p><a name="theory">By breaking the responsibility for the data into three distinct levels,
-the kernel code remains simple and robust, the applications generalized,
+clicks, and proximity updates can be read from the device. One such
+application that would be interested in this data is the X system itself.
+An XInput driver (wacom_drv.o) collects that information,
+applies various forms of filtering, and offers it to GUI-based applications
+throught the XInput API. A graphics program like gimp can then get access
+to the positions of various tools by querying X directly.
+
+<P>By breaking the responsibility for the data into three distinct levels,
+we keep the kernel code simple and robust, the applications generalized,
and the fancy features commonly accessible to all GUI applications in the
X window system itself. This document walks down the entire data path from
-the USB kernel driver to the gimp application.
-
-<br><br>
-</a></p><p><a name="theory"><b>Embedded Device Operation - Tablet PC with Wacom Digitizer</b>
-
-</a></p><p><a name="theory">Refer to </a><a href="#tabletpc">Tablet PC</a> page for detail.
-
-<a name="starthere">
-</a></p><h1><a name="starthere">2.0 - Getting It Together</a></h1>
-<p><a name="starthere">This section is devoted to preparing your system for the installation.
-Every distribution handles kernel modules and file locations a bit differently,
-so the goal here is to return everything to a known state.
-
-</a></p><p><a name="starthere">USB users will need to pay specific attention to discussions related to
-kernel drivers and modules. Serial tablet users have it much easier, and
-can bypass this. Both users will need to make changes to the XFree86/Xorg
-configuration file.
-
-</a><a name="beforestart">
-</a></p><h2><a name="beforestart">2.1 - Before We Start</a></h2>
-<p><a name="beforestart">From the beginning, let's make certain that we are on the
-same page. First, if you have Wacom related lines in your
-XF86Config/XF86Config-4 or xorg.conf files already, you should
-comment them out or remove them. In particular, this includes InputDevice
-sections with a driver set to "wacom" and their corresponding InputDevice
-lines in ServerLayout. When that's done, restart X.<br>
-
-</a></p><p><a name="beforestart">It would be a wise idea at this time to check your XFree86 or Xorg log
-file for references to wacom, wcm, or tablet. If X persists in trying to
-interact with the tablet, things will only be problematic later. The log
-file is often found at /var/log/XFree86.0.log or /var/log/Xorg.0.log.
-
-</a></p><p><a name="beforestart">To be prepared for the coming steps, it would be nice if you know what
-X server and Linux kernel versions are running on your system. The <i>X -version</i>
-command reveals those information for you.
-
-</a></p><p><a name="beforestart">If you have a USB tablet, you need to check Wacom kernel drvier first
-</a><a href="#kernel">The USB Kernel Driver</a>.
-Serial tablet or Tablet PC users can go directly to the next section
-<a href="#download">Downloading the Code</a> page.
-<a name="download">
-</a></p><h2><a name="download">2.2 - Downloading the Code</a></h2>
-
-<p><a name="download">The file </a><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.2-2.tar.bz2">linuxwacom-0.8.2-2.tar.bz2</a> is the stable package and contains
-files that you will need to get your serial or USB tablet working. The
-current beta package <a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.3-3.tar.bz2">linuxwacom-0.8.3-3.tar.bz2</a> is also available and may be
-used by people who are willing to help test new features. I will never put a
-beta package on this site that I am not running myself on my primary
-development machine. So you can be certain that if there are any obvious
-show stoppers, they will be fixed before you get to see them.
-
-</p><p>Unpacking the tarball is usually a one-step process, but I show both
-steps in case the typical -jxf option doesn't work with tar.
-
-</p><blockquote><pre>[jej@ayukawa jej]$ bunzip2 linuxwacom-0.8.2-2.tar.bz2
-[jej@ayukawa jej]$ tar -xf linuxwacom-0.8.2-2.tar
-[jej@ayukawa jej]$ cd linuxwacom-0.8.2-2</pre></blockquote>
-
-Once in the package directory, you need only to configure and build the code.
-This is described in more detail as you continue. The executables and
-wacom_drv.o are installed automatically; the kernel drivers have different
-installation procedures depend on the kernel source you use.
-
-<p>If you are interested, the following tables contain the package contents
-and release dates. Otherwise, let's continue.
-
-
-</p><h3>Stable files included for linuxwacom-0.8.2-2:</h3>
-<table border="0" cellspacing="5">
-<tbody><tr><th align="left">File</th><th align="left">Comment</th></tr>
-<tr><td valign="top">configure</td><td valign="top">- configure script for distribution independent builds</td></tr>
-<tr><td valign="top">prebuilt/install</td><td valign="top">- installer for the executables and Wacom X driver to a system identical to the development system.</td></tr>
-<tr><td valign="top">prebuilt/uninstall</td><td valign="top">- unistaller for the executables</td></tr>
-<tr><td valign="top">prebuilt/wacom.4x.gz</td><td valign="top">- man page for Wacom driver</td></tr>
-<tr><td valign="top">prebuilt/32</td><td valign="top">- Wacom X driver and its utility programs for XFree86 and X11R6/Xorg on x86 systems</td></tr>
-<tr><td valign="top">prebuilt/64</td><td valign="top">- Wacom X driver and its utility programs for XFree86 and X11R6/Xorg on x86-64 systems</td></tr>
-<tr><td valign="top">src/util/wacdump.c</td><td valign="top">- a simple program for displaying tablet event data directly using ncurses</td></tr>
-<tr><td valign="top">src/util/xidump.c</td><td valign="top">- a diagnostic program for displaying XInput event data</td></tr>
-<tr><td valign="top">src/util/wacscrn.c</td><td valign="top">- curses library for wacdump</td></tr>
-<tr><td valign="top">src/util/wactablet.c</td><td valign="top">- wacom tablet library for wacdump</td></tr>
-<tr><td valign="top">src/util/wacusb.c</td><td valign="top">- wacom USB protocol library for wacdump</td></tr>
-<tr><td valign="top">src/util/wacserial.c</td><td valign="top">- wacom serial protocol library for wacdump</td></tr>
-<tr><td valign="top">src/util/wactablet.h</td><td valign="top">- wacom tablet library for wacdump</td></tr>
-<tr><td valign="top">src/util/wacusb.h</td><td valign="top">- wacom USB protocol library for wacdump</td></tr>
-<tr><td valign="top">src/util/wacserial.h</td><td valign="top">- wacom serial protocol library for wacdump</td></tr>
-<tr><td valign="top">src/util/xsetwacom.c</td><td valign="top">- a command line configuration tool for Wacom X driver</td></tr>
-<tr><td valign="top">src/util/wacomcfg.c</td><td valign="top">- configuration option library for xsetwacom</td></tr>
-<tr><td valign="top">src/util/wcmAction.c</td><td valign="top">- keystroke and modifier encoding/decoding</td></tr>
-<tr><td valign="top">src/util/wcmAction.h</td><td valign="top">- keystroke routine definitions</td></tr>
-<tr><td valign="top">src/util/hal-setup-wacom.c</td><td valign="top">- a HAL service program for Wacom devices</td></tr>
-<tr><td valign="top">src/util/10-linuxwacom.fdi</td><td valign="top">- a HAL script for Wacom devices</td></tr>
-<tr><td valign="top">src/include/Xwacom.h</td><td valign="top">- configuration options for xsetwacom</td></tr>
-<tr><td valign="top">src/2.6.x/wacom.c</td><td valign="top">- replacement kernel driver for kernel 2.6.x where x can be 9 and 10</td></tr>
-<tr><td valign="top">src/2.6.x/wacom_sys.c</td><td valign="top">- wacom kernel driver specific to each major kernel release, where x can be 11 to 28</td></tr>
-<tr><td valign="top">src/2.6.x/wacom_wac.c</td><td valign="top">- wacom kernel driver processes tablet specific information, where x can be 16 or 28</td></tr>
-<tr><td valign="top">src/2.6.x/wacom.h</td><td valign="top">- wacom kernel driver header specific to each major kernel release, where x can be 11 to 28</td></tr>
-<tr><td valign="top">src/2.6.16/wacom_wac.h</td><td valign="top">- part of wacom kernel driver header for tablet specific declaration and definitions </td></tr>
-<tr><td valign="top">src/2.6.x/hid-core.c</td><td valign="top">- replacement kernel driver for kernel 2.6.x where x can be 8 to 16, use only if needed</td></tr>
-<tr><td valign="top">src/xdrv/xf86Wacom.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Binary available in prebuilt directory.</td></tr>
-<tr><td valign="top">src/xdrv/xf86Wacom.h</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile.</td></tr>
-<tr><td valign="top">src/xdrv/wcmCommon.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Common to USB and serial tablets</td></tr>
-<tr><td valign="top">src/xdrv/wcmXCommand.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. APIs to xsetwacom.</td></tr>
-<tr><td valign="top">src/xdrv/wcmCompat.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. XFree86 4.x support</td></tr>
-<tr><td valign="top">src/xdrv/wcmConfig.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Configuration setup</td></tr>
-<tr><td valign="top">src/xdrv/wcmFilter.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Raw data filters</td></tr>
-<tr><td valign="top">src/xdrv/wcmFilter.h</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Raw data filters</td></tr>
-<tr><td valign="top">src/xdrv/wcmISDV4.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. General Tablet PC</td></tr>
-<tr><td valign="top">src/xdrv/wcmSerial.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Serial tablet support</td></tr>
-<tr><td valign="top">src/xdrv/wcmSerial.h</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Serial tablet support</td></tr>
-<tr><td valign="top">src/xdrv/wcmUSB.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. USB tablet support</td></tr>
-<tr><td valign="top">src/xdrv/wcmTilt2Rotation.c</td><td valign="top">- source for wacom_drv.o; requires XFree86/Xorg build environment to compile. Converting mouse tilt to rotation</td></tr>
-<tr><td valign="top">src/wacomxi/wacomcpl-exec</td><td valign="top">- a graphic configuration tool for wacom XFree86 driver</td></tr>
-<tr><td valign="top">src/wacomxi/wacomxi.c</td><td valign="top">- calibration library for xsetwacom</td></tr>
-<tr><td valign="top">src/wacomxi/wacomxi.h</td><td valign="top">- calibration library for xsetwacom</td></tr>
-<tr><td valign="top">GPL</td><td valign="top">- the GNU General Public License, in case you did not already have one lying around</td></tr>
-</tbody></table>
-
-<h3>Stable Packages by Version and Date:</h3>
-<table border="0" cellspacing="5">
-<tbody><tr><th align="left">File</th><th></th><th align="left">Date</th><th align="left">Comment</th></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.2-2.tar.bz2">linuxwacom-0.8.2-2.tar.bz2</a></td><td valign="top">-</td><td valign="top">2009-01-19</td><td valign="top">Support: USB Tablet PC with and without touch; kernels up to 2.6.28; Bamboo1 and Monarch; new wacomcpl features.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.0-3.tar.bz2">linuxwacom-0.8.0-3.tar.bz2</a></td><td valign="top">-</td><td valign="top">2008-05-23</td><td valign="top">Support:
-kernels up to 2.6.25; Keystrokes for both buttons and expresskeys; New
-tablets: Bamboo series and Cintiq 12WX &amp; 20WSX, and so much more
-that you can not afford to miss.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.8-3.tar.bz2">linuxwacom-0.7.8-3.tar.bz2</a></td><td valign="top">-</td><td valign="top">2007-08-15</td><td valign="top">Supports
-new tablet, Bamboo. Provides prebuilt Wacom X driver and its utility
-programs for x86_32 and x86_64 systems. Adds many new xsetwacom options.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.6-4.tar.bz2">linuxwacom-0.7.6-4.tar.bz2</a></td><td valign="top">-</td><td valign="top">2006-12-01</td><td valign="top">Updated xsetwacom and support kernel 2.6.17/18, Intuos3 4x6 and on-the-fly tablet rotation.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.4-3.tar.bz2">linuxwacom-0.7.4-3.tar.bz2</a></td><td valign="top">-</td><td valign="top">2006-06-19</td><td valign="top">Supports kernels 2.6.15/16, 2 new Intuos3 (12x12 and 12x19), and DTF 521.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.2.tar.bz2">linuxwacom-0.7.2.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-12-21</td><td valign="top">Updated configuration script and support kernel 2.6.13/14, Graphire4, PL710, DTF720, Intuos3 6x11 and Volito2 .</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.0-1.tar.bz2">linuxwacom-0.7.0-1.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-09-23</td><td valign="top">Updated wacomcpl and support 16 buttons for all tools.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.0-x86-64-1.tar.bz2">linuxwacom-0.7.0-x86-64-1.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-09-23</td><td valign="top">Updated wacomcpl and support 16 buttons for all tools.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.8.tar.bz2">linuxwacom-0.6.8.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-05-05</td><td valign="top">Support Cintiq 21UX and kernel 2.6.11.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.6.tar.bz2">linuxwacom-0.6.6.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-12-01</td><td valign="top">Build .ko locally and support kernel 2.6.10.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.4.tar.bz2">linuxwacom-0.6.4.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-08-06</td><td valign="top">Updated wacusb.c and fixed USB tablet protocol V dual input bug.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.3.tar.bz2">linuxwacom-0.6.3.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-05-25</td><td valign="top">Fixed tool on tablet and relative speed bugs.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.2.tar.bz2">linuxwacom-0.6.2.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-04-02</td><td valign="top">Fixed DoubleSpeed, DoubleRadius, and TwinView issues.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.1.tar.bz2">linuxwacom-0.6.1.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-03-02</td><td valign="top">added wacomcpl, support kernel 2.4.24 and 2.6.2/3</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.0.tar.bz2">linuxwacom-0.6.0.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-02-04</td><td valign="top">added wacomcpl, support kernel 2.4.22 and 2.6.0</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.4.1.tar.gz">linuxwacom-0.4.1.tar.gz</a></td><td valign="top">-</td><td valign="top">2003-03-22</td><td valign="top">added xidump, checks for ncurses</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.4.0.tar.gz">linuxwacom-0.4.0.tar.gz</a></td><td valign="top">-</td><td valign="top">2003-01-31</td><td valign="top">production release from 0.3.7-beta</td></tr>
-</tbody></table>
-<h3>Beta Packages by Version and Date:</h3>
-<table border="0" cellspacing="5">
-<tbody><tr><th align="left">File</th><th></th><th align="left">Date</th><th align="left">Comment</th></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.3-3.tar.bz2">linuxwacom-0.8.3-3.tar.bz2</a></td><td valign="top">-</td><td valign="top">2009-04-27</td><td valign="top">Support Inutos4 tablets. Support kernel upto 2.6.29. Support Xorg 1.6. Updated multi-monitor suppport</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.1-6.tar.bz2">linuxwacom-0.8.1-6.tar.bz2</a></td><td valign="top">-</td><td valign="top">2008-10-24</td><td valign="top">Support USB Tablet PC with and without touch. Support kernel 2.6.27</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.9-11.tar.bz2">linuxwacom-0.7.9-11.tar.bz2</a></td><td valign="top">-</td><td valign="top">2008-04-11</td><td valign="top">Support
-kernel 2.6.22 &amp; 2.6.24. Temporary workaround for Xorg 7.3. Support
-Bamboo series and Cintiq 12WX &amp; 20WSX. Updated wacomcpl for
-keystrokes. Support serial Tablet PC with touch.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.7-12.tar.bz2">linuxwacom-0.7.7-12.tar.bz2</a></td><td valign="top">-</td><td valign="top">2007-06-15</td><td valign="top">Support
-Bamboo. Updated installer under prebuilt directory to install X driver
-as well as its associated utilities. Support non-overlapped multi-areas
-for same InputDevice. Support pad with button and keystroke events
-through xsetwacom</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.5-4.tar.bz2">linuxwacom-0.7.5-4.tar.bz2</a></td><td valign="top">-</td><td valign="top">2006-09-29</td><td valign="top">Support kernel 2.6.17/18, Intuos3 4x6, and tablet detach/attach as well as rotation while X running. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.3-1.tar.bz2">linuxwacom-0.7.3-1.tar.bz2</a></td><td valign="top">-</td><td valign="top">2006-04-07</td><td valign="top">Support kernel 2.6.15/16, Intuos3 12x12 and 12x19. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.7.1-2.tar.bz2">linuxwacom-0.7.1-2.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-12-06</td><td valign="top">Support kernel 2.6.13/14, Graphire4, PL710, DTF720, Intuos3 6x11 and Volito2. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.9.tar.bz2">linuxwacom-0.6.9.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-08-08</td><td valign="top">Support tablet orentation rotation. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.9-x86-64.tar.bz2">linuxwacom-0.6.9-x86-64.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-08-08</td><td valign="top">Support x86-64 system. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.7.tar.bz2">linuxwacom-0.6.7.tar.bz2</a></td><td valign="top">-</td><td valign="top">2005-03-28</td><td valign="top">Added Cintiq 21UX and kernel 2.6.11 support. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.6.5.tar.bz2">linuxwacom-0.6.5.tar.bz2</a></td><td valign="top">-</td><td valign="top">2004-11-05</td><td valign="top">Added Intuos3 support. </td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.5.4-beta.tar.bz2">linuxwacom-0.5.4-beta.tar.bz2</a></td><td valign="top">-</td><td valign="top">2003-12-22</td><td valign="top">General Tablet PC support. 2.6.0 kernel support.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.5.3-beta.tar.gz">linuxwacom-0.5.3-beta.tar.gz</a></td><td valign="top">-</td><td valign="top">2003-11-12</td><td valign="top">Added wacomcpl utility. 2.4.22 kernel support. TwinView support.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.5.2-beta.tar.gz">linuxwacom-0.5.2-beta.tar.gz</a></td><td valign="top">-</td><td valign="top">2003-07-10</td><td valign="top">Fixed Intuos filter code. 2.5 kernel support. Minor bug fixes.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.5.1-beta.tar.gz">linuxwacom-0.5.1-beta.tar.gz</a></td><td valign="top">-</td><td valign="top">2003-06-15</td><td valign="top">Completely refactored data path, configurability.</td></tr>
-<tr><td valign="top"><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.5.0-beta.tar.gz">linuxwacom-0.5.0-beta.tar.gz</a></td><td valign="top">-</td><td valign="top">2003-02-12</td><td valign="top">Updated PL code. Numerous tweaks.</td></tr>
-</tbody></table>
-<a name="root">
-</a><h2><a name="root">2.3 - The Root Account</a></h2>
-<p><a name="root">If you are comfortable with the root account, paths, the /sbin directory,
-and programs like <i>modprobe</i>, you can skip this section. This is largely
-to clarify some things for people who are new to Linux and get tripped up
-with the root account and paths. This is not meant to be a tutorial, so if
-this is over your head, I would recommend reading a book on Linux command line
-usage. All examples in this document assume the bash shell.
-
-</a></p><p><a name="root"> Many of the procedures in this document need root access, and the
-commands that are executed are located in places on the system that are
-not normally accessed by typical users. In order to run the <i>modprobe</i>
-command, for instance, you must have root access. Additionally, if the
-/sbin directory which contains <i>modprobe</i> does not appear in your
-path, you must specify the full pathname, /sbin/modprobe, to run the command.
-Here is an example of the problem, followed by solutions.
-
-</a></p><blockquote><pre><a name="root">[jej@ayukawa jej]$ modprobe foo
-bash: modprobe: command not found
-[jej@ayukawa jej]$ locate modprobe
-/sbin/modprobe
-[jej@ayukawa jej]$ echo $PATH
-/bin:/usr/bin: ... :/home/jej/bin
-</a></pre></blockquote>
-
-<a name="root">Normal users do not have /sbin in their path, so running <i>modprobe</i>
-directly fails. Running the program using the full pathname (/sbin/modprobe)
-will solve this, as will adding /sbin to the path. But there is another
-problem, as we will see:
-
-</a><blockquote><pre><a name="root">[jej@ayukawa jej]$ /sbin/modprobe foo
-foo.o: create_module: Operation not permitted
-</a></pre></blockquote>
-
-<a name="root">Normal users are not allowed to run this command. For that, we need
-to be root. The <i>su</i> command stands for "substitute user" since
-it can be used to become <i>any</i> user on the system, but it is generally
-known by the incorrect but very memorable mnemonic "superuser."
-
-</a><blockquote><pre><a name="root">[jej@ayukawa jej]$ su
-Password:
-[<b>root</b>@ayukawa jej]# whoami
-root
-</a></pre></blockquote>
-
-<p><a name="root">Note the change to the root account, and the additional change from
-$ to # on the prompt. I maintain this convention in all the examples in
-this document, so if you get an "access denied" error, check the prompt.
-You probably need to be root.
-
-</a></p><p><a name="root">Now that we have root access, is /sbin in our path? No. We have only
-been granted the privileges of root; we are not really in the root
-account's environment. Most notably, the home directory ($HOME) changes,
-but the path ($PATH) stays the same. Thus, becoming root is not sufficient to
-run <i>modprobe</i> without the full pathname, but does solve the access
-problem.
-
-</a></p><blockquote><pre><a name="root">[root@ayukawa jej]# modprobe foo
-bash: modprobe: command not found
-[root@ayukawa jej]# export PATH=$PATH:/sbin
-[root@ayukawa jej]# modprobe foo
-[root@ayukawa jej]#
-</a></pre></blockquote>
-
-<p><a name="root">In this example, the user adds the /sbin directory to the path and can run
-<i>modprobe</i> normally. <i>export</i> is a bash shell command that changes
-aspects of your environment; in this case, /sbin is appended to the path. In
-the highly unlikely event that you are using a different shell, which for
-novice users seems unwise to me, you would need to use a different command.
-Redhat, Mandrake, and similar distributions all use bash by default, so it is
-unlikely that you would be using anything else.
-
-</a></p><p><a name="root">At any rate, changing the path is a reasonably good solution, if you can
-remember the syntax of the <i>export</i> command.
-
-</a></p><p><a name="root">Another approach to this problem is to do more than just "be root," but to
-run in the root account's environment. This is accomplished with the
-"su -" command and provides you with root's normal path, including the /sbin
-directory. The unfortunate side-effect is that you wind up in root's home
-directory, requiring you to <i>cd</i> back to the original directory in
-which you were working.
-
-</a></p><blockquote><pre><a name="root">[jej@ayukawa src]$ pwd
-/home/jej/src/linuxwacom/src
-[jej@ayukawa src]$ su -
-[root@ayukawa root]# cd /home/jej/src/linuxwacom/src
-[root@ayukawa src]# echo $PATH
-/bin:<b>/sbin</b>:/usr/bin: ... :/root/bin
-</a></pre></blockquote>
-
-<p><a name="root">Here, the user starts in the package's src directory, but upon invoking
-"su -" is magically shuttled off to root's home directory. A quick
-<i>cd</i> back to the package directory and all is better. And, as
-demonstrated above, the path conveniently contains /sbin.
-
-</a></p><p><a name="root">So that leaves you with two immediate options, and one potential
-long-term option:
-
-</a></p><p><a name="root">Option One: Become root and add /sbin to the path.
-
-</a></p><blockquote><pre><a name="root">[jej@ayukawa src]$ su
-[jej@ayukawa src]# export PATH=$PATH:/sbin
-</a></pre></blockquote>
-
-<a name="root">Option Two: Become root using root's environment and <i>cd</i> back.
-
-</a><blockquote><pre><a name="root">[jej@ayukawa src]$ su -
-[root@ayukawa root]# cd /home/jej/src/linuxwacom/src
-</a></pre></blockquote>
-
-<a name="root">Option Three (recommended): Add /sbin to your personal account's path
-
-</a><blockquote><pre><a name="root">[jej@ayukawa src]$ export PATH=$PATH:/sbin
-[jej@ayukawa src]$ su
-[root@ayukawa src]# echo $PATH
-/bin:/usr/bin: ... :/home/jej/bin:<b>/sbin</b>
-</a></pre></blockquote>
-
-<p><a name="root">By adding the path early in the session, it becomes available every time
-you <i>su</i> to root later on. You could also add the <i>export</i>
-command to the .bash_profile file in your home directory and have the
-path set automatically when you log in.
-
-</a></p><p><a name="root">To exit from the root account and return to your normal account, you can
-use the <i>exit</i> command or type Ctrl-D on an empty line.
-
-</a></p><blockquote><pre><a name="root">[root@ayukawa src]# exit
-[jej@ayukawa src]$
-</a></pre></blockquote>
-
-<p><a name="root">If any of this is not explained clearly, drop me a line and let me know
-where you got stuck. I'd be happy to clarify directly and update this page
-for future readers.
-</a><a name="install">
-</a></p><h2><a name="install">2.4 - Install from Prebuilt </a></h2>
-
-<p><a name="install">We have created 2 sets of prebuilt Wacom X driver and its utility programs under
-linuxwacom-0.8.2-2/prebuilt; one for x86-32 systems, the other for x86-64 systems.
-
-</a></p><p><a name="install">If you don't plan to change anything in the driver, following steps will install the prebuilt files for you:
-
-</a></p><p><a name="install"><b>Note:</b> Please remove the existing linuxwacom package first if your system has one.
-
-</a></p><blockquote><pre><a name="install">[jej@ayukawa jej]$ cd linuxwacom-0.8.2-2/prebuilt
-[jej@ayukawa prebuilt]$ su
-[jej@ayukawa prebuilt]# ./uninstall
-[jej@ayukawa prebuilt]# ./install
-</a></pre></blockquote>
-
-<p><a name="install">Serial tablet (most Tablet PCs are serial) users can skip the rest
-sections and go to </a><a href="#wacdump">Viewing Wacom Data (wacdump)</a> page for details on viewing the tablet output now.
-
-</p><p>If you use an older USB tablet and your running kernel was released 6 months later than
-your tablet was first seen in market, you most probably can skip next section of this chapter
-and the whole chapter 4 too. If you would like to make certain, continue to next section.
-<a name="config">
-</a></p><h2><a name="config">2.5 - Configuring the Package</a></h2>
-
-<p><a name="config">This section describes how to configure the package. You can run
-the configure script now as the samples below demonstrate, or later
-when you reach the section of the document that explains what
-specifically needs to be configured and why. This page is provided
-largely as a reference.
-
-</a></p><p><a name="config">By default, xidump, wacdump, xsetwacom, wacom_drv.o, and wacomcpl
-are built. Additional options include replacement of kernel drivers
-for hid, mousedev, evdev, and usbmouse as well as building the
-XFree86/Xorg driver from scratch. Lastly, remember that for every
---enable option, there is also an equivalent --disable option.
-
-</a></p><p><a name="config">The configuration options are listed on this page. You can also
-see the online list by issuing <i>./configure -help</i> under
-linuxwacom's base directory.
-
-</a></p><p><a name="config"><b>Note: </b> You should remove the existing linuxwacom package on
-your system before installing the drivers and utilities from this project.
-
-</a></p><h3><a name="config">Building Kernel Modules - USB Only</a></h3>
-
-<p><a name="config">In order to build kernel modules, you will need the kernel source
-installed on your system. If you are running on Redhat or Mandrake,
-you can get it by installing the kernel-source RPM.
-
-</a></p><p><a name="config">The kernel source directory is assumed to be in /usr/src/linux-2.4,
-/usr/src/linux, /usr/src/linux-2.6, /usr/src/linux-`uname -r`, or
-/lib/modules/`uname -r`/source. If your kernel sources are elsewhere,
-you will need to specify the directory with the --with-kernel option
-described below.
-
-</a></p><p><a name="config">For older 2.6 kernels, you need to configure the kernel modules (wacom
-and hid) under your kernel source directory before configuring linuxwacom.
-
-</a></p><p class="diff"><a name="config">Note, for kernel 2.6.18 and later, no need to build hid
-any more. Refer to </a><a href="#testtablet">Testing Tablet Detection</a> to see if you need to build hid or not.</p>
-
-<h3>Module Versioning - USB Only</h3>
-
-<p>The script attempts to discover if the kernel is using module
-versioning by detecting the presence of version numbers in the hid.o
-module of the currently active kernel. Recent package versions also
-check for hid.o.gz which exist on Mandrake systems. The configure
-script may not be able to determine if kernel module versioning
-should be enabled or not, in which case it will say "unknown,
-assuming no."
-
-</p><p>If module versioning is disabled when it should be enabled, depmod
-will complain about missing symbols but otherwise, things will probably
-work fine. If it is enabled when it should be disabled, the code may
-not compile, and it almost certainly will not load properly. If the
-configure script fails to determine the correct value, the default
-action of disabling module versioning is the better choice, and you can
-allows enable it manually and rebuild if depmod complains.
-
-</p><h3>The XFree86/Xorg XInput Driver - USB and Serial</h3>
-
-<p>Generally, you will not need to build wacom_drv.o since it ships in
-binary form in the prebuilt directory. There are prebuilt binaries for
-XFree86 and Xorg corresponding to x86 and x86-64 systems, respectively.
-If no one works for you, building from source may be your only option.
-See the <a href="#builddrv">Building wacom_drv.o from Scratch</a>
-page for more information.
-
-</p><h3>Library Dependencies - ncurses and XLib</h3>
-
-<p>Various utilities in the linuxwacom package require not only specific
-libraries, but their development header files as well. The ncurses
-package is one such example. Most distributions install the ncurses
-libraries by default, but the header files are often located in a
-separate package. You will need both. On Redhat 8.0, they can be
-found in the ncurses-devel RPM.
-
-</p><p>Similarly, if you wish to test your tablet using xidump to view
-XFree86/Xorg input events, you will need the XFree86/Xorg development
-headers. On Redhat/Fedore Core, they are contained in the XFree86-devel/xorg-sdk package.
-
-</p><p>If any packages are missing, the configuration will warn you and
-disable building any programs that depend on them.
-
-</p><h3>Processor Type</h3>
-
-<p>The processor type is determined by the script and used to build the
-kernel modules. If it guesses incorrectly, or you would prefer a
-different setting, use the --with-arch option described below.
-
-</p><h3>Linux Specific Features</h3>
-
-<p>The Linux wacom driver uses the Linux input subsystem, as does the
-USB portions of the XFree86/Xorg driver. Consequently, if you are
-building on a non-Linux system, the USB code will not work for you.
-This is detected, and a comment to that effect is added to the
-configuration summary. I recognize that FreeBSD and similar systems
-have USB support; however, until someone can bridge the gap between
-the FreeBSD kernel and the XFree86/X.org driver, the problem is largely
-unsolved. Contributions are of course welcome. The Linux-specific
-features can be enabled/disabled using the --with-linux argument.
-
-</p><h3>Configuration Options</h3>
-
-The following options are provided as reference. Normally, you will
-only need a few of these options. Some obscure systems or you want to
-build a driver for another platform may need all of them. Each section
-of the document identifies which options are needed and when.<br><br>
-
-<table border="0" cellspacing="5">
-<tbody><tr><th align="left">Option</th><th align="left">Default</th>
- <th align="left">Builds</th></tr>
-<tr><td>--enable-wacom</td><td><b>no</b></td>
- <td>wacom.o kernel driver</td></tr>
-<tr><td>--enable-wacdump</td><td><b>yes</b></td>
- <td>wacdump LinuxInput event monitor</td></tr>
-<tr><td>--enable-xidump</td><td><b>yes</b></td>
- <td>xidump XInput event monitor</td></tr>
-<tr><td>--enable-libwacomcfg</td><td><b>yes</b></td>
- <td>libwacomcfg Dynamic library for xsetwacom</td></tr>
-<tr><td>--enable-libwacomxi</td><td><b>yes</b></td>
- <td>libwacomxi Dynamic library for wacomcpl</td></tr>
-<tr><td>--enable-xsetwacom</td><td><b>yes</b></td>
- <td>xsetwacom XFree86 wacom driver configuration
- comannd</td></tr>
-<tr><td>--enable-quirk-tablet-rescale</td><td>best guess</td>
- <td>Enable tablet to screen rescale code. <b> Note: </b>
- If you have TwinView setup running on a X server 1.4 and later,
- and your mappping doesn't properly, enable this option may
- resolve the issue.</td></tr>
-<tr><td>--enable-quirk-Uninit-called</td><td>best guess</td>
- <td>Enable Uninit called</td></tr>
-<tr><td>--enable-hid</td><td>no</td>
- <td>hid.o replacement kernel driver (not normally
- needed)</td></tr>
-<tr><td>--enable-usbmouse</td><td>no</td>
- <td>usbmouse.o replacement kernel driver (not
- normally needed)</td></tr>
-<tr><td>--enable-evdev</td><td>no</td>
- <td>evdev.o replacement kernel driver (not
- normally needed)</td></tr>
-<tr><td>--enable-mousedev</td><td>no</td>
- <td>mousedev.o replacement kernel driver (not
- normally needed)</td></tr>
-<tr><td>--enable-wacomdrv</td><td><b>yes</b></td>
- <td>wacom_drv.o XFree86/Xorg driver (binary is
- available in prebuilt directory)</td></tr>
-<tr><td>--enable-modver=yes|no</td><td>best guess</td>
- <td>enables kernel module versioning; usually
- guesses correctly, but can be enabled or
- disabled if not</td></tr>
-<tr><td>--with-kernel=dir</td><td>best guess</td>
- <td>Specifies the kernel source directory if
- configure cannot guess correctly.</td></tr>
-<tr><td>--with-x-src=dir</td><td>best guess</td>
- <td>Specifies the X driver build source
- directory</td></tr>
-<tr><td>--with-xorg-sdk=dir</td><td>best guess</td>
- <td>Specifies the Xorg SDK directory</td></tr>
-<tr><td>--with-tcl=dir</td><td>/usr</td>
- <td>Specifies the tcl directory. The tcl's include
- and lib directories should be under this directory.
- If tcl.h is not in dir/include, it will be searched
- under dir directly</td></tr>
-<tr><td>--with-tk=dir</td><td>/usr</td>
- <td>Specifies the tk directory. If tk is under the
- same directory as tcl, this option can be
- eliminated. Otherwise, the tk's include and lib
- directories should be under this directory. If tk.h
- is not in dir/include, it will be searched under
- dir directly</td></tr>
-<tr><td>--with-arch=arch</td><td>best guess</td>
- <td>Specifies the architecture if configure guesses
- incorrectly</td></tr>
-<tr><td>--enable-xserver64=yes|no</td><td>best guess</td>
- <td>enables 64-bit X server. You probably need to
- define xlib directory by adding option
- --with-xlib=xlib-dir so compiler can link with
- the right Xlib.</td></tr>
-<tr><td>--with-linux=yes|no</td><td>best guess</td>
- <td>Specifies if compiled on a Linux system; USB
- code is Linux specific</td></tr>
-<tr><td>--with-xlib=yes|no</td><td>best guess</td>
- <td>Specifies if building xlib-based programs;
- xidump uses XInput headers</td></tr>
-<tr><td>--enable-dlloader=yes|no</td><td>best guess</td>
- <td>Enable dlloader build option and built
- wacom_drv.so instead of wacom_drv.o</td></tr>
-<tr><td>--with-xmoduledir=dir</td><td>best guess</td>
- <td>Specify wacom_drv path explicitly.
- Implies --enable-dlloader</td></tr>
-</tbody></table>
-
-<h3>Configuration Samples</h3>
-
-<p>Here is a sample output of the script on a Fedora Core 5 system:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$ ./configure
+the kernel driver to the gimp application.
+<A NAME="starthere">
+<H1>2.0 - Getting It Together</H1>
+<P>This section is devoted to preparing your system for the installation.
+In some cases, your distribution may have automatically loaded certain
+modules which you will now need to unload. Incidentally, some distributions
+detect new hardware on boot. If you allow Redhat's "anaconda" for instance
+to automatically configure (or remove) your tablet, it may undo some of the
+settings you will make here. Until Redhat's installation program recognizes
+Wacom tablets as non-HID devices by default, you are best off in my opinion
+to <i>not</i> allow it to configure the device. Just a warning.
+<A NAME="beforestart">
+<H2>2.1 - Before We Start</H2>
+<P>From the beginning, let's make certain that we are on the
+same page. First, unplug the USB Wacom. If you have Wacom related lines
+in your XF86Config file, you should comment them out or remove them; then
+restart X.<BR>
+
+<P>Unload the old modules.
+<BLOCKQUOTE><PRE>
+[jej@ayukawa jej]$ su -
+[root@ayukawa root]# lsmod | grep wacom
+<B>wacom</B> 8020 0 (unused)
+input 5920 0 [<B>evdev</B> <B>wacom</B> mousedev keybdev hid]
+usbcore 77024 1 [<B>wacom</B> usb-storage snd printer hid usb-uhci]
+[root@ayukawa root]# rmmod wacom evdev
+</PRE></BLOCKQUOTE>
+
+The kernel now knows nothing about the Wacom or how to handle event-based
+input devices. If you get an error unloading (busy driver perhaps), try
+rebooting.<BR>
+
+<P>Check the presence of the input devices in the /dev/input directory.
+You should find approximately 114 devices with names such as event*, mouse*,
+keyboard, js*, and ttyACM*. We are interested in two devices, mouse0 and
+event0.
+
+<BLOCKQUOTE><PRE>
+[root@ayukawa root]# cd /dev/input
+[root@ayukawa input]# ls -la mouse0 event0
+crw------- 1 root root 13, 64 Aug 30 16:31 event0
+crw------- 1 root root 13, 32 Aug 30 16:31 mouse0
+[root@ayukawa input]# xxd mouse0
+xxd: mouse0: No such device
+[root@ayukawa input]# xxd event0
+xxd: event0: No such device
+</PRE></BLOCKQUOTE>
+
+<P>On some distributions, Mandrake 9.0 for instance, the /dev directory is
+managed by devfs; Redhat 8.0 does not use it. When devfs is running, the
+/dev/input directory and/or its contents may be missing if the driver is not
+loaded. If you are not using devfs and the /dev/input directory or
+mouse0/event0 devices are not present, your distribution may be lacking these
+devices. This could be an oversight, or it could be an indication that your
+distribution is too old.
+
+<P>If after executing <i>xxd mouse0</i> you <B>did not</B>
+receive the "xxd: mouse0: No such device" message, then the input device
+is still loaded; go back and try running <i>rmmod evdev</i> again.
+Once the new drivers are compiled and installed, this command will stream
+information from the Wacom tablet. mouse0 behaves like a PS/2 style mouse.
+event0 provides extensive information about the tablet including position,
+tilt, pressure, and buttons. It can also track at least two different tools
+simultaneously (Intuos2).<BR>
+<A NAME="download">
+<H2>2.2 - Downloading the Code</H2>
+The file <A HREF="/wacom/wacpack-0.2.0.tar.gz">wacpack-0.2.0.tar.gz</A> is the stable package and contains
+files that you will need to get the tablet working. The current beta
+package <A HREF="/wacom/wacpack-0.3.3-beta.tar.gz">wacpack-0.3.3-beta.tar.gz</A> is also available and may be
+used by people who are willing to risk an occasional kernel panic to help
+test new features. I will never put a beta package on this site that I am
+not running myself on my primary development machine, so you can be certain
+that if there are any obvious show stoppers, they will be fixed before you
+get to see them.
+
+
+<H3>Stable files included for wacpack-0.2.0:</H3>
+<TABLE BORDER=0 CELLSPACING=5>
+<TR><TH ALIGN=LEFT>File</TH><TH ALIGN=LEFT>Comment</TH></TR>
+<TR><TD VALIGN=TOP>configure</TD><TD>- configure script for distribution independent builds</TD></TR>
+<TR><TD VALIGN=TOP>prebuilt/wacom_drv.o</TD><TD>- binary X11 driver for the wacom (26-j0.2.0)</TD></TR>
+<TR><TD VALIGN=TOP>src/wacom.c</TD><TD>- a stable, working kernel driver (1.30-j0.2.0)</TD></TR>
+<TR><TD VALIGN=TOP>src/wacdump.c</TD><TD>- a simple program for displaying tablet event data directly using ncurses; current version is 0.2.0</TD></TR>
+<TR><TD VALIGN=TOP>src/usbmouse.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/hid-core.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/hiddev.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/hid-input.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/xf86Wacom.c</TD><TD>- source for wacom_drv.o; requires XF86 build environment to compile. Binary available in prebuilt directory.</TD></TR>
+<TR><TD VALIGN=TOP>GPL</TD><TD>- the GNU General Public License, in case you did not already have twenty or more lying around</TD></TR>
+</TABLE>
+
+<H3>Beta files included for wacpack-0.3.2-beta:</H3>
+<TABLE BORDER=0 CELLSPACING=5>
+<TR><TH ALIGN=LEFT>File</TH><TH ALIGN=LEFT>Comment</TH></TR>
+<TR><TD VALIGN=TOP>configure</TD><TD>- configure script for distribution independent builds</TD></TR>
+<TR><TD VALIGN=TOP>prebuilt/wacom_drv.o</TD><TD>- binary X11 driver for the wacom (26-j0.3.2a)</TD></TR>
+<TR><TD VALIGN=TOP>src/wacom.c</TD><TD>- a stable, working kernel driver (1.30-j0.3.1)</TD></TR>
+<TR><TD VALIGN=TOP>src/wacdump.c</TD><TD>- a simple program for displaying tablet event data directly using ncurses; current version is 0.3.2</TD></TR>
+<TR><TD VALIGN=TOP>src/usbmouse.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/hid-core.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/hiddev.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/hid-input.c</TD><TD>- replacement kernel driver (2.4.19), use only if needed</TD></TR>
+<TR><TD VALIGN=TOP>src/xf86Wacom.c</TD><TD>- legacy source for wacom_drv.o; requires XF86 build environment to compile.</TD></TR>
+<TR><TD VALIGN=TOP>src/wcm-beta.c</TD><TD>- beta source for wacom_drv.o; requires XF86 build environment to compile.</TD></TR>
+<TR><TD VALIGN=TOP>src/wcm-beta.h</TD><TD>- beta source for wacom_drv.o; requires XF86 build environment to compile.</TD></TR>
+<TR><TD VALIGN=TOP>GPL</TD><TD>- the GNU General Public License, in case you did not already have twenty or more lying around</TD></TR>
+</TABLE>
+
+<H3>Stable Packages by Version and Date:</H3>
+<TABLE BORDER=0 CELLSPACING=5>
+<TR><TH ALIGN=LEFT>File</TH><TH ALIGN=LEFT>Date</TH><TH ALIGN=LEFT>Comment</TH></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.2.0.tar.gz">wacpack-0.2.0.tar.gz</A></TD><TD> - 2002-11-24</TD><TD>Configure-based package</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1b.tar.gz">wacpack-0.1b.tar.gz</A></TD><TD> - 2002-11-06</TD><TD></TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1a.tar.gz">wacpack-0.1a.tar.gz</A></TD><TD> - 2002-11-05</TD><TD></TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1.tar.gz">wacpack-0.1.tar.gz</A></TD><TD> - 2002-11-04</TD><TD></TD></TR>
+</TABLE>
+<H3>Beta Packages by Version and Date:</H3>
+<TABLE BORDER=0 CELLSPACING=5>
+<TR><TH ALIGN=LEFT>File</TH><TH ALIGN=LEFT>Date</TH><TH ALIGN=LEFT>Comment</TH></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.3.3-beta.tar.gz">wacpack-0.3.3-beta.tar.gz</A></TD><TD> - 2002-12-22</TD><TD>Serial Intuos2, serial wacdump, Volito added, USB mouse wheel direction fixed, kernel 2.4.20 friendly</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.3.2-beta.tar.gz">wacpack-0.3.2-beta.tar.gz</A></TD><TD> - 2002-12-15</TD><TD>Fix for 4D mice and working beta driver shell</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.3.1-beta.tar.gz">wacpack-0.3.1-beta.tar.gz</A></TD><TD> - 2002-12-13</TD><TD>Fix for 2D mice and relative events in wacdump</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.3.0-beta.tar.gz">wacpack-0.3.0-beta.tar.gz</A></TD><TD> - 2002-11-24</TD><TD>Configure-based package</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1g-beta.tar.gz">wacpack-0.1g-beta.tar.gz</A></TD><TD> - 2002-11-14</TD><TD>wacdump updated; displays ranges, cleaner output</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1f-beta.tar.gz">wacpack-0.1f-beta.tar.gz</A></TD><TD> - 2002-11-14</TD><TD>build environment for xf86Wacom added</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1e-beta.tar.gz">wacpack-0.1e-beta.tar.gz</A></TD><TD> - 2002-11-11</TD><TD>fixed range for I2-6x8</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1d-beta.tar.gz">wacpack-0.1d-beta.tar.gz</A></TD><TD> - 2002-11-10</TD><TD>updated wacdump, fixed range for I2-12x12</TD></TR>
+<TR><TD VALIGN=TOP><A HREF="/wacom/wacpack-0.1c-beta.tar.gz">wacpack-0.1c-beta.tar.gz</A></TD><TD> - 2002-11-09</TD><TD>updates to range, pressure, and mouse events</TD></TR>
+</TABLE>
+<A NAME="config">
+<H2>2.3 - Configuring the Package</H2>
+
+Versions of wacpack-0.2.0 and greater are based on GNU's configure script
+based build environment. The upside is that more details are guessed by
+default. The downside is that the default configuration builds only the
+kernel driver and wacdump programs (which should cover almost everybody),
+but if you need a different module built, you will have to reconfigure the
+package first. This is mostly because different modules have different
+dependencies, some of which are difficult to resolve.
+A list of the options currently available in the stable package is
+presented below. Remember that for every --enable option, there is also
+an equivalent --disable option.
+
+<BR><BR>
+
+<TABLE BORDER=0 CELLSPACING=5>
+<TR><TH ALIGN=LEFT>Option</TH><TH ALIGN=LEFT>Default</TH>
+ <TH ALIGN=LEFT>Builds</TH></TR>
+<TR><TD>--enable-wacom</TD><TD><B>yes</B></TD>
+ <TD>wacom.o kernel driver</TD></TR>
+<TR><TD>--enable-wacdump</TD><TD><B>yes</B></TD>
+ <TD>wacdump event monitor</TD></TR>
+<TR><TD>--enable-hid</TD><TD>no</TD>
+ <TD>hid.o replacement kernel driver (not normally necessary)</TD></TR>
+<TR><TD>--enable-usbmouse</TD><TD>no</TD>
+ <TD>usbmouse.o replacement kernel driver (not normally necessary)</TD></TR>
+<TR><TD>--enable-wacomdrv</TD><TD>no</TD>
+ <TD>wacom_drv.o XFree86 driver (binary is available in prebuilt directory)</TD></TR>
+<TR><TD>--enable-modver</TD><TD>best guess</TD>
+ <TD>enables kernel module versioning; usually guesses correctly, but
+ can be enabled or disabled if not</TD></TR>
+<TR><TD>--with-kernel=dir</TD><TD>best guess</TD>
+ <TD>Specifies the kernel source directory if configure cannot guess correctly.</TD></TR>
+<TR><TD>--with-xf86=dir</TD><TD>none</TD>
+ <TD>Specifies the XFree86 build directory.</TD></TR>
+<TR><TD>--with-arch=arch</TD><TD>best guess</TD>
+ <TD>Specifies the architecture if configure guesses incorrectly.</TD></TR>
+</TABLE>
+
+<P>Chances are high that you will be able to run the configure script without
+any options and have it execute correctly. Here is a sample output of the
+script on a Redhat 8.0 system:
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacpack]$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
-checking for arch type... <b>i386-redhat-linux</b>
-checking for kernel type... <b>Linux</b>
-checking for linux-based kernel... <b>yes</b>
-checking for kernel sources... <b>/lib/modules/2.6.20-1.2320.fc5/source</b>
-checking for kernel module support... <b>yes</b>
-checking for kernel module versioning... <b>yes</b>
-checking for valid Xorg SDK... <b>ok</b>
-checking for X... <b>libraries , headers</b>
-...
-checking for X lib directory... <b>found</b>
-checking for tclsh... <b>/usr/bin/tclsh</b>
-checking for tcl version... <b>8.4</b>
-checking for tcl header files... <b>/usr/include/</b>
-checking for tk header files... <b>found</b>
-checking ncurses.h usability... <b>yes</b>
-checking ncurses.h presence... <b>yes</b>
-checking for ncurses.h... <b>yes</b>
+checking for processor type... <B>i686</B>
+checking for kernel module versioning... <B>yes</B>
+checking for kernel sources... <B>/usr/src/linux-2.4</B>
...
+
----------------------------------------
BUILD ENVIRONMENT:
- architecture - i386-redhat-linux
- linux kernel - yes 2.6.19
- module versioning - yes -DCONFIG_MODVERSIONS -DMODVERSIONS -include /lib/modules/2.6.20-1.2320.fc5/source/include/linux/modversions.h
- kernel source - yes /lib/modules/2.6.20-1.2320.fc5/source
- Xorg SDK - yes /usr/include/xorg
- XSERVER64 - no
- dlloader - yes
- XLib - yes /usr/lib
- TCL - yes /usr/include
- TK - yes /usr/include
- ncurses - yes
+ architecture - i686
+ module versioning - yes
+ kernel - yes
+ XFree86 - no
BUILD OPTIONS:
- wacom.o - no
+ wacom.o - yes
wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
hid.o - no
usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
- wacom_drv.so - yes /usr/lib/xorg/modules/input
wacom_drv.o - no
- wacom*_drv quirks - libc-wrapper key-events dixScreenOrigins
----------------------------------------
-</pre></blockquote>
-
-<p>If the configure script fails to find something that it is looking
-for, it may disable some options that you previously enabled on the
-command-line. If this happens, check the output for a warning like the
-following:
-
-</p><blockquote><pre>checking for valid XFree86/X.org build environment... xf86Version.h missing
-Tried /usr/programs/Xserver/hw/xfree86 and /usr/xc/programs/Xserver/hw/xfree86
-...
-***
-*** WARNING:
-*** Unable to compile wacom_drv.{o,so}
-*** without Xorg SDK or XFree86 build environment
-*** wacom_drv.o will not be built
-***
-</pre></blockquote>
-
-<p>In this particular case, the X driver was enabled. The
---with-x-src option was not specified. And the configure can not find
-the header file, xf86Version.h, under any of the predefined paths.
-Without the build environment, the module cannot be compiled and was consequently disabled.
-
-
-</p><p>The following sample command-line will build everything but wacdump
-while disabling module versioning. It also has a user-specified kernel
-source directory:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$ ./configure --enable-wacom \
- --enable-hid --enable-usbmouse --enable-evdev \
- --enable-moudedev --enable-input --disable-modver \
- --with-x-src=/usr/src/redhat/BUILD/XFree86-4.2.0 \
- --with-kernel=/home/jej/src/linux \
- --disable-wacdump --with-tcl=/usr/local/ActiveTcl
+</PRE></BLOCKQUOTE>
+
+<P>The processor type is determined by the script and used to build the
+kernel modules. Similarily, the script attempts to discover if the kernel
+is using module versioning by looking for version numbers in the usb.o
+module of the currently active kernel. This may not work well on all
+distributions, so if you get a line like "checking for kernel module versioning... confused" or "maybe; assuming yes", you'll have to manually enable or
+disable the option if it guesses incorrectly.
+
+<P>The kernel source directory is assumed to be either /usr/src/linux-2.4
+or /usr/src/linux. If your kernel sources are elsewhere, you will need to
+specify the directory with the --with-kernel option.
+
+<P>Generally, you will not need to build wacom_drv.o since it ships in
+binary form in the prebuilt directory. It is compiled with glibc with
+gcc 3.2 on a Redhat 8.0 system; if this will not work for you, building
+from source may be your only option. See the
+<A HREF="#builddrv">Building wacom_drv.o From Scratch</A> page
+for more information.
+
+<P>The configure script is pretty simple, so if you find any problems and
+are inclined to fix them, please send me your patch so I can include the
+change in future releases.
+
+<P>The following sample command-line will build everything but wacdump
+while disabling module versioning:
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacpack]$ ./configure --enable-hid --enable-usbmouse \
+ --enable-wacomdrv --with-xf86=/usr/src/redhat/BUILD/XFree86-4.2.0 \
+ --disable-modver --disable-wacdump
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
checking for processor type... i686
-checking for kernel module versioning... <b>yes</b>
+checking for kernel module versioning... <B>yes</B>
checking for kernel sources... /usr/src/linux-2.4
-checking for valid XFree86 build environment... <b>ok</b>
+checking for valid XFree86 build environment... <B>ok</B>
...
----------------------------------------
BUILD ENVIRONMENT:
architecture - i686
- linux kernel - yes 2.4
- module versioning - <b>no</b>
- kernel source - <b>yes /home/jej/src/linux</b>
- XFree86 - <b>yes /usr/src/redhat/BUILD/XFree86-4.2.0</b>
- XLib - yes /usr/X11R6/lib
- TCL - <b>yes /usr/local/ActiveTcl</b>
- TK - <b>yes /usr/local/ActiveTcl</b>
- ncurses - yes
-
- BUILD OPTIONS:
- wacom.o - <b>yes</b>
- wacdump - <b>no</b>
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
- hid.o - <b>yes</b>
- usbmouse.o - <b>yes</b>
- evdev.o - <b>yes</b>
- mousedev.o - <b>yes</b>
- input.o - <b>yes</b>
- tabletdev.o - no
- wacom_drv.so - no
- wacom_drv.o - <b>yes</b>
- wacom*_drv quirks - libc-wrapper key-events
-----------------------------------------
-</pre></blockquote>
-
-<p>Notice that the configure script guessed module versioning was
-enabled by default, but was disabled by the command-line option
---disable-modver. Similarly, the wacdump program which is enabled
-by default was also disabled. All the kernel modules and the
-XFree86 wacom driver are enabled.
-
-
-</p><p>Here is another sample from Red Hat Enterprise Linux ES v.4:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom-x86-64]$ ./configure \
- --enable-wacom --enable-hid \
- --with-xf86=/home/jej/Desktop/X11R6.8 \
- --with-tcl=/usr/local/ActiveTcl \
- <b>--enable-xserver64 \
- --with-xlib=/usr/X11R6/lib64 </b>
-checking for a BSD-compatible install... /usr/bin/install -c
-checking whether build environment is sane... yes
-...
-checking build system type... x86_64-redhat-linux-gnu
-checking host system type... x86_64-redhat-linux-gnu
-checking for ld used by g++... /usr/bin/ld -m elf_x86_64
-...
-
-----------------------------------------
- BUILD ENVIRONMENT:
- architecture - <b>x86-64</b>
- linux kernel - yes 2.6.9
- module versioning - yes -DCONFIG_MODVERSIONS -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h
- kernel source - yes /usr/src/linux
- XFree86 - yes /home/jej/Desktop/X11R6.8
- XSERVER64 - <b>yes</b>
- XLib - <b>yes /usr/X11R6/lib64</b>
- TCL - yes /usr/local/ActiveTcl
- TK - yes /usr/local/ActiveTcl
- ncurses - yes
+ module versioning - <B>no</B>
+ kernel - yes
+ XFree86 - <B>yes</B>
BUILD OPTIONS:
wacom.o - yes
- wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
- hid.o - yes
- usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
- wacom_drv.so - no
- wacom_drv.o - yes
- wacom*_drv quirks - libc-wrapper key-events
+ wacdump - <B>no</B>
+ hid.o - <B>yes</B>
+ usbmouse.o - <B>yes</B>
+ wacom_drv.o - <B>yes</B>
----------------------------------------
-</pre></blockquote>
+</PRE></BLOCKQUOTE>
-<a name="kernel">
-</a><h1><a name="kernel">3.0 - The USB Kernel Driver</a></h1>
-<p><a name="kernel">Serial tablet users rejoice: you can skip this entire section. Please
-go to the </a><a href="#wacdump">Viewing Wacom Data (wacdump)</a> page for details on viewing the tablet output.
-USB users stay put; we need to tweak your kernel.
+<P>Notice that the configure script guessed module versioning was enabled
+by default, but was disabled by the command-line option --disable-modver.
+Similarly, the wacdump program which is enabled by default was also disabled.
+All the kernel modules and the XFree86 wacom driver are enabled.
-</p><p>Kernel modules must be recompiled for each new kernel so I can't
+<P>If the configure script fails to find something that it is looking for,
+it may disable some options that you previously enabled on the command-line.
+If this happens, check the output for a warning like the following:
+
+<BLOCKQUOTE><PRE>
+***
+*** WARNING:
+*** Unable to compile wacom_drv.o without XF86 build environment
+*** wacom_drv.o will not be built
+***
+</PRE></BLOCKQUOTE>
+
+<P>In this particular case, the XFree86 driver was enabled, but the
+--with-xf86 option was not specified. Without the build environment,
+the module cannot be compiled and was consequently disabled.
+<A NAME="kernel">
+<H1>3.0 - The Kernel Driver</H1>
+<P>The kernel driver for the Wacom Intuos that ships with the
+Linux kernel through 2.4.19, and in particular Redhat 8.0, does
+not work correctly. The bug is pretty simple and you can fix it yourself.
+Optionally, you can compile the version that I provide directly and swap
+the new module for the old one. This avoids having to rebuild the entire
+kernel.</P>
+
+<P>Kernel modules must be recompiled for each new kernel so I can't
just provide binaries. By the time you read this, my present kernel
-will be entirely out of date with yours. </p>
-
-<p>In any event, many new features are available in the latest drivers
-from the Linux Wacom Project, so I wholly recommend using them over the
-drivers provided by your standard distribution. Rest assured, continuous
-efforts are being made to get these changes merged back into the Linux
-kernel. However, the changes can normally only merged into the next
-kernel release, instead of the current one. </p>
-
-<p>For those who don't like upgrading kernels, here is a safe statement:
-if you are not using a newly released tablet model and you are running a
-recently released kernel version, chances are that you don't need to
-update your kernel driver from linuxwacom.</p>
-
-<p><b>Note:</b> If your system is running a 2.4 kernel and you don't have
-any application required to run on kernel 2.4, upgrading to version 2.6
-(preferablely 2.6.18 or later) may save you the steps to update wacom
-kernel related modules. </p>
-<a name="testtablet">
-</a><h2><a name="testtablet">3.1 - Testing Tablet Detection</a></h2>
-
-<p><a name="testtablet">In this section we will determine which driver, if any, claims control
-over the tablet. There are at least three drivers that are interested: <br>
-1) (usb)hid.o which may think it is an HID device, <br>
-2) usbmouse.o which may think it is an HID mouse (for kernel 2.4), and <br>
-3) the wacom driver which should identify the tablet as its own. <br>
-
-</a></p><p><a name="testtablet">To see which driver is driving the tablet, issuing <i>more /proc/bus/usb/devices</i>
-should list something similiar to the following:
-
-</a></p><blockquote><pre><a name="testtablet">[jej@ayukawa wacom]$more /proc/bus/usb/devices
-T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=12 MxCh= 0
-D: Ver= 1.10 Cls=00(&gt;ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
-P: <b>Vendor=056a ProdID=0042</b> Rev= 1.15
-S: Manufacturer=Tablet
-S: Product=XD-0608-U
-C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=140mA
-I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 <b>Driver=wacom</b>
-E: Ad=81(I) Atr=03(Int.) MxPS= 10 Ivl=5ms
-</a></pre></blockquote>
-
-<p><a name="testtablet">where <b>Vendor=056a</b> indicates a Wacom device. <b>Driver=wacom</b>
-means Wacom driver is in control of the tablet. If you see anything other
-than <b>wacom</b> after <b>Driver=</b>, at least hid-core.c needs to be
-updated.
-
-</a></p><p><a name="testtablet">On newer 2.6 systems, <i>more /proc/bus/input/devices</i> gives you
-
-</a></p><blockquote><pre><a name="testtablet">[jej@ayukawa wacom]$more /proc/bus/input/devices
-I: Bus=0003 <b>Vendor=056a Product=0042</b> Version=1.15
-N: <b>Name="Wacom Intuos2 6x8"</b>
-P: Phys=usb-0000:00:1d.1-2/input0
-H: Handlers=event3
-B: EV=1f
-B: KEY=1cff 0 1f00ff 0 0 0 0 0 0 0 0
-B: REL=100
-B: ABS=f00017b
-B: MSC=1
-</a></pre></blockquote>
-
-<p><a name="testtablet">where, again, <b>Vendor=056a</b> indicates a Wacom device. <b>Name="Wacom
- Intuos2 6x8"</b> means an Intuos2 6x8 tablet reported to /dev/input/event3.
-If there is no <b>Wacom</b> after <b>Name=</b>, you need to update wacom.c.
-
-
-</a></p><p><a name="testtablet">On kernel 2.4 or older 2.6 systems, unplug then replug your tablet after
-issuing <i>tail -f /var/log/messages</i>, you should see a flurry of activity.
-The exact output depends a lot on your particular kernel and distribution.
-
-</a></p><blockquote><pre><a name="testtablet">This is Redhat 8.0 (2.4.18-17.8.0):<br>
-[jej@ayukawa usb]# tail /var/log/messages
-Apr 29 21:26:11 ayukawa kernel: hub.c: USB new device connect on bus2/2, assigned device number 2
-Apr 29 21:26:11 ayukawa kernel: <b>input0: Wacom Intuos2 12x12</b> on usb2:2.0
-Apr 29 21:26:11 ayukawakernel: <b>wacom.c: Setting tablet report for tablet data</b>
-Apr 29 21:26:11 ayukawa kernel: <b>wacom.c: input1: Wacom Intuos2 12x12</b> on usb1:6.0
-Apr 29 21:26:14 ayukawa /etc/hotplug/usb.agent: Setup wacom hid for USB product <b>56a/44</b>/115
-Apr 29 21:26:14 ayukawa /etc/hotplug/usb.agent: Setup mousedev for USB product <b>56a/44</b>/115
-</a></pre>
-<pre class="diff"><a name="testtablet">And here it is again on Redhat 7.2 (2.4.18-17.7.x):<br>
-[jej@sasami root]# tail /var/log/messages
-Apr 29 21:28:38 sasami kernel: hub.c: USB new device connect on bus1/1, assigned device number 2
-Apr 29 21:28:38 sasami kernel: <b>input0: Wacom Intuos2 12x12</b> on usb1:2.0
-Apr 29 21:28:39 sasami kernel: usb.c: registered new driver hiddev
-Apr 29 21:28:39 sasami kernel: usb.c: registered new driver hid
-Apr 29 21:28:39 sasami kernel: hid-core.c: v1.8.1 Andreas Gal, Vojtech Pavlik &lt;vojtech@suse.cz&gt;
-Apr 29 21:28:39 sasami kernel: hid-core.c: USB HID support drivers
-Apr 29 21:28:39 sasami kernel: mice: <b>PS/2 mouse</b> device common for all mice
-</a></pre>
-</blockquote>
-
-<p><a name="testtablet">If all went well like above, the USB device was successfully detected and
-handled by the wacom driver. This presumably means that information like
-pressure and tilt will be received on /dev/input/event0. You are ready to
-configure the X driver </a><a href="#download">Downloading the Code</a>.
-
-</p><p>If instead you got any of the following lines in your log, the wacom
-driver <i>did not get control</i>. Either hid or usbmouse did.
-
-</p><blockquote><pre> <b>input0,hiddev0: USB HID v1.00 Mouse [Tablet XD-1212-U]</b> on usb1:5.0
- <b>input0: Tablet XD-1212-U</b> on usb1:5.0
-<pre></pre></pre></blockquote>
-<a name="newwacom">
-</a><h2><a name="newwacom">3.2 - Updated wacom.c</a></h2>
-<p><a name="newwacom">The wacom kernel driver (wacom_wac.c and wacom_sys.c) that is available
-in </a><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.2-2.tar.bz2">linuxwacom-0.8.2-2.tar.bz2</a> supports USB Tablet PC, Bamboo1 Medium, and
-Monarch, which will be available in kernel version 2.6.28.
-
-</p><p>You can link Wacom USB tablet to "/dev/input/wacom". It can be done
-by adding the following rules in /etc/udev/rules.d/60-wacom.rules. Some
-distributions use a different number for the file name. Please look for
-proper one with wacom under /etc/udev/rules.d.
-
-</p><p>Below are examples from Debian GNU/Linux distribution:
-
-</p><p><b>60-wacom.rules on systems using ATTRS</b>
-
-</p><p><b>1. </b>Systems with only one Wacom device
-
-</p><div class="diff">
-<blockquote><pre># udev rules for wacom tablets.
-
-KERNEL!="event[0-9]*", GOTO="wacom_end"
-
-# Multiple interface support for stylus and touch devices.
-DRIVERS=="wacom", ATTRS{bInterfaceNumber}=="00", ENV{WACOM_TYPE}="stylus"
-DRIVERS=="wacom", ATTRS{bInterfaceNumber}=="01", ENV{WACOM_TYPE}="touch"
-
-# Convenience links for the common case of a single tablet. We could do just this:
-#ATTRS{idVendor}=="056a", SYMLINK+="input/wacom-$env{WACOM_TYPE}"
-# but for legacy reasons, we keep the input/wacom link as the generic stylus device.
-ATTRS{idVendor}=="056a", ENV{WACOM_TYPE}!="touch", SYMLINK+="input/wacom"
-ATTRS{idVendor}=="056a", ENV{WACOM_TYPE}=="touch", SYMLINK+="input/wacom-touch"
-
-# Check and repossess the device if a module other than the wacom one
-# is already bound to it.
-ATTRS{idVendor}=="056a", ACTION=="add", RUN+="check_driver wacom $devpath $env{ID_BUS}"
-
-LABEL="wacom_end"
-
-</pre></blockquote>
-</div>
-
-<p><b>2. </b>Systems with more than one Wacom devices
-
-</p><div class="diff">
-<blockquote><pre># udev rules for wacom tablets.
-# These rules were compiled for the Debian GNU/Linux distribution,
-# but others may, and indeed are encouraged to, use them also.
-#
-# Should you do so, PLEASE CO-ORDINATE ANY CHANGES OR ADDITIONS
-# of new devices with Ron <ron@debian.org> so that we can try
-# to present users with a standard set of device nodes
-# which they can rely on across the board.
-
-KERNEL!="event[0-9]*", GOTO="wacom_end"
-
-# Port specific link for users of multiple tablets of the same type.
-# The ID_PATH variable is set by the "path_id" script in an earlier rule file.
-ATTRS{idVendor}=="056a", ENV{ID_PATH}=="?*", SYMLINK="input/by-path/$env{ID_PATH}-wacom"
-
-# Multiple interface support for stylus and touch devices.
-DRIVERS=="wacom", ATTRS{bInterfaceNumber}=="00", ENV{WACOM_TYPE}="stylus"
-DRIVERS=="wacom", ATTRS{bInterfaceNumber}=="01", ENV{WACOM_TYPE}="touch"
-
-# Type-named links for multiple tablets. If you want to use multiple
-# tablets of the _same_ type, you will probably need to use the links
-# from /dev/input/by-path to identify which is plugged into what usb
-# port. For different tablet types though, just pick your links from
-# the list below.
-#
-# We override SYMLINK for tabletpc devices because the by-path link
-# is not required with such devices, there will only ever be one.
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0000", SYMLINK+="input/tablet-penpartner"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0003", SYMLINK+="input/tablet-cintiq_partner"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0010", SYMLINK+="input/tablet-graphire"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0011", SYMLINK+="input/tablet-graphire2-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0012", SYMLINK+="input/tablet-graphire2-5x7"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0013", SYMLINK+="input/tablet-graphire3"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0014", SYMLINK+="input/tablet-graphire3-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0015", SYMLINK+="input/tablet-graphire4-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0016", SYMLINK+="input/tablet-graphire4-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0017", SYMLINK+="input/tablet-bamboofun-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0018", SYMLINK+="input/tablet-bamboofun-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0019", SYMLINK+="input/tablet-bamboo1-medium"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0020", SYMLINK+="input/tablet-intuos-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0021", SYMLINK+="input/tablet-intuos-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0022", SYMLINK+="input/tablet-intuos-9x12"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0023", SYMLINK+="input/tablet-intuos-12x12"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0024", SYMLINK+="input/tablet-intuos-12x18"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0030", SYMLINK+="input/tablet-pl400"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0031", SYMLINK+="input/tablet-pl500"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0032", SYMLINK+="input/tablet-pl600"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0033", SYMLINK+="input/tablet-pl600sx"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0034", SYMLINK+="input/tablet-pl550"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0035", SYMLINK+="input/tablet-pl800"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0037", SYMLINK+="input/tablet-pl700"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0038", SYMLINK+="input/tablet-pl510"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0039", SYMLINK+="input/tablet-dtu710"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="003f", SYMLINK+="input/tablet-cintiq21ux"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0041", SYMLINK+="input/tablet-intuos2-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0042", SYMLINK+="input/tablet-intuos2-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0043", SYMLINK+="input/tablet-intuos2-9x12"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0044", SYMLINK+="input/tablet-intuos2-12x12"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0045", SYMLINK+="input/tablet-intuos2-12x18"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0047", SYMLINK+="input/tablet-intuos2-6x8a"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0060", SYMLINK+="input/tablet-volito"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0061", SYMLINK+="input/tablet-penstation2"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0062", SYMLINK+="input/tablet-volito2-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0063", SYMLINK+="input/tablet-volito2-2x3"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0064", SYMLINK+="input/tablet-penpartner2"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0065", SYMLINK+="input/tablet-bamboo"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0069", SYMLINK+="input/tablet-bamboo1"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0081", SYMLINK+="input/tablet-graphire_bt-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0090", SYMLINK="input/tablet-tpc90"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="0093", SYMLINK="input/tablet-tpc93-$env{WACOM_TYPE}"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="009a", SYMLINK="input/tablet-tpc9a-$env{WACOM_TYPE}"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b0", SYMLINK+="input/tablet-intuos3-4x5"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b1", SYMLINK+="input/tablet-intuos3-6x8"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b2", SYMLINK+="input/tablet-intuos3-9x12"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b3", SYMLINK+="input/tablet-intuos3-12x12"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b4", SYMLINK+="input/tablet-intuos3-12x19"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b5", SYMLINK+="input/tablet-intuos3-6x11"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b7", SYMLINK+="input/tablet-intuos3-4x6"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b8", SYMLINK+="input/tablet-intuos4-4x6"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00b9", SYMLINK+="input/tablet-intuos4-6x9"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00ba", SYMLINK+="input/tablet-intuos4-8x13"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00bb", SYMLINK+="input/tablet-intuos4-12x19"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00c0", SYMLINK+="input/tablet-dtf521"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00c4", SYMLINK+="input/tablet-dtf720"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00c5", SYMLINK+="input/tablet-cintiq20wsx"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00c6", SYMLINK+="input/tablet-cintiq12wx"
-ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00c7", ENV{WACOM_TYPE}!="touch", SYMLINK+="input/tablet-dtu1931"
-
-# Convenience links for the common case of a single tablet. We could do just this:
-#ATTRS{idVendor}=="056a", SYMLINK+="input/wacom-$env{WACOM_TYPE}"
-# but for legacy reasons, we keep the input/wacom link as the generic stylus device.
-ATTRS{idVendor}=="056a", ENV{WACOM_TYPE}!="touch", SYMLINK+="input/wacom"
-ATTRS{idVendor}=="056a", ENV{WACOM_TYPE}=="touch", SYMLINK+="input/wacom-touch"
-
-# Check and repossess the device if a module other than the wacom one
-# is already bound to it.
-ATTRS{idVendor}=="056a", ACTION=="add", RUN+="check_driver wacom $devpath $env{ID_BUS}"
-
-LABEL="wacom_end"
-
-
-</ron@debian.org></pre></blockquote>
-</div>
-
-<p><b>60-wacom.rules on systems using SYSFS</b>
-
-</p><p><b>1. </b>Systems with only one Wacom device
-
-</p><div class="diff">
-<blockquote><pre># udev rules for wacom devices
-# will create:
-# /dev/input/wacom
-# /dev/input/wacom-touch
-BUS=="usb", KERNEL=="event*", SYSFS{bInterfaceNumber}=="00", ENV{WACOM_TYPE}="stylus"
-BUS=="usb", KERNEL=="event*", SYSFS{bInterfaceNumber}=="01", ENV{WACOM_TYPE}="touch"
-
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", ENV{WACOM_TYPE}!="touch", SYMLINK+="input/wacom"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", ENV{WACOM_TYPE}=="touch", SYMLINK+="input/wacom-touch"
-</pre></blockquote>
-</div>
-
-<p><b>2. </b>Systems with more than one Wacom devices
-
-</p><div class="diff">
-<blockquote><pre># udev rules for wacom devices
-# will create:
-# /dev/input/wacom
-# /dev/input/wacom-tablets/<model>
-# /dev/input/wacom-tablets/<model>-<device id="">
-#
-# The last rule is intended for cases when you have more than one tablet
-# of the same model. The id is usb port dependent.
-#
-BUS=="usb", KERNEL=="event*", SYSFS{bInterfaceNumber}=="00", ENV{WACOM_TYPE}="stylus"
-BUS=="usb", KERNEL=="event*", SYSFS{bInterfaceNumber}=="01", ENV{WACOM_TYPE}="touch"
-
-# Type-named links for multiple tablets. If you want to use multiple
-# tablets of the _same_ type, you will probably need to use the links
-# from /dev/input/wacom-tablets to identify which is plugged into what usb
-# port. For different tablet types though, just pick your links from
-# the list below.
-#
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0000", SYMLINK+="input/wacom-tablets/penpartner input/wacom-tablets/penpartner-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0010", SYMLINK+="input/wacom-tablets/graphire input/wacom-tablets/graphire-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0011", SYMLINK+="input/wacom-tablets/graphire2-4x5 input/wacom-tablets/graphire2-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0012", SYMLINK+="input/wacom-tablets/graphire2-5x7 input/wacom-tablets/graphire2-5x7-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0013", SYMLINK+="input/wacom-tablets/graphire3 input/wacom-tablets/graphire3-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0014", SYMLINK+="input/wacom-tablets/graphire3-6x8 input/wacom-tablets/graphire3-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0015", SYMLINK+="input/wacom-tablets/graphire4-4x5 input/wacom-tablets/graphire4-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0016", SYMLINK+="input/wacom-tablets/graphire4-6x8 input/wacom-tablets/graphire4-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0017", SYMLINK+="input/wacom-tablets/bamboofun-4x5 input/wacom-tablets/bamboofun-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0018", SYMLINK+="input/wacom-tablet/bamboofun-6x8 input/wacom-tablets/bamboofun-6x8"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0019", SYMLINK+="input/wacom-tablet/bamboo1-medium input/wacom-tablets/bamboo1-medium"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0060", SYMLINK+="input/wacom-tablets/volito input/wacom-tablets/volito-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0061", SYMLINK+="input/wacom-tablets/penstation2 input/wacom-tablets/penstation2-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0062", SYMLINK+="input/wacom-tablets/volito2-4x5 input/wacom-tablets/volito2-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0063", SYMLINK+="input/wacom-tablets/volito2-2x3 input/wacom-tablets/volito2-2x3-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0064", SYMLINK+="input/wacom-tablets/penpartner2 input/wacom-tablets/penpartner2-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0020", SYMLINK+="input/wacom-tablets/intuos-4x5 input/wacom-tablets/intuos-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0021", SYMLINK+="input/wacom-tablets/intuos-6x8 input/wacom-tablets/intuos-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0022", SYMLINK+="input/wacom-tablets/intuos-9x12 input/wacom-tablets/intuos-9x12-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0023", SYMLINK+="input/wacom-tablets/intuos-12x12 input/wacom-tablets/intuos-12x12-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0024", SYMLINK+="input/wacom-tablets/intuos-12x18 input/wacom-tablets/intuos-12x18-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0030", SYMLINK+="input/wacom-tablets/pl400 input/wacom-tablets/pl400-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0031", SYMLINK+="input/wacom-tablets/pl500 input/wacom-tablets/pl500-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0032", SYMLINK+="input/wacom-tablets/pl600 input/wacom-tablets/pl600-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0033", SYMLINK+="input/wacom-tablets/pl600sx input/wacom-tablets/pl600sx-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0034", SYMLINK+="input/wacom-tablets/pl550 input/wacom-tablets/pl550-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0035", SYMLINK+="input/wacom-tablets/pl800 input/wacom-tablets/pl800-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0037", SYMLINK+="input/wacom-tablets/pl700 input/wacom-tablets/pl700-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0038", SYMLINK+="input/wacom-tablets/pl510 input/wacom-tablets/pl510-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0039", SYMLINK+="input/wacom-tablets/dtu710 input/wacom-tablets/dtu710-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00c0", SYMLINK+="input/wacom-tablets/dtf521 input/wacom-tablets/dtf521-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00c4", SYMLINK+="input/wacom-tablets/dtf720 input/wacom-tablets/dtf720-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0003", SYMLINK+="input/wacom-tablets/cintiq_partner input/wacom-tablets/cintiq_partner-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0041", SYMLINK+="input/wacom-tablets/intuos2-4x5 input/wacom-tablets/intuos2-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0042", SYMLINK+="input/wacom-tablets/intuos2-6x8 input/wacom-tablets/intuos2-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0043", SYMLINK+="input/wacom-tablets/intuos2-9x12 input/wacom-tablets/intuos2-9x12-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0044", SYMLINK+="input/wacom-tablets/intuos2-12x12 input/wacom-tablets/intuos2-12x12-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0045", SYMLINK+="input/wacom-tablets/intuos2-12x18 input/wacom-tablets/intuos2-12x18-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b0", SYMLINK+="input/wacom-tablets/intuos3-4x5 input/wacom-tablets/intuos3-4x5-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b1", SYMLINK+="input/wacom-tablets/intuos3-6x8 input/wacom-tablets/intuos3-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b2", SYMLINK+="input/wacom-tablets/intuos3-9x12 input/wacom-tablets/intuos3-9x12-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b3", SYMLINK+="input/wacom-tablets/intuos3-12x12 input/wacom-tablets/intuos3-12x12-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b4", SYMLINK+="input/wacom-tablets/intuos3-12x19 input/wacom-tablets/intuos3-12x19-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b5", SYMLINK+="input/wacom-tablets/intuos3-6x11 input/wacom-tablets/intuos3-6x11-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="003f", SYMLINK+="input/wacom-tablets/cintiq21ux input/wacom-tablets/cintiq21ux-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0047", SYMLINK+="input/wacom-tablets/intuos2-6x8a input/wacom-tablets/intuos2-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b7", SYMLINK+="input/wacom-tablets/intuos3-4x6 input/wacom-tablets/intuos3-4x6-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b8", SYMLINK+="input/wacom-tablets/intuos4-4x6 input/wacom-tablets/intuos4-4x6-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00b9", SYMLINK+="input/wacom-tablets/intuos4-6x9 input/wacom-tablets/intuos4-6x9-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00ba", SYMLINK+="input/wacom-tablets/intuos4-8x13 input/wacom-tablets/intuos4-8x13-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00bb", SYMLINK+="input/wacom-tablets/intuos4-12x19 input/wacom-tablets/intuos4-12x19-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0065", SYMLINK+="input/wacom-tablets/bamboo input/wacom-tablets/bamboo-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00c6", SYMLINK+="input/wacom-tablets/cintiq12wx input/wacom-tablets/cintiq12wx-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00c5", SYMLINK+="input/wacom-tablets/cintiq20wsx input/wacom-tablets/cintiq20wsx-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="00c7", ENV{WACOM_TYPE}!="touch", SYMLINK+="input/wacom-tablets/dtu1931 input/wacom-tablets/dtu1931-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0069", SYMLINK+="input/wacom-tablets/bamboo1 input/wacom-tablets/bamboo1-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0081", SYMLINK+="input/wacom-tablets/graphire_bt-6x8 input/wacom-tablets/graphire_bt-6x8-%b"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0090", SYMLINK="input/wacom-tablets/tpc90"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="0093", SYMLINK="input/wacom-tablets/tpc93-$env{WACOM_TYPE}"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", SYSFS{idProduct}=="009a", SYMLINK="input/wacom-tablets/tpc9a-$env{WACOM_TYPE}"
-
-# Convenience links for the common case of a single tablet. We could do just this:
-#SYSFS{idVendor}=="056a", SYMLINK+="input/wacom-$env{WACOM_TYPE}"
-# but for legacy reasons, we keep the input/wacom link as the generic stylus device.
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", ENV{WACOM_TYPE}!="touch", SYMLINK+="input/wacom"
-BUS=="usb", KERNEL=="event*", SYSFS{idVendor}=="056a", ENV{WACOM_TYPE}=="touch", SYMLINK+="input/wacom-touch"
-
-</device></model></model></pre></blockquote>
-</div>
-
-
-<div class="diff">
-Newer Mandriva Linux (Mandriva 2007 Spring and later) has an application called
-mousedrake which takes care of the setup and configuration of linuxwacom driver.
-If you use Mandriva Linux and you see InputDevice sections for Wacom device in
-your Xorg.conf, chances are your Wacom tablet is ready for you to draw.
-</div>
-
-<a name="buildwacom6">
-</a><h2><a name="buildwacom6">3.3 - Building wacom.c</a></h2>
-
-<a name="buildwacom6">To build the wacom.ko kernel module, you need to configure wacom as a kernel
-module under your kernel source tree first. The kernel sources are required
-as described on the </a><a href="#config">configuration</a> page.
-
-<p>Then, you need to configure the package with --enable-wacom option.
-Here's how the configuration should generally look:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$ ./configure --enable-wacom
+will be entirely out of date with yours. Additionally, this fix will
+appear in 2.4.20, so until you upgrade your kernel to that point, each
+time you upgrade to a version less than that, you will need to recompile this
+driver and swap it for the old one. In many cases, distributions like
+Redhat will "back-port" the fixes to older kernels, so keep an eye out
+for the change. Your driver may already be fixed.</P>
+<A NAME="newwacom">
+<H2>3.1 - Updated wacom.c</H2>
+The wacom.c driver that is available in <A HREF="/wacom/wacpack-0.2.0.tar.gz">wacpack-0.2.0.tar.gz</A> has a
+number of updates which cannot be found in many distributions yet.
+
+<P>First and foremost, it fixes an error that shipped with
+the 2.4.19 kernel and was subsequently fixed in 2.4.20. This bug fix was
+made available in the Redhat 8.0 back-ported kernel version 2.4.18-18.x.y.
+Other distributions may not yet be updated.
+
+<P>This driver contains several changes provided by Wacom UNIX developer
+Ping Cheng. Items include revised pressure code, better handling of 2D
+mice and lens cursors.
+
+<P>The driver also contains additional debugging code which may be useful in
+diagnosing data flow problems of which there are many, unfortunately.
+<A NAME="buildwacom">
+<H2>3.2 - Building wacom.c</H2>
+<P>Building the kernel driver requires having the kernel source. If you
+are running on Redhat, you can get it by installing the kernel-source RPM.
+At the time of this writing, I have the following RPMs installed:
+
+<BLOCKQUOTE>
+kernel-2.4.18-18.8.0<BR>
+kernel-2.4.18-14<BR>
+kernel-source-2.4.18-18.8.0<BR>
+</BLOCKQUOTE>
+
+On a Redhat 8.0 machine, the kernel source is installed to /usr/src/linux-2.4. You
+will need to know where your source is installed to continue with the next
+step. After unpacking the <A HREF="/wacom/wacpack-0.2.0.tar.gz">wacpack-0.2.0.tar.gz</A> file, configure the
+package. If your kernel is not located at either /usr/src/linux-2.4 or
+/usr/src/linux, use the --with-kernel option as shown below. Otherwise,
+just run <I>configure</I> without any options.
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacpack]$ ./configure --with-kernel=/home/jej/src/linux
...
-checking for valid kernel source tree... <b>ok</b>
+checking for valid kernel source tree... <B>ok</B>
...
----------------------------------------
BUILD ENVIRONMENT:
architecture - i686
- linux kernel - <b>yes 2.6.9</b>
module versioning - yes
- kernel - <b>yes /usr/src/linux</b>
+ kernel - <B>yes</B>
XFree86 - no
- XLib - yes /usr/X11R6
- TCL - yes /usr
- TK - yes /usr
- ncurses - yes
- GTK - 2.0.6
BUILD OPTIONS:
- wacom.o - <b>yes</b>
+ wacom.o - yes
wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
hid.o - no
usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
wacom_drv.o - no
----------------------------------------
-</pre></blockquote>
-
-<p>As shown above, the kernel directory was detected and the wacom.o
-module will be built. If the kernel option shows "no", you will need
-to specify the --with-kernel option and the correct directory.
-
-</p><blockquote><div class="diff">For those who feel comfortable to
-build everything from the source tree, please skip the make and install
-steps below. Scroll down to the end of this page to see the steps with
-light blue background.
-</div></blockquote>
-
-<p>To build the driver, just run <i>make</i>.
-
-</p><p>If everything works properly, you'll see the following from the make:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$ make
-...
-Making all in 2.6.9
-make[3]: Entering directory `/home/jej/linuxwacom/src/2.6.9'
- Building linuxwacom drivers for 2.6 kernel.
-make -C /usr/src/linux M=/home/jej/linuxwacom/src/2.6.9
-make[4]: Entering directory `/home/jej/linux-2.6.9'
- LD /home/jej/linuxwacom/src/2.6.9/built-in.o
- CC [M] /home/jej/linuxwacom/src/2.6.9/wacom.o
- Building modules, stage 2.
- MODPOST
- CC /home/jej/linuxwacom/src/2.6.9/wacom.mod.o
- LD [M] /home/jej/linuxwacom/src/2.6.9/wacom.ko
-make[4]: Leaving directory `/usr/src/linux'
-make[3]: Leaving directory `/home/jej/linuxwacom/src/2.6.9'
-...
-</pre></blockquote>
-
-<p></p><div class="diff">This part is for those who want to manually
-build the wacom kernel driver in source tree. If you already followed
-the steps above, you can move on to next page. <p>Please backup wacom.c in your kernel tree first. Then copy wacom.c
-(or wacom_wac.c, wacom_wac.h, wacom_sys.c, and wacom.h if defined) from
-the related linuxwacom directory to the source tree (if 4 files were
-copies, you need to add <b>wacom-objs := wacom_sys.o wacom_wac.o </b>
-to the Makefile under your kernel source input directory) and rebuild
-the kernel. An example for kernel 2.6.9 is as following: </p><blockquote><pre>
- [jej@ayukawa linuxwacom]$ cp /usr/src/linux/drivers/usb/input/wacom.c /usr/src/linux/drivers/usb/input/wacom.c.2.6.9
- [jej@ayukawa linuxwacom]$ cp src/2.6.9/wacom.c /usr/src/linux/drivers/usb/input/
- [jej@ayukawa linuxwacom]$ cd /usr/src/linux
- [jej@ayukawa linux]$ make
- [jej@ayukawa linux]$ su
- [jej@ayukawa linux]#make install
- [jej@ayukawa linux]#make modules_install
- [jej@ayukawa linux]#reboot
- </pre></blockquote>
- </div>
-<a name="testwacom">
-</a><h2><a name="testwacom">3.4 - Testing If wacom.(k)o Will Load</a></h2>
-<p><a name="testwacom">Before we install the wacom driver, we need to test that it will load
-properly. We do this by loading the driver manually. We will also
-</a><a href="#root">need to be root</a> to do this.
-
-</p><p>WARNING: there is a small chance that this will bomb your kernel,
-so we run <i>sync</i> to write all the stale buffers to the disk. People
-using ext3 have little to worry about, but it's always good to be prepared
-for the worst. At the very least, save your work.
-
-</p><blockquote><pre>[root@ayukawa linuxwacom]# sync
-</pre></blockquote>
-
-<p>From the package's associated kernel directory, we unload any previous modules and
-load the new one. The following example is from a kernel 2.4.22 system.
-
-</p><pre class="diff">
-<p>For Kernel 2.6.x, replace wacom.o with wacom.ko where it is used.
-
-</p><p>Kernel 2.6.11 and 2.6.12 are in src/2.6.11. Kernels 2.6.15 and 2.6.17 are handled in src/2.6.16.
-</p></pre>
-
-<blockquote><pre>[root@ayukawa linuxwacom]# cd src/2.4.22
-[root@ayukawa 2.4.22]# /sbin/rmmod wacom
-[root@ayukawa 2.4.22]# /sbin/insmod ./wacom.o # for those about to rock, we salute you.
-</pre></blockquote>
-
-<p>Well, if you did not bomb, then good. And if you did, well, sorry. So
+</PRE></BLOCKQUOTE>
+
+<P>If you did not receive an error or warning and the BUILD ENVIRONMENT
+summary shows "kernel - yes" then your kernel source tree was detected.
+If not, then you will need to look at the error or warning and determine
+the correct source directory. Now is also a good time to verify that the
+architecture was correctly detected. The --with-arch option allows you
+to change the value.
+
+<P>Another detail that you need to be concerned about is module
+versioning. If it reads "yes" or "no" then the configure script
+has determined the correct setting. If it says "unknown," then it will
+default disabled, and you may have to enable it manually with --enable-modver.
+If module versioning is disable when it should be enabled, depmod will
+complain about missing symbols. If it is enabled when it should be disabled,
+the code may not compile, and it almost certainly will not load properly.
+If in doubt, leave it disabled for now and enable it later if depmod complains.
+
+<P>To build the driver, just run <i>make</i>. The
+output will be a file called wacom.o in the src directory.
+This is your replacement driver.
+<A NAME="testwacom">
+<H2>3.3 - Testing If wacom.o Will Load</H2>
+<P>Before we install the wacom driver, we need to test that it will load
+properly. We do this by loading the driver manually. WARNING: there is a
+small chance that this will bomb your kernel, so we run <i>sync</i> to write
+all the stale buffers to the disk. People using ext3 have little to worry
+about, but it's always good to be prepared for the worst. At the very least,
+save your work.
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacom]# su -
+[root@ayukawa root]# cd /home/jej/src/wacom/src
+[root@ayukawa src]# sync
+[root@ayukawa src]# rmmod wacom
+[root@ayukawa src]# insmod wacom.o # for those about to rock, we salute you.
+</PRE></BLOCKQUOTE>
+
+<P>Well, if you did not bomb, then good. And if you did, well, sorry. So
far, we have not had any reports of this happening, so please send in yours.
-</p><p>Incidentally, if you run "/sbin/insmod wacom.o" and happen to be in the
-wrong directory, the old driver reloads, sometimes without warning. I
-therefore changed this to read "/sbin/insmod ./wacom.o" which seems to prevent
-this from happening. To be certain, you can check the log file for the
-correct version number.
-
-</p><blockquote><pre>[root@ayukawa src]# tail /var/log/messages
-Apr 29 20:34:41 ayukawa kernel: usb.c: registered new driver wacom
-Apr 29 20:34:41 ayukawa kernel: Reporting max 30480, 31680
-Apr 29 20:34:41 ayukawa kernel: wacom.c: Setting tablet report for tablet data
-Apr 29 20:34:41 ayukawa kernel: input0: Wacom Intuos2 12x12 on usb2:3.0
-Apr 29 20:34:41 ayukawa kernel: wacom.c: <b>$1.43-0.8.2-2</b> Vojtech Pavlik &lt;vojtech@suse.cz&gt;
-Apr 29 20:34:41 ayukawa kernel: wacom.c: USB Wacom Graphire and Wacom Intuos tablet driver
-
-</pre></blockquote>
-
-<p>The important detail is the version number. A version number like
-"1.46"
-is an original kernel version and not from the linuxwacom package. The
-correct version should also have the -j#.# or -pc#.# portion as well.
-This is to help differentiate between the stock kernel driver and those
-available from the Linux Wacom Project.
-</p><p>If you get errors inserting the module, then you may need to reconfigure
+<P>If you get errors inserting the module, then you may need to reconfigure
and build with module versioning disabled. If it loads without a hitch,
move on to the next part.
-<a name="installwacom">
-</a></p><h2><a name="installwacom">3.5 - Installing wacom.(k)o</a></h2>
-
-<pre class="diff"><p><a name="installwacom">For Kernel 2.4.x, replace wacom.ko with wacom.o where it is used.
-</a></p></pre>
-
-<p><a name="installwacom">To install or not to install, that is the question.
+<A NAME="installwacom">
+<H2>3.4 - Installing wacom.o</H2>
+<P>To install or not to install, that is the question.
Since the driver is in memory, you can pretty much use it this way
throughout the rest of this document. Anywhere you see
-"modprobe wacom", you'll instead need to "insmod ./wacom.ko".
-You'll also need to be careful that you are in the package's src directory.
-If you instead use the less-specific command "insmod wacom.ko" from a
-directory other than the package's src directory, <i>insmod</i> will load
-the driver from the kernel modules directory instead. The result is that
-you'll be using the wrong driver.
-
-</a></p><p><a name="installwacom">Why would you not install the driver? Well, for one, you may be building
-a driver against a wrong kernel source, and if the system crashes (you get
-an Oops or things come unglued in other ways), it would be nice to reboot
-and have the original drivers load instead.
-
-</a></p><p><a name="installwacom">When should I install the driver? When you're comfortable that the
-driver will not crash your system. If you really know what you're doing,
-just load the drivers manually like in the previous section </a><a href="#testwacom">Testing If wacom.(k)o Will Load</a>.
-
-</p><p class="diff">On some distributions, Mandriva (a.k.a Mandrake) included, the
-wacom.ko driver that appears in the kernel modules directory appears to be
-compressed. If you cannot find wacom.ko using the method below, try locating
-wacom.ko.gz instead. People who encountered this problem were able to run
-gzip on the module and copy that instead.</p>
-
-<p>Installing the driver requires knowing where it belongs. A little research
-will help here. By using the <i>locate</i> command, you can find all copies
-of the original driver on the computer.</p>
-
-<blockquote><pre>jej@ayukawa wacom]$ locate wacom.ko
-/lib/modules/2.6.17-1.2157_FC5/kernel/drivers/usb/input/<b>wacom.ko</b>
-/lib/modules/2.6.17-1.2174_FC5/kernel/drivers/usb/input/<b>wacom.ko</b>
+<i>modprobe wacom</i>, you'll instead need to <i>insmod wacom.o</i>.
+You'll also need to be careful that you use the correct path to wacom.o
+since insmod will load the driver from the kernel modules directory if it
+fails to find the module you specified. The result is that you'll
+be using the wrong driver.
+
+<P>Why would you not install the driver? Well, for one, you may be using
+a beta driver, and if the system crashes (you get an Oops or things come
+unglued in other ways), it would be nice to reboot and have the original
+drivers load instead.
+
+<P>When should I install the driver? When you're comfortable that the
+driver will not crash your system. The wacpack tarballs will be marked
+as beta if I am not absolutely convinced that they are stable. On the
+other hand, the new features will be in beta tarballs before they are
+marked stable, so there you have it. For the first time through this document,
+I would recommend installing the files found in the stable tarball. If you
+really know what you're doing, just load the drivers manually like in the
+previous section <A HREF="#testwacom">Testing If wacom.o Will Load</A>.
+
+<P CLASS=diff>On some distributions, Mandrake included, the wacom.o driver
+that appears in the kernel modules directory appears to be compressed. If
+you cannot find wacom.o using the method below, try locating wacom.o.gz
+instead. People who encountered this problem were able to run gzip on the
+module and copy that instead.</P>
+
+<P>Installing the driver requires knowing where it belongs. A
+little research will help here. By using the <i>locate</i> command, you
+can find all copies of the original driver on the computer.</P>
+
+<BLOCKQUOTE><PRE>
+jej@ayukawa wacom]$ locate wacom.o
+/lib/modules/2.4.18-14/kernel/drivers/usb/<B>wacom.o</B>
+/lib/modules/2.4.18-18.8.0/kernel/drivers/usb/<B>wacom.o</B>
[jej@ayukawa wacom]$ uname -r
-<b>2.6.17-1.2157_FC5</b>
-</pre></blockquote>
+<B>2.4.18-18.8.0</B>
+</PRE></BLOCKQUOTE>
-On this computer, there are two kernels installed. <i>uname</i> identifies
-the currently active kernel as 2.6.17-1.2157_FC5. The correct driver to
-replace is therefore at /lib/modules/2.6.17-1.2157_FC5/kernel/drivers/usb/input/wacom.ko.
-You will need to be root to replace this file, and it is a very good idea to
+On this computer, there are two kernels installed. <I>uname</i> identifies
+the currently active kernel as 2.4.18-18.8.0. The correct driver to replace
+is therefore at /lib/modules/2.4.18-18.8.0/kernel/drivers/usb/wacom.o. You
+will need to be root to replace this file, and it is a very good idea to
make a backup copy.
-<blockquote><pre>[jej@ayukawa wacom]$ su -
-[jej@ayukawa root]# cd /lib/modules/2.6.17-1.2157_FC5/kernel/drivers/usb/input
-[jej@ayukawa usb]# cp <b>wacom.ko</b> /home/jej/linuxwacom/src/2.6.16/<b>wacom_old.ko</b>
-[jej@ayukawa usb]# cp /home/jej/linuxwacom/src/2.6.16/<b>wacom.ko</b> <b>wacom.ko</b>
-</pre></blockquote>
-
-Here, I've saved the original to wacom_old.ko and copied my new driver over it.
-You should substitute directory names as appropriate.
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacom]$ su -
+[jej@ayukawa root]# cd /lib/modules/2.4.18-18.8.0/kernel/drivers/usb
+[jej@ayukawa usb]# cp <B>wacom.o</B> /home/jej/src/wacom/<B>wacom_old.o</B>
+[jej@ayukawa usb]# cp /home/jej/src/wacom/<B>wacom.o</B> <B>wacom.o</B>
+</PRE></BLOCKQUOTE>
-<p><b>NOTE: Don't leave the backup copy in the same directory as the
-original.</b> <i>depmod</i> will treat both as valid drivers, regardless
-of their names. Copy the original somewhere outside of the kernel module
-directory to ensure that this does not happen. In at least one case,
-the backup driver was loaded instead of the new one due to a curious
-dependency issue.
+Here, I've saved the original to wacom_old.o and copied my new driver over it.
+Substitute directory names as appropriate.
-</p><p>Finally, it is always a good thing to update the module dependencies.
+<P>Finally, it is always a good thing to update the module dependencies.
This is where you find out if the module was compiled without kernel module
versioning. The following command, even if it generates errors is relatively
benign. If it fails, then there is no harm done. It just means that you will
have to load modules in the correct order since the system will not be able to
guess for you.
-</p><blockquote><pre>[jej@ayukawa usb]# depmod -e
-</pre></blockquote>
+<BLOCKQUOTE><PRE>
+[jej@ayukawa usb]# depmod -e
+</PRE></BLOCKQUOTE>
-<p>If you get no errors and no output, everything is fine, and the module was
+If you get no errors and no output, everything is fine, and the module was
compiled, linked, and installed properly. If you received unresolved symbols
like usb_set_idle or printk, then you need to reconfigure with module
-versioning enabled and recompile.
-
-
-</p><pre class="diff"><p>Here is an example from a 2.6.12 system on Mandriva.
-
-</p><blockquote><pre>jej@ayukawa wacom]$ locate wacom.ko.gz
-/lib/modules/2.6.12-12mdksmp/kernel/drivers/usb/input/<b>wacom.ko.gz</b>
-/lib/modules/2.6.12-12mdksmp/kernel/drivers/usb/input/<b>wacom.ko.gz</b>
-
-[jej@ayukawa wacom]$ uname -r
-<b>2.6.12-12mdksmp</b>
-</pre></blockquote>
-
-
-</pre>
-<a name="loadwacom">
-</a><h2><a name="loadwacom">3.6 - Loading the wacom Driver</a></h2>
+versioning enabled and recompile. Or not. As I said, it is not critical.
+<A NAME="loadwacom">
+<H2>3.5 - Loading the wacom Driver</H2>
-<pre class="diff"><p><a name="loadwacom">For Kernel 2.6.x, replace wacom.o with wacom.ko where it is used.
-</a></p></pre>
-
-<p><a name="loadwacom">If you have installed the driver, now is the time to test whether it will
+<P>If you have installed the driver, now is the time to test whether it will
load when needed. If you have not installed it, but are instead using insmod,
-substitute <i>insmod mydir/src/wacom.o</i> where you see
+substitute <i>insmod mydir/wacom/wacom.o</i> where you see
<i>modprobe wacom</i> below. It is important that you use the correct
wacom.o file, the one you just built, since insmod may load the old driver
if it cannot find the one you have specified.
-</a></p><blockquote><pre><a name="loadwacom">[jej@ayukawa usb]# rmmod wacom
-[jej@ayukawa usb]# modprobe usb-uhci (or usb-ohci)
-<span class="diff">[jej@ayukawa usb]# modprobe input</span>
-<span class="diff">[jej@ayukawa usb]# modprobe mousedev</span>
-[jej@ayukawa usb]# modprobe wacom (or insmod mydir/src/wacom.o)
+<P>I am assuming
+that you are using a USB device, so you will also need to modprobe for usb-uhci.
+The important features of the stylus are available through the Linux event
+drivers, so load those too. With some clever additions to /etc/modules.conf,
+you can probably have these automatically loading for you whenever the tablet
+is activated. So far, I haven't figured out how to make this work reliably,
+so I've added the commands to my /etc/rc.d/rc.local file.
+
+<BLOCKQUOTE><DIV CLASS=diff>
+On Redhat 7.2 and possibly on other older distributions, mousedev and input
+are not loaded by default. Without them, the wacom driver may fail to load,
+due to unresolved symbols, and the mouse driver may not receive wacom mouse
+events, even if loaded afterwards.
+</DIV></BLOCKQUOTE>
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa usb]# rmmod wacom
+[jej@ayukawa usb]# modprobe usb-uhci
+<SPAN CLASS=diff>[jej@ayukawa usb]# modprobe input</SPAN>
+<SPAN CLASS=diff>[jej@ayukawa usb]# modprobe mousedev</SPAN>
+[jej@ayukawa usb]# modprobe wacom
[jej@ayukawa usb]# modprobe evdev
-</a></pre></blockquote>
+</PRE></BLOCKQUOTE>
-<p><a name="loadwacom">Check the system log for status messages pertaining to the wacom.
+<P>Check the system log for status messages pertaining to the wacom.
Here's a copy of the messages from my version of the driver.
-</a></p><blockquote><pre><a name="loadwacom">[jej@ayukawa usb]# grep -i wacom /var/log/messages | tail
-Apr 29 21:23:35 ayukawa kernel: usb.c: registered new driver wacom
-Apr 29 21:23:35 ayukawa kernel: wacom.c: <b>v1.43-0.8.2-2</b> Vojtech Pavlik &lt;vojtech@suse.cz&gt;
-Apr 29 21:23:35 ayukawa kernel: wacom.c: USB Wacom Graphire and Wacom Intuos tablet driver (MODIFIED)
-</a></pre></blockquote>
-
-<p><a name="loadwacom">The original driver was version 1.43. This version number
-is 1.43-0.8.2-2 so the correct driver was loaded.</a></p>
-<a name="buildhid6">
-</a><h2><a name="buildhid6">3.7 - Building (usb)hid.ko</a></h2>
-
-<p><a name="buildhid6">In the </a><a href="http://prdownloads.sourceforge.net/linuxwacom/linuxwacom-0.8.2-2.tar.bz2">linuxwacom-0.8.2-2.tar.bz2</a>
-file, you will find hid-core.c, which have special exceptions for
-wacom. This file is not built by default, so you will need to
-reconfigure the package and run make again. </p><p class="diff">Note, for kernel 2.6.18 and later, no need to build hid any more. For other kernels, refer to <a href="#testtablet">Testing Tablet Detection</a> to see if you need to build hid or not.</p>
-
-<p>You need to configure usbhid as a module under your kernel source tree before configuring linuxwacom.
-
-</p><p class="diff">On some distributions, Mandrake or Mandriva
-included, the (usb)hid.ko driver that located in the kernel modules
-directory appears to be compressed. You need to run gzip on the module
-and copy (usb)hid.ko.gz instead.</p>
-
-<blockquote><pre>[jej@ayukawa wacom]$./configure --enable-hid --with-kernel=your-kernel-src-dir
+<BLOCKQUOTE><PRE>
+[jej@ayukawa usb]# grep -i wacom /var/log/messages | tail
+Dec 22 21:23:35 ayukawa kernel: usb.c: registered new driver wacom
+Dec 22 21:23:35 ayukawa kernel: wacom.c: <B>v1.30-j0.2.0</B> Vojtech Pavlik &lt;vojtech@suse.cz&gt;
+Dec 22 21:23:35 ayukawa kernel: wacom.c: USB Wacom Graphire and Wacom Intuos tablet driver (MODIFIED)
+</PRE></BLOCKQUOTE>
+
+<P>The original driver was version 1.21.3. This version number
+is 1.30-j0.2.0 so the correct driver was loaded.</P>
+<A NAME="testtablet">
+<H2>3.6 - Testing Tablet Detection</H2>
+<P>In this section we will plug the tablet into the computer and determine
+which driver, if any, claims control over the tablet. There are at least
+three drivers that are interested: 1) hid.o which may think it is an HID
+device, 2) usbmouse.o which may think it is an HID mouse, and 3) the wacom
+driver which should identify the tablet as its own. Any number of problems
+may be experienced here, so be prepared to spend some time looking at the
+logs. A good way to do this, if you are running X, is to open a separate
+xterm, su to root, and run <i>tail -f /var/log/messages</i>. The console
+window will stream anything that is appended to the log.
+<A NAME="plugin">
+<H3>3.6.1 - Plug It In</H3>
+
+<P>Test the tablet detection by plugging the wacom into the USB port and
+checking /var/log/messages again. You should see a flurry of activity. The
+exact output depends a lot on your particular kernel and distribution.
+
+<BLOCKQUOTE><PRE>
+This is Redhat 8.0 (2.4.18-17.8.0):<BR>
+[jej@ayukawa usb]# tail /var/log/messages
+Dec 22 21:26:11 ayukawa kernel: hub.c: USB new device connect on bus2/2, assigned device number 2
+Dec 22 21:26:11 ayukawa kernel: <B>input0: Wacom Intuos2 12x12</B> on usb2:2.0
+Dec 22 21:26:14 ayukawa /etc/hotplug/usb.agent: Setup wacom hid for USB product 56a/44/115
+Dec 22 21:26:14 ayukawa /etc/hotplug/usb.agent: Setup <B>mousedev</B> for USB product 56a/44/115
+</PRE>
+<PRE CLASS=diff>
+And here it is again on Redhat 7.2 (2.4.18-17.7.x):<BR>
+[jej@sasami root]# tail /var/log/messages
+Dec 22 21:28:38 sasami kernel: hub.c: USB new device connect on bus1/1, assigned device number 2
+Dec 22 21:28:38 sasami kernel: <B>input0: Wacom Intuos2 12x12</B> on usb1:2.0
+Dec 22 21:28:39 sasami kernel: usb.c: registered new driver hiddev
+Dec 22 21:28:39 sasami kernel: usb.c: registered new driver hid
+Dec 22 21:28:39 sasami kernel: hid-core.c: v1.8.1 Andreas Gal, Vojtech Pavlik &lt;vojtech@suse.cz&gt;
+Dec 22 21:28:39 sasami kernel: hid-core.c: USB HID support drivers
+Dec 22 21:28:39 sasami kernel: mice: <B>PS/2 mouse</B> device common for all mice
+</PRE>
+</BLOCKQUOTE>
+
+<P>If all went well like above, the USB device was successfully detected and
+handled by the wacom driver; secondly, it was assigned input0. This
+presumably means that information like pressure and tilt will be received on
+/dev/input/event0. Lastly, the tablet was setup with mousedev or the generic
+PS/2 USB mouse driver, so that information should appear on /dev/input/mouse0.
+
+<P>If instead you got any of the following lines in your log, the wacom
+driver <i>did not get control</i>. Either hid or usbmouse did.
+
+<BLOCKQUOTE><PRE>
+ <B>input0,hiddev0: USB HID v1.00 Mouse</B> [Tablet XD-0608-U] on usb1:5.0
+ <B>input0: Tablet XD-1212-U</B> on usb2:2.0
+<PRE></BLOCKQUOTE>
+
+<P>The next section describes what to do if the wacom driver did not get
+control. Otherwise, skip on to
+<A HREF="#viewdata">Viewing the Raw Data</A>.
+
+<A NAME="noctrl">
+<H3>3.6.2 - Wacom Driver Does Not Get Control</H3>
+
+<P>If the wacom driver did not get control, and instead you see
+"Tablet XD-1212-U" or similar in its place, then this section is for
+you. Otherwise, consider yourself lucky and skip on to the next section,
+<A HREF="#viewdata">Viewing the Raw Data</A>. For the unlucky,
+there is a good possibility that your kernel is slightly out of date and
+that your usbmouse.c and hid-core.c files need some help.
+
+<P>When the Tablet XD-1212-U driver comes up, either usbmouse.o or hid.o
+has discovered your tablet, decided it was an HID device, and grabbed it.
+This is bad news because HID tablets seem to only output relative
+coordinates and nothing about pressure. You are in good company though
+because a number of people have reported this, even on some fairly
+up-to-date distributions. Now let's fix it.
+
+
+<A NAME="buildhid">
+<H3>3.6.3 - Building usbmouse.o and hid.o</H3>
+
+<P>In the <A HREF="/wacom/wacpack-0.2.0.tar.gz">wacpack-0.2.0.tar.gz</A> file, you will find the 2.4.19 versions
+of usbmouse.c and hid-core.c files which have special exceptions for wacom.
+These files are not built by default, so you will need to reconfigure the
+package and run make again.
+
+<DIV CLASS=diff>
+At least one person has reported errors building these files on Debian Woody
+running kernel version 2.4.20. This is not surprising since the
+source code came from 2.4.19, but I will do what I can to get these drivers updated in the near future.
+</DIV>
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacom]$ ./configure --enable-hid --enable-usbmouse
...
BUILD OPTIONS:
- hid.o - <b>yes</b>
-...
-</pre></blockquote>
-
-<p>Kernel 2.6.11 and 2.6.12 are in src/2.6.11. Kernels 2.6.16 and
-2.6.17 are handled in src/2.6.16. Kernels 2.6.18/19/20/21/22 are in
-src/2.6.18. All the other kernels are processed in its own src/2.6.x.
-New 2.6 directories will be created when compatibility issue occurs.
-</p><blockquote><div class="diff">For those who like to build everything from
-the source tree, please skip the make and install steps below. Scroll down to the end of this
-page to see the steps with light blue background.
-</div></blockquote>
-
-<p>If everything works properly, you'll see the following from the make:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$ make
-...
-Making all in 2.6.9
-make[3]: Entering directory `/home/jej/linuxwacom/src/2.6.9'
- Building linuxwacom drivers for 2.6 kernel.
-make -C /usr/src/linux M=/home/jej/linuxwacom/src/2.6.9
-make[4]: Entering directory `/home/jej/linux-2.6.9'
- LD /home/jej/linuxwacom/src/2.6.9/built-in.o
- CC [M] /home/jej/linuxwacom/src/2.6.9/hid-core.o
- CC [M] /home/jej/linuxwacom/src/2.6.9/hid-input.o
- LD [M] /home/jej/linuxwacom/src/2.6.9/usbhid.o
- Building modules, stage 2.
- MODPOST
- CC /home/jej/linuxwacom/src/2.6.9/usbhid.mod.o
- LD [M] /home/jej/linuxwacom/src/2.6.9/usbhid.ko
-make[4]: Leaving directory `/usr/src/linux'
+ hid.o - <B>yes</B>
+ usbmouse.o - <B>yes</B>
...
-</pre></blockquote>
-
-<p>Then, use the following steps to install the driver:
-
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$su
-[jej@ayukawa linuxwacom]#cd src/2.6.9
-[jej@ayukawa 2.6.9]#cp usbhid.ko /lib/modules/<b>your-kernel-ver</b>/kernel/drivers/usb/input
-[jej@ayukawa 2.6.9]#reboot
-</pre></blockquote>
-
-<p></p><div class="diff">This part is for those who want to manually build the kernel drivers from source tree.
-If you already followed the steps above, you can move on to next page.
-
-<p>Please backup your related kernel files first then copy the source from the related linuxwacom
-directory to the source tree and rebuild the kernel. An example for kernel 2.6.9 is as following:
-
-</p><blockquote><pre>[jej@ayukawa linuxwacom]$ cp /usr/src/linux/drivers/usb/input/hid-core.c /usr/src/linux/drivers/usb/input/hid-core.c.2.6.9
-[jej@ayukawa linuxwacom]$ cp src/2.6.9/hid-core.c /usr/src/linux/drivers/usb/input/
-[jej@ayukawa linuxwacom]$ cd /usr/src/linux
-[jej@ayukawa linux]$ make
-[jej@ayukawa linux]$ su
-[jej@ayukawa linux]# make install
-[jej@ayukawa linux]# make modules_install
-[jej@ayukawa linux]# reboot
-</pre></blockquote>
-</div>
-
-<a name="newtablet">
-</a><h2><a name="newtablet">3.8 - Unknown Tablet?</a></h2>
-<a name="newtablet">To determine whether your device is listed in the driver, we need to determine
-the device identifier. It can be discovered by issuing <i>more /proc/bus/usb/devices</i>:
-
-</a><blockquote><pre><a name="newtablet">[jej@ayukawa linuxwacom]# more /proc/bus/usb/devices
-T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=12 MxCh= 0
-D: Ver= 1.10 Cls=00(&gt;ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
-P: <b>Vendor=056a ProdID=0044</b> Rev= 1.15
-S: Manufacturer=Tablet
-S: <b>Product=XD-1212-U</b>
-C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=140mA
-I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=wacom
-E: Ad=81(I) Atr=03(Int.) MxPS= 10 Ivl=5ms
-</a></pre></blockquote>
-
-<p><a name="newtablet">In this case, the tablet identifier is in Vendor=056a ProdID=<b>0044</b>.
-The model (<b>Product=XD-1212-U</b>) is determined by ProdID; the Intuos2 12x12 is 0x44 for instance.
-
-</a></p><p><a name="newtablet">In the wacom.c (kernel 2.6.9/10) or wacom_wac.c (kernels 2.6.11 or later) file under linuxwacom/src/2.6.x,
-you will find a table called "wacom_ids". Look for your device identifier. Only the identifiers listed are
-handled by the wacom driver, so if it is missing, it needs to be added. Also look for routine usb_hid_configure()
-in hid-core.c if you are running a kernel older than 2.6.18. At the beginning of the routine, we added the
-following lines to let HID driver ignore all Wacom devices:
-
-</a></p><blockquote><pre><a name="newtablet"> /* ignore all Wacom devices */
- if (dev-&gt;descriptor.idVendor == USB_VENDOR_ID_WACOM)
- return NULL;
-</a></pre></blockquote>
-
-<p><a name="newtablet">If you've gotten this far, and still cannot get it to work, email me
-with your device identifier and as much of an explanation of where things did and did not work as
-described. I'll see what I can do about at least finding out why it did not work. Then we can
-go on to solutions.
-
-</a></p><p><a name="newtablet">The next section assumes you have things working up to this point.
-
-</a><a name="viewdata">
-</a></p><h2><a name="viewdata">3.11 - Viewing the Raw Data (xxd)</a></h2>
-<p><a name="viewdata">View the raw data from the tablet, by returning to the /dev/input
-directory and streaming the data directly from the device. Be patient
-here because this is where a lot of people are getting stuck.
-
-</a></p><blockquote><pre><a name="viewdata">[root@ayukawa usb]# cd /dev/input
+[jej@ayukawa wacom]$ make
+[jej@ayukawa wacom]$ cd src
+[jej@ayukawa src]$ ls -la hid.o usbmouse.o
+-rw-rw-r-- 1 jej jej 26590 Dec 22 18:56 hid.o
+-rw-rw-r-- 1 jej jej 4848 Dec 22 18:56 usbmouse.o
+</PRE></BLOCKQUOTE>
+
+<P> First off, if the code does not build, and you cannot chase the problem
+down yourself, send me a line. If your kernel is much older than 2.4.18,
+then you may have to resign yourself to the fact that the 2.4.19 drivers
+are not going to work for you. I would recommend upgrading your kernel. Some
+people are already running kernel version 2.4.20 and have encountered
+problems building as well. I will update these drivers to 2.4.20 as soon as possible.
+
+<P>Rather than copy these files to the kernel modules directory right
+away, it would be wise to test whether they get the job done. We should also
+verify that they load properly.
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa src]$ su -
+[root@ayukawa root]# cd /home/jej/src/wacom/src
+[root@ayukawa src]# rmmod hid usbmouse wacom
+[root@ayukawa src]# insmod hid.o
+[root@ayukawa src]# insmod usbmouse.o
+[root@ayukawa src]# insmod wacom.o
+</PRE></BLOCKQUOTE>
+
+As for unloading the old drivers, none of them should be busy, but if you
+run into trouble, you can use <i>lsmod</i> to check the dependencies
+and try again. Now let's check how the wacom driver managed:
+
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacom]# tail -15 /var/log/messages
+Dec 22 21:07:38 ayukawa kernel: usbmouse.c: <B>mouse_init (MODIFIED DEBUG)</B>
+Dec 22 21:07:38 ayukawa kernel: usb.c: registered new driver usb_mouse
+Dec 22 21:07:39 ayukawa kernel: hid-core.c: <B>hid_init (MODIFIED DEBUG)</B>
+Dec 22 21:07:39 ayukawa kernel: usb.c: registered new driver hiddev
+Dec 22 21:07:39 ayukawa kernel: usb.c: registered new driver hid
+Dec 22 21:07:44 ayukawa kernel: usb.c: registered new driver wacom
+Dec 22 21:07:44 ayukawa kernel: usbmouse.c: <B>usb_mouse_probe: ignoring wacom</B>
+Dec 22 21:07:44 ayukawa kernel: input0: <B>Wacom Intuos2 12x12</B> on usb2:8.0
+Dec 22 21:07:44 ayukawa kernel: wacom.c: v1.30-j0.2.0 Vojtech Pavlik &lt;vojtech@suse.cz&gt;
+Dec 22 21:07:44 ayukawa kernel: wacom.c: USB Wacom Graphire and Wacom Intuos tablet driver <B>(MODIFIED-DEBUG)</B>
+</PRE></BLOCKQUOTE>
+<P>If everything is working correctly, the log should look similar to the
+lines above. I removed some of the extraneous information, so if you have
+more than this, you should be fine. The most important thing here is that
+the usb_mouse_probe detected and ignored the wacom. It actually gets
+several shots at it, but I removed the redundant lines. For the final test,
+unplug and replug the tablet. Now check the log. The wacom driver should
+be calling the shots from here on out.
+
+<P>If all is well, and you are installing modules rather than <i>insmod</i>'ing
+them as you go, then now is the time to copy the usbmouse.o and hid.o
+drivers to their proper places in the kernel modules directory.
+<SPAN CLASS=diff>As before with some other distributions, if the files in the
+kernel module directory are compressed, you'll need to run gzip on the .o
+files to get .o.gz files.</SPAN>
+Use <i>locate</i> as you did for the wacom.o file if necessary and don't
+forget to backup the originals.
+<A NAME="morehid">
+<H3>3.6.4 - More about hid.o</H3>
+
+<P>Incidentally, the hid.o file may not be necessary, but I've included the
+source to build it anyway because hid-core.c contains a lot of wacom related
+code. If the hid.o driver gets called upon to control the wacom, and it is
+compiled in debug mode, you may see a line similar to the following in the
+log:
+
+<BLOCKQUOTE><PRE>
+Dec 22 21:11:44 ayukawa kernel: usb_hid_configure: configuring device 56A.44 (WACOM), quirk is 4 (IGNORE)
+</PRE></BLOCKQUOTE>
+
+If you get this message, but with a different quirk, or if the wacom driver
+still is not getting control by this point, there is a possibility that your
+tablet is not listed in any of the driver files. If so, continue on to the
+next section. Otherwise, if you are up and running, skip to
+<A HREF="#viewdata">Viewing the Raw Data</A>.
+<A NAME="newtablet">
+<H3>3.6.5 - Unknown Tablet?</H3>
+To determine whether your device is listed in the driver, we need to determine
+the device identifier. It can be discovered by doing the following:
+
+<BLOCKQUOTE><PRE>
+[root@ayukawa root]# grep -i 56a /var/log/messages | tail -10
+Dec 22 21:03:09 ayukawa /etc/hotplug/usb.agent: Setup mousedev for USB product <B>56a/44/115</B>
+Dec 22 21:27:48 ayukawa kernel: usb.c: USB device 2 (vend/prod <B>0x56a/0x44</B>) is not claimed by any active driver.
+</PRE></BLOCKQUOTE>
+
+<P>In this case, the tablet identifier is 56a/44 (also written 0x56a/0x44).
+The model is determined by the second number; the Intuos2 12x12 is 0x44 for
+instance.
+
+<P>In the wacom.c file, you will find a table called "wacom_ids." Look for
+your device identifier. Only the identifiers listed are handled by the
+wacom driver, so if it is missing, it needs to be added. Also look in
+hid-core.c. It has a table called "hid_blacklist" which identifies devices
+to ignore. The code is a little strange, but PENPARTNER is 0x00, GRAPHIRE is
+0x10, INTUOS is 0x20, PL is 0x30, and INTUOS2 is 0x40. A table entry like
+INTUOS2 + 4 would therefore be 0x44.
+
+<P>If you've gotten this far, and still cannot get it to work, send me email
+with your device identifier and as much of an explanation of where things did
+and did not work as described. I'll see what I can do about at least finding
+out why it did not work. Then we can go on to solutions.
+
+<P>The next section assumes you have things working up to this point.
+
+<A NAME="viewdata">
+<H2>3.7 - Viewing the Raw Data</H2>
+<P>View the raw data from the tablet,
+by returning to the /dev/input directory and streaming the data directly
+from the device. Be patient here because this is where a lot of people
+are getting stuck.
+
+<BLOCKQUOTE><PRE>
+[root@ayukawa usb]# cd /dev/input
[root@ayukawa input]# xxd event0
0000000: e65d c33d 597d 0100 0100 4101 0100 0000 .].=Y}....A.....
0000010: e65d c33d 5c7d 0100 0400 0000 b701 2800 .].=\}........(.
0000020: e65d c33d d9bb 0100 0100 4101 0000 0000 .].=......A.....
0000030: e65d c33d dcbb 0100 0400 0000 b701 2800 .].=..........(.
(Ctrl-C)
-</a></pre></blockquote>
+</PRE></BLOCKQUOTE>
+
+First off, you have to move the mouse or tap the pen to get any output.
+Second, you might not get anything at all. Don't panic. This
+seems to happen occasionally. Unfortunately, the work-around is neither
+straightfoward nor foolproof. I am currently talking with Wacom developers
+about this and hopefully we'll get it solved soon.
-<p><a name="viewdata">First off, you have to move the mouse or tap the pen to get any output.
-If the tablet is mapped to event0, a continuously data stream will be
-displayed while you move the mouse or pen on the tablet. Second, you
-might not get anything at all. Don't panic. This seems to happen
-occasionally. If absolutely no output occurs, try event1 and event2.
-<span class="diff">It is reported on Fedora Core 2 the event0 used for
-kernel 2.4 is represented as event2 when switching to kernel 2.6.1-1.65.</span>
+<P>If absolutely no output occurs, you should check your messages
+file for the following line:
-If no output occurs on those ports, reload the drive:
+<BLOCKQUOTE><PRE>
+[jej@sasami root]# tail /var/log/messages
+Dec 22 17:31:06 sasami kernel: <B>wacom_intuos_irq: received unknown report #1</B>
+Dec 22 17:31:09 sasami last message repeated 195 times
+</PRE></BLOCKQUOTE>
+
+This is a common failure mode of the driver, and I am investigated the cause.
+Each time this has happened to me though, I <I>have</I> been
+able to get it to work. Simply unload and reload the driver.
-</a></p><blockquote><pre><a name="viewdata">[jej@sasami root]# /sbin/rmmod wacom
-[jej@sasami root]# /sbin/modprobe wacom (or /sbin/insmod mydir/src/wacom.o)
+<BLOCKQUOTE><PRE>
+[jej@sasami root]# rmmod wacom
+[jej@sasami root]# modprobe wacom
[jej@sasami root]# tail /var/log/messages
-Apr 29 17:31:31 sasami kernel: usb.c: deregistering driver wacom
-Apr 29 17:31:34 sasami kernel: usb.c: registered new driver wacom
-Apr 29 17:31:35 sasami kernel: input0: Wacom Intuos2 12x12 on usb1:2.0
-Apr 29 17:31:35 sasami kernel: wacom.c: v1.43-0.8.2-2 Vojtech Pavlik &lt;vojtech@suse.cz&gt;
-</a></pre></blockquote>
+Dec 22 17:31:31 sasami kernel: usb.c: deregistering driver wacom
+Dec 22 17:31:34 sasami kernel: usb.c: registered new driver wacom
+Dec 22 17:31:35 sasami kernel: input0: Wacom Intuos2 12x12 on usb1:2.0
+Dec 22 17:31:35 sasami kernel: wacom.c: v1.30-j0.2.0 Vojtech Pavlik &lt;vojtech@suse.cz&gt;
+</PRE></BLOCKQUOTE>
-<p><a name="viewdata">The device driver and the tablet occassionally get out of
+<P>Apparently, the device driver and the tablet occassionally get out of
sync with the tablet thinking it's still in HID mode when in fact it
should be in "mode 2." By unloading and reloading the driver manually,
the initialization code has another opportunity to get it right. Try the
-<i>xxd /dev/input/event0</i> again. This time, it
-<i>should</i> work. If not, send me some email.
+<I>xxd /dev/input/event0</I> again. This time, it <I>should</I> work. If
+not, send me some email. I am trying to create a repeatable test case
+for the Wacom developers, and your problem may be just what we need to
+get this bug fixed.
-</a></p><p><a name="viewdata">Incidentally, if you have a program running that is connected to
+<P>Incidentally, if you have a program running that is connected to
/dev/input/event0 (like X or wacdump for instance), it is possible that
the tablet will not reattach back to the same event. I have seen the
wacom reattach to /dev/input/event1 when unloading and reloading the
-wacom driver with wacdump running for instance. So, try xxd on event1
-or event2 if event0 fails.
+wacom driver with wacdump running for instance.
-</a></p><p><a name="viewdata">You should also try running <i>xxd</i> on /dev/input/mouse0.
+<P>You should also try running <i>xxd</i> on /dev/input/mouse0.
You should get streams of data when the mouse and pen are moved
around the surface of the tablet. It is this device that X will
look at for mouse movement. Use Ctrl-C to exit xxd.
-</a><a name="wacdump">
-</a></p><h1><a name="wacdump">4.0 - Viewing Wacom Data (wacdump)</a></h1>
-<p><a name="wacdump">The wacdump program parses and displays raw data from the Linux event
-subsystem or serial port. It is very handy for verifying that your
-tablet works without having to hassle with X server. Generally, you
-must be root to run it unless you've set the permissions on the
-appropriate device such that you can read them.
-
-</a></p><p><a name="wacdump"><b>Running wacdump</b>
-
-</a></p><p><a name="wacdump">In the case of USB tablets, this program can run simultaneously with X,
-but it's best if X has not been configured for the tablet yet. X will
-not share the serial port with wacdump, so serial users should comment out the
-wacom InputDevice sections from XF86Config (or xorg.conf) before
-using. Alternatively, you could move your serial tablet to COM2 and
-try /dev/ttyS1 instead.
-
-</a></p><p><a name="wacdump">The command line usage of wacdump is pretty simple:
-
-</a></p><blockquote><pre><a name="wacdump">Usage: wacdump [options] device
-Options:
- -h, --help - usage
- -c, --class device_cls - use specified class (see below)
- -f, --force device_name - use specified device (see below)
- -l, --list - list all supported devices
- -v, --verbose - increase log output; multiple OK
- -V, --version - display version number
- --logfile log_file - output log to file
-
-Example devices:
- /dev/input/event0 - usb tablet device
- /dev/ttyS0 - serial tablet on com1
- /dev/ttyUSB0 - serial tablet on USB adapter
-
-Supported device classes:
- serial, usb
-Supported device names:
- serial: art, art2, dig, dig2, pp, gr, pl, int, int2, c100
- usb: pp, gr, gr2, int, int2, pl, vol
-</a></pre></blockquote>
-
-<p><a name="wacdump">Older versions of wacdump assumed the device to be /dev/input/event0.
-This is now deprecated. You should instead specify which device to use
-on the command line directly. If you get an end-of-file error or the
-device does not exist, then the wacom may be attached to a different event.
-Serial users may experience a timeout error which indicates that either
-the tablet is not responding or X server has it open. Access denied errors
-probably indicate that
-</a><a href="#root">you are not root</a>.
-If you get different types of errors, let me know so we can get them
-documented.
-
-</p><p>Serial users are advised that now is a good time to plug in your tablet,
-if you haven't already.
-
-</p><p>Let's run wacdump. Here are some command line examples:
-
-</p><blockquote><pre>[jej@ayukawa src]$ ./wacdump /dev/input/event0 # typical USB tablet
-[jej@ayukawa src]$ ./wacdump /dev/input/event1 # USB tablet on event1
-</pre></blockquote>
-
-<p>When you run wacdump, it will attempt to initialize and query the tablet.
-For a number of reasons, it may not display anything immediately, but if you
-place a mouse or pen near the surface, the screen should update.
-You will then be presented with a screen similar to the following:
-
-</p><blockquote><pre>wacdump v0.4.0
-MODEL=Wacom Intuos2 12x12 ROM=1.1-5
-CLS=USB VNDR=Wacom DEV=Intuos2 SUB=XD-1212-U
-
-TOOLTYPE=NONE SERIAL=0x00000000
- IN_PROX=+00000 (+00000 .. +00000) BUTTON=+00000 (+00000 .. +00000)
- POS_X=+00000 (+00000 .. +30480) POS_Y=+00000 (+00000 .. +31680)
- ROT_Z=+00000 (-00900 .. +00899) DISTANCE=+00000 (+00000 .. +00015)
-PRESSURE=+00000 (+00000 .. +01023) TILT_X=+00000 (+00000 .. +00127)
- TILT_Y=+00000 (+00000 .. +00127) ABSWHEEL=+00000 (+00000 .. +01023)
-RELWHEEL=+00000 (-00001 .. +00001) THROTTLE=+00000 (-01023 .. +01023)
-
- LEFT= MIDDLE= RIGHT= EXTRA=
- SIDE= TOUCH= STYLUS= STYLUS2=
-</pre></blockquote>
-
-<p>The top portion identifies the tablet, and unless you specifically
-override the device type with the -f option, it should be auto-detected
-from the tablet directly. In this case, the model is XD-1212-U, a USB
-Intuos2 12x12.
-
-</p><p>The next section describes the dynamic attributes of the tablet,
-including the current position of the pointer, the type of tool in proximity
-to the surface, its pressure, and tilt. Some tablets (Protocol V tablets,
-such as Intuos 1, 2, and 3 as well as Cintiq 21UX) provide serial numbers
-for their tools. When a button is pressed, the button heading will change
-to something like "STYLUS=DOWN".
-
-</p><p> Some tablet tools report wheel movements as single increments forward
-and reverse, while others provide absolute positions. The 4D mouse has a
-throttle instead of a wheel. All three cases are reported independently.
-
-</p><p>Different tablets will have different options. Here is the lowly
-ArtPadII for comparison.
-
-</p><blockquote><pre>wacdump v0.4.0
-MODEL=Wacom ArtPadII 4x5 ROM=1.3-6
-CLS=Serial VNDR=Wacom DEV=ArtPadII SUB=KT-0405-R
-
-TOOLTYPE=NONE IN_PROX=+00000 (+00000 .. +00000)
- BUTTON=+00000 (+00000 .. +00000) POS_X=+00000 (+00000 .. +06400)
- POS_Y=+00000 (+00000 .. +04800) PRESSURE=+00000 (+00000 .. +00255)
-
- LEFT= MIDDLE= RIGHT= EXTRA=
- SIDE= TOUCH= STYLUS= STYLUS2=
-</pre></blockquote>
-
-<p>Notice that this tablet has no tilt, and the pressure range is
-considerably reduced. This version of wacdump does not distinguish
-between tablets with mice, so the left, right, and middle buttons are
-present, even though the tablet itself has no mouse.
-<a name="x11">
-</a></p><h1><a name="x11">5.0 - Configuring X11</a></h1>
-<a name="x11">Two steps must be completed to get X to recognize your tablet. First,
-you need to add some lines to XF86Config/xorg.conf to inform X of the tablet's
+<A NAME="wacdump">
+<H1>4.0 - wacdump</H1>
+<P>wacdump.c parses and displays the raw event output. You must
+be root to run it unless you've set the permissions on /dev/input/event0
+such that you can read it. This program can run simultaneously with X,
+but it's best if X has not be configured for the tablet yet.
+wacdump is enabled by default in the configure script, so it should be
+built automatically when you run <I>make</I>.
+
+<P>The command line usage of wacdump (wacpack-0.2.0) is pretty simple:
+
+<BLOCKQUOTE><PRE>
+Usage: wacdump [-d device]
+ -?, -h, --help - usage
+ -d, --device device - use specified device
+</PRE></BLOCKQUOTE>
+
+<P>If you know that the tablet is attached to a device other than
+/dev/input/event0, you can override it with the -d option, but otherwise,
+the default is correct. If you connect the /dev/input/event0 and get an
+end-of-file error, then the wacom is probably attached to a different event.
+
+<P>When you run wacdump, nothing will happen until you place a mouse or
+pen near the surface. After that, the screen will clear and you will see
+a screen similar to the following output:
+
+<BLOCKQUOTE><PRE>
+Wacom Intuos2 12x12 bus=3, vndr=56A, prd=44, ver=115
+
+ KEY=00000000.00000000 0000 0000 00000000
+ ABS=00000000.00000000 0000 0000 00000000
+ MSC=3DD488B5.0000F385 0004 0000 0028102E
+
+ X=+17623 (+00000 .. +30480) Y=+10730 (+00000 .. +31680)
+ RZ=-00058 (-00900 .. +00899) THROTTLE=+00000 (-01023 .. +01023)
+ WHEEL=+00000 (+00000 .. +01023) PRESSURE=+00005 (+00000 .. +01023)
+DISTANCE=+00007 (+00000 .. +00015) TILT_X=+00094 (+00000 .. +00127)
+ TILT_Y=+00122 (+00000 .. +00127)
+
+ WHEEL=+00000
+ SERIAL=0028102E
+
+ LEFT= RIGHT= MIDDLE= SIDE=
+ EXTRA= PEN= RUBBER= BRUSH=
+ PENCIL= AIR= MOUSE= LENS=
+ TOUCH= STYLUS= STYLUS2=
+</PRE></BLOCKQUOTE>
+
+<P>This output comes from version 0.3.2 of the wacdump program.
+
+<P>The first row displays the model number, vendor id, product id, and
+revision number.
+
+<P>The next block shows events as they arrive. Only the
+event types that the device claims to generate are displayed.
+The quickly changing numbers are timestamps.
+
+<P>The middle block shows absolute positions of various device parameters.
+It also shows the ranges that the device claims to provide. If your device
+exceeds these ranges, please let me know so I can fix the
+driver. All the available positions are displayed, even though some of
+them are not available for certain pointers. Different tablets will have
+different capabilities; these are capabilities registered specifically for
+your tablet by the wacom.o kernel driver.
+
+<P>The second WHEEL value is from the relative events channel. Presently,
+only the beta drivers report relative events.
+
+<P>The serial number of the current stylus is displayed next. When two
+pointers are present, the serial number will alternate. This is especially
+true of Intuos2 models and possibly less accurate of other models.
+
+<P>Lastly, the button positions are displayed. Some mice have more buttons
+than others; the ones displayed are the ones that the tablet offers. Buttons
+like "Pen" or "Airbrush" are displayed as "Down" when the tool is in proximity
+to the surface.
+
+<P>Whenever you are curious if the device is working properly, wacdump is
+a useful tool for determine exactly what is coming from the tablet. You can
+run it in conjunction with X or without. The display is constrained to 80x25
+so it can also be used on the main console terminal.
+<A NAME="x11">
+<H1>5.0 - Configuring X11</H1>
+Two steps must be completed to get X to recognize the Wacom. First,
+you need to add some lines to XF86Config to inform X of the tablet's
existence. Second, you need to update the XInput driver that pertains
-to the tablet since the one that ships with XFree86/Xorg is not very functional.
+to the Wacom since the one that ships with XFree86 is not very functional.
Neither driver holds a candle to the windows driver though, so you'll
-have to take what you get for the time being. Updates to the XFree86/Xorg driver
+have to take what you get for the time being. Updates to the XFree86 driver
are available in the stable and beta releases on the
-</a><a href="#download">Downloading the Code</a> page.
-<a name="inputdev">
-</a><h2><a name="inputdev">5.1 - Adding the InputDevices</a></h2>
-
-<p><a name="inputdev">The X Window system identifies the stylus (tip and side switches
-of your pen), eraser (the other end of your pen if it is clickable),
-cursor (your Wacom mouse), and pad (buttons, strips and rings on
-your tablet if your tablet has any) as XInput devices. Most settings,
-such as stylus pressure level and system cursor movement mode can be
-done in /etc/X11/XF86Config or /etc/X11/xorg.conf configuration
-file before X server starts or live through command-line
-</a><a href="#xsetwacom">xsetwacom</a>
-or the simple GUI control panel <a href="#wacomcpl">wacomcpl</a> while Wacom driver is running.
-
-</p><p>However, adding the InputDevice sections to your XF86Config/
-xorg.conf file for Wacom devices is required. You should add these
-devices to the <a href="#srvlayout">ServerLayout</a> section of your XF86Config/xorg.conf
-file too.
-
-</p><p>We assume you are running Either XFree86 4.2 or later Or Xorg.
-<span class="diff">On some distributions, this file is called XF86Config-4.
-Notice that the serial and USB configurations are different, so only
-include the appropriate lines. The default serial and USB devices are given.
-For Tablet PCs, options "Device" and "ForceDevice" should be included. You
-should also change the device (e.g. ttyS0) to the correct one for your
-tablet. Tablet PC and Cintiq/PL/DTF models don't support cursor type.
-</span> All the new driver options are listed in the manual page below.
-
-
-</p><blockquote><pre>Section "InputDevice"
- Driver "wacom"
- Identifier "stylus"
- <b>Option "Device" "/dev/ttyS0" # SERIAL ONLY</b>
- <b>Option "Device" "/dev/input/event0" # USB ONLY</b>
- Option "Type" "stylus"
- <b>Option "USB" "on" # USB ONLY</b>
- <b>Option "ForceDevice" "ISDV4" # Serial Tablet PC ONLY</b>
-EndSection
-
-Section "InputDevice"
- Driver "wacom"
- Identifier "eraser"
- <b>Option "Device" "/dev/ttyS0" # SERIAL ONLY</b>
- <b>Option "Device" "/dev/input/event0" # USB ONLY</b>
- Option "Type" "eraser"
- <b>Option "USB" "on" # USB ONLY</b>
- <b>Option "ForceDevice" "ISDV4" # Serial Tablet PC ONLY</b>
-EndSection
-
+<A HREF="#download">Downloading the Code</A> page. You may
+also check <A HREF="http://people.mandrakesoft.com/~flepied/projects/wacom/">Lepied's Wacom Site</A> which
+has source code up to version 26 as of this writing.
+<A NAME="inputdev">
+<H2>5.1 - Adding the InputDevices</H2>
+<P>The X Window system identifies the stylus and eraser on your tablet as
+XInput devices. Applications that want to know the absolute position of
+your stylus can request that information directly, and this generally
+bypasses whatever the mouse happens to be doing at the time. This design
+is not without problems though. For one, changing your setup or adding
+a new tool requires making changes to the XF86Config file and restarting
+X. This should be fixed in the future.
+
+<P>For now however, add the InputDevice sections to your XF86Config file. This
+assumes you are running XFree86 4.x. <SPAN CLASS=diff>On some distributions,
+this file is called XF86Config-4</SPAN>.
+
+<BLOCKQUOTE><PRE>
Section "InputDevice"
Driver "wacom"
Identifier "cursor"
- <b>Option "Device" "/dev/ttyS0" # SERIAL ONLY</b>
- <b>Option "Device" "/dev/input/event0" # USB ONLY</b>
+ Option "Device" "/dev/input/event0"
Option "Type" "cursor"
- <b>Option "USB" "on" # USB ONLY</b>
- <b>Option "ForceDevice" "ISDV4" # Serial Tablet PC ONLY</b>
+ Option "Mode" "relative"
+ Option "USB" "on"
+ Option "Speed" "3.0"
+ <B>Option "Threshold" "10"</B>
EndSection
-<b># This section is for Intuos3, CintiqV5, Graphire4, or Bamboo</b>
Section "InputDevice"
Driver "wacom"
- Identifier "pad"
- <b>Option "Device" "/dev/ttyS0" # SERIAL ONLY</b>
- <b>Option "Device" "/dev/input/event0" # USB ONLY</b>
- Option "Type" "pad"
- <b>Option "USB" "on" # USB ONLY</b>
+ Identifier "stylus"
+ Option "Device" "/dev/input/event0"
+ Option "Type" "stylus"
+ Option "Mode" "absolute"
+ Option "USB" "on"
+ Option "Tilt" "on"
+ #Option "TiltInvert" "on"
+ <B>Option "Threshold" "10"</B>
EndSection
-<b># This section is for the TabletPC that supports touch</b>
Section "InputDevice"
Driver "wacom"
- Identifier "touch"
- <b>Option "Device" "/dev/ttyS0" # SERIAL ONLY</b>
- <b>Option "Device" "/dev/input/event0" # USB ONLY</b>
- Option "Type" "touch"
- <b>Option "ForceDevice" "ISDV4" # Serial Tablet PC ONLY</b>
- <b>Option "USB" "on" # USB ONLY</b>
+ Identifier "eraser"
+ Option "Device" "/dev/input/event0"
+ Option "Type" "eraser"
+ Option "Mode" "absolute"
+ Option "USB" "on"
+ Option "Tilt" "on"
+ #Option "TiltInvert" "on"
+ <B>Option "Threshold" "10"</B>
EndSection
-</pre></blockquote>
-
-<p>The above four sections identify the stylus, eraser, cursor, touch, and pad devices
-to XInput. Notice that all four reference the same device /dev/ttyS0 or
-/dev/input/event0 depending on whether its a serial or USB tablet.
-
-</p><p>The configuration options listed by your system's man page may be way out of date.
-Below is an updated wacom man page which will be installed by default when you issue
-<i>make install</i>. </p>
-<blockquote><pre>WACOM(4) WACOM(4)
+#Section "InputDevice"
+# Driver "wacom"
+# Identifier "tablet"
+# Option "Device" "/dev/input/event0"
+# Option "Type" "beta"
+#EndSection
+</PRE></BLOCKQUOTE>
+
+<P>The first three sections identify the cursor, stylus, and eraser devices
+to XInput. Notice that all three reference /dev/input/event0. Additionally,
+the TiltInvert option has been commented out. You may want to experiment
+with these values.
+
+<P>The fourth InputDevice section is for the new beta driver. Unless you
+are actually testing this code, I do not recommend using this section, at
+least not at present. There is no harm in leaving it in the file, commented
+in or out, just so long as it is not used in the ServerLayout section
+described later.
+
+<P><B>The threshold value is very important.</B> Various wacom tablets behave
+differently in terms of how the "TOUCH" event is detected. On some tablets,
+the device itself makes the determination, and on others, the driver detects
+the event by examining the pressure value. To make matters more complex,
+the ranges are all different so what is good for my Intous2 may not be good
+for your Graphire. I am providing a default value of 10. If the pressure
+exceeds that value, a "TOUCH" event is sent to the XInput system. If this
+is too hard, you may want to reduce it. If the value is too low, you will
+encounter the reviled "spurious touch" problem where the stylus clicks
+randomly as you move it around the screen.
+
+<P>Also, people using serial tablets will need completely different settings.
+Please see <A HREF="http://people.mandrakesoft.com/~flepied/projects/wacom/">Lepied's Wacom Site</A> for
+more details.
+
+<P>I am including a copy of the man page for the driver. Some of the fields
+pertain only to the serial device, and some of the fields may be deprecated
+under XFree86 4.2.0. Try them out, see what happens.</P>
+
+<BLOCKQUOTE><PRE>
+WACOM(4x) XFree86 WACOM(4x)
NAME
wacom - Wacom input driver
@@ -1928,39 +1430,27 @@ SYNOPSIS
EndSection
DESCRIPTION
- wacom is an X input driver for Wacom devices.
+ wacom is an XFree86 input driver for Wacom devices.
The wacom driver functions as a pointer input device, and may be used
as the X server's core pointer.
SUPPORTED HARDWARE
- This driver supports the Wacom IV and Wacom V protocols. Serial tablets
- only need this driver. USB tablet support is available on some Linux
- platforms. USB tablets needs wacom Linux kernel driver being loaded
- before this driver starts. Please check linuxwacom.sf.net for latest
- updates of Wacom X and kernel drivers.
+ This driver supports the Wacom IV and Wacom V protocols. Preliminary
+ support is available for USB devices on some Linux platforms.
CONFIGURATION DETAILS
- Please refer to xorg.conf(5x) for general configuration details and for
- options that can be used with all input drivers. This section only
+ Please refer to XF86Config(5x) 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.
Multiple instances of the Wacom devices can cohabit. It can be useful
to define multiple devices with different active zones. Each device
supports the following entries:
- Option "Type" "stylus"|"eraser"|"cursor"|"touch"|"pad"
- sets the type of tool the device represents. This option is
- mandatory. The core options, such as "SendCoreEvents" or
- "AlwaysCore", are unnecessary in Gimp if you don't need to
- move system cursor outside of Gimp drawing area. "pad" is
- for Intuos 3 and CintiqV5 ExpressKeys and menu strips, or
- Graphire 4 and Bamboo tablet buttons and wheel/ring. It is
- required for Intuos3, CintiqV5, Graphire 4, or Bamboo if
- you want to use keystroke features. "pad" is reported as a
- second tool in the driver. "touch" is for the tablet with
- touch support. Right now only a few Tablet PCs have this
- feature.
+ Option "Type" "stylus"|"eraser"|"cursor"
+ sets the type of tool the device represent. This option is
+ mandatory.
Option "Device" "path"
sets the path to the special file which represents serial
@@ -1971,228 +1461,94 @@ CONFIGURATION DETAILS
Option "USB" "on"
tells the driver to dialog with the tablet the USB way.
- This option is mandatory for USB tablets.
-
- Option "ForceDevice" "ISDV4"
- tells the driver to dialog with the tablet the serial
- Tablet PC way. It is a special Wacom IV protocol, called
- ISDV4 protocol. This option is mandatory for serial Tablet
- PCs only.
+ This option is only available on some Linux platforms.
Option "DeviceName" "name"
sets the name of the X device.
- Option "Suppress" "number"
+ Option "Suppress" "Inumber"
sets the position increment under which not to transmit
coordinates. This entry must be specified only in the
first Wacom subsection if you have multiple devices for one
- tablet. The default value is 2. If you don't specify this
- entry or your value is less than the default vaule or
- greater than 100, the default value will be used. To
- disable suppression, the entry should be specified as 0.
- When suppress is defined, an event will be sent only when
- at least one of the following conditions is met:
-
- the change between the current X coordinate and the
- previous one is greater than suppress;
-
- the change between the current Y coordinate and the
- previous one is greater than suppress;
-
- the change between the current pressure and the previous
- one is greater than suppress;
-
- the change between the current degree of rotation and
- the previous one of the transducer is greater than suppress;
-
- the change between the current absolute wheel value and the
- previous one is equal to or greater than suppress;
-
- the change between the current tilt value and the previous
- one is equal to or greater than suppress (if tilt is
- supported);
-
- relative wheel value has changed;
-
- button value has changed;
-
- proximity has changed.
+ tablet. If you don’t specify this entry, the default value
+ is computed to
Option "Mode" "Relative"|"Absolute"
- sets the mode of the device. The default value for stylus
- and eraser is Absolute; cursor is Relative; pad mode is
- decided according to its core option due to its nature of
- not moving system cursor: Relative if it is a core device;
- Absolute, otherwise.
+ sets the mode of the device.
+
+ Option "Tilt" "on"
+ enables tilt report if your tablet supports it (ROM version
+ 1.4 and above). If this is enabled, multiple devices at
+ the same time will not be reported.
+
+ Option "HistorySize" "number"
+ sets the motion history size. By default the value is zero.
+
+ Option "AlwaysCore" "on"
+ enables the sharing of the core pointer. When this feature
+ is enabled, the device will take control of the core
+ pointer (and thus will emit core events) and at the same
+ time will be able, when asked so, to report extended
+ events. You can use the last available integer feedback to
+ control this feature. When the value of the feedback is
+ zero, the feature is disabled. The feature is enabled for
+ any other value.
Option "TopX" "number"
- X coordinate of the top corner of the active zone.
- Default to 0.
+ X coordinate of the top corner of the active zone.
Option "TopY" "number"
- Y coordinate of the top corner of the active zone.
- Default to 0.
+ Y coordinate of the top corner of the active zone.
- Option "BottomX" "number"
- X coordinate of the bottom corner of the active zone.
- Default to width of the tablet.
+ Option "BottomX" "Inumber"
+ X coordinate of the bottom corner of the active zone.
Option "BottomY" "number"
- Y coordinate of the bottom corner of the active zone.
- Default to height of the tablet.
-
- Option "ButtonsOnly" "on"|"off"
- disables the device's motion events. Default to off.
-
- Option "ButtonM" "AC"
- reports an action AC when button M is pressed, where M is
- one of the device supported button numbers, it can be 1 to
- 32. The default action reported to Xinput is mouse button M
- click. To ignore the button click, i.e., to not report any
- button click event to Xinput, use "0" or "button 0".
-
- Option "TPCButton" "on"|"off"
- enables the stylus buttons as Tablet PC buttons, i.e.,
- reports stylus button event only when its tip is pressed.
- Default to "on" for Tablet PCs; "off" for all other models.
-
- Option "Touch" "on"|"off"
- enables the touch device for models that support touch
- feature. Default to "on" for tablets with touch; "off" for
- all other models.
-
- Option "Capacity" "number"
- sets touch sensitivity level for capacitive touch device,
- where number can be an integer from -1 to 5. Default is 3
- for capacitive tools and -1 for none capacitive tools.
-
- Option "Speed" "Rspeed"
- sets the cursor's relative movement speed to Rspeed. The
- default value is 1.0. A Rspeed greater than 1.0 will speed
- up the cursor's relative movement. A Rspeed less than 1.0
- but greater than 0 will slow down the cursor's relative
- movement. A Rspeed too close to 0 is not recommanded.
-
- Option "Twinview" "horizontal"|"vertical"|"leftof"|"aboveof"|"none"
- sets the orientation of TwinView to map the tablet to one
- screen and to be able to move the screen cursor from one
- screen to the other when tool reaches the edge of the
- tablet. The cursor can be constrained in a specific screen
- if "ScreenNo" option is added. If you want to map the
- tablet to the whole desktop, you should NOT add this
- option. The default is "none".
-
- Option "TVResolution" "res1,res2"
- specifies different resolutions for the two screens in
- TwinView setup. For example, if the resolution of screen 1
- (res1) is 1024x768 and screen 2 (res2) is 1280x1024, the
- option will be set to:
- Option "TVResolution" "1024x768,1280x1024"
-
- This option is used only when TwinView option is not none.
- It is unnecessary to add this option if your screens are
- displaying in the same resolutions.
-
- Option "ScreenNo" "n"
- In a multi-monitor environment, specifies the screen number
- in which the cursor can move.
-
- Option "MMonitor" "on"|"off"
- turns on/off across monitor movement on a non-TwinView
- multi-monitor desktop. If you have specific tablet mappings,
- i.e. TopX/Y or BottomX/Y were set, the mapping will be
- applied before rotation. The default is "on".
-
- Option "Rotate" "CW"|"CCW"|"HALF"|"NONE"
- rotates the tablet orientation counterclockwise (CCW) or
- clockwise (CW) or 180 degrees (HALF). The default is "NONE".
-
- Option "PressCurve" "x1,y1,x2,y2"
- sets pressure curve by control points x1, y1, x2, and y2.
- Their values are in range from 0..100. The input for
-
- linear curve (default) is "0,0,100,100";
- slightly depressed curve (firmer) might be "5,0,100,95";
- slightly raised curve (softer) might be "0,5,95,100".
+ Y coordinate of the bottom corner of the active zone.
Option "KeepShape" "on"
When this option is enabled, the active zone begins
- according to TopX and TopY. The bottom corner is adjusted
- to keep the ratio width/height of the active zone the same
- as the screen while maximizing the area described by TopX,
+ according to TopX and TopY. The bottom corner is adjusted
+ to keep the ratio width/height of the active zone the same
+ as the screen while maximizing the area described by TopX,
TopY, BottomX, BottomY.
- Option "DebugLevel" "number"
- sets the level of debugging info reported for the defined
- device. There are 12 levels in use, specified by the
- integers between 1 and 12. Once it is defined, all the
- debug messages with a level less than or equal to the
- "number" will be logged into /etc/X11/XFree86.0.log or
- /etc/X11/Xorg.0.log.
-
- Option "CommonDBG" "number"
- sets the level of debugging info for all devices defined
- for the same tablet. There are 12 levels in use, specified
- by the integers between 1 and 12. Once it is defined, all
- the debug messages with a level less than or equal to the
- "number" will be logged into /etc/X11/XFree86.0.log or
- /etc/X11/Xorg.0.log.
-
- Option "CursorProx" "number"
- sets the max distance from tablet to stop reporting
- movement for cursor in relative mode. Default for Intuos
- series is 10, Graphire series (including Volitos) is 42.
+
+ Option "DebugLevel" number
+ sets the level of debugging info reported.
+
+ Option "BaudRate" "38400", "19200" or "9600" (default)
+ changes the serial link speed. This option is only avail‐
+ able for wacom V models (Intuos).
Option "Serial" "number"
sets the serial number associated with the physical device.
This allows to have multiple devices of the same type (i.e.
multiple pens). This option is only available on wacom V
- devices (Intuos series and Cintiq 21UX). To see the serial
- number associated with a device, run <i><a href="#xsetwacom">xsetwacom</a></i>.
+ devices (Intuos). To see which serial number belongs to a
+ device, you have to set the DebugLevel to 6 and watch the
+ output of the X server.
Option "Threshold" "number"
sets the pressure threshold used to generate a button 1
- events of stylus. The default is MaxPressure*3/50.
+ events of stylus devices for some models of tablets (Intuos
+ and Graphire).
SEE ALSO
- Xorg(1x), xorg.conf(5x), xorgconfig(1x), Xserver(1x), X(7).
+ XFree86(1), XF86Config(5x), xf86config(1), Xserver(1), X(7x).
AUTHORS
- Frederic Lepied &lt;lepied@xfree86.org&gt;, Ping Cheng &lt;pingc@wacom.com&gt;,
- John E. Joganic &lt;jej@j&#8364;&#144;arkadia.com&gt;, Magnus Vigerlöf &lt;Magnus.Vigerlof@ipbo.se&gt;
-
-X Version 11 linuxwacom 0.8.0 WACOM(4)
-</pre></blockquote>
-<a name="mouse1">
-</a><h2><a name="mouse1">5.2 - Mouse1 (for some 2.6 systems)</a></h2>
-<p><a name="mouse1">This section largely deals with interaction problems between the mouse1
-device, PS/2 mouse, and USB tablets. Serial users can ignore this part.
-
-</a></p><p></p><div class="diff"><a name="mouse1">Starting from linuxwacom-0.7.1, this is not a problem
-for most kernel 2.6 systems. If you use kernel 2.6 and a driver newer than 0.7.1,
-you may ignore this page. However, it has been reported that on some vendors 2.6
-systems, the information detailed on this page still applies. So, if you tried
-all the other steps and the tablet still has issues, you may want to apply this
-page to elminate the /dev/input/mice issue.</a></div>
-
-<p><a name="mouse1">If you have a USB mouse or PS/2 mouse and are also using a USB tablet,
-there are two solutions here for you: you may either change your
-mouse1 or PS/2 InputDevice section to something other than /dev/input/mice
-or build mousedev.o from this project for your kernel, which will ignore
-Wacom tablets as USB mice. The wacom tablet appears as a mouse to the Linux
-kernel, and consequently, the "mice" device combines the input from all your
-mice, including the tablet. This will not give you the behavior you want.
-A better choice is to specify the precise USB device or PS/2 mouse from which
-you want to receive mouse events, namely /dev/input/mouse0 or /dev/input/mouse1
-or /dev/psaux.
-
-</a></p><p><a name="mouse1">If you do not have a USB mouse, adding the Mouse1 device
-is <i>probably not something you want to do</i>.
-Despite this, Redhat's Anaconda program will do it for you if
-you boot the machine with the tablet plugged in. You'll need to be
-careful about this.
-
-</a></p><p><a name="mouse1">When you use the mouse1 input device, the data flows from the USB wacom
+ Frederic Lepied &lt;lepied@xfree86.org&gt;
+
+4.2.0 Version WACOM(4x)
+</PRE></BLOCKQUOTE>
+<A NAME="mouse1">
+<H2>5.2 - Mouse1</H2>
+<P>Adding the Mouse1 device is <I>probably not something you want to do</I>,
+and Redhat's Anaconda program will do it for you if you boot the machine with
+the tablet plugged in. You'll need to be careful about this.
+
+<P>When you use the mouse1 input device, the data flows from the wacom
kernel driver, through the event subsystem, down into the mousedev driver,
out the /dev/input/mouse0 device, and finally into the XInput mouse driver.
You effectively lose all your absolute positioning information because the
@@ -2200,80 +1556,109 @@ mousedev driver converts it into relative data. Additionally, the XFree86
wacom driver does not get control of the cursor because mouse1 is providing
those events.
-</a></p><p><a name="mouse1">Therefore, if you have a Mouse1 section, leave it. Redhat 8.0 at least,
-expects it to be there; however, if you do not have a USB mouse and you
-are using a USB tablet, you will not be using this section, so make
-certain that it is commented out of the ServerLayout section covered next.
-
-</a></p><p><a name="mouse1">There is one exception however. If you have no other mouse
-device in your ServerLayout section, <i>do not</i> remove Mouse1. XFree86
-will not start without at least one core pointer, and the tablet
-does not count unless it is specifically identified as a "CorePointer"
-rather than merely "SendCoreEvents."
-
-</a><a name="srvlayout">
-</a></p><h2><a name="srvlayout">5.3 - ServerLayout</a></h2>
-<p><a name="srvlayout">The ServerLayout section describes what devices the X server will use.
+<P>Therefore, if you have a Mouse1 section, leave it. Redhat 8.0 at least,
+expects it to be there; however, you will not be using it, so make certain
+that it is commented out of the section covered next.
+<A NAME="srvlayout">
+<H2>5.3 - ServerLayout</H2>
+<P>The ServerLayout section describes what devices the X server will use.
Modify the ServerLayout section to reflect the new devices. Make certain
-to comment out the Mouse1 device if determined necessary from the previous
-page.
+to comment out the Mouse1 device.
-</a></p><blockquote><pre><a name="srvlayout">Section "ServerLayout"
- Identifier "Default Layout"
+<BLOCKQUOTE><PRE>
+Section "ServerLayout"
Screen 0 "Screen0" 0 0
InputDevice "Mouse0" "CorePointer"
InputDevice "Keyboard0" "CoreKeyboard"
- <b>InputDevice "stylus" "SendCoreEvents"
- InputDevice "eraser" "SendCoreEvents"
- InputDevice "cursor" "SendCoreEvents" # For non-LCD tablets only
- InputDevice "touch" "SendCoreEvents" # Only a few TabletPCs support this type
- InputDevice "pad" # For Intuos3/CintiqV5/Graphire4/Bamboo tablets</b>
+ <B>InputDevice "cursor" "SendCoreEvents"
+ InputDevice "stylus" "SendCoreEvents"
+ InputDevice "eraser" "SendCoreEvents"</B>
+ #InputDevice "Mouse1" "SendCoreEvents"
+ #InputDevice "tablet" "SendCoreEvents"
EndSection
-</a></pre></blockquote>
-
-<p><a name="srvlayout">This section determines which devices are actually used by the server.
-In the case above, the cursor, stylus, eraser, touch, and pad devices are selected.
-At present, this is the correct configuration for proper
-operation of the tablet whether you are using the beta package or the production package.
-
-</a></p><p><a name="srvlayout">You can configure one of your Wacom devices as a Core Pointer if you don't
-have a regular mouse on your system. However, you lose the Wacom specific
-functions, such as pressure sensitivity and absolute mode when you use that device.
-
-</a></p><p><a name="srvlayout">You have completed the
-XF86Config/xorg.conf file changes. But aware that if you reboot
-your computer with the Wacom plugged in and Redhat's Anaconda program
-notices,
-it may treat the tablet as a USB mouse and reconfigure this file
-incorrectly.
+</PRE></BLOCKQUOTE>
+
+<P>This section determines which devices are actually used by the server. In
+the case above, the cursor, stylus, and eraser devices are selected while
+the mouse1 and tablet devices are commented out. At present, this is the
+correct configuration for proper operation of the tablet whether you are
+using the beta package or the production package.
+
+<P>The new wacom_drv.o driver contains two independent implementations of the
+tablet code. Using the "tablet" device instead of the cursor/stylus/eraser
+devices will enable that code. Presently, that will do little for you since
+the code is fairly volatile and is simply a testbed for various design ideas.
+As it becomes more useful, I will update this section.
+
+<P>You have completed the XF86Config file changes. By aware that if you reboot
+your computer with the Wacom plugged in and Redhat's Anaconda program notices,
+it will treat the tablet as a USB mouse and reconfigure this file incorrectly.
You may need to go back and check the file to ensure that everything is
-still correct afterwards. Rebooting with the device detached is not
-recommended since X server doesn't properly support hotplugging yet. My
-recommendation is to tell Anaconda to ignore the tablet until the
-device
+still correct afterwards. Rebooting with the device detached seems to
+reverse the process, but again, you should check the file to be certain.
+My recommendation is to tell Anaconda to ignore the tablet until the device
detection works properly.
-</a><a name="restartx">
-</a></p><h2><a name="restartx">5.4 - Restart X</a></h2>
-<p><a name="restartx">Finally, restart X. You may wish to do this from runlevel 3 for
+<A NAME="wacomdrv">
+<H2>5.4 - Updating wacom_drv.o</H2>
+<P>There are a number of wacom_drv.o files about. XFree86 is shipping
+version 23. Redhat 8.0 is shipping version 25. Lepied's page has the
+source code for 26, but the binary identifies itself as 23ss1. The
+<A HREF="#download">Downloading the Code</A> page currently
+offers source and binary for 26-j0.2.0 in the stable package
+and 26-j0.3.2a in the beta version. In total, I recommend
+using the drivers in the packages that I provide since they correspond with
+what is shown in this document. Any new functionality that gets added will
+be built on top of these files as well.
+
+<P>Note: the binary wacom_drv.o file is located in the prebuilt directory
+of the stable and beta packages. Building this file from source (which is
+provided) is a major hassle, and I do not recommend it unless you are
+developer yourself or the binary is simply not compatible with your system.
+Instructions for rebuilding from source are available in the Appendix
+under <A HREF="#builddrv">Building wacom_drv.o From Scratch</A>.
+
+<P>With that said, locate and replace wacom_drv.o. Using <i>locate</i> again, we find
+the driver in the X11 tree. This directory is pretty standard, so it is
+unlikely that your file will be located elsewhere. Note the assumption is
+that you are using XFree86 4.x. Anything from the 3.x version probably won't
+work.
+
+<BLOCKQUOTE><PRE>
+[root@ayukawa root]# locate wacom_drv.o
+/usr/X11R6/lib/modules/input/<B>wacom_drv.o</B>
+[root@ayukawa root]# cd /usr/X11R6/lib/modules/input
+[root@ayukawa input]# cp <B>wacom_drv.o</B> /home/jej/src/wacom/<B>wacom_drv_old.o</B>
+[root@ayukawa input]# cp /home/jej/src/wacom/prebuilt/<B>wacom_drv.o wacom_drv.o</B>
+</PRE></BLOCKQUOTE>
+
+Again, the old file is copied away, and replaced with the newer version. The
+binary modules are presently built on a Redhat 8.0 system using gcc 3.2 under
+glibc. This should work for most, if not all, major distributions. If it
+does not load on yours, please let me know.
+
+<A NAME="restartx">
+<H2>5.5 - Restart X</H2>
+<P>Finally, restart X. You may wish to do this from runlevel 3 for
testing purposes.
-</a></p><blockquote><pre><a name="restartx">[root@ayukawa root]# init 3
+<BLOCKQUOTE><PRE>
+[root@ayukawa root]# init 3
...processes starting and stopping...
[root@ayukawa root]# startx
-</a></pre></blockquote>
-
-<a name="restartx">If the X server dies, you can always back-out the
-changes to the XF86Config or xorg.conf file and try again. But first,
-look at the X log file (XFree86.0.log for XFree86 and Xorg.0.log for
-Xorg) for clues.
-You might want to do this even if everything works correctly. When
-things
+</PRE></BLOCKQUOTE>
+
+If the X server dies, you can always back-out the changes to the XF86Config
+file and try again. Worse case, copy the wacom_drv_old.o file back to
+its original place. But first, look at the XFree86 log file for clues.
+You might want to do this even if everything works correctly. When things
are running right, the following lines appear in my log file.
-</a><blockquote><pre><a name="restartx">[root@ayukawa root]# grep -i wacom /var/log/XFree86.0.log
+
+<BLOCKQUOTE><PRE>
+[root@ayukawa root]# grep -i wacom /var/log/XFree86.0.log
(II) LoadModule: "wacom"
(II) Loading /usr/X11R6/lib/modules/input/wacom_drv.o
(II) Module wacom: vendor="The XFree86 Project"
-(II) Wacom driver level: <b>47-0.8.2-2</b> $
+(II) Wacom driver level: <B>26-j0.2.0</B> $
(II) XINPUT: Adding extended input device "eraser" (type: Wacom Eraser)
(II) XINPUT: Adding extended input device "stylus" (type: Wacom Stylus)
(II) XINPUT: Adding extended input device "cursor" (type: Wacom Cursor)
@@ -2283,12 +1668,12 @@ suppress=0
(==) Wacom Cursor top X=0 top Y=0 bottom X=30480 bottom Y=30480
(==) Wacom Stylus top X=0 top Y=0 bottom X=30480 bottom Y=30480
(==) Wacom Eraser top X=0 top Y=0 bottom X=30480 bottom Y=30480
-</a></pre></blockquote>
+</PRE></BLOCKQUOTE>
-<a name="restartx">Notice the driver version 47-0.8.2-2 above. This is the new stable
-wacom_drv.o driver. The beta driver is currently 47-0.8.3-3.
+Notice the driver version 26-j0.2.0 above. This is the new stable
+wacom_drv.o driver. The beta driver is currently 26-j0.3.2a.
-</a><p><a name="restartx">First things first, you should lift the mouse off the tablet and place it
+<P>First things first, you should lift the mouse off the tablet and place it
back down. This seems to help reset things internally. When you replace the
mouse, the cursor should jump to that portion of the screen. If everything is
working correctly, the mouse should work in absolute mode with the four
@@ -2296,1163 +1681,200 @@ corners of the tablet corresponding with the four corners of the screen. If
the cursor stops short of an edge, then the kernel driver limits are probably
incorrect. Please let me know so that I can update the driver.
-</a></p><p><a name="restartx">Next, remove the mouse and try using the eraser end of the stylus.
-Hovering over the surface of the tablet should move the cursor. Touching
-the eraser tip to the surface should generate a click. If you invert the
+<P>Next, remove the mouse and try using the eraser end of the stylus.
+Hovering over the surface of the tablet should move the cursor. Touching the
+eraser tip to the surface should generate a click. If you invert the
pen and use the stylus tip, you should get a similar result. If the pen
-tip generates spurious touch events, you will need to increase the
-threshold value in the InputDevice section. Wacdump is useful for
-determining the appropriate value.
-
-</a></p><p><a name="restartx">Lastly, if you would like more logging, the parameter "DebugLevel" (for
-individual tools) and "CommonDBG" (for all tools associated with the same
-tablet) can be set to values between 1 and 12, with 12 being way too much,
-and 1 being fairly useful.
-
-</a></p><p><a name="restartx">If X server failed to start and you are running the prebuilt wacom_drv.(s)o, you may have to go back to </a><a href="#config">Configuring the Package</a> page to build the driver on your system.
-
-<a name="ptrstat">
-</a></p><h2><a name="ptrstat">5.5 - Check the Pointer Status</a></h2>
-<p><a name="ptrstat">You can check the XInput pointer status by using <i>xsetpointer</i>
+tip generates spurious touch events, you will need to increase the threshold
+value in the InputDevice section. Wacdump is useful for determining the
+appropriate value. My pen pressure oscillates between 0 and 6 so I use
+a threshold of 10 to compensate.
+<A NAME="ptrstat">
+<H2>5.6 - Check the Pointer Status</H2>
+<P>You can check the XInput pointer status by using <i>xsetpointer</i>
as below. The man page states that calling xsetpointer with the name of
-a particular device will set it as the primary pointing device.
+a particular device will set it as the primary pointing device. So far,
+that has not been the case in my experience; however, that is the subject
+of current development, so try it, and if it doesn't work, stay tuned.
-</a></p><blockquote><pre><a name="ptrstat">[root@ayukawa log]# xsetpointer -l
+<BLOCKQUOTE><PRE>
+[root@ayukawa log]# xsetpointer -l
"eraser" [XExtensionDevice]
"stylus" [XExtensionDevice]
"cursor" [XExtensionDevice]
"Mouse0" [XPointer]
"keyboard" [XKeyboard]
-</a></pre></blockquote>
-
-<a name="xidump">
-</a><h1><a name="xidump">6.0 - Viewing XInput Events (xidump)</a></h1>
-<p><a name="xidump">The xidump program is similar to wacdump, but it parses and displays
-event data from the XFree86 XInput extension rather than from the tablet
-itself. This is useful for seeing what programs like gimp and gsumi are
-receiving from X.
-
-</a></p><p><a name="xidump">Presently, xidump will display proximity and motion events for
-the stylus, cursor, eraser, and pad input devices. xidump supports
-different display modes with "curses" and "raw" modes already
-implemented and a GTK-based graphical mode in the works. The curses
-mode is probably the most useful in terms of verifying that the tablet
-is functioning correctly in the XFree environment; however, the raw
-mode has the additional benefit of being able to verify the order,
-timing, and history of events.
-
-</a></p><p><a name="xidump">Since xidump uses the same XInput interface that gimp and gsumi use
-to get tablet data, the values displayed in xidump should be identical
-to what they are receiving. If you are having trouble with pressure in
-gimp, chances are that xidump will demonstrate the same problem.
-xidump does not require root access to use.
-
-</a></p><p><a name="xidump"><b>Running xidump</b>
-
-</a></p><p><a name="xidump">xidump takes one argument, the input device specified in your
-XF86Config/xorg.conf file. It is the Identifier entry in the
-InputDevice section. Normally they are either stylus, cursor, eraser,
-touch, or pad. You can get a complete list by running xidump
-with the list option '-l'. xidump has the additional feature of dumping all
-the device capabilities by specifying the verbose option '-v'. Both are
-demonstrated below.
-
-</a></p><p><a name="xidump">Note: The device identifiers (input_device) are case sensitive.
-
-</a></p><blockquote><pre><a name="xidump">[jej@ayukawa src]$ ./xidump -l
-eraser extension
-stylus extension
-cursor extension
-Mouse0 disabled
-keyboard keyboard
-
-[jej@ayukawa src]$ ./xidump -l -v eraser
-eraser extension
- key: min=8, max=39, num=32
- btn: num=1
- val: axes=6 mode=abs buf=0
- axis[0]: res=2540, min=0, max=30480
- axis[1]: res=2540, min=0, max=30480
- axis[2]: res=1, min=0, max=1023
- axis[3]: res=1, min=-64, max=63
- axis[4]: res=1, min=-64, max=63
- axis[5]: res=1, min=0, max=1023
-</a></pre></blockquote>
-
-<p><a name="xidump">In the first dump, we see the eraser, stylus, and cursor with the
-additional Mouse0 pointer and keyboard. Only the first three are
-"extension" devices. Using xidump on the keyboard or mouse pointer
-will generate an error since neither are XInput devices.
-
-</a></p><p><a name="xidump">The second dump shows the capabilities of the eraser device including the
-number of keys (32), buttons (1), and axes (6). It also shows the
-mode to be absolute. In order, the axes are: x, y, pressure, tilt-x,
-tilt-y, and wheel. When the cursor is used, axis 3 becomes z-rotation
-instead of tilt-x.
-
-</a></p><p><a name="xidump">You should be aware that xidump and gimp must take ownership of the device
-in order to get real-time data. This creates a conflict if you are running
-both of them simultaneously. gimp is the more clever of the two programs in
-that it only "grabs" the input device if you are hovering over the gimp
-drawing window. xidump is less friendly. In order to display the absolute
-position across the entire screen, it creates a small "listening window,"
-grabs the device immediately, and does not release it until you quit the
-program. Neither program should fail, but you will not be able to draw
-in gimp and run xidump at the same time if they are both using the same
-input device.
-
-</a></p><p><a name="xidump">We will run xidump in raw mode for the first time to see the stylus
-events directly. A small window will appear on the desktop while xidump
-runs; you can safely ignore it. Closing it will kill the application.
-
-</a></p><blockquote><pre><a name="xidump">[jej@ayukawa src]$ ./xidump -u raw stylus
-14.56291895: Proximity In
-14.56305595: Motion: x= +5978 y=+28728 p= 0 tx= +64 ty= +64 w= +0 ID: 2323 Serial: -60
-...
-16.87158095: Motion: x= +4941 y=+27842 p= 225 tx= +41 ty= +67 w= +0 ID: 2323 Serial: -60
-16.87164395: Button: 1 DOWN
-16.87169595: Motion: x= +4964 y=+27844 p= 398 tx= +42 ty= +66 w= +0 ID: 2323 Serial: -60
-...
-17.27328395: Motion: x= +5261 y=+27543 p= 3 tx= +48 ty= +64 w= +0 ID: 2323 Serial: -60
-17.27334395: Button: 1 UP
-17.27515995: Motion: x= +5348 y=+27451 p= 4 tx= +48 ty= +63 w= +0 ID: 2323 Serial: -60
-...
-17.35933795: Motion: x= +7089 y=+27061 p= 4 tx= +48 ty= +63 w= +0 ID: 2323 Serial: -60
-17.37444395: Proximity Out
-&lt;Ctrl-C&gt;
-</a></pre></blockquote>
-
-<p><a name="xidump">The timestamp on the left is seconds elapsed; the next field is the
-event type. Mostly, you will encounter motion events although I've trimmed
-many of them out of this listing. As you can see from the above, the first line
-is a "proximity in" event which indicates the stylus came in range of the
-tablet. The last event was a "proximity out." At 16.87 seconds, I tapped
-the stylus to the tablet surface as recorded by the "Button: 1 DOWN" and
-subsequent "UP" message. Raw mode is useful for verifying the order and
-timing of messages, but is not particularly clean. The ncurses mode works
-much better.
-
-</a></p><blockquote><pre><a name="xidump">[jej@ayukawa src]$ ./xidump stylus
-InputDevice: stylus
-Valuators: Absolute ID: 2323 Serial Number: -60
-
- x-axis y-axis pressure x-tilt y-tilt wheel
- data: +10826 +09919 +00084 +00058 +00065 +00000
- min: +00000 +00000 +00000 -00064 -00064 +00000
- max: +30480 +30480 +01023 +00063 +00063 +01023
- res: +00000 +00000 +00039 +00001 +00001 +00001
-
-********
-Proximity: IN
- Focus:
- Buttons: 1-DOWN
- Keys:
-</a></pre></blockquote>
-
-<p><a name="xidump">All of the ranges are displayed above, include their resolutions which as
-far as I know are not normally used. Only the proximity, focus, valuator,
-and button events are currently implemented.
-
-</a></p><p><a name="xidump">For completeness sake, here are the command line options:
-
-</a></p><blockquote><pre><a name="xidump">Usage: xidump [options] input_device
- -h, --help - usage
- -v, --verbose - verbose
- -V, --version - version
- -l, --list - list available input devices
- -u, --ui ui_type - use specified ui, see below
-
-Use --list option for input_device choices
-UI types: curses, raw
-</a></pre></blockquote>
-
-<p><a name="xidump">There are not many options, but the --list option is helpful for
-identifying devices, and the --ui option allows you to switch between
-curses and raw modes. Adding the --verbose option increases the amount of output, and
-when used in conjunction with --list, displays the device capabilities.
-
-</a><a name="tabletpc">
-</a></p><h1><a name="tabletpc">7.0 - Tablet PC</a></h1>
-
-<p><a name="tabletpc">The Wacom digitizers embedded in Tablet PCs
-utilitizes a special protocol IV, ISDV4. Most of them are serial
-tablets. There are a few Wacom USB tablet PC OEMs on the market
-recently. However, we don't support USB tablet PC yet. This page is for
-serial Tablet PC only. </a></p><p><a name="tabletpc">Similar to the conventional serial
-tablets, serial tablet PCs use a serial controller (UART). But,
-normally, they are not set to any serial ports. They are effectively
-serial devices, but require special configuration (setserial) under
-Linux. </a></p><div class="diff">
-<p><a name="tabletpc">You can use <i>xxd</i> to see if your tablet has been mapped onto a serial port or not. To do so, follow the steps below:
-
-</a></p><blockquote><pre><a name="tabletpc">[jej@ayukawa ~]$su
-Password:
-[jej@ayukawa ~]# xxd /dev/ttyS0
-</a></pre></blockquote>
-
-<p><a name="tabletpc">Move your pen on your tabletPC. If you see output
-from the terminal while you move the pen, your tablet has been mapped
-to port 1. Quit xxd by Ctrl+c. Then ignore the rest of this page and go
-to(see </a><a href="http://linuxwacom.sourceforge.net/index.php/howto/x11">Configuring X11</a>) page. Otherwise, apply xxd to port 1 to 4. If none of them show output, you need to manually map the tablet to a serial port.
-</p></div>
-
-<p>Here is a sample command. The IO port may be different for your Tablet PC.
-
-</p><blockquote><pre>[jej@ayukawa src]$ setserial /dev/ttyS2 port 0x93f8 autoconfig
-</pre></blockquote>
-
-<p>This command needs to be excuted with each reboot before X server starts.
-</p><p>You can add the command into one of your favorite start script. I normally
-add it into /etc/rc.d/rc.local. Here is my rc.local:
-
-</p><blockquote><pre>#!/bin/sh
-#
-# This script will be executed *after* all the other init scripts.
-# You can put your own initialization stuff in here if you don't
-# want to do the full Sys V style init stuff.
-
-touch /var/lock/subsys/local
-setserial /dev/ttyS2 port 0x93f8 autoconfig
-</pre></blockquote>
-
-<p>After installing wacom_drv.o and other programs, such as wacomcpl and wacdump,
-restart X server. Now you can view raw tablet data by:
-
-
-</p><blockquote><pre>[jej@ayukawa util]$ ./wacdump -f tpc /dev/ttyS2 # Wacom digitizer on fake COM3
-
-<div class="diff">
-If your wacdump is from linuxwacom version 0.7.5 or older, issue
-[jej@ayukawa util]$ ./wacdump -f c100 /dev/ttyS2
-</div>
-</pre></blockquote>
-
-<p>If everything looks right from wacdump (see <a href="http://linuxwacom.sourceforge.net/index.php/howto/wacdump">Using wacdump</a>),
-you can update /etc/X11/XF86Config or /etc/X11/xorg.conf to load wacom X driver
- (see <a href="http://linuxwacom.sourceforge.net/index.php/howto/x11">Configuring XFree86/X11R6</a>).
-
-</p><p>Please notice that in Wacom InputDevice section, the following 2 options are
-required for Tablet PC:
-
-</p><blockquote><pre> <b>Option "Device" "/dev/ttyS2" # SERIAL ONLY</b>
- <b>Option "ForceDevice" "ISDV4" # Tablet PC ONLY</b>
-</pre></blockquote>
-
-<p>Refer to <a href="http://linuxwacom.sourceforge.net/index.php/howto/inputdev">Adding the InputDevices</a> for details.
-
-</p><blockquote><div class="diff">
-
-<p>Some HP Tablet PCs require you explicitly run the following program before setserial. This
-is due to the fact that Wacom Digitizer on HP Tablet PCs are not mapped to any serial
-port by default.
-
-</p><p>Please compile tc1100ts.c as mentioned below and copy the executable (tc1100ts)
-to /usr/sbin. Then add the following two lines to the end of your /etc/rc.d/rc.local:
-
-</p><p>/usr/sbin/tc1100ts
-</p><p>setserial /dev/ttyS2 port 0x03e8 autoconfig
-
-</p><pre><b>Mapping Wacom Digitizer to /dev/ttyS2 for HP Tablet PC</b>
-
-
-/*
- * HP TC1100 Touchscreen Enable
- * Copyright (c) 2004 Hewlett-Packard Co.
- *
- * Compile with `cc -O2 -o tc1100ts tc1100ts.c',
- * and run as root with `./tc1100ts'.
- *
- * This standalone program enables the Serial Port 1
- * (SP1) of the NS LPC Super I/O, where the Wacom
- * Digitizer is connected to on the HP TC1100 Tablet PC.
- *
- * The serial device is mapped to 0x3e8 IRQ0-4 to match
- * the default /dev/ttyS2 port and IRQ mapping on Linux.
- *
- * To proof that the Wacom Digitizer is enabled by this
- * standalone, do the following:
- * - Change to superuser mode, i.e. root
- * - setserial /dev/ttyS2
- * it should return:
- * /dev/ttyS2, UART: unknown, Port: 0x03e8, IRQ: 4
- * - ./tc1100ts
- * - setserial /dev/ttyS2 autoconfig
- * - setserial /dev/ttyS2
- * now returns:
- * /dev/ttyS2, UART: 16550A, Port: 0x03e8, IRQ: 4
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys io.h="">
-#include <stdlib.h>
-
-const int cfgindex = 0x4e;
-const int cfgdata = 0x4f;
-
-#define wsio(i,d) {outb(i,cfgindex); outb(d,cfgdata);}
-
-int main()
-{
- /* Get access to the ports */
- if (iopl(3)) {perror("iopl"); exit(1);}
-
- // See the SuperIO Specificatio for details of each register
- wsio(0x07,0x03); // Select Logical Device - Serial Port 1
- wsio(0x30,0x00); // De-activate Logical Device
- wsio(0x60,0x03); // I/O Port Base [15-08]
- wsio(0x61,0xe8); // I/O Port Base [07-00]
- wsio(0x70,0x14); // Enables Wake-up on IRQ4
- wsio(0x71,0x03); // Level IRQ Req, Hi priority
- wsio(0x74,0x04); // DMA Channel Select 0 - no DMA
- wsio(0x75,0x04); // DMA Channel Select 1 - no DMA
- wsio(0x30,0x01); // Activate Logical Device
-
- /* We don't need the ports anymore */
- if (iopl(0)) {perror("iopl"); exit(1);}
-
- exit(0);
-}
-
-/* end of tc1100ts.c */
-</stdlib.h></sys></unistd.h></stdio.h></pre>
-
-</div></blockquote>
-
-<a name="wacomcpl">
-</a><h1><a name="wacomcpl">8.0 - GUI-Based (tcl/tk) Wacom Control Panel(wacomcpl)</a></h1>
-<p><a name="wacomcpl">wacomcpl is a simple graphic Wacom driver configuration tool. It
-changes the pressure sensitivity, click threshold, button functions,
-cursor mode, speed, mapping, etc. without having to manually modify
-XF86Config/xorg.conf file. For Cintiq and Tablet PC users, it is
-also a tool to calibrate the tablet. wacomcpl should be launched
-when you login as yourself since .xinitrc (or .xsession), a file
-under your home directory, will be updated locally each time you
-run wacomcpl. The .xinitrc (or .xsession) stores the preferences
-you selected through wacomcpl for your next login. The goal is to
-give each user a chance to use his/her own preference on a shared system.
-
-</a></p><div class="diff">
-<p><a name="wacomcpl">If you want all users on one system to share some settings, you can
-copy those lines started with xsetwacom in ~/.xinitrc (or ~/.xsession)
-to /etc/X11/xinit/xinitrc (/etc/X11/xinit/Xsession).
-
-</a></p><p><a name="wacomcpl">If your system doesn't execute .xinitrc (or .xsession) at login, each
-time after exiting from wacomcpl, you will need to copy those xsetwacom
-lines in .xinitrc (or .xsession) to a startup script (.bashrc, .cshrc,
-.profile, etc.) that your system launches. You can also modify wacomcpl-exec
-to automate this step.
-
-</a></p><p><a name="wacomcpl">However, it is reported that there are older systems on which can not run
-wacomcpl due to some XFree86 interface error. The workaround is to add the
-configuration options to your X config file, refer to </a><a href="#x11">Configuring X11</a> page for details.
-</p></div>
-
-<p><b>Running wacomcpl</b>
-
-</p><p>If wacom_drv.(s)o was running while installing wacomcpl, wacomcpl can be
-launched immediately after <i>make install</i> and <i>exit</i>.
-
-</p><p>If wacom_drv.(s)o is installed by the same <i>make install</i>
-as wacomcpl is, restarting X server is required to use the newly built
-wacom_drv.(s)o. We strongly recommand to build and install the
-wacom_drv.(s)o and wacomcpl from the same release package since the out
-of sync wacom_drv.(s)o and wacomcpl may crash your X server.
-<a name="xsetwacom">
-</a></p><h1><a name="xsetwacom">9.0 - Command Line Configuration Interface (xsetwacom)</a></h1>
-<p><a name="xsetwacom">The xsetwacom is a command-line Wacom driver configuration tool. It
-changes the pressure sensitivity, click threshold, button functions,
-cursor mode and speed, and much more without having to manually modify
-XF86Config or xorg.conf file.
-
-</a></p><p><a name="xsetwacom">The basic usage and options can be viewed by issuing <i>xsetwacom</i>.
-
-</a></p><p><a name="xsetwacom"><b>Note: </b>The device identifiers (dev_name) are case sensitive. You should
-use the dev_name exactly the same as <i>xsetwacom list</i> shows. The examples
-below assume that Stylus, cursor, and pad are used.
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom
-Usage: xsetwacom [options] [command [arguments...]]
-Options:
- -h, --help - usage
- -v, --verbose - verbose output
- -V, --version - version info
- -d, --display disp_name - override default display
- -s, --shell - generate shell commands for 'get'
- -x, --xconf - generate X.conf lines for 'get'
-
-Commands:
- list [dev|param] - display known devices, parameters
- list mod - display supported modifier and specific keys for keystokes
- set dev_name param [values...] - set device parameter by name
- get dev_name param [param...] - get current device parameter(s) value by name
- getdefault dev_name param [param...] - get device parameter(s) default value by name
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">xsetwacom supports 3 forms of get/getdefault commands: <i>xsetwacom get</i>
-returns the parameter's raw value; <i>xsetwacom -x get</i> returns the value in Xorg.conf
-form; and <i>xsetwacom -s get</i> returns the value in shell command form.
-
-</a></p><p><a name="xsetwacom">The most used xsetwacom command is <i>xsetwacom set dev_name param [values...]</i>,
-where param is an option which will be set to values in wacom_drv.o after excuting xsetwacom.
-To better understand the use of this command, let's see some examples. Assume that you use
-<i>Stylus</i> as your Wacom tool's Identifier, which is considered as dev_name in xsetwacom command.
-
-</a></p><p><a name="xsetwacom">If you want to change <i>Stylus's</i> mode from absolute (default) to relative, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set Stylus mode relative
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to change button 2 to left-double-click, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set Stylus button2 "dblclick 1"
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to change button 2 to button 5, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set Stylus Button2 "button 5"
-or
-[jej@ayukawa linuxwacom]$xsetwacom set Stylus Button2 5
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to change button 3 to ModeToggle, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set Stylus button3 modetoggle
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to know what the current (or default) pressure sensitivity setting is, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom -s get Stylus PressCurve (output in xsetwacom format)
-xsetwacom set stylus PressCurve "0 15 85 100"
-or
-[jej@ayukawa linuxwacom]$xsetwacom -x get Stylus PressCurve (output in xorg.conf Option format)
- Option "PressCurve" "0,15,85,100"
-
-[jej@ayukawa linuxwacom]$xsetwacom -x getdefault Stylus PressCurve
- Option "PressCurve" "0,0,100,100"
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to set the pressure sensitivity a bit softer, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set Stylus PressCurve 0 15 85 100
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want the buttons behave the Tablet PC way, i.e., sending button event only when
-button1 (the tip) is pressed, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set Stylus TPCButton on
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to change <i>pad's</i> button 1 to ctrl alt F2, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set pad Button1 "core key ctrl alt F2"
-</a></pre></blockquote>
-
-<p><a name="xsetwacom">If you want to change <i>pad's</i> button 2 to ctrl alt backspace, then:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa linuxwacom]$xsetwacom set pad Button2 "core key ctrl alt backspace"
-</a></pre></blockquote>
-
-<div class="diff"><a name="xsetwacom"><b>Note:</b> keystrokes and modifiers are only supported for Xorg 6.8 or later.
-</a></div>
-
-
-<p><a name="xsetwacom"><b>xsetwacom supported parameters</b>
-
-</a></p><p><a name="xsetwacom">Below is a list of the parameters and their values used by <i>xsetwacom</i> command (a similar
-output can be viewed by <i>xsetwacom list param</i>. All functions apply to the associated tool
-unless explicitly stated otherwise):
-
-</a></p><blockquote><pre><a name="xsetwacom"> param [values...] results
-------------------------------------------------------------------
- Mode Relative|Absolute sets the mode of the device
- TopX integer sets the X coordinate of the top corner of the active zone
- TopY integer sets the Y coordinate of the top corner of the active zone
- BottomX integer sets the X coordinate of the bottom corner of the active zone
- BottomY integer sets the Y coordinate of the bottom corner of the active zone
- STopX<i>i</i> integer returns screen <i>i</i> left coordinate in pixels
- STopY<i>i</i> integer returns screen <i>i</i> top coordinate in pixels
- SBottomX<i>i</i> integer returns screen <i>i</i> right coordinate in pixels
- SBottomY<i>i</i> integer returns screen <i>i</i> bottom coordinate in pixels
- Button<i>M</i> integer|keystroke sets button <i>M</i> to button integer click or keystroke
- Button<i>M</i> 0 ignores button <i>M</i> click
- RelWUp integer|keystroke sets relative wheel up to button click or keystroke
- RelWDn integer|keystroke sets relative wheel down to button click or keystroke
- AbsWUp integer|keystroke sets absolute wheel up to button click or keystroke
- AbsWDn integer|keystroke sets absolute wheel down to button click
- StripLUp integer|keystroke sets left strip up to button click or keystroke
- StripLDn integer|keystroke sets left strip down to button click or keystroke
- StripRUp integer|keystroke sets right strip up to button click or keystroke
- StripRDn integer|keystroke sets right strip down to button click or keystroke
- PressCurve i1 i2 i3 i4 sets the pressure bezier curve, where i1+i4=100; i2+i3=100
- DebugLevel integer (0 - 12) sets the level of debugging trace for the specified tool
- CommonDBG integer (0 - 12) sets the level of debugging trace for all tools
- associated with the same tablet.
- Suppress integer (0 - 100) number of data trimmed for the tools associated
- with the same tablet.
- Screen_No integer (-1 - 5) sets screen number the tablet is mapped to.
- TwinView none|vertical|horizontal
- |leftof|aboveof sets the mapping to TwinView. Tablet mappings applied after
- this command will be based on the new tablet orientation.
- TVResolution0 width x height sets MetaModes option for TwinView Screen 0.
- TVResolution1 width x height sets MetaModes option for TwinView Screen 1.
- SpeedLevel integer (1 - 11) sets relative cursor movement speed
- ClickForce integer (1 - 21) sets tip/eraser pressure threshold with clickforce scale
- Threshold integer sets tip/eraser pressure threshold directly to the pressure
- xyDefault resets the bounding coordinates to default in tablet units
- mmonitor on|off turns on/off across monitor movement on (non-TwinView)
- multi-monitor desktop
- TPCButton on|off turns on/off the buttons as Tablet PC buttons
- Touch on|off turns on/off Touch events (default is enable/on for tablets with touch).
- Capacity integer (-1 - 5) sets the touch sensitivity level for capacitive touch device
- (default is 3 for capacitive tools, -1 for none capacitive tools).
- CursorProx integer (distance) sets cursor distance margin for proximity-out
- in distance from the tablet surface
- Rotate none|cw|ccw|half sets the rotation of the tablet.
- ToolID returns the ID of the associated device.
- ToolSerial returns the serial number of the associated device.
- GetTabletID/TabletID returns the tablet ID of the associated device.
- NumScreen returns number of screens configured for the desktop.
-------------------------------------------------------------------
-
-Event description format:
-[CORE] [EVENT TYPE] [MODIFIERS] [CODE]
- CORE: Emit core events irrespective of the SendCoreEvents setting
- EVENT TYPE: the type of event to emit:
- KEY: Emit a key event
- BUTTON: Emit a button event
- DBLCLICK: Emit a double-click button event
- MODETOGGLE: Toggle absolute/relative tablet mode
- DISPLAYTOGGLE: Toggle cursor movement among screens
- for the selected tool except pad which
- applies to all tools asssociated with the tablet
- MODIFIERS: use "xsetwacom list mod"
- to see a list of modifiers and specific keys
- CODE: Button number if emit a button event
- or specific keys and any other keys not listed as mod
-
-</a></pre></blockquote>
-
-
-<p><a name="xsetwacom"><b>Associating parameters to physical devices</b>
-
-</a></p><p><a name="xsetwacom">Following is a list of the parameters that are associated with the elements of devcies.
-
-</a></p><blockquote><pre><a name="xsetwacom"> param tools
---------------------------------------------------------------------------
-Button# All Wacom styli/pucks buttons
- Tablet ExpressKeys
-RelWUp/RelWDn Graphire4 tablet wheel
- Wacom puck Fingerwheel
-AbsWUp/AbsWDn Intuos puck Thumbwheel
- Intuos Airbrush Fingerwheel
- Bamboo tabelt Touch Ring
-StripLUp/StripLUp Left Touch Strip on Intuos3 and V5 Cintiq (Cintiq 21UX/12WX/20WSX) tablets
-StripRUp/StripRUp Right Touch Strip on Intuos3 and V5 Cintiq (Cintiq 21UX/12WX/20WSX) tablets
---------------------------------------------------------------------------
-
-</a></pre></blockquote>
-
-
-<p><a name="xsetwacom"><b>Automatically excuting predefined xsetwacom commands at logging in</b>
-
-</a></p><p><a name="xsetwacom">The xsetwacom commands can be added to the .xinitrc under your home directory so next time when
-you login as yourself, the driver will be set to the options you choose.
-
-</a></p><p><a name="xsetwacom">Below is an example of my .xinitrc:
-
-</a></p><blockquote><pre><a name="xsetwacom">[jej@ayukawa jej]$ more .xinitrc
-xsetwacom set Stylus TopX 10
-xsetwacom set Stylus TopY 67
-xsetwacom set Stylus BottomX 7170
-xsetwacom set Stylus BottomY 5778
-xsetwacom set Stylus TPCButton 1
-# run the primary system script
-. /etc/X11/xinit/xinitrc
-</a></pre></blockquote>
-
-<div class="diff">
-<p><a name="xsetwacom">To see what's under your home directory, use <i>ls -al ~</i>.
-
-</a></p><p><a name="xsetwacom">If your system doesn't execute .xinitrc at login, you can add those xsetwacom commands into the
-startup script (.bashrc, .cshrc, .profile, etc.) that your system launches, for example, you should
-use .Xsession instead of .xinitrc on Debian.
-
-</a></p><p><a name="xsetwacom">It has been reported that xsetwacom can not run on some older systems due to a XFree86 interface
-error. A generic solution to this issue is directly adding your configuration options to the
-/etc/X11/XF86Config file. Please refer to </a><a href="#x11">Configuring X11</a> for details.
-</p></div>
-
-<p><b>More examples</b>
-
-</p><p>If you are confused with the usages above, let's see some more confusing examples.
-
-</p><p> <b>1.</b> Usage of keystroke and modifiers
-
-</p><p>keystroke and modifiers can be used through buttons, ExpressKeys, wheels, Touch Strips, and
-Touch Ring. A list of supported modifiers and special keys can be viewed through
-<i>xsetwacom list mod</i>. Special keys are symbols that go together to represent one XInput key event.
-
-</p><p>In the following example, <b>Up</b> represents the <b>up arrow</b> key:
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set cursor button4 "key core Up"
-</pre></blockquote>
-
-<p>When you press button4 on your Wacom puck, Xinput will receive an <b>up arrow</b> event.
-
-</p><p>If you want to send the <b>Up</b> keystroke, the universal escape character <b>\</b> has to be used:
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set cursor button4 "key core \Up"
-</pre></blockquote>
-
-<p>If you press button4 on your Wacom puck, Xinput will receive an <b>U</b> and a <b>p</b> events,
-i.e., <b>Up</b> would be displayed on your active console or application.
-
-</p><p>Sending <b>down arrow</b> event when button5 is pressed:
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set cursor button5 "key core Down"
-</pre></blockquote>
-
-<p>Sending <b>PageUp</b> event when tablet wheel scrolls up:
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set pad RelWUp "key core pgup"
-</pre></blockquote>
-
-<p>Sending <b>PageDown</b> event when tablet wheel scrolls down:
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set pad RelWDn "key core pgdn"
-</pre></blockquote>
-
-<p>The same functions work for parameters AbsWUp, AbsWDn, StripLUp,
-StripLDn, StripRUp, and StripRDn.
-
-</p><p> <b>2.</b> Changing debug level while driver is running
-
-</p><p>xsetwacom supports 2 ways of enabling/disabling debugging information, for individual device
-and/or for all tools associated with the same tablet, through parameters DebugLevel and CommonDBG. For example,
+</PRE></BLOCKQUOTE>
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set cursor DebugLevel 10
-</pre></blockquote>
-
-<p>Turns debugger on to level 10 for device "cursor" only. Other devices
-will not report information to Xorg.0.log file.
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom set cursor CommonDBG 3
-</pre></blockquote>
-
-<p>Turns debugger on to level 3 for all devices associated with the same
-tablet as "cursor" does. But only common debug information will be
-reported.
-
-</p><p> <b>3.</b> Configuring TwinView setup while system running
-
-</p><p>TwinView parameter sets the mapping of TwinView to
-horizontal/vertical/none. The current TwinView setup can be retrieved
-by the corresponding get command. For example:
-
-</p><blockquote><pre>[jej@ayukawa jej]$ xsetwacom -x get cursor TwinView
- Option "TwinView" "none"
-[jej@ayukawa jej]$
-</pre></blockquote>
-
-which means device <b>cursor</b> was not set to TwinView display.
-
-<p>Two other parameters, TVResolution0 and TVResolution1, made the change of MetaModes option
-in TwinView setup possible when system is running. TVResolution0 sets MetaModes option for
-TwinView Screen 0, while TVResolution1 sets MetaModes option for TwinView Screen 1.
-However, you need to make sure that the MetaModes you are going to set is the same as
-the TwinView setup in your xorg.conf for Nvidia Graphic card driver.
-
-</p><p> <b>4.</b> Changing Suppress and RawSample to filter the raw data
-
-</p><p>Use of Suppress will reduce the number of raw data we process in the driver. So, unless
-you know what you are doing, changing Suppress is not recommended. Valid values for Suppress
-is 0 to 100, where 0 means raw data is used as is. Suppress less than 101 means data will
-be used only when its change compared to the last processed event is larger than Suppress in
-points. Default is 2.
-
-</p><p>RawSample was originally introduced to smooth x/y coordinates to a certain degree.
-A four-points averaging was tested and convinced to be effective. In 0.7.8, we made
-RawSample changeable through xsetwacom. However, same as with Suppress, changing
-RawSample is not recommended. The maximum value can be as large as 20.
-But the default stays at 4.
-
-</p><p>Both Suppress and RawSample apply to the devices on the same tablet, that is,
-it is global to all devices associated with the same tablet.
-
-<a name="gimp">
-</a></p><h1><a name="gimp">10.0 - Working With Gimp</a></h1>
-<div class="diff"><a name="gimp">It has been suggested that gimp should be recompiled from
+<A NAME="gimp">
+<H1>6.0 - Working With Gimp</H1>
+<DIV CLASS=diff>It has been suggested that gimp should be recompiled from
source (v1.2.3) on Mandrake 9.0. This does not seem to be true for Redhat
8.0.
+</DIV>
-It is also reported that Slackware didn't configure gtk with xinput support.
-So, when you rebuild gtk, please make sure to configure the package with
-xinput=xfree option, i.e., use <i>./configure --with-xinput=xfree</i>. As of
-March 23, 2004, newer Slackware shipping with gtk2 has configured with
-xinput. </a></div>
+<P>Bring up <i>gimp</i> and select "File|Dialogs|Input Devices".
+You will see a drop-down list with all three devices present. After enabling
+them, you can see their respective statuses by calling up "File|Dialogs|Device
+Status". It has been recommended that the devices be set to "Screen" mode
+rather than "Window."
-<p><a name="gimp">Bring up <i>gimp</i> and select "File -&gt; Dialogs -&gt; Input Devices" if
-using 1.x or "File -&gt; Preferences -&gt; Input Devices -&gt; Configure Extended
-Input Devices" if using 2.x. You will see a drop-down list with all
-devices present. After enabling them, you can see their respective statuses
-by calling up "File -&gt; Dialogs -&gt; Device Status". It has been recommended
-that the devices be set to "Screen" mode rather than "Window".
-
-</a></p><p><a name="gimp">I have successfully been able to use gimp with several different pens,
+<P>I have successfully been able to use gimp with several different pens,
including the tips and erasers. Tilt does not appear to be used by gimp
-at present, but pressure works fine. If the pressure is too coarse, or
-doesn't kick in until too late, you may need to lower your threshold value.
-The pressure curve setting can be changed through graphic tool, wacomcpl,
-and command line tool, xsetwacom.
-
-</a></p><p><a name="gimp">Also, a useability note with Gimp: Each input device (stylus,cursor,eraser)
-has a completely different set of attributes in Gimp, and in theory, you can
-even assign a unique serial number to different pens to get even
-more granularity. You will experience this when
-you try to use your eraser for the first time. Rather than selecting the
-eraser tool, you get the rectangle selection tool instead. This is by design,
-believe it or not. Gimp does not care that its an eraser, just that it's not
-the pen you were just using. If you choose the eraser tool now, it will
-remember that for the next time you try to use it. On the plus side, you
-can set the eraser to be anything, including the Airbrush tool or Clone tool.
-
-</a></p><p><a name="gimp">If you change the tool's mapping area while
-Gimp was running, you need to relaunch Gimp to use the new settings.
-Otherwise, the tool tip will be off from the drawing point.
-</a></p><p><a name="gimp">One tablet user has pointed out that deleting his .gimp directory and
-rerunning gimp was necessary before his airbrush worked correctly. If you
-are having trouble, it's worth a shot.
-
-</a></p><p><a name="gimp">Good luck!
-</a><a name="multimonitor">
-</a></p><h1><a name="multimonitor">11.0 - Tablet-Screen Mapping</a></h1>
-
-<p><a name="multimonitor">This page explains how multi-monitor settings
-are supported and how to use the InputDevices options to setup your
-desired tablet-to-screen mapping. </a></p><p><a name="multimonitor">Linux Wacom X driver (wacom_drv.so)
-mainly supports three types of dual/multi-monitor setup in use with X
-server on Linux: TwinView, Xinerama, as well as non-TwinView and
-non-Xinerama case, where you normally can move the cursor from one
-screen to the other, but you can not move an application window, such
-as a terminal, from one screen to the other.
-</a></p><p><a name="multimonitor"><b>TwinView setup </b>
-
-</a></p><p><a name="multimonitor">By TwinView setup, we mean the two screens are configured in such a way that X "thinks" it only has one screen.
-
-</a></p><p><a name="multimonitor">There are three kinds of tablet-to-screen mappings in this setup:
-
-</a></p><p><a name="multimonitor">1. map the tablet to the whole desktop;
-</a></p><p><a name="multimonitor"> In this case, there is no extra
-option required in the InputDevices section for Wacom driver in your
-X11's configuration file. So this is the default state for TwinView
-setup.
-</a></p><p><a name="multimonitor">2. map the tablet to one screen at a time, but can switch screens at wish;
-</a></p><p><a name="multimonitor"> Option "TwinView" is used in the InputDevices section of the X11's configuration file to configure Wacom driver.
-
-</a></p><p><a name="multimonitor"> This feature was initially supported
-by Dreamwork developers. Their idea was to maximize the accuracy of the
-tablet on one screen and be able to move the cursor between screens
-without issuing a command (such as xsetwacom) or press a button (such
-as display toggle). The tradeoff is that you lost about 60 tablet count
-of points on the side that enables the screen switch. </a></p><p><a name="multimonitor">3. map the tablet to a specific screen.
-</a></p><p><a name="multimonitor"> Option "TwinView", "TVResolution0",
-"TVResolution1", and "ScreenNo" are used in the InputDevices section of
-the X11's configuration file to configure Wacom driver . Detailed use
-of these options can be found by "man wacom".
-</a></p><div class="diff">
-<p><a name="multimonitor">I've seen displays with Xinerama in their
-xorg.conf files in fact fall into TwinView setup since the whole
-desktop is reported as one screen. Use <i>xsetwacom get stylus NumScreen</i>
-to see how many screen you have. You need to use this command without
-adding any screen mapping related options in your xorg.conf file for
-Wacom device.
-</a></p></div>
-
-<a name="multimonitor"><b>Xinerama setup </b>
-
-</a><p><a name="multimonitor">1. map the tablet to the whole desktop;
-</a></p><p><a name="multimonitor"> No extra option required in the
-InputDevices section for Wacom driver in your X11's configuration file
-to support this setup. It is the default state.
-</a></p><p><a name="multimonitor">2. map the tablet to one screen at a time, but can switch screens with the regular mouse or a user defined button/app;
-</a></p><p><a name="multimonitor"> Option "MMonitor" "off" is used in
-the InputDevices section of the X11's configuration file to configure
-Wacom driver. The cursor will stay in the screen where you started to
-use the configured Wacom device. You can change screens by moving the
-cursor with another device/app, such as system mouse or another Wacom
-device which is not configured with "MMonitor" "off", then use the
-configured Wacom device in that screen.
-</a></p><p><a name="multimonitor">3. map the tablet to a specific screen.
-</a></p><p><a name="multimonitor"> Only option "ScreenNo" is needed to configure Wacom driver in this setting.
-
-</a></p><p><a name="multimonitor"><b>non-TwinView and non-Xinerama setup </b>
-
-</a></p><p><a name="multimonitor">In this setup, we only support tablet
-to a specific screen mapping, that is, you have to map the tablet to a
-specific screen by option "ScreenNo". Otherwise, your tablet may be
-mapped half on the first screen and the other half on the second
-screen. </a></p><p><a href="#inputdev">X11 InputDevices Options</a> details all options for your Wacom device that we mentioned above.
-
-
-<a name="contact">
-</a></p><h1><a name="contact">12.0 - Contacts</a></h1>
-<p><a name="contact">Ping Cheng can be contacted at the following email address:
-</a><a href="mailto:%20pingc@wacom.com?SUBJECT=WACOM">pingc@wacom.com</a>.
-<a name="appendix">
-</a></p><h1><a name="appendix">13.0 - Appendix</a></h1>
-<p><a name="appendix">This section is for everything that is either not critical or simply
+at present, but pressure works fine.
+<A NAME="changelog">
+<H1>7.0 - Changelog</H1>
+<UL>
+<LI>2002-12-22 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Added serial code to wacdump<BR>
+* Added serial protocols IV 1.0 - 1.4.<BR>
+* Added serial protocol V 1.0 - 1.1.<BR>
+* Intuos mouse wheels are now positive when rolled backwards per PS/2
+ Intellimouse convention<BR>
+* Added Intuos2 to xf86Wacom.c<BR>
+* Added build help for Debian Stable users<BR>
+</BLOCKQUOTE>
+
+<LI>2002-12-17 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Merged code from 2.4.20 hid-core.c<BR>
+* Added configuration code to handle kernels still at 2.4.19<BR>
+* Split wacdump curses code into wacscrn.c to solve namespace collision<BR>
+* Added volito to wacom.c<BR>
+</BLOCKQUOTE>
+
+<LI>2002-12-16 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* House cleaning on the website.<BR>
+* Dropped the Intuos constraint from the document name.<BR>
+* Added the expectations page.<BR>
+* Changed the internal indexing to identifier rather than chapter.
+</BLOCKQUOTE>
+<LI>2002-12-15 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Removed some debugging code, redeployed package with wacom_drv.o version
+ 0.3.2a.<BR>
+* New build has fix for 4D mouse wheel.<BR>
+* wcm-beta.c fleshed out with new driver code.<BR>
+</BLOCKQUOTE>
+<LI>2002-12-13 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Added development page.<BR>
+* New build has relative events and fix for 2D mouse wheel.<BR>
+* wcm-beta.c added to build.<BR>
+</BLOCKQUOTE>
+<LI>2002-12-09 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Added detail on "Threshold" parameter.<BR>
+* Included man page.
+</BLOCKQUOTE>
+<LI>2002-11-24 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Updated docs for version 0.2.0.<BR>
+* Package uses configure-based scripts.<BR>
+</BLOCKQUOTE>
+<LI>2002-11-14 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Moved wacom_drv.o to prebuilt directory.<BR>
+* Added xf86Wacom.c (version 26) to package along with changes to Makefile<BR>
+* Extended documentation on X11 setup including caveat over Mouse1 device.<BR>
+* Added xf86Wacom.c build instructions.<BR>
+* Updated wacdump (0.2) to display identifiers, maximum values, and all
+ registered event types.<BR>
+* Added highlighting in wacdump to display button down state.<BR>
+</BLOCKQUOTE>
+
+<LI>2002-11-11 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* wacom.c - fixed ranges for intuos2 6x8<BR>
+</BLOCKQUOTE>
+
+<LI>2002-11-10 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* wacdump.c - updated display to identify values<BR>
+* wacom.c - fixed ranges for intuos2 12x12<BR>
+</BLOCKQUOTE>
+
+<LI>2002-11-09 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* wacom.c - merged some of Cheng's changes, fixes to the
+pressure calculation, device ranges.<BR>
+* wacom.c - added an extra device (0x47) for M. T.<BR>
+* wacdump.c - added text messages for event types<BR>
+* wacdump.c - added usage and device override option<BR>
+* wacdump.c - exits when channel is closed.<BR>
+* Fixed module dependency problem in wacom.o and hid.o<BR>
+* Added clarification for devfs and Mandrake 9.0<BR>
+</BLOCKQUOTE>
+
+<LI>2002-11-06 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Busted page out into discrete chapters.<BR>
+* Added some php magic to turn it into an active book.<BR>
+* Added Mandrake 9.0<BR>
+* Gimp may need to be compiled from source (1.2.3)
+</BLOCKQUOTE>
+<LI>2002-11-05 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+<BLOCKQUOTE>
+* Updated wacom driver with Christer Nilsson's 2.4.20 patch<BR>
+* Added RedHat 7.3 success<BR>
+* Added more discussion on the device driver election.<BR>
+* Added more discussion on HID mode 1 and the correct mode 2.<BR>
+* Added usbmouse.c and hid-core.c to wacpack-0.1b.<BR>
+</BLOCKQUOTE>
+<LI>2002-11-04 - John E. Joganic &lt;jej@j-arkadia.com&gt;<BR>
+
+<BLOCKQUOTE>
+* Added update section.<BR>
+* Added success stories.<BR>
+* Added RedHat 7.2 specific information<BR>
+* Added more information about "unknown report #1"<BR>
+</BLOCKQUOTE>
+</UL>
+<A NAME="contact">
+<H1>8.0 - Contacts</H1>
+<P>John Joganic can be contacted at the following email address:
+<A HREF="mailto: jej@j-arkadia.com?SUBJECT=WACOM">jej@j-arkadia.com</A>.
+If at all possible, please include the word "WACOM" in the subject line.
+I receive hundreds of messages a day, and this little addition will help
+me find your message in the tons of spam.
+<A NAME="appendix">
+<H1>9.0 - Appendix</H1>
+<P>This section is for everything that is either not critical or simply
too complex to describe in the document above without becoming overly
distracting.
-</a><a name="dump">
-</a></p><h2><a name="dump">13.1 - Building wacdump and xidump</a></h2>
-
-<p><a name="dump"><b>Building wacdump</b>
+<A NAME="builddrv">
+<H2>9.1 - Building wacom_drv.o From Scratch</H2>
+<H3>Introduction</H3>
-</a></p><p><a name="dump">wacdump is enabled by default in the configure script, so let's do that now:
-
-</a></p><blockquote><pre><a name="dump">[jej@ayukawa linuxwacom]$ ./configure
-...
-----------------------------------------
- BUILD OPTIONS:
- wacom.o - no
- wacdump - <b>yes</b>
- hid.o - no
- usbmouse.o - no
- wacom_drv.o - no
-----------------------------------------
-</a></pre></blockquote>
-
-<p><a name="dump">As shown above, the build options indicate that wacdump will be built.
-If not, then scroll back through the configuration to see if there aren't
-any errors or warnings that would explain this.
-
-</a></p><p><a name="dump">Next, run <i>make</i>. The output will be a file called wacdump in the
-linuxwacom package's src/util directory. Running <i>make install</i>, will
-install it under /usr/local/bin.
-
-</a></p><p><a name="dump"><b>Building xidump</b>
-
-</a></p><p><a name="dump">xidump builds by default so if you've configured and built the project
-in previous steps, you probably have it already. If not, we can build it now.
-
-</a></p><p><a name="dump">xidump requires the XLib and XInput header files to be present on
-the system. On Redhat 8.0, these files are located in the XFree86-devel
-RPM package. Other distributions may be organized differently, and
-people who build X from source probably get them by default. When
-configuring, check that XLib is detected in the build environment,
-and if not, refer to the warnings and "checking for" messages for
-additional clues.
-
-</a></p><p><a name="dump">The preferred display mode for xidump uses ncurses. To compile it, you
-will need the ncurses header files. On Redhat 8.0, these files are located
-in the ncurses-devel package. Without ncurses, xidump defaults to raw mode
-automatically.
-
-</a></p><blockquote><pre><a name="dump">[jej@ayukawa linuxwacom]$ ./configure
-checking for XLib include directory... <b>found</b>
-checking for XLib header files... <b>found</b>
-checking for ncurses.h... <b>yes</b>
-...
-----------------------------------------
- BUILD ENVIRONMENT:
- ...
- <b>XLib - yes</b>
- <b>ncurses - yes</b>
- ...
+<P>I should tell you out-right that this is an ugly, time consuming process.
+If you manage to get this working in fewer steps, by all means, let me know.
- BUILD OPTIONS:
- ...
- <b>xidump - yes</b>
- ...
-----------------------------------------
-
-</a></pre></blockquote>
-
-<p><a name="dump">The configuration above indicates that the XLib and ncurses header files
-were found and xidump will be built. If ncurses.h is not found, xidump
-will still build, but it will also warn you that ncurses will not be
-available. If you encounter warnings, it is most likely that your
-development environment is missing some packages.
-
-</a></p><p><a name="dump">When you run <i>make</i>, the xidump program will be built along with any
-other programs that are specified in the build options. The output file is
-called 'xidump' and is located in the linuxwacom package's src/util directory.
-It is installed by running <i>make install</i>.
-</a><a name="xset">
-</a></p><h2><a name="xset">13.2 - Building xsetwacom</a></h2>
-
-<p><a name="xset"><b>Building xsetwacom</b>
-
-</a></p><p><a name="xset">xsetwacom uses libwacomcfg.so to communicate with Wacom X (XFree86 or
-Xorg) driver, wacom_drv.(s)o. So, libwacomcfg.so should be built and
-installed.
-
-</a></p><p><a name="xset">libwacomcfg.so relies on Xlib. In the
-configure script, it will default the Xlib path to /usr/X11R6 or
-/usr/lib (/usr/X11R6/lib64 or /usr/lib64 if --enable-xserver64 option
-is set) by checking the existence of xf86Version.h. If your Xlib is not
-installed under /usr/X11R6 or /usr/lib, you'll need to specify the path
-(dir) by <i>--with-xlib=dir</i>. Let's see
-what we get from configure:
-
-</a></p><blockquote><pre><a name="xset">[jej@ayukawa linuxwacom]$./configure
-...
-----------------------------------------
- BUILD ENVIRONMENT:
- architecture - i686
- linux kernel - yes 2.4
- module versioning - yes -DONFIG_MODVERSIONS -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h
- kernel source - yes /usr/src/linux
- XFree86 - no
- XSERVER64 - no
- dlloader - no
- XLib - yes /usr/X11R6
- TCL - yes /usr
- TK - yes /usr
- ncurses - yes
-
- BUILD OPTIONS:
- wacom.o - no
- wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
- hid.o - no
- usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
- wacom_drv.so - no
- wacom_drv.o - no
-----------------------------------------
-</a></pre></blockquote>
-
-<p><a name="xset">As shown above, the build options indicate that libwacomcfg and xsetwacom
-will be built. If not, then scroll back through the configuration to see
-if there aren't any errors or warnings that would explain this.
-
-</a></p><p><a name="xset">Next, run <i>make</i>. The output will be stored in the linuxwacom
-package's src/util and src/util/.libs directory. They will be installed by running
-<i>make install</i> (you need to switch to superuser to run this command).
-
-</a></p><p><a name="xset">If wacom_drv.(s)o was running while installing xsetwacom, xsetwacom can be
-launched immediately after <i>make install</i> and <i>exit</i>.
-
-</a></p><p><a name="xset">If wacom_drv.o is installed by the same <i>make install</i> as xsetwacom
-is, restarting X server is required to use the newly built wacom_drv.(s)o. We
-strongly recommand to build and install wacom_drv.(s)o and xsetwacom from
-the same release package since the out of sync wacom_drv.(s)o and xsetwacom
-may crash your X server.
-</a><a name="cpl">
-</a></p><h2><a name="cpl">13.3 - Building wacomcpl</a></h2>
-
-<p><a name="cpl">wacomcpl is written in tcl/tk. It uses libwacomxi.so and xsetwacom to
-communicate with Wacom XFree86/Xorg driver, wacom_drv.(s)o. So, to run
-wacomcpl, tcl/tk should be installed, libwacomxi.so and xsetwacom should
-be built and installed.
-
-</a></p><p><a name="cpl">libwacomxi.so and xsetwacom are enabled by
-default in the configure script. By default, the script will assume
-that tcl/tk is installed under /usr. That is, tcl.h and tk.h should be
-under /usr/include; libtcl.so.0 and libtk.so.0 should be under
-/usr/lib. Let's see what we get from configure:
-</a></p><blockquote><pre><a name="cpl">[jej@ayukawa linuxwacom]$./configure
-...
-----------------------------------------
- BUILD ENVIRONMENT:
- architecture - i686
- linux kernel - yes 2.4
- module versioning - yes
- kernel source - yes /usr/src/linux
- XFree86 - no
- XLib - yes /usr/X11R6
- TCL - yes /usr
- TK - yes /usr
- ncurses - yes
-
- BUILD OPTIONS:
- wacom.o - no
- wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
- hid.o - no
- usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
- wacom_drv.o - no
-----------------------------------------
-</a></pre></blockquote>
-
-<p><a name="cpl">As shown above, the build options indicate that libwacomxi and xsetwacom
-will be built. If not, then scroll back through the configuration to see
-if there aren't any errors or warnings that would explain this.
-
-</a></p><p><a name="cpl">For example, on another system, I have installed tcl/tk under /usr/local/ActiveTcl.
-That is, tcl.h and tk.h are under /usr/local/ActiveTcl/include. If I run configure
-without options, I get:
-
-</a></p><blockquote><pre><a name="cpl">[jej@ayukawa linuxwacom]$./configure
-...
-----------------------------------------
- BUILD ENVIRONMENT:
- architecture - i686
- linux kernel - yes 2.4
- module versioning - yes
- kernel source - yes /usr/src/linux
- XFree86 - no
- XLib - yes /usr/X11R6
- TCL - no
- TK - no
- ncurses - yes
- GTK - 2.0.6
-
- BUILD OPTIONS:
- wacom.o - no
- wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - no
- xsetwacom - yes
- hid.o - no
- usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
- wacom_drv.o - no
-----------------------------------------
-</a></pre></blockquote>
-
-<p><a name="cpl">The build options show that libwacomxi will not be built. When I scroll
-back through the configuration, I see:
-
-</a></p><blockquote><pre><a name="cpl">...
-checking for tcl header files... not found; tried /usr/include/tcl.h
-***
-*** WARNING:
-*** The tcl development environment does not appear to
-*** be installed. The header file tcl.h does not appear
-*** in the include path. Do you have the tcl rpm or
-*** equivalent package properly installed? Some build
-*** features will be unavailable.
-***
-checking for tk header files... not found; tried /usr/include/tk.h and /include/tk.h
-***
-*** WARNING:
-*** The tk development environment does not appear to
-*** be installed. The header file tk.h does not appear
-*** in the include path. Do you have the tk rpm or
-*** equivalent package properly installed? Some build
-*** features will be unavailable.
-***
-checking ncurses.h usability... yes
-checking ncurses.h presence... yes
-checking for ncurses.h... yes
-***
-*** WARNING:
-*** libwacomxi requires tcl environment; libwacomxi will not be built.
-***
-...
-</a></pre></blockquote>
-
-<p><a name="cpl">Then I run configure with option --with-tcl=/usr/local/ActiveTcl:
-
-</a></p><blockquote><pre><a name="cpl">[jej@ayukawa linuxwacom]$./configure --with-tcl=/usr/local/ActiveTcl
-...
-----------------------------------------
- BUILD ENVIRONMENT:
- architecture - i686
- linux kernel - yes 2.4
- module versioning - yes
- kernel source - yes /usr/src/linux
- XFree86 - no
- XLib - yes /usr/X11R6
- TCL - yes /usr/local/ActiveTcl
- TK - yes /usr/local/ActiveTcl
- ncurses - yes
-
- BUILD OPTIONS:
- wacom.o - no
- wacdump - yes
- xidump - yes
- libwacomcfg - yes
- libwacomxi - yes
- xsetwacom - yes
- hid.o - no
- usbmouse.o - no
- evdev.o - no
- mousedev.o - no
- input.o - no
- tabletdev.o - no
- wacom_drv.o - no
-----------------------------------------
-</a></pre></blockquote>
-
-<p><a name="cpl"><b>Note:</b> You may need to issue the following commands before running wacomcpl:
-
-</a></p><blockquote><pre><a name="cpl">[jej@ayukawa linuxwacom]$export LD_LIBRARY_PATH=/usr/local/ActiveTcl/lib:$LD_LIBRARY_PATH
-[jej@ayukawa linuxwacom]$su
-[jej@ayukawa linuxwacom]#cd /usr/local/ActiveTcl/lib
-[jej@ayukawa lib]#ln -s libtcl.8.4.so libtcl.so.0
-[jej@ayukawa lib]#ln -s libtk.8.4.so libtk.so.0
-</a></pre></blockquote>
-
-<p><a name="cpl">If your tcl and tk are installed on different paths, you'll need to
-specify them separately. Suppose that your tcl is under /usr/local/tcl8.4
-and your tk is under /usr/local/tk8.4, the proper configuration and setup
-commands will be:
-
-</a></p><blockquote><pre><a name="cpl">[jej@ayukawa linuxwacom]$./configure --with-tcl=/usr/local/tcl8.4 --with-tk=/usr/local/tk8.4
-[jej@ayukawa linuxwacom]$export LD_LIBRARY_PATH=/usr/local/tcl8.4/lib:/usr/local/tk8.4/lib:$LD_LIBRARY_PATH
-[jej@ayukawa linuxwacom]$su
-[jej@ayukawa linuxwacom]#cd /usr/local/tcl8.4/lib
-[jej@ayukawa lib]#ln -s libtcl.8.4.so libtcl.so.0
-[jej@ayukawa lib]#cd /usr/local/tk8.4/lib
-[jej@ayukawa lib]#ln -s libtk.8.4.so libtk.so.0
-</a></pre></blockquote>
-
-<p><a name="cpl">Next, run <i>make</i>. The output will be stored in the linuxwacom
-package's src/wacomxi and src/wacomxi/.libs directories. They will be
-installed by running <i>make install (you need to switch to superuser
-to run this command)</i>.
-</a><a name="builddrv">
-</a></p><h2><a name="builddrv">13.4 - Building wacom_drv.o from Scratch</a></h2>
-<h3><a name="builddrv">Introduction</a></h3>
-
-<p><a name="builddrv">I should tell you out-right that this is a time consuming process.
-
-</a></p><p><a name="builddrv">Why would you want to do this? Two reasons. One, you are a developer
+<P>Why would you want to do this? Two reasons. One, you are a developer
and need to make changes to the source code directly. Two, your distribution
uses c libraries or configuration options that are not compatible with the
wacom_drv.o file that I provide. People running libc5 for instance, would
need to build their own driver.
-</a></p><blockquote><div class="diff">
-<a name="builddrv">Timothy Klein has submitted a brief howto for compiling on Debian Stable
+<BLOCKQUOTE><DIV CLASS=diff>
+Timothy Klein has submitted a brief howto for compiling on Debian Stable
which is still running XFree86 4.1 as of this writing. It covers steps
one through four of this document, and a savvy developer should be able
to figure out step five on his own. If someone solves step five and
generates a patch to Makefile.am, I'll see what I can do about getting
-it into the configuration script. That document is on the </a><a href="#debwcmdrv">Installing wacom driver On Debian</a> page.
-</div></blockquote>
+it into the configuration script. That document is on the <A HREF="#debwcmdrv">Building wacom_drv.o On Debian Stable</A> page.
+</DIV></BLOCKQUOTE>
-<p>You will need the X source code to rebuild the wacom_drv.o driver.
+<P>You will need the X source code to rebuild the wacom_drv.o driver.
The build configuration for X generates a number of header files that are
necessary but not installed by default on most distributions. Consequently,
you will need to not only get the source, but build it, practically in its
entirety. Then, after all that, the configure script can be instructed to
-hook into the X build tree and rebuild wacom_drv.o at any time without
+hook into the X build tree and rebuild xf86Wacom.c at any time without
having to rebuild X again.
-</p><p>Since I am running Redhat 8.0 and cannot really pull down the original
+<P>Since I am running Redhat 8.0 and cannot really pull down the original
XFree86 4.2.0 source code, compile it, and expect it to work on my
system, I need to instead use the source RPM provided by Redhat. If you
choose to go this route, I provide pretty detailed instructions for making
@@ -3460,19 +1882,20 @@ this work. If your distribution works differently, or you are using Gentoo
where most everything is source code by default, you'll need to handle this
as best as possible according to your particular situation.
-</p><p></p><h3>Step One: Get The Source</h3>
+<P><H3>Step One: Get The Source</H3>
-<p>On Redhat 8.0, I discovered the version number for my currently installed
-XFree86 packages by running <i>rpm -q XFree86</i>. This reported version
+<P>On Redhat 8.0, I discovered the version number for my currently installed
+XFree86 packages by running <I>rpm -q XFree86</I>. This reported version
4.2.0-72, therefore the source package is XFree86-4.2.0-72.src.rpm.
I downloaded the package from Redhat directly and installed it to the system
as follows:
-</p><blockquote><pre>[root@sen src]# rpm -ivh XFree86-4.2.0-72.src.rpm
+<BLOCKQUOTE><PRE>
+[root@sen src]# rpm -ivh XFree86-4.2.0-72.src.rpm
1:XFree86 ########################################### [100%]
-</pre></blockquote>
+</PRE></BLOCKQUOTE>
-<p>This installs a number of files to the /usr/src/redhat directory,
+<P>This installs a number of files to the /usr/src/redhat directory,
particularly in the SOURCES and SPECS subdirectories. Other distributions
undoubtedly install elsewhere. Look for the XFree86.spec file which should
be located in the SPECS directory. This file contains all the information
@@ -3480,15 +1903,15 @@ necessary to patch the orginal XFree86-4.2.0 source code to the level that
Redhat is distributing in their regular binary package. The source code
and patch files are located in SOURCES.
-</p><h3>Step Two: Build the Source</h3>
+<H3>Step Two: Build the Source</H3>
-<p>This step describes how to build the source from the RPM itself. If
+<P>This step describes how to build the source from the RPM itself. If
you are building from some other mechanism, I honestly cannot offer much
assistance since I generally don't build my X system from scratch.
If you'd like to write up a short section on building the
server for your particular distribution, I would be happy to include it here.
-</p><p>Next, you don't actually have to build the entire thing. The
+<P>Next, you don't actually have to build the entire thing. The
point at which the xf86Wacom.c driver can be built however,
is not until somewhere in the middle of the build process. The driver
depends on a number of header files that are created dynamically so until
@@ -3498,16 +1921,17 @@ periodically attempt to build it. When it successfully built, I stopped
the X build process. Here's how to build the source for an RPM that's
been exploded out into the SPECS and SOURCES directories.
-</p><blockquote><pre>[root@sen root]# cd /usr/src/redhat
+<BLOCKQUOTE><PRE>
+[root@sen root]# cd /usr/src/redhat
[root@sen redhat]# rpmbuild -bc SPECS/XFree86.spec
-</pre></blockquote>
+</PRE></BLOCKQUOTE>
-<p>Not every distribution has <i>rpmbuild</i>; try using just <i>rpm</i>
+<P>Not every distribution has <I>rpmbuild</I>; try using just <i>rpm</i>
instead. At some point, Redhat split the build functionality into separate
programs. If after looking through the <i>rpm</i> man page, you still
cannot get this to work, send me some email, and I'll look into it.
-</p><p>The important item is the "-bc" option of <i>rpmbuild</i> which unpacks,
+<P>The important item is the "-bc" option of <I>rpmbuild</I> which unpacks,
patches, and builds the source without actually installing. While it is also
possible to simply unpack and patch using the "-bp" option, there does not
seem to be a way to just build. The "-bc" option simply deletes all the
@@ -3517,17 +1941,18 @@ file over the old one, you'll find that the build step deletes it and starts
over again. I have gotten this to work by creating a new patch file, but
this requires a bit more effort, so I don't recommend it right off.
-</p><h3>Step Three: Build the Original Driver</h3>
+<H3>Step Three: Build the Original Driver</H3>
-<p>The xf86Wacom.c file is buried pretty deep in the X build tree. If it
+<P>The xf86Wacom.c file is buried pretty deep in the X build tree. If it
is in a different location than the one I have provided below, try using
-<i>find . -name xf86Wacom.c</i> from the BUILD directory.
+<I>find . -name xf86Wacom.c</I> from the BUILD directory.
-</p><blockquote><pre>[root@sen redhat]# cd BUILD/XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/input/wacom
+<BLOCKQUOTE><PRE>
+[root@sen redhat]# cd BUILD/XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/input/wacom
[root@sen wacom]# ls
Imakefile wacom.man xf86Wacom.c.Wacom-USB-driver-a25-update
Makefile xf86Wacom.c
-</pre></blockquote>
+</PRE></BLOCKQUOTE>
The "a25-update" file is the original xf86Wacom.c file before Redhat's patch.
If you open xf86Wacom.c, you'll find that it is version 25, at least as
@@ -3538,31 +1963,74 @@ files that you need have been generated, and you can build xf86Wacom.c. Try
it, and if it does not build, wait a bit. The absence of xf86Version.h
for instance, is a good indication that the build process is not ready.
-<blockquote><pre>[root@sen wacom]# make
+<BLOCKQUOTE><PRE>
+[root@sen wacom]# make
rm -f xf86Wacom.o
gcc -O2 -march=i386 ... -c xf86Wacom.c
+rm -f wacom_drv.o
ld -r xf86Wacom.o -o wacom_drv.o
-</pre></blockquote>
-
-<h3> Step Four: Automating the Build Process</h3>
-
-<p>By configuring the package with the --with-xf86 option set to the XFree86
-build tree, you can build the driver outside of the X build tree.
-</p><blockquote><pre>[jej@ayukawa wacom]$ ./configure \
- --with-xf86=/usr/src/redhat/BUILD/XFree86-4.2.0
+</PRE></BLOCKQUOTE>
+
+<H3>Step Four: Build the New Driver</H3>
+
+<P>With a valid build environment, it should be possible to copy the
+updated driver source over the old one, run <i>make</i>, and get an updated
+driver.
+
+<BLOCKQUOTE><DIV class=diff>The beta package contains a version xf86Wacom.c that depends
+on wcm-beta.c and wcm-beta.h. If you are compiling this version, you will
+need to copy all three files. Secondly, the driver will build and link, but
+will not be usable since the current X build environment does not expect the
+wcm-beta code to be compiled. This problem is addressed correctly in the
+automated build process discussed below.
+</DIV></BLOCKQUOTE>
+
+<BLOCKQUOTE><PRE>
+[root@sen wacom]# cp xf86Wacom.c xf86Wacom_old.c
+[root@sen wacom]# cp /home/jej/src/wacom/src/xf86Wacom.c xf86Wacom.c
+[root@sen wacom]# make
+rm -f xf86Wacom.o
+gcc -O2 -march=i386 ... -c xf86Wacom.c
+rm -f wacom_drv.o
+ld -r xf86Wacom.o -o wacom_drv.o
+</PRE></BLOCKQUOTE>
+
+If the source did not build correctly the second time, it is possible
+that the Imake-based build environment has generated a makefile that
+will not work correctly for the new code. Your options are to generate
+a patch file that can be applied by the build process, hack the makefile
+in the driver directory to work properly, or to find some
+way to get Imake to reconfigure. This is probably less of a hassle for people
+building from source, but to be fair, all the commands and information you
+need to reconfigure from RPM are listed in the beginning of the build output.
+You might also want to continue ahead to see if the default build rule does
+not work for you.
+
+<H3> Step Five: Automating the Build Process</H3>
+
+<P>Copying the updated source file into the build tree and compiling from
+there is not convenient. By configuring the package with the --with-xf86
+option set to the XFree86 build tree and enabling the driver using the
+--enable-wacomdrv option, you can build the driver outside of the X build
+tree.
+<BLOCKQUOTE><PRE>
+[jej@ayukawa wacom]$ ./configure \
+ --with-xf86=/usr/src/redhat/BUILD/XFree86-4.2.0 \
+ --enable-wacomdrv
...
BUILD ENVIRONMENT:
XFree86 - yes
BUILD OPTIONS:
wacom_drv.o - yes
[jej@ayukawa wacom]$ make
-</pre></blockquote>
+</PRE></BLOCKQUOTE>
-<p>The makefile rule which builds the driver is contained within src/Makefile.am
+<P>The makefile rule which builds the driver is contained within src/Makefile.am
and is modified according to the configuration to generate a rule similar to
this in src/Makefile:
-</p><blockquote><pre>xf86Wacom.o: xf86Wacom.c
+<BLOCKQUOTE><PRE>
+xf86Wacom.o: xf86Wacom.c
gcc -O2 -march=i386 -mcpu=$(ARCHITECTURE) -pipe -ansi \
-pedantic -Wall -Wpointer-arith -fno-merge-constants \
-I. -I$(XF86_DIR)/programs/Xserver/hw/xfree86/common \
@@ -3585,13 +2053,12 @@ this in src/Makefile:
-DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG -DFUNCPROTO=15 \
-DNARROWPROTO -DIN_MODULE -DXFree86Module -DLINUX_INPUT \
-o xf86Wacom.o -c xf86Wacom.c
-</pre></blockquote>
+</PRE></BLOCKQUOTE>
-<blockquote><div class="diff">similar rules applie to wcmSerial.c, wcmUSB.c,
-wcmISDV4.c, wcmCommon.c, wcmCompat.c, wcmConfig.c, and, wcmFilter.c.
-</div></blockquote>
+<BLOCKQUOTE><DIV class=diff>In the beta package, a similar rule applies to wcm-beta.c.
+</DIV></BLOCKQUOTE>
-<p>The options and directories specified come directly from the output of the
+<P>The options and directories specified come directly from the output of the
make command in the previous step. All the root and parent directories have
been replaced with the macro XF86_DIR which in this case is set by the
configuration script to /usr/src/redhat/BUILD/XFree86-4.2.0/xc. If the
@@ -3601,1129 +2068,150 @@ alterations. You can update the Makefile.am file and rerun automake,
update the Makefile.in and rerun configure, or just update the Makefile
directly.
-</p><p>So long as the X build tree exists, the include directories will point to
+<P>So long as the X build tree exists, the include directories will point to
the correct locations, and the driver will build. If space is an issue, you
can probably remove all the non-essential directories, but be careful; the
dependency tree in X is huge.
-<a name="debwcmdrv">
-</a></p><h2><a name="debwcmdrv">13.5 - Installing wacom driver On Debian</a></h2>
-<a name="debwcmdrv">The following documentation for building wacom driver on Debian was
-written by Olivier Lecarme. You can also refer to Olivier's page
-</a><a href="http://www.i3s.unice.fr/%7Eol/success.html">here</a> for updates.
-
-<br><br><br><br>
-
-Copyright (C) June 14, 2005 Olivier Lecarme. <br><br>
-
-<pre>I'm using the Sid version of Debian, but I was told that the Sarge
-distribution, recently become the stable one, already contains what
-is necessary. Version 2.6.11 of the kernel is the highly preferred
-one by people maintaining the Linux Wacom software.
-
-<b>Download the 2.6.11 kernel</b>
-
-I was completely unsuccessful when trying to configure and compile
-my own kernel: certainly I omitted some capital module, but I could
-not decide what it was. Thus, I chose the last pre-compiled kernel.
-
- 1. apt-get kernel-image-2.6.11-1-686
-
- 2. apt-get kernel-headers-2.6.11-1-686
-
-If you use Lilo, configure your /etc/lilo.conf file, taking into
-account that this kernel needs an initrd= line.
-
-<b>Optionally</b>
+<H3>Conclusion</H3>
-If your case is irrelevant, please skip this section and the following one.
+<P>Although a bit of a hassle, it is possible to compile the xf86Wacom.c
+file into the wacom_drv.o driver from outside the X build tree. If you
+have any comments, questions, or suggestions regarding this process,
+please send email to <A HREF="mailto:jej@j-arkadia.com?SUBJECT=WACOM_DRV">jej@j-arkadia.com</A> with a subject of "WACOM_DRV".
+<A NAME="debwcmdrv">
+<H2>9.2 - Building wacom_drv.o On Debian Stable</H2>
+The following documentation for building wacom_drv.o on Debian Stable
+was written by Timothy Klein. If you have any problems or questions,
+go ahead and post them to the list, or send email to me directly. If
+I cannot provide a satisfactory answer, I'll forward your email on to
+Timothy.
- 1. I Have a Broadcom NetXtreme BCM5751 Ethernet card, which needs
-the tigon3 driver, unavailable in Debian kernel 2.6.11. The solution is here.
+<BR><BR><BR><BR>
- Thus I got the package:
+<PRE>
+Just thought I would give you some brief notes on compiling wacom_drv.o
+on Debian Stable. This must be done, as the Stable version of Debian
+has XFree86 v. 4.1.0.1, and your pre-compiled module is for a later
+version of X (4.2?). X complains about the server having ABI 2, and the
+module having ABI 3, and refuses to load. So one must compile the
+wacom_drv.o module for Debian Stable.
- 1. cd /usr/src
- 2. wget http://www.acm.rpi.edu/~dilinger/kernel-source-nonfree-2.6.11
-/kernel-nonfree-modules-2.6.11-1-686-2.6.11-1_i386.deb
+The good news is that, while it requires a *huge* download, and takes a
+bit of time, it is easy.
- 2. I have an ATI X 300 video card, whose driver is not available
-in Debian kernel 2.6.11. The solution is here.
+-------------------------------------------------------------
+Debian wacom_drv.o Compilation
- Thus I got the packages:
+<B>1. Download the Debian source package for XFree86.</B>
- 1. for the driver: wget http://www.stanchina.net/~flavio/
-debian-fglrx-xfree86/fglrx-driver_8.12.10-1_i386.deb
- 2. and for the kernel module: wget http://www.stanchina.net/~flavio
-/debian-fglrx-modules/fglrx-kernel-2.6.11-1-686-smp_8.12.10-1+2.6.11-2_i386.deb
+For Debian Stable this is three files:
-<b>Install the optional packages</b>
+xfree86_4.1.0-16.diff.gz
+xfree86_4.1.0-16.dsc
+xfree86_4.1.0.orig.tar.gz
- 1. cd /usr/src
+Note that these are *big* files. The 'diff' file is 1.5 megabytes, and
+the 'orig' file is 52 megabytes. So if you have a 28.8 modem
+connection, this is going to be painful.
- 2. dpkg -i kernel-nonfree-modules-2.6.11-1-686_2.6.11-1_i386.deb
+These files can be obtained automatically by using the command:
- 3. dpkg -i fglrx-driver_8.12.10-1_i386.deb
+apt-get source xfree86
- 4. dpkg -i fglrx-kernel-2.6.11-1-686_8.12.10-1+2.6.11-2_i386.deb
+It is not necessary to be root to download the source package. After it
+is downloaded, the package will be automatically extracted. Using this
+method requires that you have a valid 'source' line in your
+'/etc/apt/sources.list' file, though.
-<b>Install the wacom tools package</b>
+You can also just download the three packages above from your favorite
+Debian mirror. If you do that, you need to extract them yourself, which
+is done with the following command:
- 1. apt-get install wacom-tools
+dpkg-source -x xfree86_4.1.0-16.dsc &lt;only for manual download&gt;
- 2. dpkg-reconfigure wacom-kernel-source
+Either method will give you a 'xfree86-4.1.0' directory in the download
+directory. For both this step, and the later package creation, you are
+going to need tools from the 'dpkg-dev' package. So install that with
+'apt-get' if you don't already have it installed.
- Since your debconf configuration probably did not ask for the lowest
-priority questions, this step is needed. You might also use it later if you
-update your kernel, for instance.
- When asked whether you want to build the modules, answer yes, and tell
-where the headers are located (normally /usr/src/kernel-headers-2.6.11-1-686).
-<b>Prepare for the /dev/input/wacom link</b>
+<B>2. Make sure you have the requisite build dependencies.</B>
-In /etc/udev/rules.d/10-wacom.rules, add the following line:
+XFree86 requires certain packages to compile. It seems that 'dpkg' is
+pretty good about telling you what packages it needs if they are not
+installed (probably a nice script included by the Debian X maintainer).
+Thus, you can just try and compile it and see what it complains about
+not having and, at that point, install the needed packages with apt-get.
+The other, cleaner, option is to run:
-KERNEL="event*", SYSFS{idVendor}="056a", NAME="input/%k", SYMLINK="input/wacom%e"
+apt-get build-dep xfree86
-Thus the drivers will find the Wacom tablet, whatever its /dev/input/eventX address is.
+This command will attempt to automatically install (or once in a blue
+moon uninstall) all the necessary packages to compile XFree86. You need
+to be 'root' to do this.
-<b>Change your XF86Config-4 file</b>
-The important sections are:
+<B>3. Begin the Build Process for xfree86</B>
- 1. The ServerLayout section:
-Section "ServerLayout"
- [ ... ]
- InputDevice "stylus" "SendCoreEvents"
- InputDevice "eraser" "SendCoreEvents"
- InputDevice "cursor" "SendCoreEvents"
- InputDevice "pad"
-EndSection
+Become 'root' (or you could use fakeroot), and change into the
+'xfree86-4.1.0' directory. Then run:
- 2. The InputDevice sections:
+dpkg-buildpackage
-Section "InputDevice"
- Identifier "stylus"
- Driver "wacom"
- Option "Type" "stylus"
- Option "USB" "on"
- Option "Threshold" "10"
- Option "Device" "/dev/input/wacom"
-EndSection
-
-Section "InputDevice"
- Identifier "eraser"
- Driver "wacom"
- Option "Type" "eraser"
- Option "USB" "on"
- Option "Threshold" "10"
- Option "Device" "/dev/input/wacom"
-EndSection
-
-Section "InputDevice"
- Identifier "cursor"
- Driver "wacom"
- Option "Type" "cursor"
- Option "USB" "on"
- Option "Threshold" "10"
- Option "Device" "/dev/input/wacom"
-EndSection
-
-Section "InputDevice"
- Identifier "pad"
- Driver "wacom"
- Option "Device" "/dev/input/wacom"
- Option "Type" "pad"
- Option "USB" "on"
-EndSection
-
- 3. The section dealing with your normal mouse must be considered too. See <a href="#mouse1">Mouse1 (for some 2.6 systems)</a>.
-I didn't use /dev/psaux nor /dev/input/mice. /dev/input/mouse0 works for a PS/2
-mouse. For a USB mouse, there is a problem mentioned in the <b>Remaining problems</b>.
-
- 4. If you use the ATI X300 card, you need to change also the Device section:
-
-Section "Device"
- Identifier "ATI"
- Driver "fglrx"
- Option "VideoOverlay" "on"
- Option "OpenGLOverlay" "off"
- Option "UseInternalAGPGART" "no"
-EndSection
-
-<b>Final steps</b>
-
- 1. Reboot. This will also restart the X server, of course.
- 2. Enjoy!
-
-<b>If you want to use the expresskeys of your Intuos tablet</b>
-
-If you do nothing more, the pad is not usable at all. However, you will find <a href="http://web.telia.com/%7Eu46133770/wacom/index.html">here</a> a specific
-tool for having the pad available in various programs, for example XTerm, Gimp, or Blender.
-
-This tool is very easy to compile, install, and use. If you want to use the pad
-in Gimp, do <b>not</b> enable it in "Preferences -&gt; Input Devices -&gt; Configure
-the extended input devices", contrarily to the three other tools (stylus, eraser,
-and cursor). You can easily configure what the expresskeys send, according to
-your tastes, and use only them for the tasks that need a good control of the
-stylus or eraser.
-
-<b>Remaining problems</b>
-
-If your tablet is always plugged, everything works perfectly. If you want to plug
-it out, for example in order to move it onto another computer, and then to plug
-it back later, problems begin.
-
-For the present, you must take care of the following things:
-
- 1. If you plug in the tablet again, the corresponding driver is not informed
-of this, thus you must restart the X server.
-
- 2. If the tablet is plugged when you reboot, and you have an USB mouse, maybe
-the /dev/input address of this mouse is not the same as the previous time. Thus
-you will have to change this in your XF86Config-4 file.
-
- 3. If you use GDM or KDM or XDM, you should plug in the tablet after rebooting,
-but before the X server starts, which is somewhat difficult! Thus you will be forced
-to restart the X server, i.e. kill it (Ctrl+Alt+Backspace) and not simply logging out.
-
-<b>Final remarks</b>
-
- I would like to thank all persons who helped me, on the LinuxWacom or the
-Gimp-user discussion lists, especially Carol Spears, Karine Delvare, Ping Cheng, and Ron.
-
-</pre>
-<a name="ppcwcmdrv">
-</a><h2><a name="ppcwcmdrv">13.6 - Building wacom driver On PowerMac</a></h2>
-<a name="ppcwcmdrv">The following documentation for building wacom driver on PowerMac [silver]
-was written by Joseph E. Sacco. If you have any problems or questions,
-go ahead and post them to the list, or send email to me directly. I'll
-forward your email on to Joseph.
-
-<br><br><br><br>
-
-Copyright (C) 2004 Joseph E. Sacco<br><br>
-
-</a><pre><a name="ppcwcmdrv">System:
-
-&lt;&lt; Hardware &gt;&gt;
-* PowerMac [silver] with dual 533 MHz G4 [7410] CPU's, 1GB RAM,
- (3) 73 GB SCSI drives
-* Contour UniMouse [USB, optical, three button]
-* Wacom Intuos Tablet [USB]: GD-1218-U
- * 4-d mouse
- * pen
- * air brush
-
-&lt;&lt; Software &gt;&gt;
-* Yellow Dog Linux 3.0.1 [Redhat variant for PPC]
-* kernel: 2.4.25-ben1
-* linuxwacom-0.6.1
-
-* XFree86-4.3.0-2.1e
-* atk-1.6.0-1
-* freetype-2.1.3-4
-* gcc-3.3
-* gtk+-2.4.0
-* glib2-2.4.0
-* ncurses-5.2-28
-* pango-1.4.0
-
-============================================================
-
-I have a Wacom Intuos tablet "working" [after a fashion] on a PPC
-running Yellow Dog Linux 3.0.1.
-
-&lt;&lt; What works &gt;&gt;
-* input devices:
- * cursor movement
- * button clicks
- * wheel rotation [as seen from wacdump]
- * pressure [as seen from wacdump &amp; gimp]
- * tilt [as seen from wacdump]
-
-* applications:
- * wacdump
- * xidump
- * xev
- * xinput-1.2
- * gimp-1.25 &amp; gimp-2.0
- * dia-0.9.2
-
-&lt; What does *not* work &gt;&gt;
-* input devices:
- * Mode "Relative" for pen &amp; air brush [should it???]
-
-* applications:
- * xsetwacom
- * wacomcpl [because of xsetwacom]
-
-There are some issues I would like to report.
-----------------------------------------------------------------------------------------------------------------------------------------
-
-* Makefiles
-The makefiles are set up for Intel architecture. Some options are not
-applicable for PPC's.
-
-[ from ./src/2.4.22/Makefile.in ]
-KCFLAGS = -Wall $(DEBUG_FLAGS) -D__KERNEL__ \
- -DMODULE -DEXPORT_SYMTAB $(MODS) \
- -Wstrict-prototypes -Wno-trigraphs -O2 \
- -fno-strict-aliasing \
- -fno-common -fomit-frame-pointer -pipe \
- ===&gt; -mpreferred-stack-boundary=2 \
- ===&gt; -march=$(ARCHITECTURE)
-
-The last two options are not applicable to a PPC.
-
-A more appropriate set of flags, taken from building the 2.4.25 kernel
-modules, might be:
-
-KCFLAGS = -Wall $(DEBUG_FLAGS) -D__KERNEL__ \
- -Wstrict-prototypes -Wno-trigraphs -O2 \
- -fno-strict-aliasing -fno-common -fomit-frame-pointer \
- -fsigned-char -msoft-float -pipe -ffixed-r2 \
- -Wno-uninitialized -mmultiple -mstring \
- -DMODULE -DMODVERSIONS -iwithprefix
-
-[ from ./src/Makefile.in ]
-$(XF86OBJS): xf86Wacom.c Makefile
- ==&gt; gcc -O2 $(DEPFLAGS) -march=i386 -mcpu=$(ARCHITECTURE) -pipe -ansi \
- -pedantic -Wall -Wpointer-arith $(NO_MERGE_CONSTANTS) \
- -I. -I$(XF86_DIR)/programs/Xserver/hw/xfree86/common \
- -I$(XF86_DIR)/programs/Xserver/hw/xfree86/loader \
- -I$(XF86_DIR)/programs/Xserver/hw/xfree86/os-support \
- -I$(XF86_DIR)/programs/Xserver/include \
- -I$(XF86_DIR)/programs/Xserver/mi \
- -I$(XF86_DIR)/exports/include/X11 \
- -I$(XF86_DIR)/include/extensions \
- -I$(XF86_DIR) \
- -I$(XF86_DIR)/exports/include \
-==&gt; -Dlinux -D__i386__ -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 -DXF86BIGFONT -DDPMSExtension -DPIXPRIV -DPANORAMIX \
- -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV \
- -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER \
- -DXFree86Server -DXF86VIDMODE -DXvMCExtension \
- -DSMART_SCHEDULE -DBUILDDEBUG -DXResExtension \
- -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG -DFUNCPROTO=15 \
- -DNARROWPROTO -DIN_MODULE -DXFree86Module $(LINUX_INPUT) \
- -o $@ -c $(subst .o,.c,$@)
+The source will begin to compile. It will take a while. If you have a
+really old machine, like a Pentium 166 or such, go on a vacation. It
+may be done when you return.
-A more appropriate set of flags, taken from building XFree86-4.3.0, might be:
-$(XF86OBJS): xf86Wacom.c Makefile
- gcc -O2 $(DEPFLAGS) -mcpu=$(ARCHITECTURE) -pipe -ansi \
- -pedantic -Wall -Wpointer-arith $(NO_MERGE_CONSTANTS) \
- -I. -I$(XF86_DIR)/programs/Xserver/hw/xfree86/common \
- -I$(XF86_DIR)/programs/Xserver/hw/xfree86/loader \
- -I$(XF86_DIR)/programs/Xserver/hw/xfree86/os-support \
- -I$(XF86_DIR)/programs/Xserver/include \
- -I$(XF86_DIR)/programs/Xserver/mi \
- -I$(XF86_DIR)/exports/include/X11 \
- -I$(XF86_DIR)/include/extensions \
- -I$(XF86_DIR) \
- -I$(XF86_DIR)/exports/include \
- -Dlinux -D__powerpc__ -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 -DXF86BIGFONT -DDPMSExtension -DPIXPRIV -DPANORAMIX \
- -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV \
- -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER \
- -DXFree86Server -DXF86VIDMODE -DXvMCExtension \
- -DSMART_SCHEDULE -DBUILDDEBUG -DXResExtension \
- -DX_BYTE_ORDER=X_BIG_ENDIAN -DNDEBUG -DFUNCPROTO=15 \
- -DNARROWPROTO -DIN_MODULE -DXFree86Module $(LINUX_INPUT) \
- -o $@ -c $(subst .o,.c,$@)
-
-where $(ARCHITECTURE) = powerppc [ppc will not work]
-
-* Kernel modules
-I experimented with different ways of building [and loading] the kernel
-modules:
- * evdev.o
- * hid.o
- * mousedev.o
- * wacom.o
-
-I settled on building the modules within the existing framework for building
-the Linux kernel rather than using the makefiles provided by linuxwacom-0.6.1.
-I did so to insure that I got all the PPC dependency stuff right.
-
-* Hotplug kernel module issues
-I had some issues using 'modprobe' to load the wacom kernel module that forced
-me to reconfigure and rebuild the 2.4.25-ben1 kernel.
-
-A typical YDL kernel build for a PowerMac statically links most of the input
-core support into the kernel:
-
- [from .config file provided by YDL]
- # Input core support
- #
- CONFIG_INPUT=y
- CONFIG_INPUT_KEYBDEV=y
- CONFIG_INPUT_MOUSEDEV=y
- CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
- CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
- CONFIG_INPUT_JOYDEV=m
- CONFIG_INPUT_EVDEV=y
-
-I had initially built only wacom.o as a loadable module. The other modules
-were statically linked into the kernel.
-
-When wacom.o was loaded using:
-
- $ /sbin/insmod wacom.o
-
-all went well:
-
-[output from /var/log/messages]
-
-Mar 24 10:26:33 plantain kernel: usb.c: registered new driver wacom
-Mar 24 10:26:33 plantain kernel: Reporting max 45720, 31680
-Mar 24 10:26:33 plantain kernel: wacom.c: Setting tablet report for tabletdata
-Mar 24 10:26:33 plantain kernel: input4: Wacom Intuos 12x18 on usb2:3.0
-Mar 24 10:26:33 plantain kernel: wacom.c: v1.30-j0.6.1 Vojtech Pavlik
-<vojtech@suse.cz>
-Mar 24 10:26:33 plantain kernel: wacom.c: USB Wacom Graphire and Wacom Intuos
-tablet driver (LINUXWACOM-DEBUG)
-Mar 24 10:26:33 plantain kernel: wacom_events
-
-When wacom.o was loaded using:
-
- $ /sbin/modprobe wacom
-
-the module failed to load:
-
- $ /sbin/rmmod wacom
- $ /sbin/modprobe wacom
- modprobe: Can't locate module evdev which is needed for wacom
-
-I was perplexed about this failure because "evdev" was statically linked into
-the kernel. I puzzled over this for a while and concluded that it had
-something to do with how USB hotplug was configured.
-
-I arrived at this conclusion by unplugging the tablet, waiting, and then
-plugging it back in. I found that the tablet "worked" but there are complaints
-in /var/log/messages:
-
-Mar 24 10:34:51 plantain kernel: usb.c: USB disconnect on device 10:19.0-1
-address 3
-
-Mar 24 10:35:53 plantain kernel: hub.c: new USB device 10:19.0-1, assigned
-address 4
-Mar 24 10:35:53 plantain kernel: Reporting max 45720, 31680
-Mar 24 10:35:53 plantain kernel: wacom.c: Setting tablet report for tablet
-data
-Mar 24 10:35:53 plantain kernel: input4: Wacom Intuos 12x18 on usb2:4.0
-Mar 24 10:35:53 plantain kernel: wacom_intuos_irq: tool change 0x094
-Mar 24 10:35:56 plantain /etc/hotplug/usb.agent: Setup wacom for USB product
-56a/24/101
-Mar 24 10:35:56 plantain /etc/hotplug/usb.agent: Setup evdev mousedev for USB
-product 56a/24/101
-Mar 24 10:35:56 plantain modprobe: modprobe: Can't locate module evdev
-Mar 24 10:35:56 plantain modprobe: modprobe: Can't locate module mousedev
-
-I really don't understand how the USB hotplug mechanisms are supposed to be
-configured. Yes... I did look at the scripts in /etc/hotplug. Yes.. I did
-attempt a few unsucessful modifications to usb.handmap and usb.distmap. I
-pondered over this for a while and then decided on a work-around:
-
-I reconfigured and rebuilt the kernel to dynamically load
- * evdev.o
- * hid.o
- * mousedev.o
- * wacom.o
-
-which "eliminated" the problem.
-
-If someone out there knows what should have been done to allow modprobe to
-successfully load wacom when evdev and friends are already statically linked
-into the kernel, please send me email.
-
-* XFree86 module: wacom_drv.o
-I rebuilt wacom_drv.o using the linuxwacom-0.6.1 makefile and the flags listed
-above. The build was uneventful.
-
-* Mouse1
-I do not have a Mouse1 entry in XF86Config. I mention this because there is an
-obscure reference in the documentation to potential mouse conflict problems
-when running a USB Wacom mouse on a system with a USB mouse. The USB mouse
-connected to the system and the Wacom input devices all seem to work.
-
-On my system:
-
- /dev/mouse is a link to /dev/input/mice
-
-Mouse0 is configured in XF86Config as:
-
-Section "InputDevice"
- Identifier "Mouse0"
- Driver "mouse"
- Option "ZAxisMapping" "4 5"
- Option "Protocol" "IMPS/2"
- Option "Device" "/dev/input/mice"
-EndSection
-
-Maybe something nasty is going on that I don't know about. Thoughts???
-
-* xsetwacom
-There are problems...
-
-The 'list' command prints stuff:
-
-$ xsetwacom list
-eraser eraser
-stylus stylus
-cursor cursor
-
-The set command fails:
-
-$ xsetwacom -v set stylus FileModel
-Set: sending 100 0 (0x0)
-Error (5): WacomConfigSetRawParam: Unknown X error
-Set: Failed to set stylus value for 'FileModel'
-
-Looking at the code, I see that it is failing in a call to
-XChangeDeviceControl() made from WacomConfigSetRawParam(). I also poked
-around in this one with GDB. The X-Display gets opened properly. Things look
-OK until the request is dispatched, which then returns an unknown X error.
-
-I also tried to use xsetwacom to toggle the cursor mode between relative and
-absolute. Again the command fails with an unkown X error. Note that the
-XFree86 command 'xsetmode' works fine.
-
--Joseph
-</vojtech@suse.cz></a></pre>
-<a name="debwacomnosrc">
-</a><h2><a name="debwacomnosrc">13.7 - Building wacom driver On Fedora Core 3</a></h2>
-<a name="debwacomnosrc">The following documentation for building wacom kernel modules and x.org
-driver on Fedora Core 3 was written by Paul Duffy. If you have any problems
-or questions, go ahead and post them to the list, or send email to me directly.
-If I cannot provide a satisfactory answer, I'll forward your email on to Paul.
-
-<br><br><br><br>
-
-Copyright (C) 2005 Paul Duffy<br><br>
-
-</a><pre><a name="debwacomnosrc">Procedure for building linuxwacom package on Fedora Core 3 with 2.6 series
-kernel. These instructions are current as of May 23, 2005.
-There are several reasons why FC3 is different. The two main reasons
-being:
-
-- evdev, hid-core and mousedev are compiled into the kernel core so you can't
-just recompile them as modules.
-
-- the Fedora Core kernel is heavily patched, which I don't mind as it means my
-Creative Live! Drive II works, but it does mean that compiling the kernel
-from www.kernel.org may lose you some hardware support.
-
-Additionally, Red Hat no longer supply a simple linux-source rpm so if you
-want the official kernel source for Fedora Core 3 you're going to have to use
-the source RPM.
-
-At this stage, I am assuming that you have a fully updated system and are
-using kernel 2.6.11-1.14_FC3
-
-<b>What you will need:</b>
-
-At this stage you're going to need all of the development packages required to
-compile the kernel (gcc, automake, etc) and the xorg-x11-sdk package
-installed (under Development &gt;&gt; X Software Development). If you're unsure
-where this all is, you can select the hat menu in KDE or Gnome and you want
-to select System Settings &gt;&gt; Add/Remove Applications.
-
-If you're unsure as to exactly what you need to install, install everything
-(except gcc-java, it causes problems with Sun or IBM java installs) assuming
-you have the hard drive space.
-
-Also the vast majority of this will require you to be in SuperUser mode so you
-might as well 'su' from the start; not normally advice I'd be giving anyone
-but it's kinda necessary in this case.
-
-You have two choices for the first step; you can either download the kernel
-SRPM from one of the mirrors at
-http://fedora.redhat.com/download/mirrors.html where you can find the correct
-package as updates/3/SRPMS/kernel-2.6.11-1.14_FC3.src.rpm and install it
-with
-
-rpm -ivh kernel-2.6.11-1.14_FC3.src.rpm
-
-or you can use
-
-up2date --get-source kernel
-
-Either method should leave you with a lot of files in /usr/src/redhat/SOURCES
-and the file /usr/src/redhat/SPECS/kernel-2.6.spec
-At this stage, don't worry about all the files starting linux-2.6.9... the
-main file you are looking for is linux-2.6.11.tar.bz2. As long as that's
-there you should be fine.
-
-Now, to actually get all the kernel sources setup in a compilable form you
-need to run the command
-
-rpmbuild -bp --target=<arch> /usr/src/redhat/SPECS/kernel-2.6.spec
-
-If you don't know what <arch> is, run the command
-
-uname -m
-
-and it should tell you.
-Of course, it should be noted at this point that if my architecture is i686
-and I select that, what will actually be installed is the source
-configuration for i386 and above so if you're still not sure but you know you
-can run Windows then --target=i386 is a safe default.
-
-After everything has been setup the rpmbuild will have applied all the
-standard patches and setup a default configuration so the only reason to run
-'make config', or 'make xconfig', is to change something from the default.
-
-Having said this, I like to run 'make xconfig' to alter the selected chip the
-kernel is going to compile for as it defaults to compiling for i386 whereas
-anyone with a reasonably recent chip (Athlon, Pentium III even) is going to
-want something a bit more advanced.
-
-So, the first thing you want to do, if you want most add-on modules to find
-the kernel source without adding a really long command-line parameter, is to
-add a symbolic link to the source directory.
-
-cd /usr/src
-ln -s redhat/BUILD/kernel-2.6.11/linux-2.6.11 linux
-
-So now everything can find the current kernel source in /usr/src/linux
-
-cd linux
-make xconfig
-
-select 'Processor type and features' and change 'Processor family' from 386 to
-whatever it is you're running.
-If you make a mistake and you don't know what you've done you can always close
-the program and select 'Discard changes' and start again.
-Otherwise, click on the floppy disk icon to save and exit safe in the
-knowledge that you're not compiling for a CPU that doesn't even have a
-floating point unit.
-
-OK, so by now you should have the basic kernel source setup and available
-in /usr/src/linux and, due to the setup of the default kernel, we can't just
-recompile a few modules, we have to recompile the whole kernel.
-
-So at this stage, we're just about where we'd like to be if we wanted to
-compile the kernel as it is, with no support for the Intuos3 or any of the
-Cintix range but if you've got an AthlonXP or a Pentium 4 you might get a
-little bit more performance out of it.
-
-We now want to be getting the latest linuxwacom-0.6.8.tar.bz2 You may want to
-setup your own arrangement for wherever you want it but your home directory
-should be fine and...
-
-tar jxvf linuxwacom-0.6.8.tar.bz2
-cd linuxwacom-0.6.8
-
-...and you're in the source directory for the code that enables proper Wacom
-support.
-
-Now we need to copy just four files, usbmouse.c has been deprecated in favour
-of hid-core.c and can be safely ignored, also we don't need to do anything to
-input.c. Now we copy all the necessary source files.
-
-cd src/2.6.11
-cp evdev.c mousedev.c /usr/src/linux/drivers/input/
-cp hid-core.c wacom.c /usr/src/linux/drivers/usb/input/
-
-Now, with the manual patching done everything should work and, unless I've
-somehow missed a stage, everything should compile just fine.
-
-cd /usr/src/linux
-make all
-
-Now, this is going to take a while, especially if your system's a bit aold
-like mine so now would be a good time to get some tea, coffee, go down the
-corner shop or have lunch.
-
-Assuming there have been no errors, everything should now be compiled.
-
-make modules_install
-make install
-
-You need to install the modules first or 'make install' will quit, complaining
-about there being no '/lib/modules/2.6.11-prep' and sulk in the corner.
-
-After all this, there's still one last thing you need to do and that's make
-this new kernel the default on boot. You will need to
-edit /boot/grub/menu.lst and change the 'default' value from 1 to 0.
-
-Those of you with nVidia and other such graphics cards who like their 3D
-acceleration will need to reinstall the drivers before X Windows will work.
-
-As it is, on reboot you will need to change the boot parameters. When Grub
-comes up, press a to alter the boot parameters. It is advisable at this stage
-to remove 'rhgb' as, one of the effects of running the Red Hat Graphical Boot
-is that if you want a change in the xorg.conf file to take effect you have to
-reboot the entire system and this just gets to be a PITA when you're trying
-to configure something. Then add '3' (without quotes) to the end of the line
-to make FC3 boot to the command line.
-
-Right, so by now we should have the kernel set up to recognise whatever tablet
-you have properly. We can check this.
-
-cat /proc/bus/usb/devices
-
-should give you a readout of every device on your usb system and we're looking
-for the line which includes Vendor=056a
-
-With my Intuos 3 I have ProdID 00b1, manufacturer is listed as 'Tablet' and
-Product is listed as PTZ-630 although this may differ depending on which
-tablet you have and what size it is.
-
-The most important line is the one beginning with I: which should end with
-'Driver=wacom'.
-
-If this is that case, congratulations, your kernel is now fully set up to
-recgonise your tablet :o)
-
-Now, to get it running with X Windows we need to update the wacom_drv driver
-and this, in itself is going to be different as the configuration script will
-not know where to find your x11 SDK and so will efuse to compile the driver.
-
-The xorg SDK in the case of FC3 is located in /usr/X11R6/lib/Server and we can
-tell the configuration script this
-
-./configure --with-xorg-sdk=/usr/X11R6/lib/Server
-
-should do the trick and
-
-make install
-
-should compile and install the module in the appropriate place.
-
-After all this is done, now all you need to do is setup the configuration
-in /etc/X11 xorg.conf
-
-The ServerLayout section is at the start of the configuration file and, as an
-example, mine looks like this:
-
-Section "ServerLayout"
- Identifier "Default Layout"
- Screen 0 "Screen0" 0 0
- InputDevice "Mouse0" "CorePointer"
- InputDevice "Keyboard0" "CoreKeyboard"
- InputDevice "eraser" "SendCoreEvents"
- InputDevice "stylus" "SendCoreEvents"
-EndSection
-
-Where Mouse3 and Mouse5 are the identifiers for the pen and eraser.
-
-My InputDevice sections look like this:
-
-Section "InputDevice"
- Identifier "eraser"
- Driver "wacom"
-# Option "TopX" "0"
-# Option "TopY" "0"
-# Option "BottomX" "1600"
-# Option "BottomY" "1200"
- Option "Device" "/dev/input/event3"
- Option "Type" "eraser"
- Option "USB" "On"
-EndSection
-
-Section "InputDevice"
- Identifier "stylus"
- Driver "wacom"
-# Option "TopX" "0"
-# Option "TopY" "0"
-# Option "BottomX" "1600"
-# Option "BottomY" "1200"
- Option "Device" "/dev/input/event3"
- Option "Type" "stylus"
- Option "USB" "On"
-EndSection
+<B>4. Recompile the wacom_drv.o module.</B>
-It's important to note, at this point, that the TopX/Y and BottomX/Y options
-are not actually necessary unless you have problem with the detection of the
-tablet as all the lpi information is included in the source code for the
-wacom module so it's perfectly safe to leave these out if you don't know what
-the values should be.
+The source you need to replace and recompile will be in the following
+directory:
-Also note, that at this stage I still don't have /dev/input/wacom and the
-tablet appears on /dev/input/event3
+&lt;download_dir&gt;/xfree86-4.1.0/build-tree/xc/programs/Xserver/hw/xfree86/input/wacom
-If you're unsure as to which device your tablet is using, then wacdump should
-be able to find it. It is, to be honest, a bit trial and error but you'll
-know when you've found it as the readout will look like this:
+Replace the 'xf86Wacom.c' file therein with the one provided. While X
+does need to have some configuration done for this to compile, and that
+configuration is accomplished automatically by the build process, it
+does not necessarily need to finish compiling the whole package. So,
+once a 'Makefile' is created automatically by the build scripts in this
+directory, you can attempt to run 'make' from time to time. Once it
+compiles without error, you can halt the very lengthy build process of
+the XFree86 package.
+</PRE>
-wacdump v0.5.2
+<BLOCKQUOTE><DIV CLASS=diff>This may not work with the current beta package
+since it also contains the wcm-beta.c and wcm-beta.h files. You can
+solve this by updating the Makefile, or proceed to step five
+on the <A HREF="#builddrv">Building wacom_drv.o From Scratch</A> page.
+The command line options for building the driver will undoubtably have
+changed, so be prepared to update the Makefile in the wacpack/src directory.
+</DIV></BLOCKQUOTE>
-MODEL=Wacom Intuos3 6x8 ROM=1.0-2
-CLS=USB VNDR=Wacom DEV=Intuos3 SUB=PTZ-630
+<PRE>
+<B>5. Move the wacom_drv.o module to the proper place.</B>
+That's it. Once the 'make' command compiles without error, you will
+have several new files in the directory. The one we are interested in
+is 'wacom_drv.o.' Now you can just move the 'wacom_drv.o' file to the
+directory:
+/usr/X11R6/lib/modules/input/
+This will also require 'root' privileges.
+---------------------------------------------------------------------
-TOOLTYPE=NONE IN_PROX=+00000 (+00000 .. +00000)
- BUTTON=+00000 (+00000 .. +00000) POS_X=+00000 (+00000 .. +40640)
- POS_Y=+00000 (+00000 .. +30480) ROT_Z=+00000 (-00900 .. +00899)
-DISTANCE=+00000 (+00000 .. +00015) PRESSURE=+00000 (+00000 .. +01023)
- TILT_X=+00000 (+00000 .. +00127) TILT_Y=+00000 (+00000 .. +00127)
-ABSWHEEL=+00000 (+00000 .. +01023) RELWHEEL=+00000 (-00001 .. +00001)
-THROTTLE=+00000 (-01023 .. +01023)
-
- LEFT= MIDDLE= RIGHT= EXTRA=
- SIDE= TOUCH= STYLUS= STYLUS2=
+You may want to add that to you HOWTO, for my fellow Debian users. And
+thanks again for the very nice work on the HOWTO and the drivers.
+HTH,
-Once you've setup all the configuration with the correct input device execute
-
-init 5; exit
+Tim
+</PRE>
-and you should find yourself in X with a fully working graphics tablet.
-Instructions for configuring GIMP 2.2 are the same as in the official HowTo.
-
-Good luck.
-
-regards, Paul
-
-</arch></arch></a></pre>
-<a name="susewacom">
-</a><h2><a name="susewacom">13.8 - Building wacom driver On Suse 9.2</a></h2>
-
-<a name="susewacom">Nico Kadel-Garcia has provided a changed SPEC file for SuSE 9.2.
-You can download the spec </a><a href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1117278&amp;group_id=69596&amp;atid=525124">here</a>.
-
-<pre>
-"There are only a few needed changes: use the new
-software, throw out an old patch, teach it to use the right
-options for x86_64 compilation, and stop it from
-generating symlinks into /usr/include/X11 at compilation
-time, and it's done. ". Nico said on Mar 21 2005.
-
-</pre><a name="laptop">
-</a><h2><a name="laptop">13.9 - Laptop Suspend/Resume Tips</a></h2>
-<a name="laptop">Thomas Netter (tnetter at iniDOTunizhDOTc) kindly provided a solution
-to the following problem:
-
-</a><blockquote><pre><a name="laptop">When laptop recovers from suspend/resume, XFree86/X.org no longer
-registers the tablet. The laptop, however, receives all the tablet data
-(I can "cat /dev/input/event2" and see the data).
-
-The only way I know for X to recover the tablet is to restart X.
-</a></pre></blockquote>
-
-<a name="laptop">The peoblem lies in the step that when unplugging tablet cable while the
-laptop is entering Suspend Mode. The proper steps to plug/unplug, suspend/resume
-a Wacom tablet on a laptop are:
-
-</a><blockquote><pre><a name="laptop">- Fold the laptop's screen
-- Wait 4 or 5 seconds for the tablet's orange LED to extinguish
-- Unplug the tablet's USB cable
-
-THEN you can recover the tablet functionalities after resuming the
-laptop and repluging the tablet.
-
-However, If you:
-- Fold the laptop's screen
-- Immediately unplug the tablet's USB cable before the LED extinguishes
-
-THEN you cannot recover the tablet functionalities after resuming the
-laptop and replugging the tablet, even if you replug the tablet before
-resuming the laptop.
-
-Therefore, old airline operations apply: Extinguish LEDs before take-off!
-
--Thomas
-</a></pre></blockquote>
-<a name="lic">
-</a><h2><a name="lic">13.10 - GNU GENERAL PUBLIC LICENSE</a></h2>
-<a name="lic"> GNU GENERAL PUBLIC LICENSE<br>
- Version 2, June 1991<br>
-<br>
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>
- 675 Mass Ave, Cambridge, MA 02139, USA<br>
- Everyone is permitted to copy and distribute verbatim copies<br>
- of this license document, but changing it is not allowed.<br>
-<br>
- Preamble<br>
-<br>
- </a><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-</a></p><p><a name="lic"> 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".
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic"> 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></p><p><a name="lic"> a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic"> 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></p><p><a name="lic"> 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,
-
-</a></p><p><a name="lic"> 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,
-
-</a></p><p><a name="lic"> 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.)
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic">This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic">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.
-
-</a></p><p><a name="lic"> 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
-
-</a></p><p><a name="lic"> 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.
-
-</a></p><p><a name="lic"> 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
-</a></p></td></tr></tbody></table></center>
-
-<br><br>
-
-<div class="copy" align="center">
- Copyright (C) 2002-2009 - LinuxWacom -Last updated April 29, 2009<br>
- This website and its contents are licensed under the GNU GENERAL PUBLIC LICENSE.<br>
-</div>
-</body></html> \ No newline at end of file
+<CENTER><B>Copyright (C) 2002 - John E. Joganic</B></CENTER>
+</BODY>
+</HTML>
diff --git a/docs/docs.txt b/docs/docs.txt
new file mode 100644
index 0000000..8dd4cde
--- /dev/null
+++ b/docs/docs.txt
@@ -0,0 +1,2221 @@
+
+ John's Linux USB Wacom Page
+
+Last Modified: December 22, 2002 18:12
+Changelog <#changelog>
+
+
+Navigation: MAIN </wacom/index.php/id/book> NEXT
+</wacom/index.php/id/intro> INDEX </wacom/index.php/toc> *ALL*
+</wacom/index.php/all>
+
+
+
+ 1.0 - Introduction
+
+This document was written for three reasons: 1) to remind myself how I
+got my brand-new Wacom Intuos2 running on my Redhat 8.0 Linux box in
+case I have to do it again from scratch, 2) to help other people do the
+same, and 3) to help de-mystify the process by explaining why things
+work as they do, and where to look when things seem to be going wrong.
+
+If you find an error, have a question, or have something to add, please
+contact me directly at jej@j-arkadia.com
+<mailto:jej@j-arkadia.com?subject=WACOM>. Furthermore, please add the
+word "WACOM" to the subject line. I get hundreds of messages a day, so
+that'll help me see your message amidst the spam.
+
+
+ 1.1 - Expectations
+
+
+ What You Can Expect Today
+
+Depending on whether you are using serial or USB tablets, your
+experience will differ, but for the moment at least, the serial tablets
+have a generally simpler configuration. This document currently
+addresses only the USB tablets, but that will change in the future. Mr.
+Lepied's XInput driver for XFree86
+<http://people.mandrakesoft.com/~flepied/projects/wacom/> web page has a
+good description of the serial configuration process. The goal of this
+website is to make configuration and use of both tablet types as simple
+as possible. Here is what you can expect now:
+
+
+ You Should Be Able to Get Your Tablet Working
+
+Most all serial and USB tablets are working to a reasonably functional
+degree. I have an old ArtPad (1997) that does not initialize with the
+XFree86 driver, and USB Cintiq users are having a little trouble with
+the kernel drivers. Everyone else should be up and running, namely:
+
+ * PenPartner,
+ * Graphire,
+ * Graphire2,
+ * Intuos, and
+* Intuos2
+
+
+ All Your Fancy Styluses and Pointers Should Work
+
+I have a collection of pointers, pens, and brushes to test; all of them
+work completely as one would expect. Users have reported success with
+their tools as well. I have not tested the airbrush yet, but presumably
+it works just fine. Tools that are known to work include:
+
+ * Graphire2 2D mouse (EC-120-0K),
+ * Intuos Pen (GP-300E-01H),
+ * Intuos2 2D mouse,
+ * Intuos2 4D mouse,
+ * Intuos2 Lens cursor,
+ * Intuos2 grip pen (XP-501E-00A),
+ * Intuos2 stroke pen (XP-120-00A),
+* Intuos2 ink pen (XP-110-00A),
+
+
+ You Will Need to Modify Your XF86Config File
+
+This project is actively working to become a turn-key system. It will be
+awhile before major distributions like Redhat include these settings
+automatically for you. Until that time, you will need to make some
+changes to your XFree86 configuration files by hand.
+
+
+ You May Need to Update Your Kernel
+
+This project assumes that you have a kernel version of at least 2.4.18.
+While it may be possible to use this document with older kernels, the
+likelihood of success diminishes the farther back you go. Redhat 8.0
+ships with this kernel, and most of the major distributions are already
+past this point.
+
+
+ You Will Need to Work With the Command Line
+
+This document details a step-by-step process for setting up and
+diagnosing the tablet. There are no GUI tools to help you through this
+process- at least not today. Some familiarity with the command line is
+recommended since I provide enough information to get the task
+accomplished, but I do not explain how the command line itself operates.
+Any good book on UNIX will do, and I use the bash shell for all my work.
+If you are not using bash, you presumably know what you are doing already.
+
+
+ What You Can Expect Soon
+
+I have a near-term design goal to get all the tablets and their
+respective tools functioning using the original driver design. This
+currently includes the airbrush (which may work already), the Cintiq,
+and if possible and time permits, the lowly ArtPad. If there are any
+outstanding problems with the original driver, I will take care of them
+as they come up.
+
+While the current way of configuring the tablet is sub-par in my
+opinion, it is also the established way of doing things. Merging
+large-scale changes back into either the Linux kernel or the XFree86
+code tree will be difficult, if for no other reason than insufficient
+multi-platform testing. To solve this problem, the new functionality
+described below will be implemented in a separate project and accessed
+through the original driver as an advanced option. This will allow all
+the various platforms to use the new code or not depending on their own
+constraints and circumstances. It also allows for people to write their
+own tablet libraries without mucking around in the XFree86 code.
+
+
+ The Next Steps
+
+First and foremost, the tablet needs to be configurable without
+restarting X. By separating the tablet code from the low-level X code,
+it will be possible to talk directly to the tablet engine without
+interfering with the X server's operation. Additionally, it will be
+possible to use either the XInput configuration API or the tablet
+engine's API to access that functionality. The preferred way would
+probably be an X server extension, but today at least, that is outside
+of the scope of my interest. Ask me again in another month.
+
+The next issue is plug and play. The USB tablets have the unfriendly
+habit of being unaccessible when they are unplugged and replugged. Since
+the X server holds the device open, the tablets cannot reconnect to
+their original position and get bumped to another event slot. The new
+tablet engine will address the problem, and can probably even auto-probe
+for the USB tablets.
+
+Third, a GUI-based configuration tool should cap things off nicely. I
+intend to replicate the functionality of the Windows configuration tool.
+This includes diagnostics, pressure mappings, button settings, keyboard
+mappings, etc.
+
+
+ Your Role
+
+I have some expectations as well. If you have a Wacom tablet and you use
+this code, I would appreciate it if you could test the beta releases
+whenever a feature or issue that might affect you comes up. The sooner
+that problems are resolved, the less likely you will be impacted by a
+buggy production release. If you only use the stable builds, none of the
+new features will be available to you until after they have been
+thoroughly hammered out which could be awhile. Of course, nothing is
+stopping you from using the stable builds; they are purposefully made
+available for people and companies who need the tablet drivers as stable
+as possible.
+
+
+ 1.2 - Most Recent Updates
+
+This is a list of the updates for the past month or so. The Changelog
+<#changelog> has a more complete list.
+
+December 22, 2002 - Added support for the serial Intuos2 under
+xf86Wacom.c. Fixed the sign convention on the mouse wheel for USB Intuos
+mice. Graphire should be fixed, too. Added preliminary support for
+Volito to kernel driver. Cleaned up wacdump and hid-core to compile on
+Debian Woody without warnings. Added build help for Debian Stable users.
+Added ability to read serial devices using wacdump. New package is
+0.3.3-beta.
+
+December 15, 2002 - Added initial framework for new driver code. Fixed
+the mouse wheel for 4D mice. Fairly responsive, almost too responsive,
+in fact. (Updated: quick fix to xf86Wacom.c to remove some debugging
+code that got left in accidentally; new driver version is 0.3.2a, but
+the package is the same.)
+
+December 13, 2002 - Added development page. New beta build has fix for
+2D mouse wheel. Wacdump displays relative data now. Build environment
+for wacom_drv.o set up for new code.
+
+December 9, 2002 - Added more information about the parameters accepted
+by the InputDevice section, including the man pages.
+
+November 24, 2002 - Moved beta tree to version 0.2.0. Added complete
+configure-based environment. wacom.o and wacdump are built by default;
+wacom_drv.o is available in binary and source form.
+
+
+ 1.3 - Success Stories
+
+Originally, this document dealt only with Redhat 8.0. I will extend this
+to cover as many different distributions as possible, but I can
+personally only test on machines at my disposal. At present, that means
+Redhat 7.2 and 8.0. If you have success stories for a distribution or
+version not mentioned, let me know so I can update the document.
+
+ * Redhat
+ o Redhat 8.0 - tested on kernel 2.4.18-18.8.0
+ o Redhat 8.0 - tested on kernel 2.4.18-17.8.0
+ o Redhat 7.3 - tested on kernel 2.4.18-17.7.x
+ o Redhat 7.2 - tested on kernel 2.4.18-17.7.x
+ * Mandrake
+ o Mandrake 9.0 - tested on ???
+ * Gentoo
+ o Gentoo 1.4rc - tested on 2.4.19 kernel, gcc3.2, XFree86 4.2.0
+ * Debian
+ o Debian Woody - XFree86 4.2 on 2.4.20
+ o Debian Stable - XFree86 4.1 (see Building wacom_drv.o On
+ Debian Stable <#debwcmdrv>)
+ * Slackware
+ o Slackware 8.1, (standard release)
+ * SuSE
+ o Suse Linux 8.0, kernel 2.4.18, XFree 4.2
+
+
+ 1.4 - How To Use This Document
+
+ Where the guide differs between distributions or packages, I have
+ added a comment like this to help distinguish between versions.
+
+In terms of document organization, if you have not figured it out
+already, you can browse the document one page at a time, or you can
+click on the ALL link and view the entire thing in one long page.
+
+Next, this document was written with the assumption that you are
+starting from scratch with a relatively recent distribution of the Linux
+kernel. Also, if you have already added lines to your X11 configuration
+file (XF86Config), you should comment them out and restart X. Since
+we'll be stepping through the entire process, we need X to ignore the
+tablet until we're ready. Otherwise, X will just get in the way.
+
+Finally, if you know what you're doing, you can leave your X settings
+intact, print this out, switch to runlevel 3, and follow along from the
+console. The newer packages should have an HTML and text version of this
+document in the documentation directory. And of course, there's always
+lynx <http://lynx.isc.org/> for the gurus out there, which is why this
+document is written out in plain vanilla HTML.
+
+
+ 1.5 - Resources and References
+
+Lepied's Wacom XInput driver for XFree86
+<http://people.mandrakesoft.com/~flepied/projects/wacom/> This page
+contains the original driver and help for serial tablet users.
+Lepied's Wacom Mailing List Archive
+<http://www.lepied.com/archive_wacom.html> This is an archive of
+Lepied's driver mailing list. /Warning: posting directly to the mailing
+list page does not mail to the list. Many posts are missed this way./
+Subscribe to Lepied's Wacom Mailing List
+<mailto:wacom-subscribe@lepied.com> If you want to post to the list and
+receive notifications about driver updates, this link will subscribe you.
+Stefan Runkel's Wacom Tablet HOWTO
+<http://www.runkel-it.de/wacom_tablet_howto.html> This page is a bit
+old, but it covers a lot of details that I mention only briefly. Good
+reading, even if it is possibly outdated.
+Wacom Webpage <http://www.wacom.com> The Wacom web site contains little
+information about the Linux drivers, but you can look at their nifty new
+tablets.
+pxh: Graphire USB <http://www.pxh.de/fs/graphire/> This page is devoted
+to a Graphire-specific XFree86 driver.
+A Webpage Dealing with Cintiq (Wacom PL-500 in particular) on Linux
+<http://homepages.feis.herts.ac.uk/~bt7al/wcm/> This website deals with
+getting the Cintiq running; I will be merging this code into the kernel
+soon.
+Wacom Intuos USB Micro-HOWTO <http://sem.best.vwh.net/linux/wacom/> An
+older webpage which may not be relevent anymore, but was useful to me
+when I got started.
+Wacom Intuos USB on Linux
+<http://www.ecn.wfu.edu/~cottrell/thinkpad/tpa21m/wacom.html> Another
+page that was useful to me when I started.
+Wacom Software Developer Support
+<http://www.wacomeng.com/devsupport/index.html> This page contains some
+documentation for the older tablets.
+
+
+ 1.6 - Frequently Asked Questions
+
+This FAQ is based on the questions that I receive in email. If you have
+a question that is not answered here, send me email directly.
+<mailto:jej@j-arkadia.com?subject=WACOM> Please add the word "WACOM" to
+the subject line to help me distinguish your message from the spam I
+normally receive.
+
+
+ Index
+
+ * Who is responsible for this code? <#WHO>
+ * Is my tablet supported? What about my special stylus? <#SUPPORT>
+ * What about my Penpartner/Graphire/Cintiq? <#OTHERS>
+ * How do I get my stylus to stop clicking randomly whenever I use
+ it? <#SPURIOUS>
+ * The old drivers had filtering, how do I enable it now? <#FILTER>
+ * What happened to feature XYZ? <#FEATURE>
+* How do I get the special features of my stylus to work? <#BUSTED>
+
+
+
+
+ Who is responsible for this code?
+
+We are. That is, Linux users with Wacom tablets are responsible for the
+development of this code. The source code was written by at least two
+dozen individuals, none of whom still seem to be directly involved in
+the project. I, John Joganic, took up the code in November of 2002,
+largely to satisfy my own needs, but also because I believe Linux needs
+to be more useful in the graphic and video industries. What I ask of
+you, is to use the drivers and report the problems you encounter.
+
+
+ Is my tablet supported? What about my special stylus?
+
+Most recent tablets are supported as well all the styluses. The
+Expectations <#expect> page has a list of all the tablets and styluses
+that are known to work as well as what you can expect out of these
+drivers now and in the future.
+
+
+ What about my Penpartner/Graphire/Cintiq?
+
+The USB kernel driver currently seems to support Penpartner, Graphire,
+Graphire2, Intuos, Intuos2, and PL400-800. Based on user reports, the
+Cintiqs may identify themselves as PL series tablets. There is no kernel
+driver necessary for serial tablets. The XFree86 wacom driver supports
+both USB and serial devices. It has support for all the USB devices as
+well as virtually all of the older tablet models as well. Depending on
+how the Cintiq identifies itself, it may potentially work with the
+XFree86 driver as a serial device. There are no guarantees as of yet, so
+I would not buy one (currently over $3000 USD) on the assumption that it
+will work without doing some actual research.
+
+
+ How do I get my stylus to stop clicking randomly whenever I use it?
+
+The "Threshold" setting in the InputDevice section of the XFree86
+configuration file determines the minimum pressure value before a touch
+event is detected. Wacdump can show you what pressure values are
+actually being received from the tablet, and setting the threshold to a
+value higher than that should solve the problem. My stylus oscillates
+between 0 and 6, even if the stylus is not touching the tablet. I use a
+threshold of 10.
+
+
+ The old drivers had filtering, how do I enable it now?
+
+At some point, the maintainers of the wacom kernel driver ripped out all
+the good features and moved them into the xf86Wacom driver. Not
+everything works as well as one might like. The "Suppress" setting in
+the InputDevice section specifies the tablet sensitivity.
+
+
+ What happened to feature XYZ?
+
+As mentioned above, many of the features in the original kernel driver
+were removed and transferred to the xf86Wacom driver. Not all the
+features made the trip. The goal of this website is to have all the
+original features working again as well as all the features available
+for the windows driver. If your favorite feature is not working, drop me
+a line. I prioritize my work based on my perception of user need.
+
+
+ How do I get the special features of my stylus to work?
+
+There are many different types of stylus, mice, and cursors. All of them
+work to varying degrees, so if you are running into trouble, send me
+email. There are presently known issues with the mouse wheel on 2D mice
+(fixed in 0.3.1-beta), and some of the extra buttons on the 4D mice.
+While the values are generally reported correctly to the driver, the
+xf86Wacom driver does not interpret the information properly. The 4D
+mouse wheel for instance behaves completely contrary to expectation
+(fixed in 0.3.2-beta). These problems will be addressed in future
+production releases (and are available now in the beta releases).
+
+I do not have an airbrush tool at my disposal. If you have one and it
+does not work for you, let me know. You could be beta-testing the code
+that gets this working.
+
+
+ 1.7 - Development
+
+
+ CURRENT DEVELOPMENT
+
+Date: 2002-12-22 (Sunday)
+Status: Moving over to SourceForge, and testing new serial driver.
+Estimated Time: Ready on 2002-12-29 (Sunday)
+
+
+ Completed
+
+ * Added Intuos2 serial to xf86Wacom.c.
+ * Added serial tablet code to wacdump.c.
+ * Added experimental Volito code to kernel.
+ * Split ncurses and Linux input code to avoid namespace collision on
+ Debian.
+* Corrected wheel sign for USB mice.
+
+
+ Immediate
+
+ * Get code onto SourceForge.
+* Intuos2 2D mouse does not work correctly under xf86Wacom.c
+
+
+ Secondary
+
+ * Getting test application for XF86 driver together
+ * Testing ability to create new pointer devices on the fly
+* Testing ability to fork out new server process
+
+
+
+
+ KNOWN ISSUES
+
+There are plenty of known issues. If you have one, and it is not listed,
+check the FAQ, and if it's not there either, let me know.
+
+
+ wacom.o
+
+ * 2002-12-13: Tablet does not reinitialize properly when replugged
+(report #1).
+
+
+ wacdump
+
+* Nothing outstanding.
+
+
+ wacom_drv.o
+
+ * 2002-12-22: Intuos2 2D mouse does not work correctly under
+xf86Wacom.c
+
+
+ 1.8 - Wacom Driver Theory of Operation
+
+Initially at least, the Wacom tablet is an HID compliant device, and
+when first connected to the computer, will identify itself as such.
+Unfortunately, this is not what you want because in this mode, you will
+not get any of the fancy features. The hid-core.c and usbmouse.c files
+contain exceptions for the wacom; when the device is detected, they
+ignore the tablet. In this way, the more sophisticated wacom driver has
+the opportunity to assume control.
+
+The first thing that the driver does is register itself with the USB
+subsystem and wait for work to do. When the user plugs the device in, or
+the device is first detected, the USB subsystem shops the vendor and
+device identifier around, checking it against different drivers. The
+wacom driver takes responsibility for the tablet and then notifies the
+event system that it will be providing data. It then asks the tablet to
+switch from HID-compliant mode to "mode 2", a wacom-specific protocol
+which allows for values like pressure, Z rotation, and tilt. As
+information arrives, the wacom driver dutifully converts the data into
+real-world values and hands it on to the event system.
+
+From here, any usermode application can get access to the event data by
+opening /dev/input/event0. A stream of events including mouse movements,
+clicks, and proximity updates can be read from the device. One such
+application that would be interested in this data is the X system
+itself. An XInput driver (wacom_drv.o) collects that information,
+applies various forms of filtering, and offers it to GUI-based
+applications throught the XInput API. A graphics program like gimp can
+then get access to the positions of various tools by querying X directly.
+
+By breaking the responsibility for the data into three distinct levels,
+we keep the kernel code simple and robust, the applications generalized,
+and the fancy features commonly accessible to all GUI applications in
+the X window system itself. This document walks down the entire data
+path from the kernel driver to the gimp application.
+
+
+ 2.0 - Getting It Together
+
+This section is devoted to preparing your system for the installation.
+In some cases, your distribution may have automatically loaded certain
+modules which you will now need to unload. Incidentally, some
+distributions detect new hardware on boot. If you allow Redhat's
+"anaconda" for instance to automatically configure (or remove) your
+tablet, it may undo some of the settings you will make here. Until
+Redhat's installation program recognizes Wacom tablets as non-HID
+devices by default, you are best off in my opinion to /not/ allow it to
+configure the device. Just a warning.
+
+
+ 2.1 - Before We Start
+
+From the beginning, let's make certain that we are on the same page.
+First, unplug the USB Wacom. If you have Wacom related lines in your
+XF86Config file, you should comment them out or remove them; then restart X.
+
+Unload the old modules.
+
+[jej@ayukawa jej]$ su -
+[root@ayukawa root]# lsmod | grep wacom
+*wacom* 8020 0 (unused)
+input 5920 0 [*evdev* *wacom* mousedev keybdev hid]
+usbcore 77024 1 [*wacom* usb-storage snd printer hid usb-uhci]
+[root@ayukawa root]# rmmod wacom evdev
+
+The kernel now knows nothing about the Wacom or how to handle
+event-based input devices. If you get an error unloading (busy driver
+perhaps), try rebooting.
+
+Check the presence of the input devices in the /dev/input directory. You
+should find approximately 114 devices with names such as event*, mouse*,
+keyboard, js*, and ttyACM*. We are interested in two devices, mouse0 and
+event0.
+
+[root@ayukawa root]# cd /dev/input
+[root@ayukawa input]# ls -la mouse0 event0
+crw------- 1 root root 13, 64 Aug 30 16:31 event0
+crw------- 1 root root 13, 32 Aug 30 16:31 mouse0
+[root@ayukawa input]# xxd mouse0
+xxd: mouse0: No such device
+[root@ayukawa input]# xxd event0
+xxd: event0: No such device
+
+On some distributions, Mandrake 9.0 for instance, the /dev directory is
+managed by devfs; Redhat 8.0 does not use it. When devfs is running, the
+/dev/input directory and/or its contents may be missing if the driver is
+not loaded. If you are not using devfs and the /dev/input directory or
+mouse0/event0 devices are not present, your distribution may be lacking
+these devices. This could be an oversight, or it could be an indication
+that your distribution is too old.
+
+If after executing /xxd mouse0/ you *did not* receive the "xxd: mouse0:
+No such device" message, then the input device is still loaded; go back
+and try running /rmmod evdev/ again. Once the new drivers are compiled
+and installed, this command will stream information from the Wacom
+tablet. mouse0 behaves like a PS/2 style mouse. event0 provides
+extensive information about the tablet including position, tilt,
+pressure, and buttons. It can also track at least two different tools
+simultaneously (Intuos2).
+
+
+ 2.2 - Downloading the Code
+
+The file wacpack-0.2.0.tar.gz </wacom/wacpack-0.2.0.tar.gz> is the
+stable package and contains files that you will need to get the tablet
+working. The current beta package wacpack-0.3.3-beta.tar.gz
+</wacom/wacpack-0.3.3-beta.tar.gz> is also available and may be used by
+people who are willing to risk an occasional kernel panic to help test
+new features. I will never put a beta package on this site that I am not
+running myself on my primary development machine, so you can be certain
+that if there are any obvious show stoppers, they will be fixed before
+you get to see them.
+
+
+ Stable files included for wacpack-0.2.0:
+
+File Comment
+configure - configure script for distribution independent builds
+prebuilt/wacom_drv.o - binary X11 driver for the wacom (26-j0.2.0)
+src/wacom.c - a stable, working kernel driver (1.30-j0.2.0)
+src/wacdump.c - a simple program for displaying tablet event data
+directly using ncurses; current version is 0.2.0
+src/usbmouse.c - replacement kernel driver (2.4.19), use only if needed
+src/hid-core.c - replacement kernel driver (2.4.19), use only if needed
+src/hiddev.c - replacement kernel driver (2.4.19), use only if needed
+src/hid-input.c - replacement kernel driver (2.4.19), use only if needed
+src/xf86Wacom.c - source for wacom_drv.o; requires XF86 build
+environment to compile. Binary available in prebuilt directory.
+GPL - the GNU General Public License, in case you did not already have
+twenty or more lying around
+
+
+ Beta files included for wacpack-0.3.2-beta:
+
+File Comment
+configure - configure script for distribution independent builds
+prebuilt/wacom_drv.o - binary X11 driver for the wacom (26-j0.3.2a)
+src/wacom.c - a stable, working kernel driver (1.30-j0.3.1)
+src/wacdump.c - a simple program for displaying tablet event data
+directly using ncurses; current version is 0.3.2
+src/usbmouse.c - replacement kernel driver (2.4.19), use only if needed
+src/hid-core.c - replacement kernel driver (2.4.19), use only if needed
+src/hiddev.c - replacement kernel driver (2.4.19), use only if needed
+src/hid-input.c - replacement kernel driver (2.4.19), use only if needed
+src/xf86Wacom.c - legacy source for wacom_drv.o; requires XF86 build
+environment to compile.
+src/wcm-beta.c - beta source for wacom_drv.o; requires XF86 build
+environment to compile.
+src/wcm-beta.h - beta source for wacom_drv.o; requires XF86 build
+environment to compile.
+GPL - the GNU General Public License, in case you did not already have
+twenty or more lying around
+
+
+ Stable Packages by Version and Date:
+
+File Date Comment
+wacpack-0.2.0.tar.gz </wacom/wacpack-0.2.0.tar.gz> - 2002-11-24
+Configure-based package
+wacpack-0.1b.tar.gz </wacom/wacpack-0.1b.tar.gz> - 2002-11-06
+wacpack-0.1a.tar.gz </wacom/wacpack-0.1a.tar.gz> - 2002-11-05
+wacpack-0.1.tar.gz </wacom/wacpack-0.1.tar.gz> - 2002-11-04
+
+
+ Beta Packages by Version and Date:
+
+File Date Comment
+wacpack-0.3.3-beta.tar.gz </wacom/wacpack-0.3.3-beta.tar.gz> -
+2002-12-22 Serial Intuos2, serial wacdump, Volito added, USB mouse wheel
+direction fixed, kernel 2.4.20 friendly
+wacpack-0.3.2-beta.tar.gz </wacom/wacpack-0.3.2-beta.tar.gz> -
+2002-12-15 Fix for 4D mice and working beta driver shell
+wacpack-0.3.1-beta.tar.gz </wacom/wacpack-0.3.1-beta.tar.gz> -
+2002-12-13 Fix for 2D mice and relative events in wacdump
+wacpack-0.3.0-beta.tar.gz </wacom/wacpack-0.3.0-beta.tar.gz> -
+2002-11-24 Configure-based package
+wacpack-0.1g-beta.tar.gz </wacom/wacpack-0.1g-beta.tar.gz> - 2002-11-14
+wacdump updated; displays ranges, cleaner output
+wacpack-0.1f-beta.tar.gz </wacom/wacpack-0.1f-beta.tar.gz> - 2002-11-14
+build environment for xf86Wacom added
+wacpack-0.1e-beta.tar.gz </wacom/wacpack-0.1e-beta.tar.gz> - 2002-11-11
+fixed range for I2-6x8
+wacpack-0.1d-beta.tar.gz </wacom/wacpack-0.1d-beta.tar.gz> - 2002-11-10
+updated wacdump, fixed range for I2-12x12
+wacpack-0.1c-beta.tar.gz </wacom/wacpack-0.1c-beta.tar.gz> - 2002-11-09
+updates to range, pressure, and mouse events
+
+
+ 2.3 - Configuring the Package
+
+Versions of wacpack-0.2.0 and greater are based on GNU's configure
+script based build environment. The upside is that more details are
+guessed by default. The downside is that the default configuration
+builds only the kernel driver and wacdump programs (which should cover
+almost everybody), but if you need a different module built, you will
+have to reconfigure the package first. This is mostly because different
+modules have different dependencies, some of which are difficult to
+resolve. A list of the options currently available in the stable package
+is presented below. Remember that for every --enable option, there is
+also an equivalent --disable option.
+
+Option Default Builds
+--enable-wacom *yes* wacom.o kernel driver
+--enable-wacdump *yes* wacdump event monitor
+--enable-hid no hid.o replacement kernel driver (not normally necessary)
+--enable-usbmouse no usbmouse.o replacement kernel driver (not normally
+necessary)
+--enable-wacomdrv no wacom_drv.o XFree86 driver (binary is available in
+prebuilt directory)
+--enable-modver best guess enables kernel module versioning; usually
+guesses correctly, but can be enabled or disabled if not
+--with-kernel=dir best guess Specifies the kernel source directory if
+configure cannot guess correctly.
+--with-xf86=dir none Specifies the XFree86 build directory.
+--with-arch=arch best guess Specifies the architecture if configure
+guesses incorrectly.
+
+Chances are high that you will be able to run the configure script
+without any options and have it execute correctly. Here is a sample
+output of the script on a Redhat 8.0 system:
+
+[jej@ayukawa wacpack]$ ./configure
+checking for a BSD-compatible install... /usr/bin/install -c
+checking whether build environment is sane... yes
+...
+checking for processor type... *i686*
+checking for kernel module versioning... *yes*
+checking for kernel sources... */usr/src/linux-2.4*
+...
+
+----------------------------------------
+ BUILD ENVIRONMENT:
+ architecture - i686
+ module versioning - yes
+ kernel - yes
+ XFree86 - no
+
+ BUILD OPTIONS:
+ wacom.o - yes
+ wacdump - yes
+ hid.o - no
+ usbmouse.o - no
+ wacom_drv.o - no
+----------------------------------------
+
+The processor type is determined by the script and used to build the
+kernel modules. Similarily, the script attempts to discover if the
+kernel is using module versioning by looking for version numbers in the
+usb.o module of the currently active kernel. This may not work well on
+all distributions, so if you get a line like "checking for kernel module
+versioning... confused" or "maybe; assuming yes", you'll have to
+manually enable or disable the option if it guesses incorrectly.
+
+The kernel source directory is assumed to be either /usr/src/linux-2.4
+or /usr/src/linux. If your kernel sources are elsewhere, you will need
+to specify the directory with the --with-kernel option.
+
+Generally, you will not need to build wacom_drv.o since it ships in
+binary form in the prebuilt directory. It is compiled with glibc with
+gcc 3.2 on a Redhat 8.0 system; if this will not work for you, building
+from source may be your only option. See the Building wacom_drv.o From
+Scratch <#builddrv> page for more information.
+
+The configure script is pretty simple, so if you find any problems and
+are inclined to fix them, please send me your patch so I can include the
+change in future releases.
+
+The following sample command-line will build everything but wacdump
+while disabling module versioning:
+
+[jej@ayukawa wacpack]$ ./configure --enable-hid --enable-usbmouse \
+ --enable-wacomdrv --with-xf86=/usr/src/redhat/BUILD/XFree86-4.2.0 \
+ --disable-modver --disable-wacdump
+checking for a BSD-compatible install... /usr/bin/install -c
+checking whether build environment is sane... yes
+...
+checking for processor type... i686
+checking for kernel module versioning... *yes*
+checking for kernel sources... /usr/src/linux-2.4
+checking for valid XFree86 build environment... *ok*
+...
+----------------------------------------
+ BUILD ENVIRONMENT:
+ architecture - i686
+ module versioning - *no*
+ kernel - yes
+ XFree86 - *yes*
+
+ BUILD OPTIONS:
+ wacom.o - yes
+ wacdump - *no*
+ hid.o - *yes*
+ usbmouse.o - *yes*
+ wacom_drv.o - *yes*
+----------------------------------------
+
+Notice that the configure script guessed module versioning was enabled
+by default, but was disabled by the command-line option
+--disable-modver. Similarly, the wacdump program which is enabled by
+default was also disabled. All the kernel modules and the XFree86 wacom
+driver are enabled.
+
+If the configure script fails to find something that it is looking for,
+it may disable some options that you previously enabled on the
+command-line. If this happens, check the output for a warning like the
+following:
+
+***
+*** WARNING:
+*** Unable to compile wacom_drv.o without XF86 build environment
+*** wacom_drv.o will not be built
+***
+
+In this particular case, the XFree86 driver was enabled, but the
+--with-xf86 option was not specified. Without the build environment, the
+module cannot be compiled and was consequently disabled.
+
+
+ 3.0 - The Kernel Driver
+
+The kernel driver for the Wacom Intuos that ships with the Linux kernel
+through 2.4.19, and in particular Redhat 8.0, does not work correctly.
+The bug is pretty simple and you can fix it yourself. Optionally, you
+can compile the version that I provide directly and swap the new module
+for the old one. This avoids having to rebuild the entire kernel.
+
+Kernel modules must be recompiled for each new kernel so I can't just
+provide binaries. By the time you read this, my present kernel will be
+entirely out of date with yours. Additionally, this fix will appear in
+2.4.20, so until you upgrade your kernel to that point, each time you
+upgrade to a version less than that, you will need to recompile this
+driver and swap it for the old one. In many cases, distributions like
+Redhat will "back-port" the fixes to older kernels, so keep an eye out
+for the change. Your driver may already be fixed.
+
+
+ 3.1 - Updated wacom.c
+
+The wacom.c driver that is available in wacpack-0.2.0.tar.gz
+</wacom/wacpack-0.2.0.tar.gz> has a number of updates which cannot be
+found in many distributions yet.
+
+First and foremost, it fixes an error that shipped with the 2.4.19
+kernel and was subsequently fixed in 2.4.20. This bug fix was made
+available in the Redhat 8.0 back-ported kernel version 2.4.18-18.x.y.
+Other distributions may not yet be updated.
+
+This driver contains several changes provided by Wacom UNIX developer
+Ping Cheng. Items include revised pressure code, better handling of 2D
+mice and lens cursors.
+
+The driver also contains additional debugging code which may be useful
+in diagnosing data flow problems of which there are many, unfortunately.
+
+
+ 3.2 - Building wacom.c
+
+Building the kernel driver requires having the kernel source. If you are
+running on Redhat, you can get it by installing the kernel-source RPM.
+At the time of this writing, I have the following RPMs installed:
+
+ kernel-2.4.18-18.8.0
+ kernel-2.4.18-14
+ kernel-source-2.4.18-18.8.0
+
+On a Redhat 8.0 machine, the kernel source is installed to
+/usr/src/linux-2.4. You will need to know where your source is installed
+to continue with the next step. After unpacking the wacpack-0.2.0.tar.gz
+</wacom/wacpack-0.2.0.tar.gz> file, configure the package. If your
+kernel is not located at either /usr/src/linux-2.4 or /usr/src/linux,
+use the --with-kernel option as shown below. Otherwise, just run
+/configure/ without any options.
+
+[jej@ayukawa wacpack]$ ./configure --with-kernel=/home/jej/src/linux
+...
+checking for valid kernel source tree... *ok*
+...
+----------------------------------------
+ BUILD ENVIRONMENT:
+ architecture - i686
+ module versioning - yes
+ kernel - *yes*
+ XFree86 - no
+
+ BUILD OPTIONS:
+ wacom.o - yes
+ wacdump - yes
+ hid.o - no
+ usbmouse.o - no
+ wacom_drv.o - no
+----------------------------------------
+
+If you did not receive an error or warning and the BUILD ENVIRONMENT
+summary shows "kernel - yes" then your kernel source tree was detected.
+If not, then you will need to look at the error or warning and determine
+the correct source directory. Now is also a good time to verify that the
+architecture was correctly detected. The --with-arch option allows you
+to change the value.
+
+Another detail that you need to be concerned about is module versioning.
+If it reads "yes" or "no" then the configure script has determined the
+correct setting. If it says "unknown," then it will default disabled,
+and you may have to enable it manually with --enable-modver. If module
+versioning is disable when it should be enabled, depmod will complain
+about missing symbols. If it is enabled when it should be disabled, the
+code may not compile, and it almost certainly will not load properly. If
+in doubt, leave it disabled for now and enable it later if depmod
+complains.
+
+To build the driver, just run /make/. The output will be a file called
+wacom.o in the src directory. This is your replacement driver.
+
+
+ 3.3 - Testing If wacom.o Will Load
+
+Before we install the wacom driver, we need to test that it will load
+properly. We do this by loading the driver manually. WARNING: there is a
+small chance that this will bomb your kernel, so we run /sync/ to write
+all the stale buffers to the disk. People using ext3 have little to
+worry about, but it's always good to be prepared for the worst. At the
+very least, save your work.
+
+[jej@ayukawa wacom]# su -
+[root@ayukawa root]# cd /home/jej/src/wacom/src
+[root@ayukawa src]# sync
+[root@ayukawa src]# rmmod wacom
+[root@ayukawa src]# insmod wacom.o # for those about to rock, we salute you.
+
+Well, if you did not bomb, then good. And if you did, well, sorry. So
+far, we have not had any reports of this happening, so please send in
+yours.
+
+If you get errors inserting the module, then you may need to reconfigure
+and build with module versioning disabled. If it loads without a hitch,
+move on to the next part.
+
+
+ 3.4 - Installing wacom.o
+
+To install or not to install, that is the question. Since the driver is
+in memory, you can pretty much use it this way throughout the rest of
+this document. Anywhere you see /modprobe wacom/, you'll instead need to
+/insmod wacom.o/. You'll also need to be careful that you use the
+correct path to wacom.o since insmod will load the driver from the
+kernel modules directory if it fails to find the module you specified.
+The result is that you'll be using the wrong driver.
+
+Why would you not install the driver? Well, for one, you may be using a
+beta driver, and if the system crashes (you get an Oops or things come
+unglued in other ways), it would be nice to reboot and have the original
+drivers load instead.
+
+When should I install the driver? When you're comfortable that the
+driver will not crash your system. The wacpack tarballs will be marked
+as beta if I am not absolutely convinced that they are stable. On the
+other hand, the new features will be in beta tarballs before they are
+marked stable, so there you have it. For the first time through this
+document, I would recommend installing the files found in the stable
+tarball. If you really know what you're doing, just load the drivers
+manually like in the previous section Testing If wacom.o Will Load
+<#testwacom>.
+
+On some distributions, Mandrake included, the wacom.o driver that
+appears in the kernel modules directory appears to be compressed. If you
+cannot find wacom.o using the method below, try locating wacom.o.gz
+instead. People who encountered this problem were able to run gzip on
+the module and copy that instead.
+
+Installing the driver requires knowing where it belongs. A little
+research will help here. By using the /locate/ command, you can find all
+copies of the original driver on the computer.
+
+jej@ayukawa wacom]$ locate wacom.o
+/lib/modules/2.4.18-14/kernel/drivers/usb/*wacom.o*
+/lib/modules/2.4.18-18.8.0/kernel/drivers/usb/*wacom.o*
+
+[jej@ayukawa wacom]$ uname -r
+*2.4.18-18.8.0*
+
+On this computer, there are two kernels installed. /uname/ identifies
+the currently active kernel as 2.4.18-18.8.0. The correct driver to
+replace is therefore at
+/lib/modules/2.4.18-18.8.0/kernel/drivers/usb/wacom.o. You will need to
+be root to replace this file, and it is a very good idea to make a
+backup copy.
+
+[jej@ayukawa wacom]$ su -
+[jej@ayukawa root]# cd /lib/modules/2.4.18-18.8.0/kernel/drivers/usb
+[jej@ayukawa usb]# cp *wacom.o* /home/jej/src/wacom/*wacom_old.o*
+[jej@ayukawa usb]# cp /home/jej/src/wacom/*wacom.o* *wacom.o*
+
+Here, I've saved the original to wacom_old.o and copied my new driver
+over it. Substitute directory names as appropriate.
+
+Finally, it is always a good thing to update the module dependencies.
+This is where you find out if the module was compiled without kernel
+module versioning. The following command, even if it generates errors is
+relatively benign. If it fails, then there is no harm done. It just
+means that you will have to load modules in the correct order since the
+system will not be able to guess for you.
+
+[jej@ayukawa usb]# depmod -e
+
+If you get no errors and no output, everything is fine, and the module
+was compiled, linked, and installed properly. If you received unresolved
+symbols like usb_set_idle or printk, then you need to reconfigure with
+module versioning enabled and recompile. Or not. As I said, it is not
+critical.
+
+
+ 3.5 - Loading the wacom Driver
+
+If you have installed the driver, now is the time to test whether it
+will load when needed. If you have not installed it, but are instead
+using insmod, substitute /insmod mydir/wacom/wacom.o/ where you see
+/modprobe wacom/ below. It is important that you use the correct wacom.o
+file, the one you just built, since insmod may load the old driver if it
+cannot find the one you have specified.
+
+I am assuming that you are using a USB device, so you will also need to
+modprobe for usb-uhci. The important features of the stylus are
+available through the Linux event drivers, so load those too. With some
+clever additions to /etc/modules.conf, you can probably have these
+automatically loading for you whenever the tablet is activated. So far,
+I haven't figured out how to make this work reliably, so I've added the
+commands to my /etc/rc.d/rc.local file.
+
+ On Redhat 7.2 and possibly on other older distributions, mousedev
+ and input are not loaded by default. Without them, the wacom driver
+ may fail to load, due to unresolved symbols, and the mouse driver
+ may not receive wacom mouse events, even if loaded afterwards.
+
+[jej@ayukawa usb]# rmmod wacom
+[jej@ayukawa usb]# modprobe usb-uhci
+[jej@ayukawa usb]# modprobe input
+[jej@ayukawa usb]# modprobe mousedev
+[jej@ayukawa usb]# modprobe wacom
+[jej@ayukawa usb]# modprobe evdev
+
+Check the system log for status messages pertaining to the wacom. Here's
+a copy of the messages from my version of the driver.
+
+[jej@ayukawa usb]# grep -i wacom /var/log/messages | tail
+Dec 22 21:23:35 ayukawa kernel: usb.c: registered new driver wacom
+Dec 22 21:23:35 ayukawa kernel: wacom.c: *v1.30-j0.2.0* Vojtech Pavlik <vojtech@suse.cz>
+Dec 22 21:23:35 ayukawa kernel: wacom.c: USB Wacom Graphire and Wacom Intuos tablet driver (MODIFIED)
+
+The original driver was version 1.21.3. This version number is
+1.30-j0.2.0 so the correct driver was loaded.
+
+
+ 3.6 - Testing Tablet Detection
+
+In this section we will plug the tablet into the computer and determine
+which driver, if any, claims control over the tablet. There are at least
+three drivers that are interested: 1) hid.o which may think it is an HID
+device, 2) usbmouse.o which may think it is an HID mouse, and 3) the
+wacom driver which should identify the tablet as its own. Any number of
+problems may be experienced here, so be prepared to spend some time
+looking at the logs. A good way to do this, if you are running X, is to
+open a separate xterm, su to root, and run /tail -f /var/log/messages/.
+The console window will stream anything that is appended to the log.
+
+
+ 3.6.1 - Plug It In
+
+Test the tablet detection by plugging the wacom into the USB port and
+checking /var/log/messages again. You should see a flurry of activity.
+The exact output depends a lot on your particular kernel and distribution.
+
+This is Redhat 8.0 (2.4.18-17.8.0):
+
+[jej@ayukawa usb]# tail /var/log/messages
+Dec 22 21:26:11 ayukawa kernel: hub.c: USB new device connect on bus2/2, assigned device number 2
+Dec 22 21:26:11 ayukawa kernel: *input0: Wacom Intuos2 12x12* on usb2:2.0
+Dec 22 21:26:14 ayukawa /etc/hotplug/usb.agent: Setup wacom hid for USB product 56a/44/115
+Dec 22 21:26:14 ayukawa /etc/hotplug/usb.agent: Setup *mousedev* for USB product 56a/44/115
+
+And here it is again on Redhat 7.2 (2.4.18-17.7.x):
+
+[jej@sasami root]# tail /var/log/messages
+Dec 22 21:28:38 sasami kernel: hub.c: USB new device connect on bus1/1, assigned device number 2
+Dec 22 21:28:38 sasami kernel: *input0: Wacom Intuos2 12x12* on usb1:2.0
+Dec 22 21:28:39 sasami kernel: usb.c: registered new driver hiddev
+Dec 22 21:28:39 sasami kernel: usb.c: registered new driver hid
+Dec 22 21:28:39 sasami kernel: hid-core.c: v1.8.1 Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>
+Dec 22 21:28:39 sasami kernel: hid-core.c: USB HID support drivers
+Dec 22 21:28:39 sasami kernel: mice: *PS/2 mouse* device common for all mice
+
+If all went well like above, the USB device was successfully detected
+and handled by the wacom driver; secondly, it was assigned input0. This
+presumably means that information like pressure and tilt will be
+received on /dev/input/event0. Lastly, the tablet was setup with
+mousedev or the generic PS/2 USB mouse driver, so that information
+should appear on /dev/input/mouse0.
+
+If instead you got any of the following lines in your log, the wacom
+driver /did not get control/. Either hid or usbmouse did.
+
+ *input0,hiddev0: USB HID v1.00 Mouse* [Tablet XD-0608-U] on usb1:5.0
+ *input0: Tablet XD-1212-U* on usb2:2.0
+
+The next section describes what to do if the wacom driver did not get
+control. Otherwise, skip on to Viewing the Raw Data <#viewdata>.
+
+
+ 3.6.2 - Wacom Driver Does Not Get Control
+
+If the wacom driver did not get control, and instead you see "Tablet
+XD-1212-U" or similar in its place, then this section is for you.
+Otherwise, consider yourself lucky and skip on to the next section,
+Viewing the Raw Data <#viewdata>. For the unlucky, there is a good
+possibility that your kernel is slightly out of date and that your
+usbmouse.c and hid-core.c files need some help.
+
+When the Tablet XD-1212-U driver comes up, either usbmouse.o or hid.o
+has discovered your tablet, decided it was an HID device, and grabbed
+it. This is bad news because HID tablets seem to only output relative
+coordinates and nothing about pressure. You are in good company though
+because a number of people have reported this, even on some fairly
+up-to-date distributions. Now let's fix it.
+
+
+ 3.6.3 - Building usbmouse.o and hid.o
+
+In the wacpack-0.2.0.tar.gz </wacom/wacpack-0.2.0.tar.gz> file, you will
+find the 2.4.19 versions of usbmouse.c and hid-core.c files which have
+special exceptions for wacom. These files are not built by default, so
+you will need to reconfigure the package and run make again.
+
+At least one person has reported errors building these files on Debian
+Woody running kernel version 2.4.20. This is not surprising since the
+source code came from 2.4.19, but I will do what I can to get these
+drivers updated in the near future.
+
+[jej@ayukawa wacom]$ ./configure --enable-hid --enable-usbmouse
+...
+ BUILD OPTIONS:
+ hid.o - *yes*
+ usbmouse.o - *yes*
+...
+[jej@ayukawa wacom]$ make
+[jej@ayukawa wacom]$ cd src
+[jej@ayukawa src]$ ls -la hid.o usbmouse.o
+-rw-rw-r-- 1 jej jej 26590 Dec 22 18:56 hid.o
+-rw-rw-r-- 1 jej jej 4848 Dec 22 18:56 usbmouse.o
+
+First off, if the code does not build, and you cannot chase the problem
+down yourself, send me a line. If your kernel is much older than 2.4.18,
+then you may have to resign yourself to the fact that the 2.4.19 drivers
+are not going to work for you. I would recommend upgrading your kernel.
+Some people are already running kernel version 2.4.20 and have
+encountered problems building as well. I will update these drivers to
+2.4.20 as soon as possible.
+
+Rather than copy these files to the kernel modules directory right away,
+it would be wise to test whether they get the job done. We should also
+verify that they load properly.
+
+[jej@ayukawa src]$ su -
+[root@ayukawa root]# cd /home/jej/src/wacom/src
+[root@ayukawa src]# rmmod hid usbmouse wacom
+[root@ayukawa src]# insmod hid.o
+[root@ayukawa src]# insmod usbmouse.o
+[root@ayukawa src]# insmod wacom.o
+
+As for unloading the old drivers, none of them should be busy, but if
+you run into trouble, you can use /lsmod/ to check the dependencies and
+try again. Now let's check how the wacom driver managed:
+
+[jej@ayukawa wacom]# tail -15 /var/log/messages
+Dec 22 21:07:38 ayukawa kernel: usbmouse.c: *mouse_init (MODIFIED DEBUG)*
+Dec 22 21:07:38 ayukawa kernel: usb.c: registered new driver usb_mouse
+Dec 22 21:07:39 ayukawa kernel: hid-core.c: *hid_init (MODIFIED DEBUG)*
+Dec 22 21:07:39 ayukawa kernel: usb.c: registered new driver hiddev
+Dec 22 21:07:39 ayukawa kernel: usb.c: registered new driver hid
+Dec 22 21:07:44 ayukawa kernel: usb.c: registered new driver wacom
+Dec 22 21:07:44 ayukawa kernel: usbmouse.c: *usb_mouse_probe: ignoring wacom*
+Dec 22 21:07:44 ayukawa kernel: input0: *Wacom Intuos2 12x12* on usb2:8.0
+Dec 22 21:07:44 ayukawa kernel: wacom.c: v1.30-j0.2.0 Vojtech Pavlik <vojtech@suse.cz>
+Dec 22 21:07:44 ayukawa kernel: wacom.c: USB Wacom Graphire and Wacom Intuos tablet driver *(MODIFIED-DEBUG)*
+
+If everything is working correctly, the log should look similar to the
+lines above. I removed some of the extraneous information, so if you
+have more than this, you should be fine. The most important thing here
+is that the usb_mouse_probe detected and ignored the wacom. It actually
+gets several shots at it, but I removed the redundant lines. For the
+final test, unplug and replug the tablet. Now check the log. The wacom
+driver should be calling the shots from here on out.
+
+If all is well, and you are installing modules rather than /insmod/'ing
+them as you go, then now is the time to copy the usbmouse.o and hid.o
+drivers to their proper places in the kernel modules directory. As
+before with some other distributions, if the files in the kernel module
+directory are compressed, you'll need to run gzip on the .o files to get
+.o.gz files. Use /locate/ as you did for the wacom.o file if necessary
+and don't forget to backup the originals.
+
+
+ 3.6.4 - More about hid.o
+
+Incidentally, the hid.o file may not be necessary, but I've included the
+source to build it anyway because hid-core.c contains a lot of wacom
+related code. If the hid.o driver gets called upon to control the wacom,
+and it is compiled in debug mode, you may see a line similar to the
+following in the log:
+
+Dec 22 21:11:44 ayukawa kernel: usb_hid_configure: configuring device 56A.44 (WACOM), quirk is 4 (IGNORE)
+
+If you get this message, but with a different quirk, or if the wacom
+driver still is not getting control by this point, there is a
+possibility that your tablet is not listed in any of the driver files.
+If so, continue on to the next section. Otherwise, if you are up and
+running, skip to Viewing the Raw Data <#viewdata>.
+
+
+ 3.6.5 - Unknown Tablet?
+
+To determine whether your device is listed in the driver, we need to
+determine the device identifier. It can be discovered by doing the
+following:
+
+[root@ayukawa root]# grep -i 56a /var/log/messages | tail -10
+Dec 22 21:03:09 ayukawa /etc/hotplug/usb.agent: Setup mousedev for USB product *56a/44/115*
+Dec 22 21:27:48 ayukawa kernel: usb.c: USB device 2 (vend/prod *0x56a/0x44*) is not claimed by any active driver.
+
+In this case, the tablet identifier is 56a/44 (also written 0x56a/0x44).
+The model is determined by the second number; the Intuos2 12x12 is 0x44
+for instance.
+
+In the wacom.c file, you will find a table called "wacom_ids." Look for
+your device identifier. Only the identifiers listed are handled by the
+wacom driver, so if it is missing, it needs to be added. Also look in
+hid-core.c. It has a table called "hid_blacklist" which identifies
+devices to ignore. The code is a little strange, but PENPARTNER is 0x00,
+GRAPHIRE is 0x10, INTUOS is 0x20, PL is 0x30, and INTUOS2 is 0x40. A
+table entry like INTUOS2 + 4 would therefore be 0x44.
+
+If you've gotten this far, and still cannot get it to work, send me
+email with your device identifier and as much of an explanation of where
+things did and did not work as described. I'll see what I can do about
+at least finding out why it did not work. Then we can go on to solutions.
+
+The next section assumes you have things working up to this point.
+
+
+ 3.7 - Viewing the Raw Data
+
+View the raw data from the tablet, by returning to the /dev/input
+directory and streaming the data directly from the device. Be patient
+here because this is where a lot of people are getting stuck.
+
+[root@ayukawa usb]# cd /dev/input
+[root@ayukawa input]# xxd event0
+0000000: e65d c33d 597d 0100 0100 4101 0100 0000 .].=Y}....A.....
+0000010: e65d c33d 5c7d 0100 0400 0000 b701 2800 .].=\}........(.
+0000020: e65d c33d d9bb 0100 0100 4101 0000 0000 .].=......A.....
+0000030: e65d c33d dcbb 0100 0400 0000 b701 2800 .].=..........(.
+(Ctrl-C)
+
+First off, you have to move the mouse or tap the pen to get any output.
+Second, you might not get anything at all. Don't panic. This seems to
+happen occasionally. Unfortunately, the work-around is neither
+straightfoward nor foolproof. I am currently talking with Wacom
+developers about this and hopefully we'll get it solved soon.
+
+If absolutely no output occurs, you should check your messages file for
+the following line:
+
+[jej@sasami root]# tail /var/log/messages
+Dec 22 17:31:06 sasami kernel: *wacom_intuos_irq: received unknown report #1*
+Dec 22 17:31:09 sasami last message repeated 195 times
+
+This is a common failure mode of the driver, and I am investigated the
+cause. Each time this has happened to me though, I /have/ been able to
+get it to work. Simply unload and reload the driver.
+
+[jej@sasami root]# rmmod wacom
+[jej@sasami root]# modprobe wacom
+[jej@sasami root]# tail /var/log/messages
+Dec 22 17:31:31 sasami kernel: usb.c: deregistering driver wacom
+Dec 22 17:31:34 sasami kernel: usb.c: registered new driver wacom
+Dec 22 17:31:35 sasami kernel: input0: Wacom Intuos2 12x12 on usb1:2.0
+Dec 22 17:31:35 sasami kernel: wacom.c: v1.30-j0.2.0 Vojtech Pavlik <vojtech@suse.cz>
+
+Apparently, the device driver and the tablet occassionally get out of
+sync with the tablet thinking it's still in HID mode when in fact it
+should be in "mode 2." By unloading and reloading the driver manually,
+the initialization code has another opportunity to get it right. Try the
+/xxd /dev/input/event0/ again. This time, it /should/ work. If not, send
+me some email. I am trying to create a repeatable test case for the
+Wacom developers, and your problem may be just what we need to get this
+bug fixed.
+
+Incidentally, if you have a program running that is connected to
+/dev/input/event0 (like X or wacdump for instance), it is possible that
+the tablet will not reattach back to the same event. I have seen the
+wacom reattach to /dev/input/event1 when unloading and reloading the
+wacom driver with wacdump running for instance.
+
+You should also try running /xxd/ on /dev/input/mouse0. You should get
+streams of data when the mouse and pen are moved around the surface of
+the tablet. It is this device that X will look at for mouse movement.
+Use Ctrl-C to exit xxd.
+
+
+ 4.0 - wacdump
+
+wacdump.c parses and displays the raw event output. You must be root to
+run it unless you've set the permissions on /dev/input/event0 such that
+you can read it. This program can run simultaneously with X, but it's
+best if X has not be configured for the tablet yet. wacdump is enabled
+by default in the configure script, so it should be built automatically
+when you run /make/.
+
+The command line usage of wacdump (wacpack-0.2.0) is pretty simple:
+
+Usage: wacdump [-d device]
+ -?, -h, --help - usage
+ -d, --device device - use specified device
+
+If you know that the tablet is attached to a device other than
+/dev/input/event0, you can override it with the -d option, but
+otherwise, the default is correct. If you connect the /dev/input/event0
+and get an end-of-file error, then the wacom is probably attached to a
+different event.
+
+When you run wacdump, nothing will happen until you place a mouse or pen
+near the surface. After that, the screen will clear and you will see a
+screen similar to the following output:
+
+Wacom Intuos2 12x12 bus=3, vndr=56A, prd=44, ver=115
+
+ KEY=00000000.00000000 0000 0000 00000000
+ ABS=00000000.00000000 0000 0000 00000000
+ MSC=3DD488B5.0000F385 0004 0000 0028102E
+
+ X=+17623 (+00000 .. +30480) Y=+10730 (+00000 .. +31680)
+ RZ=-00058 (-00900 .. +00899) THROTTLE=+00000 (-01023 .. +01023)
+ WHEEL=+00000 (+00000 .. +01023) PRESSURE=+00005 (+00000 .. +01023)
+DISTANCE=+00007 (+00000 .. +00015) TILT_X=+00094 (+00000 .. +00127)
+ TILT_Y=+00122 (+00000 .. +00127)
+
+ WHEEL=+00000
+ SERIAL=0028102E
+
+ LEFT= RIGHT= MIDDLE= SIDE=
+ EXTRA= PEN= RUBBER= BRUSH=
+ PENCIL= AIR= MOUSE= LENS=
+ TOUCH= STYLUS= STYLUS2=
+
+This output comes from version 0.3.2 of the wacdump program.
+
+The first row displays the model number, vendor id, product id, and
+revision number.
+
+The next block shows events as they arrive. Only the event types that
+the device claims to generate are displayed. The quickly changing
+numbers are timestamps.
+
+The middle block shows absolute positions of various device parameters.
+It also shows the ranges that the device claims to provide. If your
+device exceeds these ranges, please let me know so I can fix the driver.
+All the available positions are displayed, even though some of them are
+not available for certain pointers. Different tablets will have
+different capabilities; these are capabilities registered specifically
+for your tablet by the wacom.o kernel driver.
+
+The second WHEEL value is from the relative events channel. Presently,
+only the beta drivers report relative events.
+
+The serial number of the current stylus is displayed next. When two
+pointers are present, the serial number will alternate. This is
+especially true of Intuos2 models and possibly less accurate of other
+models.
+
+Lastly, the button positions are displayed. Some mice have more buttons
+than others; the ones displayed are the ones that the tablet offers.
+Buttons like "Pen" or "Airbrush" are displayed as "Down" when the tool
+is in proximity to the surface.
+
+Whenever you are curious if the device is working properly, wacdump is a
+useful tool for determine exactly what is coming from the tablet. You
+can run it in conjunction with X or without. The display is constrained
+to 80x25 so it can also be used on the main console terminal.
+
+
+ 5.0 - Configuring X11
+
+Two steps must be completed to get X to recognize the Wacom. First, you
+need to add some lines to XF86Config to inform X of the tablet's
+existence. Second, you need to update the XInput driver that pertains to
+the Wacom since the one that ships with XFree86 is not very functional.
+Neither driver holds a candle to the windows driver though, so you'll
+have to take what you get for the time being. Updates to the XFree86
+driver are available in the stable and beta releases on the Downloading
+the Code <#download> page. You may also check Lepied's Wacom Site
+<http://people.mandrakesoft.com/~flepied/projects/wacom/> which has
+source code up to version 26 as of this writing.
+
+
+ 5.1 - Adding the InputDevices
+
+The X Window system identifies the stylus and eraser on your tablet as
+XInput devices. Applications that want to know the absolute position of
+your stylus can request that information directly, and this generally
+bypasses whatever the mouse happens to be doing at the time. This design
+is not without problems though. For one, changing your setup or adding a
+new tool requires making changes to the XF86Config file and restarting
+X. This should be fixed in the future.
+
+For now however, add the InputDevice sections to your XF86Config file.
+This assumes you are running XFree86 4.x. On some distributions, this
+file is called XF86Config-4.
+
+Section "InputDevice"
+ Driver "wacom"
+ Identifier "cursor"
+ Option "Device" "/dev/input/event0"
+ Option "Type" "cursor"
+ Option "Mode" "relative"
+ Option "USB" "on"
+ Option "Speed" "3.0"
+ *Option "Threshold" "10"*
+EndSection
+
+Section "InputDevice"
+ Driver "wacom"
+ Identifier "stylus"
+ Option "Device" "/dev/input/event0"
+ Option "Type" "stylus"
+ Option "Mode" "absolute"
+ Option "USB" "on"
+ Option "Tilt" "on"
+ #Option "TiltInvert" "on"
+ *Option "Threshold" "10"*
+EndSection
+
+Section "InputDevice"
+ Driver "wacom"
+ Identifier "eraser"
+ Option "Device" "/dev/input/event0"
+ Option "Type" "eraser"
+ Option "Mode" "absolute"
+ Option "USB" "on"
+ Option "Tilt" "on"
+ #Option "TiltInvert" "on"
+ *Option "Threshold" "10"*
+EndSection
+
+#Section "InputDevice"
+# Driver "wacom"
+# Identifier "tablet"
+# Option "Device" "/dev/input/event0"
+# Option "Type" "beta"
+#EndSection
+
+The first three sections identify the cursor, stylus, and eraser devices
+to XInput. Notice that all three reference /dev/input/event0.
+Additionally, the TiltInvert option has been commented out. You may want
+to experiment with these values.
+
+The fourth InputDevice section is for the new beta driver. Unless you
+are actually testing this code, I do not recommend using this section,
+at least not at present. There is no harm in leaving it in the file,
+commented in or out, just so long as it is not used in the ServerLayout
+section described later.
+
+*The threshold value is very important.* Various wacom tablets behave
+differently in terms of how the "TOUCH" event is detected. On some
+tablets, the device itself makes the determination, and on others, the
+driver detects the event by examining the pressure value. To make
+matters more complex, the ranges are all different so what is good for
+my Intous2 may not be good for your Graphire. I am providing a default
+value of 10. If the pressure exceeds that value, a "TOUCH" event is sent
+to the XInput system. If this is too hard, you may want to reduce it. If
+the value is too low, you will encounter the reviled "spurious touch"
+problem where the stylus clicks randomly as you move it around the screen.
+
+Also, people using serial tablets will need completely different
+settings. Please see Lepied's Wacom Site
+<http://people.mandrakesoft.com/~flepied/projects/wacom/> for more details.
+
+I am including a copy of the man page for the driver. Some of the fields
+pertain only to the serial device, and some of the fields may be
+deprecated under XFree86 4.2.0. Try them out, see what happens.
+
+WACOM(4x) XFree86 WACOM(4x)
+
+NAME
+ wacom - Wacom input driver
+
+SYNOPSIS
+ Section "InputDevice"
+ Identifier "idevname"
+ Driver "wacom"
+ Option "Device" "devpath"
+ ...
+ EndSection
+
+DESCRIPTION
+ wacom is an XFree86 input driver for Wacom devices.
+
+ The wacom driver functions as a pointer input device, and may be used
+ as the X server's core pointer.
+
+SUPPORTED HARDWARE
+ This driver supports the Wacom IV and Wacom V protocols. Preliminary
+ support is available for USB devices on some Linux platforms.
+
+CONFIGURATION DETAILS
+ Please refer to XF86Config(5x) 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.
+
+ Multiple instances of the Wacom devices can cohabit. It can be useful
+ to define multiple devices with different active zones. Each device
+ supports the following entries:
+
+ Option "Type" "stylus"|"eraser"|"cursor"
+ sets the type of tool the device represent. This option is
+ mandatory.
+
+ Option "Device" "path"
+ sets the path to the special file which represents serial
+ line where the tablet is plugged. You have to specify it
+ for each subsection with the same value if you want to have
+ multiple devices with the same tablet. This option is
+ mandatory.
+
+ Option "USB" "on"
+ tells the driver to dialog with the tablet the USB way.
+ This option is only available on some Linux platforms.
+
+ Option "DeviceName" "name"
+ sets the name of the X device.
+
+ Option "Suppress" "Inumber"
+ sets the position increment under which not to transmit
+ coordinates. This entry must be specified only in the
+ first Wacom subsection if you have multiple devices for one
+ tablet. If you don??t specify this entry, the default value
+ is computed to
+
+ Option "Mode" "Relative"|"Absolute"
+ sets the mode of the device.
+
+ Option "Tilt" "on"
+ enables tilt report if your tablet supports it (ROM version
+ 1.4 and above). If this is enabled, multiple devices at
+ the same time will not be reported.
+
+ Option "HistorySize" "number"
+ sets the motion history size. By default the value is zero.
+
+ Option "AlwaysCore" "on"
+ enables the sharing of the core pointer. When this feature
+ is enabled, the device will take control of the core
+ pointer (and thus will emit core events) and at the same
+ time will be able, when asked so, to report extended
+ events. You can use the last available integer feedback to
+ control this feature. When the value of the feedback is
+ zero, the feature is disabled. The feature is enabled for
+ any other value.
+
+ Option "TopX" "number"
+ X coordinate of the top corner of the active zone.
+
+ Option "TopY" "number"
+ Y coordinate of the top corner of the active zone.
+
+ Option "BottomX" "Inumber"
+ X coordinate of the bottom corner of the active zone.
+
+ Option "BottomY" "number"
+ Y coordinate of the bottom corner of the active zone.
+
+ Option "KeepShape" "on"
+ When this option is enabled, the active zone begins
+ according to TopX and TopY. The bottom corner is adjusted
+ to keep the ratio width/height of the active zone the same
+ as the screen while maximizing the area described by TopX,
+ TopY, BottomX, BottomY.
+
+
+ Option "DebugLevel" number
+ sets the level of debugging info reported.
+
+ Option "BaudRate" "38400", "19200" or "9600" (default)
+ changes the serial link speed. This option is only avail??
+ able for wacom V models (Intuos).
+
+ Option "Serial" "number"
+ sets the serial number associated with the physical device.
+ This allows to have multiple devices of the same type (i.e.
+ multiple pens). This option is only available on wacom V
+ devices (Intuos). To see which serial number belongs to a
+ device, you have to set the DebugLevel to 6 and watch the
+ output of the X server.
+
+ Option "Threshold" "number"
+ sets the pressure threshold used to generate a button 1
+ events of stylus devices for some models of tablets (Intuos
+ and Graphire).
+
+SEE ALSO
+ XFree86(1), XF86Config(5x), xf86config(1), Xserver(1), X(7x).
+
+AUTHORS
+ Frederic Lepied <lepied@xfree86.org>
+
+4.2.0 Version WACOM(4x)
+
+
+ 5.2 - Mouse1
+
+Adding the Mouse1 device is /probably not something you want to do/, and
+Redhat's Anaconda program will do it for you if you boot the machine
+with the tablet plugged in. You'll need to be careful about this.
+
+When you use the mouse1 input device, the data flows from the wacom
+kernel driver, through the event subsystem, down into the mousedev
+driver, out the /dev/input/mouse0 device, and finally into the XInput
+mouse driver. You effectively lose all your absolute positioning
+information because the mousedev driver converts it into relative data.
+Additionally, the XFree86 wacom driver does not get control of the
+cursor because mouse1 is providing those events.
+
+Therefore, if you have a Mouse1 section, leave it. Redhat 8.0 at least,
+expects it to be there; however, you will not be using it, so make
+certain that it is commented out of the section covered next.
+
+
+ 5.3 - ServerLayout
+
+The ServerLayout section describes what devices the X server will use.
+Modify the ServerLayout section to reflect the new devices. Make certain
+to comment out the Mouse1 device.
+
+Section "ServerLayout"
+ Screen 0 "Screen0" 0 0
+ InputDevice "Mouse0" "CorePointer"
+ InputDevice "Keyboard0" "CoreKeyboard"
+ *InputDevice "cursor" "SendCoreEvents"
+ InputDevice "stylus" "SendCoreEvents"
+ InputDevice "eraser" "SendCoreEvents"*
+ #InputDevice "Mouse1" "SendCoreEvents"
+ #InputDevice "tablet" "SendCoreEvents"
+EndSection
+
+This section determines which devices are actually used by the server.
+In the case above, the cursor, stylus, and eraser devices are selected
+while the mouse1 and tablet devices are commented out. At present, this
+is the correct configuration for proper operation of the tablet whether
+you are using the beta package or the production package.
+
+The new wacom_drv.o driver contains two independent implementations of
+the tablet code. Using the "tablet" device instead of the
+cursor/stylus/eraser devices will enable that code. Presently, that will
+do little for you since the code is fairly volatile and is simply a
+testbed for various design ideas. As it becomes more useful, I will
+update this section.
+
+You have completed the XF86Config file changes. By aware that if you
+reboot your computer with the Wacom plugged in and Redhat's Anaconda
+program notices, it will treat the tablet as a USB mouse and reconfigure
+this file incorrectly. You may need to go back and check the file to
+ensure that everything is still correct afterwards. Rebooting with the
+device detached seems to reverse the process, but again, you should
+check the file to be certain. My recommendation is to tell Anaconda to
+ignore the tablet until the device detection works properly.
+
+
+ 5.4 - Updating wacom_drv.o
+
+There are a number of wacom_drv.o files about. XFree86 is shipping
+version 23. Redhat 8.0 is shipping version 25. Lepied's page has the
+source code for 26, but the binary identifies itself as 23ss1. The
+Downloading the Code <#download> page currently offers source and binary
+for 26-j0.2.0 in the stable package and 26-j0.3.2a in the beta version.
+In total, I recommend using the drivers in the packages that I provide
+since they correspond with what is shown in this document. Any new
+functionality that gets added will be built on top of these files as well.
+
+Note: the binary wacom_drv.o file is located in the prebuilt directory
+of the stable and beta packages. Building this file from source (which
+is provided) is a major hassle, and I do not recommend it unless you are
+developer yourself or the binary is simply not compatible with your
+system. Instructions for rebuilding from source are available in the
+Appendix under Building wacom_drv.o From Scratch <#builddrv>.
+
+With that said, locate and replace wacom_drv.o. Using /locate/ again, we
+find the driver in the X11 tree. This directory is pretty standard, so
+it is unlikely that your file will be located elsewhere. Note the
+assumption is that you are using XFree86 4.x. Anything from the 3.x
+version probably won't work.
+
+[root@ayukawa root]# locate wacom_drv.o
+/usr/X11R6/lib/modules/input/*wacom_drv.o*
+[root@ayukawa root]# cd /usr/X11R6/lib/modules/input
+[root@ayukawa input]# cp *wacom_drv.o* /home/jej/src/wacom/*wacom_drv_old.o*
+[root@ayukawa input]# cp /home/jej/src/wacom/prebuilt/*wacom_drv.o wacom_drv.o*
+
+Again, the old file is copied away, and replaced with the newer version.
+The binary modules are presently built on a Redhat 8.0 system using gcc
+3.2 under glibc. This should work for most, if not all, major
+distributions. If it does not load on yours, please let me know.
+
+
+ 5.5 - Restart X
+
+Finally, restart X. You may wish to do this from runlevel 3 for testing
+purposes.
+
+[root@ayukawa root]# init 3
+...processes starting and stopping...
+[root@ayukawa root]# startx
+
+If the X server dies, you can always back-out the changes to the
+XF86Config file and try again. Worse case, copy the wacom_drv_old.o file
+back to its original place. But first, look at the XFree86 log file for
+clues. You might want to do this even if everything works correctly.
+When things are running right, the following lines appear in my log file.
+
+[root@ayukawa root]# grep -i wacom /var/log/XFree86.0.log
+(II) LoadModule: "wacom"
+(II) Loading /usr/X11R6/lib/modules/input/wacom_drv.o
+(II) Module wacom: vendor="The XFree86 Project"
+(II) Wacom driver level: *26-j0.2.0* $
+(II) XINPUT: Adding extended input device "eraser" (type: Wacom Eraser)
+(II) XINPUT: Adding extended input device "stylus" (type: Wacom Stylus)
+(II) XINPUT: Adding extended input device "cursor" (type: Wacom Cursor)
+(==) Wacom Kernel Input device name: "Wacom Intuos2 12x12"
+(==) Wacom tablet maximum X=30480 maximum Y=30480 X resolution=0 Y resolution=0
+suppress=0
+(==) Wacom Cursor top X=0 top Y=0 bottom X=30480 bottom Y=30480
+(==) Wacom Stylus top X=0 top Y=0 bottom X=30480 bottom Y=30480
+(==) Wacom Eraser top X=0 top Y=0 bottom X=30480 bottom Y=30480
+
+Notice the driver version 26-j0.2.0 above. This is the new stable
+wacom_drv.o driver. The beta driver is currently 26-j0.3.2a.
+
+First things first, you should lift the mouse off the tablet and place
+it back down. This seems to help reset things internally. When you
+replace the mouse, the cursor should jump to that portion of the screen.
+If everything is working correctly, the mouse should work in absolute
+mode with the four corners of the tablet corresponding with the four
+corners of the screen. If the cursor stops short of an edge, then the
+kernel driver limits are probably incorrect. Please let me know so that
+I can update the driver.
+
+Next, remove the mouse and try using the eraser end of the stylus.
+Hovering over the surface of the tablet should move the cursor. Touching
+the eraser tip to the surface should generate a click. If you invert the
+pen and use the stylus tip, you should get a similar result. If the pen
+tip generates spurious touch events, you will need to increase the
+threshold value in the InputDevice section. Wacdump is useful for
+determining the appropriate value. My pen pressure oscillates between 0
+and 6 so I use a threshold of 10 to compensate.
+
+
+ 5.6 - Check the Pointer Status
+
+You can check the XInput pointer status by using /xsetpointer/ as below.
+The man page states that calling xsetpointer with the name of a
+particular device will set it as the primary pointing device. So far,
+that has not been the case in my experience; however, that is the
+subject of current development, so try it, and if it doesn't work, stay
+tuned.
+
+[root@ayukawa log]# xsetpointer -l
+"eraser" [XExtensionDevice]
+"stylus" [XExtensionDevice]
+"cursor" [XExtensionDevice]
+"Mouse0" [XPointer]
+"keyboard" [XKeyboard]
+
+
+ 6.0 - Working With Gimp
+
+It has been suggested that gimp should be recompiled from source
+(v1.2.3) on Mandrake 9.0. This does not seem to be true for Redhat 8.0.
+
+Bring up /gimp/ and select "File|Dialogs|Input Devices". You will see a
+drop-down list with all three devices present. After enabling them, you
+can see their respective statuses by calling up "File|Dialogs|Device
+Status". It has been recommended that the devices be set to "Screen"
+mode rather than "Window."
+
+I have successfully been able to use gimp with several different pens,
+including the tips and erasers. Tilt does not appear to be used by gimp
+at present, but pressure works fine.
+
+
+ 7.0 - Changelog
+
+ * 2002-12-22 - John E. Joganic <jej@j-arkadia.com>
+
+ * Added serial code to wacdump
+ * Added serial protocols IV 1.0 - 1.4.
+ * Added serial protocol V 1.0 - 1.1.
+ * Intuos mouse wheels are now positive when rolled backwards
+ per PS/2 Intellimouse convention
+ * Added Intuos2 to xf86Wacom.c
+ * Added build help for Debian Stable users
+
+ * 2002-12-17 - John E. Joganic <jej@j-arkadia.com>
+
+ * Merged code from 2.4.20 hid-core.c
+ * Added configuration code to handle kernels still at 2.4.19
+ * Split wacdump curses code into wacscrn.c to solve namespace
+ collision
+ * Added volito to wacom.c
+
+ * 2002-12-16 - John E. Joganic <jej@j-arkadia.com>
+
+ * House cleaning on the website.
+ * Dropped the Intuos constraint from the document name.
+ * Added the expectations page.
+ * Changed the internal indexing to identifier rather than
+ chapter.
+
+ * 2002-12-15 - John E. Joganic <jej@j-arkadia.com>
+
+ * Removed some debugging code, redeployed package with
+ wacom_drv.o version 0.3.2a.
+ * New build has fix for 4D mouse wheel.
+ * wcm-beta.c fleshed out with new driver code.
+
+ * 2002-12-13 - John E. Joganic <jej@j-arkadia.com>
+
+ * Added development page.
+ * New build has relative events and fix for 2D mouse wheel.
+ * wcm-beta.c added to build.
+
+ * 2002-12-09 - John E. Joganic <jej@j-arkadia.com>
+
+ * Added detail on "Threshold" parameter.
+ * Included man page.
+
+ * 2002-11-24 - John E. Joganic <jej@j-arkadia.com>
+
+ * Updated docs for version 0.2.0.
+ * Package uses configure-based scripts.
+
+ * 2002-11-14 - John E. Joganic <jej@j-arkadia.com>
+
+ * Moved wacom_drv.o to prebuilt directory.
+ * Added xf86Wacom.c (version 26) to package along with changes
+ to Makefile
+ * Extended documentation on X11 setup including caveat over
+ Mouse1 device.
+ * Added xf86Wacom.c build instructions.
+ * Updated wacdump (0.2) to display identifiers, maximum
+ values, and all registered event types.
+ * Added highlighting in wacdump to display button down state.
+
+ * 2002-11-11 - John E. Joganic <jej@j-arkadia.com>
+
+ * wacom.c - fixed ranges for intuos2 6x8
+
+ * 2002-11-10 - John E. Joganic <jej@j-arkadia.com>
+
+ * wacdump.c - updated display to identify values
+ * wacom.c - fixed ranges for intuos2 12x12
+
+ * 2002-11-09 - John E. Joganic <jej@j-arkadia.com>
+
+ * wacom.c - merged some of Cheng's changes, fixes to the
+ pressure calculation, device ranges.
+ * wacom.c - added an extra device (0x47) for M. T.
+ * wacdump.c - added text messages for event types
+ * wacdump.c - added usage and device override option
+ * wacdump.c - exits when channel is closed.
+ * Fixed module dependency problem in wacom.o and hid.o
+ * Added clarification for devfs and Mandrake 9.0
+
+ * 2002-11-06 - John E. Joganic <jej@j-arkadia.com>
+
+ * Busted page out into discrete chapters.
+ * Added some php magic to turn it into an active book.
+ * Added Mandrake 9.0
+ * Gimp may need to be compiled from source (1.2.3)
+
+ * 2002-11-05 - John E. Joganic <jej@j-arkadia.com>
+
+ * Updated wacom driver with Christer Nilsson's 2.4.20 patch
+ * Added RedHat 7.3 success
+ * Added more discussion on the device driver election.
+ * Added more discussion on HID mode 1 and the correct mode 2.
+ * Added usbmouse.c and hid-core.c to wacpack-0.1b.
+
+ * 2002-11-04 - John E. Joganic <jej@j-arkadia.com>
+
+ * Added update section.
+ * Added success stories.
+ * Added RedHat 7.2 specific information
+ * Added more information about "unknown report #1"
+
+
+ 8.0 - Contacts
+
+John Joganic can be contacted at the following email address:
+jej@j-arkadia.com <mailto: jej@j-arkadia.com?SUBJECT=WACOM>. If at all
+possible, please include the word "WACOM" in the subject line. I receive
+hundreds of messages a day, and this little addition will help me find
+your message in the tons of spam.
+
+
+ 9.0 - Appendix
+
+This section is for everything that is either not critical or simply too
+complex to describe in the document above without becoming overly
+distracting.
+
+
+ 9.1 - Building wacom_drv.o From Scratch
+
+
+ Introduction
+
+I should tell you out-right that this is an ugly, time consuming
+process. If you manage to get this working in fewer steps, by all means,
+let me know.
+
+Why would you want to do this? Two reasons. One, you are a developer and
+need to make changes to the source code directly. Two, your distribution
+uses c libraries or configuration options that are not compatible with
+the wacom_drv.o file that I provide. People running libc5 for instance,
+would need to build their own driver.
+
+ Timothy Klein has submitted a brief howto for compiling on Debian
+ Stable which is still running XFree86 4.1 as of this writing. It
+ covers steps one through four of this document, and a savvy
+ developer should be able to figure out step five on his own. If
+ someone solves step five and generates a patch to Makefile.am, I'll
+ see what I can do about getting it into the configuration script.
+ That document is on the Building wacom_drv.o On Debian Stable
+ <#debwcmdrv> page.
+
+You will need the X source code to rebuild the wacom_drv.o driver. The
+build configuration for X generates a number of header files that are
+necessary but not installed by default on most distributions.
+Consequently, you will need to not only get the source, but build it,
+practically in its entirety. Then, after all that, the configure script
+can be instructed to hook into the X build tree and rebuild xf86Wacom.c
+at any time without having to rebuild X again.
+
+Since I am running Redhat 8.0 and cannot really pull down the original
+XFree86 4.2.0 source code, compile it, and expect it to work on my
+system, I need to instead use the source RPM provided by Redhat. If you
+choose to go this route, I provide pretty detailed instructions for
+making this work. If your distribution works differently, or you are
+using Gentoo where most everything is source code by default, you'll
+need to handle this as best as possible according to your particular
+situation.
+
+
+ Step One: Get The Source
+
+On Redhat 8.0, I discovered the version number for my currently
+installed XFree86 packages by running /rpm -q XFree86/. This reported
+version 4.2.0-72, therefore the source package is
+XFree86-4.2.0-72.src.rpm. I downloaded the package from Redhat directly
+and installed it to the system as follows:
+
+[root@sen src]# rpm -ivh XFree86-4.2.0-72.src.rpm
+ 1:XFree86 ########################################### [100%]
+
+This installs a number of files to the /usr/src/redhat directory,
+particularly in the SOURCES and SPECS subdirectories. Other
+distributions undoubtedly install elsewhere. Look for the XFree86.spec
+file which should be located in the SPECS directory. This file contains
+all the information necessary to patch the orginal XFree86-4.2.0 source
+code to the level that Redhat is distributing in their regular binary
+package. The source code and patch files are located in SOURCES.
+
+
+ Step Two: Build the Source
+
+This step describes how to build the source from the RPM itself. If you
+are building from some other mechanism, I honestly cannot offer much
+assistance since I generally don't build my X system from scratch. If
+you'd like to write up a short section on building the server for your
+particular distribution, I would be happy to include it here.
+
+Next, you don't actually have to build the entire thing. The point at
+which the xf86Wacom.c driver can be built however, is not until
+somewhere in the middle of the build process. The driver depends on a
+number of header files that are created dynamically so until they are
+generated, wacom_drv.o cannot be compiled. My solution was to open a
+separate terminal in the wacom driver directory and periodically attempt
+to build it. When it successfully built, I stopped the X build process.
+Here's how to build the source for an RPM that's been exploded out into
+the SPECS and SOURCES directories.
+
+[root@sen root]# cd /usr/src/redhat
+[root@sen redhat]# rpmbuild -bc SPECS/XFree86.spec
+
+Not every distribution has /rpmbuild/; try using just /rpm/ instead. At
+some point, Redhat split the build functionality into separate programs.
+If after looking through the /rpm/ man page, you still cannot get this
+to work, send me some email, and I'll look into it.
+
+The important item is the "-bc" option of /rpmbuild/ which unpacks,
+patches, and builds the source without actually installing. While it is
+also possible to simply unpack and patch using the "-bp" option, there
+does not seem to be a way to just build. The "-bc" option simply deletes
+all the files provided by "-bp" and recreates them again. The downside
+of this is that if you wanted to simply unpack, patch, and then copy the
+new xf86Wacom.c file over the old one, you'll find that the build step
+deletes it and starts over again. I have gotten this to work by creating
+a new patch file, but this requires a bit more effort, so I don't
+recommend it right off.
+
+
+ Step Three: Build the Original Driver
+
+The xf86Wacom.c file is buried pretty deep in the X build tree. If it is
+in a different location than the one I have provided below, try using
+/find . -name xf86Wacom.c/ from the BUILD directory.
+
+[root@sen redhat]# cd BUILD/XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/input/wacom
+[root@sen wacom]# ls
+Imakefile wacom.man xf86Wacom.c.Wacom-USB-driver-a25-update
+Makefile xf86Wacom.c
+
+The "a25-update" file is the original xf86Wacom.c file before Redhat's
+patch. If you open xf86Wacom.c, you'll find that it is version 25, at
+least as of this writing and this distribution. The presence of the
+Makefile means that the configuration has at least been run for this
+directory. If you have built a sufficient portion of the X source files,
+then all the header files that you need have been generated, and you can
+build xf86Wacom.c. Try it, and if it does not build, wait a bit. The
+absence of xf86Version.h for instance, is a good indication that the
+build process is not ready.
+
+[root@sen wacom]# make
+rm -f xf86Wacom.o
+gcc -O2 -march=i386 ... -c xf86Wacom.c
+rm -f wacom_drv.o
+ld -r xf86Wacom.o -o wacom_drv.o
+
+
+ Step Four: Build the New Driver
+
+With a valid build environment, it should be possible to copy the
+updated driver source over the old one, run /make/, and get an updated
+driver.
+
+ The beta package contains a version xf86Wacom.c that depends on
+ wcm-beta.c and wcm-beta.h. If you are compiling this version, you
+ will need to copy all three files. Secondly, the driver will build
+ and link, but will not be usable since the current X build
+ environment does not expect the wcm-beta code to be compiled. This
+ problem is addressed correctly in the automated build process
+ discussed below.
+
+[root@sen wacom]# cp xf86Wacom.c xf86Wacom_old.c
+[root@sen wacom]# cp /home/jej/src/wacom/src/xf86Wacom.c xf86Wacom.c
+[root@sen wacom]# make
+rm -f xf86Wacom.o
+gcc -O2 -march=i386 ... -c xf86Wacom.c
+rm -f wacom_drv.o
+ld -r xf86Wacom.o -o wacom_drv.o
+
+If the source did not build correctly the second time, it is possible
+that the Imake-based build environment has generated a makefile that
+will not work correctly for the new code. Your options are to generate a
+patch file that can be applied by the build process, hack the makefile
+in the driver directory to work properly, or to find some way to get
+Imake to reconfigure. This is probably less of a hassle for people
+building from source, but to be fair, all the commands and information
+you need to reconfigure from RPM are listed in the beginning of the
+build output. You might also want to continue ahead to see if the
+default build rule does not work for you.
+
+
+ Step Five: Automating the Build Process
+
+Copying the updated source file into the build tree and compiling from
+there is not convenient. By configuring the package with the --with-xf86
+option set to the XFree86 build tree and enabling the driver using the
+--enable-wacomdrv option, you can build the driver outside of the X
+build tree.
+
+[jej@ayukawa wacom]$ ./configure \
+ --with-xf86=/usr/src/redhat/BUILD/XFree86-4.2.0 \
+ --enable-wacomdrv
+...
+BUILD ENVIRONMENT:
+ XFree86 - yes
+ BUILD OPTIONS:
+ wacom_drv.o - yes
+[jej@ayukawa wacom]$ make
+
+The makefile rule which builds the driver is contained within
+src/Makefile.am and is modified according to the configuration to
+generate a rule similar to this in src/Makefile:
+
+xf86Wacom.o: xf86Wacom.c
+ gcc -O2 -march=i386 -mcpu=$(ARCHITECTURE) -pipe -ansi \
+ -pedantic -Wall -Wpointer-arith -fno-merge-constants \
+ -I. -I$(XF86_DIR)/programs/Xserver/hw/xfree86/common \
+ -I$(XF86_DIR)/programs/Xserver/hw/xfree86/loader \
+ -I$(XF86_DIR)/programs/Xserver/hw/xfree86/os-support \
+ -I$(XF86_DIR)/programs/Xserver/include \
+ -I$(XF86_DIR)/programs/Xserver/mi \
+ -I$(XF86_DIR)/exports/include/X11 \
+ -I$(XF86_DIR)/include/extensions \
+ -I$(XF86_DIR) \
+ -I$(XF86_DIR)/exports/include \
+ -Dlinux -D__i386__ -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 -DXF86BIGFONT -DDPMSExtension -DPIXPRIV -DPANORAMIX \
+ -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV \
+ -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER \
+ -DXFree86Server -DXF86VIDMODE -DXvMCExtension \
+ -DSMART_SCHEDULE -DBUILDDEBUG -DXResExtension \
+ -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG -DFUNCPROTO=15 \
+ -DNARROWPROTO -DIN_MODULE -DXFree86Module -DLINUX_INPUT \
+ -o xf86Wacom.o -c xf86Wacom.c
+
+ In the beta package, a similar rule applies to wcm-beta.c.
+
+The options and directories specified come directly from the output of
+the make command in the previous step. All the root and parent
+directories have been replaced with the macro XF86_DIR which in this
+case is set by the configuration script to
+/usr/src/redhat/BUILD/XFree86-4.2.0/xc. If the options that you see in
+your build are identical to those above, then the default rule will work
+for you now. If not, you'll need to make some alterations. You can
+update the Makefile.am file and rerun automake, update the Makefile.in
+and rerun configure, or just update the Makefile directly.
+
+So long as the X build tree exists, the include directories will point
+to the correct locations, and the driver will build. If space is an
+issue, you can probably remove all the non-essential directories, but be
+careful; the dependency tree in X is huge.
+
+
+ Conclusion
+
+Although a bit of a hassle, it is possible to compile the xf86Wacom.c
+file into the wacom_drv.o driver from outside the X build tree. If you
+have any comments, questions, or suggestions regarding this process,
+please send email to jej@j-arkadia.com
+<mailto:jej@j-arkadia.com?SUBJECT=WACOM_DRV> with a subject of "WACOM_DRV".
+
+
+ 9.2 - Building wacom_drv.o On Debian Stable
+
+The following documentation for building wacom_drv.o on Debian Stable
+was written by Timothy Klein. If you have any problems or questions, go
+ahead and post them to the list, or send email to me directly. If I
+cannot provide a satisfactory answer, I'll forward your email on to
+Timothy.
+
+
+
+Just thought I would give you some brief notes on compiling wacom_drv.o
+on Debian Stable. This must be done, as the Stable version of Debian
+has XFree86 v. 4.1.0.1, and your pre-compiled module is for a later
+version of X (4.2?). X complains about the server having ABI 2, and the
+module having ABI 3, and refuses to load. So one must compile the
+wacom_drv.o module for Debian Stable.
+
+The good news is that, while it requires a *huge* download, and takes a
+bit of time, it is easy.
+
+-------------------------------------------------------------
+Debian wacom_drv.o Compilation
+
+*1. Download the Debian source package for XFree86.*
+
+For Debian Stable this is three files:
+
+xfree86_4.1.0-16.diff.gz
+xfree86_4.1.0-16.dsc
+xfree86_4.1.0.orig.tar.gz
+
+Note that these are *big* files. The 'diff' file is 1.5 megabytes, and
+the 'orig' file is 52 megabytes. So if you have a 28.8 modem
+connection, this is going to be painful.
+
+These files can be obtained automatically by using the command:
+
+apt-get source xfree86
+
+It is not necessary to be root to download the source package. After it
+is downloaded, the package will be automatically extracted. Using this
+method requires that you have a valid 'source' line in your
+'/etc/apt/sources.list' file, though.
+
+You can also just download the three packages above from your favorite
+Debian mirror. If you do that, you need to extract them yourself, which
+is done with the following command:
+
+dpkg-source -x xfree86_4.1.0-16.dsc <only for manual download>
+
+Either method will give you a 'xfree86-4.1.0' directory in the download
+directory. For both this step, and the later package creation, you are
+going to need tools from the 'dpkg-dev' package. So install that with
+'apt-get' if you don't already have it installed.
+
+
+
+*2. Make sure you have the requisite build dependencies.*
+
+XFree86 requires certain packages to compile. It seems that 'dpkg' is
+pretty good about telling you what packages it needs if they are not
+installed (probably a nice script included by the Debian X maintainer).
+Thus, you can just try and compile it and see what it complains about
+not having and, at that point, install the needed packages with apt-get.
+The other, cleaner, option is to run:
+
+apt-get build-dep xfree86
+
+This command will attempt to automatically install (or once in a blue
+moon uninstall) all the necessary packages to compile XFree86. You need
+to be 'root' to do this.
+
+
+*3. Begin the Build Process for xfree86*
+
+
+Become 'root' (or you could use fakeroot), and change into the
+'xfree86-4.1.0' directory. Then run:
+
+dpkg-buildpackage
+
+The source will begin to compile. It will take a while. If you have a
+really old machine, like a Pentium 166 or such, go on a vacation. It
+may be done when you return.
+
+
+*4. Recompile the wacom_drv.o module.*
+
+The source you need to replace and recompile will be in the following
+directory:
+
+<download_dir>/xfree86-4.1.0/build-tree/xc/programs/Xserver/hw/xfree86/input/wacom
+
+Replace the 'xf86Wacom.c' file therein with the one provided. While X
+does need to have some configuration done for this to compile, and that
+configuration is accomplished automatically by the build process, it
+does not necessarily need to finish compiling the whole package. So,
+once a 'Makefile' is created automatically by the build scripts in this
+directory, you can attempt to run 'make' from time to time. Once it
+compiles without error, you can halt the very lengthy build process of
+the XFree86 package.
+
+ This may not work with the current beta package since it also
+ contains the wcm-beta.c and wcm-beta.h files. You can solve this by
+ updating the Makefile, or proceed to step five on the Building
+ wacom_drv.o From Scratch <#builddrv> page. The command line options
+ for building the driver will undoubtably have changed, so be
+ prepared to update the Makefile in the wacpack/src directory.
+
+*5. Move the wacom_drv.o module to the proper place.*
+
+That's it. Once the 'make' command compiles without error, you will
+have several new files in the directory. The one we are interested in
+is 'wacom_drv.o.' Now you can just move the 'wacom_drv.o' file to the
+directory:
+
+/usr/X11R6/lib/modules/input/
+
+This will also require 'root' privileges.
+---------------------------------------------------------------------
+
+You may want to add that to you HOWTO, for my fellow Debian users. And
+thanks again for the very nice work on the HOWTO and the drivers.
+
+HTH,
+
+Tim
+
+*Copyright (C) 2002 - John E. Joganic*
+
diff --git a/src/Makefile.am b/src/Makefile.am
index f7753ae..9c902b1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,10 +1,105 @@
-SUBDIRS = . wacomxi util xdrv @WCM_KERNEL_VER@
+noinst_PROGRAMS = @WAC_PROGS@ @WAC_XF86PROGS@
+noinst_SCRIPTS = @WAC_MODULES@ @WAC_XF86MODULES@
-wmanpagedir = @mandir@/man4
-wmanpage_HEADERS = wacom.4x.gz
+AM_CFLAGS = -Wall
-EXTRA_DIST = wacom.4x
+EXTRA_PROGRAMS = wacdump
+EXTRA_SCRIPTS = wacom.o hid.o usbmouse.o wacom_drv.o
+
+wacdump_SOURCES = wacdump.c wacscrn.c wacscrn.h wacserial.c wacserial.h
+wacdump_LDADD = -lncurses
+EXTRA_DIST = wacom.c hid-core.c hid-input.c hiddev.c xf86Wacom.c usbmouse.c \
+ wcm-beta.c wcm-beta.h
+
+KERNEL_DIR=@WAC_KERNELDIR@
+XF86_DIR=@WAC_XF86DIR@/xc
+DEBUG_FLAGS = -D__JEJ_DEBUG
+MODS = @WAC_MODVER@
+ARCHITECTURE=@WAC_ARCH@
+USBDIR=$(KERNEL_DIR)/drivers/usb
+KCFLAGS = -Wall $(DEBUG_FLAGS) -D__KERNEL__ \
+ -DMODULE -DEXPORT_SYMTAB $(MODS) \
+ -Wstrict-prototypes -Wno-trigraphs -O2 \
+ -fno-strict-aliasing \
+ -fno-common -fomit-frame-pointer -pipe \
+ -mpreferred-stack-boundary=2 \
+ -march=$(ARCHITECTURE)
+
+wacom.o: wacom.c Makefile
+ gcc -I$(KERNEL_DIR)/include $(KCFLAGS) \
+ -DKBUILD_BASENAME=wacom -c -o wacom.o wacom.c
+
+HID_OBJS = hid-core.o hiddev.o hid-input.o
+
+hid.o: $(HID_OBJS) Makefile
+ $(LD) -r -o $@ $(HID_OBJS)
+
+hid-core.o: hid-core.c Makefile
+ gcc -I$(KERNEL_DIR)/include -I$(USBDIR) $(KCFLAGS) \
+ -DKBUILD_BASENAME=hid-core -c -o hid-core.o hid-core.c
+
+hiddev.o: $(USBDIR)/hiddev.c Makefile
+ gcc -I$(KERNEL_DIR)/include -I$(USBDIR) $(KCFLAGS) \
+ -DKBUILD_BASENAME=hiddev -c -o hiddev.o hiddev.c
+
+hid-input.o: $(USBDIR)/hid-input.c Makefile
+ gcc -I$(KERNEL_DIR)/include -I$(USBDIR) $(KCFLAGS) \
+ -DKBUILD_BASENAME=hid-input -c \
+ -o hid-input.o hid-input.c
+
+usbmouse.o: usbmouse.c Makefile
+ gcc -I$(KERNEL_DIR)/include -I$(USBDIR) $(KCFLAGS) \
+ -DKBUILD_BASENAME=usbmouse -c \
+ -o usbmouse.o usbmouse.c
+
+xf86Wacom.o: xf86Wacom.c wcm-beta.h Makefile
+ gcc -O2 -march=i386 -mcpu=$(ARCHITECTURE) -pipe -ansi \
+ -pedantic -Wall -Wpointer-arith -fno-merge-constants \
+ -I. -I$(XF86_DIR)/programs/Xserver/hw/xfree86/common \
+ -I$(XF86_DIR)/programs/Xserver/hw/xfree86/loader \
+ -I$(XF86_DIR)/programs/Xserver/hw/xfree86/os-support \
+ -I$(XF86_DIR)/programs/Xserver/include \
+ -I$(XF86_DIR)/programs/Xserver/mi \
+ -I$(XF86_DIR)/exports/include/X11 \
+ -I$(XF86_DIR)/include/extensions \
+ -I$(XF86_DIR) \
+ -I$(XF86_DIR)/exports/include \
+ -Dlinux -D__i386__ -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 -DXF86BIGFONT -DDPMSExtension -DPIXPRIV -DPANORAMIX \
+ -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV \
+ -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER \
+ -DXFree86Server -DXF86VIDMODE -DXvMCExtension \
+ -DSMART_SCHEDULE -DBUILDDEBUG -DXResExtension \
+ -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG -DFUNCPROTO=15 \
+ -DNARROWPROTO -DIN_MODULE -DXFree86Module -DLINUX_INPUT \
+ -o xf86Wacom.o -c xf86Wacom.c
+
+wcm-beta.o: wcm-beta.c wcm-beta.h Makefile
+ gcc -O2 -march=i386 -mcpu=$(ARCHITECTURE) -pipe -ansi \
+ -pedantic -Wall -Wpointer-arith -fno-merge-constants \
+ -I. -I$(XF86_DIR)/programs/Xserver/hw/xfree86/common \
+ -I$(XF86_DIR)/programs/Xserver/hw/xfree86/loader \
+ -I$(XF86_DIR)/programs/Xserver/hw/xfree86/os-support \
+ -I$(XF86_DIR)/programs/Xserver/include \
+ -I$(XF86_DIR)/programs/Xserver/mi \
+ -I$(XF86_DIR)/exports/include/X11 \
+ -I$(XF86_DIR)/include/extensions \
+ -I$(XF86_DIR) \
+ -I$(XF86_DIR)/exports/include \
+ -Dlinux -D__i386__ -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 -DXF86BIGFONT -DDPMSExtension -DPIXPRIV -DPANORAMIX \
+ -DRENDER -DGCCUSESGAS -DAVOID_GLYPHBLT -DPIXPRIV \
+ -DSINGLEDEPTH -DXFreeXDGA -DXvExtension -DXFree86LOADER \
+ -DXFree86Server -DXF86VIDMODE -DXvMCExtension \
+ -DSMART_SCHEDULE -DBUILDDEBUG -DXResExtension \
+ -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DNDEBUG -DFUNCPROTO=15 \
+ -DNARROWPROTO -DIN_MODULE -DXFree86Module -DLINUX_INPUT \
+ -o wcm-beta.o -c wcm-beta.c
+
+wacom_drv.o: xf86Wacom.o wcm-beta.o
+ ld -r xf86Wacom.o wcm-beta.o -o wacom_drv.o
-$(wmanpage_HEADERS): $(EXTRA_DIST)
- rm -f $(wmanpage_HEADERS)
- gzip -9c < $(srcdir)/$(EXTRA_DIST) > $(wmanpage_HEADERS)
diff --git a/src/hid-core.c b/src/hid-core.c
new file mode 100644
index 0000000..5ef2645
--- /dev/null
+++ b/src/hid-core.c
@@ -0,0 +1,1386 @@
+/*
+ * $Id: hid-core.c,v 1.1.1.1 2002/12/23 02:44:43 jjoganic Exp $
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ * USB HID support for Linux
+ *
+ * Sponsored by SuSE
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include "../config.h"
+
+/*
+ * WARNING: THIS IS NOT PART OF THE OFFICIAL KERNEL TREE
+ * THIS IS FOR TESTING PURPOSES
+ *
+ * v1.8.1-j0 - merged changes from 2.4.20 with conditional 2.4.19 code
+ */
+
+#include <linux/autoconf.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+#endif
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <asm/unaligned.h>
+#include <linux/input.h>
+
+#undef DEBUG
+#undef DEBUG_DATA
+
+#include <linux/usb.h>
+
+#include "hid.h"
+#include <linux/hiddev.h>
+
+/*
+ * Version Information
+ */
+
+#define DRIVER_VERSION "v1.8.1-j0"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID support drivers"
+
+static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
+ "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
+
+/*
+ * Register a new report for a device.
+ */
+
+static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
+{
+ struct hid_report_enum *report_enum = device->report_enum + type;
+ struct hid_report *report;
+
+ if (report_enum->report_id_hash[id])
+ return report_enum->report_id_hash[id];
+
+ if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL)))
+ return NULL;
+ memset(report, 0, sizeof(struct hid_report));
+
+ if (id != 0) report_enum->numbered = 1;
+
+ report->id = id;
+ report->type = type;
+ report->size = 0;
+ report->device = device;
+ report_enum->report_id_hash[id] = report;
+
+ list_add_tail(&report->list, &report_enum->report_list);
+
+ return report;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+{
+ struct hid_field *field;
+
+ if (report->maxfield == HID_MAX_FIELDS) {
+ dbg("too many fields in report");
+ return NULL;
+ }
+
+ if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
+
+ memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ + values * sizeof(unsigned));
+
+ report->field[report->maxfield++] = field;
+ field->usage = (struct hid_usage *)(field + 1);
+ field->value = (unsigned *)(field->usage + usages);
+ field->report = report;
+
+ return field;
+}
+
+/*
+ * Open a collection. The type/usage is pushed on the stack.
+ */
+
+static int open_collection(struct hid_parser *parser, unsigned type)
+{
+ struct hid_collection *collection;
+ unsigned usage;
+
+ usage = parser->local.usage[0];
+
+ if (type == HID_COLLECTION_APPLICATION
+ && parser->device->maxapplication < HID_MAX_APPLICATIONS)
+ parser->device->application[parser->device->maxapplication++] = usage;
+
+ if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
+ dbg("collection stack overflow");
+ return -1;
+ }
+
+ collection = parser->collection_stack + parser->collection_stack_ptr++;
+ collection->type = type;
+ collection->usage = usage;
+
+ return 0;
+}
+
+/*
+ * Close a collection.
+ */
+
+static int close_collection(struct hid_parser *parser)
+{
+ if (!parser->collection_stack_ptr) {
+ dbg("collection stack underflow");
+ return -1;
+ }
+ parser->collection_stack_ptr--;
+ return 0;
+}
+
+/*
+ * Climb up the stack, search for the specified collection type
+ * and return the usage.
+ */
+
+static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
+{
+ int n;
+ for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
+ if (parser->collection_stack[n].type == type)
+ return parser->collection_stack[n].usage;
+ return 0; /* we know nothing about this usage type */
+}
+
+/*
+ * Add a usage to the temporary parser table.
+ */
+
+static int hid_add_usage(struct hid_parser *parser, unsigned usage)
+{
+ if (parser->local.usage_index >= HID_MAX_USAGES) {
+ dbg("usage index exceeded");
+ return -1;
+ }
+ parser->local.usage[parser->local.usage_index++] = usage;
+ return 0;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
+{
+ struct hid_report *report;
+ struct hid_field *field;
+ int usages;
+ unsigned offset;
+ int i;
+
+ if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
+ dbg("hid_register_report failed");
+ return -1;
+ }
+
+ if (parser->global.logical_maximum <= parser->global.logical_minimum) {
+ dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+ return -1;
+ }
+
+ usages = parser->local.usage_index;
+
+ offset = report->size;
+ report->size += parser->global.report_size * parser->global.report_count;
+
+ if (usages == 0)
+ return 0; /* ignore padding fields */
+
+ if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
+ return 0;
+
+ field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
+ field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
+ field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
+
+ for (i = 0; i < usages; i++)
+ field->usage[i].hid = parser->local.usage[i];
+
+ field->maxusage = usages;
+ field->flags = flags;
+ field->report_offset = offset;
+ field->report_type = report_type;
+ field->report_size = parser->global.report_size;
+ field->report_count = parser->global.report_count;
+ field->logical_minimum = parser->global.logical_minimum;
+ field->logical_maximum = parser->global.logical_maximum;
+ field->physical_minimum = parser->global.physical_minimum;
+ field->physical_maximum = parser->global.physical_maximum;
+ field->unit_exponent = parser->global.unit_exponent;
+ field->unit = parser->global.unit;
+
+ return 0;
+}
+
+/*
+ * Read data value from item.
+ */
+
+static __inline__ __u32 item_udata(struct hid_item *item)
+{
+ switch (item->size) {
+ case 1: return item->data.u8;
+ case 2: return item->data.u16;
+ case 4: return item->data.u32;
+ }
+ return 0;
+}
+
+static __inline__ __s32 item_sdata(struct hid_item *item)
+{
+ switch (item->size) {
+ case 1: return item->data.s8;
+ case 2: return item->data.s16;
+ case 4: return item->data.s32;
+ }
+ return 0;
+}
+
+/*
+ * Process a global item.
+ */
+
+static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
+{
+ switch (item->tag) {
+
+ case HID_GLOBAL_ITEM_TAG_PUSH:
+
+ if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
+ dbg("global enviroment stack overflow");
+ return -1;
+ }
+
+ memcpy(parser->global_stack + parser->global_stack_ptr++,
+ &parser->global, sizeof(struct hid_global));
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_POP:
+
+ if (!parser->global_stack_ptr) {
+ dbg("global enviroment stack underflow");
+ return -1;
+ }
+
+ memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
+ sizeof(struct hid_global));
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+ parser->global.usage_page = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+ parser->global.logical_minimum = item_sdata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+ if (parser->global.logical_minimum < 0)
+ parser->global.logical_maximum = item_sdata(item);
+ else
+ parser->global.logical_maximum = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+ parser->global.physical_minimum = item_sdata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+ if (parser->global.physical_minimum < 0)
+ parser->global.physical_maximum = item_sdata(item);
+ else
+ parser->global.physical_maximum = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+ parser->global.unit_exponent = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_UNIT:
+ parser->global.unit = item_udata(item);
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+ if ((parser->global.report_size = item_udata(item)) > 32) {
+ dbg("invalid report_size %d", parser->global.report_size);
+ return -1;
+ }
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+ if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
+ dbg("invalid report_count %d", parser->global.report_count);
+ return -1;
+ }
+ return 0;
+
+ case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+ if ((parser->global.report_id = item_udata(item)) == 0) {
+ dbg("report_id 0 is invalid");
+ return -1;
+ }
+ return 0;
+
+ default:
+ dbg("unknown global tag 0x%x", item->tag);
+ return -1;
+ }
+}
+
+/*
+ * Process a local item.
+ */
+
+static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
+{
+ __u32 data;
+ unsigned n;
+
+ if (item->size == 0) {
+ dbg("item data expected for local item");
+ return -1;
+ }
+
+ data = item_udata(item);
+
+ switch (item->tag) {
+
+ case HID_LOCAL_ITEM_TAG_DELIMITER:
+
+ if (data) {
+ /*
+ * We treat items before the first delimiter
+ * as global to all usage sets (branch 0).
+ * In the moment we process only these global
+ * items and the first delimiter set.
+ */
+ if (parser->local.delimiter_depth != 0) {
+ dbg("nested delimiters");
+ return -1;
+ }
+ parser->local.delimiter_depth++;
+ parser->local.delimiter_branch++;
+ } else {
+ if (parser->local.delimiter_depth < 1) {
+ dbg("bogus close delimiter");
+ return -1;
+ }
+ parser->local.delimiter_depth--;
+ }
+ return 1;
+
+ case HID_LOCAL_ITEM_TAG_USAGE:
+
+ if (parser->local.delimiter_branch > 1) {
+ dbg("alternative usage ignored");
+ return 0;
+ }
+
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
+
+ return hid_add_usage(parser, data);
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+
+ if (parser->local.delimiter_branch > 1) {
+ dbg("alternative usage ignored");
+ return 0;
+ }
+
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
+
+ parser->local.usage_minimum = data;
+ return 0;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+
+ if (parser->local.delimiter_branch > 1) {
+ dbg("alternative usage ignored");
+ return 0;
+ }
+
+ if (item->size <= 2)
+ data = (parser->global.usage_page << 16) + data;
+
+ for (n = parser->local.usage_minimum; n <= data; n++)
+ if (hid_add_usage(parser, n)) {
+ dbg("hid_add_usage failed\n");
+ return -1;
+ }
+ return 0;
+
+ default:
+
+ dbg("unknown local item tag 0x%x", item->tag);
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * Process a main item.
+ */
+
+static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
+{
+ __u32 data;
+ int ret;
+
+ data = item_udata(item);
+
+ switch (item->tag) {
+ case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+ ret = open_collection(parser, data & 3);
+ break;
+ case HID_MAIN_ITEM_TAG_END_COLLECTION:
+ ret = close_collection(parser);
+ break;
+ case HID_MAIN_ITEM_TAG_INPUT:
+ ret = hid_add_field(parser, HID_INPUT_REPORT, data);
+ break;
+ case HID_MAIN_ITEM_TAG_OUTPUT:
+ ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
+ break;
+ case HID_MAIN_ITEM_TAG_FEATURE:
+ ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
+ break;
+ default:
+ dbg("unknown main item tag 0x%x", item->tag);
+ ret = 0;
+ }
+
+ memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */
+
+ return ret;
+}
+
+/*
+ * Process a reserved item.
+ */
+
+static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
+{
+ dbg("reserved item type, tag 0x%x", item->tag);
+ return 0;
+}
+
+/*
+ * Free a report and all registered fields. The field->usage and
+ * field->value table's are allocated behind the field, so we need
+ * only to free(field) itself.
+ */
+
+static void hid_free_report(struct hid_report *report)
+{
+ unsigned n;
+
+ for (n = 0; n < report->maxfield; n++)
+ kfree(report->field[n]);
+ if (report->data)
+ kfree(report->data);
+ kfree(report);
+}
+
+/*
+ * Free a device structure, all reports, and all fields.
+ */
+
+static void hid_free_device(struct hid_device *device)
+{
+ unsigned i,j;
+
+ for (i = 0; i < HID_REPORT_TYPES; i++) {
+ struct hid_report_enum *report_enum = device->report_enum + i;
+
+ for (j = 0; j < 256; j++) {
+ struct hid_report *report = report_enum->report_id_hash[j];
+ if (report) hid_free_report(report);
+ }
+ }
+
+ if (device->rdesc) kfree(device->rdesc);
+}
+
+/*
+ * Fetch a report description item from the data stream. We support long
+ * items, though they are not used yet.
+ */
+
+static __u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+{
+ if ((end - start) > 0) {
+
+ __u8 b = *start++;
+ item->type = (b >> 2) & 3;
+ item->tag = (b >> 4) & 15;
+
+ if (item->tag == HID_ITEM_TAG_LONG) {
+
+ item->format = HID_ITEM_FORMAT_LONG;
+
+ if ((end - start) >= 2) {
+
+ item->size = *start++;
+ item->tag = *start++;
+
+ if ((end - start) >= item->size) {
+ item->data.longdata = start;
+ start += item->size;
+ return start;
+ }
+ }
+ } else {
+
+ item->format = HID_ITEM_FORMAT_SHORT;
+ item->size = b & 3;
+ switch (item->size) {
+
+ case 0:
+ return start;
+
+ case 1:
+ if ((end - start) >= 1) {
+ item->data.u8 = *start++;
+ return start;
+ }
+ break;
+
+ case 2:
+ if ((end - start) >= 2) {
+ item->data.u16 = le16_to_cpu( get_unaligned(((__u16*)start)++));
+ return start;
+ }
+
+ case 3:
+ item->size++;
+ if ((end - start) >= 4) {
+ item->data.u32 = le32_to_cpu( get_unaligned(((__u32*)start)++));
+ return start;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Parse a report description into a hid_device structure. Reports are
+ * enumerated, fields are attached to these reports.
+ */
+
+static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+{
+ struct hid_device *device;
+ struct hid_parser *parser;
+ struct hid_item item;
+ __u8 *end;
+ unsigned i;
+ static int (*dispatch_type[])(struct hid_parser *parser,
+ struct hid_item *item) = {
+ hid_parser_main,
+ hid_parser_global,
+ hid_parser_local,
+ hid_parser_reserved
+ };
+
+ if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL)))
+ return NULL;
+ memset(device, 0, sizeof(struct hid_device));
+
+ for (i = 0; i < HID_REPORT_TYPES; i++)
+ INIT_LIST_HEAD(&device->report_enum[i].report_list);
+
+ if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
+ kfree(device);
+ return NULL;
+ }
+ memcpy(device->rdesc, start, size);
+
+ if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+ kfree(device->rdesc);
+ kfree(device);
+ return NULL;
+ }
+ memset(parser, 0, sizeof(struct hid_parser));
+ parser->device = device;
+
+ end = start + size;
+ while ((start = fetch_item(start, end, &item)) != 0) {
+ if (item.format != HID_ITEM_FORMAT_SHORT) {
+ dbg("unexpected long global item");
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+ if (dispatch_type[item.type](parser, &item)) {
+ dbg("item %u %u %u %u parsing failed\n",
+ item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+
+ if (start == end) {
+ if (parser->collection_stack_ptr) {
+ dbg("unbalanced collection at end of report description");
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+ if (parser->local.delimiter_depth) {
+ dbg("unbalanced delimiter at end of report description");
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+ }
+ kfree(parser);
+ return device;
+ }
+ }
+
+ dbg("item fetching failed at offset %d\n", (int)(end - start));
+ hid_free_device(device);
+ kfree(parser);
+ return NULL;
+}
+
+/*
+ * Convert a signed n-bit integer to signed 32-bit integer. Common
+ * cases are done through the compiler, the screwed things has to be
+ * done by hand.
+ */
+
+static __inline__ __s32 snto32(__u32 value, unsigned n)
+{
+ switch (n) {
+ case 8: return ((__s8)value);
+ case 16: return ((__s16)value);
+ case 32: return ((__s32)value);
+ }
+ return value & (1 << (n - 1)) ? value | (-1 << n) : value;
+}
+
+/*
+ * Convert a signed 32-bit integer to a signed n-bit integer.
+ */
+
+static __inline__ __u32 s32ton(__s32 value, unsigned n)
+{
+ __s32 a = value >> (n - 1);
+ if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
+ return value & ((1 << n) - 1);
+}
+
+/*
+ * Extract/implement a data field from/to a report.
+ */
+
+static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+{
+ report += (offset >> 5) << 2; offset &= 31;
+ return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1);
+}
+
+static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
+{
+ report += (offset >> 5) << 2; offset &= 31;
+ put_unaligned((get_unaligned((__u64*)report)
+ & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
+ | cpu_to_le64((__u64)value << offset), (__u64*)report);
+}
+
+/*
+ * Search an array for a value.
+ */
+
+static __inline__ int search(__s32 *array, __s32 value, unsigned n)
+{
+ while (n--) if (*array++ == value) return 0;
+ return -1;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
+{
+ hid_dump_input(usage, value);
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_hid_event(hid, field, usage, value);
+ if (hid->claimed & HID_CLAIMED_HIDDEV)
+ hiddev_hid_event(hid, usage->hid, value);
+}
+
+
+/*
+ * Analyse a received field, and fetch the data from it. The field
+ * content is stored for next report processing (we do differential
+ * reporting to the layer).
+ */
+
+static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data)
+{
+ unsigned n;
+ unsigned count = field->report_count;
+ unsigned offset = field->report_offset;
+ unsigned size = field->report_size;
+ __s32 min = field->logical_minimum;
+ __s32 max = field->logical_maximum;
+ __s32 value[count]; /* WARNING: gcc specific */
+
+ for (n = 0; n < count; n++) {
+
+ value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
+ extract(data, offset + n * size, size);
+
+ if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
+ && value[n] >= min && value[n] <= max
+ && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+ return;
+ }
+
+ for (n = 0; n < count; n++) {
+
+ if (HID_MAIN_ITEM_VARIABLE & field->flags) {
+
+ if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+ if (!value[n]) continue;
+ } else {
+ if (value[n] == field->value[n]) continue;
+ }
+ hid_process_event(hid, field, &field->usage[n], value[n]);
+ continue;
+ }
+
+ if (field->value[n] >= min && field->value[n] <= max
+ && field->usage[field->value[n] - min].hid
+ && search(value, field->value[n], count))
+ hid_process_event(hid, field, &field->usage[field->value[n] - min], 0);
+
+ if (value[n] >= min && value[n] <= max
+ && field->usage[value[n] - min].hid
+ && search(field->value, value[n], count))
+ hid_process_event(hid, field, &field->usage[value[n] - min], 1);
+ }
+
+ memcpy(field->value, value, count * sizeof(__s32));
+}
+
+static int hid_input_report(int type, u8 *data, int len, struct hid_device *hid)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_report *report;
+ int n, size;
+
+ if (!len) {
+ dbg("empty report");
+ return -1;
+ }
+
+#ifdef DEBUG_DATA
+ printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
+#endif
+
+ n = 0; /* Normally report number is 0 */
+ if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
+ n = *data++;
+ len--;
+ }
+
+ if (!(report = report_enum->report_id_hash[n])) {
+ dbg("undefined report_id %d received", n);
+#ifdef DEBUG
+ printk(KERN_DEBUG __FILE__ ": report (size %u) = ", len);
+ for (n = 0; n < len; n++)
+ printk(" %02x", data[n]);
+ printk("\n");
+#endif
+
+ return -1;
+ }
+
+ size = ((report->size - 1) >> 3) + 1;
+
+ if (len < size) {
+
+ if (size <= 8) {
+ dbg("report %d is too short, (%d < %d)", report->id, len, size);
+ return -1;
+ }
+
+ /*
+ * Some low-speed devices have large reports and maxpacketsize 8.
+ * We buffer the data in that case and parse it when we got it all.
+ * Works only for unnumbered reports. Doesn't make sense for numbered
+ * reports anyway - then they don't need to be large.
+ */
+
+ if (!report->data)
+ if (!(report->data = kmalloc(size, GFP_ATOMIC))) {
+ dbg("couldn't allocate report buffer");
+ return -1;
+ }
+
+ if (report->idx + len > size) {
+ dbg("report data buffer overflow");
+ report->idx = 0;
+ return -1;
+ }
+
+ memcpy(report->data + report->idx, data, len);
+ report->idx += len;
+
+ if (report->idx < size)
+ return 0;
+
+ data = report->data;
+ }
+
+ for (n = 0; n < report->maxfield; n++)
+ hid_input_field(hid, report->field[n], data);
+
+ report->idx = 0;
+ return 0;
+}
+
+/*
+ * Interrupt input handler.
+ */
+
+static void hid_irq(struct urb *urb)
+{
+ if (urb->status) {
+ dbg("nonzero status in irq %d", urb->status);
+ return;
+ }
+
+ hid_input_report(HID_INPUT_REPORT, urb->transfer_buffer, urb->actual_length, urb->context);
+}
+
+/*
+ * hid_read_report() reads in report values without waiting for an irq urb.
+ */
+
+void hid_read_report(struct hid_device *hid, struct hid_report *report)
+{
+ int len = ((report->size - 1) >> 3) + 1 + hid->report_enum[report->type].numbered;
+ u8 data[len];
+ int read;
+
+ if (hid->quirks & HID_QUIRK_NOGET)
+ return;
+
+ if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
+ dbg("reading report type %d id %d failed len %d read %d", report->type + 1, report->id, len, read);
+ return;
+ }
+
+ hid_input_report(report->type, data, len, hid);
+}
+
+/*
+ * Output the field into the report.
+ */
+
+static void hid_output_field(struct hid_field *field, __u8 *data)
+{
+ unsigned count = field->report_count;
+ unsigned offset = field->report_offset;
+ unsigned size = field->report_size;
+ unsigned n;
+
+ for (n = 0; n < count; n++) {
+ if (field->logical_minimum < 0) /* signed values */
+ implement(data, offset + n * size, size, s32ton(field->value[n], size));
+ else /* unsigned values */
+ implement(data, offset + n * size, size, field->value[n]);
+ }
+}
+
+/*
+ * Create a report.
+ */
+
+void hid_output_report(struct hid_report *report, __u8 *data)
+{
+ unsigned n;
+ for (n = 0; n < report->maxfield; n++)
+ hid_output_field(report->field[n], data);
+}
+
+/*
+ * Set a field value. The report this field belongs to has to be
+ * created and transfered to the device, to set this value in the
+ * device.
+ */
+
+int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
+{
+ unsigned size = field->report_size;
+
+ hid_dump_input(field->usage + offset, value);
+
+ if (offset >= field->report_count) {
+ dbg("offset exceeds report_count");
+ return -1;
+ }
+ if (field->logical_minimum < 0) {
+ if (value != snto32(s32ton(value, size), size)) {
+ dbg("value %d is out of range", value);
+ return -1;
+ }
+ }
+ if ( (value > field->logical_maximum)
+ || (value < field->logical_minimum)) {
+ dbg("value %d is invalid", value);
+ return -1;
+ }
+ field->value[offset] = value;
+ return 0;
+}
+
+int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
+ struct list_head *list = report_enum->report_list.next;
+ int i, j;
+
+ while (list != &report_enum->report_list) {
+ struct hid_report *report = (struct hid_report *) list;
+ list = list->next;
+ for (i = 0; i < report->maxfield; i++) {
+ *field = report->field[i];
+ for (j = 0; j < (*field)->maxusage; j++)
+ if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+ return j;
+ }
+ }
+ return -1;
+}
+
+static int hid_submit_out(struct hid_device *hid)
+{
+#if WAC_PATCH_DRVALUE
+ hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.wLength);
+#else
+ hid->urbout.transfer_buffer_length = le16_to_cpup(&hid->out[hid->outtail].dr.length);
+#endif
+
+ hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer;
+ hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
+ hid->urbout.dev = hid->dev;
+
+ if (usb_submit_urb(&hid->urbout)) {
+ err("usb_submit_urb(out) failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void hid_ctrl(struct urb *urb)
+{
+ struct hid_device *hid = urb->context;
+
+ if (urb->status)
+ warn("ctrl urb status %d received", urb->status);
+
+ hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+
+ if (hid->outhead != hid->outtail)
+ hid_submit_out(hid);
+}
+
+void hid_write_report(struct hid_device *hid, struct hid_report *report)
+{
+ hid_output_report(report, hid->out[hid->outhead].buffer);
+
+#if WAC_PATCH_DRVALUE
+ hid->out[hid->outhead].dr.wValue = cpu_to_le16(0x200 | report->id);
+ hid->out[hid->outhead].dr.wLength = cpu_to_le16((report->size + 7) >> 3);
+#else
+ hid->out[hid->outhead].dr.value = cpu_to_le16(0x200 | report->id);
+ hid->out[hid->outhead].dr.length = cpu_to_le16((report->size + 7) >> 3);
+#endif
+
+ hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+
+ if (hid->outhead == hid->outtail)
+ hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+
+ if (hid->urbout.status != -EINPROGRESS)
+ hid_submit_out(hid);
+}
+
+int hid_open(struct hid_device *hid)
+{
+ if (hid->open++)
+ return 0;
+
+ hid->urb.dev = hid->dev;
+
+ if (usb_submit_urb(&hid->urb))
+ return -EIO;
+
+ return 0;
+}
+
+void hid_close(struct hid_device *hid)
+{
+ if (!--hid->open)
+ usb_unlink_urb(&hid->urb);
+}
+
+/*
+ * Initialize all readable reports
+ */
+void hid_init_reports(struct hid_device *hid)
+{
+ int i;
+ struct hid_report *report;
+ struct hid_report_enum *report_enum;
+ struct list_head *list;
+
+ for (i = 0; i < HID_REPORT_TYPES; i++) {
+ if (i == HID_FEATURE_REPORT || i == HID_INPUT_REPORT) {
+ report_enum = hid->report_enum + i;
+ list = report_enum->report_list.next;
+ while (list != &report_enum->report_list) {
+ report = (struct hid_report *) list;
+ /* JEJ: 2.4.20 patch */
+ usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
+ hid_read_report(hid, report);
+ list = list->next;
+ }
+ }
+ }
+}
+
+#define USB_VENDOR_ID_WACOM 0x056a
+#define USB_DEVICE_ID_WACOM_PENPARTNER 0x0000
+#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
+#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
+#define USB_DEVICE_ID_WACOM_PL 0x0030
+#define USB_DEVICE_ID_WACOM_INTUOS2 0x0041
+
+#define USB_VENDOR_ID_ATEN 0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
+#define USB_DEVICE_ID_ATEN_CS124U 0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
+
+struct hid_blacklist {
+ __u16 idVendor;
+ __u16 idProduct;
+ unsigned quirks;
+} hid_blacklist[] = {
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
+
+ /* JEJ - exists in wacom.c, so it should exist here, too */
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE },
+
+ /* JEJ - added as test for M. T. (Intuos2 6x8 model XD-0608-U) */
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+ { 0, 0 }
+};
+
+static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
+{
+ struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
+ struct hid_descriptor *hdesc;
+ struct hid_device *hid;
+ unsigned quirks = 0, rsize = 0;
+ char *buf;
+ int n;
+
+ for (n = 0; hid_blacklist[n].idVendor; n++)
+ if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
+ (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
+ quirks = hid_blacklist[n].quirks;
+
+#if __DEBUG_JEJ
+ printk(KERN_INFO __FILE__ ": usb_hid_configure: "
+ "configuring device %X.%X%s, quirk is %X%s\n",
+ hid_blacklist[n].idVendor,
+ hid_blacklist[n].idProduct,
+ (hidblacklist[n].idVendor == USB_VENDOR_ID_WACOM) ? " (WACOM)" : "",
+ quirks, (quirks & HID_QUIRK_IGNORE) ? " (IGNORE)" : "");
+#endif /* __DEBUG_JEJ */
+
+ if (quirks & HID_QUIRK_IGNORE)
+ return NULL;
+
+ if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
+ usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc))) {
+ dbg("class descriptor not present\n");
+ return NULL;
+ }
+
+ for (n = 0; n < hdesc->bNumDescriptors; n++)
+ if (hdesc->desc[n].bDescriptorType == USB_DT_REPORT)
+ rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
+
+ if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
+ dbg("weird size of report descriptor (%u)", rsize);
+ return NULL;
+ }
+
+ {
+ __u8 rdesc[rsize];
+
+ if ((n = usb_get_class_descriptor(dev, interface->bInterfaceNumber, USB_DT_REPORT, 0, rdesc, rsize)) < 0) {
+ dbg("reading report descriptor failed");
+ return NULL;
+ }
+
+#ifdef DEBUG_DATA
+ printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+ for (n = 0; n < rsize; n++)
+ printk(" %02x", (unsigned) rdesc[n]);
+ printk("\n");
+#endif
+
+ if (!(hid = hid_parse_report(rdesc, rsize))) {
+ dbg("parsing report descriptor failed");
+ return NULL;
+ }
+ }
+
+ hid->quirks = quirks;
+
+ for (n = 0; n < interface->bNumEndpoints; n++) {
+
+ struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
+ int pipe, maxp;
+
+ if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
+ continue;
+
+ if (!(endpoint->bEndpointAddress & 0x80)) /* Not an input endpoint */
+ continue;
+
+ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+ FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, maxp > 32 ? 32 : maxp, hid_irq, hid, endpoint->bInterval);
+
+ break;
+ }
+
+ if (n == interface->bNumEndpoints) {
+ dbg("couldn't find an input interrupt endpoint");
+ hid_free_device(hid);
+ return NULL;
+ }
+
+ hid->version = hdesc->bcdHID;
+ hid->country = hdesc->bCountryCode;
+ hid->dev = dev;
+ hid->ifnum = interface->bInterfaceNumber;
+
+ for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
+#if WAC_PATCH_DRVALUE
+ hid->out[n].dr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ hid->out[n].dr.bRequest = USB_REQ_SET_REPORT;
+ hid->out[n].dr.wIndex = cpu_to_le16(hid->ifnum);
+#else
+ hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ hid->out[n].dr.request = USB_REQ_SET_REPORT;
+ hid->out[n].dr.index = cpu_to_le16(hid->ifnum);
+#endif
+ }
+
+ hid->name[0] = 0;
+
+ if (!(buf = kmalloc(63, GFP_KERNEL)))
+ return NULL;
+
+ if (usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) {
+ strcat(hid->name, buf);
+ if (usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
+ sprintf(hid->name, "%s %s", hid->name, buf);
+ } else
+ sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+ kfree(buf);
+
+ FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0),
+ (void*) &hid->out[0].dr, hid->out[0].buffer, 1, hid_ctrl, hid);
+
+/*
+ * Some devices don't like this and crash. I don't know of any devices
+ * needing this, so it is disabled for now.
+ */
+
+#if 0
+ if (interface->bInterfaceSubClass == 1)
+ usb_set_protocol(dev, hid->ifnum, 1);
+#endif
+
+ return hid;
+}
+
+static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
+ const struct usb_device_id *id)
+{
+ struct hid_device *hid;
+ int i;
+ char *c;
+
+ dbg("HID probe called for ifnum %d", ifnum);
+
+ if (!(hid = usb_hid_configure(dev, ifnum)))
+ return NULL;
+
+ hid_init_reports(hid);
+ hid_dump_device(hid);
+
+ if (!hidinput_connect(hid))
+ hid->claimed |= HID_CLAIMED_INPUT;
+ if (!hiddev_connect(hid))
+ hid->claimed |= HID_CLAIMED_HIDDEV;
+ printk(KERN_INFO);
+
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ printk("input%d", hid->input.number);
+ if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
+ printk(",");
+ if (hid->claimed & HID_CLAIMED_HIDDEV)
+ printk("hiddev%d", hid->minor);
+
+ c = "Device";
+ for (i = 0; i < hid->maxapplication; i++)
+ if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
+ c = hid_types[hid->application[i] & 0xffff];
+ break;
+ }
+
+ printk(": USB HID v%x.%02x %s [%s] on usb%d:%d.%d\n",
+ hid->version >> 8, hid->version & 0xff, c, hid->name,
+ dev->bus->busnum, dev->devnum, ifnum);
+
+ return hid;
+}
+
+static void hid_disconnect(struct usb_device *dev, void *ptr)
+{
+ struct hid_device *hid = ptr;
+
+ dbg("cleanup called");
+ usb_unlink_urb(&hid->urb);
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_disconnect(hid);
+ if (hid->claimed & HID_CLAIMED_HIDDEV)
+ hiddev_disconnect(hid);
+ hid_free_device(hid);
+}
+
+static struct usb_device_id hid_usb_ids [] = {
+ { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
+ bInterfaceClass: USB_INTERFACE_CLASS_HID },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, hid_usb_ids);
+
+static struct usb_driver hid_driver = {
+ name: "hid",
+ probe: hid_probe,
+ disconnect: hid_disconnect,
+ id_table: hid_usb_ids,
+};
+
+static int __init hid_init(void)
+{
+#ifdef __JEJ_DEBUG
+ printk(KERN_INFO __FILE__ ": hid_init (MODIFIED DEBUG)\n");
+#endif
+ hiddev_init();
+ usb_register(&hid_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+
+ return 0;
+}
+
+static void __exit hid_exit(void)
+{
+ hiddev_exit();
+ usb_deregister(&hid_driver);
+}
+
+module_init(hid_init);
+module_exit(hid_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
diff --git a/src/hid-input.c b/src/hid-input.c
new file mode 100644
index 0000000..60d807f
--- /dev/null
+++ b/src/hid-input.c
@@ -0,0 +1,434 @@
+/*
+ * $Id: hid-input.c,v 1.1.1.1 2002/12/23 02:44:44 jjoganic Exp $
+ *
+ * Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ * USB HID to Linux Input mapping module
+ *
+ * Sponsored by SuSE
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/autoconf.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+#endif
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include "hid.h"
+
+#define unk KEY_UNKNOWN
+
+static unsigned char hid_keyboard[256] = {
+ 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+ 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
+ 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+ 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+ 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+ 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+ 115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189,
+ 190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk,
+ unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+ unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+ unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+ unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+ 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+ 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
+};
+
+static struct {
+ __s32 x;
+ __s32 y;
+} hid_hat_to_axis[] = {{0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage)
+{
+ struct input_dev *input = &device->input;
+ int max;
+ unsigned long *bit;
+
+ switch (usage->hid & HID_USAGE_PAGE) {
+
+ case HID_UP_KEYBOARD:
+
+ set_bit(EV_REP, input->evbit);
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+
+ if ((usage->hid & HID_USAGE) < 256) {
+ if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE]))
+ return;
+ clear_bit(usage->code, bit);
+ } else
+ usage->code = KEY_UNKNOWN;
+
+ break;
+
+ case HID_UP_BUTTON:
+
+ usage->code = ((usage->hid - 1) & 0xf) + 0x100;
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+
+ switch (field->application) {
+ case HID_GD_GAMEPAD: usage->code += 0x10;
+ case HID_GD_JOYSTICK: usage->code += 0x10;
+ case HID_GD_MOUSE: usage->code += 0x10; break;
+ default:
+ if (field->physical == HID_GD_POINTER)
+ usage->code += 0x10;
+ break;
+ }
+ break;
+
+ case HID_UP_GENDESK:
+
+ if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
+ switch (usage->hid & 0xf) {
+ case 0x1: usage->code = KEY_POWER; break;
+ case 0x2: usage->code = KEY_SLEEP; break;
+ case 0x3: usage->code = KEY_WAKEUP; break;
+ default: usage->code = KEY_UNKNOWN; break;
+ }
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ break;
+ }
+
+ usage->code = usage->hid & 0xf;
+
+ if (field->report_size == 1) {
+ usage->code = BTN_MISC;
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ break;
+ }
+
+ if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+ usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
+ break;
+ }
+
+ usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+
+ if (usage->hid == HID_GD_HATSWITCH) {
+ usage->code = ABS_HAT0X;
+ usage->hat_min = field->logical_minimum;
+ usage->hat_max = field->logical_maximum;
+ }
+ break;
+
+ case HID_UP_LED:
+
+ usage->code = (usage->hid - 1) & 0xf;
+ usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
+ break;
+
+ case HID_UP_DIGITIZER:
+
+ switch (usage->hid & 0xff) {
+
+ case 0x30: /* TipPressure */
+
+ if (!test_bit(BTN_TOUCH, input->keybit)) {
+ device->quirks |= HID_QUIRK_NOTOUCH;
+ set_bit(EV_KEY, input->evbit);
+ set_bit(BTN_TOUCH, input->keybit);
+ }
+ usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+ usage->code = ABS_PRESSURE;
+ clear_bit(usage->code, bit);
+ break;
+
+ case 0x32: /* InRange */
+
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ switch (field->physical & 0xff) {
+ case 0x21: usage->code = BTN_TOOL_MOUSE; break;
+ case 0x22: usage->code = BTN_TOOL_FINGER; break;
+ default: usage->code = BTN_TOOL_PEN; break;
+ }
+ break;
+
+ case 0x3c: /* Invert */
+
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ usage->code = BTN_TOOL_RUBBER;
+ clear_bit(usage->code, bit);
+ break;
+
+ case 0x33: /* Touch */
+ case 0x42: /* TipSwitch */
+ case 0x43: /* TipSwitch2 */
+
+ device->quirks &= ~HID_QUIRK_NOTOUCH;
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ usage->code = BTN_TOUCH;
+ clear_bit(usage->code, bit);
+ break;
+
+ case 0x44: /* BarrelSwitch */
+
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ usage->code = BTN_STYLUS;
+ clear_bit(usage->code, bit);
+ break;
+
+ default: goto unknown;
+ }
+ break;
+
+ case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x000: usage->code = 0; break;
+ case 0x034: usage->code = KEY_SLEEP; break;
+ case 0x036: usage->code = BTN_MISC; break;
+ case 0x08a: usage->code = KEY_WWW; break;
+ case 0x095: usage->code = KEY_HELP; break;
+
+ case 0x0b4: usage->code = KEY_REWIND; break;
+ case 0x0b5: usage->code = KEY_NEXTSONG; break;
+ case 0x0b6: usage->code = KEY_PREVIOUSSONG; break;
+ case 0x0b7: usage->code = KEY_STOPCD; break;
+ case 0x0b8: usage->code = KEY_EJECTCD; break;
+ case 0x0cd: usage->code = KEY_PLAYPAUSE; break;
+
+ case 0x0e2: usage->code = KEY_MUTE; break;
+ case 0x0e9: usage->code = KEY_VOLUMEUP; break;
+ case 0x0ea: usage->code = KEY_VOLUMEDOWN; break;
+
+ case 0x183: usage->code = KEY_CONFIG; break;
+ case 0x18a: usage->code = KEY_MAIL; break;
+ case 0x192: usage->code = KEY_CALC; break;
+ case 0x194: usage->code = KEY_FILE; break;
+
+ case 0x21a: usage->code = KEY_UNDO; break;
+ case 0x21b: usage->code = KEY_COPY; break;
+ case 0x21c: usage->code = KEY_CUT; break;
+ case 0x21d: usage->code = KEY_PASTE; break;
+
+ case 0x221: usage->code = KEY_FIND; break;
+ case 0x223: usage->code = KEY_HOMEPAGE; break;
+ case 0x224: usage->code = KEY_BACK; break;
+ case 0x225: usage->code = KEY_FORWARD; break;
+ case 0x226: usage->code = KEY_STOP; break;
+ case 0x227: usage->code = KEY_REFRESH; break;
+ case 0x22a: usage->code = KEY_BOOKMARKS; break;
+
+ default: usage->code = KEY_UNKNOWN; break;
+
+ }
+
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ break;
+
+ default:
+ unknown:
+
+ if (field->report_size == 1) {
+
+ if (field->report->type == HID_OUTPUT_REPORT) {
+ usage->code = LED_MISC;
+ usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
+ break;
+ }
+
+ usage->code = BTN_MISC;
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ break;
+ }
+
+ if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+ usage->code = REL_MISC;
+ usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
+ break;
+ }
+
+ usage->code = ABS_MISC;
+ usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+ break;
+ }
+
+ set_bit(usage->type, input->evbit);
+
+ while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
+ usage->code = find_next_zero_bit(bit, max + 1, usage->code);
+ }
+
+ if (usage->code > max) return;
+
+ if (usage->type == EV_ABS) {
+ int a = field->logical_minimum;
+ int b = field->logical_maximum;
+
+ input->absmin[usage->code] = a;
+ input->absmax[usage->code] = b;
+ input->absfuzz[usage->code] = (b - a) >> 8;
+ input->absflat[usage->code] = (b - a) >> 4;
+ }
+
+ if (usage->hat_min != usage->hat_max) {
+ int i;
+ for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
+ input->absmax[i] = 1;
+ input->absmin[i] = -1;
+ input->absfuzz[i] = 0;
+ input->absflat[i] = 0;
+ }
+ set_bit(usage->code + 1, input->absbit);
+ }
+}
+
+void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
+{
+ struct input_dev *input = &hid->input;
+ int *quirks = &hid->quirks;
+
+ if (usage->hat_min != usage->hat_max) {
+ value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
+ if (value < 0 || value > 8) value = 0;
+ input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x);
+ input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y);
+ return;
+ }
+
+ if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
+ *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
+ return;
+ }
+
+ if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
+ if (value) {
+ input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
+ return;
+ }
+ input_event(input, usage->type, usage->code, 0);
+ input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
+ return;
+ }
+
+ if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
+ int a = field->logical_minimum;
+ int b = field->logical_maximum;
+ input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
+ }
+
+ if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
+ return;
+
+ input_event(input, usage->type, usage->code, value);
+
+ if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
+ input_event(input, usage->type, usage->code, 0);
+}
+
+static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_field *field = NULL;
+ int offset;
+
+ if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+ warn("event field not found");
+ return -1;
+ }
+
+ hid_set_field(field, offset, value);
+ hid_write_report(hid, field->report);
+
+ return 0;
+}
+
+static int hidinput_open(struct input_dev *dev)
+{
+ struct hid_device *hid = dev->private;
+ return hid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+ struct hid_device *hid = dev->private;
+ hid_close(hid);
+}
+
+/*
+ * Register the input device; print a message.
+ * Configure the input layer interface
+ * Read all reports and initalize the absoulte field values.
+ */
+
+int hidinput_connect(struct hid_device *hid)
+{
+ struct usb_device *dev = hid->dev;
+ struct hid_report_enum *report_enum;
+ struct hid_report *report;
+ struct list_head *list;
+ int i, j, k;
+
+ for (i = 0; i < hid->maxapplication; i++)
+ if (IS_INPUT_APPLICATION(hid->application[i]))
+ break;
+
+ if (i == hid->maxapplication)
+ return -1;
+
+ hid->input.private = hid;
+ hid->input.event = hidinput_input_event;
+ hid->input.open = hidinput_open;
+ hid->input.close = hidinput_close;
+
+ hid->input.name = hid->name;
+ hid->input.idbus = BUS_USB;
+ hid->input.idvendor = dev->descriptor.idVendor;
+ hid->input.idproduct = dev->descriptor.idProduct;
+ hid->input.idversion = dev->descriptor.bcdDevice;
+
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+ report_enum = hid->report_enum + k;
+ list = report_enum->report_list.next;
+ while (list != &report_enum->report_list) {
+ report = (struct hid_report *) list;
+ for (i = 0; i < report->maxfield; i++)
+ for (j = 0; j < report->field[i]->maxusage; j++)
+ hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j);
+ list = list->next;
+ }
+ }
+
+ input_register_device(&hid->input);
+
+ return 0;
+}
+
+void hidinput_disconnect(struct hid_device *hid)
+{
+ input_unregister_device(&hid->input);
+}
diff --git a/src/hiddev.c b/src/hiddev.c
new file mode 100644
index 0000000..9adda3c
--- /dev/null
+++ b/src/hiddev.c
@@ -0,0 +1,686 @@
+/*
+ * Copyright (c) 2001 Paul Stewart
+ * Copyright (c) 2001 Vojtech Pavlik
+ *
+ * HID char devices, giving access to raw HID device events.
+ *
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net>
+ */
+
+#include <linux/autoconf.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+#endif
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#define HIDDEV_MINOR_BASE 96
+#define HIDDEV_MINORS 16
+#define HIDDEV_BUFFER_SIZE 64
+
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include "hid.h"
+#include <linux/hiddev.h>
+
+struct hiddev {
+ int exist;
+ int open;
+ int minor;
+ wait_queue_head_t wait;
+ devfs_handle_t devfs;
+ struct hid_device *hid;
+ struct hiddev_list *list;
+};
+
+struct hiddev_list {
+ struct hiddev_event buffer[HIDDEV_BUFFER_SIZE];
+ int head;
+ int tail;
+ struct fasync_struct *fasync;
+ struct hiddev *hiddev;
+ struct hiddev_list *next;
+};
+
+static struct hiddev *hiddev_table[HIDDEV_MINORS];
+static devfs_handle_t hiddev_devfs_handle;
+
+/*
+ * Find a report, given the report's type and ID. The ID can be specified
+ * indirectly by REPORT_ID_FIRST (which returns the first report of the given
+ * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
+ * given type which follows old_id.
+ */
+static struct hid_report *
+hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
+{
+ struct hid_report_enum *report_enum;
+ struct list_head *list;
+
+ if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
+ rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
+
+ report_enum = hid->report_enum +
+ (rinfo->report_type - HID_REPORT_TYPE_MIN);
+ if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) {
+ switch (rinfo->report_id & ~HID_REPORT_ID_MASK) {
+ case HID_REPORT_ID_FIRST:
+ list = report_enum->report_list.next;
+ if (list == &report_enum->report_list) return NULL;
+ rinfo->report_id = ((struct hid_report *) list)->id;
+ break;
+
+ case HID_REPORT_ID_NEXT:
+ list = (struct list_head *)
+ report_enum->report_id_hash[rinfo->report_id &
+ HID_REPORT_ID_MASK];
+ if (list == NULL) return NULL;
+ list = list->next;
+ if (list == &report_enum->report_list) return NULL;
+ rinfo->report_id = ((struct hid_report *) list)->id;
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+
+ return report_enum->report_id_hash[rinfo->report_id];
+}
+
+/*
+ * Perform an exhaustive search of the report table for a usage, given its
+ * type and usage id.
+ */
+static struct hid_field *
+hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
+{
+ int i, j;
+ struct hid_report *report;
+ struct hid_report_enum *report_enum;
+ struct list_head *list;
+ struct hid_field *field;
+
+ if (uref->report_type < HID_REPORT_TYPE_MIN ||
+ uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
+
+ report_enum = hid->report_enum +
+ (uref->report_type - HID_REPORT_TYPE_MIN);
+ list = report_enum->report_list.next;
+ while (list != &report_enum->report_list) {
+ report = (struct hid_report *) list;
+ for (i = 0; i < report->maxfield; i++) {
+ field = report->field[i];
+ for (j = 0; j < field->maxusage; j++) {
+ if (field->usage[j].hid == uref->usage_code) {
+ uref->report_id = report->id;
+ uref->field_index = i;
+ uref->usage_index = j;
+ return field;
+ }
+ }
+ }
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * This is where hid.c calls into hiddev to pass an event that occurred over
+ * the interrupt pipe
+ */
+void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value)
+{
+ struct hiddev *hiddev = hid->hiddev;
+ struct hiddev_list *list = hiddev->list;
+
+ while (list) {
+ list->buffer[list->head].hid = usage;
+ list->buffer[list->head].value = value;
+ list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1);
+
+ kill_fasync(&list->fasync, SIGIO, POLL_IN);
+
+ list = list->next;
+ }
+
+ wake_up_interruptible(&hiddev->wait);
+}
+
+/*
+ * fasync file op
+ */
+static int hiddev_fasync(int fd, struct file *file, int on)
+{
+ int retval;
+ struct hiddev_list *list = file->private_data;
+ retval = fasync_helper(fd, file, on, &list->fasync);
+ return retval < 0 ? retval : 0;
+}
+
+/*
+ * De-allocate a hiddev structure
+ */
+static void hiddev_cleanup(struct hiddev *hiddev)
+{
+ devfs_unregister(hiddev->devfs);
+ hiddev_table[hiddev->minor] = NULL;
+ kfree(hiddev);
+}
+
+/*
+ * release file op
+ */
+static int hiddev_release(struct inode * inode, struct file * file)
+{
+ struct hiddev_list *list = file->private_data;
+ struct hiddev_list **listptr;
+
+ lock_kernel();
+ listptr = &list->hiddev->list;
+ hiddev_fasync(-1, file, 0);
+
+ while (*listptr && (*listptr != list))
+ listptr = &((*listptr)->next);
+ *listptr = (*listptr)->next;
+
+ if (!--list->hiddev->open) {
+ if (list->hiddev->exist)
+ hid_close(list->hiddev->hid);
+ else
+ hiddev_cleanup(list->hiddev);
+ }
+
+ kfree(list);
+ unlock_kernel();
+
+ return 0;
+}
+
+/*
+ * open file op
+ */
+static int hiddev_open(struct inode * inode, struct file * file) {
+ struct hiddev_list *list;
+
+ int i = MINOR(inode->i_rdev) - HIDDEV_MINOR_BASE;
+
+ if (i >= HIDDEV_MINORS || !hiddev_table[i])
+ return -ENODEV;
+
+ if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
+ return -ENOMEM;
+ memset(list, 0, sizeof(struct hiddev_list));
+
+ list->hiddev = hiddev_table[i];
+ list->next = hiddev_table[i]->list;
+ hiddev_table[i]->list = list;
+
+ file->private_data = list;
+
+ if (!list->hiddev->open++)
+ if (list->hiddev->exist)
+ hid_open(hiddev_table[i]->hid);
+
+ return 0;
+}
+
+/*
+ * "write" file op
+ */
+static ssize_t hiddev_write(struct file * file, const char * buffer,
+ size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+/*
+ * "read" file op
+ */
+static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
+ loff_t *ppos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct hiddev_list *list = file->private_data;
+ int retval = 0;
+
+ if (list->head == list->tail) {
+
+ add_wait_queue(&list->hiddev->wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (list->head == list->tail) {
+
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!list->hiddev->exist) {
+ retval = -EIO;
+ break;
+ }
+
+ schedule();
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&list->hiddev->wait, &wait);
+ }
+
+ if (retval)
+ return retval;
+
+ while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) {
+ if (copy_to_user(buffer + retval, list->buffer + list->tail,
+ sizeof(struct hiddev_event))) return -EFAULT;
+ list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
+ retval += sizeof(struct hiddev_event);
+ }
+
+ return retval;
+}
+
+/*
+ * "poll" file op
+ * No kernel lock - fine
+ */
+static unsigned int hiddev_poll(struct file *file, poll_table *wait)
+{
+ struct hiddev_list *list = file->private_data;
+ poll_wait(file, &list->hiddev->wait, wait);
+ if (list->head != list->tail)
+ return POLLIN | POLLRDNORM;
+ if (!list->hiddev->exist)
+ return POLLERR | POLLHUP;
+ return 0;
+}
+
+#define GET_TIMEOUT 3
+#define SET_TIMEOUT 3
+
+/*
+ * "ioctl" file op
+ */
+static int hiddev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct hiddev_list *list = file->private_data;
+ struct hiddev *hiddev = list->hiddev;
+ struct hid_device *hid = hiddev->hid;
+ struct usb_device *dev = hid->dev;
+ struct hiddev_report_info rinfo;
+ struct hiddev_usage_ref uref;
+ struct hid_report *report;
+ struct hid_field *field;
+
+ if (!hiddev->exist) return -EIO;
+
+ switch (cmd) {
+
+ case HIDIOCGVERSION:
+ return put_user(HID_VERSION, (int *) arg);
+
+ case HIDIOCAPPLICATION:
+ if (arg < 0 || arg >= hid->maxapplication)
+ return -EINVAL;
+ return hid->application[arg];
+
+ case HIDIOCGDEVINFO:
+ {
+ struct hiddev_devinfo dinfo;
+ dinfo.bustype = BUS_USB;
+ dinfo.busnum = dev->bus->busnum;
+ dinfo.devnum = dev->devnum;
+ dinfo.ifnum = hid->ifnum;
+ dinfo.vendor = dev->descriptor.idVendor;
+ dinfo.product = dev->descriptor.idProduct;
+ dinfo.version = dev->descriptor.bcdDevice;
+ dinfo.num_applications = hid->maxapplication;
+ return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
+ }
+
+ case HIDIOCGSTRING:
+ {
+ int idx, len;
+ char *buf;
+
+ if (get_user(idx, (int *) arg))
+ return -EFAULT;
+
+ if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
+ kfree(buf);
+ return -EINVAL;
+ }
+
+ if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+
+ kfree(buf);
+
+ return len;
+ }
+
+ case HIDIOCINITREPORT:
+
+ hid_init_reports(hid);
+
+ return 0;
+
+ case HIDIOCGREPORT:
+ if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+ return -EFAULT;
+
+ if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
+ return -EINVAL;
+
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ hid_read_report(hid, report);
+
+ return 0;
+
+ case HIDIOCSREPORT:
+ if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+ return -EFAULT;
+
+ if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
+ return -EINVAL;
+
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ hid_write_report(hid, report);
+
+ return 0;
+
+ case HIDIOCGREPORTINFO:
+ if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+ return -EFAULT;
+
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ rinfo.num_fields = report->maxfield;
+
+ return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
+
+ case HIDIOCGFIELDINFO:
+ {
+ struct hiddev_field_info finfo;
+ if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
+ return -EFAULT;
+ rinfo.report_type = finfo.report_type;
+ rinfo.report_id = finfo.report_id;
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ if (finfo.field_index >= report->maxfield)
+ return -EINVAL;
+
+ field = report->field[finfo.field_index];
+ memset(&finfo, 0, sizeof(finfo));
+ finfo.report_type = rinfo.report_type;
+ finfo.report_id = rinfo.report_id;
+ finfo.field_index = field->report_count - 1;
+ finfo.maxusage = field->maxusage;
+ finfo.flags = field->flags;
+ finfo.physical = field->physical;
+ finfo.logical = field->logical;
+ finfo.application = field->application;
+ finfo.logical_minimum = field->logical_minimum;
+ finfo.logical_maximum = field->logical_maximum;
+ finfo.physical_minimum = field->physical_minimum;
+ finfo.physical_maximum = field->physical_maximum;
+ finfo.unit_exponent = field->unit_exponent;
+ finfo.unit = field->unit;
+
+ return copy_to_user((void *) arg, &finfo, sizeof(finfo));
+ }
+
+ case HIDIOCGUCODE:
+ if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+ return -EFAULT;
+
+ rinfo.report_type = uref.report_type;
+ rinfo.report_id = uref.report_id;
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ if (uref.field_index >= report->maxfield)
+ return -EINVAL;
+
+ field = report->field[uref.field_index];
+ if (uref.usage_index >= field->maxusage)
+ return -EINVAL;
+
+ uref.usage_code = field->usage[uref.usage_index].hid;
+
+ return copy_to_user((void *) arg, &uref, sizeof(uref));
+
+ case HIDIOCGUSAGE:
+ if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+ return -EFAULT;
+
+ if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
+ field = hiddev_lookup_usage(hid, &uref);
+ if (field == NULL)
+ return -EINVAL;
+ } else {
+ rinfo.report_type = uref.report_type;
+ rinfo.report_id = uref.report_id;
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ if (uref.field_index >= report->maxfield)
+ return -EINVAL;
+
+ field = report->field[uref.field_index];
+ if (uref.usage_index >= field->maxusage)
+ return -EINVAL;
+ }
+
+ uref.value = field->value[uref.usage_index];
+
+ return copy_to_user((void *) arg, &uref, sizeof(uref));
+
+ case HIDIOCSUSAGE:
+ if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+ return -EFAULT;
+
+ if (uref.report_type == HID_REPORT_TYPE_INPUT)
+ return -EINVAL;
+
+ if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
+ field = hiddev_lookup_usage(hid, &uref);
+ if (field == NULL)
+ return -EINVAL;
+ } else {
+ rinfo.report_type = uref.report_type;
+ rinfo.report_id = uref.report_id;
+ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+ return -EINVAL;
+
+ if (uref.field_index >= report->maxfield)
+ return -EINVAL;
+
+ field = report->field[uref.field_index];
+ if (uref.usage_index >= field->maxusage)
+ return -EINVAL;
+ }
+
+ field->value[uref.usage_index] = uref.value;
+
+ return 0;
+
+ default:
+
+ if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
+ return -EINVAL;
+
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
+ int len;
+ if (!hid->name) return 0;
+ len = strlen(hid->name) + 1;
+ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+ return copy_to_user((char *) arg, hid->name, len) ?
+ -EFAULT : len;
+ }
+ }
+ return -EINVAL;
+}
+
+static struct file_operations hiddev_fops = {
+ owner: THIS_MODULE,
+ read: hiddev_read,
+ write: hiddev_write,
+ poll: hiddev_poll,
+ open: hiddev_open,
+ release: hiddev_release,
+ ioctl: hiddev_ioctl,
+ fasync: hiddev_fasync,
+};
+
+/*
+ * This is where hid.c calls us to connect a hid device to the hiddev driver
+ */
+int hiddev_connect(struct hid_device *hid)
+{
+ struct hiddev *hiddev;
+ int minor, i;
+ char devfs_name[16];
+
+ for (i = 0; i < hid->maxapplication; i++)
+ if (!IS_INPUT_APPLICATION(hid->application[i]))
+ break;
+
+ if (i == hid->maxapplication)
+ return -1;
+
+ for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
+ if (minor == HIDDEV_MINORS) {
+ printk(KERN_ERR "hiddev: no more free hiddev devices\n");
+ return -1;
+ }
+
+ if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
+ return -1;
+ memset(hiddev, 0, sizeof(struct hiddev));
+
+ init_waitqueue_head(&hiddev->wait);
+
+ hiddev->minor = minor;
+ hiddev_table[minor] = hiddev;
+
+ hiddev->hid = hid;
+ hiddev->exist = 1;
+
+ sprintf(devfs_name, "hiddev%d", minor);
+ hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
+ DEVFS_FL_DEFAULT, USB_MAJOR,
+ minor + HIDDEV_MINOR_BASE,
+ S_IFCHR | S_IRUGO | S_IWUSR,
+ &hiddev_fops, NULL);
+ hid->minor = minor;
+ hid->hiddev = hiddev;
+
+ return 0;
+}
+
+/*
+ * This is where hid.c calls us to disconnect a hiddev device from the
+ * corresponding hid device (usually because the usb device has disconnected)
+ */
+void hiddev_disconnect(struct hid_device *hid)
+{
+ struct hiddev *hiddev = hid->hiddev;
+
+ hiddev->exist = 0;
+
+ if (hiddev->open) {
+ hid_close(hiddev->hid);
+ wake_up_interruptible(&hiddev->wait);
+ } else {
+ hiddev_cleanup(hiddev);
+ }
+}
+
+/* Currently this driver is a USB driver. It's not a conventional one in
+ * the sense that it doesn't probe at the USB level. Instead it waits to
+ * be connected by HID through the hiddev_connect / hiddev_disconnect
+ * routines. The reason to register as a USB device is to gain part of the
+ * minor number space from the USB major.
+ *
+ * In theory, should the HID code be generalized to more than one physical
+ * medium (say, IEEE 1384), this driver will probably need to register its
+ * own major number, and in doing so, no longer need to register with USB.
+ * At that point the probe routine and hiddev_driver struct below will no
+ * longer be useful.
+ */
+
+
+/* We never attach in this manner, and rely on HID to connect us. This
+ * is why there is no disconnect routine defined in the usb_driver either.
+ */
+static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum,
+ const struct usb_device_id *hiddev_info)
+{
+ return NULL;
+}
+
+
+static /* const */ struct usb_driver hiddev_driver = {
+ name: "hiddev",
+ probe: hiddev_usbd_probe,
+ fops: &hiddev_fops,
+ minor: HIDDEV_MINOR_BASE
+};
+
+int __init hiddev_init(void)
+{
+ hiddev_devfs_handle =
+ devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL);
+ usb_register(&hiddev_driver);
+ return 0;
+}
+
+void __exit hiddev_exit(void)
+{
+ devfs_unregister(hiddev_devfs_handle);
+ usb_deregister(&hiddev_driver);
+}
diff --git a/src/usbmouse.c b/src/usbmouse.c
new file mode 100644
index 0000000..9d2854d
--- /dev/null
+++ b/src/usbmouse.c
@@ -0,0 +1,230 @@
+/*
+ * $Id: usbmouse.c,v 1.1.1.1 2002/12/23 02:44:46 jjoganic Exp $
+ *
+ * Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ * USB HIDBP Mouse support
+ *
+ * Sponsored by SuSE
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/autoconf.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+#endif
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.6"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+struct usb_mouse {
+ signed char data[8];
+ char name[128];
+ struct usb_device *usbdev;
+ struct input_dev dev;
+ struct urb irq;
+ int open;
+};
+
+static void usb_mouse_irq(struct urb *urb)
+{
+ struct usb_mouse *mouse = urb->context;
+ signed char *data = mouse->data;
+ struct input_dev *dev = &mouse->dev;
+
+ if (urb->status) return;
+
+ input_report_key(dev, BTN_LEFT, data[0] & 0x01);
+ input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
+ input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
+ input_report_key(dev, BTN_SIDE, data[0] & 0x08);
+ input_report_key(dev, BTN_EXTRA, data[0] & 0x10);
+
+ input_report_rel(dev, REL_X, data[1]);
+ input_report_rel(dev, REL_Y, data[2]);
+ input_report_rel(dev, REL_WHEEL, data[3]);
+}
+
+static int usb_mouse_open(struct input_dev *dev)
+{
+ struct usb_mouse *mouse = dev->private;
+
+ if (mouse->open++)
+ return 0;
+
+ mouse->irq.dev = mouse->usbdev;
+ if (usb_submit_urb(&mouse->irq))
+ return -EIO;
+
+ return 0;
+}
+
+static void usb_mouse_close(struct input_dev *dev)
+{
+ struct usb_mouse *mouse = dev->private;
+
+ if (!--mouse->open)
+ usb_unlink_urb(&mouse->irq);
+}
+
+static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
+ const struct usb_device_id *id)
+{
+ struct usb_interface *iface;
+ struct usb_interface_descriptor *interface;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_mouse *mouse;
+ int pipe, maxp;
+ char *buf;
+
+ iface = &dev->actconfig->interface[ifnum];
+ interface = &iface->altsetting[iface->act_altsetting];
+
+ if (interface->bNumEndpoints != 1) return NULL;
+
+ endpoint = interface->endpoint + 0;
+ if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
+ if ((endpoint->bmAttributes & 3) != 3) return NULL;
+
+ /* wacom tablets match... */
+ if (dev->descriptor.idVendor == 0x056a)
+ {
+#ifdef __JEJ_DEBUG
+ printk(KERN_INFO __FILE__ ": usb_mouse_probe: ignoring wacom\n");
+#endif
+ return NULL;
+ }
+
+ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+ usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
+
+ if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
+ memset(mouse, 0, sizeof(struct usb_mouse));
+
+ mouse->usbdev = dev;
+
+ mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+ mouse->dev.relbit[0] |= BIT(REL_WHEEL);
+
+ mouse->dev.private = mouse;
+ mouse->dev.open = usb_mouse_open;
+ mouse->dev.close = usb_mouse_close;
+
+ mouse->dev.name = mouse->name;
+ mouse->dev.idbus = BUS_USB;
+ mouse->dev.idvendor = dev->descriptor.idVendor;
+ mouse->dev.idproduct = dev->descriptor.idProduct;
+ mouse->dev.idversion = dev->descriptor.bcdDevice;
+
+ if (!(buf = kmalloc(63, GFP_KERNEL))) {
+ kfree(mouse);
+ return NULL;
+ }
+
+ if (dev->descriptor.iManufacturer &&
+ usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
+ strcat(mouse->name, buf);
+ if (dev->descriptor.iProduct &&
+ usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
+ sprintf(mouse->name, "%s %s", mouse->name, buf);
+
+ if (!strlen(mouse->name))
+ sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
+ mouse->dev.idvendor, mouse->dev.idproduct);
+
+ kfree(buf);
+
+ FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
+ usb_mouse_irq, mouse, endpoint->bInterval);
+
+ input_register_device(&mouse->dev);
+
+ printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n",
+ mouse->dev.number, mouse->name, dev->bus->busnum, dev->devnum, ifnum);
+
+ return mouse;
+}
+
+static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
+{
+ struct usb_mouse *mouse = ptr;
+ usb_unlink_urb(&mouse->irq);
+ input_unregister_device(&mouse->dev);
+ kfree(mouse);
+}
+
+static struct usb_device_id usb_mouse_id_table [] = {
+ { USB_INTERFACE_INFO(3, 1, 2) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
+
+static struct usb_driver usb_mouse_driver = {
+ name: "usb_mouse",
+ probe: usb_mouse_probe,
+ disconnect: usb_mouse_disconnect,
+ id_table: usb_mouse_id_table,
+};
+
+static int __init usb_mouse_init(void)
+{
+#ifdef __JEJ_DEBUG
+ printk(KERN_INFO __FILE__ ": usb_mouse_init (MODIFIED DEBUG)\n");
+#endif
+ usb_register(&usb_mouse_driver);
+ info(DRIVER_VERSION ":" DRIVER_DESC);
+ return 0;
+}
+
+static void __exit usb_mouse_exit(void)
+{
+ usb_deregister(&usb_mouse_driver);
+}
+
+module_init(usb_mouse_init);
+module_exit(usb_mouse_exit);
diff --git a/src/wacdump.c b/src/wacdump.c
new file mode 100644
index 0000000..241baee
--- /dev/null
+++ b/src/wacdump.c
@@ -0,0 +1,716 @@
+/*****************************************************************************
+** wacdump.c
+**
+** Copyright (C) 2002 - John E. Joganic
+**
+** 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** REVISION HISTORY
+** 2002-12-21 0.3.4 - changed to FILE* to file descriptors
+** 2002-12-17 0.3.3 - split ncurses from main file to avoid namespace
+** collision in linux/input.h
+**
+****************************************************************************/
+
+#include "wacscrn.h"
+#include "wacserial.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+
+#define WACDUMP_VER "wacdump v0.3.4"
+
+/* from linux/input.h */
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define BIT(x) (1UL<<((x)%BITS_PER_LONG))
+#define LONG(x) ((x)/BITS_PER_LONG)
+
+static int InitUSB(int fd);
+static void FetchUSB(int fd);
+static int InitSerial(WACOMTABLET hTablet);
+void FetchSerial(WACOMTABLET hTablet);
+static const char* GetTypeCode(unsigned short wCode);
+static const char* GetRelCode(unsigned short wCode);
+static const char* GetAbsCode(unsigned short wCode);
+static const char* GetKeyCode(unsigned short wCode);
+static void DisplayEv(unsigned short wCode);
+static void DisplayRel(unsigned short wCode);
+static void DisplayAbs(unsigned short wCode);
+static void DisplayKey(unsigned short wCode);
+static void DisplayToolSerial(void);
+
+static void DisplaySerialValue(unsigned int uField);
+static void DisplaySerialButton(unsigned int uCode);
+
+struct EV_STATE
+{
+ int bValid;
+ int nRow;
+ struct input_event ev;
+};
+
+struct REL_STATE
+{
+ int bValid;
+ int nRow, nCol;
+ int nValue;
+};
+
+struct ABS_STATE
+{
+ int bValid;
+ int nRow, nCol;
+ int nValue, nMin, nMax;
+};
+
+struct KEY_STATE
+{
+ int bValid;
+ int nRow, nCol;
+ int nValue;
+};
+
+struct SERIAL_STATE
+{
+ int nRow;
+ int nSerial;
+};
+
+ struct EV_STATE gEvState[EV_MAX];
+ struct ABS_STATE gRelState[REL_MAX];
+ struct ABS_STATE gAbsState[ABS_MAX];
+ struct KEY_STATE gKeyState[KEY_MAX];
+ struct SERIAL_STATE gSerialState;
+
+static int InitUSB(int fd)
+{
+ int nCnt, nItem, nRow=0;
+ unsigned short i;
+ char chBuf[256];
+ short sID[4];
+ int nAbs[5];
+ unsigned long evbits[NBITS(EV_MAX)];
+ unsigned long absbits[NBITS(ABS_MAX)];
+ unsigned long relbits[NBITS(REL_MAX)];
+ unsigned long keybits[NBITS(KEY_MAX)];
+
+ /* Identify program and version */
+ wacscrn_standout();
+ for (i=0; i<80; ++i) wacscrn_output(nRow,i," ");
+ wacscrn_output(nRow,0,WACDUMP_VER);
+ wacscrn_normal();
+ nRow += 2;
+
+ /* Get device name and id */
+ if (ioctl(fd,EVIOCGNAME(sizeof(chBuf)),chBuf) < 0)
+ strncpy(chBuf,"Unknown Device Name",sizeof(chBuf));
+ wacscrn_output(nRow,0,chBuf);
+ if (ioctl(fd,EVIOCGID,sID) < 0)
+ strncpy(chBuf,"No ID",sizeof(chBuf));
+ else
+ snprintf(chBuf,sizeof(chBuf),"bus=%X, vndr=%X, prd=%X, ver=%X",
+ sID[0], sID[1], sID[2], sID[3]);
+ wacscrn_output(nRow,40,chBuf);
+ nRow += 2;
+
+ /* Get event types supported */
+ nItem = 0;
+ memset(gEvState,0,sizeof(gEvState));
+ nCnt = ioctl(fd,EVIOCGBIT(0 /*EV*/,sizeof(evbits)),evbits);
+ if (nCnt < 0) { perror("Failed to CGBIT"); return 1; }
+ assert(nCnt == sizeof(evbits));
+ for (i=0; i<EV_MAX; ++i)
+ {
+ if (evbits[LONG(i)] & BIT(i))
+ {
+ gEvState[i].bValid = 1;
+ gEvState[i].nRow = nRow + nItem;
+ DisplayEv(i);
+ ++nItem;
+ }
+ }
+ nRow += nItem + 1;
+
+ /* get absolute event types supported, ranges, and immediate values */
+ nItem = 0;
+ memset(gAbsState,0,sizeof(gAbsState));
+ if (evbits[LONG(EV_ABS)] & BIT(EV_ABS))
+ {
+ nCnt = ioctl(fd,EVIOCGBIT(EV_ABS,sizeof(absbits)),absbits);
+ if (nCnt < 0) { perror("Failed to CGBIT"); return 1; }
+ assert(nCnt == sizeof(absbits));
+ for (i=0; i<ABS_MAX; ++i)
+ {
+ if (absbits[LONG(i)] & BIT(i))
+ {
+ ioctl(fd, EVIOCGABS(i), nAbs);
+ gAbsState[i].bValid = 1;
+ gAbsState[i].nValue = nAbs[0];
+ gAbsState[i].nMin = nAbs[1];
+ gAbsState[i].nMax = nAbs[2];
+ gAbsState[i].nRow = nRow + nItem / 2;
+ gAbsState[i].nCol = nItem % 2;
+ DisplayAbs(i);
+ ++nItem;
+ }
+ }
+ }
+ nRow += ((nItem + 1) / 2) + 1;
+
+ /* get relative event types supported, ranges, and immediate values */
+ nItem = 0;
+ memset(gRelState,0,sizeof(gRelState));
+ if (evbits[LONG(EV_REL)] & BIT(EV_REL))
+ {
+ nCnt = ioctl(fd,EVIOCGBIT(EV_REL,sizeof(relbits)),relbits);
+ if (nCnt < 0) { perror("Failed to CGBIT"); return 1; }
+ assert(nCnt == sizeof(relbits));
+ for (i=0; i<REL_MAX; ++i)
+ {
+ if (relbits[LONG(i)] & BIT(i))
+ {
+ gRelState[i].bValid = 1;
+ gRelState[i].nValue = 0; /* start at zero */
+ gRelState[i].nRow = nRow + nItem / 4;
+ gRelState[i].nCol = nItem % 4;
+ DisplayRel(i);
+ ++nItem;
+ }
+ }
+ }
+ nRow += ((nItem + 1) / 4) + 1;
+
+ /* Get serial */
+ gSerialState.nRow = nRow;
+ gSerialState.nSerial = 0;
+ nRow += 2;
+
+ /* get key event types supported */
+ nItem = 0;
+ memset(gKeyState,0,sizeof(gKeyState));
+ if (evbits[LONG(EV_KEY)] & BIT(EV_KEY))
+ {
+ nCnt = ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(keybits)),keybits);
+ if (nCnt < 0) { perror("Failed to CGBIT"); return 1; }
+ assert(nCnt == sizeof(keybits));
+ for (i=0; i<KEY_MAX; ++i)
+ {
+ if (keybits[LONG(i)] & BIT(i))
+ {
+ /* fetching key state not possible :( */
+ gKeyState[i].bValid = 1;
+ gKeyState[i].nRow = nRow + nItem / 4;
+ gKeyState[i].nCol = nItem % 4;
+ DisplayKey(i);
+ ++nItem;
+ }
+ }
+ }
+ nRow += ((nItem + 3) / 4) + 1;
+ return 0;
+}
+
+void DisplayEv(unsigned short wCode)
+{
+ static char xchBuf[256];
+ if ((wCode >= EV_MAX) || !gEvState[wCode].bValid)
+ {
+ snprintf(xchBuf,sizeof(xchBuf),"Bad EV Code: 0x%X",wCode);
+ wacscrn_output(23,0,xchBuf);
+ return;
+ }
+
+ snprintf(xchBuf,sizeof(xchBuf),"%4s=%08lX.%08lX %04X %04X %08X",
+ GetTypeCode(wCode),
+ gEvState[wCode].ev.time.tv_sec,
+ gEvState[wCode].ev.time.tv_usec,
+ gEvState[wCode].ev.type,
+ gEvState[wCode].ev.code,
+ gEvState[wCode].ev.value);
+ wacscrn_output(gEvState[wCode].nRow,0,xchBuf);
+}
+
+
+void DisplayRel(unsigned short wCode)
+{
+ static char xchBuf[256];
+ if ((wCode >= REL_MAX) || !gRelState[wCode].bValid)
+ {
+ snprintf(xchBuf,sizeof(xchBuf),"Bad REL Code: 0x%X",wCode);
+ wacscrn_output(24,0,xchBuf);
+ return;
+ }
+
+ snprintf(xchBuf,sizeof(xchBuf),"%8s=%+06d",
+ GetRelCode(wCode), gRelState[wCode].nValue);
+
+ wacscrn_output(gRelState[wCode].nRow,gRelState[wCode].nCol*20,xchBuf);
+}
+
+void DisplayAbs(unsigned short wCode)
+{
+ static char xchBuf[256];
+ if ((wCode >= ABS_MAX) || !gAbsState[wCode].bValid)
+ {
+ snprintf(xchBuf,sizeof(xchBuf),"Bad ABS Code: 0x%X",wCode);
+ wacscrn_output(24,0,xchBuf);
+ return;
+ }
+
+ snprintf(xchBuf,sizeof(xchBuf),"%8s=%+06d (%+06d .. %+06d)",
+ GetAbsCode(wCode),
+ gAbsState[wCode].nValue,
+ gAbsState[wCode].nMin,
+ gAbsState[wCode].nMax);
+ wacscrn_output(gAbsState[wCode].nRow,gAbsState[wCode].nCol*40,xchBuf);
+}
+
+static void DisplayToolSerial(void)
+{
+ static char xchBuf[256];
+ snprintf(xchBuf,sizeof(xchBuf)," SERIAL=%08X",gSerialState.nSerial);
+ wacscrn_output(gSerialState.nRow,0,xchBuf);
+}
+
+static void DisplayKey(unsigned short wCode)
+{
+ int bDown;
+ static char xchBuf[256];
+ if ((wCode >= KEY_MAX) || !gKeyState[wCode].bValid)
+ {
+ snprintf(xchBuf,sizeof(xchBuf),"Bad Key Code: 0x%X",wCode);
+ wacscrn_output(24,0,xchBuf);
+ return;
+ }
+
+ bDown = gKeyState[wCode].nValue ? 1 : 0;
+
+ snprintf(xchBuf,sizeof(xchBuf),"%8s=%s",
+ GetKeyCode(wCode), bDown ? "DOWN" : " ");
+
+ if (bDown) wacscrn_standout();
+ wacscrn_output(gKeyState[wCode].nRow,gKeyState[wCode].nCol*20,xchBuf);
+ wacscrn_normal();
+}
+
+static const char* GetTypeCode(unsigned short wCode)
+{
+ static const char* xszEv[] =
+ {
+ "RST", "KEY", "REL", "ABS", "MSC"
+ };
+
+ return (wCode >= (sizeof(xszEv)/sizeof(*xszEv))) ?
+ "EV?" : xszEv[wCode];
+}
+
+static const char* GetRelCode(unsigned short wCode)
+{
+ static const char* xszRel[] =
+ {
+ "X", "Y", "Z", "0x03", "0x04", "0x05", "HWHEEL",
+ "DIAL", "WHEEL", "MISC"
+ };
+
+ return (wCode > REL_MISC) ? "KEY?" : xszRel[wCode];
+}
+
+static const char* GetAbsCode(unsigned short wCode)
+{
+ static const char* xszAbs[] =
+ {
+ "X", "Y", "Z", "RX", "RY", "RZ",
+ "THROTTLE", "RUDDER", "WHEEL", "GAS", "BRAKE",
+ "0x0B", "0x0C", "0x0D", "0x0E", "0x0F",
+ "HAT0X", "HAT0Y", "HAT1X", "HAT1Y",
+ "HAT2X", "HAT2Y", "HAY3X", "HAT3Y",
+ "PRESSURE", "DISTANCE", "TILT_X", "TILT_Y",
+ "MISC"
+ };
+
+ return (wCode > ABS_MISC) ? "KEY?" : xszAbs[wCode];
+}
+
+static const char* GetKeyCode(unsigned short wCode)
+{
+ static const char* xszMouseKey[] =
+ {
+ "LEFT", "RIGHT", "MIDDLE", "SIDE", "EXTRA", "FORWARD",
+ "BACK"
+ };
+
+ static const char* xszToolKey[] =
+ {
+ "PEN", "RUBBER", "BRUSH", "PENCIL", "AIR",
+ "FINGER", "MOUSE", "LENS",
+ "0x148", "0x149", "TOUCH", "STYLUS", "STYLUS2"
+ };
+
+ static char xchBuf[16];
+
+ if ((wCode >= BTN_LEFT) && (wCode <= BTN_BACK))
+ return xszMouseKey[wCode - BTN_LEFT];
+
+ if ((wCode >= BTN_TOOL_PEN) && (wCode <= BTN_STYLUS2))
+ return xszToolKey[wCode - BTN_TOOL_PEN];
+
+ snprintf(xchBuf,sizeof(xchBuf),"K_%X",wCode);
+ return xchBuf;
+}
+
+void Usage(void)
+{
+ fprintf(stderr,"Usage: wacdump [-d device]\n"
+ " -?, -h, --help - usage\n"
+ " -d, --device device - use specified device\n");
+}
+
+static void termscr(void)
+{
+ wacscrn_term();
+}
+
+static void FetchUSB(int fd)
+{
+ int nCnt, nXfer;
+ struct input_event ev;
+
+ while (1)
+ {
+ /* read one whole event record */
+ nCnt=0;
+ while (nCnt < sizeof(ev))
+ {
+ nXfer = read(fd,((char*)&ev)+nCnt,sizeof(ev)-nCnt);
+ if (nXfer == 0) break;
+ nCnt += nXfer;
+ }
+
+ if (ev.type < EV_MAX)
+ {
+ gEvState[ev.type].ev = ev;
+ DisplayEv(ev.type);
+ }
+
+ if (ev.type == EV_MSC)
+ {
+ gSerialState.nSerial = ev.value;
+ DisplayToolSerial();
+ }
+ else if ((ev.type == EV_KEY) && (ev.code < KEY_MAX))
+ {
+ gKeyState[ev.code].nValue = ev.value;
+ DisplayKey(ev.code);
+ }
+ else if ((ev.type == EV_ABS) && (ev.code < ABS_MAX))
+ {
+ gAbsState[ev.code].nValue = ev.value;
+ DisplayAbs(ev.code);
+ }
+ else if ((ev.type == EV_REL) && (ev.code < REL_MAX))
+ {
+ gRelState[ev.code].nValue += ev.value;
+ DisplayRel(ev.code);
+ }
+
+ wacscrn_refresh();
+ }
+}
+
+static int InitSerial(WACOMTABLET hTablet)
+{
+ int i, nCaps, nItem, nRow=0;
+ int nMajor, nMinor, nRelease;
+ char chBuf[256];
+ WACOMMODEL model;
+ WACOMSTATE min, max;
+ const char* pszName;
+
+ /* Identify program and version */
+ wacscrn_standout();
+ for (i=0; i<80; ++i) wacscrn_output(nRow,i," ");
+ wacscrn_output(nRow,0,WACDUMP_VER);
+ wacscrn_normal();
+ nRow += 2;
+
+ /* Get device name, ROM, and model */
+ model = WacomGetModel(hTablet);
+ pszName = WacomGetModelName(hTablet);
+ WacomGetRomVersion(hTablet,&nMajor,&nMinor,&nRelease);
+ wacscrn_output(nRow,0,pszName);
+ snprintf(chBuf,sizeof(chBuf),"SERIAL model=0x%X ROM=%d.%d-%d",
+ model, nMajor, nMinor, nRelease);
+ wacscrn_output(nRow,40,chBuf);
+ nRow += 2;
+
+ gEvState[0].nRow = nRow++; /* data */
+ nRow += 2;
+
+ /* get event types supported, ranges, and immediate values */
+ nCaps = WacomGetCapabilities(hTablet);
+ WacomGetRanges(hTablet,&min,&max);
+
+ nItem = 0;
+ for (i=0; i<31; ++i)
+ {
+ if (nCaps & (1<<i))
+ {
+ gAbsState[i].bValid = 1;
+ gAbsState[i].nValue = 0;
+ gAbsState[i].nMin = ((int*)(&min))[i + 1];
+ gAbsState[i].nMax = ((int*)(&max))[i + 1];
+ gAbsState[i].nRow = nRow + nItem / 2;
+ gAbsState[i].nCol = nItem % 2;
+ DisplaySerialValue(i);
+ ++nItem;
+ }
+ }
+ nRow += ((nItem + 1) / 2) + 1;
+
+ /* get key event types */
+ nItem = 0;
+ for (i=0; i<WACOMBUTTON_MAX; ++i)
+ {
+ gKeyState[i].bValid = 1;
+ gKeyState[i].nRow = nRow + nItem / 4;
+ gKeyState[i].nCol = nItem % 4;
+ DisplaySerialButton(i);
+ ++nItem;
+ }
+ nRow += ((nItem + 3) / 4) + 1;
+ return 0;
+}
+
+const char* GetSerialField(unsigned int uField)
+{
+ static const char* xszField[WACOMFIELD_MAX] =
+ {
+ "TOOLTYPE", "SERIAL", "IN_PROX", "BUTTON",
+ "POS_X", "POS_Y", "ROT_Z", "DISTANCE",
+ "PRESSURE", "TILT_X", "TILT_Y", "ABSWHEEL",
+ "RELWHEEL", "THROTTLE"
+ };
+
+ return (uField >= WACOMFIELD_MAX) ? "FIELD?" : xszField[uField];
+}
+
+static void DisplaySerialValue(unsigned int uField)
+{
+ static char xchBuf[256];
+ if ((uField >= WACOMFIELD_MAX) || !gAbsState[uField].bValid)
+ {
+ snprintf(xchBuf,sizeof(xchBuf),"Bad FIELD Code: 0x%X",uField);
+ wacscrn_output(24,0,xchBuf);
+ return;
+ }
+
+ snprintf(xchBuf,sizeof(xchBuf),"%8s=%+06d (%+06d .. %+06d)",
+ GetSerialField(uField),
+ gAbsState[uField].nValue,
+ gAbsState[uField].nMin,
+ gAbsState[uField].nMax);
+ wacscrn_output(gAbsState[uField].nRow,gAbsState[uField].nCol*40,xchBuf);
+}
+
+const char* GetSerialButton(unsigned int uButton)
+{
+ static const char* xszButton[WACOMBUTTON_MAX] =
+ {
+ "LEFT", "MIDDLE", "RIGHT", "EXTRA", "SIDE",
+ "TOUCH", "STYLUS", "STYLUS2"
+ };
+
+ return (uButton >= WACOMBUTTON_MAX) ? "FIELD?" : xszButton[uButton];
+}
+
+
+static void DisplaySerialButton(unsigned int uButton)
+{
+ int bDown;
+ static char xchBuf[256];
+ if ((uButton >= WACOMBUTTON_MAX) || !gKeyState[uButton].bValid)
+ {
+ snprintf(xchBuf,sizeof(xchBuf),"Bad Button Code: 0x%X",uButton);
+ wacscrn_output(24,0,xchBuf);
+ return;
+ }
+
+ bDown = gKeyState[uButton].nValue ? 1 : 0;
+
+ snprintf(xchBuf,sizeof(xchBuf),"%8s=%s",
+ GetSerialButton(uButton), bDown ? "DOWN" : " ");
+
+ if (bDown) wacscrn_standout();
+ wacscrn_output(gKeyState[uButton].nRow,gKeyState[uButton].nCol*20,xchBuf);
+ wacscrn_normal();
+}
+
+void FetchSerial(WACOMTABLET hTablet)
+{
+ char chOut[16];
+ unsigned char uchBuf[16];
+ int i, nLength, nRow=gEvState[0].nRow;
+ WACOMSTATE state;
+
+ while (1)
+ {
+ nLength = WacomReadRaw(hTablet,uchBuf,sizeof(uchBuf));
+ if (nLength < 0) break;
+
+ if (WacomParseData(hTablet,uchBuf,nLength,&state)) break;
+
+ gAbsState[WACOMFIELD_PROXIMITY].nValue = state.nProximity;
+ gAbsState[WACOMFIELD_BUTTONS].nValue = state.nButtons;
+ gAbsState[WACOMFIELD_TOOLTYPE].nValue = state.nToolType;
+ gAbsState[WACOMFIELD_POSITION_X].nValue = state.nPosX;
+ gAbsState[WACOMFIELD_POSITION_Y].nValue = state.nPosY;
+ gAbsState[WACOMFIELD_ROTATION_Z].nValue = state.nRotZ;
+ gAbsState[WACOMFIELD_PRESSURE].nValue = state.nPressure;
+ gAbsState[WACOMFIELD_SERIAL].nValue = state.nSerial;
+ gAbsState[WACOMFIELD_TILT_X].nValue = state.nTiltX;
+ gAbsState[WACOMFIELD_TILT_Y].nValue = state.nTiltY;
+ gAbsState[WACOMFIELD_ABSWHEEL].nValue = state.nAbsWheel;
+ gAbsState[WACOMFIELD_RELWHEEL].nValue += state.nRelWheel;
+ gAbsState[WACOMFIELD_THROTTLE].nValue = state.nThrottle;
+ DisplaySerialValue(WACOMFIELD_PROXIMITY);
+ DisplaySerialValue(WACOMFIELD_BUTTONS);
+ DisplaySerialValue(WACOMFIELD_TOOLTYPE);
+ DisplaySerialValue(WACOMFIELD_POSITION_X);
+ DisplaySerialValue(WACOMFIELD_POSITION_Y);
+ DisplaySerialValue(WACOMFIELD_ROTATION_Z);
+ DisplaySerialValue(WACOMFIELD_PRESSURE);
+ DisplaySerialValue(WACOMFIELD_SERIAL);
+ DisplaySerialValue(WACOMFIELD_TILT_X);
+ DisplaySerialValue(WACOMFIELD_TILT_Y);
+ DisplaySerialValue(WACOMFIELD_ABSWHEEL);
+ DisplaySerialValue(WACOMFIELD_RELWHEEL);
+ DisplaySerialValue(WACOMFIELD_THROTTLE);
+ gKeyState[WACOMBUTTON_TOUCH].nValue = state.nButtons &
+ (1 << WACOMBUTTON_TOUCH) ? 1 : 0;
+ gKeyState[WACOMBUTTON_STYLUS].nValue = state.nButtons &
+ (1 << WACOMBUTTON_STYLUS) ? 1 : 0;
+ gKeyState[WACOMBUTTON_STYLUS2].nValue = state.nButtons &
+ (1 << WACOMBUTTON_STYLUS2) ? 1 : 0;
+ gKeyState[WACOMBUTTON_LEFT].nValue = state.nButtons &
+ (1 << WACOMBUTTON_LEFT) ? 1 : 0;
+ gKeyState[WACOMBUTTON_MIDDLE].nValue = state.nButtons &
+ (1 << WACOMBUTTON_MIDDLE) ? 1 : 0;
+ gKeyState[WACOMBUTTON_RIGHT].nValue = state.nButtons &
+ (1 << WACOMBUTTON_RIGHT) ? 1 : 0;
+ gKeyState[WACOMBUTTON_EXTRA].nValue = state.nButtons &
+ (1 << WACOMBUTTON_EXTRA) ? 1 : 0;
+ gKeyState[WACOMBUTTON_SIDE].nValue = state.nButtons &
+ (1 << WACOMBUTTON_SIDE) ? 1 : 0;
+ DisplaySerialButton(WACOMBUTTON_TOUCH);
+ DisplaySerialButton(WACOMBUTTON_STYLUS);
+ DisplaySerialButton(WACOMBUTTON_STYLUS2);
+ DisplaySerialButton(WACOMBUTTON_LEFT);
+ DisplaySerialButton(WACOMBUTTON_MIDDLE);
+ DisplaySerialButton(WACOMBUTTON_RIGHT);
+ DisplaySerialButton(WACOMBUTTON_EXTRA);
+ DisplaySerialButton(WACOMBUTTON_SIDE);
+
+ for (i=0; i<nLength; ++i)
+ {
+ snprintf(chOut,sizeof(chOut),"%02X",uchBuf[i]);
+ wacscrn_output(nRow,i*3,chOut);
+ }
+ for (i=0; i<nLength; ++i)
+ {
+ snprintf(chOut,sizeof(chOut),"%c",isprint(uchBuf[i]) ?
+ uchBuf[i] : '.');
+ wacscrn_output(nRow,60 + i,chOut);
+ }
+
+ wacscrn_refresh();
+ }
+}
+
+int main(int argc, char** argv)
+{
+ int fd;
+ const char* pszFile = NULL;
+ const char* arg;
+
+ /* parse args */
+ ++argv;
+ while (*argv)
+ {
+ arg = *(argv++);
+ if ((strcmp(arg,"-?") == 0) || (strcmp(arg,"-h") == 0) ||
+ (strcmp(arg,"--help")==0))
+ {
+ Usage();
+ exit(0);
+ }
+ if ((strcmp(arg,"-d") == 0) || (strcmp(arg,"--device") == 0))
+ {
+ arg = *(argv++);
+ if (arg == NULL) { fprintf(stderr,"Missing device\n"); exit(1); }
+ pszFile = arg;
+ }
+ else
+ {
+ fprintf(stderr,"Unknown argument %s\n",arg);
+ exit(1);
+ }
+ }
+
+ /* default device if not specified */
+ if (!pszFile) pszFile = "/dev/input/event0";
+
+ /* open input device */
+ fd = open(pszFile,O_RDONLY);
+ if (fd < 0) { perror("Failed to open device"); exit(1); }
+
+ /* if it is serial, close and try again */
+ if (isatty(fd))
+ {
+ WACOMTABLET hTablet = NULL;
+
+ close(fd);
+ hTablet = WacomOpenSerial(pszFile);
+ if (!hTablet) exit(1);
+
+ /* begin curses window mode */
+ wacscrn_init();
+ atexit(termscr);
+
+ /* get device capabilities, build screen */
+ if (InitSerial(hTablet)) { WacomCloseSerial(hTablet); exit(1); }
+ FetchSerial(hTablet);
+ WacomCloseSerial(hTablet);
+ return 0;
+ }
+
+ /* begin curses window mode */
+ wacscrn_init();
+ atexit(termscr);
+
+ /* get device capabilities, build screen */
+ if (InitUSB(fd)) { close(fd); exit(1); }
+ FetchUSB(fd);
+ close(fd);
+ return 0;
+}
+
diff --git a/src/wacom.c b/src/wacom.c
new file mode 100644
index 0000000..be46f91
--- /dev/null
+++ b/src/wacom.c
@@ -0,0 +1,690 @@
+/*
+ * $Id: wacom.c,v 1.1.1.1 2002/12/23 02:44:48 jjoganic Exp $
+ *
+ * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk>
+ * Copyright (c) 2000 Clifford Wolf <clifford@clifford.at>
+ * Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org>
+ * Copyright (c) 2000 James E. Blair <corvus@gnu.org>
+ * Copyright (c) 2000 Daniel Egger <egger@suse.de>
+ * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
+ * Copyright (c) 2002 Christer Nilsson <christer.nilsson@kretskompaniet.se>
+ * Copyright (c) 2002 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002 John Joganic <john@joganic.com>
+ *
+ * USB Wacom Graphire and Intuos tablet support
+ *
+ * Sponsored by SuSE
+ *
+ * ChangeLog:
+ * v0.1 (vp) - Initial release
+ * v0.2 (aba) - Support for all buttons / combinations
+ * v0.3 (vp) - Support for Intuos added
+ * v0.4 (sm) - Support for more Intuos models, menustrip
+ * relative mode, proximity.
+ * v0.5 (vp) - Big cleanup, nifty features removed,
+ * they belong in userspace
+ * v1.8 (vp) - Submit URB only when operating, moved to CVS,
+ * use input_report_key instead of report_btn and
+ * other cleanups
+ * v1.11 (vp) - Add URB ->dev setting for new kernels
+ * v1.11 (jb) - Add support for the 4D Mouse & Lens
+ * v1.12 (de) - Add support for two more inking pen IDs
+ * v1.14 (vp) - Use new USB device id probing scheme.
+ * Fix Wacom Graphire mouse wheel
+ * v1.18 (vp) - Fix mouse wheel direction
+ * Make mouse relative
+ * v1.20 (fl) - Report tool id for Intuos devices
+ * - Multi tools support
+ * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
+ * - Add PL models support
+ * - Fix Wacom Graphire mouse wheel again
+ * v1.21 (vp) - Removed protocol descriptions
+ * - Added MISC_SERIAL for tool serial numbers
+ * (gb) - Identify version on module load.
+ * v1.21.1 (fl) - added Graphire2 support
+ * v1.21.2 (fl) - added Intuos2 support
+ * - added all the PL ids
+ * v1.21.3 (fl) - added another eraser id from Neil Okamoto
+ * - added smooth filter for Graphire from Peri Hankey
+ * - added PenPartner support from Olaf van Es
+ * - new tool ids from Ole Martin Bjoerndalen
+ * v1.29 (pc) - Add support for more tablets
+ * - Fix pressure reporting
+ * v1.30 (vp) - Merge 2.4 and 2.5 drivers
+ * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
+ * - Cleanups here and there
+ *
+ * WARNING: THIS IS NOT PART OF THE OFFICIAL KERNEL TREE
+ * THIS IS FOR TESTING PURPOSES
+ *
+ * v1.21.3-j0 - fixed absolute x and y for intuos by John Joganic
+ * v1.21.3-j1 - applied Christer Nilsson's patches for 2.4.20
+ * v1.30.1-j0 - applied Ping Cheng's patches for device ranges and caps
+ * v1.30.1-j1 - updated device ranges for Intuos2 12x12 (0x44)
+ * v1.30.1-j2 - updated device ranges for Intuos2 6x8 (0x42)
+ * v1.30-j0.3.1 - fixed pen identifers, 2D mouse handling
+ * v1.30-j0.3.3 - added volito, thanks to Pasi Savolainen; fixed wheel sign
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/autoconf.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+# define MODVERSIONS
+#endif
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.30-j0.3.3"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#ifndef __JEJ_DEBUG
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver (MODIFIED)"
+#else
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver (MODIFIED-DEBUG)"
+#endif
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define USB_VENDOR_ID_WACOM 0x056a
+
+struct wacom_features {
+ char *name;
+ int pktlen;
+ int x_max;
+ int y_max;
+ int pressure_max;
+ int distance_max;
+ void (*irq)(struct urb *urb);
+ unsigned long evbit;
+ unsigned long absbit;
+ unsigned long relbit;
+ unsigned long btnbit;
+ unsigned long digibit;
+};
+
+struct wacom {
+ signed char data[10];
+ struct input_dev dev;
+ struct usb_device *usbdev;
+ struct urb irq;
+ struct wacom_features *features;
+ int tool[2];
+ int open;
+ __u32 serial[2];
+};
+
+static void wacom_pl_irq(struct urb *urb)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ int prox, pressure;
+
+ if (urb->status) return;
+
+ if (data[0] != 2) {
+ printk(KERN_ERR "wacom_pl_irq: received unknown report #%d\n", data[0]);
+ return;
+ }
+
+ /* Cheng proximity and pressure code */
+ prox = data[1] & 0x40;
+
+ if (prox) {
+ pressure = (signed char) ((data[7] <<1 ) | ((data[4] >> 2) & 1));
+ if ( wacom->features->pressure_max > 350 ) {
+ pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+ }
+ pressure += (( wacom->features->pressure_max + 1 )/ 2);
+
+ /*
+ * if going from out of proximity into proximity select between the eraser
+ * and the pen based on the state of the stylus2 button, choose eraser if
+ * pressed else choose pen. if not a proximity change from out to in stay
+ * with the previously selected tool.
+ */
+ if (!wacom->tool[0]) {
+ /* Going into proximity select tool */
+ wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+ }
+ else {
+ /* was entered with stylus2 pressed */
+ if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) {
+ wacom->tool[1] = BTN_TOOL_PEN;
+ }
+ }
+ if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+ /* Unknown tool selected default to pen tool */
+ wacom->tool[1] = BTN_TOOL_PEN;
+ }
+ input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
+
+ input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14));
+ input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14));
+ input_report_abs(dev, ABS_PRESSURE, pressure);
+ input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
+ input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
+ /* Only allow the stylus2 button to be reported for the pen tool. */
+ input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
+ }
+ else {
+ /* report proximity-out of a (valid) tool */
+ if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+ /* Unknown tool selected default to pen tool */
+ wacom->tool[1] = BTN_TOOL_PEN;
+ }
+ input_report_key(dev, wacom->tool[1], prox);
+ }
+
+ wacom->tool[0] = prox; /* Save proximity state */
+ /* end Cheng proximity code */
+
+ input_event(dev, EV_MSC, MSC_SERIAL, 0);
+}
+
+static void wacom_penpartner_irq(struct urb *urb)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ int leftmb = (((signed char)data[6] > -80) && !(data[5] &0x20));
+
+ if (urb->status) return;
+
+ input_report_key(dev, BTN_TOOL_PEN, 1);
+ input_report_abs(dev, ABS_X, data[2] << 8 | data[1]);
+ input_report_abs(dev, ABS_Y, data[4] << 8 | data[3]);
+ input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
+ input_report_key(dev, BTN_TOUCH, leftmb);
+ input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
+
+ input_event(dev, EV_MSC, MSC_SERIAL, leftmb);
+}
+
+static void wacom_graphire_irq(struct urb *urb)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ int x, y;
+
+ if (urb->status) return;
+
+ if (data[0] != 2) {
+ printk(KERN_ERR "wacom_graphire_irq: received unknown report #%d\n", data[0]);
+ return;
+ }
+
+ x = data[2] | ((__u32)data[3] << 8);
+ y = data[4] | ((__u32)data[5] << 8);
+
+ switch ((data[1] >> 5) & 3) {
+
+ case 0: /* Pen */
+ input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80);
+ break;
+
+ case 1: /* Rubber */
+ input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
+ break;
+
+ case 2: /* Mouse with wheel */
+ input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+ case 3: /* Mouse without wheel */
+ input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24);
+ input_report_key(dev, BTN_LEFT, data[1] & 0x01);
+ input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
+ input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
+ input_report_abs(dev, ABS_DISTANCE, data[7]);
+
+ input_report_abs(dev, ABS_X, x);
+ input_report_abs(dev, ABS_Y, y);
+
+ input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
+ return;
+ }
+
+ if (data[1] & 0x80) {
+ input_report_abs(dev, ABS_X, x);
+ input_report_abs(dev, ABS_Y, y);
+ }
+
+ input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+ input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+ input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
+ input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
+
+ input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
+}
+
+static void wacom_intuos_irq(struct urb *urb)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ unsigned int t;
+ int idx;
+
+ if (urb->status) return;
+
+ /* check for valid report */
+ if (data[0] != 2)
+ {
+ #ifndef __JEJ_DEBUG
+ printk(KERN_ERR "wacom_intuos_irq: received unknown report #%d\n",
+ data[0]);
+ #else
+ printk(KERN_ERR "wacom_intuos_irq: unknown report "
+ "%02X %02X %02X %02X\n",data[0], data[1], data[2], data[3]);
+ #endif
+ return;
+ }
+
+ /* tool index */
+ idx = data[1] & 0x01;
+
+ /* Enter report */
+ if ((data[1] & 0xfc) == 0xc0)
+ {
+ /* serial number of the tool */
+ wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 4) +
+ ((__u32)data[4] << 16) + ((__u32)data[5] << 12) +
+ ((__u32)data[6] << 4) + (data[7] >> 4);
+
+ #ifdef __JEJ_DEBUG
+ printk(KERN_INFO "wacom_intuos_irq: tool change 0x%03X\n",
+ (((__u32)data[2] << 4) | (data[3] >> 4)));
+ #endif
+
+ switch ((((__u32)data[2] << 4) | (data[3] >> 4)))
+ {
+ case 0x812: /* Intuos2 ink pen XP-110-00A */
+ case 0x012: /* Inking pen */
+ wacom->tool[idx] = BTN_TOOL_PENCIL; break;
+
+ case 0x822: /* Intuos Pen GP-300E-01H */
+ case 0x852: /* Intuos2 Grip Pen XP-501E-00A */
+ case 0x842: /* added from Cheng */
+ case 0x022:
+ wacom->tool[idx] = BTN_TOOL_PEN; break;
+
+ case 0x832: /* Intuos2 stroke pen XP-120-00A */
+ case 0x032: /* Stroke pen */
+ wacom->tool[idx] = BTN_TOOL_BRUSH; break;
+
+ case 0x007: /* 2D Mouse */
+ case 0x09C: /* ?? Mouse */
+ case 0x094: /* 4D Mouse */
+ wacom->tool[idx] = BTN_TOOL_MOUSE; break;
+
+ case 0x096: /* Lens cursor */
+ wacom->tool[idx] = BTN_TOOL_LENS; break;
+
+ case 0x82a:
+ case 0x85a:
+ case 0x91a:
+ case 0x0fa: /* Eraser */
+ wacom->tool[idx] = BTN_TOOL_RUBBER; break;
+
+ case 0x112: /* Airbrush */
+ wacom->tool[idx] = BTN_TOOL_AIRBRUSH; break;
+
+ default: /* Unknown tool */
+ wacom->tool[idx] = BTN_TOOL_PEN; break;
+ }
+
+ input_report_key(dev, wacom->tool[idx], 1);
+ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ return;
+ }
+
+ /* Exit report */
+ if ((data[1] & 0xfe) == 0x80)
+ {
+ input_report_key(dev, wacom->tool[idx], 0);
+ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ return;
+ }
+
+ input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
+ input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
+ input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
+
+ /* general pen packet */
+ if ((data[1] & 0xb8) == 0xa0)
+ {
+ t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
+ input_report_abs(dev, ABS_PRESSURE, t);
+ input_report_abs(dev, ABS_TILT_X,
+ ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+ input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+ input_report_key(dev, BTN_STYLUS, data[1] & 2);
+ input_report_key(dev, BTN_STYLUS2, data[1] & 4);
+ input_report_key(dev, BTN_TOUCH, t > 10);
+ }
+
+ /* airbrush second packet */
+ if ((data[1] & 0xbc) == 0xb4)
+ {
+ input_report_abs(dev, ABS_WHEEL,
+ ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+ input_report_abs(dev, ABS_TILT_X,
+ ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+ input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+ }
+
+ /* 4D mouse, 2D mouse, or Lens cursor packets */
+ if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0)
+ {
+ /* Rotation packet */
+ if (data[1] & 0x02)
+ {
+ input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
+ ((__u32)data[6] << 2) | ((data[7] >> 6) & 3):
+ (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1);
+ }
+
+ /* 4D mouse packets */
+ else if ((data[1] & 0x10) == 0)
+ {
+ input_report_key(dev, BTN_LEFT, data[8] & 0x01);
+ input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
+ input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
+ input_report_key(dev, BTN_SIDE, data[8] & 0x20);
+ input_report_key(dev, BTN_EXTRA, data[8] & 0x10);
+ /* JEJ - throttle is positive when rolled backwards */
+ input_report_abs(dev, ABS_THROTTLE, - ((data[8] & 0x08) ?
+ ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
+ -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)));
+ }
+
+ /* 2D mouse packets */
+ else if (wacom->tool[idx] == BTN_TOOL_MOUSE)
+ {
+ /* JEJ - validated with 2D Intuos2 mouse */
+ input_report_key(dev, BTN_LEFT, data[8] & 0x04);
+ input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
+ input_report_key(dev, BTN_RIGHT, data[8] & 0x10);
+ /* JEJ - mouse wheel is positive when rolled backwards */
+ input_report_rel(dev, REL_WHEEL, - (((__u32)(data[8] & 0x01)) -
+ ((__u32)((data[8] & 0x02) >> 1))));
+ }
+
+ /* lens cursor packets */
+ else
+ {
+ input_report_key(dev, BTN_LEFT, data[8] & 0x01);
+ input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
+ input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
+ input_report_key(dev, BTN_SIDE, data[8] & 0x10);
+ input_report_key(dev, BTN_EXTRA, data[8] & 0x08);
+ }
+ }
+
+ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+}
+
+#define WACOM_GRAPHIRE_BITS (BIT(EV_REL))
+#define WACOM_GRAPHIRE_REL (BIT(REL_WHEEL))
+#define WACOM_INTUOS_TOOLS (BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS))
+#define WACOM_INTUOS_BUTTONS (BIT(BTN_SIDE) | BIT(BTN_EXTRA))
+#define WACOM_INTUOS_BITS (BIT(EV_REL))
+#define WACOM_INTUOS_REL (BIT(REL_WHEEL))
+#define WACOM_INTUOS_ABS (BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE))
+
+struct wacom_features wacom_features[] = {
+
+ /* PenPartner */
+ /* 0 */ { "Wacom Penpartner", 7, 5040, 3780, 255, 32,
+ wacom_penpartner_irq, 0, 0, 0, 0 },
+
+ /* Graphire */
+ /* 1 */ { "Wacom Graphire", 8, 10206, 7422, 511, 32,
+ wacom_graphire_irq, WACOM_GRAPHIRE_BITS, 0, BIT(REL_WHEEL), 0 },
+ /* 2 */ { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32,
+ wacom_graphire_irq, WACOM_GRAPHIRE_BITS, 0, BIT(REL_WHEEL), 0 },
+ /* 3 */ { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32,
+ wacom_graphire_irq, WACOM_GRAPHIRE_BITS, 0, BIT(REL_WHEEL), 0 },
+
+ /* Intuos */
+ /* 4 */ { "Wacom Intuos 4x5", 10, 12700, 10360, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* JEJ - confirmed X and Y range from test tablet */
+ /* 5 */ { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* 6 */ { "Wacom Intuos 9x12", 10, 30670, 24130, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* 7 */ { "Wacom Intuos 12x12", 10, 30670, 31600, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* 8 */ { "Wacom Intuos 12x18", 10, 45860, 31600, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+
+ /* PL - Cintiq */
+ /* 9 */ { "Wacom PL400", 8, 5408, 4056, 255, 32,
+ wacom_pl_irq, 0, 0, 0, 0 },
+ /* 10 */ { "Wacom PL500", 8, 6144, 4608, 255, 32,
+ wacom_pl_irq, 0, 0, 0, 0 },
+ /* 11 */ { "Wacom PL600", 8, 6126, 4604, 255, 32,
+ wacom_pl_irq, 0, 0, 0, 0 },
+ /* 12 */ { "Wacom PL600SX", 8, 6260, 5016, 255, 32,
+ wacom_pl_irq, 0, 0, 0, 0 },
+ /* 13 */ { "Wacom PL550", 8, 6144, 4608, 511, 32,
+ wacom_pl_irq, 0, 0, 0, 0 },
+ /* 14 */ { "Wacom PL800", 8, 7220, 5780, 511, 32,
+ wacom_pl_irq, 0, 0, 0, 0 },
+
+ /* Intuos2 */
+ /* 15 */ { "Wacom Intuos2 4x5", 10, 12700, 10360, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* JEJ - confirmed X and Y range from R.T. and J.S. tablets */
+ /* 16 */ { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* JEJ - values from serial 9x12 */
+ /* 17 */ { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* JEJ - confirmed X and Y range from tablet */
+ /* 18 */ { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+ /* 19 */ { "Wacom Intuos2 12x18", 10, 45860, 31600, 1023, 15,
+ wacom_intuos_irq, WACOM_INTUOS_BITS, WACOM_INTUOS_ABS,
+ WACOM_INTUOS_REL, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+
+ /* Volito - (Graphire2 4x5 no mouse wheel) */
+ /* 20 */ { "Wacom Volito", 8, 10206, 7422, 511, 32,
+ wacom_graphire_irq, WACOM_GRAPHIRE_BITS, 0, 0, 0 },
+
+ { NULL , 0 }
+};
+
+struct usb_device_id wacom_ids[] = {
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00), driver_info: 0 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), driver_info: 1 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11), driver_info: 2 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12), driver_info: 3 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), driver_info: 4 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), driver_info: 5 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 6 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 7 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 8 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30), driver_info: 9 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 10 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32), driver_info: 11 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33), driver_info: 12 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34), driver_info: 13 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35), driver_info: 14 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41), driver_info: 15 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42), driver_info: 16 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43), driver_info: 17 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44), driver_info: 18 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45), driver_info: 19 },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60), driver_info: 20 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, wacom_ids);
+
+static int wacom_open(struct input_dev *dev)
+{
+ struct wacom *wacom = dev->private;
+
+ if (wacom->open++)
+ return 0;
+
+ wacom->irq.dev = wacom->usbdev;
+ if (usb_submit_urb(&wacom->irq))
+ return -EIO;
+
+ return 0;
+}
+
+static void wacom_close(struct input_dev *dev)
+{
+ struct wacom *wacom = dev->private;
+
+ if (!--wacom->open)
+ usb_unlink_urb(&wacom->irq);
+}
+
+static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+{
+ struct usb_endpoint_descriptor *endpoint;
+ struct wacom *wacom;
+ char rep_data[2] = {0x02, 0x02};
+
+ if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
+ memset(wacom, 0, sizeof(struct wacom));
+
+ wacom->features = wacom_features + id->driver_info;
+
+ wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) |
+ wacom->features->evbit;
+ wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) |
+ BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | wacom->features->absbit;
+ wacom->dev.relbit[0] |= wacom->features->relbit;
+ wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) |
+ BIT(BTN_MIDDLE) | wacom->features->btnbit;
+ wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) |
+ BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) |
+ BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) |
+ wacom->features->digibit;
+ wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
+
+ #ifdef __JEJ_DEBUG
+ printk(KERN_INFO "Reporting max %d, %d\n",
+ wacom->features->x_max, wacom->features->y_max);
+ #endif
+
+ wacom->dev.absmax[ABS_X] = wacom->features->x_max;
+ wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
+ wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
+ wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
+ wacom->dev.absmax[ABS_TILT_X] = 127;
+ wacom->dev.absmax[ABS_TILT_Y] = 127;
+ wacom->dev.absmax[ABS_WHEEL] = 1023;
+
+ wacom->dev.absmin[ABS_RZ] = -900;
+ wacom->dev.absmax[ABS_RZ] = 899;
+ wacom->dev.absmin[ABS_THROTTLE] = -1023;
+ wacom->dev.absmax[ABS_THROTTLE] = 1023;
+
+ wacom->dev.absfuzz[ABS_X] = 4;
+ wacom->dev.absfuzz[ABS_Y] = 4;
+
+ wacom->dev.private = wacom;
+ wacom->dev.open = wacom_open;
+ wacom->dev.close = wacom_close;
+
+ wacom->dev.name = wacom->features->name;
+ wacom->dev.idbus = BUS_USB;
+ wacom->dev.idvendor = dev->descriptor.idVendor;
+ wacom->dev.idproduct = dev->descriptor.idProduct;
+ wacom->dev.idversion = dev->descriptor.bcdDevice;
+ wacom->usbdev = dev;
+
+ endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
+ usb_set_idle(dev, dev->config[0].interface[ifnum].altsetting[0].bInterfaceNumber, 0, 0);
+
+ FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev,
+ endpoint->bEndpointAddress), wacom->data, wacom->features->pktlen,
+ wacom->features->irq, wacom, endpoint->bInterval);
+
+ input_register_device(&wacom->dev);
+
+ #ifdef __JEJ_DEBUG
+ printk(KERN_INFO __FILE__ ": Setting tablet report for tablet data\n");
+ #endif
+
+ /* ask the tablet to report tablet data */
+ usb_set_report(dev, ifnum, 3, 2, rep_data, 2);
+ usb_set_report(dev, ifnum, 3, 5, rep_data, 0);
+ usb_set_report(dev, ifnum, 3, 6, rep_data, 0);
+
+ printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n",
+ wacom->dev.number, wacom->features->name, dev->bus->busnum,
+ dev->devnum, ifnum);
+
+ return wacom;
+}
+
+static void wacom_disconnect(struct usb_device *dev, void *ptr)
+{
+ struct wacom *wacom = ptr;
+ if (wacom) {
+ usb_unlink_urb(&wacom->irq);
+ input_unregister_device(&wacom->dev);
+ kfree(wacom);
+ }
+}
+
+static struct usb_driver wacom_driver = {
+ name: "wacom",
+ probe: wacom_probe,
+ disconnect: wacom_disconnect,
+ id_table: wacom_ids,
+};
+
+static int __init wacom_init(void)
+{
+ usb_register(&wacom_driver);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ return 0;
+}
+
+static void __exit wacom_exit(void)
+{
+ usb_deregister(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
diff --git a/src/wacscrn.c b/src/wacscrn.c
new file mode 100644
index 0000000..608be65
--- /dev/null
+++ b/src/wacscrn.c
@@ -0,0 +1,39 @@
+/*****************************************************************************
+** wacscrn.c
+**
+** Copyright (C) 2002 - John E. Joganic
+**
+** 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ncurses.h>
+
+/****************************************************************************/
+
+void wacscrn_init(void)
+ { initscr(); }
+void wacscrn_term(void)
+ { endwin(); }
+void wacscrn_output(int y, int x, const char* pszText)
+ { mvaddstr(y,x,pszText); }
+void wacscrn_standout(void)
+ { attron(A_STANDOUT); }
+void wacscrn_normal(void)
+ { attrset(A_NORMAL); }
+void wacscrn_refresh(void)
+ { refresh(); }
diff --git a/src/wacscrn.h b/src/wacscrn.h
new file mode 100644
index 0000000..ba33f01
--- /dev/null
+++ b/src/wacscrn.h
@@ -0,0 +1,32 @@
+/*****************************************************************************
+** wacscrn.h
+**
+** Copyright (C) 2002 - John E. Joganic
+**
+** 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+****************************************************************************/
+
+#ifndef __WACPACK_WACSCRN_H
+#define __WACPACK_WACSCRN_H
+
+void wacscrn_init(void);
+void wacscrn_term(void);
+void wacscrn_output(int y, int x, const char* pszText);
+void wacscrn_standout(void);
+void wacscrn_normal(void);
+void wacscrn_refresh(void);
+
+#endif /* __WACPACK_WACSCRN_H */
diff --git a/src/wacserial.c b/src/wacserial.c
new file mode 100644
index 0000000..7d0e5b7
--- /dev/null
+++ b/src/wacserial.c
@@ -0,0 +1,966 @@
+/*****************************************************************************
+** wacserial.c
+**
+** Copyright (C) 2002 - John E. Joganic
+**
+** 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+****************************************************************************/
+
+#include "wacserial.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+/*****************************************************************************
+** Structures
+*****************************************************************************/
+
+typedef struct
+{
+ const char* pszID;
+ unsigned int uDeviceType;
+ const char* pszName;
+ unsigned int uPacketLength;
+ int nProtocol;
+ int nCaps;
+} MODEL_INFO;
+
+/*****************************************************************************
+** Tablet object
+*****************************************************************************/
+
+typedef struct _TABLET TABLET;
+
+typedef int (*PARSEFUNC)(TABLET* pTablet, const unsigned char* puchData,
+ unsigned int uLength, WACOMSTATE* pState);
+
+struct _TABLET
+{
+ int fd;
+ MODEL_INFO* pInfo;
+ unsigned int uPacketLength;
+ int nVerMajor, nVerMinor, nVerRelease;
+ int nCaps;
+ PARSEFUNC pfnParse;
+ int nToolID;
+ WACOMSTATE state, max, min;
+};
+
+static int TabletIdentifyModel(TABLET* pTablet);
+static int TabletInitializeModel(TABLET* pTablet);
+
+static int TabletParseWacomV(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState);
+static int TabletParseWacomIV_1_4(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState);
+static int TabletParseWacomIV_1_3(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState);
+static int TabletParseWacomIV_1_2(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState);
+
+#ifndef BIT
+#undef BIT
+#define BIT(x) (1<<(x))
+#endif
+
+#define WACOMVALID(x) BIT(WACOMFIELD_##x)
+
+#define ARTPADII_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
+ WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
+ WACOMVALID(PRESSURE))
+
+#define DIGITIZERII_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(PROXIMITY)| \
+ WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)|WACOMVALID(POSITION_Y)| \
+ WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y))
+
+#define INTUOS_CAPS (WACOMVALID(TOOLTYPE)|WACOMVALID(SERIAL)| \
+ WACOMVALID(PROXIMITY)|WACOMVALID(BUTTONS)|WACOMVALID(POSITION_X)| \
+ WACOMVALID(POSITION_Y)|WACOMVALID(ROTATION_Z)|WACOMVALID(DISTANCE)| \
+ WACOMVALID(PRESSURE)|WACOMVALID(TILT_X)|WACOMVALID(TILT_Y)| \
+ WACOMVALID(ABSWHEEL)|WACOMVALID(RELWHEEL)|WACOMVALID(THROTTLE))
+
+#define INTUOS2_CAPS INTUOS_CAPS
+
+/*****************************************************************************
+** Globals
+*****************************************************************************/
+
+ static MODEL_INFO xModels[] =
+ {
+ { "KT-0405-R", WACOMDEVICE_ARTPADII, "Wacom ArtPadII 4x5", 7, 4,
+ ARTPADII_CAPS },
+
+ { "UD-0608-R", WACOMDEVICE_DIGITIZERII, "Wacom DigitizerII 6x8", 7, 4,
+ DIGITIZERII_CAPS },
+ { "UD-1212-R", WACOMDEVICE_DIGITIZERII, "Wacom DigitizerII 12x12", 7, 4,
+ DIGITIZERII_CAPS },
+ { "UD-1218-R", WACOMDEVICE_DIGITIZERII, "Wacom DigitizerII 12x18", 7, 4,
+ DIGITIZERII_CAPS },
+ { "UD-1825-R", WACOMDEVICE_DIGITIZERII, "Wacom DigitizerII 18x25", 7, 4,
+ DIGITIZERII_CAPS },
+ /*
+ { "CT-0405-R", WACOMDEVICE_PENPARTNER, "Wacom PenPartner", 7, 4 },
+ { "ET-0405-R", WACOMDEVICE_GRAPHIRE, "Wacom Graphire", 7, 4 },
+
+ { "?D-0405-R", WACOMDEVICE_GRAPHIRE2, "Wacom Graphire2 4x5", 7, 4 },
+ { "?D-0507-R", WACOMDEVICE_GRAPHIRE2, "Wacom Graphire2 5x7", 7, 4 },
+ */
+
+ { "GD-0405-R", WACOMDEVICE_INTUOS, "Wacom Intuos 4x5", 9, 5,
+ INTUOS_CAPS },
+ { "GD-0608-R", WACOMDEVICE_INTUOS, "Wacom Intuos 6x8", 9, 5,
+ INTUOS_CAPS },
+ { "GD-0912-R", WACOMDEVICE_INTUOS, "Wacom Intuos 9x12", 9, 5,
+ INTUOS_CAPS },
+ { "GD-1212-R", WACOMDEVICE_INTUOS, "Wacom Intuos 12x12", 9, 5,
+ INTUOS_CAPS },
+ { "GD-1218-R", WACOMDEVICE_INTUOS, "Wacom Intuos 12x18", 9, 5,
+ INTUOS_CAPS },
+
+ { "XD-0405-R", WACOMDEVICE_INTUOS2, "Wacom Intuos2 4x5", 9, 5,
+ INTUOS2_CAPS },
+ { "XD-0608-R", WACOMDEVICE_INTUOS2, "Wacom Intuos2 6x8", 9, 5,
+ INTUOS2_CAPS },
+ { "XD-0912-R", WACOMDEVICE_INTUOS2, "Wacom Intuos2 9x12", 9, 5,
+ INTUOS2_CAPS },
+ { "XD-1212-R", WACOMDEVICE_INTUOS2, "Wacom Intuos2 12x12", 9, 5,
+ INTUOS2_CAPS },
+ { "XD-1218-R", WACOMDEVICE_INTUOS2, "Wacom Intuos2 12x18", 9, 5,
+ INTUOS2_CAPS },
+
+ { NULL }
+ };
+
+/*****************************************************************************
+** Static Prototypes
+*****************************************************************************/
+
+static int WacomSendReset(int fd);
+static int WacomSendStop(int fd);
+static int WacomSendStart(int fd);
+
+static int WacomSend(int fd, const char* pszData);
+static int WacomSendRaw(int fd, const unsigned char* puchData,
+ unsigned int uSize);
+static int WacomFlush(int fd);
+static int WacomSendRequest(int fd, const char* pszRequest, char* pchResponse,
+ unsigned int uSize);
+
+/*****************************************************************************
+** Public Functions
+*****************************************************************************/
+
+WACOMTABLET WacomOpenSerial(const char* pszDevice)
+{
+ int fd;
+ struct termios tios;
+ TABLET* pTablet = NULL;
+
+ /* open device for read/write access */
+ fd = open(pszDevice,O_RDWR);
+ if (fd < 0)
+ { perror("open"); return NULL; }
+
+ /* configure tty */
+ if (isatty(fd))
+ {
+ /* set up default port parameters */
+ if (tcgetattr (fd, &tios))
+ { perror("tcgetattr"); close(fd); return NULL; }
+
+ tios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ tios.c_oflag &= ~OPOST;
+ tios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ tios.c_cflag &= ~(CSIZE|PARENB);
+ tios.c_cflag |= CS8|CLOCAL;
+
+ tios.c_cflag &= ~(CSTOPB); /* 1 stop bit */
+
+ tios.c_cflag &= ~(CSIZE); /* 8 data bits */
+ tios.c_cflag |= CS8;
+
+ tios.c_cflag &= ~(PARENB); /* no parity */
+
+ tios.c_iflag |= IXOFF; /* flow control XOff */
+
+#if 0
+ {
+ int nValue;
+ /* clear DTR */
+ nValue = TIOCCDTR;
+ if (ioctl(fd, TIOCMBIC, &nValue))
+ { perror("clear dtr"); close(fd); return NULL; }
+
+ /* clear RTS */
+ nValue = TIOCM_RTS;
+ if (ioctl(fd, TIOCMBIC, &nValue))
+ { perror("clear rts"); close(fd); return NULL; }
+ }
+#endif
+
+ tios.c_cc[VMIN] = 1; /* vmin value */
+ tios.c_cc[VTIME] = 0; /* vtime value */
+
+ if (tcsetattr (fd, TCSANOW, &tios))
+ { perror("tcsetattr"); close(fd); return NULL; }
+
+ /* start high and work down */
+ cfsetispeed(&tios, B38400);
+ cfsetospeed(&tios, B38400);
+ if (WacomSendReset(fd)) { close(fd); return NULL; }
+ cfsetispeed(&tios, B19200);
+ cfsetospeed(&tios, B19200);
+ if (WacomSendReset(fd)) { close(fd); return NULL; }
+ cfsetispeed(&tios, B9600);
+ cfsetospeed(&tios, B9600);
+ if (WacomSendReset(fd)) { close(fd); return NULL; }
+ }
+ else /* not tty */
+ {
+ if (WacomSendReset(fd)) { close(fd); return NULL; }
+ }
+
+ /* Send stop */
+ if (WacomSendStop(fd) || WacomFlush(fd))
+ { perror("stop"); close(fd); return NULL; }
+
+ /* Allocate tablet */
+ pTablet = (TABLET*)malloc(sizeof(TABLET));
+ memset(pTablet,0,sizeof(*pTablet));
+ pTablet->fd = fd;
+
+ /* Identify and initialize the model */
+ if (TabletIdentifyModel(pTablet))
+ { perror("identify"); close(fd); free(pTablet); return NULL; }
+ if (TabletInitializeModel(pTablet))
+ { perror("init_model"); close(fd); free(pTablet); return NULL; }
+
+ /* Send start */
+ WacomSendStart(fd);
+
+ return (WACOMTABLET)pTablet;
+}
+
+void WacomCloseSerial(WACOMTABLET hTablet)
+{
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) return;
+
+ close(pTablet->fd);
+ free(pTablet);
+}
+
+WACOMMODEL WacomGetModel(WACOMTABLET hTablet)
+{
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 0; }
+ return pTablet->pInfo->uDeviceType | WACOMCLASS_SERIAL;
+}
+
+const char* WacomGetModelName(WACOMTABLET hTablet)
+{
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 0; }
+ return pTablet->pInfo->pszName;
+}
+
+int WacomGetRomVersion(WACOMTABLET hTablet, int* pnMajor, int* pnMinor,
+ int* pnRelease)
+{
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 0; }
+ if (!pnMajor) { errno=EINVAL; return 1; }
+ *pnMajor = pTablet->nVerMajor;
+ if (pnMinor) *pnMinor = pTablet->nVerMinor;
+ if (pnRelease) *pnRelease = pTablet->nVerRelease;
+ return 0;
+}
+
+int WacomReadRaw(WACOMTABLET hTablet, unsigned char* puchData,
+ unsigned int uSize)
+{
+ int nXfer;
+ unsigned int uCnt, uPacketLength;
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 0; }
+ uPacketLength = pTablet->uPacketLength;
+
+ /* check size of buffer */
+ if (uSize < uPacketLength) { errno=EINVAL; return 0; }
+
+ for (uCnt=0; uCnt<uPacketLength; uCnt+=nXfer)
+ {
+ nXfer = read(pTablet->fd,puchData+uCnt,uPacketLength-uCnt);
+ if (nXfer <= 0) return nXfer;
+ }
+
+ return (signed)uCnt;
+}
+
+int WacomGetCapabilities(WACOMTABLET hTablet)
+{
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 0; }
+ return pTablet->pInfo->nCaps;
+}
+
+int WacomGetRanges(WACOMTABLET hTablet, WACOMSTATE* pMin, WACOMSTATE* pMax)
+{
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 0; }
+
+ *pMin = pTablet->min;
+ *pMax = pTablet->max;
+ return 0;
+}
+
+
+int WacomParseData(WACOMTABLET hTablet, const unsigned char* puchData,
+ unsigned int uLength, WACOMSTATE* pState)
+{
+ int i;
+ TABLET* pTablet = (TABLET*)hTablet;
+ if (!pTablet) { errno=EBADF; return 1; }
+
+ /* check synchronization */
+ if (!puchData[0] & 0x80) { errno=EINVAL; return 1; }
+ for (i=1; i<uLength; ++i)
+ {
+ if (puchData[i] & 0x80)
+ { errno=EINVAL; return 1; }
+ }
+
+ /* dispatch to parser */
+ if (pTablet->pfnParse)
+ return (*pTablet->pfnParse)(pTablet,puchData,uLength,pState);
+
+ errno = EINVAL;
+ return 1;
+}
+
+/*****************************************************************************
+** Tablet Functions
+*****************************************************************************/
+
+static int TabletIdentifyModel(TABLET* pTablet)
+{
+ char* pszPos;
+ MODEL_INFO* pInfo;
+ char chResp[64];
+
+ if (WacomSendRequest(pTablet->fd,"~#\r",chResp,sizeof(chResp)))
+ return 1;
+
+ /* look through model table for information */
+ for (pInfo=xModels; pInfo->pszID; ++pInfo)
+ {
+ if (strncmp(chResp,pInfo->pszID,strlen(pInfo->pszID)) == 0)
+ {
+ pTablet->pInfo = pInfo;
+ pTablet->uPacketLength = pInfo->uPacketLength;
+
+ /* get version number */
+ pszPos = chResp;
+ while (*pszPos) ++pszPos;
+ while ((pszPos > chResp) && (pszPos[-1] != 'V')) --pszPos;
+ if (sscanf(pszPos,"%d.%d-%d",&pTablet->nVerMajor,
+ &pTablet->nVerMinor,&pTablet->nVerRelease) != 3)
+ {
+ pTablet->nVerRelease = 0;
+ if (sscanf(pszPos,"%d.%d",&pTablet->nVerMajor,
+ &pTablet->nVerMinor) != 2)
+ {
+ errno = EINVAL;
+ fprintf(stderr,"bad version number: %s\n",pszPos);
+ return 1;
+ }
+ }
+ return 0;
+ }
+ }
+
+ fprintf(stderr,"UNIDENTIFIED TABLET: %s\n",chResp);
+ return 1;
+}
+
+static int TabletInitializeModel(TABLET* pTablet)
+{
+ char chResp[32];
+
+ /* Request tablet dimensions */
+ if (WacomSendRequest(pTablet->fd,"~C\r",chResp,sizeof(chResp)))
+ return 1;
+ if (sscanf(chResp,"%d,%d",&pTablet->max.nPosX,&pTablet->max.nPosY) != 2)
+ { errno=EINVAL; perror("bad dim response"); return 1; }
+
+ /* tablet specific initialization */
+ switch (pTablet->pInfo->uDeviceType)
+ {
+ case WACOMDEVICE_PENPARTNER:
+ /* pressure mode */
+ WacomSend(pTablet->fd, "PH1\r");
+ break;
+
+ case WACOMDEVICE_INTUOS:
+ /* multi-mode, max-rate */
+ WacomSend(pTablet->fd, "MT1\rID1\rIT0\r");
+ }
+
+ if (pTablet->pInfo->nProtocol == 4)
+ {
+ /* multi-mode (MU), upper-origin (OC), all-macro (M0),
+ * no-macro1 (M1), max-rate (IT), no-inc (IN),
+ * stream-mode (SR), Z-filter (ZF) */
+
+/* if (WacomSend(pTablet->fd, "MU1\rOC1\r~M0\r~M1\rIT0\rIN0\rSR\rZF1\r"))
+ return 1;
+ */
+
+ if (pTablet->nVerMajor == 1)
+ {
+ if (pTablet->nVerMinor >= 4)
+ {
+ /* enable tilt mode */
+ if (WacomSend(pTablet->fd,"FM1\r")) return 1;
+
+ pTablet->pfnParse = TabletParseWacomIV_1_4;
+ pTablet->uPacketLength = 9;
+ pTablet->max.nPressure = 255;
+ pTablet->min.nTiltX = -64;
+ pTablet->max.nTiltX = 63;
+ pTablet->min.nTiltY = -64;
+ pTablet->max.nTiltY = 63;
+ }
+ else if (pTablet->nVerMinor == 3)
+ {
+ pTablet->pfnParse = TabletParseWacomIV_1_3;
+ pTablet->max.nPressure = 255;
+ }
+ else if (pTablet->nVerMinor == 2)
+ {
+ pTablet->pfnParse = TabletParseWacomIV_1_2;
+ pTablet->max.nPressure = 255;
+ }
+ else if (pTablet->nVerMinor < 2)
+ {
+ pTablet->pfnParse = TabletParseWacomIV_1_2;
+ pTablet->max.nPressure = 120;
+ }
+ }
+ }
+ else if (pTablet->pInfo->nProtocol == 5)
+ {
+ pTablet->pfnParse = TabletParseWacomV;
+ pTablet->max.nPressure = 1023;
+ pTablet->max.nAbsWheel = 1023;
+ pTablet->min.nRotZ = -899;
+ pTablet->max.nRotZ = 900;
+ pTablet->min.nThrottle = -1023;
+ pTablet->max.nThrottle = 1023;
+ pTablet->min.nTiltX = -64;
+ pTablet->max.nTiltX = 63;
+ pTablet->min.nTiltY = -64;
+ pTablet->max.nTiltY = 63;
+ }
+ else { errno=EINVAL; return 1; }
+
+ return 0;
+}
+
+static int TabletParseWacomV(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState)
+{
+ int x=0, y=0, rot=0, tiltx=0, tilty=0, wheel=0,
+ tool=WACOMTOOLTYPE_NONE, button=0, press=0, throttle=0;
+
+ /* Wacom V
+ * Supports: 1024 pressure, eraser, 2 side-switch, tilt, throttle, wheel
+ * Limitation: no tilt */
+
+ if (uLength != 9) { errno=EINVAL; return 1; }
+
+ /* in */
+ if ((puchData[0] & 0xFC) == 0xC0)
+ {
+ int toolid = (((int)puchData[1]&0x7F) << 5) |
+ (((int)puchData[2]&0x7C) >> 2);
+
+ int serial = ((((int)puchData[2] & 0x03) << 30) |
+ (((int)puchData[3] & 0x7f) << 23) |
+ (((int)puchData[4] & 0x7f) << 16) |
+ (((int)puchData[5] & 0x7f) << 9) |
+ (((int)puchData[6] & 0x7f) << 23) |
+ (((int)puchData[7] & 0x60) >> 5));
+
+ switch (toolid)
+ {
+ case 0x812: /* Intuos2 ink pen XP-110-00A */
+ case 0x012: /* Inking pen */
+ tool = WACOMTOOLTYPE_PENCIL; break;
+
+ case 0x822: /* Intuos Pen GP-300E-01H */
+ case 0x852: /* Intuos2 Grip Pen XP-501E-00A */
+ case 0x842: /* added from Cheng */
+ case 0x022:
+ tool = WACOMTOOLTYPE_PEN; break;
+
+ case 0x832: /* Intuos2 stroke pen XP-120-00A */
+ case 0x032: /* Stroke pen */
+ tool = WACOMTOOLTYPE_BRUSH; break;
+
+ case 0x007: /* 2D Mouse */
+ case 0x09C: /* ?? Mouse */
+ case 0x094: /* 4D Mouse */
+ tool = WACOMTOOLTYPE_MOUSE; break;
+
+ case 0x096: /* Lens cursor */
+ tool = WACOMTOOLTYPE_LENS; break;
+
+ case 0x82a:
+ case 0x85a:
+ case 0x91a:
+ case 0x0fa: /* Eraser */
+ tool = WACOMTOOLTYPE_ERASER; break;
+
+ case 0x112: /* Airbrush */
+ tool = WACOMTOOLTYPE_AIRBRUSH; break;
+
+ default: /* Unknown tool */
+ tool = WACOMTOOLTYPE_PEN; break;
+ }
+
+ pTablet->nToolID = toolid;
+ pTablet->state.nValid = pTablet->nCaps;
+ pTablet->state.nProximity = 1;
+ pTablet->state.nSerial = serial;
+ pTablet->state.nToolType = tool;
+ *pState = pTablet->state;
+ return 0;
+ }
+
+ /* out */
+ if ((puchData[0] & 0xFE) == 0x80)
+ {
+ pTablet->nToolID = 0;
+ memset(&pTablet->state,0,sizeof(pTablet->state));
+ pTablet->state.nValid = pTablet->nCaps;
+ *pState = pTablet->state;
+ return 0;
+ }
+
+ /* pen data */
+ if (((puchData[0] & 0xB8) == 0xA0) || ((puchData[0] & 0xBE) == 0xB4))
+ {
+ x = ((((int)puchData[1] & 0x7f) << 9) |
+ (((int)puchData[2] & 0x7f) << 2) |
+ (((int)puchData[3] & 0x60) >> 5));
+ y = ((((int)puchData[3] & 0x1f) << 11) |
+ (((int)puchData[4] & 0x7f) << 4) |
+ (((int)puchData[5] & 0x78) >> 3));
+ tiltx = (puchData[7] & 0x3F);
+ tilty = (puchData[8] & 0x3F);
+ if (puchData[7] & 0x40) tiltx -= 0x40;
+ if (puchData[8] & 0x40) tilty -= 0x40;
+
+ /* pen packet */
+ if ((puchData[0] & 0xB8) == 0xA0)
+ {
+ press = ((((int)puchData[5] & 0x07) << 7) | ((int)puchData[6] & 0x7f));
+ button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
+ button |= (puchData[0] & 0x02) ? BIT(WACOMBUTTON_STYLUS) : 0;
+ button |= (puchData[0] & 0x04) ? BIT(WACOMBUTTON_STYLUS2) : 0;
+ }
+
+ /* 2nd airbrush packet */
+ else
+ {
+ wheel = ((((int)puchData[5] & 0x07) << 7) |
+ ((int)puchData[6] & 0x7f));
+ }
+
+ pTablet->state.nValid = pTablet->nCaps;
+ pTablet->state.nPosX = x;
+ pTablet->state.nPosY = y;
+ pTablet->state.nTiltX = tiltx;
+ pTablet->state.nTiltY = tilty;
+ pTablet->state.nPressure = press;
+ pTablet->state.nButtons = button;
+ pTablet->state.nAbsWheel = wheel;
+ *pState = pTablet->state;
+ return 0;
+ }
+
+ /* mouse packet */
+ if (((puchData[0] & 0xBE) == 0xA8) || ((puchData[0] & 0xBE) == 0xB0))
+ {
+ x = ((((int)puchData[1] & 0x7f) << 9) |
+ (((int)puchData[2] & 0x7f) << 2) |
+ (((int)puchData[3] & 0x60) >> 5));
+ y = ((((int)puchData[3] & 0x1f) << 11) |
+ (((int)puchData[4] & 0x7f) << 4) |
+ (((int)puchData[5] & 0x78) >> 3));
+ throttle = ((((int)puchData[5] & 0x07) << 7) | (puchData[6] & 0x7f));
+ if (puchData[8] & 0x08) throttle = -throttle;
+
+ /* 4D mouse */
+ if (pTablet->nToolID == 0x094)
+ {
+ button = (((puchData[8] & 0x70) >> 1) | (puchData[8] & 0x07));
+ }
+ /* lens cursor */
+ else if (pTablet->nToolID == 0x096)
+ {
+ button = puchData[8] & 0x1F;
+ }
+ /* 2D mouse */
+ else
+ {
+ button = (puchData[8] & 0x1C) >> 2;
+ wheel = - (puchData[8] & 1) + ((puchData[8] & 2) >> 1);
+ }
+
+ pTablet->state.nValid = pTablet->nCaps;
+ pTablet->state.nPosX = x;
+ pTablet->state.nPosY = y;
+ pTablet->state.nRelWheel = wheel;
+ pTablet->state.nThrottle = throttle;
+ pTablet->state.nButtons &= ~(BIT(WACOMBUTTON_LEFT) |
+ BIT(WACOMBUTTON_RIGHT) | BIT(WACOMBUTTON_MIDDLE) |
+ BIT(WACOMBUTTON_EXTRA) | BIT(WACOMBUTTON_SIDE));
+ if (button & 1) pTablet->state.nButtons |= BIT(WACOMBUTTON_LEFT);
+ if (button & 2) pTablet->state.nButtons |= BIT(WACOMBUTTON_MIDDLE);
+ if (button & 4) pTablet->state.nButtons |= BIT(WACOMBUTTON_RIGHT);
+ if (button & 8) pTablet->state.nButtons |= BIT(WACOMBUTTON_EXTRA);
+ if (button & 16) pTablet->state.nButtons |= BIT(WACOMBUTTON_SIDE);
+
+ *pState = pTablet->state;
+ return 0;
+ }
+
+ /* 2nd 4D mouse packet */
+ if ((puchData[0] & 0xBE) == 0xAA)
+ {
+ x = ((((int)puchData[1] & 0x7f) << 9) |
+ (((int)puchData[2] & 0x7f) << 2) |
+ (((int)puchData[3] & 0x60) >> 5));
+ y = ((((int)puchData[3] & 0x1f) << 11) |
+ (((int)puchData[4] & 0x7f) << 4) |
+ (((int)puchData[5] & 0x78) >> 3));
+ rot = ((((int)puchData[6] & 0x0f) << 7) |
+ ((int)puchData[7] & 0x7f));
+
+ /* FIX ROT */
+ if (rot < 900) rot = -rot;
+ else rot = 1800 - rot;
+
+ pTablet->state.nPosX = x;
+ pTablet->state.nPosY = y;
+ pTablet->state.nRotZ = rot;
+ *pState = pTablet->state;
+ return 0;
+ }
+
+ errno = EINVAL;
+ return 1;
+}
+
+static int TabletParseWacomIV_1_4(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState)
+{
+ /* Wacom IV, Rom 1.4
+ * Supports: 256 pressure, eraser, 2 side-switch, tilt */
+
+ if ((uLength != 7) && (uLength != 9)) { errno=EINVAL; return 1; }
+
+ if (TabletParseWacomIV_1_3(pTablet,puchData,7,pState))
+ return 1;
+
+ /* tilt mode */
+ if (uLength == 9)
+ {
+ pTablet->state.nValid |= WACOMVALID(TILT_X) | WACOMVALID(TILT_Y);
+ pTablet->state.nTiltX = puchData[7] & 0x3F;
+ pTablet->state.nTiltY = puchData[8] & 0x3F;
+ if (puchData[7] & 0x40) pTablet->state.nTiltX -= 64;
+ if (puchData[8] & 0x40) pTablet->state.nTiltY -= 64;
+
+ pState->nValid = pTablet->state.nValid;
+ pState->nTiltX = pTablet->state.nTiltX;
+ pState->nTiltY = pTablet->state.nTiltY;
+ }
+
+ return 0;
+}
+
+static int TabletParseWacomIV_1_3(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState)
+{
+ int x=0, y=0, prox=0, tool=WACOMTOOLTYPE_NONE,
+ button=0, press=0, stylus, eraser;
+
+ /* Wacom IV, Rom 1.3 (ArtPadII)
+ * Supports: 256 pressure, eraser, 2 side-switch
+ * Limitation: no tilt */
+
+ if (uLength != 7) { errno=EINVAL; return 1; }
+
+ prox = puchData[0] & 0x40 ? 1 : 0;
+ if (prox)
+ {
+ stylus = puchData[0] & 0x20 ? 1 : 0;
+ press = (puchData[6] & 0x3F) << 1 | ((puchData[3] & 0x4) >> 2);
+ press |= (puchData[6] & 0x40) ? 0 : 0x80;
+ eraser = (puchData[3] & 0x20) ? 1 : 0;
+
+ if (stylus)
+ {
+ /* if entering proximity, choose eraser or stylus2 for bit */
+ if (pTablet->state.nProximity == 0)
+ {
+ if (eraser) tool = WACOMTOOLTYPE_ERASER;
+ else tool = WACOMTOOLTYPE_PEN;
+ }
+
+ /* otherwise, keep the last tool */
+ else tool = pTablet->state.nToolType;
+
+ button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
+
+ /* pen has 2 side-switch, eraser has none */
+ if (tool == WACOMTOOLTYPE_PEN)
+ {
+ button |= (puchData[3] & 0x10) ?
+ BIT(WACOMBUTTON_STYLUS) : 0;
+ button |= (eraser) ? BIT(WACOMBUTTON_STYLUS2) : 0;
+ }
+ }
+ else
+ {
+ tool = WACOMTOOLTYPE_MOUSE;
+ button = (puchData[3] & 0x78) >> 3; /* not tested */
+ }
+
+ x = puchData[2] | ((int)puchData[1] << 7) |
+ (((int)puchData[0] & 0x3) << 14);
+ y = puchData[5] | ((int)puchData[4] << 7) |
+ (((int)puchData[3] & 0x3) << 14);
+ }
+
+ /* set valid fields */
+ pTablet->state.nValid = WACOMVALID(PROXIMITY) |
+ WACOMVALID(TOOLTYPE) | WACOMVALID(POSITION_X) |
+ WACOMVALID(POSITION_Y) | WACOMVALID(PRESSURE) |
+ WACOMVALID(BUTTONS);
+
+ pTablet->state.nProximity = prox;
+ pTablet->state.nToolType = tool;
+ pTablet->state.nPosX = x;
+ pTablet->state.nPosY = y;
+ pTablet->state.nPressure = press;
+ pTablet->state.nButtons = button;
+
+ *pState = pTablet->state;
+ return 0;
+}
+
+
+static int TabletParseWacomIV_1_2(TABLET* pTablet,
+ const unsigned char* puchData, unsigned int uLength,
+ WACOMSTATE* pState)
+{
+ int x=0, y=0, prox=0, tool=0, button=WACOMTOOLTYPE_NONE,
+ press=0, stylus;
+
+ /* Wacom IV, Rom 1.2, 1.1, and 1.0
+ * Supports: 256 pressure (120 for 1.1 and 1.0), multi-mode
+ * Limitation: no stylus2, no tilt, no eraser */
+
+ if (uLength != 7) { errno=EINVAL; return 1; }
+
+ prox = puchData[0] & 0x40 ? 1 : 0;
+ if (prox)
+ {
+ stylus = puchData[0] & 0x20 ? 1 : 0;
+ if (pTablet->nVerMinor == 2)
+ press = (puchData[6] & 0x3F) << 1 | ((puchData[3] & 0x4) >> 2) |
+ (puchData[6] & 0x40) ? 0 : 0x80;
+ else
+ press = (puchData[6] & 0x3F) + (puchData[6] & 0x40) ? 0 : 64;
+
+ if (stylus)
+ {
+ tool = WACOMTOOLTYPE_PEN;
+ button = (press > 10) ? BIT(WACOMBUTTON_TOUCH) : 0;
+ button |= (puchData[3] & 0x10) ? BIT(WACOMBUTTON_STYLUS) : 0;
+ }
+ else
+ {
+ tool = WACOMTOOLTYPE_MOUSE;
+ button = (puchData[3] & 0x78) >> 3; /* not tested */
+ }
+
+ x = puchData[2] | ((int)puchData[1] << 7) |
+ (((int)puchData[0] & 0x3) << 14);
+ y = puchData[5] | ((int)puchData[4] << 7) |
+ (((int)puchData[3] & 0x3) << 14);
+ }
+
+ /* set valid fields */
+ pTablet->state.nValid = WACOMVALID(PROXIMITY) |
+ WACOMVALID(TOOLTYPE) | WACOMVALID(POSITION_X) |
+ WACOMVALID(POSITION_Y) | WACOMVALID(PRESSURE) |
+ WACOMVALID(BUTTONS);
+
+ pTablet->state.nProximity = prox;
+ pTablet->state.nToolType = tool;
+ pTablet->state.nPosX = x;
+ pTablet->state.nPosY = y;
+ pTablet->state.nPressure = press;
+ pTablet->state.nButtons = button;
+
+ *pState = pTablet->state;
+ return 0;
+}
+
+
+/*****************************************************************************
+** Internal Functions
+*****************************************************************************/
+
+static int WacomSendReset(int fd)
+{
+ /* reset to Wacom II-S command set, and factory defaults */
+ if (WacomSend(fd,"\r$")) return 1;
+ usleep(250000); /* 250 milliseconds */
+
+ /* reset tablet to Wacom IV command set */
+ if (WacomSend(fd,"\r#")) return 1;
+ usleep(75000); /* 75 milliseconds */
+
+ return 0;
+}
+
+static int WacomSendStop(int fd)
+{
+ if (WacomSend(fd,"\rSP\r")) return 1;
+ usleep(100000);
+ return 0;
+}
+
+static int WacomSendStart(int fd)
+{
+ return WacomSend(fd,"ST\r");
+}
+
+static int WacomSend(int fd, const char* pszMsg)
+{
+ return WacomSendRaw(fd,pszMsg,strlen(pszMsg));
+}
+
+static int WacomSendRaw(int fd, const unsigned char* puchData,
+ unsigned int uSize)
+{
+ int nXfer;
+ unsigned int uCnt=0;
+
+ while (uCnt < uSize)
+ {
+ nXfer = write(fd,puchData+uCnt,uSize-uCnt);
+ if (!nXfer) { perror("sendraw confused"); return 1; }
+ if (nXfer < 0) { perror("sendraw bad"); return 1; }
+ uCnt += nXfer;
+ }
+
+ return 0;
+}
+
+static int WacomFlush(int fd)
+{
+ char ch[16];
+ fd_set fdsRead;
+ struct timeval timeout;
+
+ if (tcflush(fd, TCIFLUSH) == 0)
+ return 0;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ while (1)
+ {
+ FD_ZERO(&fdsRead);
+ FD_SET(fd, &fdsRead);
+ if (select(FD_SETSIZE,&fdsRead,NULL,NULL,&timeout) <= 0)
+ break;
+ read(fd,&ch,sizeof(ch));
+ }
+
+ return 0;
+}
+
+static int WacomSendRequest(int fd, const char* pszRequest, char* pchResponse,
+ unsigned int uSize)
+{
+ int nXfer;
+ unsigned int uLen, uCnt;
+
+ uLen = strlen(pszRequest);
+ if (WacomSendRaw(fd,pszRequest,uLen)) return 1;
+ --uLen;
+
+ if (uSize < uLen) { errno=EINVAL; perror("bad size"); return 1; }
+
+ /* read response header */
+ for (uCnt=0; uCnt<uLen; uCnt+=nXfer)
+ {
+ nXfer = read(fd,pchResponse+uCnt,uLen-uCnt);
+ if (nXfer <= 0) { perror("trunc response header"); return 1; }
+ }
+
+ /* check the header */
+ if (strncmp(pszRequest,pchResponse,uLen) != 0)
+ { perror("bad response header"); return 1; }
+
+ /* get the rest of the response */
+ for (uCnt=0; uCnt<uSize; ++uCnt)
+ {
+ nXfer = read(fd,pchResponse+uCnt,1);
+ if (nXfer <= 0) { perror("bad response read"); return 1; }
+
+ /* stop on CR */
+ if (pchResponse[uCnt] == '\r')
+ {
+ pchResponse[uCnt] = '\0';
+ return 0;
+ }
+ }
+
+ errno = EINVAL;
+ perror("bad response");
+ return 1;
+}
diff --git a/src/wacserial.h b/src/wacserial.h
new file mode 100644
index 0000000..f56058d
--- /dev/null
+++ b/src/wacserial.h
@@ -0,0 +1,115 @@
+/*****************************************************************************
+** wacserial.h
+**
+** Copyright (C) 2002 - John E. Joganic
+**
+** 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+****************************************************************************/
+
+#ifndef __WACPACK_WACSERIAL_H
+#define __WACPACK_WACSERIAL_H
+
+#define WACOMDEVICE_MASK 0x000F
+#define WACOMDEVICE_ARTPAD 0x0001
+#define WACOMDEVICE_ARTPADII 0x0002
+#define WACOMDEVICE_DIGITIZER 0x0003
+#define WACOMDEVICE_DIGITIZERII 0x0004
+#define WACOMDEVICE_PENPARTNER 0x0005
+#define WACOMDEVICE_GRAPHIRE 0x0006
+#define WACOMDEVICE_GRAPHIRE2 0x0007
+#define WACOMDEVICE_INTUOS 0x0008
+#define WACOMDEVICE_INTUOS2 0x0009
+#define WACOMDEVICE_CINTIQ 0x000A
+#define WACOMDEVICE(x) ((x)&WACOMDEVICE_MASK)
+
+#define WACOMCLASS_MASK 0x0300
+#define WACOMCLASS_SERIAL 0x0100
+#define WACOMCLASS_USB 0x0200
+#define WACOMCLASS(x) ((x)&WACOMCLASS_MASK)
+
+#define WACOMMODEL_SERIAL_INTUOS2 (WACOMCLASS_SERIAL|WACOMDEVICE_INTUOS2)
+typedef unsigned int WACOMMODEL;
+
+#define WACOMTOOLTYPE_NONE 0x00
+#define WACOMTOOLTYPE_PEN 0x01
+#define WACOMTOOLTYPE_PENCIL 0x02
+#define WACOMTOOLTYPE_BRUSH 0x03
+#define WACOMTOOLTYPE_ERASER 0x04
+#define WACOMTOOLTYPE_AIRBRUSH 0x05
+#define WACOMTOOLTYPE_MOUSE 0x06
+#define WACOMTOOLTYPE_LENS 0x07
+
+#define WACOMBUTTON_LEFT 0
+#define WACOMBUTTON_MIDDLE 1
+#define WACOMBUTTON_RIGHT 2
+#define WACOMBUTTON_EXTRA 3
+#define WACOMBUTTON_SIDE 4
+#define WACOMBUTTON_TOUCH 5
+#define WACOMBUTTON_STYLUS 6
+#define WACOMBUTTON_STYLUS2 7
+#define WACOMBUTTON_MAX 8
+
+#define WACOMFIELD_TOOLTYPE 0
+#define WACOMFIELD_SERIAL 1
+#define WACOMFIELD_PROXIMITY 2
+#define WACOMFIELD_BUTTONS 3
+#define WACOMFIELD_POSITION_X 4
+#define WACOMFIELD_POSITION_Y 5
+#define WACOMFIELD_ROTATION_Z 6
+#define WACOMFIELD_DISTANCE 7
+#define WACOMFIELD_PRESSURE 8
+#define WACOMFIELD_TILT_X 9
+#define WACOMFIELD_TILT_Y 10
+#define WACOMFIELD_ABSWHEEL 11
+#define WACOMFIELD_RELWHEEL 12
+#define WACOMFIELD_THROTTLE 13
+#define WACOMFIELD_MAX 14
+
+typedef struct
+{
+ int nValid;
+ int nToolType;
+ int nSerial;
+ int nProximity;
+ int nButtons;
+ int nPosX;
+ int nPosY;
+ int nRotZ;
+ int nDistance;
+ int nPressure;
+ int nTiltX;
+ int nTiltY;
+ int nAbsWheel;
+ int nRelWheel;
+ int nThrottle;
+} WACOMSTATE;
+
+typedef struct { int __unused; } *WACOMTABLET;
+
+WACOMTABLET WacomOpenSerial(const char* pszDevice);
+void WacomCloseSerial(WACOMTABLET hTablet);
+WACOMMODEL WacomGetModel(WACOMTABLET hTablet);
+const char* WacomGetModelName(WACOMTABLET hTablet);
+int WacomReadRaw(WACOMTABLET hTablet, unsigned char* puchData,
+ unsigned int uSize);
+int WacomGetRomVersion(WACOMTABLET hTablet, int* pnMajor, int* pnMinor,
+ int* pnRelease);
+int WacomGetCapabilities(WACOMTABLET hTablet);
+int WacomGetRanges(WACOMTABLET hTablet, WACOMSTATE* pMin, WACOMSTATE* pMax);
+int WacomParseData(WACOMTABLET hTablet, const unsigned char* puchData,
+ unsigned int uLength, WACOMSTATE* pState);
+
+#endif /* __WACPACK_WACSERIAL_H */
diff --git a/src/wcm-beta.c b/src/wcm-beta.c
new file mode 100644
index 0000000..babb2f6
--- /dev/null
+++ b/src/wcm-beta.c
@@ -0,0 +1,618 @@
+/*****************************************************************************
+ * wcm-beta.c
+ *
+ * Copyright 2002 by John Joganic <john@joganic.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * REVISION HISTORY
+ *
+ ****************************************************************************/
+
+#include "wcm-beta.h"
+
+/*****************************************************************************
+ * Notes:
+ *
+ * Namespaces - the public functions use "wcmBeta" as the namespace. This is
+ * to separate the XF86 module-level routines from the internal
+ * tablet-specific routines which are static and fall under the
+ * "wacom" namespace.
+ ****************************************************************************/
+
+
+#include "xf86.h"
+#include "keysym.h"
+#include "xf86_OSproc.h"
+#include "xf86Xinput.h"
+#include "exevents.h"
+
+/****************************************************************************
+** Defines
+****************************************************************************/
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(lvl, f) {if ((lvl) <= xnDebugLevel) f;}
+
+#ifdef SYSCALL
+#undef SYSCALL
+#endif
+#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
+
+#define WACOM_FLAG_BETA 128 /* must be same as xf86Wacom.c BETA_FLAG */
+
+/* Note: xf86 valuator conversion code does not handle more than 6 axes. */
+
+#define WACOM_AXIS_X 0
+#define WACOM_AXIS_Y 1
+#define WACOM_AXIS_PRESS 2
+#define WACOM_AXIS_TILTX 3
+#define WACOM_AXIS_TILTY 4
+#define WACOM_AXIS_WHEEL 5
+#define WACOM_AXIS_MAX 6
+
+#define WACOM_BUTTON_COUNT 16
+
+/*****************************************************************************
+** Structures
+*****************************************************************************/
+
+typedef struct _WacomCoord WacomCoord;
+typedef struct _WacomDevice WacomDevice;
+typedef struct _WacomDevice* WacomDevicePtr;
+
+struct _WacomCoord
+{
+ int nX;
+ int nY;
+ int nPress;
+ int nTiltX;
+ int nTiltY;
+ int nWheel;
+};
+
+struct _WacomDevice
+{
+ unsigned int uFlags; /* must be first for xf86Wacom.c compatibility */
+ InputDriverPtr pDriver; /* device driver */
+ char* pszDevicePath; /* device file name */
+ int nScreen; /* screen number for tablet */
+
+ /* active tablet window */
+ int nLeft;
+ int nTop;
+ int nRight;
+ int nBottom;
+
+ /* ratio of screen to active tablet window dimensions */
+ double dRatioX;
+ double dRatioY;
+
+ /* device capabilities */
+ WacomCoord min;
+ WacomCoord max;
+};
+
+/****************************************************************************
+** Globals
+****************************************************************************/
+
+ static int xnDebugLevel = 0;
+
+ static const char* xszDefaultOptions[] =
+ {
+ "BaudRate", "9600",
+ "StopBits", "1",
+ "DataBits", "8",
+ "Parity", "None",
+ "Vmin", "1",
+ "Vtime", "10",
+ "FlowControl", "Xoff",
+ NULL
+ };
+
+ static KeySym xSyms[] =
+ {
+ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x04 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x08 */ XK_F1, XK_F2, XK_F3, XK_F4,
+ /* 0x0C */ XK_F5, XK_F6, XK_F7, XK_F8,
+ /* 0x10 */ XK_F9, XK_F10, XK_F11, XK_F12,
+ /* 0x14 */ XK_F13, XK_F14, XK_F15, XK_F16,
+ /* 0x18 */ XK_F17, XK_F18, XK_F19, XK_F20,
+ /* 0x1C */ XK_F21, XK_F22, XK_F23, XK_F24,
+ /* 0x20 */ XK_F25, XK_F26, XK_F27, XK_F28,
+ /* 0x24 */ XK_F29, XK_F30, XK_F31, XK_F32
+ };
+
+ static KeySymsRec xKeySyms =
+ {
+ xSyms, /* map */
+ 0x08, /* minimum key code */
+ (sizeof(xSyms) / sizeof(*xSyms)) - 1, /* maximum key code */
+ 1, /* character width in bytes */
+ };
+
+/****************************************************************************
+** Static Prototypes
+****************************************************************************/
+
+static void wacomFreeDevice(LocalDevicePtr pDevice);
+static int wacomConfigDevice(InputDriverPtr pDriver, LocalDevicePtr pDevice,
+ IDevPtr pConfig);
+static int wacomDeviceCtrlProc(DeviceIntPtr pInt, int nWhat);
+static void wacomDeviceFeedbackCtrlProc(DeviceIntPtr pInt, PtrCtrl* pCtrl);
+static int wacomInitDevice(LocalDevicePtr pDevice);
+static int wacomEnableDevice(LocalDevicePtr pDevice);
+static int wacomDisableDevice(LocalDevicePtr pDevice);
+static void wacomCloseDevice(LocalDevicePtr pDevice);
+static Bool wacomConvertDeviceValuators(LocalDevicePtr pDevice,
+ int nFirst, int nNum, int v0, int v1, int v2, int v3,
+ int v4, int v5, int* px, int* py);
+static Bool wacomReverseDeviceValuators(LocalDevicePtr pDevice, int x, int y,
+ int* pValuators);
+static int wacomSwitchDeviceMode(ClientPtr pClient, DeviceIntPtr pInt,
+ int nMode);
+static int wacomControlDevice(LocalDevicePtr pDevice, xDeviceCtl* pCtrl);
+static int wacomOpenDevice(DeviceIntPtr pInt);
+static void wacomReadInput(LocalDevicePtr pDevice);
+
+/*****************************************************************************
+** Device initialization and termination
+*****************************************************************************/
+
+InputInfoPtr wcmBetaNewDevice(InputDriverPtr pDriver, IDevPtr pConfig,
+ int nFlags)
+{
+ LocalDevicePtr pDevice;
+ WacomDevicePtr pPriv;
+
+ xf86Msg(X_CONFIG, "wcmBetaInitDevice: drv=%d %s %p %d\n",
+ pDriver->driverVersion,
+ pDriver->driverName,
+ pDriver->module,
+ pDriver->refCount);
+ xf86Msg(X_CONFIG, "wcmBetaInitDevice: config=%s %s\n",
+ pConfig->identifier,
+ pConfig->driver);
+ xf86Msg(X_CONFIG, "wcmBetaInitDevice: flags=%08X\n",nFlags);
+
+ /* allocate private structure */
+ pPriv = (WacomDevicePtr) xalloc(sizeof(WacomDevice));
+ if (!pPriv) return NULL;
+ memset(pPriv,0,sizeof(pPriv));
+
+ /* allocate input device and add to list */
+ pDevice = xf86AllocateInput(pDriver, 0);
+ if (!pDevice)
+ {
+ xfree(pPriv);
+ return NULL;
+ }
+
+ /* initialize and configure device */
+ pDevice->private = pPriv;
+ if (wacomConfigDevice(pDriver,pDevice,pConfig))
+ {
+ wacomFreeDevice(pDevice);
+ return NULL;
+ }
+
+ return pDevice;
+}
+
+void wcmBetaDeleteDevice(InputDriverPtr pDriver, LocalDevicePtr pDevice,
+ int nFlags)
+{
+ xf86Msg(X_CONFIG, "wcmBetaDeleteDevice: drv=%d %s %p %d\n",
+ pDriver->driverVersion,
+ pDriver->driverName,
+ pDriver->module,
+ pDriver->refCount);
+ xf86Msg(X_CONFIG, "wcmBetaDeleteDevice: dev=%s\n",pDevice->name);
+ xf86Msg(X_CONFIG, "wcmBetaDeleteDevice: flags=%08X\n",nFlags);
+
+ /* disable and deallocate device */
+ wacomDisableDevice(pDevice);
+ wacomFreeDevice(pDevice);
+}
+
+/*****************************************************************************
+** Implementation
+*****************************************************************************/
+
+static int wacomConfigDevice(InputDriverPtr pDriver, LocalDevicePtr pDevice,
+ IDevPtr pConfig)
+{
+ WacomDevicePtr pPriv = (WacomDevicePtr) pDevice->private;
+
+ xf86Msg(X_INFO, "wacomConfigDevice\n");
+
+ /* Initialize XF86 local device structure */
+ pDevice->name = "TABLET";
+ pDevice->type_name = "Wacom Tablet";
+ pDevice->flags = 0;
+ pDevice->device_control = wacomDeviceCtrlProc;
+ pDevice->read_input = wacomReadInput;
+ pDevice->control_proc = wacomControlDevice;
+ pDevice->close_proc = wacomCloseDevice;
+ pDevice->switch_mode = wacomSwitchDeviceMode;
+ pDevice->conversion_proc = wacomConvertDeviceValuators;
+ pDevice->reverse_conversion_proc = wacomReverseDeviceValuators;
+ pDevice->fd = -1;
+ pDevice->atom = 0;
+ pDevice->dev = NULL;
+ pDevice->private_flags = 0;
+ pDevice->history_size = 0;
+ pDevice->old_x = -1;
+ pDevice->old_y = -1;
+
+ /* Initialize private structure */
+ memset(pPriv,0,sizeof(*pPriv));
+ pPriv->uFlags = WACOM_FLAG_BETA;
+ pPriv->pDriver = pDriver;
+ pPriv->pszDevicePath = "";
+ pPriv->nScreen = -1;
+ pPriv->nLeft = pPriv->nTop = pPriv->nRight = pPriv->nBottom = -1;
+
+ /* retrieve values from configuration */
+ pDevice->name = pConfig->identifier;
+ pDevice->conf_idev = pConfig;
+ xf86CollectInputOptions(pDevice, xszDefaultOptions, NULL);
+
+ /* Handle common options like AlwaysCore, CorePointer, HistorySize, ... */
+ xf86ProcessCommonOptions(pDevice, pDevice->options);
+
+ /* Get the debugging log level */
+ xnDebugLevel = xf86SetIntOption(pDevice->options,
+ "DebugLevel", xnDebugLevel);
+
+ if (xnDebugLevel > 0)
+ xf86Msg(X_CONFIG, "wacomConfigDevice: debug level set to %d\n",
+ xnDebugLevel);
+
+ /* Get tablet device (eg. /dev/ttyS0 or /dev/input/event0) */
+ pPriv->pszDevicePath = xf86FindOptionValue(pDevice->options, "Device");
+ if (!pPriv->pszDevicePath)
+ {
+ xf86Msg (X_ERROR, "wacomConfigDevice: No device specified for %s.\n",
+ pDevice->name);
+ return 1;
+ }
+ else
+ xf86Msg(X_CONFIG, "wacomConfigDevice: %s device is %s\n",
+ pDevice->name, pPriv->pszDevicePath);
+
+ /* Get screen number, if provided */
+ pPriv->nScreen = xf86SetIntOption(pDevice->options, "ScreenNo", -1);
+ if (pPriv->nScreen != -1)
+ {
+ xf86Msg(X_CONFIG, "wacomConfigDevice: %s device on screen %d\n",
+ pDevice->name, pPriv->nScreen);
+ }
+
+ /* Mark device as fully configured and ready */
+ pDevice->flags = XI86_POINTER_CAPABLE | XI86_CONFIGURED;
+
+ return 0;
+}
+
+static void wacomFreeDevice(LocalDevicePtr pDevice)
+{
+ WacomDevicePtr pPriv = (WacomDevicePtr) pDevice->private;
+
+ DBG(1,xf86Msg(X_INFO, "wacomFreeDevice: %s\n",pDevice->name));
+
+ xfree(pPriv);
+ pDevice->private = NULL;
+ xf86DeleteInput(pDevice,0);
+}
+
+static int wacomDeviceCtrlProc(DeviceIntPtr pInt, int nWhat)
+{
+ LocalDevicePtr pDevice = (LocalDevicePtr) pInt->public.devicePrivate;
+
+ switch (nWhat)
+ {
+ case DEVICE_INIT: return wacomInitDevice(pDevice);
+ case DEVICE_ON: return wacomEnableDevice(pDevice);
+ case DEVICE_OFF: return wacomDisableDevice(pDevice);
+ case DEVICE_CLOSE: wacomCloseDevice(pDevice); return Success;
+ }
+
+ xf86Msg(X_ERROR,"wacomDeviceCtrlProc: %s received bad request %d\n",
+ pDevice->name,nWhat);
+
+ return !Success;
+}
+
+static int wacomInitDevice(LocalDevicePtr pDevice)
+{
+ int i;
+ CARD8 uchMap[WACOM_BUTTON_COUNT];
+
+ DBG(1,xf86Msg(X_INFO, "wacomInitDevice: %s\n",pDevice->name));
+
+ /* Initialize for everything - too much in fact.
+ * The individual pointer types will be more specialized. */
+
+ /* we report button events */
+ for (i=1; i<=WACOM_BUTTON_COUNT; ++i) uchMap[i] = i;
+ if (!InitButtonClassDeviceStruct(pDevice->dev, WACOM_BUTTON_COUNT, uchMap))
+ {
+ xf86Msg(X_ERROR, "wacomInitDevice: "
+ "failed to init as button class device\n");
+ return !Success;
+ }
+
+ /* we report key events */
+ if (!InitKeyClassDeviceStruct(pDevice->dev, &xKeySyms, NULL))
+ {
+ xf86Msg(X_ERROR, "wacomInitDevice: "
+ "failed to init as key class device\n");
+ return !Success;
+ }
+
+ /* we can be focused */
+ if (!InitFocusClassDeviceStruct(pDevice->dev))
+ {
+ xf86Msg(X_ERROR, "wacomInitDevice: "
+ "failed to init as focus class device\n");
+ return !Success;
+ }
+
+ /* we support feedbacks - sort of */
+ if (!InitPtrFeedbackClassDeviceStruct(pDevice->dev,
+ wacomDeviceFeedbackCtrlProc))
+ {
+ xf86Msg(X_ERROR, "wacomInitDevice: "
+ "failed to init as feedback class device\n");
+ return !Success;
+ }
+
+ /* we report proximity events */
+ if (!InitProximityClassDeviceStruct(pDevice->dev))
+ {
+ xf86Msg(X_ERROR, "wacomInitDevice: "
+ "failed to init as proximity class device\n");
+ return !Success;
+ }
+
+ /* we report valuator data in motion events */
+ if (!InitValuatorClassDeviceStruct(pDevice->dev, WACOM_AXIS_MAX,
+ xf86GetMotionEvents, pDevice->history_size,
+ OutOfProximity | Absolute))
+ {
+ xf86Msg(X_ERROR, "wacomInitDevice: "
+ "failed to init as valuator class device\n");
+ return !Success;
+ }
+
+ /* allocate the motion history buffer */
+ xf86MotionHistoryAllocate(pDevice);
+
+ /* open the device to gather informations */
+ return wacomOpenDevice(pDevice->dev);
+}
+
+static int wacomEnableDevice(LocalDevicePtr pDevice)
+{
+ DBG(1,xf86Msg(X_INFO, "wacomEnableDevice: %s\n",pDevice->name));
+ if (pDevice->fd < 0)
+ {
+ if (wacomOpenDevice(pDevice->dev) != Success)
+ return !Success;
+ xf86AddEnabledDevice(pDevice);
+ }
+
+ pDevice->dev->public.on = TRUE;
+ return Success;
+}
+
+static int wacomDisableDevice(LocalDevicePtr pDevice)
+{
+ DBG(1,xf86Msg(X_INFO, "wacomDisableDevice: %s\n",pDevice->name));
+ if (pDevice->fd >= 0)
+ {
+ xf86RemoveEnabledDevice(pDevice);
+ SYSCALL(xf86CloseSerial(pDevice->fd));
+ pDevice->fd = -1;
+ }
+
+ pDevice->dev->public.on = FALSE;
+ return Success;
+}
+
+static void wacomCloseDevice(LocalDevicePtr pDevice)
+{
+ DBG(1,xf86Msg(X_INFO, "wacomCloseDevice: %s\n",pDevice->name));
+ if (pDevice->fd >= 0) wacomDisableDevice(pDevice);
+}
+
+static void wacomDeviceFeedbackCtrlProc(DeviceIntPtr pInt, PtrCtrl* pCtrl)
+{
+ DBG(1, xf86Msg(X_INFO, "wacomDeviceFeedbackCtrlProc\n"));
+}
+
+static Bool wacomConvertDeviceValuators(LocalDevicePtr pDevice,
+ int nFirst, int nNum, int v0, int v1, int v2, int v3,
+ int v4, int v5, int* px, int* py)
+{
+ WacomDevicePtr pPriv = (WacomDevicePtr)pDevice->private;
+
+ /* what does this do? */
+ if (nFirst != 0 || nNum == 1) return FALSE;
+
+ /* screen coordinates are based solely on X and Y axis */
+
+ *px = (int)(v0 * pPriv->dRatioX + 0.5); /* WACOM_X_AXIS */
+ *py = (int)(v1 * pPriv->dRatioY + 0.5); /* WACOM_Y_AXIS */
+
+ return TRUE;
+}
+
+static Bool wacomReverseDeviceValuators(LocalDevicePtr pDevice, int x, int y,
+ int* pValuators)
+{
+ WacomDevicePtr pPriv = (WacomDevicePtr)pDevice->private;
+
+ /* screen coordinates are based solely on X and Y axis */
+
+ pValuators[WACOM_AXIS_X] = (int)(x / pPriv->dRatioX + 0.5);
+ pValuators[WACOM_AXIS_Y] = (int)(y / pPriv->dRatioY + 0.5);
+
+ return TRUE;
+}
+
+static int wacomSwitchDeviceMode(ClientPtr pClient, DeviceIntPtr pInt,
+ int nMode)
+{
+ LocalDevicePtr pDevice = (LocalDevicePtr) pInt->public.devicePrivate;
+
+ DBG(3, xf86Msg(X_INFO, "wacomSwitchDeviceMode %s mode=%s\n",
+ pDevice->name, (nMode == Absolute) ? "ABS" :
+ (nMode == Relative) ? "REL" : "UNK"));
+
+ /* ignore */
+ return Success;
+}
+
+static int wacomControlDevice(LocalDevicePtr pDevice, xDeviceCtl* pCtrl)
+{
+ /* no controls defined */
+ return Success;
+}
+
+static int wacomOpenDevice(DeviceIntPtr pInt)
+{
+ LocalDevicePtr pDevice = (LocalDevicePtr)pInt->public.devicePrivate;
+ WacomDevicePtr pPriv = (WacomDevicePtr)pDevice->private;
+ ScreenPtr pScreen;
+
+ xf86Msg(X_INFO, "wacomOpenDevice\n");
+
+ /* open device as serial line */
+ if (pDevice->fd < 0)
+ {
+ pDevice->fd = xf86OpenSerial(pDevice->options);
+ if (pDevice->fd < 0)
+ return !Success;
+ }
+
+ /* Query device capabilities for hypothetical 6x4 tablet */
+ pPriv->min.nX = 0;
+ pPriv->max.nX = 15240;
+ pPriv->min.nY = 0;
+ pPriv->max.nY = 10160;
+ pPriv->min.nPress = 0;
+ pPriv->max.nPress = 1023;
+ pPriv->min.nTiltX = -64;
+ pPriv->max.nTiltX = 63;
+ pPriv->min.nTiltY = -64;
+ pPriv->max.nTiltY = 63;
+ pPriv->min.nWheel = 0;
+ pPriv->max.nWheel = 1023;
+
+ /* set bounds to defaults, if not specified by configuration */
+ if (pPriv->nLeft < 0) pPriv->nLeft = pPriv->min.nX;
+ if (pPriv->nTop < 0) pPriv->nTop = pPriv->min.nY;
+ if (pPriv->nRight < 0) pPriv->nRight = pPriv->max.nX;
+ if (pPriv->nBottom < 0) pPriv->nBottom = pPriv->max.nY;
+
+ /* validate left bound */
+ if ((pPriv->nLeft > pPriv->max.nX || pPriv->nLeft < pPriv->min.nX))
+ pPriv->nLeft = pPriv->min.nX;
+
+ /* validate top bound */
+ if ((pPriv->nTop > pPriv->max.nY || pPriv->nTop < pPriv->min.nY))
+ pPriv->nTop = pPriv->min.nY;
+
+ /* validate right bound */
+ if ((pPriv->nRight > pPriv->max.nX || pPriv->nRight < pPriv->min.nX))
+ pPriv->nRight = pPriv->max.nX;
+
+ /* validate bottom bound */
+ if ((pPriv->nBottom > pPriv->max.nY || pPriv->nBottom < pPriv->min.nY))
+ pPriv->nBottom = pPriv->max.nY;
+
+ /* validate width */
+ if (pPriv->nLeft >= pPriv->nRight)
+ {
+ pPriv->nLeft = pPriv->min.nX;
+ pPriv->nRight = pPriv->max.nX;
+ }
+
+ /* validate height */
+ if (pPriv->nTop >= pPriv->nBottom)
+ {
+ pPriv->nTop = pPriv->min.nY;
+ pPriv->nBottom = pPriv->max.nY;
+ }
+
+ xf86Msg(X_INFO, "wacomOpenDevice: %s bounds %d,%d %d,%d\n",
+ pDevice->name, pPriv->nLeft, pPriv->nTop,
+ pPriv->nRight, pPriv->nBottom);
+
+ /* get screen */
+ if (pPriv->nScreen < 0) pPriv->nScreen = 0;
+ if (pPriv->nScreen >= screenInfo.numScreens)
+ {
+ xf86Msg(X_INFO,"wacomOpenDevice: %s on invalid screen %d, reset to 0\n",
+ pDevice->name, pPriv->nScreen);
+ pPriv->nScreen = 0;
+ }
+ pScreen = screenInfo.screens[pPriv->nScreen];
+
+ xf86Msg(X_INFO, "wacomOpenDevice: %s on screen %d (%d, %d)\n",
+ pDevice->name, pPriv->nScreen, pScreen->width, pScreen->height);
+
+ /* calculate screen to tablet ratios */
+ pPriv->dRatioX = (double)pScreen->width / (pPriv->nRight - pPriv->nLeft);
+ pPriv->dRatioY = (double)pScreen->height / (pPriv->nBottom - pPriv->nTop);
+
+ xf86Msg(X_INFO, "wacomOpenDevice: %s scaled %.4g, %.4g\n",
+ pDevice->name, pPriv->dRatioX, pPriv->dRatioY);
+
+ /* Initialize valuators */
+ InitValuatorAxisStruct(pInt,WACOM_AXIS_X,
+ 0, pPriv->nRight - pPriv->nLeft,
+ 100000,0,100000);
+ InitValuatorAxisStruct(pInt,WACOM_AXIS_Y,
+ 0, pPriv->nBottom - pPriv->nTop,
+ 100000,0,100000);
+ InitValuatorAxisStruct(pInt,WACOM_AXIS_PRESS,
+ pPriv->min.nPress, pPriv->max.nPress,
+ 100000,0,100000);
+ InitValuatorAxisStruct(pInt,WACOM_AXIS_TILTX,
+ pPriv->min.nTiltX, pPriv->max.nTiltX,
+ 100000,0,100000);
+ InitValuatorAxisStruct(pInt,WACOM_AXIS_TILTY,
+ pPriv->min.nTiltY, pPriv->max.nTiltY,
+ 100000,0,100000);
+ InitValuatorAxisStruct(pInt,WACOM_AXIS_WHEEL,
+ pPriv->min.nWheel, pPriv->max.nWheel,
+ 100000,0,100000);
+ return (pDevice->fd >= 0) ? Success : !Success;
+}
+
+static void wacomReadInput(LocalDevicePtr pDevice)
+{
+ int nLen;
+ unsigned char chBuf[256];
+
+ /* read and ignore for now */
+ SYSCALL(nLen = xf86ReadSerial(pDevice->fd, chBuf, sizeof(chBuf)));
+ return;
+}
+
+
diff --git a/src/wcm-beta.h b/src/wcm-beta.h
new file mode 100644
index 0000000..f3bafcc
--- /dev/null
+++ b/src/wcm-beta.h
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * wcm-beta.h
+ *
+ * Copyright 2002 by John Joganic <john@joganic.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+ *
+ * REVISION HISTORY
+ *
+ ****************************************************************************/
+
+#ifndef __XF86_WCM_BETA_H
+#define __XF86_WCM_BETA_H
+
+#include "xf86Version.h"
+#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(3,9,0,0,0)
+#error This code will not work on XFree86 version 3.x, yet
+#endif
+
+/* FOO **********************************************************************/
+
+#ifdef LINUX_INPUT
+#include <asm/types.h>
+#include <linux/input.h>
+
+/* 2.4.5 module support */
+#ifndef EV_MSC
+#define EV_MSC 0x04
+#endif
+
+#ifndef MSC_SERIAL
+#define MSC_SERIAL 0x00
+#endif
+
+/* max number of input events to read in one read call */
+#define MAX_EVENTS 50
+
+/* keithp - a hack to avoid redefinitions of these in xf86str.h */
+#ifdef BUS_PCI
+#undef BUS_PCI
+#endif
+#ifdef BUS_ISA
+#undef BUS_ISA
+#endif
+#endif /* LINUX_INPUT */
+
+/* BAR ***********************************************************************/
+
+#include <xf86Xinput.h>
+
+/***************************************************************************/
+
+InputInfoPtr wcmBetaNewDevice(InputDriverPtr pDriver, IDevPtr pConfig,
+ int nFlags);
+void wcmBetaDeleteDevice(InputDriverPtr pDriver, LocalDevicePtr pDevice,
+ int nFlags);
+
+/***************************************************************************/
+#endif /* __XF86_WCM_BETA_H */
diff --git a/src/xf86Wacom.c b/src/xf86Wacom.c
new file mode 100644
index 0000000..7924bd4
--- /dev/null
+++ b/src/xf86Wacom.c
@@ -0,0 +1,4070 @@
+/* $XConsortium: xf86Wacom.c /main/20 1996/10/27 11:05:20 kaleb $ */
+/*
+ * Copyright 1995-2002 by Frederic Lepied, France. <Lepied@XFree86.org>
+ *
+ * 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 Frederic Lepied not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Frederic Lepied makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL FREDERIC LEPIED 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.
+ *
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/wacom/xf86Wacom.c,v 1.26 2001/04/01 14:00:13 tsi Exp $ */
+
+/*
+ * This driver is only able to handle the Wacom IV and Wacom V protocols.
+ *
+ * Wacom V protocol work done by Raph Levien <raph@gtk.org> and
+ * Frdric Lepied <lepied@xfree86.org>.
+ *
+ * Many thanks to Dave Fleck from Wacom for the help provided to
+ * build this driver.
+ *
+ * Modified for Linux USB by MATSUMURA Namihiko,
+ * Daniel Egger, Germany. <egger@suse.de>,
+ * Frederic Lepied <lepied@xfree86.org>,
+ * Brion Vibber <brion@pobox.com>,
+ * Aaron Optimizer Digulla <digulla@hepe.com>,
+ * Jonathan Layes <jonathan@layes.com>.
+ *
+ */
+
+/*
+ * TO XFREE86 THE MAINTAINERS: don't remove the 3.3 code as I continue to maintain it.
+ * Discuss with me before changing things in this driver!
+ *
+ * Fred
+ */
+
+/*
+ * REVISION HISTORY
+ *
+ * 2002-12-17 26-j0.3.3 - added Intuos2
+ */
+
+static const char identification[] = "$Identification: 26-j0.3.3 $";
+
+#include "xf86Version.h"
+
+#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(3,9,0,0,0)
+#define XFREE86_V4 1
+#endif
+
+#ifdef LINUX_INPUT
+#include <asm/types.h>
+#include <linux/input.h>
+
+/* 2.4.5 module support */
+#ifndef EV_MSC
+#define EV_MSC 0x04
+#endif
+
+#ifndef MSC_SERIAL
+#define MSC_SERIAL 0x00
+#endif
+
+/* max number of input events to read in one read call */
+#define MAX_EVENTS 50
+
+/* keithp - a hack to avoid redefinitions of these in xf86str.h */
+#ifdef BUS_PCI
+#undef BUS_PCI
+#endif
+#ifdef BUS_ISA
+#undef BUS_ISA
+#endif
+#endif
+
+#ifdef XFREE86_V4
+/* post 3.9 headers */
+
+#ifndef XFree86LOADER
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#include "misc.h"
+#include "xf86.h"
+#define NEED_XF86_TYPES
+#if !defined(DGUX)
+#include "xf86_ansic.h"
+#include "xisb.h"
+#endif
+#include "xf86_OSproc.h"
+#include "xf86Xinput.h"
+#include "exevents.h" /* Needed for InitValuator/Proximity stuff */
+#include "keysym.h"
+#include "mipointer.h"
+
+#ifdef XFree86LOADER
+#include "xf86Module.h"
+#endif
+
+#undef sleep
+#define sleep(t) xf86WaitForInput(-1, 1000 * (t))
+#define wait_for_fd(fd) xf86WaitForInput((fd), 1000000)
+#define tcflush(fd, n) xf86FlushInput((fd))
+#undef read
+#define read(a,b,c) xf86ReadSerial((a),(b),(c))
+#undef write
+#define write(a,b,c) xf86WriteSerial((a),(char*)(b),(c))
+#undef close
+#define close(a) xf86CloseSerial((a))
+#define XCONFIG_PROBED "(==)"
+#define XCONFIG_GIVEN "(**)"
+#define xf86Verbose 1
+#undef PRIVATE
+#define PRIVATE(x) XI_PRIVATE(x)
+
+/*
+ * Be sure to set vmin appropriately for your device's protocol. You want to
+ * read a full packet before returning
+ */
+static const char *default_options[] =
+{
+ "BaudRate", "9600",
+ "StopBits", "1",
+ "DataBits", "8",
+ "Parity", "None",
+ "Vmin", "1",
+ "Vtime", "10",
+ "FlowControl", "Xoff",
+ NULL
+};
+
+static InputDriverPtr wcmDrv;
+
+#else /* pre 3.9 headers */
+
+#include "Xos.h"
+#include <signal.h>
+#include <stdio.h>
+
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "XI.h"
+#include "XIproto.h"
+#include "keysym.h"
+
+#if defined(sun) && !defined(i386)
+#define POSIX_TTY
+#include <errno.h>
+#include <termio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include "extio.h"
+#else
+#include "compiler.h"
+
+#include "xf86.h"
+#include "xf86Procs.h"
+#include "xf86_OSlib.h"
+#include "xf86_Config.h"
+#include "xf86Xinput.h"
+#include "atKeynames.h"
+#include "xf86Version.h"
+#endif
+
+#if !defined(sun) || defined(i386)
+#include "osdep.h"
+#include "exevents.h"
+
+#include "extnsionst.h"
+#include "extinit.h"
+#endif
+
+#endif /* Pre 3.9 headers */
+
+#if defined(__QNX__) || defined(__QNXNTO__)
+#define POSIX_TTY
+#endif
+
+/******************************************************************************
+ * debugging macro
+ *****************************************************************************/
+#ifdef DBG
+#undef DBG
+#endif
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+static int debug_level = 0;
+#define DEBUG 1
+#if DEBUG
+#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}
+#else
+#define DBG(lvl, f)
+#endif
+
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+
+/******************************************************************************
+ * WacomDeviceRec flags
+ *****************************************************************************/
+#define DEVICE_ID(flags) ((flags) & 0x07)
+
+#define STYLUS_ID 1
+#define CURSOR_ID 2
+#define ERASER_ID 4
+#define ABSOLUTE_FLAG 8
+#define FIRST_TOUCH_FLAG 16
+#define KEEP_SHAPE_FLAG 32
+#define BAUD_19200_FLAG 64
+#define BETA_FLAG 128
+
+/******************************************************************************
+ * WacomCommonRec flags
+ *****************************************************************************/
+#define TILT_FLAG 1
+#define GRAPHIRE_FLAG 2
+
+typedef struct
+{
+ int state;
+ int coord[3];
+ int tilt[3];
+} WacomFilterState;
+
+typedef struct
+{
+ int device_id;
+ int device_type;
+ unsigned int serial_num;
+ int x;
+ int y;
+ int buttons;
+ int pressure;
+ int tiltx;
+ int tilty;
+ int rotation;
+ int wheel;
+ int discard_first;
+ int proximity;
+ WacomFilterState x_filter;
+ WacomFilterState y_filter;
+} WacomDeviceState;
+
+#define PEN(ds) (((ds->device_id) & 0x07ff) == 0x0022 || ((ds->device_id) & 0x07ff) == 0x0052)
+#define STROKING_PEN(ds) (((ds->device_id) & 0x07ff) == 0x0032)
+#define AIRBRUSH(ds) (((ds->device_id) & 0x07ff) == 0x0112)
+#define MOUSE_4D(ds) (((ds->device_id) & 0x07ff) == 0x0094)
+#define LENS_CURSOR(ds) (((ds->device_id) & 0x07ff) == 0x0096)
+#define INKING_PEN(ds) (((ds->device_id) & 0x07ff) == 0x0012)
+
+typedef struct
+{
+ /* configuration fields */
+ unsigned int flags; /* various flags (device type, absolute, first touch...) */
+ int topX; /* X top */
+ int topY; /* Y top */
+ int bottomX; /* X bottom */
+ int bottomY; /* Y bottom */
+ double factorX; /* X factor */
+ double factorY; /* Y factor */
+ unsigned int serial; /* device serial number */
+ int initNumber; /* magic number for the init phasis */
+ int screen_no; /* associated screen */
+
+ struct _WacomCommonRec *common; /* common info pointer */
+
+ /* state fields */
+ int oldX; /* previous X position */
+ int oldY; /* previous Y position */
+ int oldZ; /* previous pressure */
+ int oldTiltX; /* previous tilt in x direction */
+ int oldTiltY; /* previous tilt in y direction */
+ int oldWheel; /* previous wheel value */
+ int oldButtons; /* previous buttons state */
+ int oldProximity; /* previous proximity */
+
+ /* JEJ - throttle */
+ int throttleStart; /* time in ticks for last wheel movement */
+ int throttleLimit; /* time in ticks for next wheel movement */
+ int throttleValue; /* current throttle value */
+
+} WacomDeviceRec, *WacomDevicePtr;
+
+#define MAX_USB_EVENTS 6
+
+typedef struct _WacomCommonRec
+{
+ char *wcmDevice; /* device file name */
+ int wcmSuppress; /* transmit position if increment is superior */
+ unsigned char wcmFlags; /* various flags (handle tilt) */
+ int wcmMaxX; /* max X value */
+ int wcmMaxY; /* max Y value */
+ int wcmMaxZ; /* max Z value */
+ int wcmResolX; /* X resolution in points/inch */
+ int wcmResolY; /* Y resolution in points/inch */
+ int wcmResolZ; /* Z resolution in points/inch */
+ LocalDevicePtr *wcmDevices; /* array of all devices sharing the same port */
+ int wcmNumDevices; /* number of devices */
+ int wcmIndex; /* number of bytes read */
+ int wcmPktLength; /* length of a packet */
+ unsigned char wcmData[9]; /* data read on the device */
+ Bool wcmHasEraser; /* True if an eraser has been configured */
+ Bool wcmStylusSide; /* eraser or stylus ? */
+ Bool wcmStylusProximity; /* the stylus is in proximity ? */
+ int wcmProtocolLevel; /* 4 for Wacom IV, 5 for Wacom V */
+ int wcmThreshold; /* Threshold for counting pressure as a button */
+ WacomDeviceState wcmDevStat[2]; /* device state for each tool */
+ int wcmInitNumber; /* magic number for the init phasis */
+ unsigned int wcmLinkSpeed; /* serial link speed */
+ Bool (*wcmOpen)(LocalDevicePtr /*local*/); /* function used to open the line (serial or USB) */
+ unsigned int wcmLastSerial; /* last device (used by the USB part) */
+ int wcmLastTool; /* last tool (used by USB part) */
+#ifdef LINUX_INPUT
+ struct input_event wcmEvent[MAX_USB_EVENTS]; /* data used by USB driver */
+#endif
+} WacomCommonRec, *WacomCommonPtr;
+
+/******************************************************************************
+ * configuration stuff
+ *****************************************************************************/
+#define CURSOR_SECTION_NAME "wacomcursor"
+#define STYLUS_SECTION_NAME "wacomstylus"
+#define ERASER_SECTION_NAME "wacomeraser"
+
+#ifndef XFREE86_V4
+
+#define PORT 1
+#define DEVICENAME 2
+#define THE_MODE 3
+#define SUPPRESS 4
+#define DEBUG_LEVEL 5
+#define TILT_MODE 6
+#define HISTORY_SIZE 7
+#define ALWAYS_CORE 8
+#define KEEP_SHAPE 9
+#define TOP_X 10
+#define TOP_Y 11
+#define BOTTOM_X 12
+#define BOTTOM_Y 13
+#define SERIAL 14
+#define BAUD_RATE 15
+#define THRESHOLD 16
+#define MAX_X 17
+#define MAX_Y 18
+#define MAX_Z 19
+#define RESOLUTION_X 20
+#define RESOLUTION_Y 21
+#define RESOLUTION_Z 22
+#define USB 23
+#define SCREEN_NO 24
+
+#if !defined(sun) || defined(i386)
+static SymTabRec WcmTab[] = {
+ { ENDSUBSECTION, "endsubsection" },
+ { PORT, "port" },
+ { DEVICENAME, "devicename" },
+ { THE_MODE, "mode" },
+ { SUPPRESS, "suppress" },
+ { DEBUG_LEVEL, "debuglevel" },
+ { TILT_MODE, "tiltmode" },
+ { HISTORY_SIZE, "historysize" },
+ { ALWAYS_CORE, "alwayscore" },
+ { KEEP_SHAPE, "keepshape" },
+ { TOP_X, "topx" },
+ { TOP_Y, "topy" },
+ { BOTTOM_X, "bottomx" },
+ { BOTTOM_Y, "bottomy" },
+ { SERIAL, "serial" },
+ { BAUD_RATE, "baudrate" },
+ { THRESHOLD, "threshold" },
+ { MAX_X, "maxx" },
+ { MAX_Y, "maxy" },
+ { MAX_Z, "maxz" },
+ { RESOLUTION_X, "resolutionx" },
+ { RESOLUTION_Y, "resolutiony" },
+ { RESOLUTION_Z, "resolutionz" },
+ { USB, "usb" },
+ { SCREEN_NO, "screenno" },
+ { -1, "" }
+};
+
+#define RELATIVE 1
+#define ABSOLUTE 2
+
+static SymTabRec ModeTabRec[] = {
+ { RELATIVE, "relative" },
+ { ABSOLUTE, "absolute" },
+ { -1, "" }
+};
+
+#endif
+
+#endif /* Pre 3.9 headers */
+
+/******************************************************************************
+ * constant and macros declarations
+ *****************************************************************************/
+#define DEFAULT_MAXZ 240 /* default value of MaxZ when nothing is configured */
+#define BUFFER_SIZE 256 /* size of reception buffer */
+#define XI_STYLUS "STYLUS" /* X device name for the stylus */
+#define XI_CURSOR "CURSOR" /* X device name for the cursor */
+#define XI_ERASER "ERASER" /* X device name for the eraser */
+#define MAX_VALUE 100 /* number of positions */
+#define MAXTRY 3 /* max number of try to receive magic number */
+#define MAX_COORD_RES 1270.0 /* Resolution of the returned MaxX and MaxY */
+#define INVALID_THRESHOLD 30000 /* Invalid threshold value used to test if the user
+ * configured it or not */
+
+#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
+
+#define WC_RESET "\r#" /* reset to wacom IV command set or wacom V reset */
+#define WC_RESET_BAUD "\r$" /* reset baud rate to default (wacom V) or switch to wacom IIs (wacom IV) */
+#define WC_CONFIG "~R\r" /* request a configuration string */
+#define WC_COORD "~C\r" /* request max coordinates */
+#define WC_MODEL "~#\r" /* request model and ROM version */
+
+#define WC_MULTI "MU1\r" /* multi mode input */
+#define WC_UPPER_ORIGIN "OC1\r" /* origin in upper left */
+#define WC_SUPPRESS "SU" /* suppress mode */
+#define WC_ALL_MACRO "~M0\r" /* enable all macro buttons */
+#define WC_NO_MACRO1 "~M1\r" /* disable macro buttons of group 1 */
+#define WC_RATE "IT0\r" /* max transmit rate (unit of 5 ms) */
+#define WC_TILT_MODE "FM1\r" /* enable extra protocol for tilt management */
+#define WC_NO_INCREMENT "IN0\r" /* do not enable increment mode */
+#define WC_STREAM_MODE "SR\r" /* enable continuous mode */
+#define WC_PRESSURE_MODE "PH1\r" /* enable pressure mode */
+#define WC_ZFILTER "ZF1\r" /* stop sending coordinates */
+#define WC_STOP "\nSP\r" /* stop sending coordinates */
+#define WC_START "ST\r" /* start sending coordinates */
+#define WC_NEW_RESOLUTION "NR" /* change the resolution */
+
+static const char * setup_string = WC_MULTI WC_UPPER_ORIGIN
+ WC_ALL_MACRO WC_NO_MACRO1 WC_RATE WC_NO_INCREMENT WC_STREAM_MODE WC_ZFILTER;
+
+static const char * penpartner_setup_string = WC_PRESSURE_MODE WC_START;
+
+#define WC_V_SINGLE "MT0\r"
+#define WC_V_MULTI "MT1\r"
+#define WC_V_ID "ID1\r"
+#define WC_V_19200 "BA19\r"
+#define WC_V_38400 "BA38\r"
+/* #define WC_V_9600 "BA96\r" */
+#define WC_V_9600 "$\r"
+
+#define WC_RESET_19200 "\r$" /* reset to 9600 baud */
+#define WC_RESET_19200_IV "\r#"
+
+static const char * intuos_setup_string = WC_V_MULTI WC_V_ID WC_RATE WC_START;
+
+#define COMMAND_SET_MASK 0xc0
+#define BAUD_RATE_MASK 0x0a
+#define PARITY_MASK 0x30
+#define DATA_LENGTH_MASK 0x40
+#define STOP_BIT_MASK 0x80
+
+#define HEADER_BIT 0x80
+#define ZAXIS_SIGN_BIT 0x40
+#define ZAXIS_BIT 0x04
+#define ZAXIS_BITS 0x3f
+#define POINTER_BIT 0x20
+#define PROXIMITY_BIT 0x40
+#define BUTTON_FLAG 0x08
+#define BUTTONS_BITS 0x78
+#define TILT_SIGN_BIT 0x40
+#define TILT_BITS 0x3f
+
+/* defines to discriminate second side button and the eraser */
+#define ERASER_PROX 4
+#define OTHER_PROX 1
+
+#define HANDLE_TILT(comm) ((comm)->wcmPktLength == 9)
+
+#define mils(res) (res * 100 / 2.54) /* resolution */
+
+/******************************************************************************
+ * Function/Macro keys variables
+ *****************************************************************************/
+static KeySym wacom_map[] =
+{
+ NoSymbol, /* 0x00 */
+ NoSymbol, /* 0x01 */
+ NoSymbol, /* 0x02 */
+ NoSymbol, /* 0x03 */
+ NoSymbol, /* 0x04 */
+ NoSymbol, /* 0x05 */
+ NoSymbol, /* 0x06 */
+ NoSymbol, /* 0x07 */
+ XK_F1, /* 0x08 */
+ XK_F2, /* 0x09 */
+ XK_F3, /* 0x0a */
+ XK_F4, /* 0x0b */
+ XK_F5, /* 0x0c */
+ XK_F6, /* 0x0d */
+ XK_F7, /* 0x0e */
+ XK_F8, /* 0x0f */
+ XK_F8, /* 0x10 */
+ XK_F10, /* 0x11 */
+ XK_F11, /* 0x12 */
+ XK_F12, /* 0x13 */
+ XK_F13, /* 0x14 */
+ XK_F14, /* 0x15 */
+ XK_F15, /* 0x16 */
+ XK_F16, /* 0x17 */
+ XK_F17, /* 0x18 */
+ XK_F18, /* 0x19 */
+ XK_F19, /* 0x1a */
+ XK_F20, /* 0x1b */
+ XK_F21, /* 0x1c */
+ XK_F22, /* 0x1d */
+ XK_F23, /* 0x1e */
+ XK_F24, /* 0x1f */
+ XK_F25, /* 0x20 */
+ XK_F26, /* 0x21 */
+ XK_F27, /* 0x22 */
+ XK_F28, /* 0x23 */
+ XK_F29, /* 0x24 */
+ XK_F30, /* 0x25 */
+ XK_F31, /* 0x26 */
+ XK_F32 /* 0x27 */
+};
+
+/* minKeyCode = 8 because this is the min legal key code */
+static KeySymsRec wacom_keysyms = {
+ /* map minKeyCode maxKC width */
+ wacom_map, 8, 0x27, 1
+};
+
+/******************************************************************************
+ * external declarations
+ *****************************************************************************/
+
+#ifdef LINUX_INPUT
+static void xf86WcmReadUSBInput(LocalDevicePtr);
+static Bool xf86WcmUSBOpen(LocalDevicePtr);
+#endif
+
+
+#ifndef XFREE86_V4
+
+#if defined(sun) && !defined(i386)
+#define ENQUEUE suneqEnqueue
+#else
+#define ENQUEUE xf86eqEnqueue
+
+extern void xf86eqEnqueue(
+#if NeedFunctionPrototypes
+ xEventPtr /*e*/
+#endif
+);
+#endif
+
+extern void miPointerDeltaCursor(
+#if NeedFunctionPrototypes
+ int /*dx*/,
+ int /*dy*/,
+ unsigned long /*time*/
+#endif
+);
+
+#endif /* pre 3.9 declarations */
+
+#if NeedFunctionPrototypes
+static LocalDevicePtr xf86WcmAllocateStylus(void);
+static LocalDevicePtr xf86WcmAllocateCursor(void);
+static LocalDevicePtr xf86WcmAllocateEraser(void);
+#endif
+
+#ifndef XFREE86_V4
+/*
+ ***************************************************************************
+ *
+ * xf86WcmConfig --
+ * Configure the device.
+ *
+ ***************************************************************************
+ */
+static Bool
+xf86WcmConfig(LocalDevicePtr *array,
+ int inx,
+ int max,
+ LexPtr val)
+{
+ LocalDevicePtr dev = array[inx];
+ WacomDevicePtr priv = (WacomDevicePtr)(dev->private);
+ WacomCommonPtr common = priv->common;
+ int token;
+ int mtoken;
+
+ DBG(1, ErrorF("xf86WcmConfig\n"));
+
+ if (xf86GetToken(WcmTab) != PORT) {
+ xf86ConfigError("PORT option must be the first option of a Wacom SubSection");
+ }
+
+ if (xf86GetToken(NULL) != STRING)
+ xf86ConfigError("Option string expected");
+ else {
+ int loop;
+
+ /* try to find another wacom device which share the same port */
+ for(loop=0; loop<max; loop++) {
+ if (loop == inx)
+ continue;
+ if ((array[loop]->device_config == xf86WcmConfig) &&
+ (strcmp(((WacomDevicePtr)array[loop]->private)->common->wcmDevice, val->str) == 0)) {
+ DBG(2, ErrorF("xf86WcmConfig wacom port share between"
+ " %s and %s\n",
+ dev->name, array[loop]->name));
+ ((WacomDevicePtr) array[loop]->private)->common->wcmHasEraser |= common->wcmHasEraser;
+ xfree(common->wcmDevices);
+ xfree(common);
+ common = priv->common = ((WacomDevicePtr) array[loop]->private)->common;
+ common->wcmNumDevices++;
+ common->wcmDevices = (LocalDevicePtr *) xrealloc(common->wcmDevices,
+ sizeof(LocalDevicePtr) * common->wcmNumDevices);
+ common->wcmDevices[common->wcmNumDevices - 1] = dev;
+ break;
+ }
+ }
+ if (loop == max) {
+ common->wcmDevice = strdup(val->str);
+ if (xf86Verbose)
+ ErrorF("%s Wacom port is %s\n", XCONFIG_GIVEN,
+ common->wcmDevice);
+ }
+ }
+
+ while ((token = xf86GetToken(WcmTab)) != ENDSUBSECTION) {
+ switch(token) {
+ case DEVICENAME:
+ if (xf86GetToken(NULL) != STRING)
+ xf86ConfigError("Option string expected");
+ dev->name = strdup(val->str);
+ if (xf86Verbose)
+ ErrorF("%s Wacom X device name is %s\n", XCONFIG_GIVEN,
+ dev->name);
+ break;
+
+ case THE_MODE:
+ mtoken = xf86GetToken(ModeTabRec);
+ if ((mtoken == EOF) || (mtoken == STRING) || (mtoken == NUMBER))
+ xf86ConfigError("Mode type token expected");
+ else {
+ switch (mtoken) {
+ case ABSOLUTE:
+ priv->flags = priv->flags | ABSOLUTE_FLAG;
+ break;
+ case RELATIVE:
+ priv->flags = priv->flags & ~ABSOLUTE_FLAG;
+ break;
+ default:
+ xf86ConfigError("Illegal Mode type");
+ break;
+ }
+ }
+ break;
+
+ case SUPPRESS:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmSuppress = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom suppress value is %d\n", XCONFIG_GIVEN,
+ common->wcmSuppress);
+ break;
+
+ case DEBUG_LEVEL:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ debug_level = val->num;
+ if (xf86Verbose) {
+#if DEBUG
+ ErrorF("%s Wacom debug level sets to %d\n", XCONFIG_GIVEN,
+ debug_level);
+#else
+ ErrorF("%s Wacom debug level not sets to %d because"
+ " debugging is not compiled\n", XCONFIG_GIVEN,
+ debug_level);
+#endif
+ }
+ break;
+
+ case TILT_MODE:
+ common->wcmFlags |= TILT_FLAG;
+ break;
+
+ case HISTORY_SIZE:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ dev->history_size = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom Motion history size is %d\n", XCONFIG_GIVEN,
+ dev->history_size);
+ break;
+
+ case ALWAYS_CORE:
+ xf86AlwaysCore(dev, TRUE);
+ if (xf86Verbose)
+ ErrorF("%s Wacom device always stays core pointer\n",
+ XCONFIG_GIVEN);
+ break;
+
+ case KEEP_SHAPE:
+ priv->flags |= KEEP_SHAPE_FLAG;
+ if (xf86Verbose)
+ ErrorF("%s Wacom keeps shape\n",
+ XCONFIG_GIVEN);
+ break;
+
+ case TOP_X:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->topX = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom top x = %d\n", XCONFIG_GIVEN, priv->topX);
+ break;
+
+ case TOP_Y:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->topY = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom top y = %d\n", XCONFIG_GIVEN, priv->topY);
+ break;
+
+ case BOTTOM_X:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->bottomX = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom bottom x = %d\n", XCONFIG_GIVEN, priv->bottomX);
+ break;
+
+ case BOTTOM_Y:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->bottomY = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom bottom y = %d\n", XCONFIG_GIVEN, priv->bottomY);
+ break;
+
+ case SERIAL:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->serial = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom serial number = %u\n", XCONFIG_GIVEN,
+ priv->serial);
+ break;
+
+ case BAUD_RATE:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ switch(val->num) {
+ case 38400:
+ common->wcmLinkSpeed = 38400;
+ break;
+ case 19200:
+ common->wcmLinkSpeed = 19200;
+ break;
+ case 9600:
+ common->wcmLinkSpeed = 9600;
+ break;
+ default:
+ xf86ConfigError("Illegal speed value");
+ break;
+ }
+ if (xf86Verbose)
+ ErrorF("%s Wacom baud rate of %u\n", XCONFIG_GIVEN,
+ val->num);
+ break;
+
+ case THRESHOLD:
+ if (xf86GetToken(NULL) != STRING)
+ xf86ConfigError("Option string expected");
+
+ common->wcmThreshold = atoi(val->str);
+
+ if (xf86Verbose)
+ ErrorF("%s Wacom pressure threshold for button 1 = %d\n",
+ XCONFIG_GIVEN, common->wcmThreshold);
+ break;
+
+ case MAX_X:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmMaxX = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom max x = %d\n", XCONFIG_GIVEN, common->wcmMaxX);
+ break;
+
+ case MAX_Y:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmMaxY = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom max y = %d\n", XCONFIG_GIVEN, common->wcmMaxY);
+ break;
+
+ case MAX_Z:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmMaxZ = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom max y = %d\n", XCONFIG_GIVEN, common->wcmMaxZ);
+ break;
+
+ case RESOLUTION_X:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmResolX = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom resolution x = %d\n", XCONFIG_GIVEN, common->wcmResolX);
+ break;
+
+ case RESOLUTION_Y:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmResolY = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom resolution y = %d\n", XCONFIG_GIVEN, common->wcmResolY);
+ break;
+
+ case RESOLUTION_Z:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ common->wcmResolZ = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom resolution y = %d\n", XCONFIG_GIVEN, common->wcmResolZ);
+ break;
+
+ case USB:
+#ifdef LINUX_INPUT
+ dev->read_input=xf86WcmReadUSBInput;
+ common->wcmOpen=xf86WcmUSBOpen;
+ ErrorF("%s Wacom reading USB link\n", XCONFIG_GIVEN);
+#else
+ ErrorF("The USB version of the driver isn't available for your platform\n");
+#endif
+ break;
+
+ case SCREEN_NO:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->screen_no = val->num;
+ if (xf86Verbose)
+ ErrorF("%s Wacom attached screen = %d\n", XCONFIG_GIVEN,
+ priv->screen_no);
+ break;
+
+ case EOF:
+ FatalError("Unexpected EOF (missing EndSubSection)");
+ break;
+
+ default:
+ xf86ConfigError("Wacom subsection keyword expected");
+ break;
+ }
+ }
+
+ DBG(1, ErrorF("xf86WcmConfig name=%s\n", common->wcmDevice));
+
+ return Success;
+}
+#endif /* Pre 3.9 stuff */
+
+#if 0
+/*
+ ***************************************************************************
+ *
+ * ascii_to_hexa --
+ *
+ ***************************************************************************
+ */
+/*
+ * transform two ascii hexa representation into an unsigned char
+ * most significant byte is the first one
+ */
+static unsigned char
+ascii_to_hexa(char buf[2])
+{
+ unsigned char uc;
+
+ if (buf[0] >= 'A') {
+ uc = buf[0] - 'A' + 10;
+ }
+ else {
+ uc = buf[0] - '0';
+ }
+ uc = uc << 4;
+ if (buf[1] >= 'A') {
+ uc += buf[1] - 'A' + 10;
+ }
+ else {
+ uc += buf[1] - '0';
+ }
+ return uc;
+}
+#endif
+
+#ifndef XFREE86_V4
+/*
+ ***************************************************************************
+ *
+ * set_serial_speed --
+ *
+ * Set speed of the serial port.
+ *
+ ***************************************************************************
+ */
+static int
+set_serial_speed(int fd,
+ int speed_code)
+{
+ struct termios termios_tty;
+ int err;
+
+#ifdef POSIX_TTY
+ SYSCALL(err = tcgetattr(fd, &termios_tty));
+
+ if (err == -1) {
+ ErrorF("Wacom tcgetattr error : %s\n", strerror(errno));
+ return !Success;
+ }
+ termios_tty.c_iflag = IXOFF;
+ termios_tty.c_oflag = 0;
+ termios_tty.c_cflag = speed_code|CS8|CREAD|CLOCAL;
+ termios_tty.c_lflag = 0;
+
+ termios_tty.c_cc[VINTR] = 0;
+ termios_tty.c_cc[VQUIT] = 0;
+ termios_tty.c_cc[VERASE] = 0;
+ termios_tty.c_cc[VEOF] = 0;
+#ifdef VWERASE
+ termios_tty.c_cc[VWERASE] = 0;
+#endif
+#ifdef VREPRINT
+ termios_tty.c_cc[VREPRINT] = 0;
+#endif
+ termios_tty.c_cc[VKILL] = 0;
+ termios_tty.c_cc[VEOF] = 0;
+ termios_tty.c_cc[VEOL] = 0;
+#ifdef VEOL2
+ termios_tty.c_cc[VEOL2] = 0;
+#endif
+ termios_tty.c_cc[VSUSP] = 0;
+#ifdef VDSUSP
+ termios_tty.c_cc[VDSUSP] = 0;
+#endif
+#ifdef VDISCARD
+ termios_tty.c_cc[VDISCARD] = 0;
+#endif
+#ifdef VLNEXT
+ termios_tty.c_cc[VLNEXT] = 0;
+#endif
+
+ /* minimum 1 character in one read call and timeout to 100 ms */
+ termios_tty.c_cc[VMIN] = 1;
+ termios_tty.c_cc[VTIME] = 10;
+
+ SYSCALL(err = tcsetattr(fd, TCSANOW, &termios_tty));
+ if (err == -1) {
+ ErrorF("Wacom tcsetattr TCSANOW error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+#else
+ Code for OSs without POSIX tty functions
+#endif
+
+ return Success;
+}
+
+/*
+ ***************************************************************************
+ *
+ * wait_for_fd --
+ *
+ * Wait one second that the file descriptor becomes readable.
+ *
+ ***************************************************************************
+ */
+static int
+wait_for_fd(int fd)
+{
+ int err;
+ fd_set readfds;
+ struct timeval timeout;
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ SYSCALL(err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout));
+
+ return err;
+}
+
+/*
+ ***************************************************************************
+ *
+ * flush_input_fd --
+ *
+ * Flush all input pending on the file descriptor.
+ *
+ ***************************************************************************
+ */
+static int
+flush_input_fd(int fd)
+{
+ int err;
+ fd_set readfds;
+ struct timeval timeout;
+ char dummy[1];
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ do {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ SYSCALL(err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout));
+
+ if (err > 0) {
+ SYSCALL(err = read(fd, &dummy, 1));
+ DBG(10, ErrorF("flush_input_fd: read %d bytes\n", err));
+ }
+ } while (err > 0);
+ return err;
+}
+#endif /* Pre 3.9 stuff */
+
+/*
+ ***************************************************************************
+ *
+ * send_request --
+ *
+ ***************************************************************************
+ */
+/*
+ * send a request and wait for the answer.
+ * the answer must begin with the first two chars of the request and must end
+ * with \r. The last character in the answer string (\r) is replaced by a \0.
+ */
+static char *
+send_request(int fd,
+ char *request,
+ char *answer)
+{
+ int len, nr;
+ int maxtry = MAXTRY;
+
+ /* send request string */
+ do {
+ SYSCALL(len = write(fd, request, strlen(request)));
+ if ((len == -1) && (errno != EAGAIN)) {
+ ErrorF("Wacom write error : %s", strerror(errno));
+ return NULL;
+ }
+ maxtry--;
+ } while ((len == -1) && maxtry);
+
+ if (maxtry == 0) {
+ ErrorF("Wacom unable to write request string '%s' after %d tries\n", request, MAXTRY);
+ return NULL;
+ }
+
+ do {
+ maxtry = MAXTRY;
+
+ /* Read the first byte of the answer which must be equal to the first
+ * byte of the request.
+ */
+ do {
+ if ((nr = wait_for_fd(fd)) > 0) {
+ SYSCALL(nr = read(fd, answer, 1));
+ if ((nr == -1) && (errno != EAGAIN)) {
+ ErrorF("Wacom read error : %s\n", strerror(errno));
+ return NULL;
+ }
+ DBG(10, ErrorF("%c err=%d [0]\n", answer[0], nr));
+ }
+ maxtry--;
+ } while ((answer[0] != request[0]) && maxtry);
+
+ if (maxtry == 0) {
+ ErrorF("Wacom unable to read first byte of request '%c%c' answer after %d tries\n",
+ request[0], request[1], MAXTRY);
+ return NULL;
+ }
+
+ /* Read the second byte of the answer which must be equal to the second
+ * byte of the request.
+ */
+ do {
+ maxtry = MAXTRY;
+ do {
+ if ((nr = wait_for_fd(fd)) > 0) {
+ SYSCALL(nr = read(fd, answer+1, 1));
+ if ((nr == -1) && (errno != EAGAIN)) {
+ ErrorF("Wacom read error : %s\n", strerror(errno));
+ return NULL;
+ }
+ DBG(10, ErrorF("%c err=%d [1]\n", answer[1], nr));
+ }
+ maxtry--;
+ } while ((nr <= 0) && maxtry);
+
+ if (maxtry == 0) {
+ ErrorF("Wacom unable to read second byte of request '%c%c' answer after %d tries\n",
+ request[0], request[1], MAXTRY);
+ return NULL;
+ }
+
+ if (answer[1] != request[1])
+ answer[0] = answer[1];
+
+ } while ((answer[0] == request[0]) &&
+ (answer[1] != request[1]));
+
+ } while ((answer[0] != request[0]) &&
+ (answer[1] != request[1]));
+
+ /* Read until carriage return or timeout (to handle broken protocol
+ * implementations which don't end with a <cr>).
+ */
+ len = 2;
+ maxtry = MAXTRY;
+ do {
+ do {
+ if ((nr = wait_for_fd(fd)) > 0) {
+ SYSCALL(nr = read(fd, answer+len, 1));
+ if ((nr == -1) && (errno != EAGAIN)) {
+ ErrorF("Wacom read error : %s\n", strerror(errno));
+ return NULL;
+ }
+ DBG(10, ErrorF("%c err=%d [%d]\n", answer[len], nr, len));
+ }
+ else {
+ DBG(10, ErrorF("timeout remains %d tries\n", maxtry));
+ maxtry--;
+ }
+ } while ((nr <= 0) && maxtry);
+
+ if (nr > 0) {
+ len += nr;
+ }
+
+ if (maxtry == 0) {
+ ErrorF("Wacom unable to read last byte of request '%c%c' answer after %d tries\n",
+ request[0], request[1], MAXTRY);
+ break;
+ }
+ } while (answer[len-1] != '\r');
+
+ if (len <= 3)
+ return NULL;
+
+ answer[len-1] = '\0';
+
+ return answer;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmConvert --
+ * Convert valuators to X and Y.
+ *
+ ***************************************************************************
+ */
+static Bool
+xf86WcmConvert(LocalDevicePtr local,
+ int first,
+ int num,
+ int v0,
+ int v1,
+ int v2,
+ int v3,
+ int v4,
+ int v5,
+ int* x,
+ int* y)
+{
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+
+ DBG(6, ErrorF("xf86WcmConvert\n"));
+
+ if (first != 0 || num == 1)
+ return FALSE;
+
+#ifdef XFREE86_V4
+ {
+ ScreenPtr pscr;
+
+ if (priv->screen_no != -1) {
+ pscr = screenInfo.screens[priv->screen_no];
+ } else {
+ pscr = miPointerCurrentScreen();
+ }
+
+ if (pscr == NULL)
+ return FALSE;
+
+ priv->factorX = ((double) pscr->width)
+ / (priv->bottomX - priv->topX);
+ priv->factorY = ((double) pscr->height)
+ / (priv->bottomY - priv->topY);
+ }
+#endif
+
+ *x = v0 * priv->factorX + 0.5;
+ *y = v1 * priv->factorY + 0.5;
+
+ DBG(6, ErrorF("Wacom converted v0=%d v1=%d to x=%d y=%d\n",
+ v0, v1, *x, *y));
+#ifdef XFREE86_V4
+ if (priv->screen_no != -1) {
+ xf86XInputSetScreen(local, priv->screen_no, *x, *y);
+ }
+#endif
+ return TRUE;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmReverseConvert --
+ * Convert X and Y to valuators.
+ *
+ ***************************************************************************
+ */
+static Bool
+xf86WcmReverseConvert(LocalDevicePtr local,
+ int x,
+ int y,
+ int *valuators)
+{
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+
+#ifdef XFREE86_V4
+ priv->factorX = ((double) miPointerCurrentScreen()->width)
+ / (priv->bottomX - priv->topX);
+ priv->factorY = ((double) miPointerCurrentScreen()->height)
+ / (priv->bottomY - priv->topY);
+#endif
+
+ valuators[0] = x / priv->factorX + 0.5;
+ valuators[1] = y / priv->factorY + 0.5;
+
+ DBG(6, ErrorF("Wacom converted x=%d y=%d to v0=%d v1=%d\n", x, y,
+ valuators[0], valuators[1]));
+
+ return TRUE;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmSendButtons --
+ * Send button events by comparing the current button mask with the
+ * previous one.
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmSendButtons(LocalDevicePtr local,
+ int buttons,
+ int rx,
+ int ry,
+ int rz,
+ int rtx,
+ int rty,
+ int rwheel)
+
+{
+ int button;
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+
+ for (button=1; button<=16; button++) {
+ int mask = 1 << (button-1);
+
+ if ((mask & priv->oldButtons) != (mask & buttons)) {
+ DBG(4, ErrorF("xf86WcmSendButtons button=%d state=%d\n",
+ button, (buttons & mask) != 0));
+ xf86PostButtonEvent(local->dev,
+ (priv->flags & ABSOLUTE_FLAG),
+ button, (buttons & mask) != 0,
+ 0, 6, rx, ry, rz, rtx, rty, rwheel);
+ }
+ }
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmSendEvents --
+ * Send events according to the device state.
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmSendEvents(LocalDevicePtr local,
+ int type,
+ unsigned int serial,
+ int is_stylus,
+ int is_button,
+ int is_proximity,
+ int x,
+ int y,
+ int z,
+ int buttons,
+ int tx,
+ int ty,
+ int wheel)
+{
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+ WacomCommonPtr common = priv->common;
+ int rx, ry, rz, rtx, rty, rwheel;
+ int is_core_pointer, is_absolute;
+
+ if ((DEVICE_ID(priv->flags) != type) ||
+ ((common->wcmProtocolLevel == 5) &&
+ priv->serial && (serial != priv->serial))) {
+ DBG(7,
+ {if (common->wcmProtocolLevel == 5) {
+ ErrorF("xf86WcmSendEvents not the same device id (%u,%u)\n",
+ serial, priv->serial);
+ } else {
+ ErrorF("xf86WcmSendEvents not the same device type (%u,%u)\n",
+ DEVICE_ID(priv->flags), type);}});
+ return;
+ }
+
+ DBG(7, ErrorF("[%s] prox=%s\tx=%d\ty=%d\tz=%d\tbutton=%s\tbuttons=%d\ttx=%d ty=%d\twl=%d\n",
+ (type == STYLUS_ID) ? "stylus" : (type == CURSOR_ID) ? "cursor" : "eraser",
+ is_proximity ? "true" : "false",
+ x, y, z,
+ is_button ? "true" : "false", buttons,
+ tx, ty, wheel));
+
+ /* Translate coordinates according to Top and Bottom points
+ * if we are outside the zone do as a ProximityOut event.
+ */
+
+ if (x > priv->bottomX) {
+ is_proximity = FALSE;
+ buttons = 0;
+ x = priv->bottomX;
+ }
+
+ if (y > priv->bottomY) {
+ is_proximity = FALSE;
+ buttons = 0;
+ y = priv->bottomY;
+ }
+
+ DBG(10, ErrorF("topX=%d topY=%d\n", priv->topX, priv->topY));
+
+ x = x - priv->topX;
+ y = y - priv->topY;
+
+ if (x < 0) {
+ is_proximity = FALSE;
+ buttons = 0;
+ x = 0;
+ }
+
+ if (y < 0) {
+ is_proximity = FALSE;
+ buttons = 0;
+ y = 0;
+ }
+
+ is_absolute = (priv->flags & ABSOLUTE_FLAG);
+ is_core_pointer = xf86IsCorePointer(local->dev);
+
+ DBG(6, ErrorF("[%s] %s prox=%s\tx=%d\ty=%d\tz=%d\tbutton=%s\tbuttons=%d\n",
+ is_stylus ? "stylus" : "cursor",
+ is_absolute ? "abs" : "rel",
+ is_proximity ? "true" : "false",
+ x, y, z,
+ is_button ? "true" : "false", buttons));
+
+ /* Hardware filtering isn't working on Graphire so we do it here.
+ */
+ if ((common->wcmFlags & GRAPHIRE_FLAG) &&
+ ((is_proximity && priv->oldProximity) ||
+ ((is_proximity == 0) && (priv->oldProximity == 0))) &&
+ (buttons == priv->oldButtons) &&
+ (ABS(x - priv->oldX) <= common->wcmSuppress) &&
+ (ABS(y - priv->oldY) <= common->wcmSuppress) &&
+ (ABS(z - priv->oldZ) < 3) &&
+ (ABS(tx - priv->oldTiltX) < 3) &&
+ (ABS(ty - priv->oldTiltY) < 3)) {
+
+ DBG(10, ErrorF("Graphire filtered\n"));
+
+ return;
+ }
+
+ /* sets rx and ry according to the mode */
+ if (is_absolute) {
+ rx = x;
+ ry = y;
+ rz = z;
+ rtx = tx;
+ rty = ty;
+ rwheel = wheel;
+ } else {
+ rx = x - priv->oldX;
+ ry = y - priv->oldY;
+ rz = z - priv->oldZ;
+ rtx = tx - priv->oldTiltX;
+ rty = ty - priv->oldTiltY;
+ rwheel = wheel - priv->oldWheel;
+ }
+
+ /* coordinates are ready we can send events */
+ if (is_proximity) {
+
+ if (!priv->oldProximity) {
+ xf86PostProximityEvent(local->dev, 1, 0, 6, rx, ry, z, tx, ty, rwheel);
+
+ priv->flags |= FIRST_TOUCH_FLAG;
+ DBG(4, ErrorF("xf86WcmSendEvents FIRST_TOUCH_FLAG set\n"));
+
+ if (common->wcmProtocolLevel == 4) {
+ /* handle the two sides switches in the stylus */
+ if (is_stylus && (buttons == 4)) {
+ priv->oldProximity = ERASER_PROX;
+ }
+ else {
+ priv->oldProximity = OTHER_PROX;
+ }
+ }
+ else {
+ priv->oldProximity = OTHER_PROX;
+ }
+ }
+
+ if (common->wcmProtocolLevel == 4 &&
+ !(common->wcmFlags & GRAPHIRE_FLAG)) {
+ /* The stylus reports button 4 for the second side
+ * switch and button 4/5 for the eraser tip. We know
+ * how to choose when we come in proximity for the
+ * first time. If we are in proximity and button 4 then
+ * we have the eraser else we have the second side
+ * switch.
+ */
+ if (is_stylus) {
+ if (buttons == 4) {
+ buttons = (priv->oldProximity == ERASER_PROX) ? 0 : 3;
+ }
+ else {
+ if (priv->oldProximity == ERASER_PROX && buttons == 5) {
+ buttons = ((DEVICE_ID(priv->flags) == ERASER_ID) ? 1 : 4);
+ }
+ }
+ }
+ else {
+ /* If the button flag is pressed, but the switch state
+ * is zero, this means that cursor button 16 was pressed
+ */
+ if (is_button && buttons == 0) {
+ buttons = 16;
+ }
+ }
+ }
+ DBG(4, ErrorF("xf86WcmSendEvents %s rx=%d ry=%d rz=%d buttons=%d\n",
+ is_stylus ? "stylus" : "cursor", rx, ry, rz, buttons));
+
+ /* Turn button index reported into a bit mask for WACOM IV.
+ * The WACOM V and Graphire models already report buttons
+ * as a bit mask.
+ */
+ if (common->wcmProtocolLevel == 4 &&
+ !(common->wcmFlags & GRAPHIRE_FLAG)) {
+ buttons = 1 << (buttons - 1);
+ }
+
+ if ((priv->oldX != x) ||
+ (priv->oldY != y) ||
+ (priv->oldZ != z) ||
+ (is_stylus && HANDLE_TILT(common) &&
+ (tx != priv->oldTiltX || ty != priv->oldTiltY))) {
+ if (!is_absolute && (priv->flags & FIRST_TOUCH_FLAG)) {
+ priv->flags -= FIRST_TOUCH_FLAG;
+ DBG(4, ErrorF("xf86WcmSendEvents FIRST_TOUCH_FLAG unset\n"));
+ } else {
+ xf86PostMotionEvent(local->dev, is_absolute, 0, 6, rx, ry, rz,
+ rtx, rty, rwheel);
+ }
+ }
+
+ if (priv->oldButtons != buttons) {
+ xf86WcmSendButtons (local, buttons, rx, ry, rz, rtx, rty, rwheel);
+ }
+
+ /* Simulate buttons 4 and 5 for Graphire wheel */
+ if ((((common->wcmProtocolLevel == 4) && (common->wcmFlags & GRAPHIRE_FLAG) && (wheel != 0)) ||
+ ((common->wcmOpen == xf86WcmUSBOpen) && (wheel != priv->oldWheel))) &&
+ !is_stylus) {
+ int fake_button;
+
+ if (common->wcmOpen == xf86WcmUSBOpen) {
+ fake_button = (wheel > priv->oldWheel) ? 5 : 4;
+ } else{
+ fake_button = (wheel > 0) ? 5 : 4;
+ }
+
+ xf86PostButtonEvent(local->dev,
+ (priv->flags & ABSOLUTE_FLAG),
+ fake_button, 1,
+ 0, 6, rx, ry, rz, rtx, rty, rwheel);
+
+ xf86PostButtonEvent(local->dev,
+ (priv->flags & ABSOLUTE_FLAG),
+ fake_button, 0,
+ 0, 6, rx, ry, rz, rtx, rty, rwheel);
+ }
+
+ priv->oldButtons = buttons;
+ priv->oldX = x;
+ priv->oldY = y;
+ priv->oldZ = z;
+ priv->oldTiltX = tx;
+ priv->oldTiltY = ty;
+ priv->oldWheel = wheel;
+ }
+ else { /* !PROXIMITY */
+ /* reports button up when the device has been down and becomes out of proximity */
+ if (priv->oldButtons) {
+ xf86WcmSendButtons (local, 0, rx, ry, rz, rtx, rty, rwheel);
+ priv->oldButtons = 0;
+ }
+ if (!is_core_pointer) {
+ /* macro button management */
+ if (common->wcmProtocolLevel == 4 && buttons) {
+ int macro = z / 2;
+
+ DBG(6, ErrorF("macro=%d buttons=%d wacom_map[%d]=%x\n",
+ macro, buttons, macro, wacom_map[macro]));
+
+ /* First available Keycode begins at 8 => macro+7 */
+ xf86PostKeyEvent(local->dev, macro+7, 1,
+ is_absolute, 0, 6,
+ 0, 0, buttons, rtx, rty, rwheel);
+ xf86PostKeyEvent(local->dev, macro+7, 0,
+ is_absolute, 0, 6,
+ 0, 0, buttons, rtx, rty, rwheel);
+ }
+ if (priv->oldProximity) {
+ xf86PostProximityEvent(local->dev, 0, 0, 6, rx, ry, rz,
+ rtx, rty, rwheel);
+ }
+ }
+ priv->oldProximity = 0;
+ }
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmSuppress --
+ * Determine whether device state has changed enough - return 1
+ * if not.
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmSuppress(int suppress,
+ WacomDeviceState *ds1,
+ WacomDeviceState *ds2)
+{
+ if (ds1->buttons != ds2->buttons) return 0;
+ if (ds1->proximity != ds2->proximity) return 0;
+ if (ABS(ds1->x - ds2->x) >= suppress) return 0;
+ if (ABS(ds1->y - ds2->y) >= suppress) return 0;
+ if (ABS(ds1->pressure - ds2->pressure) >= suppress) return 0;
+ if ((1800 + ds1->rotation - ds2->rotation) % 1800 >= suppress &&
+ (1800 + ds2->rotation - ds1->rotation) % 1800 >= suppress) return 0;
+ if (ABS(ds1->wheel - ds2->wheel) >= suppress) return 0;
+ return 1;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmIntuosFilter --
+ * Correct some hardware defects we've been seeing in Intuos pads,
+ * but also cuts down quite a bit on jitter.
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmIntuosFilter(WacomFilterState *state,
+ int coord,
+ int tilt)
+{
+ int tilt_filtered;
+ int ts;
+ int x0_pred;
+ int x0_pred1;
+ int x0, x1, x2, x3;
+ int x;
+
+ tilt_filtered = tilt + state->tilt[1] + state->tilt[2] + state->tilt[3];
+ state->tilt[2] = state->tilt[1];
+ state->tilt[1] = state->tilt[0];
+ state->tilt[0] = tilt;
+
+ x0 = coord;
+ x1 = state->coord[0];
+ x2 = state->coord[1];
+ x3 = state->coord[2];
+ state->coord[0] = x0;
+ state->coord[1] = x1;
+ state->coord[2] = x2;
+
+ ts = tilt_filtered >= 0 ? 1 : -1;
+
+ if (state->state == 0 || state->state == 3) {
+ x0_pred = 2 * x1 - x2;
+ x0_pred1 = 3 * x2 - 2 * x3;
+ if (ts * (x0 - x0_pred) > 12 &&
+ ts * (x0 - x0_pred1) > 12) {
+ /* detected a jump at x0 */
+ state->state = 1;
+ x = x1;
+ }
+ else if (state->state == 0) {
+ x = (7 * x0 + 14 * x1 + 15 * x2 - 4 * x3 + 16) >> 5;
+ }
+ else { /* state->state == 3 */
+ /* a jump at x3 was detected */
+ x = (x0 + 2 * x1 + x2 + 2) >> 2;
+ state->state = 0;
+ }
+ }
+ else if (state->state == 1) {
+ /* a jump at x1 was detected */
+ x = (3 * x0 + 7 * x2 - 2 * x3 + 4) >> 3;
+ state->state = 2;
+ }
+ else { /* state->state == 2 */
+ /* a jump at x2 was detected */
+ x = x1;
+ state->state = 3;
+ }
+
+ return x;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmReadInput --
+ * Read the new events from the device, and enqueue them.
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmReadInput(LocalDevicePtr local)
+{
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+ WacomCommonPtr common = priv->common;
+ int len, loop, idx;
+ int is_stylus = 1, is_button, is_proximity, wheel=0;
+ int is_absolute = (priv->flags & ABSOLUTE_FLAG);
+ int x, y, z, buttons, tx = 0, ty = 0;
+ unsigned char buffer[BUFFER_SIZE];
+ WacomDeviceState *ds;
+ WacomDeviceState old_ds;
+ int have_data;
+
+ DBG(7, ErrorF("xf86WcmReadInput BEGIN device=%s fd=%d\n",
+ common->wcmDevice, local->fd));
+
+ SYSCALL(len = read(local->fd, buffer, sizeof(buffer)));
+
+ if (len <= 0) {
+ ErrorF("Error reading wacom device : %s\n", strerror(errno));
+ return;
+ } else {
+ DBG(10, ErrorF("xf86WcmReadInput read %d bytes\n", len));
+ }
+
+ for(loop=0; loop<len; loop++) {
+
+ /* Format of 7 bytes data packet for Wacom Tablets
+ Byte 1
+ bit 7 Sync bit always 1
+ bit 6 Pointing device detected
+ bit 5 Cursor = 0 / Stylus = 1
+ bit 4 Reserved
+ bit 3 1 if a button on the pointing device has been pressed
+ bit 2 Reserved
+ bit 1 X15
+ bit 0 X14
+
+ Byte 2
+ bit 7 Always 0
+ bits 6-0 = X13 - X7
+
+ Byte 3
+ bit 7 Always 0
+ bits 6-0 = X6 - X0
+
+ Byte 4
+ bit 7 Always 0
+ bit 6 B3
+ bit 5 B2
+ bit 4 B1
+ bit 3 B0
+ bit 2 P0
+ bit 1 Y15
+ bit 0 Y14
+
+ Byte 5
+ bit 7 Always 0
+ bits 6-0 = Y13 - Y7
+
+ Byte 6
+ bit 7 Always 0
+ bits 6-0 = Y6 - Y0
+
+ Byte 7
+ bit 7 Always 0
+ bit 6 Sign of pressure data
+ bit 5 P6
+ bit 4 P5
+ bit 3 P4
+ bit 2 P3
+ bit 1 P2
+ bit 0 P1
+
+ byte 8 and 9 are optional and present only
+ in tilt mode.
+
+ Byte 8
+ bit 7 Always 0
+ bit 6 Sign of tilt X
+ bit 5 Xt6
+ bit 4 Xt5
+ bit 3 Xt4
+ bit 2 Xt3
+ bit 1 Xt2
+ bit 0 Xt1
+
+ Byte 9
+ bit 7 Always 0
+ bit 6 Sign of tilt Y
+ bit 5 Yt6
+ bit 4 Yt5
+ bit 3 Yt4
+ bit 2 Yt3
+ bit 1 Yt2
+ bit 0 Yt1
+
+ */
+
+ if ((common->wcmIndex == 0) && !(buffer[loop] & HEADER_BIT)) { /* magic bit is not OK */
+ DBG(6, ErrorF("xf86WcmReadInput bad magic number 0x%x (pktlength=%d) %d\n",
+ buffer[loop], common->wcmPktLength, loop));
+ continue;
+ }
+ else { /* magic bit at wrong place */
+ if ((common->wcmIndex != 0) && (buffer[loop] & HEADER_BIT)) {
+ DBG(6, ErrorF("xf86WcmReadInput magic number 0x%x detetected at index %d loop=%d\n",
+ (unsigned int) buffer[loop], common->wcmIndex, loop));
+ common->wcmIndex = 0;
+ }
+ }
+
+ common->wcmData[common->wcmIndex++] = buffer[loop];
+
+ if (common->wcmProtocolLevel == 4 &&
+ common->wcmIndex == common->wcmPktLength) {
+ int is_graphire = common->wcmFlags & GRAPHIRE_FLAG;
+
+ /* the packet is OK */
+
+ /* reset char count for next read */
+ common->wcmIndex = 0;
+
+ x = (((common->wcmData[0] & 0x3) << 14) +
+ (common->wcmData[1] << 7) +
+ common->wcmData[2]);
+ y = (((common->wcmData[3] & 0x3) << 14) +
+ (common->wcmData[4] << 7) +
+ common->wcmData[5]);
+
+ /* check which device we have */
+ is_stylus = (common->wcmData[0] & POINTER_BIT);
+
+ z = ((common->wcmData[6] & ZAXIS_BITS) * 2) +
+ ((common->wcmData[3] & ZAXIS_BIT) >> 2);
+
+ if (common->wcmMaxZ == 512) {
+ z = z*4 + ((common->wcmData[0] & ZAXIS_BIT) >> 1);
+
+ if (!(common->wcmData[6] & ZAXIS_SIGN_BIT)) {
+ z += 256;
+ }
+ DBG(10, ErrorF("graphire pressure(%c)=%d\n",
+ (common->wcmData[6] & ZAXIS_SIGN_BIT) ? '-' : '+', z));
+ }
+ else {
+ if (!(common->wcmData[6] & ZAXIS_SIGN_BIT)) {
+ z += (common->wcmMaxZ / 2);
+ }
+ }
+
+ is_proximity = (common->wcmData[0] & PROXIMITY_BIT);
+
+ if (is_graphire) {
+ if (is_stylus) {
+ buttons = ((common->wcmData[3] & 0x30) >> 3) |
+ (z >= common->wcmThreshold ? 1 : 0);
+ }
+ else {
+ buttons = (common->wcmData[3] & 0x38) >> 3;
+
+ wheel = (common->wcmData[6] & 0x30) >> 4;
+
+ if (common->wcmData[6] & 0x40) {
+ wheel = -wheel;
+ }
+ }
+ is_button = (buttons != 0);
+
+ DBG(10, ErrorF("graphire buttons=%d prox=%d wheel=%d\n", buttons, is_proximity, wheel));
+ }
+ else {
+ is_button = (common->wcmData[0] & BUTTON_FLAG);
+ buttons = (common->wcmData[3] & BUTTONS_BITS) >> 3;
+ }
+
+ /* The stylus reports button 4 for the second side
+ * switch and button 4/5 for the eraser tip. We know
+ * how to choose when we come in proximity for the
+ * first time. If we are in proximity and button 4 then
+ * we have the eraser else we have the second side
+ * switch.
+ */
+ if (is_stylus) {
+ if (!common->wcmStylusProximity && is_proximity) {
+ if (is_graphire) {
+ common->wcmStylusSide = !(common->wcmData[3] & 0x40);
+ }
+ else {
+ common->wcmStylusSide = (buttons != 4);
+ }
+ }
+ DBG(8, ErrorF("xf86WcmReadInput %s side\n",
+ common->wcmStylusSide ? "stylus" : "eraser"));
+ common->wcmStylusProximity = is_proximity;
+
+ /* handle tilt values only for stylus */
+ if (HANDLE_TILT(common)) {
+ tx = (common->wcmData[7] & TILT_BITS);
+ ty = (common->wcmData[8] & TILT_BITS);
+ if (common->wcmData[7] & TILT_SIGN_BIT)
+ tx -= (TILT_BITS + 1);
+ if (common->wcmData[8] & TILT_SIGN_BIT)
+ ty -= (TILT_BITS + 1);
+ }
+ }
+
+ for(idx=0; idx<common->wcmNumDevices; idx++) {
+ LocalDevicePtr local_dev = common->wcmDevices[idx];
+ WacomDevicePtr priv = (WacomDevicePtr) local_dev->private;
+ int temp_buttons = buttons;
+ int temp_is_proximity = is_proximity;
+ int curDevice;
+
+ DBG(7, ErrorF("xf86WcmReadInput trying to send to %s\n",
+ local_dev->name));
+
+ /* check for device type (STYLUS, ERASER or CURSOR) */
+
+ if (is_stylus) {
+ /*
+ * The eraser is reported as button 4 and 5 of the stylus.
+ * if we haven't an independent device for the eraser
+ * report the button as button 3 of the stylus.
+ */
+ if (is_proximity) {
+ if (is_graphire) {
+ if (common->wcmData[3] & 0x40) {
+ curDevice = ERASER_ID;
+ }
+ else {
+ curDevice = STYLUS_ID;
+ }
+ }
+ else {
+ if ((buttons & 4) && common->wcmHasEraser &&
+ ((!priv->oldProximity ||
+ (priv->oldProximity == ERASER_PROX)))) {
+ curDevice = ERASER_ID;
+ } else {
+ curDevice = STYLUS_ID;
+ }
+ }
+ } else {
+ /*
+ * When we are out of proximity with the eraser the
+ * button 4 isn't reported so we must check the
+ * previous proximity device.
+ */
+ if (common->wcmHasEraser && (priv->oldProximity == ERASER_PROX)) {
+ curDevice = ERASER_ID;
+ } else {
+ curDevice = STYLUS_ID;
+ }
+ }
+
+ /* We check here to see if we changed between eraser and stylus
+ * without leaving proximity. The most likely cause is that
+ * we were fooled by the second side switch into thinking the
+ * stylus was the eraser. If this happens, we send
+ * a proximity-out for the old device.
+ */
+ if ((DEVICE_ID(priv->flags) == STYLUS_ID ||
+ DEVICE_ID(priv->flags) == ERASER_ID) &&
+ curDevice != DEVICE_ID(priv->flags)) {
+ if (priv->oldProximity) {
+ curDevice = DEVICE_ID(priv->flags);
+ temp_buttons = 0;
+ temp_is_proximity = 0;
+ DBG(10, ErrorF("eraser and stylus mix\n"));
+ } else
+ continue;
+ }
+
+ DBG(10, ErrorF((DEVICE_ID(priv->flags) == ERASER_ID) ?
+ "Eraser\n" :
+ "Stylus\n"));
+ }
+ else {
+ if (DEVICE_ID(priv->flags) != CURSOR_ID)
+ continue;
+ DBG(10, ErrorF("Cursor\n"));
+ curDevice = CURSOR_ID;
+ }
+
+ xf86WcmSendEvents(common->wcmDevices[idx],
+ curDevice, 0,
+ is_stylus,
+ is_button,
+ temp_is_proximity,
+ x, y, z, temp_buttons,
+ tx, ty, wheel);
+ }
+ } /* protocol 4 */
+ else if (common->wcmProtocolLevel == 5 &&
+ common->wcmIndex == common->wcmPktLength) {
+ /* the packet is OK */
+ int x, y;
+
+ /* reset count for read of next packet */
+ common->wcmIndex = 0;
+
+ ds = &common->wcmDevStat[common->wcmData[0] & 0x01];
+ old_ds = *ds;
+ have_data = 0;
+
+ DBG(7, ErrorF("packet header = 0x%x\n",
+ (unsigned int)common->wcmData[0]));
+
+ /* Device ID packet */
+ if ((common->wcmData[0] & 0xfc) == 0xc0) {
+ memset(ds, 0, sizeof(*ds));
+ ds->proximity = 1;
+ ds->device_id = (((common->wcmData[1] & 0x7f) << 5) |
+ ((common->wcmData[2] & 0x7c) >> 2));
+ ds->serial_num = (((common->wcmData[2] & 0x03) << 30) |
+ ((common->wcmData[3] & 0x7f) << 23) |
+ ((common->wcmData[4] & 0x7f) << 16) |
+ ((common->wcmData[5] & 0x7f) << 9) |
+ ((common->wcmData[6] & 0x7f) << 23) |
+ ((common->wcmData[7] & 0x60) >> 5));
+ if ((ds->device_id & 0xf06) != 0x802)
+ ds->discard_first = 1;
+
+ if (PEN(ds) || STROKING_PEN(ds) || INKING_PEN(ds) || AIRBRUSH(ds))
+ ds->device_type = STYLUS_ID;
+ else if (MOUSE_4D(ds) || LENS_CURSOR(ds))
+ ds->device_type = CURSOR_ID;
+ else
+ ds->device_type = ERASER_ID;
+
+ DBG(6, ErrorF("device_id=0x%x serial_num=%u type=%s\n",
+ ds->device_id, ds->serial_num,
+ (ds->device_type == STYLUS_ID) ? "stylus"
+ : (ds->device_type == CURSOR_ID) ? "cursor"
+ : "eraser"));
+ }
+ /* Out of proximity packet */
+ else if ((common->wcmData[0] & 0xfe) == 0x80) {
+ ds->proximity = 0;
+ have_data = 1;
+ }
+ /* General pen packet or eraser packet or airbrush first packet */
+ else if (((common->wcmData[0] & 0xb8) == 0xa0) ||
+ /* airbrush second packet */
+ ((common->wcmData[0] & 0xbe) == 0xb4)) {
+ is_stylus = 1;
+ ds->x = (((common->wcmData[1] & 0x7f) << 9) |
+ ((common->wcmData[2] & 0x7f) << 2) |
+ ((common->wcmData[3] & 0x60) >> 5));
+ ds->y = (((common->wcmData[3] & 0x1f) << 11) |
+ ((common->wcmData[4] & 0x7f) << 4) |
+ ((common->wcmData[5] & 0x78) >> 3));
+ if ((common->wcmData[0] & 0xb8) == 0xa0) {
+ ds->pressure = (((common->wcmData[5] & 0x07) << 7) |
+ (common->wcmData[6] & 0x7f));
+ ds->buttons = (((common->wcmData[0]) & 0x06) |
+ (ds->pressure >= common->wcmThreshold));
+ }
+ else {
+ ds->wheel = (((common->wcmData[5] & 0x07) << 7) |
+ (common->wcmData[6] & 0x7f));
+ }
+ ds->tiltx = (common->wcmData[7] & TILT_BITS);
+ ds->tilty = (common->wcmData[8] & TILT_BITS);
+ if (common->wcmData[7] & TILT_SIGN_BIT)
+ ds->tiltx -= (TILT_BITS + 1);
+ if (common->wcmData[8] & TILT_SIGN_BIT)
+ ds->tilty -= (TILT_BITS + 1);
+ ds->proximity = (common->wcmData[0] & PROXIMITY_BIT);
+ have_data = 1;
+ }
+ /* 4D mouse 1st packet or Lens cursor packet */
+ else if (((common->wcmData[0] & 0xbe) == 0xa8) ||
+ ((common->wcmData[0] & 0xbe) == 0xb0)) {
+ is_stylus = 0;
+ ds->x = (((common->wcmData[1] & 0x7f) << 9) |
+ ((common->wcmData[2] & 0x7f) << 2) |
+ ((common->wcmData[3] & 0x60) >> 5));
+ ds->y = (((common->wcmData[3] & 0x1f) << 11) |
+ ((common->wcmData[4] & 0x7f) << 4) |
+ ((common->wcmData[5] & 0x78) >> 3));
+ ds->tilty = 0;
+ ds->wheel = (((common->wcmData[5] & 0x07) << 7) |
+ (common->wcmData[6] & 0x7f));
+ if (common->wcmData[8] & 0x08) ds->wheel = -ds->wheel;
+ /* 4D mouse */
+ if (MOUSE_4D(ds)) {
+ ds->buttons = (((common->wcmData[8] & 0x70) >> 1) |
+ (common->wcmData[8] & 0x07));
+ have_data = !ds->discard_first;
+ }
+ /* Lens cursor */
+ else {
+ ds->buttons = common->wcmData[8];
+ have_data = 1;
+ }
+ ds->proximity = (common->wcmData[0] & PROXIMITY_BIT);
+ }
+ /* 4D mouse 2nd packet */
+ else if ((common->wcmData[0] & 0xbe) == 0xaa) {
+ is_stylus = 0;
+ ds->x = (((common->wcmData[1] & 0x7f) << 9) |
+ ((common->wcmData[2] & 0x7f) << 2) |
+ ((common->wcmData[3] & 0x60) >> 5));
+ ds->y = (((common->wcmData[3] & 0x1f) << 11) |
+ ((common->wcmData[4] & 0x7f) << 4) |
+ ((common->wcmData[5] & 0x78) >> 3));
+ ds->tilty = 0;
+ ds->rotation = (((common->wcmData[6] & 0x0f) << 7) |
+ (common->wcmData[7] & 0x7f));
+ ds->tiltx = ((900 - ((ds->rotation + 900) % 1800)) >> 1);
+ ds->proximity = (common->wcmData[0] & PROXIMITY_BIT);
+ have_data = 1;
+ ds->discard_first = 0;
+ }
+ else {
+ DBG(10, ErrorF("unknown wacom V packet 0x%x\n",
+ common->wcmData[0]));
+ }
+
+ /* Suppress data */
+ if (have_data &&
+ xf86WcmSuppress(common->wcmSuppress, &old_ds, ds)) {
+ DBG(10, ErrorF("Suppressing data according to filter\n"));
+ *ds = old_ds;
+ have_data = 0;
+ }
+
+ if (have_data) {
+ if (is_absolute) {
+ x = xf86WcmIntuosFilter (&ds->x_filter, ds->x, ds->tiltx);
+ y = xf86WcmIntuosFilter (&ds->y_filter, ds->y, ds->tilty);
+ }
+ else {
+ x = ds->x;
+ y = ds->y;
+ }
+ for(idx=0; idx<common->wcmNumDevices; idx++) {
+ DBG(7, ErrorF("xf86WcmReadInput trying to send to %s\n",
+ common->wcmDevices[idx]->name));
+
+ xf86WcmSendEvents(common->wcmDevices[idx],
+ ds->device_type, ds->serial_num,
+ is_stylus,
+ ds->buttons,
+ ds->proximity,
+ x, y,
+ ds->pressure,
+ ds->buttons,
+ ds->tiltx, ds->tilty,
+ ds->wheel);
+ }
+ }
+ } /* protocol 5 */
+ } /* next data */
+ DBG(7, ErrorF("xf86WcmReadInput END local=0x%x priv=0x%x index=%d\n",
+ local, priv, common->wcmIndex));
+}
+
+#ifdef LINUX_INPUT
+/*
+ ***************************************************************************
+ *
+ * xf86WcmIsUSBLine --
+ * Test if the attached device is a USB one.
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmIsUSBLine(int fd)
+{
+ int version;
+ int err;
+
+ SYSCALL(err = ioctl(fd, EVIOCGVERSION, &version));
+
+ if (!err) {
+ ErrorF("%s Wacom Kernel Input driver version is %d.%d.%d\n", XCONFIG_PROBED,
+ version >> 16, (version >> 8) & 0xff, version & 0xff);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int ThrottleToRate(int x)
+{
+ if (x<0) x=-x;
+
+ /* piece-wise exponential function */
+
+ if (x < 128) return 0; /* infinite */
+ if (x < 256) return 1000; /* 1 second */
+ if (x < 512) return 500; /* 0.5 seconds */
+ if (x < 768) return 250; /* 0.25 seconds */
+ if (x < 896) return 100; /* 0.1 seconds */
+ if (x < 960) return 50; /* 0.05 seconds */
+ if (x < 1024) return 25; /* 0.025 seconds */
+ return 0; /* infinite */
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmReadUSBInput --
+ * Read the new events from the device, and enqueue them.
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmReadUSBInput(LocalDevicePtr local)
+{
+ WacomDevicePtr priv = (WacomDevicePtr) local->private;
+ WacomCommonPtr common = priv->common;
+ int serial = common->wcmLastSerial;
+ int is_proximity = priv->oldProximity;
+ int x = priv->oldX;
+ int y = priv->oldY;
+ int pressure = priv->oldZ;
+ int buttons = priv->oldButtons;
+ int tilt_x = priv->oldTiltX;
+ int tilt_y = priv->oldTiltY;
+ int wheel = priv->oldWheel;
+ int sampleTime, ticks;
+
+ ssize_t len;
+ int idx, loop;
+ struct input_event * event, *readevent;
+ char eventbuf[sizeof(struct input_event) * MAX_EVENTS];
+#define MOD_BUTTONS(bit, value) \
+ { int _b=bit, _v=value; buttons = (((_v) != 0) ? (buttons | _b) : (buttons & ~ _b)); }
+
+ /* get the sample time */
+ sampleTime = GetTimeInMillis();
+
+ /* account for roll overs and initialization */
+ if ((priv->throttleStart > sampleTime) || (!priv->throttleStart))
+ {
+ priv->throttleStart = sampleTime;
+ priv->throttleLimit = -1;
+ }
+
+ SYSCALL(len = read(local->fd, eventbuf, sizeof(eventbuf)));
+
+ DBG(10, ErrorF("xf86WcmReadUSBInput read %d events\n", len/sizeof(struct input_event)));
+
+ if (len <= 0) {
+ ErrorF("Error reading wacom device : %s\n", strerror(errno));
+ return;
+ }
+
+ for (readevent=(struct input_event *)eventbuf;
+ readevent<(struct input_event *)(eventbuf+len); readevent++) {
+ /* sanity check */
+ if (common->wcmIndex >= MAX_USB_EVENTS) {
+ DBG(11, ErrorF("xf86WcmReadUSBInput resetting buffer index\n"));
+ common->wcmIndex = 0;
+ }
+
+ common->wcmEvent[common->wcmIndex++] = *readevent;
+
+ /* MSC_SERIAL is the event terminator */
+ if (!((readevent->type == EV_MSC && readevent->code == MSC_SERIAL) ||
+ (readevent->type == EV_ABS && readevent->code == ABS_MISC))) {
+ continue;
+ }
+
+ for(loop=0; loop<common->wcmIndex; loop++) {
+ event = common->wcmEvent + loop;
+ DBG(11, ErrorF("xf86WcmReadUSBInput event[%d]->type=%d code=%d value=%d\n",
+ loop, event->type, event->code, event->value));
+ switch (event->type) {
+ case EV_ABS:
+ switch (event->code) {
+ case ABS_X:
+ x = event->value;
+ break;
+
+ case ABS_Y:
+ y = event->value;
+ break;
+
+ case ABS_TILT_X:
+ case ABS_RZ:
+ tilt_x = event->value;
+ break;
+
+ case ABS_TILT_Y:
+ tilt_y = event->value;
+ break;
+
+ case ABS_PRESSURE:
+ pressure = event->value;
+ MOD_BUTTONS (1, event->value > common->wcmThreshold ? 1 : 0);
+ break;
+
+ case ABS_DISTANCE:
+ /* This is not sent by the driver */
+ /* JEJ - actually it is, but it's not very useful */
+ break;
+
+ case ABS_MISC:
+ serial = event->value;
+ DBG(10, ErrorF("wacom tool serial id=%d\n", serial));
+ break;
+
+ case ABS_WHEEL:
+ wheel = event->value;
+ break;
+
+ case ABS_THROTTLE:
+ priv->throttleValue = event->value;
+ ticks = ThrottleToRate(event->value);
+ priv->throttleLimit = ticks ? priv->throttleStart + ticks : -1;
+ break;
+ }
+ break; /* EV_ABS */
+
+ case EV_REL:
+ switch (event->code) {
+ case REL_WHEEL:
+ wheel += event->value;
+ break;
+ default:
+ ErrorF("wacom: relative event received (%d)!!!\n", event->code);
+ break;
+ }
+ break; /* EV_REL */
+
+ case EV_KEY:
+ switch (event->code) {
+ case BTN_TOOL_PEN:
+ case BTN_TOOL_PENCIL:
+ case BTN_TOOL_BRUSH:
+ case BTN_TOOL_AIRBRUSH:
+ DBG(10, ErrorF("USB Stylus detected %x\n", event->code));
+ common->wcmLastTool = STYLUS_ID;
+ is_proximity = (event->value != 0);
+ break;
+
+ case BTN_TOOL_RUBBER:
+ DBG(10, ErrorF("USB eraser detected %x\n", event->code));
+ common->wcmLastTool = ERASER_ID;
+ is_proximity = (event->value != 0);
+ break;
+
+ case BTN_TOOL_MOUSE:
+ case BTN_TOOL_LENS:
+ DBG(10, ErrorF("USB mouse detected %x\n", event->code));
+ common->wcmLastTool = CURSOR_ID;
+ is_proximity = (event->value != 0);
+ break;
+
+ case BTN_TOUCH:
+ /* we use the pressure to determine the button 1 */
+ break;
+
+ case BTN_STYLUS:
+ case BTN_MIDDLE:
+ MOD_BUTTONS (2, event->value);
+ break;
+
+ case BTN_STYLUS2:
+ case BTN_RIGHT:
+ MOD_BUTTONS (4, event->value);
+ break;
+
+ case BTN_LEFT:
+ MOD_BUTTONS (1, event->value);
+ break;
+
+ case BTN_SIDE:
+ MOD_BUTTONS (8, event->value);
+ break;
+
+ case BTN_EXTRA:
+ MOD_BUTTONS (16, event->value);
+ break;
+ }
+ break; /* EV_KEY */
+ case EV_MSC:
+ switch (event->code) {
+ case MSC_SERIAL:
+ serial = event->value;
+ DBG(10, ErrorF("wacom tool serial id=%d\n", serial));
+ break;
+ }
+ break; /* EV_MSC */
+ } /* switch event->type */
+
+ /* MSC_SERIAL is the event terminator */
+ if (!(event->type == EV_MSC && event->code == MSC_SERIAL) &&
+ !(event->type == EV_ABS && event->code == ABS_MISC)) {
+ continue;
+ }
+
+ /* handle throttle */
+ if ((priv->throttleLimit >= 0) && (priv->throttleLimit < sampleTime))
+ {
+ DBG(6, ErrorF("LIMIT REACHED: s=%d l=%d n=%d v=%d N=%d\n",
+ priv->throttleStart,
+ priv->throttleLimit,
+ sampleTime,
+ priv->throttleValue,
+ sampleTime + ThrottleToRate(priv->throttleValue)));
+
+ wheel += (priv->throttleValue > 0) ? 1 :
+ (priv->throttleValue < 0) ? -1 : 0;
+
+ priv->throttleStart = sampleTime;
+ priv->throttleLimit = sampleTime + ThrottleToRate(priv->throttleValue);
+ }
+
+ if ((is_proximity == priv->oldProximity) &&
+ (buttons == priv->oldButtons) &&
+ (wheel == priv->oldWheel) &&
+ (ABS(x - priv->oldX) <= common->wcmSuppress) &&
+ (ABS(y - priv->oldY) <= common->wcmSuppress) &&
+ (ABS(pressure - priv->oldZ) < 3) &&
+ (ABS(tilt_x - priv->oldTiltX) < 3) &&
+ (ABS(tilt_y - priv->oldTiltY) < 3)) {
+ DBG(10, ErrorF("filtered %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ x, priv->oldX,
+ y, priv->oldY,
+ pressure, priv->oldZ,
+ is_proximity, priv->oldProximity,
+ buttons, priv->oldButtons,
+ wheel, priv->oldWheel,
+ tilt_x, priv->oldTiltX,
+ tilt_y, priv->oldTiltY));
+ continue;
+ }
+
+ DBG(10, ErrorF("sending event %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ x, priv->oldX,
+ y, priv->oldY,
+ pressure, priv->oldZ,
+ is_proximity, priv->oldProximity,
+ buttons, priv->oldButtons,
+ wheel, priv->oldWheel,
+ tilt_x, priv->oldTiltX,
+ tilt_y, priv->oldTiltY));
+
+ for (idx=0; idx<common->wcmNumDevices; idx++) {
+ WacomDevicePtr dev = common->wcmDevices[idx]->private;
+ int id;
+
+ id = DEVICE_ID (dev->flags);
+
+ /* Find the device the current events are meant for */
+ if (id == common->wcmLastTool) {
+ DBG(11, ErrorF("tool id=%d for %s\n", id, local->name));
+
+ xf86WcmSendEvents(common->wcmDevices[idx],
+ common->wcmLastTool,
+ serial,
+ (common->wcmLastTool == STYLUS_ID || common->wcmLastTool == ERASER_ID),
+ !!(buttons),
+ is_proximity,
+ x, y, pressure, buttons,
+ tilt_x, tilt_y, wheel);
+ }
+ }
+ priv->oldX = x;
+ priv->oldY = y;
+ priv->oldZ = pressure;
+ priv->oldTiltX = tilt_x;
+ priv->oldTiltY = tilt_y;
+ priv->oldProximity = is_proximity;
+ priv->oldButtons = buttons;
+ priv->oldWheel = wheel;
+ common->wcmLastSerial = serial;
+ } /* next event */
+ common->wcmIndex=0;
+ } /* next event group */
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmUSBOpen --
+ *
+ ***************************************************************************
+ */
+
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define LONG(x) ((x)/BITS_PER_LONG)
+
+static Bool
+xf86WcmUSBOpen(LocalDevicePtr local)
+{
+ int err = 0;
+ WacomDevicePtr priv = (WacomDevicePtr)local->private;
+ WacomCommonPtr common = priv->common;
+ char name[256] = "Unknown";
+ int abs[5];
+ unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
+ int i, j;
+
+#ifdef XFREE86_V4
+ local->fd = xf86OpenSerial(local->options);
+#else
+ SYSCALL(local->fd = open(common->wcmDevice, O_RDONLY|O_NDELAY, 0));
+#endif
+ if (local->fd == -1) {
+ ErrorF("Error opening %s : %s\n", common->wcmDevice, strerror(errno));
+ return !Success;
+ }
+
+ ioctl(local->fd, EVIOCGNAME(sizeof(name)), name);
+ ErrorF("%s Wacom Kernel Input device name: \"%s\"\n", XCONFIG_PROBED, name);
+
+ memset(bit, 0, sizeof(bit));
+ ioctl(local->fd, EVIOCGBIT(0, EV_MAX), bit[0]);
+
+ for (i = 0; i < EV_MAX; i++)
+ if (test_bit(i, bit[0])) {
+ ioctl(local->fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
+ for (j = 0; j < KEY_MAX; j++)
+ if (test_bit(j, bit[i])) {
+ if (i == EV_ABS) {
+ ioctl(local->fd, EVIOCGABS(j), abs);
+ switch (j) {
+ case ABS_X:
+ if (common->wcmMaxX == 0) {
+ common->wcmMaxX = abs[2];
+ }
+ break;
+
+ case ABS_Y:
+ if (common->wcmMaxY == 0) {
+ common->wcmMaxY = abs[2];
+ }
+ break;
+
+ case ABS_PRESSURE:
+ if (common->wcmMaxZ == DEFAULT_MAXZ) {
+ common->wcmMaxZ = abs[2];
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ DBG(2, ErrorF("setup is max X=%d(%d) Y=%d(%d) Z=%d(%d)\n",
+ common->wcmMaxX, common->wcmResolX,
+ common->wcmMaxY, common->wcmResolY,
+ common->wcmMaxZ, common->wcmResolZ));
+
+ /* send the tilt mode command after setup because it must be enabled */
+ /* after multi-mode to take precedence */
+ if (HANDLE_TILT(common)) {
+ /* Unfortunately, the USB driver doesn't allow to send this
+ * command to the tablet. Any other solutions ? */
+ DBG(2, ErrorF("Sending tilt mode order\n"));
+ }
+
+ if (common->wcmSuppress < 0) {
+ int xratio = common->wcmMaxX/screenInfo.screens[0]->width;
+ int yratio = common->wcmMaxY/screenInfo.screens[0]->height;
+
+ common->wcmSuppress = (xratio > yratio) ? yratio : xratio;
+ }
+
+ if (common->wcmSuppress > 100) {
+ common->wcmSuppress = 99;
+ }
+ /* Cannot send WC_SUPPRESS to the table. Will have to do
+ * this manually. */
+
+ priv->topX = 0;
+ priv->bottomX = common->wcmMaxX;
+ priv->topY = 0;
+ priv->bottomY = common->wcmMaxY;
+
+ if (xf86Verbose)
+ ErrorF("%s Wacom tablet maximum X=%d maximum Y=%d "
+ "X resolution=%d Y resolution=%d suppress=%d%s\n",
+ XCONFIG_PROBED, common->wcmMaxX, common->wcmMaxY,
+ common->wcmResolX, common->wcmResolY, common->wcmSuppress,
+ HANDLE_TILT(common) ? " Tilt" : "");
+
+ if (err < 0) {
+ ErrorF("ERROR: %d\n", err);
+ SYSCALL(close(local->fd));
+ return !Success;
+ }
+
+ /* to have the button field handled as a bit field */
+ common->wcmProtocolLevel = 5;
+
+ return Success;
+}
+
+#endif /* LINUX_INPUT */
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmControlProc --
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmControlProc(DeviceIntPtr device,
+ PtrCtrl *ctrl)
+{
+ DBG(2, ErrorF("xf86WcmControlProc\n"));
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmOpen --
+ *
+ ***************************************************************************
+ */
+#ifdef XFREE86_V4
+#define WAIT(t) \
+ err = xf86WaitForInput(-1, ((t) * 1000)); \
+ if (err == -1) { \
+ ErrorF("Wacom select error : %s\n", strerror(errno)); \
+ return !Success; \
+ }
+#else
+#define WAIT(t) \
+ timeout.tv_sec = 0; \
+ timeout.tv_usec = (t) * 1000; \
+ SYSCALL(err = select(0, NULL, NULL, NULL, &timeout)); \
+ if (err == -1) { \
+ ErrorF("Wacom select error : %s\n", strerror(errno)); \
+ return !Success; \
+ }
+#endif
+
+static Bool
+xf86WcmOpen(LocalDevicePtr local)
+{
+#ifndef XFREE86_V4
+ struct timeval timeout;
+#endif
+ char buffer[256];
+ char header[64]; /* This is a small buffer for discarding the unwanted header */
+ int err;
+ WacomDevicePtr priv = (WacomDevicePtr)local->private;
+ WacomCommonPtr common = priv->common;
+ int a, b;
+ int loop, idx;
+ float version = 0.0;
+ int is_a_penpartner = 0;
+
+ DBG(1, ErrorF("opening %s\n", common->wcmDevice));
+
+#ifdef XFREE86_V4
+ local->fd = xf86OpenSerial(local->options);
+#else
+ SYSCALL(local->fd = open(common->wcmDevice, O_RDWR|O_NDELAY, 0));
+#endif
+ if (local->fd < 0) {
+ ErrorF("Error opening %s : %s\n", common->wcmDevice, strerror(errno));
+ return !Success;
+ }
+
+#ifdef LINUX_INPUT
+ DBG(1, ErrorF("testing USB\n"));
+
+ if (xf86WcmIsUSBLine(local->fd)) {
+ int loop;
+
+ SYSCALL(close(local->fd));
+
+ for(loop=0; loop<common->wcmNumDevices; loop++) {
+ common->wcmDevices[loop]->read_input=xf86WcmReadUSBInput;
+ }
+ common->wcmOpen=xf86WcmUSBOpen;
+
+ return xf86WcmUSBOpen(local);
+ }
+#endif
+
+ DBG(1, ErrorF("initializing tablet\n"));
+
+ /* Set the speed of the serial link to 38400 */
+#ifdef XFREE86_V4
+ if (xf86SetSerialSpeed(local->fd, 38400) < 0) {
+ return !Success;
+ }
+#else
+ if (set_serial_speed(local->fd, B38400) == !Success)
+ return !Success;
+#endif
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET_BAUD, strlen(WC_RESET_BAUD)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 250 mSecs */
+ WAIT(250);
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET, strlen(WC_RESET)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 75 mSecs */
+ WAIT(75);
+
+ /* Set the speed of the serial link to 19200 */
+#ifdef XFREE86_V4
+ if (xf86SetSerialSpeed(local->fd, 19200) < 0) {
+ return !Success;
+ }
+#else
+ if (set_serial_speed(local->fd, B19200) == !Success)
+ return !Success;
+#endif
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET_BAUD, strlen(WC_RESET_BAUD)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 250 mSecs */
+ WAIT(250);
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET, strlen(WC_RESET)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 75 mSecs */
+ WAIT(75);
+
+ /* Set the speed of the serial link to 9600 */
+#ifdef XFREE86_V4
+ if (xf86SetSerialSpeed(local->fd, 9600) < 0) {
+ return !Success;
+ }
+#else
+ if (set_serial_speed(local->fd, B9600) == !Success)
+ return !Success;
+#endif
+
+ /* Send reset to the tablet */
+ SYSCALL(err = write(local->fd, WC_RESET_BAUD, strlen(WC_RESET_BAUD)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 250 mSecs */
+ WAIT(250);
+
+ SYSCALL(err = write(local->fd, WC_STOP, strlen(WC_STOP)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 30 mSecs */
+ WAIT(30);
+
+#ifdef XFREE86_V4
+ xf86FlushInput(local->fd);
+#else
+ flush_input_fd(local->fd);
+#endif
+
+ DBG(2, ErrorF("reading model\n"));
+ if (!send_request(local->fd, WC_MODEL, buffer)) {
+ return !Success;
+ }
+ DBG(2, ErrorF("%s\n", buffer));
+
+ if (xf86Verbose) {
+ ErrorF("%s Wacom tablet model : %s\n", XCONFIG_PROBED, buffer+2);
+ }
+
+ /* Answer is in the form ~#Tablet-Model VRom_Version */
+ /* look for the first V from the end of the string */
+ /* this seems to be the better way to find the version of the ROM */
+ for(loop=strlen(buffer); loop>=0 && *(buffer+loop) != 'V'; loop--);
+ for(idx=loop; idx<strlen(buffer) && *(buffer+idx) != '-'; idx++);
+ *(buffer+idx) = '\0';
+
+ /* Extract version numbers */
+ sscanf(buffer+loop+1, "%f", &version);
+
+ if ((buffer[2] == 'G' && buffer[3] == 'D') ||
+ (buffer[2] == 'X' && buffer[3] == 'D')) {
+ DBG(2, ErrorF("detected an Intuos model\n"));
+ common->wcmProtocolLevel = 5;
+ common->wcmMaxZ = 1023; /* max Z value */
+ common->wcmResolX = 2540; /* X resolution in points/inch */
+ common->wcmResolY = 2540; /* Y resolution in points/inch */
+ common->wcmResolZ = 2540; /* Z resolution in points/inch */
+ common->wcmPktLength = 9; /* length of a packet */
+ if (common->wcmThreshold == INVALID_THRESHOLD) {
+ common->wcmThreshold = -480; /* Threshold for counting pressure as a button */
+ if (xf86Verbose) {
+ ErrorF("%s Wacom using pressure threshold of %d for button 1\n",
+ XCONFIG_PROBED, common->wcmThreshold);
+ }
+ }
+ }
+
+ /* Tilt works on ROM 1.4 and above */
+ DBG(2, ErrorF("wacom flags=%d ROM version=%f buffer=%s\n",
+ common->wcmFlags, version, buffer+loop+1));
+ if (common->wcmProtocolLevel == 4 &&
+ (common->wcmFlags & TILT_FLAG) && (version >= (float)1.4)) {
+ common->wcmPktLength = 9;
+ }
+
+ /* Check for a PenPartner or Graphire model which doesn't answer WC_CONFIG
+ * request. The Graphire model is handled like a PenPartner except that
+ * it doesn't answer WC_COORD requests.
+ */
+ if ((buffer[2] == 'C' || buffer[2] == 'E') && buffer[3] == 'T') {
+ if (buffer[2] == 'E') {
+ DBG(2, ErrorF("detected a Graphire model\n"));
+ common->wcmFlags |= GRAPHIRE_FLAG;
+ /* Graphire models don't answer WC_COORD requests */
+ common->wcmMaxX = 5103;
+ common->wcmMaxY = 3711;
+ common->wcmMaxZ = 512;
+ }
+ else {
+ DBG(2, ErrorF("detected a PenPartner model\n"));
+ common->wcmMaxZ = 256;
+ }
+ common->wcmResolX = 1000;
+ common->wcmResolY = 1000;
+ is_a_penpartner = 1;
+ }
+ else if (common->wcmProtocolLevel == 4 && !(common->wcmResolX && common->wcmResolY)) {
+ DBG(2, ErrorF("reading config\n"));
+ if (send_request(local->fd, WC_CONFIG, buffer)) {
+ DBG(2, ErrorF("%s\n", buffer));
+ /* The header string is simply a place to put the unwanted
+ * config header don't use buffer+xx because the header size
+ * varies on different tablets
+ */
+ if (sscanf(buffer, "%[^,],%d,%d,%d,%d", header, &a, &b, &common->wcmResolX, &common->wcmResolY) == 5) {
+ DBG(6, ErrorF("WC_CONFIG Header = %s\n", header));
+ }
+ else {
+ ErrorF("WACOM: unable to parse resolution. Using default.\n");
+ common->wcmResolX = common->wcmResolY = 1270;
+ }
+ }
+ else {
+ ErrorF("WACOM: unable to read resolution. Using default.\n");
+ common->wcmResolX = common->wcmResolY = 1270;
+ }
+ }
+
+ if (!(common->wcmFlags & GRAPHIRE_FLAG) && !(common->wcmMaxX && common->wcmMaxY)) {
+ DBG(2, ErrorF("reading max coordinates\n"));
+ if (!send_request(local->fd, WC_COORD, buffer)) {
+ ErrorF("WACOM: unable to read max coordinates. Use the MaxX and MaxY options.\n");
+ return !Success;
+ }
+ DBG(2, ErrorF("%s\n", buffer));
+ if (sscanf(buffer+2, "%d,%d", &common->wcmMaxX, &common->wcmMaxY) != 2) {
+ ErrorF("WACOM: unable to parse max coordinates. Use the MaxX and MaxY options.\n");
+ return !Success;
+ }
+ }
+
+ DBG(2, ErrorF("setup is max X=%d max Y=%d resol X=%d resol Y=%d\n",
+ common->wcmMaxX, common->wcmMaxY, common->wcmResolX,
+ common->wcmResolY));
+
+ /* We can't change the resolution on PenPartner and Graphire models */
+ if (!is_a_penpartner && common->wcmProtocolLevel == 4) {
+ int resolX = common->wcmResolX, resolY = common->wcmResolY;
+
+ /* Force the resolution.
+ */
+ if (((float)version) >= 1.2) {
+ resolX = resolY = 2540;
+ }
+ sprintf(buffer, "%s%d\r", WC_NEW_RESOLUTION, resolX);
+ SYSCALL(err = write(local->fd, buffer, strlen(buffer)));
+
+ /* Verify the resolution change.
+ */
+ DBG(2, ErrorF("rereading config\n"));
+ if (send_request(local->fd, WC_CONFIG, buffer)) {
+ DBG(2, ErrorF("%s\n", buffer));
+ /* The header string is simply a place to put the unwanted
+ * config header don't use buffer+xx because the header size
+ * varies on different tablets
+ */
+ if (sscanf(buffer, "%[^,],%d,%d,%d,%d", header, &a, &b, &common->wcmResolX, &common->wcmResolY) == 5) {
+ DBG(6, ErrorF("WC_CONFIG Header = %s\n", header));
+ }
+ else {
+ ErrorF("WACOM: unable to reparse resolution. Using previous values.\n");
+ }
+ }
+ else {
+ ErrorF("WACOM: unable to reread resolution. Using previous values.\n");
+ }
+
+ /* The following couple of lines convert the MaxX and MaxY returned by
+ * the Wacom from 1270lpi to the Wacom's active resolution.
+ */
+ common->wcmMaxX = (common->wcmMaxX / MAX_COORD_RES) * common->wcmResolX;
+ common->wcmMaxY = (common->wcmMaxY / MAX_COORD_RES) * common->wcmResolY;
+ }
+
+ DBG(2, ErrorF("setup is max X=%d max Y=%d resol X=%d resol Y=%d\n",
+ common->wcmMaxX, common->wcmMaxY, common->wcmResolX,
+ common->wcmResolY));
+
+ /* Send a setup string to the tablet */
+ if (is_a_penpartner) {
+ SYSCALL(err = write(local->fd, penpartner_setup_string,
+ strlen(penpartner_setup_string)));
+ }
+ else if (common->wcmProtocolLevel == 4) {
+ SYSCALL(err = write(local->fd, WC_RESET, strlen(WC_RESET)));
+ WAIT(75);
+ SYSCALL(err = write(local->fd, setup_string, strlen(setup_string)));
+ }
+ else {
+ SYSCALL(err = write(local->fd, intuos_setup_string,
+ strlen(intuos_setup_string)));
+ }
+
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Send the tilt mode command after setup because it must be enabled */
+ /* after multi-mode to take precedence */
+ if (common->wcmProtocolLevel == 4 && HANDLE_TILT(common)) {
+ DBG(2, ErrorF("Sending tilt mode order\n"));
+
+ SYSCALL(err = write(local->fd, WC_TILT_MODE, strlen(WC_TILT_MODE)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+ }
+
+ if (common->wcmSuppress < 0) {
+ int xratio = common->wcmMaxX/screenInfo.screens[0]->width;
+ int yratio = common->wcmMaxY/screenInfo.screens[0]->height;
+
+ common->wcmSuppress = (xratio > yratio) ? yratio : xratio;
+ }
+
+ if (common->wcmSuppress > 100) {
+ common->wcmSuppress = 99;
+ }
+
+ if (common->wcmProtocolLevel == 4) {
+ char buf[20];
+
+ sprintf(buf, "%s%d\r", WC_SUPPRESS, common->wcmSuppress);
+ SYSCALL(err = write(local->fd, buf, strlen(buf)));
+
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+ }
+
+ if (xf86Verbose)
+ ErrorF("%s Wacom %s tablet maximum X=%d maximum Y=%d "
+ "X resolution=%d Y resolution=%d suppress=%d%s\n",
+ XCONFIG_PROBED, common->wcmProtocolLevel == 4 ? "IV" : "V",
+ common->wcmMaxX, common->wcmMaxY,
+ common->wcmResolX, common->wcmResolY, common->wcmSuppress,
+ HANDLE_TILT(common) ? " Tilt" : "");
+
+ if (err <= 0) {
+ SYSCALL(close(local->fd));
+ return !Success;
+ }
+
+ /* change the serial speed if requested */
+ if (common->wcmLinkSpeed > 9600) {
+ if (common->wcmProtocolLevel == 5) {
+ char *speed_init_string = WC_V_19200;
+#ifndef XFREE86_V4
+ int speed = B19200;
+#endif
+ DBG(1, ErrorF("Switching serial link to %d\n", common->wcmLinkSpeed));
+
+ if (common->wcmLinkSpeed == 38400 && version < 2.0) {
+ ErrorF("Wacom: 38400 speed not supported with this Intuos firmware (%f)\n", version);
+ ErrorF("Switching to 19200\n");
+ common->wcmLinkSpeed = 19200;
+ }
+
+ switch (common->wcmLinkSpeed) {
+ case 38400:
+ speed_init_string = WC_V_38400;
+#ifndef XFREE86_V4
+ speed = B38400;
+#endif
+ break;
+
+ case 19200:
+ speed_init_string = WC_V_19200;
+#ifndef XFREE86_V4
+ speed = B19200;
+#endif
+ break;
+ }
+ /* Switch the tablet to the requested speed */
+ SYSCALL(err = write(local->fd, speed_init_string, strlen(speed_init_string)));
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ /* Wait 75 mSecs */
+ WAIT(75);
+
+ /* Set the speed of the serial link to requested speed */
+#ifdef XFREE86_V4
+ if (xf86SetSerialSpeed(local->fd, common->wcmLinkSpeed) < 0) {
+ return !Success;
+ }
+#else
+ if (set_serial_speed(local->fd, speed) == !Success)
+ return !Success;
+#endif
+ }
+ else {
+ ErrorF("Changing the speed of a wacom IV device is not yet implemented\n");
+ }
+ }
+
+ /* Tell the tablet to start sending coordinates */
+ SYSCALL(err = write(local->fd, WC_START, strlen(WC_START)));
+
+ if (err == -1) {
+ ErrorF("Wacom write error : %s\n", strerror(errno));
+ return !Success;
+ }
+
+ return Success;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmOpenDevice --
+ * Open the physical device and init information structs.
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmOpenDevice(DeviceIntPtr pWcm)
+{
+ LocalDevicePtr local = (LocalDevicePtr)pWcm->public.devicePrivate;
+ WacomDevicePtr priv = (WacomDevicePtr)PRIVATE(pWcm);
+ WacomCommonPtr common = priv->common;
+ double screenRatio, tabletRatio;
+ int gap;
+ int loop;
+ int screen_idx = 0;
+
+ if (local->fd < 0) {
+ if (common->wcmInitNumber > 2 ||
+ priv->initNumber == common->wcmInitNumber) {
+ if (common->wcmOpen(local) != Success) {
+ if (local->fd >= 0) {
+ SYSCALL(close(local->fd));
+ }
+ local->fd = -1;
+ }
+ else {
+ /* report the file descriptor to all devices */
+ for(loop=0; loop<common->wcmNumDevices; loop++) {
+ common->wcmDevices[loop]->fd = local->fd;
+ }
+ }
+ common->wcmInitNumber++;
+ priv->initNumber = common->wcmInitNumber;
+ }
+ else {
+ priv->initNumber = common->wcmInitNumber;
+ }
+ }
+
+ if (local->fd != -1 &&
+ priv->factorX == 0.0) {
+
+ if (priv->bottomX == 0) priv->bottomX = common->wcmMaxX;
+
+ if (priv->bottomY == 0) priv->bottomY = common->wcmMaxY;
+
+ /* Verify Box validity */
+
+ if (priv->topX > common->wcmMaxX ||
+ priv->topX < 0) {
+ ErrorF("Wacom invalid TopX (%d) reseting to 0\n", priv->topX);
+ priv->topX = 0;
+ }
+
+ if (priv->topY > common->wcmMaxY ||
+ priv->topY < 0) {
+ ErrorF("Wacom invalid TopY (%d) reseting to 0\n", priv->topY);
+ priv->topY = 0;
+ }
+
+ if (priv->bottomX > common->wcmMaxX ||
+ priv->bottomX < priv->topX) {
+ ErrorF("Wacom invalid BottomX (%d) reseting to %d\n",
+ priv->bottomX, common->wcmMaxX);
+ priv->bottomX = common->wcmMaxX;
+ }
+
+ if (priv->bottomY > common->wcmMaxY ||
+ priv->bottomY < priv->topY) {
+ ErrorF("Wacom invalid BottomY (%d) reseting to %d\n",
+ priv->bottomY, common->wcmMaxY);
+ priv->bottomY = common->wcmMaxY;
+ }
+
+ if (priv->screen_no != -1 &&
+ (priv->screen_no >= screenInfo.numScreens ||
+ priv->screen_no < 0)) {
+ ErrorF("%s: invalid screen number %d, resetting to 0\n",
+ local->name, priv->screen_no);
+ priv->screen_no = 0;
+ }
+
+ /* Calculate the ratio according to KeepShape, TopX and TopY */
+
+ if (priv->screen_no != -1) {
+ screen_idx = priv->screen_no;
+ }
+
+ if (priv->flags & KEEP_SHAPE_FLAG) {
+ screenRatio = ((double) screenInfo.screens[screen_idx]->width)
+ / screenInfo.screens[screen_idx]->height;
+
+ tabletRatio = ((double) (common->wcmMaxX - priv->topX))
+ / (common->wcmMaxY - priv->topY);
+
+ DBG(2, ErrorF("screenRatio = %.3g, tabletRatio = %.3g\n",
+ screenRatio, tabletRatio));
+
+ if (screenRatio > tabletRatio) {
+ gap = common->wcmMaxY * (1 - tabletRatio/screenRatio);
+ priv->bottomX = common->wcmMaxX;
+ priv->bottomY = common->wcmMaxY - gap;
+ } else {
+ gap = common->wcmMaxX * (1 - screenRatio/tabletRatio);
+ priv->bottomX = common->wcmMaxX - gap;
+ priv->bottomY = common->wcmMaxY;
+ }
+ }
+ priv->factorX = ((double) screenInfo.screens[0]->width)
+ / (priv->bottomX - priv->topX);
+ priv->factorY = ((double) screenInfo.screens[0]->height)
+ / (priv->bottomY - priv->topY);
+
+ if (xf86Verbose)
+ ErrorF("%s Wacom tablet top X=%d top Y=%d "
+ "bottom X=%d bottom Y=%d\n",
+ XCONFIG_PROBED, priv->topX, priv->topY,
+ priv->bottomX, priv->bottomY);
+
+ DBG(2, ErrorF("X factor = %.3g, Y factor = %.3g\n",
+ priv->factorX, priv->factorY));
+ }
+
+ /* Check threshold correctness */
+ DBG(2, ErrorF("Threshold=%d\n", common->wcmThreshold));
+
+ if (common->wcmThreshold > common->wcmMaxZ ||
+ common->wcmThreshold < 0) {
+ if (((common->wcmProtocolLevel == 5) ||
+ (common->wcmFlags & GRAPHIRE_FLAG)) &&
+ xf86Verbose &&
+ common->wcmThreshold != INVALID_THRESHOLD)
+ ErrorF("%s Wacom invalid threshold %d. Reset to %d\n",
+ XCONFIG_PROBED, common->wcmThreshold, common->wcmMaxZ / 3);
+ common->wcmThreshold = common->wcmMaxZ / 3;
+ }
+ DBG(2, ErrorF("New threshold=%d\n", common->wcmThreshold));
+
+ /* Set the real values */
+ InitValuatorAxisStruct(pWcm,
+ 0,
+ 0, /* min val */
+ priv->bottomX - priv->topX, /* max val */
+ mils(common->wcmResolX), /* resolution */
+ 0, /* min_res */
+ mils(common->wcmResolX)); /* max_res */
+ InitValuatorAxisStruct(pWcm,
+ 1,
+ 0, /* min val */
+ priv->bottomY - priv->topY, /* max val */
+ mils(common->wcmResolY), /* resolution */
+ 0, /* min_res */
+ mils(common->wcmResolY)); /* max_res */
+ InitValuatorAxisStruct(pWcm,
+ 2,
+ 0, /* min val */
+ common->wcmMaxZ, /* max val */
+ mils(common->wcmResolZ), /* resolution */
+ 0, /* min_res */
+ mils(common->wcmResolZ)); /* max_res */
+ InitValuatorAxisStruct(pWcm,
+ 3,
+ -64, /* min val */
+ 63, /* max val */
+ 128, /* resolution ??? */
+ 0,
+ 128);
+ InitValuatorAxisStruct(pWcm,
+ 4,
+ -64, /* min val */
+ 63, /* max val */
+ 128, /* resolution ??? */
+ 0,
+ 128);
+ InitValuatorAxisStruct(pWcm,
+ 5,
+ 0, /* min val */
+ 1023, /* max val */
+ 128, /* resolution ??? */
+ 0,
+ 128);
+
+ return (local->fd != -1);
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmClose --
+ *
+ ***************************************************************************
+ */
+static void
+xf86WcmClose(LocalDevicePtr local)
+{
+ WacomDevicePtr priv = (WacomDevicePtr)local->private;
+ WacomCommonPtr common = priv->common;
+ int loop;
+ int num = 0;
+
+ for(loop=0; loop<common->wcmNumDevices; loop++) {
+ if (common->wcmDevices[loop]->fd >= 0) {
+ num++;
+ }
+ }
+ DBG(4, ErrorF("Wacom number of open devices = %d\n", num));
+
+ if (num == 1) {
+ SYSCALL(close(local->fd));
+ }
+
+ local->fd = -1;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmProc --
+ * Handle the initialization, etc. of a wacom
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmProc(DeviceIntPtr pWcm,
+ int what)
+{
+ CARD8 map[(32 << 4) + 1];
+ int nbaxes;
+ int nbbuttons;
+ int loop;
+ LocalDevicePtr local = (LocalDevicePtr)pWcm->public.devicePrivate;
+ WacomDevicePtr priv = (WacomDevicePtr)PRIVATE(pWcm);
+
+ DBG(2, ErrorF("BEGIN xf86WcmProc dev=0x%x priv=0x%x type=%s flags=%d what=%d\n",
+ pWcm, priv, (DEVICE_ID(priv->flags) == STYLUS_ID) ? "stylus" :
+ (DEVICE_ID(priv->flags) == CURSOR_ID) ? "cursor" : "eraser",
+ priv->flags, what));
+
+ switch (what)
+ {
+ case DEVICE_INIT:
+ DBG(1, ErrorF("xf86WcmProc pWcm=0x%x what=INIT\n", pWcm));
+
+ nbaxes = 6; /* X, Y, Pressure, Tilt-X, Tilt-Y, Wheel */
+
+ switch(DEVICE_ID(priv->flags)) {
+ case ERASER_ID:
+ nbbuttons = 1;
+ break;
+ case STYLUS_ID:
+ nbbuttons = 4;
+ break;
+ default:
+ nbbuttons = 16;
+ break;
+ }
+
+ for(loop=1; loop<=nbbuttons; loop++) map[loop] = loop;
+
+ if (InitButtonClassDeviceStruct(pWcm,
+ nbbuttons,
+ map) == FALSE) {
+ ErrorF("unable to allocate Button class device\n");
+ return !Success;
+ }
+
+ if (InitFocusClassDeviceStruct(pWcm) == FALSE) {
+ ErrorF("unable to init Focus class device\n");
+ return !Success;
+ }
+
+ if (InitPtrFeedbackClassDeviceStruct(pWcm,
+ xf86WcmControlProc) == FALSE) {
+ ErrorF("unable to init ptr feedback\n");
+ return !Success;
+ }
+
+ if (InitProximityClassDeviceStruct(pWcm) == FALSE) {
+ ErrorF("unable to init proximity class device\n");
+ return !Success;
+ }
+
+ if (InitKeyClassDeviceStruct(pWcm, &wacom_keysyms, NULL) == FALSE) {
+ ErrorF("unable to init key class device\n");
+ return !Success;
+ }
+
+ if (InitValuatorClassDeviceStruct(pWcm,
+ nbaxes,
+ xf86GetMotionEvents,
+ local->history_size,
+ ((priv->flags & ABSOLUTE_FLAG)
+ ? Absolute : Relative) |
+ OutOfProximity)
+ == FALSE) {
+ ErrorF("unable to allocate Valuator class device\n");
+ return !Success;
+ }
+ else {
+ /* allocate the motion history buffer if needed */
+ xf86MotionHistoryAllocate(local);
+#ifndef XFREE86_V4
+ AssignTypeAndName(pWcm, local->atom, local->name);
+#endif
+ }
+
+ /* open the device to gather informations */
+ xf86WcmOpenDevice(pWcm);
+
+ break;
+
+ case DEVICE_ON:
+ DBG(1, ErrorF("xf86WcmProc pWcm=0x%x what=ON\n", pWcm));
+
+ if ((local->fd < 0) && (!xf86WcmOpenDevice(pWcm))) {
+ return !Success;
+ }
+#ifdef XFREE86_V4
+ xf86AddEnabledDevice(local);
+#else
+ AddEnabledDevice(local->fd);
+#endif
+ pWcm->public.on = TRUE;
+ break;
+
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ DBG(1, ErrorF("xf86WcmProc pWcm=0x%x what=%s\n", pWcm,
+ (what == DEVICE_CLOSE) ? "CLOSE" : "OFF"));
+ if (local->fd >= 0) {
+#ifdef XFREE86_V4
+ xf86RemoveEnabledDevice(local);
+#else
+ RemoveEnabledDevice(local->fd);
+#endif
+ xf86WcmClose(local);
+ }
+ pWcm->public.on = FALSE;
+ break;
+
+ default:
+ ErrorF("wacom unsupported mode=%d\n", what);
+ return !Success;
+ break;
+ }
+ DBG(2, ErrorF("END xf86WcmProc Success what=%d dev=0x%x priv=0x%x\n",
+ what, pWcm, priv));
+ return Success;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmChangeControl --
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmChangeControl(LocalDevicePtr local,
+ xDeviceCtl *control)
+{
+ xDeviceResolutionCtl *res;
+ int *resolutions;
+ char str[10];
+
+ res = (xDeviceResolutionCtl *)control;
+
+ if ((control->control != DEVICE_RESOLUTION) ||
+ (res->num_valuators < 1))
+ return (BadMatch);
+
+ resolutions = (int *)(res +1);
+
+ DBG(3, ErrorF("xf86WcmChangeControl changing to %d (suppressing under)\n",
+ resolutions[0]));
+
+ sprintf(str, "SU%d\r", resolutions[0]);
+ SYSCALL(write(local->fd, str, strlen(str)));
+
+ return(Success);
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmSwitchMode --
+ *
+ ***************************************************************************
+ */
+static int
+xf86WcmSwitchMode(ClientPtr client,
+ DeviceIntPtr dev,
+ int mode)
+{
+ LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
+ WacomDevicePtr priv = (WacomDevicePtr)local->private;
+
+ DBG(3, ErrorF("xf86WcmSwitchMode dev=0x%x mode=%d\n", dev, mode));
+
+ if (mode == Absolute) {
+ priv->flags = priv->flags | ABSOLUTE_FLAG;
+ }
+ else {
+ if (mode == Relative) {
+ priv->flags = priv->flags & ~ABSOLUTE_FLAG;
+ }
+ else {
+ DBG(1, ErrorF("xf86WcmSwitchMode dev=0x%x invalid mode=%d\n", dev,
+ mode));
+ return BadMatch;
+ }
+ }
+ return Success;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmAllocate --
+ *
+ ***************************************************************************
+ */
+static LocalDevicePtr
+xf86WcmAllocate(char * name,
+ int flag)
+{
+ LocalDevicePtr local;
+ WacomDevicePtr priv;
+ WacomCommonPtr common;
+
+ priv = (WacomDevicePtr) xalloc(sizeof(WacomDeviceRec));
+ if (!priv)
+ return NULL;
+
+ common = (WacomCommonPtr) xalloc(sizeof(WacomCommonRec));
+ if (!common) {
+ xfree(priv);
+ return NULL;
+ }
+
+#ifdef XFREE86_V4
+ local = xf86AllocateInput(wcmDrv, 0);
+#else
+ local = (LocalDevicePtr) xalloc(sizeof(LocalDeviceRec));
+#endif
+ if (!local) {
+ xfree(priv);
+ xfree(common);
+ return NULL;
+ }
+
+ local->name = name;
+ local->flags = 0;
+#ifndef XFREE86_V4
+ local->device_config = xf86WcmConfig;
+#endif
+ local->device_control = xf86WcmProc;
+ local->read_input = xf86WcmReadInput;
+ local->control_proc = xf86WcmChangeControl;
+ local->close_proc = xf86WcmClose;
+ local->switch_mode = xf86WcmSwitchMode;
+ local->conversion_proc = xf86WcmConvert;
+ local->reverse_conversion_proc = xf86WcmReverseConvert;
+ local->fd = -1;
+ local->atom = 0;
+ local->dev = NULL;
+ local->private = priv;
+ local->private_flags = 0;
+ local->history_size = 0;
+ local->old_x = -1;
+ local->old_y = -1;
+
+ priv->flags = flag; /* various flags (device type, absolute, first touch...) */
+ priv->oldX = -1; /* previous X position */
+ priv->oldY = -1; /* previous Y position */
+ priv->oldZ = -1; /* previous pressure */
+ priv->oldTiltX = -1; /* previous tilt in x direction */
+ priv->oldTiltY = -1; /* previous tilt in y direction */
+ priv->oldButtons = 0; /* previous buttons state */
+ priv->oldProximity = 1; /* previous proximity */
+ priv->oldWheel = 0; /* previous wheel */
+ priv->topX = 0; /* X top */
+ priv->topY = 0; /* Y top */
+ priv->bottomX = 0; /* X bottom */
+ priv->bottomY = 0; /* Y bottom */
+ priv->factorX = 0.0; /* X factor */
+ priv->factorY = 0.0; /* Y factor */
+ priv->common = common; /* common info pointer */
+ priv->oldProximity = 0; /* previous proximity */
+ priv->serial = 0; /* serial number */
+ priv->initNumber = 0; /* magic number for the init phasis */
+ priv->screen_no = -1; /* associated screen */
+
+ /* JEJ - throttle sampling code */
+ priv->throttleValue = 0;
+ priv->throttleStart = 0;
+ priv->throttleLimit = -1;
+
+ common->wcmDevice = ""; /* device file name */
+ common->wcmSuppress = -1; /* transmit position if increment is superior */
+ common->wcmFlags = 0; /* various flags */
+ common->wcmDevices = (LocalDevicePtr*) xalloc(sizeof(LocalDevicePtr));
+ common->wcmDevices[0] = local;
+ common->wcmNumDevices = 1; /* number of devices */
+ common->wcmIndex = 0; /* number of bytes read */
+ common->wcmPktLength = 7; /* length of a packet */
+ common->wcmMaxX = 0; /* max X value */
+ common->wcmMaxY = 0; /* max Y value */
+ common->wcmMaxZ = DEFAULT_MAXZ; /* max Z value */
+ common->wcmResolX = 0; /* X resolution in points/inch */
+ common->wcmResolY = 0; /* Y resolution in points/inch */
+ common->wcmResolZ = 1270; /* Z resolution in points/inch */
+ common->wcmHasEraser = (flag & ERASER_ID) ? TRUE : FALSE; /* True if an eraser has been configured */
+ common->wcmStylusSide = TRUE; /* eraser or stylus ? */
+ common->wcmStylusProximity = FALSE; /* a stylus is in proximity ? */
+ common->wcmProtocolLevel = 4; /* protocol level */
+ common->wcmThreshold = INVALID_THRESHOLD; /* button 1 threshold for some tablet models */
+ common->wcmInitNumber = 0; /* magic number for the init phasis */
+ common->wcmLinkSpeed = 9600; /* serial link speed */
+ common->wcmOpen = xf86WcmOpen; /* function used to open the line (serial or USB) */
+ common->wcmLastSerial = 0; /* last device (used by the USB part) */
+ common->wcmLastTool = -1; /* last tool (used by the USB part) */
+ return local;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmAllocateStylus --
+ *
+ ***************************************************************************
+ */
+static LocalDevicePtr
+xf86WcmAllocateStylus()
+{
+ LocalDevicePtr local = xf86WcmAllocate(XI_STYLUS, STYLUS_ID);
+
+ if (local)
+ local->type_name = "Wacom Stylus";
+ return local;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmAllocateCursor --
+ *
+ ***************************************************************************
+ */
+static LocalDevicePtr
+xf86WcmAllocateCursor()
+{
+ LocalDevicePtr local = xf86WcmAllocate(XI_CURSOR, CURSOR_ID);
+
+ if (local)
+ local->type_name = "Wacom Cursor";
+ return local;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86WcmAllocateEraser --
+ *
+ ***************************************************************************
+ */
+static LocalDevicePtr
+xf86WcmAllocateEraser()
+{
+ LocalDevicePtr local = xf86WcmAllocate(XI_ERASER, ABSOLUTE_FLAG|ERASER_ID);
+
+ if (local)
+ local->type_name = "Wacom Eraser";
+ return local;
+}
+
+/*
+ ***************************************************************************
+ *
+ * Wacom Stylus device association --
+ *
+ ***************************************************************************
+ */
+DeviceAssocRec wacom_stylus_assoc =
+{
+ STYLUS_SECTION_NAME, /* config_section_name */
+ xf86WcmAllocateStylus /* device_allocate */
+};
+
+/*
+ ***************************************************************************
+ *
+ * Wacom Cursor device association --
+ *
+ ***************************************************************************
+ */
+DeviceAssocRec wacom_cursor_assoc =
+{
+ CURSOR_SECTION_NAME, /* config_section_name */
+ xf86WcmAllocateCursor /* device_allocate */
+};
+
+/*
+ ***************************************************************************
+ *
+ * Wacom Eraser device association --
+ *
+ ***************************************************************************
+ */
+DeviceAssocRec wacom_eraser_assoc =
+{
+ ERASER_SECTION_NAME, /* config_section_name */
+ xf86WcmAllocateEraser /* device_allocate */
+};
+
+#ifndef XFREE86_V4
+#ifdef DYNAMIC_MODULE
+/*
+ ***************************************************************************
+ *
+ * entry point of dynamic loading
+ *
+ ***************************************************************************
+ */
+int
+#ifndef DLSYM_BUG
+init_module(unsigned long server_version)
+#else
+init_xf86Wacom(unsigned long server_version)
+#endif
+{
+ xf86AddDeviceAssoc(&wacom_stylus_assoc);
+ xf86AddDeviceAssoc(&wacom_cursor_assoc);
+ xf86AddDeviceAssoc(&wacom_eraser_assoc);
+
+ if (server_version != XF86_VERSION_CURRENT) {
+ ErrorF("Warning: Wacom module compiled for version%s\n", XF86_VERSION);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#endif /* DYNAMIC_MODULE */
+
+#else /* XFREE86_V4 */
+
+#include "wcm-beta.h"
+
+/*
+ * xf86WcmUninit --
+ *
+ * called when the device is no longer needed.
+ */
+static void
+xf86WcmUninit(InputDriverPtr drv,
+ LocalDevicePtr local,
+ int flags)
+{
+ WacomDevicePtr priv;
+
+ priv = (WacomDevicePtr) local->private;
+
+ DBG(1, ErrorF("xf86WcmUninit\n"));
+
+ if (priv->flags & BETA_FLAG)
+ {
+ wcmBetaDeleteDevice(drv,local,flags);
+ return;
+ }
+
+ xf86WcmProc(local->dev, DEVICE_OFF);
+
+ xfree (priv);
+ xf86DeleteInput(local, 0);
+}
+
+/*
+ * xf86WcmInit --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static InputInfoPtr
+xf86WcmInit(InputDriverPtr drv,
+ IDevPtr dev,
+ int flags)
+{
+ LocalDevicePtr local = NULL;
+ LocalDevicePtr fakeLocal = NULL;
+ WacomDevicePtr priv = NULL;
+ WacomCommonPtr common = NULL;
+ char *s;
+ LocalDevicePtr localDevices;
+
+ wcmDrv = drv;
+
+ fakeLocal = (LocalDevicePtr) xcalloc(1, sizeof(LocalDeviceRec));
+ if (!fakeLocal)
+ return NULL;
+
+ fakeLocal->conf_idev = dev;
+
+ /* Force default serial port options to exist because the serial init
+ * phasis is based on those values.
+ */
+ xf86CollectInputOptions(fakeLocal, default_options, NULL);
+
+ /* Type is mandatory */
+ s = xf86FindOptionValue(fakeLocal->options, "Type");
+
+ /* Beta code jumps out here */
+ if (s && (xf86NameCmp(s, "beta") == 0))
+ {
+ xfree(fakeLocal);
+ return wcmBetaNewDevice(drv,dev,flags);
+ }
+ else if (s && (xf86NameCmp(s, "stylus") == 0)) {
+ local = xf86WcmAllocateStylus();
+ }
+ else if (s && (xf86NameCmp(s, "cursor") == 0)) {
+ local = xf86WcmAllocateCursor();
+ }
+ else if (s && (xf86NameCmp(s, "eraser") == 0)) {
+ local = xf86WcmAllocateEraser();
+ }
+ else {
+ xf86Msg(X_ERROR, "%s: No type or invalid type specified.\n"
+ "Must be one of stylus, cursor or eraser\n",
+ dev->identifier);
+ goto SetupProc_fail;
+ }
+
+ if (!local) {
+ xfree(fakeLocal);
+ return NULL;
+ }
+
+ priv = (WacomDevicePtr) local->private;
+ common = priv->common;
+
+ local->options = fakeLocal->options;
+ local->conf_idev = fakeLocal->conf_idev;
+ local->name = dev->identifier;
+ xfree(fakeLocal);
+
+ /* Serial Device is mandatory */
+ common->wcmDevice = xf86FindOptionValue(local->options, "Device");
+
+ if (!common->wcmDevice) {
+ xf86Msg (X_ERROR, "%s: No Device specified.\n", dev->identifier);
+ goto SetupProc_fail;
+ }
+
+ /* Lookup to see if there is another wacom device sharing
+ * the same serial line.
+ */
+ localDevices = xf86FirstLocalDevice();
+
+ while(localDevices) {
+ if ((local != localDevices) &&
+ (localDevices->device_control == xf86WcmProc) &&
+ (strcmp(((WacomDevicePtr)localDevices->private)->common->wcmDevice,
+ common->wcmDevice) == 0)) {
+ DBG(2, ErrorF("xf86WcmConfig wacom port share between"
+ " %s and %s\n",
+ local->name, localDevices->name));
+ ((WacomDevicePtr) localDevices->private)->common->wcmHasEraser |= common->wcmHasEraser;
+ xfree(common->wcmDevices);
+ xfree(common);
+ common = priv->common = ((WacomDevicePtr) localDevices->private)->common;
+ common->wcmNumDevices++;
+ common->wcmDevices = (LocalDevicePtr *) xrealloc(common->wcmDevices,
+ sizeof(LocalDevicePtr) * common->wcmNumDevices);
+ common->wcmDevices[common->wcmNumDevices - 1] = local;
+ break;
+ }
+ localDevices = localDevices->next;
+ }
+
+ /* Process the common options. */
+ xf86ProcessCommonOptions(local, local->options);
+
+ /* Optional configuration */
+
+ xf86Msg(X_CONFIG, "%s serial device is %s\n", dev->identifier,
+ common->wcmDevice);
+
+ debug_level = xf86SetIntOption(local->options, "DebugLevel", debug_level);
+ if (debug_level > 0) {
+ xf86Msg(X_CONFIG, "WACOM: debug level set to %d\n", debug_level);
+ }
+
+ s = xf86FindOptionValue(local->options, "Mode");
+
+ if (s && (xf86NameCmp(s, "absolute") == 0)) {
+ priv->flags = priv->flags | ABSOLUTE_FLAG;
+ }
+ else if (s && (xf86NameCmp(s, "relative") == 0)) {
+ priv->flags = priv->flags & ~ABSOLUTE_FLAG;
+ }
+ else if (s) {
+ xf86Msg(X_ERROR, "%s: invalid Mode (should be absolute or relative). Using default.\n",
+ dev->identifier);
+ }
+ xf86Msg(X_CONFIG, "%s is in %s mode\n", local->name,
+ (priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
+
+ common->wcmSuppress = xf86SetIntOption(local->options, "Suppress", common->wcmSuppress);
+ if (common->wcmSuppress != -1) {
+ xf86Msg(X_CONFIG, "WACOM: suppress value is %d\n", XCONFIG_GIVEN,
+ common->wcmSuppress);
+ }
+
+ if (xf86SetBoolOption(local->options, "Tilt", (common->wcmFlags & TILT_FLAG))) {
+ common->wcmFlags |= TILT_FLAG;
+ }
+
+#ifdef LINUX_INPUT
+ if (xf86SetBoolOption(local->options, "USB", (common->wcmOpen == xf86WcmUSBOpen))) {
+ local->read_input=xf86WcmReadUSBInput;
+ common->wcmOpen=xf86WcmUSBOpen;
+ xf86Msg(X_CONFIG, "%s: reading USB link\n", dev->identifier);
+ }
+#else
+ if (xf86SetBoolOption(local->options, "USB", 0)) {
+ ErrorF("The USB version of the driver isn't available for your platform\n");
+ }
+#endif
+
+ priv->screen_no = xf86SetIntOption(local->options, "ScreenNo", -1);
+ if (priv->screen_no != -1) {
+ xf86Msg(X_CONFIG, "%s: attached screen number %d\n", dev->identifier,
+ priv->screen_no);
+ }
+
+ if (xf86SetBoolOption(local->options, "KeepShape", 0)) {
+ priv->flags |= KEEP_SHAPE_FLAG;
+ xf86Msg(X_CONFIG, "%s: keeps shape\n", dev->identifier);
+ }
+
+ priv->topX = xf86SetIntOption(local->options, "TopX", 0);
+ if (priv->topX != 0) {
+ xf86Msg(X_CONFIG, "%s: top x = %d\n", dev->identifier, priv->topX);
+ }
+ priv->topY = xf86SetIntOption(local->options, "TopY", 0);
+ if (priv->topY != 0) {
+ xf86Msg(X_CONFIG, "%s: top x = %d\n", dev->identifier, priv->topY);
+ }
+ priv->bottomX = xf86SetIntOption(local->options, "BottomX", 0);
+ if (priv->bottomX != 0) {
+ xf86Msg(X_CONFIG, "%s: bottom x = %d\n", dev->identifier,
+ priv->bottomX);
+ }
+ priv->bottomY = xf86SetIntOption(local->options, "BottomY", 0);
+ if (priv->bottomY != 0) {
+ xf86Msg(X_CONFIG, "%s: bottom x = %d\n", dev->identifier,
+ priv->bottomY);
+ }
+ priv->serial = xf86SetIntOption(local->options, "Serial", 0);
+ if (priv->bottomY != 0) {
+ xf86Msg(X_CONFIG, "%s: serial number = %u\n", dev->identifier,
+ priv->serial);
+ }
+ common->wcmThreshold = xf86SetIntOption(local->options, "Threshold", common->wcmThreshold);
+ if (common->wcmThreshold != INVALID_THRESHOLD) {
+ xf86Msg(X_CONFIG, "%s: threshold = %d\n", dev->identifier,
+ common->wcmThreshold);
+ }
+ common->wcmMaxX = xf86SetIntOption(local->options, "MaxX", common->wcmMaxX);
+ if (common->wcmMaxX != 0) {
+ xf86Msg(X_CONFIG, "%s: max x = %d\n", dev->identifier,
+ common->wcmMaxX);
+ }
+ common->wcmMaxY = xf86SetIntOption(local->options, "MaxY", common->wcmMaxY);
+ if (common->wcmMaxY != 0) {
+ xf86Msg(X_CONFIG, "%s: max x = %d\n", dev->identifier,
+ common->wcmMaxY);
+ }
+ common->wcmMaxZ = xf86SetIntOption(local->options, "MaxZ", common->wcmMaxZ);
+ if (common->wcmMaxZ != DEFAULT_MAXZ) {
+ xf86Msg(X_CONFIG, "%s: max x = %d\n", dev->identifier,
+ common->wcmMaxZ);
+ }
+ common->wcmResolX = xf86SetIntOption(local->options, "ResolutionX", common->wcmResolX);
+ if (common->wcmResolX != 0) {
+ xf86Msg(X_CONFIG, "%s: resol x = %d\n", dev->identifier,
+ common->wcmResolX);
+ }
+ common->wcmResolY = xf86SetIntOption(local->options, "ResolutionY", common->wcmResolY);
+ if (common->wcmResolY != 0) {
+ xf86Msg(X_CONFIG, "%s: resol x = %d\n", dev->identifier,
+ common->wcmResolY);
+ }
+ common->wcmResolZ = xf86SetIntOption(local->options, "ResolutionZ", common->wcmResolZ);
+ if (common->wcmResolZ != 0) {
+ xf86Msg(X_CONFIG, "%s: resol x = %d\n", dev->identifier,
+ common->wcmResolZ);
+ }
+
+ {
+ int val;
+ val = xf86SetIntOption(local->options, "BaudRate", 0);
+
+ switch(val) {
+ case 38400:
+ common->wcmLinkSpeed = 38400;
+ break;
+ case 19200:
+ common->wcmLinkSpeed = 19200;
+ break;
+ case 9600:
+ common->wcmLinkSpeed = 9600;
+ break;
+ default:
+ xf86Msg(X_ERROR, "%s: Illegal speed value (must be 9600 or 19200 or 38400).", dev->identifier);
+ break;
+ }
+ if (xf86Verbose)
+ xf86Msg(X_CONFIG, "%s: serial speed %u\n", dev->identifier,
+ val);
+ }
+ /* mark the device configured */
+ local->flags |= XI86_POINTER_CAPABLE | XI86_CONFIGURED;
+
+ /* return the LocalDevice */
+ return (local);
+
+ SetupProc_fail:
+ if (common)
+ xfree(common);
+ if (priv)
+ xfree(priv);
+ if (local)
+ xfree(local);
+ return NULL;
+}
+
+#ifdef XFree86LOADER
+static
+#endif
+InputDriverRec WACOM = {
+ 1, /* driver version */
+ "wacom", /* driver name */
+ NULL, /* identify */
+ xf86WcmInit, /* pre-init */
+ xf86WcmUninit, /* un-init */
+ NULL, /* module */
+ 0 /* ref count */
+};
+
+/*
+ ***************************************************************************
+ *
+ * Dynamic loading functions
+ *
+ ***************************************************************************
+ */
+#ifdef XFree86LOADER
+/*
+ * xf86WcmUnplug --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static void
+xf86WcmUnplug(pointer p)
+{
+ DBG(1, ErrorF("xf86WcmUnplug\n"));
+}
+
+/*
+ * xf86WcmPlug --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static pointer
+xf86WcmPlug(pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin)
+{
+ xf86Msg(X_INFO, "Wacom driver level: %s\n", identification+strlen("$Identification: "));
+
+ xf86AddInputDriver(&WACOM, module, 0);
+
+ return module;
+}
+
+static XF86ModuleVersionInfo xf86WcmVersionRec =
+{
+ "wacom",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature, to be patched into the file by */
+ /* a tool */
+};
+
+XF86ModuleData wacomModuleData = {&xf86WcmVersionRec,
+ xf86WcmPlug,
+ xf86WcmUnplug};
+
+#endif /* XFree86LOADER */
+#endif /* XFREE86_V4 */
+
+/*
+ * Local variables:
+ * change-log-default-name: "~/xinput.log"
+ * c-file-style: "bsd"
+ * End:
+ */
+/* end of xf86Wacom.c */