OSDN Git Service

Massive commit to enter in changes from the past six months contributed
authorDouglas Lowder <douglowder@mac.com>
Thu, 22 Jul 2004 02:12:59 +0000 (19:12 -0700)
committerDouglas Lowder <douglowder@mac.com>
Thu, 22 Jul 2004 02:12:59 +0000 (19:12 -0700)
by Chris Larson <kergoth@handhelds.org> and others.

See ChangeLog for all the details.

-Doug Lowder <douglowder@mac.com>

24 files changed:
ChangeLog
README
configure.in
etc/ts.conf
plugins/Makefile.am
plugins/dejitter.c
plugins/linear.c
plugins/variance.c
src/Makefile.am
src/ts_attach.c
src/ts_config.c
src/ts_load_module.c
src/ts_open.c
src/ts_read.c
src/ts_read_raw.c
src/tslib-private.h
src/tslib.h
tests/Makefile.am
tests/fbutils.c
tests/fbutils.h
tests/ts_calibrate.c
tests/ts_print.c
tests/ts_print_raw.c
tests/ts_test.c

index 39f07d9..80ff66f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2004-01-26 Andrew Zabolotny <zap@homelink.ru>
+
+       * README: Updated documentation on module parameters.
+       * plugins/linear.c: Removed the bogus noxyswap parameter.
+
+2004-06-14  Chris Larson  <kergoth@handhelds.org>
+
+       * src/ts_read_raw.c: Fix bug hit by me and identified by Phil
+         related to the way we call the raw read functions.
+       * src/input-raw.c (ts_input_read): Rename function, call out
+         check_fd to confirm sanity of this inputdevice, make EV_SYN
+         decision at runtime.
+       * src/input-raw.c (check_fd): Rework a bit, and check for EV_SYN
+         event availability.
+       * src/input-raw.c (mod_init): Switch from static to vars in our
+         malloced tslib_module_info based structure.
+       * src/input-raw.c (ts_input_fini): New function.  Free malloced structure.
+       * etc/ts.conf: Add commented module_raw entry for 'input'.
+       * src/ts_config.c: Abort and warn when no raw modules were loaded.
+       * plugins/*.c: Use C99 initializers.
+
+2004-06-11  Philip Blundell  <philb@gnu.org>
+
+       * plugins/variance.c (variance_read): Also clear VAR_LASTVALID on
+         pen up events.
+
+2004-06-09  Chris Larson  <kergoth@handhelds.org>
+
+       * plugins/Makefile.am: Ensure plugins get installed.
+       * plugins/input-raw.c: Watch for a BTN_TOUCH input key event,
+         to use it as an indication of pen release.
+
+2004-06-09  Glenn McGrath  <glennm@hydrix.com>
+       * input-raw.c:
+         - Rewrite !EV_SYN section.
+         - Never return -1, causes cursor flicker in kdrive xserver.
+         - Handle partial reads without throwing out data.
+         - Run through indent.
+         - Simplify.
+       * ts_config.c:
+         - Optimize to save some space.
+         - Fix long line check, they dont always end '\n'.
+         - Report the name of modules that wont load.
+       * configure.ac:
+         - Allow default plugindir to be set by configure.
+
+2004-06-08  Philip Blundell  <philb@gnu.org>
+
+       Patch from Glenn McGrath <bug1@iinet.net.au>
+       * configure.in: Renamed to ...
+       * configure.ac: ... this.  Use AM_CONDITIONAL to enable plugins.
+         Fix confusion between input and arctic2 drivers.  Install plugins
+         into ${libdir}/ts, not ${libdir}/ts/plugins.
+       * plugins/Makefile.am: Keep in step with AM_CONDITIONAL changes.
+
+2004-06-07  Philip Blundell  <philb@gnu.org>
+
+       * plugins/input-raw.c: Fix compilation errors.
+       * src/tslib-private.h: Remove #ifdef USE_INPUT_API block.
+       * configure.in: Enable input plugin if requested.
+
+2004-06-06  Philip Blundell  <philb@gnu.org>
+
+       * tests/Makefile.am (ts_test_SOURCES, ts_calibrate_SOURCES,
+         ts_harvest_SOURCES): Add fbutils.h and font.h.
+         (ts_calibrate_SOURCES, ts_harvest_SOURCES): Add testutils.h as
+         well.
+
+       * src/ts_open.c (ts_open): Remove INPUT_API stuff.
+       * src/ts_read_raw_module.c: Deleted.
+       * src/Makefile.am (libts_la_SOURCES): Remove ts_read_raw_module.c.
+       * plugins/input-raw.c: New file.
+       * plugins/Makefile.am (EXTRA_LTLIBRARIES): Add input.la.
+       * configure.in: Remove --enable-input-api option.
+         (PLUGIN_DIR): Place under ${libdir}, not ${datadir}.
+
+2004-06-04  Philip Blundell  <philb@gnu.org>
+
+       * src/ts_config.c (ts_config): Increase size of line buffer.
+
+       * plugins/variance.c (variance_read): Correct test of return value
+         from ->read method.
+
+2004-05-10 Michael Opdenacker <michaelo@handhelds.org>
+
+       * src/tslib.h: removed the obsolete comment that ts_fd is not implemented yet
+
+       * tests/testutils.c: new file, containing the getxy function,
+         previously in tests/ts_calibrate.c
+
+       * tests/testutils.h: corresponding include file
+
+       * tests/ts_calibrate.c: moved getxy, sort_by_x and sort_by_y functions
+         to tests/testutils.c
+
+       * tests/ts_harvest.c: new program to harvest hundreds
+         of raw coordinates for non linear touchscreens
+         (as found in the h2200 devices, for example)
+
+       * tests/Makefile.am: added ts_harvest.c and testutils.c
+
+       * tests/ts_test.c: now tells the name of the touchscreen device file
+         when it fails to open it.
+
+       * src/ts_config.c: added missing \n at the end of
+         "option `%s' not recognised" and "line too long" error messages.
+         Also made the error message clearer by giving the config file
+         name and telling that the number is a line number.
+
+       * src/ts_config.c: fixed the code testing blank lines
+         which didn't work for me.
+
+2004-01-29 Chris Larson <kergoth@handhelds.org>
+
+       * Make all the actual hardware access methods (minus input) individual
+         module_raw tslib modules.  Remove reference to TSLIB_TSEVENTTYPE from
+         README, and update etc/ts.conf to include commented out entries for
+         the various module_raw modules.
+
+2004-01-26 Andrew Zabolotny <zap@homelink.ru>
+
+       * src/ts_read_raw_module.c: Added EV_SYN support for kernels >2.5.x.
+         This makes the touchscreen event boundary detection 100% correct
+         and removes the need for tricky assumptions tslib had to do until
+         now. If the EV_SYN macro is not defined, the old algorithm is
+         enabled instead.
+
+       * plugins/variance.c: Rewrote almost from scratch the variance filter.
+         The old variance filter made the input very sluggish because it
+         lets out only one of every four input samples. Now it generates
+         approximatively 1:1 output, except that it filters out what it
+         thinks are "noise" samples.
+
+       * plugins/dejitter.c: Rewrote almost from scratch the dejitter filter.
+         Now it just applies a weighted smoothing algorithm with most weight
+         in most recent samples; this leaves touchscreen input responsive and
+         still smooths out jitter.
+
+       * tests/fbutilc.c: Improved a lot; added line drawing, rectangle
+         drawing and filled rectangle drawing, support for up to 256
+         user-defined colors.
+
+       * tests/ts_test.c, tests/ts_calibrate.c: Update to take advantage of
+         the improved functionality of fbutils.c. The ts_test tool now has
+         a "drag" (old behaviour) and "draw" mode (the pen leaves a trace on
+         the screen).
+
+2003-11-01 Chris Larson <kergoth@handhelds.org>
+
+       * plugins/pthres.c, plugins/Makefile.am, configure.in: Added pressure
+         threshold tslib plugin, which is used to ensure that the release
+         event's pressure is 0.
+
+       * plugins/variance.c, plugins/dejitter.c: Removed pressure threshold
+         handling from plugins, now that pthres is handling it.
+
+       * etc/ts.conf: Updated default ts.conf per changes due to pthres.
+
+2003-08-05 Chris Larson <kergoth@handhelds.org>
+
+       * Updated README documentation.  Added information on what the various
+         TSLIB environment variables do, and information on a guideline for
+         tslib filter module creators.
+
+2003-07-31 Chris Larson <kergoth@handhelds.org>
+
+       * Corrected some issues with automake usage, which included changing
+         references of CFLAGS to AM_CFLAGS where necessary.
+
+2003-03-12 Chris Larson <kergoth@handhelds.org>
+
+       * Add a raw module linked list, connected to the primary list, to
+         facilitate tslib modules affecting ts_read_raw behavior.
+
 2003-03-04 Douglas Lowder <dlowder@earthlink.net>
-- Added support for COLLIE and CORGI event types (thanks to Chris Larson
-  of the OpenZaurus project)
+
+       * Added support for COLLIE and CORGI event types (thanks to Chris Larson
+         of the OpenZaurus project)
 
 2003-03-03 Douglas Lowder <dlowder@earthlink.net>
-- Fixed segfault bug in src/ts_parse_args.c
+
+       * Fixed segfault bug in src/ts_parse_args.c
 
 2002-11-08  Douglas Lowder <dlowder@earthlink.net>
-- Added patch from Scott Anderson to improve tests/ts_calibrate.c by taking
-  median of multiple samples for each point.
+
+       * Added patch from Scott Anderson to improve tests/ts_calibrate.c by taking
+         median of multiple samples for each point.
 
 2002-08-29  Douglas Lowder <dlowder@earthlink.net>
-- Added tests/ts_print_raw.c to print raw uncalibrated touchscreen events
-  (useful for debugging)
+
+       * Added tests/ts_print_raw.c to print raw uncalibrated touchscreen events
+         (useful for debugging)
 
 2002-07-11  Douglas Lowder <dlowder@earthlink.net>
-- Added code in src/ts_read_raw.c to handle reading events from the mk712
-  touchscreen driver on the Hitachi Webpad.
 
-- Fixed a bug in plugins/linear.c (incorrect default calibration in
-  absence of /etc/pointercal)
+       * Added code in src/ts_read_raw.c to handle reading events from the mk712
+         touchscreen driver on the Hitachi Webpad.
+
+       * Fixed a bug in plugins/linear.c (incorrect default calibration in
+         absence of /etc/pointercal)
 
 2002-07-10  Douglas Lowder <dlowder@earthlink.net>
 
-- Added a patch by Holger Schurig <h.schurig@mn-logistik.de> to fix
-  issues encountered on an Accelent PXA250 board.  The patch is against
-  tests/ts_calibrate.c.  Among other things, it removes the extra event
-  that was being read before the first crosshair is painted.
+       * Added a patch by Holger Schurig <h.schurig@mn-logistik.de> to fix
+         issues encountered on an Accelent PXA250 board.  The patch is against
+         tests/ts_calibrate.c.  Among other things, it removes the extra event
+         that was being read before the first crosshair is painted.
 
-- Modified the code in plugins/dejitter.c to guarantee that the "release"
-  touchscreen event (event with pressure=0 that occurs when the pointer is
-  lifted from the screen) has the same xy position as the preceding event.
-  This eliminates the cursor "jumping" that can occur otherwise.
+       * Modified the code in plugins/dejitter.c to guarantee that the "release"
+         touchscreen event (event with pressure=0 that occurs when the pointer is
+         lifted from the screen) has the same xy position as the preceding event.
+         This eliminates the cursor "jumping" that can occur otherwise.
 
-- Fixed a bug in src/ts_read_raw.c that caused segfaults if TSLIB_TSEVENTTYPE
-  was not defined in the environment.
+       * Fixed a bug in src/ts_read_raw.c that caused segfaults if TSLIB_TSEVENTTYPE
+         was not defined in the environment.
 
 2002-07-05  Douglas Lowder <dlowder@earthlink.net>
 
-- libts.so now handles both UCB1x00 and H3600 type touchscreen events.  Default
-  is UCB1x00; H3600 is selected by setting environment variable
-  TSLIB_TSEVENTTYPE to the value "H3600".
+       * libts.so now handles both UCB1x00 and H3600 type touchscreen events.  Default
+         is UCB1x00; H3600 is selected by setting environment variable
+         TSLIB_TSEVENTTYPE to the value "H3600".
 
-- With the above change, generation of libtsipaq.so is no longer required,
-  and it has been removed.
+       * With the above change, generation of libtsipaq.so is no longer required,
+         and it has been removed.
 
 2002-07-03  Douglas Lowder <dlowder@earthlink.net>
 
-- Added back the code to open the virtual console (works if device file chosen
-  correctly).
+       * Added back the code to open the virtual console (works if device file chosen
+         correctly).
 
-- Made the console device and framebuffer device configurable for ts_calibrate
-  and ts_test: new environment variables defined.
-  TSLIB_FBDEVICE (defaults to /dev/fb0)
-  TSLIB_CONSOLEDEVICE (defaults to /dev/tty)
+       * Made the console device and framebuffer device configurable for ts_calibrate
+         and ts_test: new environment variables defined.
+         TSLIB_FBDEVICE (defaults to /dev/fb0)
+         TSLIB_CONSOLEDEVICE (defaults to /dev/tty)
 
-  On a system using devfs, the above should be set to /dev/fb/0 and /dev/vc/,
-  respectively.
+         On a system using devfs, the above should be set to /dev/fb/0 and /dev/vc/,
+         respectively.
 
 2002-07-01  Douglas Lowder <dlowder@earthlink.net>
 
-- Fixes to make this code work better on targets with framebuffers that have
-  more than 8 bits per pixel (changes to tests/fbutils.c):
-  * Removed the code that attempts to change colormap
-  * Temporarily commented out the code that opens /dev/tty1 (does not work on all targets)
+       * Fixes to make this code work better on targets with framebuffers that have
+         more than 8 bits per pixel (changes to tests/fbutils.c):
+         * Removed the code that attempts to change colormap
+         * Temporarily commented out the code that opens /dev/tty1 (does not work on all targets)
 
-- Fixed the test program so that the crosshair is drawn XORed with the text on the screen,
-  so the text is not corrupted when the crosshair moves over it. (tests/fbutils.c)
+       * Fixed the test program so that the crosshair is drawn XORed with the text on the screen,
+         so the text is not corrupted when the crosshair moves over it. (tests/fbutils.c)
 
-- Made the code much more configurable by adding checks for environment variables:
-  TSLIB_CALIBFILE -- location of calibration file for linear plugin (default: /etc/pointercal)
-  TSLIB_CONFFILE -- location of configuration file (default: /usr/local/etc/ts.conf)
-  TSLIB_PLUGINDIR -- location of plugins (default: /usr/local/share/ts/plugins)
-  TSLIB_TSDEVICE -- Name of touchscreen device file if not using input API (default: /dev/touchscreen/ucb1x00)
+       * Made the code much more configurable by adding checks for environment variables:
+         TSLIB_CALIBFILE -- location of calibration file for linear plugin (default: /etc/pointercal)
+         TSLIB_CONFFILE -- location of configuration file (default: /usr/local/etc/ts.conf)
+         TSLIB_PLUGINDIR -- location of plugins (default: /usr/local/share/ts/plugins)
+         TSLIB_TSDEVICE -- Name of touchscreen device file if not using input API (default: /dev/touchscreen/ucb1x00)
 
-- Added new file, src/ts_read_raw_ipaq.c, to make code work with the h3600_ts driver
-  on the Compaq iPAQ.  This creates a new library, libtsipaq.so, that should replace
-  the default libts.so if using this code on an iPAQ.
+       * Added new file, src/ts_read_raw_ipaq.c, to make code work with the h3600_ts driver
+         on the Compaq iPAQ.  This creates a new library, libtsipaq.so, that should replace
+         the default libts.so if using this code on an iPAQ.
 
 2002-06-19  Douglas Lowder <dlowder@earthlink.net>
 
-- Fixed a problem that caused tslib_parse_vars() (src/ts_parse_vars.c) to not
-  read parameters correctly from the ts.conf file.
+       * Fixed a problem that caused tslib_parse_vars() (src/ts_parse_vars.c) to not
+         read parameters correctly from the ts.conf file.
 
-- Made modifications to simplify and improve the performance of the dejitter filter
-  (plugins/dejitter.c).
+       * Made modifications to simplify and improve the performance of the dejitter filter
+         (plugins/dejitter.c).
 
-- Added the configure script and Makefile.in files, plus other files generated by
-  autogen.sh, so that only "configure" needs to be run before running "make".
-  If a user wishes to rerun the automake and autoconf steps, run "autogen-clean.sh"
-  and then "autogen.sh".
+       * Added the configure script and Makefile.in files, plus other files generated by
+         autogen.sh, so that only "configure" needs to be run before running "make".
+         If a user wishes to rerun the automake and autoconf steps, run "autogen-clean.sh"
+         and then "autogen.sh".
 
 2002-06-17  Douglas Lowder <dlowder@earthlink.net>
 
-- I added a simple script, autogen-clean.sh, to make it easier to change configure.in
-  and regenerate configure scripts and Makefiles.
-
-- I made modifications so that npitre's new input API code is now wrapped in
-  #ifdef USE_INPUT_API.  Added a new configure flag, --enable-inputapi, which
-  is turned on by default, and which adds -DUSE_INPUT_API to CFLAGS in all the
-  Makefiles.  --disable-inputapi will return the code to its original behavior
-  of opening /dev/touchscreen/ucb1x00 and reading events directly.
-
-- I modified plugins/linear.c so that it determines the full linear transformation
-  between touchscreen and framebuffer coordinate systems.  This method not only
-  rescales and offsets the coordinates correctly, but also automatically takes care
-  of rotation or tilt between the coordinate systems, and automatically takes care
-  of cases where X and Y are interchanged.  Therefore, the xyswap parameter is
-  no longer required or used.
-
-- I found the framebuffer code in tests/ts_calibrate.c and tests/ts_test.c to be
-  broken, and fixed it so it works correctly (used ADS GraphicsClient+ and an Intel
-  DBPXA250 (Lubbock) Xscale target for testing). 
-  Since there was a lot of duplication, I extracted all the framebuffer specific stuff
-  to new files fbutils.c and fbutils.h, so it will be easier to add more framebuffer
-  tests in future if desired.  I also extract a couple of fonts and wrote simple text
-  printing code so text messages can be displayed in ts_test and ts_calibrate.
-
-- I added a new configure flag, --enable-debug, which is turned off by default.  When
-  enabled, it adds -g -ggdb -DDEBUG to CFLAGS in all the Makefiles.  I have debug
-  print statements in ts_read_raw and in the plugins that are wrapped with #ifdef DEBUG --
-  this way I can see how many events are being filtered away and get a better idea
-  of what the filters are doing.
-
-- Joanne Woo <jwoo@mvista.com> added C++ wrappers to the header files so this library
-  can be safely used with C++ code.
+       * I added a simple script, autogen-clean.sh, to make it easier to change configure.in
+         and regenerate configure scripts and Makefiles.
+
+       * I made modifications so that npitre's new input API code is now wrapped in
+         #ifdef USE_INPUT_API.  Added a new configure flag, --enable-inputapi, which
+         is turned on by default, and which adds -DUSE_INPUT_API to CFLAGS in all the
+         Makefiles.  --disable-inputapi will return the code to its original behavior
+         of opening /dev/touchscreen/ucb1x00 and reading events directly.
+
+       * I modified plugins/linear.c so that it determines the full linear transformation
+         between touchscreen and framebuffer coordinate systems.  This method not only
+         rescales and offsets the coordinates correctly, but also automatically takes care
+         of rotation or tilt between the coordinate systems, and automatically takes care
+         of cases where X and Y are interchanged.  Therefore, the xyswap parameter is
+         no longer required or used.
+
+       * I found the framebuffer code in tests/ts_calibrate.c and tests/ts_test.c to be
+         broken, and fixed it so it works correctly (used ADS GraphicsClient+ and an Intel
+         DBPXA250 (Lubbock) Xscale target for testing).
+         Since there was a lot of duplication, I extracted all the framebuffer specific stuff
+         to new files fbutils.c and fbutils.h, so it will be easier to add more framebuffer
+         tests in future if desired.  I also extract a couple of fonts and wrote simple text
+         printing code so text messages can be displayed in ts_test and ts_calibrate.
+
+       * I added a new configure flag, --enable-debug, which is turned off by default.  When
+         enabled, it adds -g -ggdb -DDEBUG to CFLAGS in all the Makefiles.  I have debug
+         print statements in ts_read_raw and in the plugins that are wrapped with #ifdef DEBUG --
+         this way I can see how many events are being filtered away and get a better idea
+         of what the filters are doing.
+
+       * Joanne Woo <jwoo@mvista.com> added C++ wrappers to the header files so this library
+         can be safely used with C++ code.
 
diff --git a/README b/README
index c463085..4cd7f25 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-$Id: README,v 1.3 2002/06/19 18:55:08 dlowder Exp $
+$Id: README,v 1.4 2004/07/21 19:12:58 dlowder Exp $
 
 General
 =======
@@ -14,8 +14,9 @@ specifies one module, and the parameters for that module.  The modules
 are loaded in order, with the first one processing the touchscreen data
 first.  For example:
 
-  module variance xlimit=50 ylimit=50 pthreshold=100
-  module dejitter xdelta=3 ydelta=2 pthreshold=100
+  module_raw input
+  module variance delta=30
+  module dejitter delta=100
   module linear
 
 These parameters are described below.
@@ -23,8 +24,8 @@ These parameters are described below.
 With this configuration file, we end up with the following data flow
 through the library:
 
-  raw device --> variance --> dejitter --> linear --> application
-                 module       module       module
+  raw read --> variance --> dejitter --> linear --> application
+  module       module       module       module
 
 You can re-order these modules as you wish, add more modules, or remove them
 all together.  When you call ts_read(), the values you read are values that
@@ -34,9 +35,42 @@ raw data directly from the device.
 
 There are a couple of programs in the tslib/test directory which give example
 usages.  They are by no means exhaustive, nor probably even good examples.
-They are basically the programs I used to test this library.
-
-
+They are basically the programs used to test this library.
+
+
+Environment Variables
+=====================
+
+TSLIB_TSDEVICE                 TS device file name.
+                               Default (non inputapi): /dev/touchscreen/ucb1x00
+                               Default (inputapi): /dev/input/event0
+TSLIB_CALIBFILE                        Calibration file.
+                               Default: ${sysconfdir}/pointercal
+TSLIB_CONFFILE                 Config file.
+                               Default: ${sysconfdir}/ts.conf
+TSLIB_PLUGINDIR                        Plugin directory.
+                               Default: ${datadir}/plugins
+TSLIB_CONSOLEDEVICE            Console device.
+                               Default: /dev/tty
+TSLIB_FBDEVICE                 Framebuffer device.
+                               Default: /dev/fb0
+
+
+Module Creation Notes
+=====================
+
+For those creating tslib modules, it is important to note a couple things with
+regard to handling of the ability for a user to request more than one ts event
+at a time.  The first thing to note is that the lower layers may send up less
+events than the user requested, because some events may be filtered out by
+intermediate layers. Next, your module should send up just as many events
+as the user requested in nr. If your module is one that consumes events,
+such as variance, then you loop on the read from the lower layers, and only
+send the events up when
+1) you have the number of events requested by the user, or
+2) one of the events from the lower layers was a pen release.
+
 Module Parameters
 =================
 
@@ -44,39 +78,47 @@ module:     variance
 ----------------
 
 Description:
-  Variance filter.  Calculates the variance on the last 4 X and Y axis values
-  independently, and averages the two samples with the smallest variance.
+  Variance filter. Tries to do it's best in order to filter out random noise
+  coming from touchscreen ADC's. This is achieved by limiting the sample
+  movement speed to some value (e.g. the pen is not supposed to move quicker
+  than some threshold).
 
-Parameters:
-  xlimit
-       Sets the X axis variance limit on the last 4 touch screen samples,
-       in touch screen coordinates.  Variances outside this limit will
-       cause 4 extra samples to be collected.
+  This is a 'greedy' filter, e.g. it gives less samples on output than
+  receives on input.
 
-  ylimit
-       Sets the Y axis variance limit on the last 4 touch screen samples,
-       in touch screen coordinates.  Variances outside this limit will
-       cause 4 extra samples to be collected.
+Parameters:
+  delta
+       Set the squared distance in touchscreen units between previous and
+       current pen position (e.g. (X2-X1)^2 + (Y2-Y1)^2). This defines the
+       criteria for determining whenever two samples are 'near' or 'far'
+       to each other.
+
+       Now if the distance between previous and current sample is 'far',
+       the sample is marked as 'potential noise'. This doesn't mean yet
+       that it will be discarded; if the next reading will be close to it,
+       this will be considered just a regular 'quick motion' event, and it
+       will sneak to the next layer. Also, if the sample after the
+       'potential noise' is 'far' from both previously discussed samples,
+       this is also considered a 'quick motion' event and the sample sneaks
+       into the output stream.
 
-  pthreshold
-       Sets the pressure threshold, above which we believe the pen
-       to be down.
 
 module: dejitter
 ----------------
 
 Description:
-  Removes jitter on the X and Y co-ordinates.  Samples whos X and Y
-  differentials are within these limits will be treated as an identical
-  value, and gobbled up.
+  Removes jitter on the X and Y co-ordinates. This is achieved by applying a
+  weighted smoothing filter. The latest samples have most weight; earlier
+  samples have less weight. This allows to achieve 1:1 input->output rate.
 
 Parameters:
-  xdelta
-  ydelta
-       Sets the minimum differential between the current and the previous
-       X or Y sample.
+  delta
+       Squared distance between two samples ((X2-X1)^2 + (Y2-Y1)^2) that
+       defines the 'quick motion' threshold. If the pen moves quick, it
+       is not feasible to smooth pen motion, besides quick motion is not
+       precise anyway; so if quick motion is detected the module just
+       discards the backlog and simply copies input to output.
 
-  pthreshold
 
 module: linear
 --------------
index 29dd20d..fbc704e 100644 (file)
@@ -1,15 +1,34 @@
-dnl $Id: configure.in,v 1.3 2002/06/17 17:21:42 dlowder Exp $
+dnl $Id: configure.in,v 1.4 2004/07/21 19:12:58 dlowder Exp $
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/ts_close.c)
 AM_INIT_AUTOMAKE(libts,0.0.1)
 AM_CONFIG_HEADER(config.h)
 
+# filters
 AC_ARG_ENABLE(linear,   [  --enable-linear         Enable building of linear scaling [default=yes]],
   [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS linear.la", PLUGINS="$PLUGINS linear.la")
 AC_ARG_ENABLE(dejitter, [  --enable-dejitter       Enable building of dejitter filter [default=yes]],
   [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS dejitter.la", PLUGINS="$PLUGINS dejitter.la")
 AC_ARG_ENABLE(variance, [  --enable-variance       Enable building of variance filter [default=yes]],
   [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS variance.la", PLUGINS="$PLUGINS variance.la")
+AC_ARG_ENABLE(pthres,   [  --enable-pthres         Enable building of pthres filter [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS pthres.la", PLUGINS="$PLUGINS pthres.la")
+
+# hardware access modules
+AC_ARG_ENABLE(ucb1x00,  [  --enable-ucb1x00        Enable building of ucb1x00 raw module (UCB1x00 support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS ucb1x00.la", PLUGINS="$PLUGINS ucb1x00.la")
+AC_ARG_ENABLE(corgi,    [  --enable-corgi          Enable building of corgi raw module (Sharp Zaurus sl-c7x0 support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS corgi.la", PLUGINS="$PLUGINS corgi.la")
+AC_ARG_ENABLE(collie,   [  --enable-collie         Enable building of collie raw module (Sharp Zaurus sl-5500/5000d support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS collie.la", PLUGINS="$PLUGINS collie.la")
+AC_ARG_ENABLE(h3600,    [  --enable-h3600          Enable building of h3600 raw module (HP iPaq H3600 support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS h3600.la", PLUGINS="$PLUGINS h3600.la")
+AC_ARG_ENABLE(mk712,    [  --enable-mk712          Enable building of mk712 raw module (Hitachi Webpad support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS mk712.la", PLUGINS="$PLUGINS mk712.la")
+AC_ARG_ENABLE(arctic2,  [  --enable-arctic2        Enable building of arctic2 raw module (IBM Arctic II support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS arctic2.la", PLUGINS="$PLUGINS arctic2.la")
+AC_ARG_ENABLE(arctic2,  [  --enable-input          Enable building of input raw module (Linux /dev/input/eventN support) [default=yes]],
+  [ "x$enableval" = "xyes" ] && PLUGINS="$PLUGINS input.la", PLUGINS="$PLUGINS input.la")
 
 AC_MSG_CHECKING(--enable-debug argument)
 AC_ARG_ENABLE(debug,    [  --enable-debug          Enable debug messages from filters [default=no]], 
@@ -21,26 +40,14 @@ else
        DEBUGFLAGS=""
 fi
 
-AC_MSG_CHECKING(--enable-inputapi argument)
-AC_ARG_ENABLE(inputapi, [  --enable-inputapi       Enable use of the input API [default=yes]],
-  , [enable_inputapi="yes"])
-AC_MSG_RESULT($enable_inputapi)
-if test "$enable_inputapi" = "yes"; then
-       INPUTAPIFLAG="-DUSE_INPUT_API"
-else
-       INPUTAPIFLAG=""
-fi
-
 AC_SUBST(DEBUGFLAGS)
-AC_SUBST(INPUTAPIFLAG)
-
 AC_SUBST(PLUGINS)
 
 AM_DISABLE_STATIC
 AM_ENABLE_SHARED
 
 
-PLUGIN_DIR='${datadir}/ts/plugins'
+PLUGIN_DIR='${libdir}/ts/plugins'
 AC_SUBST(PLUGIN_DIR)
 
 TS_CONF='${sysconfdir}/ts.conf'
index 4105373..dc5c4de 100644 (file)
@@ -1,3 +1,25 @@
-module variance xlimit=50 ylimit=50 pthreshold=1
-module dejitter xdelta=10 ydelta=10 pthreshold=1
+# Uncomment if you wish to use the linux input layer event interface
+# module_raw input
+
+# Uncomment if you're using a Sharp Zaurus SL-5500/SL-5000d
+# module_raw collie
+
+# Uncomment if you're using a Sharp Zaurus SL-C700/C750/C760/C860
+# module_raw corgi
+
+# Uncomment if you're using a device with a UCB1200/1300/1400 TS interface
+# module_raw ucb1x00
+
+# Uncomment if you're using an HP iPaq h3600 or similar
+# module_raw h3600
+
+# Uncomment if you're using a Hitachi Webpad
+# module_raw mk712
+
+# Uncomment if you're using an IBM Arctic II
+# module_raw arctic2
+
+module pthres pmin=1
+module variance delta=30
+module dejitter delta=100
 module linear
index ab22098..716a3cf 100644 (file)
 # This file is placed under the LGPL.  Please see the file
 # COPYING for more details.
 #
-# $Id: Makefile.am,v 1.3 2002/06/19 18:55:08 dlowder Exp $
+# $Id: Makefile.am,v 1.4 2004/07/21 19:12:58 dlowder Exp $
 #
 
-CFLAGS                  := $(CFLAGS) $(DEBUGFLAGS) $(INPUTAPIFLAG)
-INCLUDES                = -I$(top_srcdir)/src
-LDFLAGS                        := $(LDFLAGS) -rpath $(PLUGIN_DIR)
-#LTVSN                 := -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+AM_CFLAGS              = $(DEBUGFLAGS)
+AM_LDFLAGS             = -rpath $(PLUGIN_DIR)
+INCLUDES               = -I$(top_srcdir)/src
+  
+#LTVSN                 = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
 #                         -release $(LT_RELEASE)
-LTVSN                  := -avoid-version
-LIBS                    =
+LTVSN                  = -avoid-version
+LIBS                   =
+pluginexecdir          = $(PLUGIN_DIR)
+  
+if ENABLE_LINEAR_MODULE
+LINEAR_MODULE = linear.la
+else
+LINEAR_MODULE =
+endif
 
-plugindir               = $(PLUGIN_DIR)
+if ENABLE_LINEAR_MODULE
+DEJITTER_MODULE = dejitter.la
+else
+DEJITTER_MODULE =
+endif
 
-EXTRA_LTLIBRARIES       = variance.la dejitter.la linear.la
-plugin_LTLIBRARIES      = $(PLUGINS)
+if ENABLE_VARIANCE_MODULE
+VARIANCE_MODULE = variance.la
+else
+VARIANCE_MODULE =
+endif
 
-variance_la_SOURCES     = variance.c
-variance_la_LDFLAGS     = -module $(LTVSN)
+if ENABLE_PTHRES_MODULE
+PTHRES_MODULE = pthres.la
+else
+PTHRES_MODULE =
+endif
 
-dejitter_la_SOURCES     = dejitter.c
-dejitter_la_LDFLAGS     = -module $(LTVSN)
+if ENABLE_UCB1X00_MODULE
+UCB1X00_MODULE = ucb1x00.la
+else
+UCB1X00_MODULE =
+endif
 
-linear_la_SOURCES       = linear.c
-linear_la_LDFLAGS       = -module $(LTVSN)
+if ENABLE_CORGI_MODULE
+CORGI_MODULE = corgi.la
+else
+CORGI_MODULE =
+endif
+
+if ENABLE_COLLIE_MODULE
+COLLIE_MODULE = collie.la
+else
+COLLIE_MODULE =
+endif
+
+if ENABLE_H3600_MODULE
+H3600_MODULE = h3600.la
+else
+H3600_MODULE =
+endif
+
+if ENABLE_MK712_MODULE
+MK712_MODULE = mk712.la
+else
+MK712_MODULE =
+endif
+
+if ENABLE_ARCTIC2_MODULE
+ARCTIC2_MODULE = arctic2.la
+else
+ARCTIC2_MODULE =
+endif
+
+if ENABLE_INPUT_MODULE
+INPUT_MODULE = input.la
+else
+INPUT_MODULE =
+endif
+
+pluginexec_LTLIBRARIES = \
+       $(LINEAR_MODULE) \
+       $(DEJITTER_MODULE) \
+       $(VARIANCE_MODULE) \
+       $(PTHRES_MODULE) \
+       $(UCB1X00_MODULE) \
+       $(CORGI_MODULE) \
+       $(COLLIE_MODULE) \
+       $(H3600_MODULE) \
+       $(MK712_MODULE) \
+       $(ARCTIC2_MODULE) \
+       $(INPUT_MODULE)
+  
+variance_la_SOURCES    = variance.c
+variance_la_LDFLAGS    = -module $(LTVSN)
+  
+dejitter_la_SOURCES    = dejitter.c
+dejitter_la_LDFLAGS    = -module $(LTVSN)
+  
+linear_la_SOURCES      = linear.c
+linear_la_LDFLAGS      = -module $(LTVSN)
+
+pthres_la_SOURCES      = pthres.c
+pthres_la_LDFLAGS      = -module $(LTVSN)
+
+# hw access
+corgi_la_SOURCES       = corgi-raw.c
+corgi_la_LDFLAGS       = -module $(LTVSN)
+
+collie_la_SOURCES      = collie-raw.c
+collie_la_LDFLAGS      = -module $(LTVSN)
+
+ucb1x00_la_SOURCES     = ucb1x00-raw.c
+ucb1x00_la_LDFLAGS     = -module $(LTVSN)
+
+h3600_la_SOURCES       = h3600-raw.c
+h3600_la_LDFLAGS       = -module $(LTVSN)
+
+mk712_la_SOURCES       = mk712-raw.c
+mk712_la_LDFLAGS       = -module $(LTVSN)
+
+arctic2_la_SOURCES     = arctic2-raw.c
+arctic2_la_LDFLAGS     = -module $(LTVSN)
+
+input_la_SOURCES       = input-raw.c
+input_la_LDFLAGS       = -module $(LTVSN)
index c9a2ff2..cea8f5c 100644 (file)
@@ -1,14 +1,26 @@
 /*
- *  tslib/plugins/threshold.c
+ *  tslib/plugins/dejitter.c
  *
  *  Copyright (C) 2001 Russell King.
  *
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: dejitter.c,v 1.6 2002/11/08 23:28:55 dlowder Exp $
+ * $Id: dejitter.c,v 1.7 2004/07/21 19:12:58 dlowder Exp $
  *
- * Threshold filter for touchscreen values
+ * Problem: some touchscreens read the X/Y values from ADC with a
+ * great level of noise in their lowest bits. This produces "jitter"
+ * in touchscreen output, e.g. even if we hold the stylus still,
+ * we get a great deal of X/Y coordinate pairs that are close enough
+ * but not equal. Also if we try to draw a straight line in a painter
+ * program, we'll get a line full of spikes.
+ *
+ * Solution: we apply a smoothing filter on the last several values
+ * thus excluding spikes from output. If we detect a substantial change
+ * in coordinates, we reset the backlog of pen positions, thus avoiding
+ * smoothing coordinates that are not supposed to be smoothed. This
+ * supposes all noise has been filtered by the lower-level filter,
+ * e.g. by the "variance" module.
  */
 #include <errno.h>
 #include <stdlib.h>
 #include "tslib.h"
 #include "tslib-filter.h"
 
-#define NR_LAST        4
-
-struct tslib_threshold {
-       struct tslib_module_info        module;
-       int                     pthreshold;
-       int                     xdelta;
-       int                     ydelta;
-       int                     delta2;
-       unsigned int                    x;
-       unsigned int                    y;
-       unsigned int                    down;
+/**
+ * This filter works as follows: we keep track of latest N samples,
+ * and average them with certain weights. The oldest samples have the
+ * least weight and the most recent samples have the most weight.
+ * This helps remove the jitter and at the same time doesn't influence
+ * responsivity because for each input sample we generate one output
+ * sample; pen movement becomes just somehow more smooth.
+ */
+
+#define NR_SAMPHISTLEN 4
+
+/* To keep things simple (avoiding division) we ensure that
+ * SUM(weight) = power-of-two. Also we must know how to approximate
+ * measurements when we have less than NR_SAMPHISTLEN samples.
+ */
+static const unsigned char weight [NR_SAMPHISTLEN - 1][NR_SAMPHISTLEN + 1] =
+{
+       /* The last element is pow2(SUM(0..3)) */
+       { 5, 3, 0, 0, 3 },      /* When we have 2 samples ... */
+       { 8, 5, 3, 0, 4 },      /* When we have 3 samples ... */
+       { 6, 4, 3, 3, 4 },      /* When we have 4 samples ... */
+};
+
+struct ts_hist {
+       int x;
+       int y;
+       int p;
 };
 
-static int threshold_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
+struct tslib_dejitter {
+       struct tslib_module_info module;
+       unsigned int delta;
+       unsigned int x;
+       unsigned int y;
+       unsigned int down;
+       unsigned int nr;
+       unsigned int head;
+       struct ts_hist hist[NR_SAMPHISTLEN];
+};
+
+static int sqr (int x)
+{
+       return x * x;
+}
+
+static void average (struct tslib_dejitter *djt, struct ts_sample *samp)
+{
+       const unsigned char *w;
+       int sn = djt->head;
+       int i, x = 0, y = 0, p = 0;
+
+        w = weight [djt->nr - 2];
+
+       for (i = 0; i < djt->nr; i++) {
+               x += djt->hist [sn].x * w [i];
+               y += djt->hist [sn].y * w [i];
+               p += djt->hist [sn].p * w [i];
+               sn = (sn - 1) & (NR_SAMPHISTLEN - 1);
+       }
+
+       samp->x = x >> w [NR_SAMPHISTLEN];
+       samp->y = y >> w [NR_SAMPHISTLEN];
+       samp->pressure = p >> w [NR_SAMPHISTLEN];
+#ifdef DEBUG
+       fprintf(stderr,"DEJITTER----------------> %d %d %d\n",
+               samp->x, samp->y, samp->pressure);
+#endif
+}
+
+static int dejitter_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
 {
-       struct tslib_threshold *thr = (struct tslib_threshold *)info;
+        struct tslib_dejitter *djt = (struct tslib_dejitter *)info;
        struct ts_sample *s;
-       int ret;
+       int count = 0, ret;
 
        ret = info->next->ops->read(info->next, samp, nr);
-       if (ret >= 0) {
-               int nr = 0;
+       for (s = samp; ret > 0; s++, ret--) {
+               if (s->pressure == 0) {
+                       /*
+                        * Pen was released. Reset the state and
+                        * forget all history events.
+                        */
+                       djt->nr = 0;
+                       samp [count++] = *s;
+                        continue;
+               }
 
-               for (s = samp; s < samp + ret; s++) {
-                       int dr2;
+                /* If the pen moves too fast, reset the backlog. */
+               if (djt->nr) {
+                       int prev = (djt->head - 1) & (NR_SAMPHISTLEN - 1);
+                       if (sqr (s->x - djt->hist [prev].x) +
+                           sqr (s->y - djt->hist [prev].y) > djt->delta) {
 #ifdef DEBUG
-                       fprintf(stderr,"BEFORE DEJITTER---------------> %d %d %d\n",s->x,s->y,s->pressure);
-#endif /*DEBUG*/
-                       thr->down = (s->pressure >= thr->pthreshold);
-                       if (thr->down) {
-                               dr2 = (thr->x - s->x)*(thr->x - s->x) 
-                                       + (thr->y - s->y)*(thr->y - s->y);
-                               if(dr2 < thr->delta2) {
-                                       s->x = thr->x;
-                                       s->y = thr->y;
-                               } else {
-                                       thr->x = s->x;
-                                       thr->y = s->y;
-                               }
-
-                       } else {
-                               s->x = thr->x;
-                               s->y = thr->y;
+                               fprintf (stderr, "DEJITTER: pen movement exceeds threshold\n");
+#endif
+                                djt->nr = 0;
                        }
+               }
 
-
-                       samp[nr++] = *s;
+               djt->hist[djt->head].x = s->x;
+               djt->hist[djt->head].y = s->y;
+               djt->hist[djt->head].p = s->pressure;
+               if (djt->nr < NR_SAMPHISTLEN)
+                       djt->nr++;
+
+               /* We'll pass through the very first sample since
+                * we can't average it (no history yet).
+                */
+               if (djt->nr == 1)
+                       samp [count] = *s;
+               else {
+                       average (djt, samp + count);
+                       samp [count].tv = s->tv;
                }
+               count++;
 
-               ret = nr;
+               djt->head = (djt->head + 1) & (NR_SAMPHISTLEN - 1);
        }
-       return ret;
+
+       return count;
 }
 
-static int threshold_fini(struct tslib_module_info *info)
+static int dejitter_fini(struct tslib_module_info *info)
 {
        free(info);
+       return 0;
 }
 
-static const struct tslib_ops threshold_ops =
+static const struct tslib_ops dejitter_ops =
 {
-       read:   threshold_read,
-       fini:   threshold_fini,
+       .read   = dejitter_read,
+       .fini   = dejitter_fini,
 };
 
-static int threshold_limit(struct tslib_module_info *inf, char *str, void *data)
+static int dejitter_limit(struct tslib_module_info *inf, char *str, void *data)
 {
-       struct tslib_threshold *thr = (struct tslib_threshold *)inf;
+       struct tslib_dejitter *djt = (struct tslib_dejitter *)inf;
        unsigned long v;
        int err = errno;
 
@@ -99,15 +180,7 @@ static int threshold_limit(struct tslib_module_info *inf, char *str, void *data)
        errno = err;
        switch ((int)data) {
        case 1:
-               thr->xdelta = v;
-               break;
-
-       case 2:
-               thr->ydelta = v;
-               break;
-
-       case 3:
-               thr->pthreshold = v;
+               djt->delta = v;
                break;
 
        default:
@@ -116,35 +189,31 @@ static int threshold_limit(struct tslib_module_info *inf, char *str, void *data)
        return 0;
 }
 
-static const struct tslib_vars threshold_vars[] =
+static const struct tslib_vars dejitter_vars[] =
 {
-       { "xdelta",     (void *)1, threshold_limit },
-       { "ydelta",     (void *)2, threshold_limit },
-       { "pthreshold", (void *)3, threshold_limit }
+       { "delta",      (void *)1, dejitter_limit },
 };
 
-//#define NR_VARS (sizeof(threshold_vars) / sizeof(threshold_vars[0]))
-#define NR_VARS 3
+#define NR_VARS (sizeof(dejitter_vars) / sizeof(dejitter_vars[0]))
 
 struct tslib_module_info *mod_init(struct tsdev *dev, const char *params)
 {
-       struct tslib_threshold *thr;
+       struct tslib_dejitter *djt;
 
-       thr = malloc(sizeof(struct tslib_threshold));
-       if (thr == NULL)
+       djt = malloc(sizeof(struct tslib_dejitter));
+       if (djt == NULL)
                return NULL;
 
-       thr->module.ops = &threshold_ops;
+       djt->module.ops = &dejitter_ops;
 
-       thr->xdelta = 10;
-       thr->ydelta = 10;
-       thr->pthreshold = 100;
+       djt->delta = 100;
+        djt->head = 0;
 
-       if (tslib_parse_vars(&thr->module, threshold_vars, NR_VARS, params)) {
-               free(thr);
+       if (tslib_parse_vars(&djt->module, dejitter_vars, NR_VARS, params)) {
+               free(djt);
                return NULL;
        }
-       thr->delta2 = (thr->xdelta)*(thr->xdelta) + (thr->ydelta)*(thr->ydelta);
+       djt->delta = sqr (djt->delta);
 
-       return &thr->module;
+       return &djt->module;
 }
index bacb51c..ce59770 100644 (file)
@@ -6,7 +6,7 @@
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: linear.c,v 1.8 2003/03/05 23:03:04 dlowder Exp $
+ * $Id: linear.c,v 1.9 2004/07/21 19:12:59 dlowder Exp $
  *
  * Linearly scale touchscreen values
  */
@@ -74,25 +74,25 @@ linear_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
 static int linear_fini(struct tslib_module_info *info)
 {
        free(info);
+       return 0;
 }
 
 static const struct tslib_ops linear_ops =
 {
-       read:           linear_read,
-       fini:           linear_fini,
+       .read   = linear_read,
+       .fini   = linear_fini,
 };
 
 static int linear_xyswap(struct tslib_module_info *inf, char *str, void *data)
 {
        struct tslib_linear *lin = (struct tslib_linear *)inf;
 
-       lin->swap_xy = (int)data;
+       lin->swap_xy = 1;
        return 0;
 }
 
 static const struct tslib_vars linear_vars[] =
 {
-       { "noxyswap",   (void *)0, linear_xyswap },
        { "xyswap",     (void *)1, linear_xyswap }
 };
 
@@ -104,7 +104,6 @@ struct tslib_module_info *mod_init(struct tsdev *dev, const char *params)
        struct tslib_linear *lin;
        struct stat sbuf;
        int pcal_fd;
-       int a[7];
        char pcalbuf[200];
        int index;
        char *tokptr;
index a4d6eec..93b4413 100644 (file)
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: variance.c,v 1.3 2002/11/08 23:28:55 dlowder Exp $
+ * $Id: variance.c,v 1.4 2004/07/21 19:12:59 dlowder Exp $
  *
- * Variance filter for touchscreen values
+ * Variance filter for touchscreen values.
+ *
+ * Problem: some touchscreens are sampled very roughly, thus even if
+ * you hold the pen still, the samples can differ, sometimes substantially.
+ * The worst happens when electric noise during sampling causes the result
+ * to be substantially different from the real pen position; this causes
+ * the mouse cursor to suddenly "jump" and then return back.
+ *
+ * Solution: delay sampled data by one timeslot. If we see that the last
+ * sample read differs too much, we mark it as "suspicious". If next sample
+ * read is close to the sample before the "suspicious", the suspicious sample
+ * is dropped, otherwise we consider that a quick pen movement is in progress
+ * and pass through both the "suspicious" sample and the sample after it.
  */
 #include <errno.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 
-#include <stdio.h>
-
 #include "tslib.h"
 #include "tslib-filter.h"
 
-#define NR_LAST        4
-
 struct tslib_variance {
-       struct tslib_module_info        module;
-       int                             nr;
-       unsigned int                    pthreshold;
-       unsigned int                    xlimit;
-       unsigned int                    ylimit;
-       struct ts_sample                last[NR_LAST];
+       struct tslib_module_info module;
+       unsigned int delta;
+        struct ts_sample last;
+        struct ts_sample noise;
+       unsigned int flags;
+#define VAR_PENDOWN            0x00000001
+#define VAR_LASTVALID          0x00000002
+#define VAR_NOISEVALID         0x00000004
+#define VAR_SUBMITNOISE                0x00000008
 };
 
-/*
- * We have 4 complete samples.  Calculate the variance between each,
- * treating X and Y values separately.  Then pick the two with the
- * least variance, and average them.
- */
-static int
-variance_calculate(struct tslib_variance *var, struct ts_sample *samp,
-                  struct ts_sample *s)
+static int sqr (int x)
 {
-       int i, j;
-       int diff_x, min_x, i_x, j_x;
-       int diff_y, min_y, i_y, j_y;
-       int diff_p, min_p, i_p, j_p;
-
-       min_x = INT_MAX;
-       min_y = INT_MAX;
-       min_p = INT_MAX;
-
-       for (i = 0; i < var->nr - 1; i++) {
-               for (j = i + 1; j < var->nr; j++) {
-                       /*
-                        * Calculate the variance between sample 'i'
-                        * and sample 'j'.  X and Y values are treated
-                        * separately.
-                        */
-                       diff_x = var->last[i].x - var->last[j].x;
-                       if (diff_x < 0)
-                               diff_x = -diff_x;
-
-                       diff_y = var->last[i].y - var->last[j].y;
-                       if (diff_y < 0)
-                               diff_y = -diff_y;
-
-                       diff_p = var->last[i].pressure - var->last[j].pressure;
-                       if (diff_p < 0)
-                               diff_p = -diff_p;
-
-                       /*
-                        * Is the variance between any two samples too large?
-                        */
-                       if (diff_x > var->xlimit || diff_y > var->ylimit)
-                               return 0;
-
-                       /*
-                        * Find the minimum X variance.
-                        */
-                       if (min_x > diff_x) {
-                               min_x = diff_x;
-                               i_x = i;
-                               j_x = j;
-                       }
-
-                       /*
-                        * Find the minimum Y variance.
-                        */
-                       if (min_y > diff_y) {
-                               min_y = diff_y;
-                               i_y = i;
-                               j_y = j;
-                       }
-
-                       if (min_p > diff_p) {
-                               min_p = diff_p;
-                               i_p = i;
-                               j_p = j;
-                       }
-               }
-       }
-
-       samp->x          = (var->last[i_x].x + var->last[j_x].x) / 2;
-       samp->y          = (var->last[i_y].y + var->last[j_y].y) / 2;
-       samp->pressure   = (var->last[i_p].pressure + var->last[j_p].pressure) / 2;
-       samp->tv.tv_sec  = s->tv.tv_sec;
-       samp->tv.tv_usec = s->tv.tv_usec;
-
-       return 1;
+       return x * x;
 }
 
 static int variance_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
 {
        struct tslib_variance *var = (struct tslib_variance *)info;
-       struct ts_sample *s;
-       int ret;
-
-       ret = info->next->ops->read(info->next, samp, nr);
-       if (ret >= 0) {
-               int nr = 0;
-
-               for (s = samp; s < samp + ret; s++) {
-                       if (s->pressure < var->pthreshold) {
-                               /*
-                                * Pen was released.  Reset our state and
-                                * pass up the release information.
-                                */
-//                             samp[nr].x = 0;
-//                             samp[nr].y = 0;
-                               samp[nr].pressure = s->pressure;
-                               samp[nr].tv.tv_sec = s->tv.tv_sec;
-                               samp[nr].tv.tv_usec = s->tv.tv_usec;
-
-                               nr++;
-
-                               var->nr = 0;
-                               continue;
-                       } else if (var->nr == -1) {
-                               /*
-                                * Pen was pressed.  Inform upper layers
-                                * immediately.
-                                */
-                               samp[nr] = *s;
-                               nr++;
-                       }
+       struct ts_sample cur;
+       int count = 0, dist;
+
+       while (count < nr) {
+               if (var->flags & VAR_SUBMITNOISE) {
+                       cur = var->noise;
+                       var->flags &= ~VAR_SUBMITNOISE;
+               } else {
+                       if (info->next->ops->read(info->next, &cur, 1) < 1)
+                               return count;
+               }
 
-                       if (var->nr >= 0) {
-                               var->last[var->nr].x = s->x;
-                               var->last[var->nr].y = s->y;
-                               var->last[var->nr].pressure = s->pressure;
+               if (cur.pressure == 0) {
+                       /* Flush the queue immediately when the pen is just
+                        * released, otherwise the previous layer will
+                        * get the pen up notification too late. This 
+                        * will happen if info->next->ops->read() blocks.
+                        */
+                       if (var->flags & VAR_PENDOWN) {
+                               var->flags |= VAR_SUBMITNOISE;
+                               var->noise = cur;
                        }
+                       /* Reset the state machine on pen up events. */
+                       var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
+                       goto acceptsample;
+               } else
+                       var->flags |= VAR_PENDOWN;
+
+               if (!(var->flags & VAR_LASTVALID)) {
+                       var->last = cur;
+                       var->flags |= VAR_LASTVALID;
+                       continue;
+               }
 
-                       var->nr++;
-
-                       if (var->nr == NR_LAST) {
-                               if (variance_calculate(var, samp + nr, s))
-                                       nr++;
-                               var->nr = 0;
-                       }
+               if (var->flags & VAR_PENDOWN) {
+                       /* Compute the distance between last sample and current */
+                       dist = sqr (cur.x - var->last.x) +
+                              sqr (cur.y - var->last.y);
+
+                       if (dist > var->delta) {
+                               /* Do we suspect the previous sample was a noise? */
+                               if (var->flags & VAR_NOISEVALID) {
+                                       /* Two "noises": it's just a quick pen movement */
+                                       samp [count++] = var->last = var->noise;
+                                       var->flags = (var->flags & ~VAR_NOISEVALID) |
+                                               VAR_SUBMITNOISE;
+                               } else
+                                       var->flags |= VAR_NOISEVALID;
+
+                               /* The pen jumped too far, maybe it's a noise ... */
+                               var->noise = cur;
+                               continue;
+                       } else
+                               var->flags &= ~VAR_NOISEVALID;
                }
 
-               ret = nr;
+acceptsample:
+#ifdef DEBUG
+               fprintf(stderr,"VARIANCE----------------> %d %d %d\n",
+                       var->last.x, var->last.y, var->last.pressure);
+#endif
+               samp [count++] = var->last;
+               var->last = cur;
        }
-       return ret;
+
+       return count;
 }
 
 static int variance_fini(struct tslib_module_info *info)
 {
        free(info);
+        return 0;
 }
 
 static const struct tslib_ops variance_ops =
 {
-       read:   variance_read,
-       fini:   variance_fini,
+       .read   = variance_read,
+       .fini   = variance_fini,
 };
 
 static int variance_limit(struct tslib_module_info *inf, char *str, void *data)
@@ -189,15 +145,7 @@ static int variance_limit(struct tslib_module_info *inf, char *str, void *data)
        errno = err;
        switch ((int)data) {
        case 1:
-               var->xlimit = v;
-               break;
-
-       case 2:
-               var->ylimit = v;
-               break;
-
-       case 3:
-               var->pthreshold = v;
+               var->delta = v;
                break;
 
        default:
@@ -208,9 +156,7 @@ static int variance_limit(struct tslib_module_info *inf, char *str, void *data)
 
 static const struct tslib_vars variance_vars[] =
 {
-       { "xlimit",     (void *)1, variance_limit },
-       { "ylimit",     (void *)2, variance_limit },
-       { "pthreshold", (void *)3, variance_limit }
+       { "delta",      (void *)1, variance_limit },
 };
 
 #define NR_VARS (sizeof(variance_vars) / sizeof(variance_vars[0]))
@@ -225,15 +171,15 @@ struct tslib_module_info *mod_init(struct tsdev *dev, const char *params)
 
        var->module.ops = &variance_ops;
 
-       var->nr = -1;
-       var->xlimit = 160;
-       var->ylimit = 160;
-       var->pthreshold = 100;
+       var->delta = 30;
+       var->flags = 0;
 
        if (tslib_parse_vars(&var->module, variance_vars, NR_VARS, params)) {
                free(var);
                return NULL;
        }
 
+        var->delta = sqr (var->delta);
+
        return &var->module;
 }
index 98589b1..be1134d 100644 (file)
@@ -6,10 +6,10 @@
 # This file is placed under the LGPL.  Please see the file
 # COPYING for more details.
 #
-# $Id: Makefile.am,v 1.5 2002/07/08 17:44:28 dlowder Exp $
+# $Id: Makefile.am,v 1.6 2004/07/21 19:12:59 dlowder Exp $
 #
 
-CFLAGS         := $(CFLAGS) -DPLUGIN_DIR=\"@PLUGIN_DIR@\" -DTS_CONF=\"@TS_CONF@\" $(DEBUGFLAGS) $(INPUTAPIFLAG)
+AM_CFLAGS       = -DPLUGIN_DIR=\"@PLUGIN_DIR@\" -DTS_CONF=\"@TS_CONF@\" $(DEBUGFLAGS)
 
 noinst_HEADERS   = tslib-private.h tslib-filter.h
 include_HEADERS  = tslib.h
index 060cdae..b0bb3f6 100644 (file)
@@ -6,10 +6,12 @@
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_attach.c,v 1.1.1.1 2001/12/22 21:12:06 rmk Exp $
+ * $Id: ts_attach.c,v 1.2 2004/07/21 19:12:59 dlowder Exp $
  *
  * Attach a filter to a touchscreen device.
  */
+#include <stdlib.h>
+
 #include "config.h"
 
 #include "tslib-private.h"
@@ -22,3 +24,30 @@ int __ts_attach(struct tsdev *ts, struct tslib_module_info *info)
 
        return 0;
 }
+
+int __ts_attach_raw(struct tsdev *ts, struct tslib_module_info *info)
+{
+       struct tslib_module_info *next, *prev, *prev_list = ts->list_raw;
+       info->dev = ts;
+       info->next = prev_list;
+       ts->list_raw = info;
+
+       /* 
+        * ensure the last item in the normal list now points to the
+        * top of the raw list.
+        */
+
+       if (ts->list == NULL || ts->list == prev_list) { /* main list is empty, ensure it points here */
+               ts->list = info;
+               return 0;
+       }
+
+       next = ts->list;
+       
+       while (next != NULL && next != prev_list)
+               prev = next, next = prev->next;
+
+       prev->next = info;
+
+       return 0;
+}
index 3c9800f..9d221e7 100644 (file)
@@ -6,93 +6,94 @@
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_config.c,v 1.3 2002/07/01 23:02:57 dlowder Exp $
+ * $Id: ts_config.c,v 1.4 2004/07/21 19:12:59 dlowder Exp $
  *
  * Read the configuration and load the appropriate drivers.
  */
 #include "config.h"
+#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "tslib-private.h"
 
-struct opt {
-       const char *str;
-       int (*fn)(struct tsdev *ts, char *rest);
-};
-
-static int ts_opt_module(struct tsdev *ts, char *rest)
-{
-       char *tok = strsep(&rest, " \t");
-
-       return ts_load_module(ts, tok, rest);
-}
-
-static struct opt options[] = {
-       { "module", ts_opt_module },
-};
-
-#define NR_OPTS (sizeof(options) / sizeof(options[0]))
+/* Maximum line size is BUF_SIZE - 2 
+ * -1 for fgets and -1 to test end of line
+ */
+#define BUF_SIZE 512
 
 int ts_config(struct tsdev *ts)
 {
-       char buf[80], *p;
+       char buf[BUF_SIZE], *p;
        FILE *f;
-       int line = 0, ret = 0;
+       int line = 0;
+       int ret;
 
        char *conffile;
 
-       if( (conffile = getenv("TSLIB_CONFFILE")) != NULL) {
-               f = fopen(conffile,"r");
-       } else {
-               f = fopen(TS_CONF, "r");
+       if( (conffile = getenv("TSLIB_CONFFILE")) == NULL) {
+               conffile = strdup (TS_CONF);
        }
-       if (!f)
+
+       f = fopen(conffile, "r");
+       if (!f) {
+               perror("Couldnt open tslib config file");
                return -1;
+       }
 
-       while ((p = fgets(buf, sizeof(buf), f)) != NULL && ret == 0) {
-               struct opt *opt;
-               char *e, *tok;
+       buf[BUF_SIZE - 2] = '\0';
+       while ((p = fgets(buf, BUF_SIZE, f)) != NULL) {
+               char *e;
+               char *tok;
+               char *module_name;
 
                line++;
 
-               /*
-                * Did we read a whole line?
-                */
+               /* Chomp */
                e = strchr(p, '\n');
-               if (!e) {
-                       ts_error("%d: line too long", line);
-                       break;
+               if (e) {
+                       *e = '\0';
                }
 
-               /*
-                * Chomp.
-                */
-               *e = '\0';
+               /* Did we read a whole line? */
+               if (buf[BUF_SIZE - 2] != '\0') {
+                       ts_error("%s: line %d too long\n", conffile, line);
+                       break;
+               }
 
                tok = strsep(&p, " \t");
-
-               /*
-                * Ignore comments or blank lines.
+               
+               /* Ignore comments or blank lines.
+                * Note: strsep modifies p (see man strsep)
                 */
-               if (!tok || *tok == '#')
+
+               if (p==NULL || *tok == '#')
                        continue;
 
-               /*
-                * Search for the option.
-                */
-               for (opt = options; opt < options + NR_OPTS; opt++)
-                       if (strcasecmp(tok, opt->str) == 0) {
-                               ret = opt->fn(ts, p);
-                               break;
-                       }
-
-               if (opt == options + NR_OPTS) {
-                       ts_error("%d: option `%s' not recognised", line, tok);
-                       ret = -1;
+               /* Search for the option. */
+               if (strcasecmp(tok, "module") == 0) {
+                       module_name = strsep(&p, " \t");
+                       ret = ts_load_module(ts, module_name, p);
+               }
+               else if (strcasecmp(tok, "module_raw") == 0) {
+                       module_name = strsep(&p, " \t");
+                       ret = ts_load_module_raw(ts, module_name, p);
+               } else {
+                       ts_error("%s: Unrecognised option %s:%d:%s\n", conffile, line, tok);
+                       break;
+               }
+               if (ret != 0) {
+                       ts_error("Couldnt load module %s\n", module_name);
+                       break;
                }
        }
 
+       if (ts->list_raw == NULL) {
+               ts_error("No raw modules loaded.\n");
+               return -1;
+       }
+
        fclose(f);
 
        return ret;
index 4138eff..a132584 100644 (file)
@@ -6,7 +6,7 @@
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_load_module.c,v 1.2 2002/07/01 23:02:57 dlowder Exp $
+ * $Id: ts_load_module.c,v 1.3 2004/07/21 19:12:59 dlowder Exp $
  *
  * Close a touchscreen device.
  */
@@ -21,7 +21,7 @@
 
 #include "tslib-private.h"
 
-int ts_load_module(struct tsdev *ts, const char *module, const char *params)
+int __ts_load_module(struct tsdev *ts, const char *module, const char *params, int raw)
 {
        struct tslib_module_info * (*init)(struct tsdev *, const char *);
        struct tslib_module_info *info;
@@ -42,6 +42,9 @@ int ts_load_module(struct tsdev *ts, const char *module, const char *params)
        strcat(fn, module);
        strcat(fn, ".so");
 
+#ifdef DEBUG
+       printf ("Loading module %s\n", fn);
+#endif
        handle = dlopen(fn, RTLD_NOW);
        if (!handle)
                return -1;
@@ -60,7 +63,11 @@ int ts_load_module(struct tsdev *ts, const char *module, const char *params)
 
        info->handle = handle;
 
-       ret = __ts_attach(ts, info);
+       if (raw) {
+               ret = __ts_attach_raw(ts, info);
+       } else {
+               ret = __ts_attach(ts, info);
+       }
        if (ret) {
                info->ops->fini(info);
                dlclose(handle);
@@ -68,3 +75,14 @@ int ts_load_module(struct tsdev *ts, const char *module, const char *params)
 
        return ret;
 }
+
+
+int ts_load_module(struct tsdev *ts, const char *module, const char *params)
+{
+       __ts_load_module(ts, module, params, 0);
+}
+
+int ts_load_module_raw(struct tsdev *ts, const char *module, const char *params)
+{
+       __ts_load_module(ts, module, params, 1);
+}
index 4fa9ff4..d8a047b 100644 (file)
@@ -6,7 +6,7 @@
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_open.c,v 1.3 2002/06/17 17:21:43 dlowder Exp $
+ * $Id: ts_open.c,v 1.4 2004/07/21 19:12:59 dlowder Exp $
  *
  * Open a touchscreen device.
  */
@@ -36,40 +36,15 @@ struct tsdev *ts_open(const char *name, int nonblock)
 
        ts = malloc(sizeof(struct tsdev));
        if (ts) {
-#ifdef USE_INPUT_API
-               int version;
-               long bit;
-#endif /* USE_INPUT_API */
-
                memset(ts, 0, sizeof(struct tsdev));
 
                ts->fd = open(name, flags);
                if (ts->fd == -1)
                        goto free;
-
-#ifdef USE_INPUT_API
-               /* make sure we're dealing with a touchscreen device */
-               if (ioctl(ts->fd, EVIOCGVERSION, &version) < 0 ||
-                   version != EV_VERSION ||
-                   ioctl(ts->fd, EVIOCGBIT(0, sizeof(bit)*8), &bit) < 0 ||
-                   !(bit & (1 << EV_ABS)) ||
-                   ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(bit)*8), &bit) < 0 ||
-                   !(bit & (1 << ABS_X)) ||
-                   !(bit & (1 << ABS_Y)) ||
-                   !(bit & (1 << ABS_PRESSURE)))
-                       goto close;
-#endif /* USE_INPUT_API */
-
-               __ts_attach(ts, &__ts_raw);
        }
 
        return ts;
 
-#ifdef USE_INPUT_API
-close:
-       close(ts->fd);
-#endif /* USE_INPUT_API */
-
 free:
        free(ts);
        return NULL;
index 22333fd..3918a04 100644 (file)
@@ -6,7 +6,7 @@
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_read.c,v 1.3 2003/03/04 17:09:47 dlowder Exp $
+ * $Id: ts_read.c,v 1.4 2004/07/21 19:12:59 dlowder Exp $
  *
  * Read raw pressure, x, y, and timestamp from a touchscreen device.
  */
@@ -40,7 +40,8 @@ int ts_read(struct tsdev *ts, struct ts_sample *samp, int nr)
 //             samp[i] = ts_read_private_samples[i];
 //     }
 #ifdef DEBUG
-       fprintf(stderr,"TS_READ----> x = %d, y = %d, pressure = %d\n", samp->x, samp->y, samp->pressure);
+       if (result)
+               fprintf(stderr,"TS_READ----> x = %d, y = %d, pressure = %d\n", samp->x, samp->y, samp->pressure);
 #endif
        return result;
 
index 986f930..6442592 100644 (file)
 /*
  *  tslib/src/ts_read_raw.c
  *
- *  Original version:
- *  Copyright (C) 2001 Russell King.
- *
- *  Rewritten for the Linux input device API:
- *  Copyright (C) 2002 Nicolas Pitre
+ *  Copyright (C) 2003 Chris Larson.
  *
  * This file is placed under the LGPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_read_raw.c,v 1.9 2003/03/05 22:56:37 dlowder Exp $
- *
  * Read raw pressure, x, y, and timestamp from a touchscreen device.
  */
 #include "config.h"
 
-#include <stdio.h>
+#include "tslib-private.h"
 
+#ifdef DEBUG
 #include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
 #endif
-#include <sys/time.h>
-#include <sys/types.h>
-
-#ifdef USE_INPUT_API
-#include <linux/input.h>
-#else
-struct ts_event  {   /* Used in UCB1x00 style touchscreens (the default) */
-       unsigned short pressure;
-       unsigned short x;
-       unsigned short y;
-       unsigned short pad;
-       struct timeval stamp;
-};
-struct h3600_ts_event { /* Used in the Compaq IPAQ */
-       unsigned short pressure;
-       unsigned short x;
-       unsigned short y;
-       unsigned short pad;
-};
-struct mk712_ts_event { /* Used in the Hitachi Webpad */
-       unsigned int header;
-       unsigned int x;
-       unsigned int y;
-       unsigned int reserved;
-};
-struct arctic2_ts_event { /* Used in the IBM Arctic II */
-       signed short pressure;
-       signed int x;
-       signed int y;
-       int millisecs;
-       int flags;
-};
-struct collie_ts_event { /* Used in the Sharp Zaurus SL-5000d and SL-5500 */
-       long y;
-       long x;
-       long pressure;
-       long long millisecs;
-};
-struct corgi_ts_event { /* Used in the Sharp Zaurus SL-C700 */
-       short pressure;
-       short x;
-       short y;
-       short millisecs;
-};
-#endif /* USE_INPUT_API */
-
-#include "tslib-private.h"
 
 int ts_read_raw(struct tsdev *ts, struct ts_sample *samp, int nr)
 {
-#ifdef USE_INPUT_API
-       struct input_event ev;
-#else
-       struct ts_event *evt;
-       struct h3600_ts_event *hevt;
-       struct mk712_ts_event *mevt;
-       struct arctic2_ts_event *aevt;
-       struct collie_ts_event *collie_evt;
-       struct corgi_ts_event *corgi_evt;
-#endif /* USE_INPUT_API */
-       int ret;
-       int total = 0;
-
-       char *tseventtype=NULL;
-       char *defaulttseventtype="UCB1x00";
-
-#ifdef USE_INPUT_API
-       /* warning: maybe those static vars should be part of the tsdev struct? */
-       static int curr_x = 0, curr_y = 0, curr_p = 0;
-       static int got_curr_x = 0, got_curr_y = 0;
-       int got_curr_p = 0;
-       int next_x, next_y;
-       int got_next_x = 0, got_next_y = 0;
-       int got_tstamp = 0;
-
-       while (total < nr) {
-               ret = read(ts->fd, &ev, sizeof(struct input_event));
-               if (ret < sizeof(struct input_event)) break;
-
-               /*
-                * We must filter events here.  We need to look for
-                * a set of input events that will correspond to a
-                * complete ts event.  Also need to be aware that
-                * repeated input events are filtered out by the kernel.
-                * 
-                * We assume the normal sequence is: 
-                * ABS_X -> ABS_Y -> ABS_PRESSURE
-                * If that sequence goes backward then we got a different
-                * ts event.  If some are missing then they didn't change.
-                */
-               if (ev.type == EV_ABS) switch (ev.code) {
-               case ABS_X:
-                       if (!got_curr_x && !got_curr_y) {
-                               got_curr_x = 1;
-                               curr_x = ev.value;
-                       } else {
-                               got_next_x = 1;
-                               next_x = ev.value;
-                       }
-                       break;
-               case ABS_Y:
-                       if (!got_curr_y) {
-                               got_curr_y = 1;
-                               curr_y = ev.value;
-                       } else {
-                               got_next_y = 1;
-                               next_y = ev.value;
-                       }
-                       break;
-               case ABS_PRESSURE:
-                       got_curr_p = 1;
-                       curr_p = ev.value;
-                       break;
-               }
-
-               /* go back if we just got irrelevant events so far */
-               if (!got_curr_x && !got_curr_y && !got_curr_p) continue;
-
-               /* time stamp with the first valid event only */
-               if (!got_tstamp) {
-                       got_tstamp = 1;
-                       samp->tv = ev.time;
-               }
-
-               if ( (!got_curr_x || !got_curr_y) && !got_curr_p &&
-                    !got_next_x && !got_next_y ) {
-                       /*
-                        * The current event is not complete yet.
-                        * Give the kernel a chance to feed us more.
-                        */
-                       struct timeval tv = {0, 0};
-                       fd_set fdset;
-                       FD_ZERO(&fdset);
-                       FD_SET(ts->fd, &fdset);
-                       ret = select(ts->fd+1, &fdset, NULL, NULL, &tv);
-                       if (ret == 1) continue;
-                       if (ret == -1) break;
-               }
-
-               /* We consider having a complete ts event */
-               samp->x = curr_x;
-               samp->y = curr_y;
-               samp->pressure = curr_p;
-#ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-               samp++;
-               total++;
-        
-               /* get ready for next event */
-               if (got_next_x) curr_x = next_x; else got_curr_x = 0;
-               if (got_next_y) curr_y = next_y; else got_curr_y = 0;
-               got_next_x = got_next_y = got_tstamp = 0;
-       }
-
-       if (ret) ret = -1;
-       if (total) ret = total;
-#else
-       tseventtype = getenv("TSLIB_TSEVENTTYPE");
-       if(tseventtype==NULL) tseventtype=defaulttseventtype;
-
-       if( strcmp(tseventtype,"H3600") == 0) { /* iPAQ style h3600 touchscreen events */
-               hevt = alloca(sizeof(*hevt) * nr);
-               ret = read(ts->fd, hevt, sizeof(*hevt) * nr);
-               if(ret > 0) {
-                       int nr = ret / sizeof(*hevt);
-                       while(ret >= sizeof(*hevt)) {
-                               samp->x = hevt->x;
-                               samp->y = hevt->y;
-                               samp->pressure = hevt->pressure;
-#ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-                               gettimeofday(&samp->tv,NULL);
-                               samp++;
-                               hevt++;
-                               ret -= sizeof(*hevt);
-                       }
-               } else {
-                       return -1;
-               }
-       } else if( strcmp(tseventtype,"MK712") == 0) { /* Hitachi Webpad events */
-               mevt = alloca(sizeof(*mevt) * nr);
-               ret = read(ts->fd, mevt, sizeof(*mevt) * nr);
-               if(ret > 0) {
-                       int nr = ret / sizeof(*mevt);
-                       while(ret >= sizeof(*mevt)) {
-                               samp->x = (short)mevt->x;
-                               samp->y = (short)mevt->y;
-                               if(mevt->header==0)
-                                       samp->pressure=1;
-                               else
-                                       samp->pressure=0;
-#ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-                               gettimeofday(&samp->tv,NULL);
-                               samp++;
-                               mevt++;
-                               ret -= sizeof(*mevt);
-                       }
-               } else {
-                       return -1;
-               }
-
-       } else if( strcmp(tseventtype,"ARCTIC2") == 0) { /* IBM Arctic II events */
-               aevt = alloca(sizeof(*aevt) * nr);
-               ret = read(ts->fd, aevt, sizeof(*aevt) * nr);
-               if(ret > 0) {
-                       int nr = ret / sizeof(*aevt);
-                       while(ret >= sizeof(*aevt)) {
-                               samp->x = (short)aevt->x;
-                               samp->y = (short)aevt->y;
-                               samp->pressure = aevt->pressure;
-#ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-                               gettimeofday(&samp->tv,NULL);
-                               samp++;
-                               aevt++;
-                               ret -= sizeof(*aevt);
-                       }
-               } else {
-                       return -1;
-               }
-
-       } else if( strcmp(tseventtype,"COLLIE") == 0) { /* Sharp Zaurus SL-5000d/5500 events */
-               collie_evt = alloca(sizeof(*collie_evt) * nr);
-               ret = read(ts->fd, collie_evt, sizeof(*collie_evt) * nr);
-               if(ret > 0) {
-                       int nr = ret / sizeof(*collie_evt);
-                       while(ret >= sizeof(*collie_evt)) {
-                               samp->x = collie_evt->x;
-                               samp->y = collie_evt->y;
-                               samp->pressure = collie_evt->pressure;
-#ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-                               samp->tv.tv_usec = collie_evt->millisecs % 1000;
-                               samp->tv.tv_sec = collie_evt->millisecs / 1000;
-                               samp++;
-                               collie_evt++;
-                               ret -= sizeof(*collie_evt);
-                       }
-               } else {
-                       return -1;
-               }
-
-       } else if( strcmp(tseventtype,"CORGI") == 0) { /* Sharp Zaurus SL-C700 events */
-               corgi_evt = alloca(sizeof(*corgi_evt) * nr);
-               ret = read(ts->fd, corgi_evt, sizeof(*corgi_evt) * nr);
-               if(ret > 0) {
-                       int nr = ret / sizeof(*corgi_evt);
-                       while(ret >= sizeof(*corgi_evt)) {
-                               samp->x = corgi_evt->x;
-                               samp->y = corgi_evt->y;
-                               samp->pressure = corgi_evt->pressure;
-#ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-                               samp->tv.tv_usec = corgi_evt->millisecs % 1000;
-                               samp->tv.tv_sec = corgi_evt->millisecs / 1000;
-                               samp++;
-                               corgi_evt++;
-                               ret -= sizeof(*corgi_evt);
-                       }
-               } else {
-                       return -1;
-               }
-
-       } else { /* Use normal UCB1x00 type events */
-               evt = alloca(sizeof(*evt) * nr);
-               ret = read(ts->fd, evt, sizeof(*evt) * nr);
-               if(ret > 0) {
-                       int nr = ret / sizeof(*evt);
-                       while(ret >= sizeof(*evt)) {
-                               samp->x = evt->x;
-                               samp->y = evt->y;
-                               samp->pressure = evt->pressure;
+       int result = ts->list_raw->ops->read(ts->list_raw, samp, nr);
 #ifdef DEBUG
-        fprintf(stderr,"RAW---------------------------> %d %d %d\n",samp->x,samp->y,samp->pressure);
-#endif /*DEBUG*/
-                               samp->tv.tv_usec = evt->stamp.tv_usec;
-                               samp->tv.tv_sec = evt->stamp.tv_sec;
-                               samp++;
-                               evt++;
-                               ret -= sizeof(*evt);
-                       }
-               } else {
-                       return -1;
-               }
-       }
-       ret = nr;
-#endif /* USE_INPUT_API */
-
-       return ret;
-}
-
-static int __ts_read_raw(struct tslib_module_info *inf, struct ts_sample *samp, int nr)
-{
-       return ts_read_raw(inf->dev, samp, nr);
+       fprintf(stderr,"TS_READ_RAW----> x = %d, y = %d, pressure = %d\n", samp->x, samp->y, samp->pressure);
+#endif
+       return result;
 }
-
-static const struct tslib_ops __ts_raw_ops =
-{
-       read:   __ts_read_raw,
-};
-
-struct tslib_module_info __ts_raw =
-{
-       next:   NULL,
-       ops:    &__ts_raw_ops,
-};
index 676e573..4e94dd3 100644 (file)
@@ -7,7 +7,7 @@
  *
  * This file is placed under the LGPL.
  *
- * $Id: tslib-private.h,v 1.2 2002/06/17 17:21:43 dlowder Exp $
+ * $Id: tslib-private.h,v 1.3 2004/07/21 19:12:59 dlowder Exp $
  *
  * Internal touch screen library definitions.
  */
@@ -21,10 +21,15 @@ extern "C" {
 struct tsdev {
        int fd;
        struct tslib_module_info *list;
+       struct tslib_module_info *list_raw; /* points to position in 'list' where raw reads
+                                              come from.  default is the position of the
+                                              ts_read_raw module. */
 };
 
 int __ts_attach(struct tsdev *ts, struct tslib_module_info *info);
+int __ts_attach_raw(struct tsdev *ts, struct tslib_module_info *info);
 int ts_load_module(struct tsdev *dev, const char *module, const char *params);
+int ts_load_module_raw(struct tsdev *dev, const char *module, const char *params);
 int ts_error(const char *fmt, ...);
 
 #ifdef __cplusplus
index 3d2a869..e9e68b4 100644 (file)
@@ -7,7 +7,7 @@
  *
  * This file is placed under the LGPL.
  *
- * $Id: tslib.h,v 1.2 2002/06/17 17:21:43 dlowder Exp $
+ * $Id: tslib.h,v 1.3 2004/07/21 19:12:59 dlowder Exp $
  *
  * Touch screen library interface definitions.
  */
@@ -43,7 +43,6 @@ extern int (*ts_error_fn)(const char *fmt, va_list ap);
 
 /*
  * Returns the file descriptor in use for the touchscreen device.
- * (not currently implemented)
  */
 int ts_fd(struct tsdev *);
 
index 2b714cc..8308a45 100644 (file)
@@ -6,15 +6,15 @@
 # This file is placed under the LGPL.  Please see the file
 # COPYING for more details.
 #
-# $Id: Makefile.am,v 1.3 2002/08/29 20:40:09 dlowder Exp $
+# $Id: Makefile.am,v 1.4 2004/07/21 19:12:59 dlowder Exp $
 #
 
-CFLAGS                  :=  $(CFLAGS) $(DEBUGFLAGS) $(INPUTAPIFLAG)
+AM_CFLAGS               = $(DEBUGFLAGS)
 INCLUDES               = -I$(top_srcdir)/src
 
-bin_PROGRAMS           = ts_test ts_calibrate ts_print ts_print_raw
+bin_PROGRAMS           = ts_test ts_calibrate ts_print ts_print_raw ts_harvest
 
-ts_test_SOURCES                = ts_test.c fbutils.c font_8x8.c font_8x16.c
+ts_test_SOURCES                = ts_test.c fbutils.c fbutils.h font_8x8.c font_8x16.c font.h
 ts_test_LDADD          = $(top_builddir)/src/libts.la
 
 ts_print_SOURCES       = ts_print.c
@@ -23,5 +23,8 @@ ts_print_LDADD                = $(top_builddir)/src/libts.la
 ts_print_raw_SOURCES   = ts_print_raw.c
 ts_print_raw_LDADD     = $(top_builddir)/src/libts.la
 
-ts_calibrate_SOURCES   = ts_calibrate.c fbutils.c font_8x8.c font_8x16.c
+ts_calibrate_SOURCES   = ts_calibrate.c fbutils.c fbutils.h testutils.c testutils.h font_8x8.c font_8x16.c font.h
 ts_calibrate_LDADD     = $(top_builddir)/src/libts.la
+
+ts_harvest_SOURCES     = ts_harvest.c fbutils.c fbutils.h testutils.c testutils.h font_8x8.c font_8x16.c font.h
+ts_harvest_LDADD               = $(top_builddir)/src/libts.la
index c57ea3a..26d3a3d 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <sys/fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/time.h>
-#include <linux/fb.h>
-#include <linux/kd.h>
+
 #include <linux/vt.h>
+#include <linux/kd.h>
+#include <linux/fb.h>
 
 #include "font.h"
+#include "fbutils.h"
+
+union multiptr {
+       unsigned char *p8;
+       unsigned short *p16;
+       unsigned long *p32;
+};
 
 static int con_fd, fb_fd, last_vt = -1;
 static struct fb_fix_screeninfo fix;
 static struct fb_var_screeninfo var;
-static struct fb_cmap cmap;
-static char *fbuffer;
+static unsigned char *fbuffer;
+static unsigned char **line_addr;
 static int fb_fd=0;
+static int bytes_per_pixel;
+static unsigned colormap [256];
 int xres, yres;
 
 static char *defaultfbdevice = "/dev/fb0";
@@ -39,26 +51,26 @@ static char *consoledevice = NULL;
 
 int open_framebuffer(void)
 {
-        struct vt_stat vts;
-        char vtname[128];
-        int fd, nr;
-       unsigned short col[2];
+       struct vt_stat vts;
+       char vtname[128];
+       int fd, nr;
+       unsigned y, addr;
 
-       if( (fbdevice = getenv("TSLIB_FBDEVICE")) == NULL)
+       if ((fbdevice = getenv ("TSLIB_FBDEVICE")) == NULL)
                fbdevice = defaultfbdevice;
 
-       if( (consoledevice = getenv("TSLIB_CONSOLEDEVICE")) == NULL)
+       if ((consoledevice = getenv ("TSLIB_CONSOLEDEVICE")) == NULL)
                consoledevice = defaultconsoledevice;
 
-       if(strcmp(consoledevice,"none")!=0) {
-               sprintf(vtname,"%s%d", consoledevice, 1);
-               fd = open(vtname, O_WRONLY);
+       if (strcmp (consoledevice, "none") != 0) {
+               sprintf (vtname,"%s%d", consoledevice, 1);
+               fd = open (vtname, O_WRONLY);
                if (fd < 0) {
                        perror("open consoledevice");
                        return -1;
                }
 
-               if (ioctl(fd, VT_OPENQRY, &nr) < 0) {
+               if (ioctl(fd, VT_OPENQRY, &nr) < 0) {
                        perror("ioctl VT_OPENQRY");
                        return -1;
                }
@@ -115,32 +127,20 @@ int open_framebuffer(void)
        xres = var.xres;
        yres = var.yres;
 
-       cmap.start = 0;
-       cmap.len = 2;
-       cmap.red = col;
-       cmap.green = col;
-       cmap.blue = col;
-       cmap.transp = NULL;
-
-       col[0] = 0;
-       col[1] = 0xffff;
-
-       if(var.bits_per_pixel==8) {
-               if (ioctl(fb_fd, FBIOPUTCMAP, &cmap) < 0) {
-                       perror("ioctl FBIOPUTCMAP");
-                       close(fb_fd);
-                       return -1;
-               }
-       }
-
        fbuffer = mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fb_fd, 0);
-       if (fbuffer == (char *)-1) {
+       if (fbuffer == (unsigned char *)-1) {
                perror("mmap framebuffer");
                close(fb_fd);
                return -1;
        }
        memset(fbuffer,0,fix.smem_len);
 
+       bytes_per_pixel = (var.bits_per_pixel + 7) / 8;
+       line_addr = malloc (sizeof (unsigned) * var.yres_virtual);
+       addr = 0;
+       for (y = 0; y < var.yres_virtual; y++, addr += fix.line_length)
+               line_addr [y] = fbuffer + addr;
+
        return 0;
 }
 
@@ -161,135 +161,231 @@ void close_framebuffer(void)
 
                close(con_fd);
        }
+
+        free (line_addr);
 }
 
-void put_cross(int x, int y, int c)
+void put_cross(int x, int y, unsigned colidx)
 {
-       int off, i, s, e, loc;
-
-       if (x < 0) x = 0;
-       if (y < 0) y = 0;
-       if (x >= var.xres) x = var.xres - 1;
-       if (y >= var.yres) y = var.yres - 1;
-
-       s = x - 10;
-       if(s<0) s=0;
-       e = x + 10;
-       if(e>var.xres) e= var.xres;
-       for(i=s;i<e;i++) {
-               loc = (i + var.xoffset)*(var.bits_per_pixel/8)
-                       + (y + var.yoffset)*fix.line_length;
-               switch(var.bits_per_pixel) {
-                       case 8:
-                       default:
-                               //fbuffer[loc] = c;
-                               fbuffer[loc] = fbuffer[loc] ? 0 : 1;
-                               break;
-                       case 16:
-                               *((unsigned short *)(fbuffer + loc)) = *((unsigned short *)(fbuffer + loc)) ? 0 : 0xffff;
-                               break;
-                       case 24:
-                       case 32:
-                               *((unsigned int *)(fbuffer + loc)) = *((unsigned int *)(fbuffer + loc)) ? 0 : 0xffffffff;
-                               break;
-               }
-       }
-       s = y - 10;
-       if(s<0) s=0;
-       e = y + 10;
-       if(e>var.yres) e = var.yres;
-       for(i=s;i<e;i++) {
-               loc = (x + var.xoffset)*(var.bits_per_pixel/8)
-                       + (i + var.yoffset)*fix.line_length;
-               switch(var.bits_per_pixel) {
-                       case 8:
-                       default:
-                               //fbuffer[loc] = c;
-                               fbuffer[loc] = fbuffer[loc] ? 0 : 1;
-                               break;
-                       case 16:
-                               *((unsigned short *)(fbuffer + loc)) = *((unsigned short *)(fbuffer + loc)) ? 0 : 0xffff;
-                               break;
-                       case 24:
-                       case 32:
-                               *((unsigned int *)(fbuffer + loc)) = *((unsigned int *)(fbuffer + loc)) ? 0 : 0xffffffff;
-                               break;
-               }
+       line (x - 10, y, x - 2, y, colidx);
+       line (x + 2, y, x + 10, y, colidx);
+       line (x, y - 10, x, y - 2, colidx);
+       line (x, y + 2, x, y + 10, colidx);
+
+#if 1
+       line (x - 6, y - 9, x - 9, y - 9, colidx + 1);
+       line (x - 9, y - 8, x - 9, y - 6, colidx + 1);
+       line (x - 9, y + 6, x - 9, y + 9, colidx + 1);
+       line (x - 8, y + 9, x - 6, y + 9, colidx + 1);
+       line (x + 6, y + 9, x + 9, y + 9, colidx + 1);
+       line (x + 9, y + 8, x + 9, y + 6, colidx + 1);
+       line (x + 9, y - 6, x + 9, y - 9, colidx + 1);
+       line (x + 8, y - 9, x + 6, y - 9, colidx + 1);
+#else
+       line (x - 7, y - 7, x - 4, y - 4, colidx + 1);
+       line (x - 7, y + 7, x - 4, y + 4, colidx + 1);
+       line (x + 4, y - 4, x + 7, y - 7, colidx + 1);
+       line (x + 4, y + 4, x + 7, y + 7, colidx + 1);
+#endif
+}
+
+void put_char(int x, int y, int c, int colidx)
+{
+       int i,j,bits;
+
+       for (i = 0; i < font_vga_8x8.height; i++) {
+               bits = font_vga_8x8.data [font_vga_8x8.height * c + i];
+               for (j = 0; j < font_vga_8x8.width; j++, bits <<= 1)
+                       if (bits & 0x80)
+                               pixel (x + j, y + i, colidx);
        }
-       return;
 }
 
-void put_char(int x, int y, int c, int color)
+void put_string(int x, int y, char *s, unsigned colidx)
 {
-       int i,j,bits,loc;
-
-       for(i=0;i<font_vga_8x8.height;i++) {
-               bits = font_vga_8x8.data[font_vga_8x8.height*c + i];
-               for(j=0;j<8;j++) {
-                       loc = (x + j + var.xoffset)*(var.bits_per_pixel/8)
-                               + (y + i + var.yoffset)*fix.line_length;
-                       if(loc>=0 && loc<fix.smem_len && ((bits >> (7-j)) & 1)) {
-                               switch(var.bits_per_pixel) {
-                                       case 8:
-                                       default:
-                                               if(color==0)
-                                                       fbuffer[loc] = 0;
-                                               else
-                                                       fbuffer[loc] = 1;
-                                               break;
-                                       case 16:
-                                               if(color==0)
-                                                       *((unsigned short *)(fbuffer + loc)) = 0;
-                                               else
-                                                       *((unsigned short *)(fbuffer + loc)) = 0xffff;
-                                               break;
-                                       case 24:
-                                       case 32:
-                                               if(color==0)
-                                                       *((unsigned int *)(fbuffer + loc)) = 0;
-                                               else
-                                                       *((unsigned int *)(fbuffer + loc)) = 0xffffffff;
-                                               break;
-                               }
-                       }       
-               }
+       int i;
+       for (i = 0; *s; i++, x += font_vga_8x8.width, s++)
+               put_char (x, y, *s, colidx);
+}
+
+void put_string_center(int x, int y, char *s, unsigned colidx)
+{
+       size_t sl = strlen (s);
+        put_string (x - (sl / 2) * font_vga_8x8.width,
+                    y - font_vga_8x8.height / 2, s, colidx);
+}
+
+void setcolor(unsigned colidx, unsigned value)
+{
+       unsigned res;
+       unsigned short red, green, blue;
+       struct fb_cmap cmap;
+
+#ifdef DEBUG
+       if (colidx > 255) {
+               fprintf (stderr, "WARNING: color index = %u, must be <256\n",
+                        colidx);
+               return;
+       }
+#endif
+
+       switch (bytes_per_pixel) {
+       default:
+       case 1:
+               res = colidx;
+               red = (value >> 8) & 0xff00;
+               green = value & 0xff00;
+               blue = (value << 8) & 0xff00;
+               cmap.start = colidx;
+               cmap.len = 1;
+               cmap.red = &red;
+               cmap.green = &green;
+               cmap.blue = &blue;
+               cmap.transp = NULL;
+
+               if (ioctl (fb_fd, FBIOPUTCMAP, &cmap) < 0)
+                       perror("ioctl FBIOPUTCMAP");
+               break;
+       case 2:
+       case 4:
+               red = (value >> 16) & 0xff;
+               green = (value >> 8) & 0xff;
+               blue = value & 0xff;
+               res = ((red >> (8 - var.red.length)) << var.red.offset) |
+                      ((green >> (8 - var.green.length)) << var.green.offset) |
+                      ((blue >> (8 - var.blue.length)) << var.blue.offset);
        }
+        colormap [colidx] = res;
 }
-               
 
+static inline void __setpixel (union multiptr loc, unsigned xormode, unsigned color)
+{
+       switch(bytes_per_pixel) {
+       case 1:
+       default:
+               if (xormode)
+                       *loc.p8 ^= color;
+               else
+                       *loc.p8 = color;
+               break;
+       case 2:
+               if (xormode)
+                       *loc.p16 ^= color;
+               else
+                       *loc.p16 = color;
+               break;
+       case 4:
+               if (xormode)
+                       *loc.p32 ^= color;
+               else
+                       *loc.p32 = color;
+               break;
+       }
+}
 
-void put_string(int x, int y, char *s, int color)
+void pixel (int x, int y, unsigned colidx)
 {
-       int i;
-       for(i=0;i<strlen(s);i++) {
-               put_char( (x + font_vga_8x8.width* (i - strlen(s)/2)), y, s[i], color);
+       unsigned xormode;
+       union multiptr loc;
+
+       if ((x < 0) || (x >= var.xres_virtual) ||
+           (y < 0) || (y >= var.yres_virtual))
+               return;
+
+       xormode = colidx & XORMODE;
+       colidx &= ~XORMODE;
+
+#ifdef DEBUG
+       if (colidx > 255) {
+               fprintf (stderr, "WARNING: color value = %u, must be <256\n",
+                        colidx);
+               return;
        }
+#endif
+
+       loc.p8 = line_addr [y] + x * bytes_per_pixel;
+       __setpixel (loc, xormode, colormap [colidx]);
 }
 
-void setcolors(int bgcolor, int fgcolor) {
-/* No longer implemented
-       unsigned short red[2], green[2], blue[2];
-
-       red[0] = ( (bgcolor >> 16) & 0xff ) << 8;
-       red[1] = ( (fgcolor >> 16) & 0xff ) << 8;
-       green[0] = ( (bgcolor >> 8) & 0xff ) << 8;
-       green[1] = ( (fgcolor >> 8) & 0xff ) << 8;
-       blue[0] = ( bgcolor & 0xff ) << 8;
-       blue[1] = ( fgcolor & 0xff ) << 8;
-        cmap.start = 0;
-        cmap.len = 2;
-        cmap.red = red;
-        cmap.green = green;
-        cmap.blue = blue;
-        cmap.transp = NULL;
-
-       if(var.bits_per_pixel==8) {
-               if (ioctl(fb_fd, FBIOPUTCMAP, &cmap) < 0) {
-                       perror("ioctl FBIOPUTCMAP");
-                       close(fb_fd);
+void line (int x1, int y1, int x2, int y2, unsigned colidx)
+{
+       int tmp;
+       int dx = x2 - x1;
+       int dy = y2 - y1;
+
+       if (abs (dx) < abs (dy)) {
+               if (y1 > y2) {
+                       tmp = x1; x1 = x2; x2 = tmp;
+                       tmp = y1; y1 = y2; y2 = tmp;
+                       dx = -dx; dy = -dy;
+               }
+               x1 <<= 16;
+               /* dy is apriori >0 */
+               dx = (dx << 16) / dy;
+               while (y1 <= y2) {
+                       pixel (x1 >> 16, y1, colidx);
+                       x1 += dx;
+                       y1++;
+               }
+       } else {
+               if (x1 > x2) {
+                       tmp = x1; x1 = x2; x2 = tmp;
+                       tmp = y1; y1 = y2; y2 = tmp;
+                       dx = -dx; dy = -dy;
+               }
+               y1 <<= 16;
+               dy = dx ? (dy << 16) / dx : 0;
+               while (x1 <= x2) {
+                       pixel (x1, y1 >> 16, colidx);
+                       y1 += dy;
+                       x1++;
                }
        }
-*/
 }
 
+void rect (int x1, int y1, int x2, int y2, unsigned colidx)
+{
+       line (x1, y1, x2, y1, colidx);
+       line (x2, y1, x2, y2, colidx);
+       line (x2, y2, x1, y2, colidx);
+       line (x1, y2, x1, y1, colidx);
+}
+
+void fillrect (int x1, int y1, int x2, int y2, unsigned colidx)
+{
+       int tmp;
+       unsigned xormode;
+       union multiptr loc;
+
+       /* Clipping and sanity checking */
+       if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; }
+       if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; }
+       if (x1 < 0) x1 = 0; if (x1 >= xres) x1 = xres - 1;
+       if (x2 < 0) x2 = 0; if (x2 >= xres) x2 = xres - 1;
+       if (y1 < 0) y1 = 0; if (y1 >= yres) y1 = yres - 1;
+       if (y2 < 0) y2 = 0; if (y2 >= yres) y2 = yres - 1;
+
+       if ((x1 > x2) || (y1 > y2))
+               return;
+
+       xormode = colidx & XORMODE;
+       colidx &= ~XORMODE;
+
+#ifdef DEBUG
+       if (colidx > 255) {
+               fprintf (stderr, "WARNING: color value = %u, must be <256\n",
+                        colidx);
+               return;
+       }
+#endif
+
+       colidx = colormap [colidx];
 
+       for (; y1 <= y2; y1++) {
+               loc.p8 = line_addr [y1] + x1 * bytes_per_pixel;
+               for (tmp = x1; tmp <= x2; tmp++) {
+                       __setpixel (loc, xormode, colidx);
+                       loc.p8 += bytes_per_pixel;
+               }
+       }
+}
index a315928..0656ea6 100644 (file)
  *
  */
 
+#ifndef _FBUTILS_H
+#define _FBUTILS_H
+
+/* This constant, being ORed with the color index tells the library
+ * to draw in exclusive-or mode (that is, drawing the same second time
+ * in the same place will remove the element leaving the background intact).
+ */
+#define XORMODE        0x80000000
+
 extern int xres, yres;
 
 int open_framebuffer(void);
 void close_framebuffer(void);
-void put_cross(int x, int y, int c);
-void put_string(int x, int y, char *s, int color);
-void setcolors(int bgcolor, int fgcolor);
+void setcolor(unsigned colidx, unsigned value);
+void put_cross(int x, int y, unsigned colidx);
+void put_string(int x, int y, char *s, unsigned colidx);
+void put_string_center(int x, int y, char *s, unsigned colidx);
+void pixel (int x, int y, unsigned colidx);
+void line (int x1, int y1, int x2, int y2, unsigned colidx);
+void rect (int x1, int y1, int x2, int y2, unsigned colidx);
+void fillrect (int x1, int y1, int x2, int y2, unsigned colidx);
+
+#endif /* _FBUTILS_H */
index 77a3e23..1b024b6 100644 (file)
@@ -6,7 +6,7 @@
  * This file is placed under the GPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_calibrate.c,v 1.6 2002/11/08 23:28:55 dlowder Exp $
+ * $Id: ts_calibrate.c,v 1.7 2004/07/21 19:12:59 dlowder Exp $
  *
  * Basic test program for touchscreen library.
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <string.h>
+#include <unistd.h>
 #include <sys/fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/time.h>
-#include <linux/fb.h>
 #include <linux/kd.h>
 #include <linux/vt.h>
+#include <linux/fb.h>
 
 #include "tslib.h"
 
 #include "fbutils.h"
+#include "testutils.h"
+
+static int palette [] =
+{
+       0x000000, 0xffe080, 0xffffff, 0xe0c0a0
+};
+#define NR_COLORS (sizeof (palette) / sizeof (palette [0]))
 
 typedef struct {
        int x[5], xfb[5];
@@ -35,82 +44,11 @@ typedef struct {
 
 static void sig(int sig)
 {
-       close_framebuffer();
-       fflush(stderr);
-       printf("signal %d caught\n", sig);
-       fflush(stdout);
-       exit(1);
-}
-
-static int sort_by_x(const void* a, const void *b)
-{
-       return (((struct ts_sample *)a)->x - ((struct ts_sample *)b)->x);
-}
-static int sort_by_y(const void* a, const void *b)
-{
-       return (((struct ts_sample *)a)->y - ((struct ts_sample *)b)->y);
-}
-static int getxy(struct tsdev *ts, int *x, int *y)
-{
-#define MAX_SAMPLES 128
-       struct ts_sample samp[MAX_SAMPLES];
-       int index, middle;
-
-       /* Read until we get a touch. */
-       do {
-               if (ts_read_raw(ts, &samp[0], 1) < 0) {
-                       perror("ts_read");
-                       close_framebuffer();
-                       exit(1);
-               }
-       } while (samp[0].pressure == 0);
-
-       /* Now collect up to MAX_SAMPLES touches into the samp array. */
-       index = 0;
-       do {
-               if (index < MAX_SAMPLES-1)
-                       index++;
-               if (ts_read_raw(ts, &samp[index], 1) < 0) {
-                       perror("ts_read");
-                       close_framebuffer();
-                       exit(1);
-               }
-       } while (samp[index].pressure > 0);
-       printf("Took %d samples...\n",index);
-
-       /*
-        * At this point, we have samples in indices zero to (index-1)
-        * which means that we have (index) number of samples.  We want
-        * to calculate the median of the samples so that wild outliers
-        * don't skew the result.  First off, let's assume that arrays
-        * are one-based instead of zero-based.  If this were the case
-        * and index was odd, we would need sample number ((index+1)/2)
-        * of a sorted array; if index was even, we would need the
-        * average of sample number (index/2) and sample number
-        * ((index/2)+1).  To turn this into something useful for the
-        * real world, we just need to subtract one off of the sample
-        * numbers.  So for when index is odd, we need sample number
-        * (((index+1)/2)-1).  Due to integer division truncation, we
-        * can simplify this to just (index/2).  When index is even, we
-        * need the average of sample number ((index/2)-1) and sample
-        * number (index/2).  Calculate (index/2) now and we'll handle
-        * the even odd stuff after we sort.
-        */
-       middle = index/2;
-       if (x) {
-               qsort(samp, index, sizeof(struct ts_sample), sort_by_x);
-               if (index & 1)
-                       *x = samp[middle].x;
-               else
-                       *x = (samp[middle-1].x + samp[middle].x) / 2;
-       }
-       if (x) {
-               qsort(samp, index, sizeof(struct ts_sample), sort_by_y);
-               if (index & 1)
-                       *y = samp[middle].y;
-               else
-                       *y = (samp[middle-1].y + samp[middle].y) / 2;
-       }
+       close_framebuffer ();
+       fflush (stderr);
+       printf ("signal %d caught\n", sig);
+       fflush (stdout);
+       exit (1);
 }
 
 int perform_calibration(calibration *cal) {
@@ -193,10 +131,40 @@ int perform_calibration(calibration *cal) {
 
 }
 
+static void get_sample (struct tsdev *ts, calibration *cal,
+                       int index, int x, int y, char *name)
+{
+       static int last_x = -1, last_y;
+
+       if (last_x != -1) {
+#define NR_STEPS 10
+               int dx = ((x - last_x) << 16) / NR_STEPS;
+               int dy = ((y - last_y) << 16) / NR_STEPS;
+               int i;
+               last_x <<= 16;
+               last_y <<= 16;
+               for (i = 0; i < NR_STEPS; i++) {
+                       put_cross (last_x >> 16, last_y >> 16, 2 | XORMODE);
+                       usleep (1000);
+                       put_cross (last_x >> 16, last_y >> 16, 2 | XORMODE);
+                       last_x += dx;
+                       last_y += dy;
+               }
+       }
+
+       put_cross(x, y, 2 | XORMODE);
+       getxy (ts, &cal->x [index], &cal->y [index]);
+       put_cross(x, y, 2 | XORMODE);
+
+       last_x = cal->xfb [index] = x;
+       last_y = cal->yfb [index] = y;
+
+       printf("%s : X = %4d Y = %4d\n", name, cal->x [index], cal->y [index]);
+}
+
 int main()
 {
        struct tsdev *ts;
-       int fd;
        calibration cal;
        int cal_fd;
        char cal_buffer[256];
@@ -231,96 +199,46 @@ int main()
                close_framebuffer();
                exit(1);
        }
-       close_framebuffer();
-       if (open_framebuffer()) {
-               close_framebuffer();
-               exit(1);
-       }
 
-       setcolors(0x48ff48,0x880000);
+       for (i = 0; i < NR_COLORS; i++)
+               setcolor (i, palette [i]);
 
-       put_string(xres/2,yres/4,"TSLIB calibration utility",1);
-       put_string(xres/2,yres/4 + 20,"Touch crosshair to calibrate",1);
+       put_string_center (xres / 2, yres / 4,
+                          "TSLIB calibration utility", 1);
+       put_string_center (xres / 2, yres / 4 + 20,
+                          "Touch crosshair to calibrate", 2);
 
-       printf("xres = %d, yres = %d\n",xres,yres);
+       printf("xres = %d, yres = %d\n", xres, yres);
 
 // Read a touchscreen event to clear the buffer
        //getxy(ts, 0, 0);
 
-// Now paint a crosshair on the upper left and start taking calibration
-// data
-       put_cross(50,50,1);
-       getxy(ts, &cal.x[0], &cal.y[0]);
-       put_cross(50,50,0);
-
-       cal.xfb[0] = 50;
-       cal.yfb[0] = 50;
-
-       printf("Top left : X = %4d Y = %4d\n", cal.x[0], cal.y[0]);
-
-       put_cross(xres - 50, 50, 1);
-       getxy(ts, &cal.x[1], &cal.y[1]);
-       put_cross(xres - 50, 50, 0);
-
-       cal.xfb[1] = xres-50;
-       cal.yfb[1] = 50;
+       get_sample (ts, &cal, 0, 50,        50,        "Top left");
+       get_sample (ts, &cal, 1, xres - 50, 50,        "Top right");
+       get_sample (ts, &cal, 2, xres - 50, yres - 50, "Bot right");
+       get_sample (ts, &cal, 3, 50,        yres - 50, "Bot left");
+       get_sample (ts, &cal, 4, xres / 2,  yres / 2,  "Center");
 
-       printf("Top right: X = %4d Y = %4d\n", cal.x[1], cal.y[1]);
-
-       put_cross(xres - 50, yres - 50, 1);
-       getxy(ts, &cal.x[2], &cal.y[2]);
-       put_cross(xres - 50, yres - 50, 0);
-
-       cal.xfb[2] = xres-50;
-       cal.yfb[2] = yres-50;
-
-       printf("Bot right: X = %4d Y = %4d\n", cal.x[2], cal.y[2]);
-
-       put_cross(50, yres - 50, 1);
-       getxy(ts, &cal.x[3], &cal.y[3]);
-       put_cross(50, yres - 50, 0);
-
-       cal.xfb[3] = 50;
-       cal.yfb[3] = yres-50;
-
-       printf("Bot left : X = %4d Y = %4d\n", cal.x[3], cal.y[3]);
-
-       put_cross(xres/2, yres/2, 1);
-       getxy(ts, &cal.x[4], &cal.y[4]);
-       put_cross(xres/2, yres/2, 0);
-
-       cal.xfb[4] = xres/2;
-       cal.yfb[4] = yres/2;
-
-       printf("Middle: X = %4d Y = %4d\n", cal.x[4], cal.y[4]);
-
-       if(perform_calibration(&cal)) {
-               printf("Calibration constants: ");
-               for(i=0;i<7;i++) printf("%d ",cal.a[i]);
+       if (perform_calibration (&cal)) {
+               printf ("Calibration constants: ");
+               for (i = 0; i < 7; i++) printf("%d ", cal.a [i]);
                printf("\n");
-               if(calfile = getenv("TSLIB_CALIBFILE")) != NULL) {
-                       cal_fd = open(calfile,O_CREAT|O_RDWR);
+               if ((calfile = getenv("TSLIB_CALIBFILE")) != NULL) {
+                       cal_fd = open (calfile, O_CREAT | O_RDWR);
                } else {
-                       cal_fd = open("/etc/pointercal",O_CREAT|O_RDWR);
+                       cal_fd = open ("/etc/pointercal", O_CREAT | O_RDWR);
                }
-               sprintf(cal_buffer,"%d %d %d %d %d %d %d",cal.a[1],cal.a[2],cal.a[0],cal.a[4],cal.a[5],cal.a[3],cal.a[6]);
-               write(cal_fd,cal_buffer,strlen(cal_buffer)+1);
-               close(cal_fd);  
+               sprintf (cal_buffer,"%d %d %d %d %d %d %d",
+                        cal.a[1], cal.a[2], cal.a[0],
+                        cal.a[4], cal.a[5], cal.a[3], cal.a[6]);
+               write (cal_fd, cal_buffer, strlen (cal_buffer) + 1);
+               close (cal_fd);
+                i = 0;
        } else {
                printf("Calibration failed.\n");
+               i = -1;
        }
 
-//     while (1) {
-//             struct ts_sample samp;
-//
-//             if (ts_read_raw(ts, &samp, 1) < 0) {
-//                     perror("ts_read");
-//                     exit(1);
-//             }
-//
-//             printf("%ld.%06ld: %6d %6d %6d\n", samp.tv.tv_sec, samp.tv.tv_usec,
-//                     samp.x, samp.y, samp.pressure);
-//     }
        close_framebuffer();
-
+       return i;
 }
index 7aa2708..8881cc9 100644 (file)
@@ -23,7 +23,6 @@
 int main()
 {
        struct tsdev *ts;
-       int x, y;
        char *tsdevice=NULL;
 
         if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
index 773613e..6fe063a 100644 (file)
@@ -23,7 +23,6 @@
 int main()
 {
        struct tsdev *ts;
-       int x, y;
        char *tsdevice=NULL;
 
         if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
index ecb536c..59c3334 100644 (file)
@@ -6,7 +6,7 @@
  * This file is placed under the GPL.  Please see the file
  * COPYING for more details.
  *
- * $Id: ts_test.c,v 1.4 2002/07/01 23:02:58 dlowder Exp $
+ * $Id: ts_test.c,v 1.5 2004/07/21 19:12:59 dlowder Exp $
  *
  * Basic test program for touchscreen library.
  */
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <signal.h>
 #include <sys/fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/time.h>
-#include <linux/fb.h>
-#include <linux/kd.h>
-#include <linux/vt.h>
 
 #include "tslib.h"
 #include "fbutils.h"
 
+static int palette [] =
+{
+       0x000000, 0xffe080, 0xffffff, 0xe0c0a0, 0x304050, 0x80b8c0
+};
+#define NR_COLORS (sizeof (palette) / sizeof (palette [0]))
+
+struct ts_button {
+       int x, y, w, h;
+       char *text;
+       int flags;
+#define BUTTON_ACTIVE 0x00000001
+};
+
+/* [inactive] border fill text [active] border fill text */
+static int button_palette [6] =
+{
+       1, 4, 2,
+       1, 5, 0
+};
+
+#define NR_BUTTONS 2
+static struct ts_button buttons [NR_BUTTONS];
+
 static void sig(int sig)
 {
        close_framebuffer();
@@ -35,10 +56,61 @@ static void sig(int sig)
        exit(1);
 }
 
+static void button_draw (struct ts_button *button)
+{
+       int s = (button->flags & BUTTON_ACTIVE) ? 3 : 0;
+       rect (button->x, button->y, button->x + button->w - 1,
+             button->y + button->h - 1, button_palette [s]);
+       fillrect (button->x + 1, button->y + 1,
+                 button->x + button->w - 2,
+                 button->y + button->h - 2, button_palette [s + 1]);
+       put_string_center (button->x + button->w / 2,
+                          button->y + button->h / 2,
+                          button->text, button_palette [s + 2]);
+}
+
+static int button_handle (struct ts_button *button, struct ts_sample *samp)
+{
+       int inside = (samp->x >= button->x) && (samp->y >= button->y) &&
+               (samp->x < button->x + button->w) &&
+               (samp->y < button->y + button->h);
+
+       if (samp->pressure > 0) {
+               if (inside) {
+                       if (!(button->flags & BUTTON_ACTIVE)) {
+                               button->flags |= BUTTON_ACTIVE;
+                               button_draw (button);
+                       }
+               } else if (button->flags & BUTTON_ACTIVE) {
+                       button->flags &= ~BUTTON_ACTIVE;
+                       button_draw (button);
+               }
+       } else if (button->flags & BUTTON_ACTIVE) {
+               button->flags &= ~BUTTON_ACTIVE;
+               button_draw (button);
+                return 1;
+       }
+
+        return 0;
+}
+
+static void refresh_screen ()
+{
+       int i;
+
+       fillrect (0, 0, xres - 1, yres - 1, 0);
+       put_string_center (xres/2, yres/4,   "TSLIB test program", 1);
+       put_string_center (xres/2, yres/4+20,"Touch screen to move crosshair", 2);
+
+       for (i = 0; i < NR_BUTTONS; i++)
+               button_draw (&buttons [i]);
+}
+
 int main()
 {
        struct tsdev *ts;
-       int x, y;
+       int i, x, y;
+       int mode = 0;
 
        char *tsdevice=NULL;
 
@@ -46,18 +118,18 @@ int main()
        signal(SIGINT, sig);
        signal(SIGTERM, sig);
 
-        if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
-                ts = ts_open(tsdevice,0);
-        } else {
+       if ((tsdevice = getenv("TSLIB_TSDEVICE")) == NULL) {
 #ifdef USE_INPUT_API
-                ts = ts_open("/dev/input/event0", 0);
+               tsdevice = strdup ("/dev/input/event0");
 #else
-                ts = ts_open("/dev/touchscreen/ucb1x00", 0);
+               tsdevice = strdup ("/dev/touchscreen/ucb1x00");
 #endif /* USE_INPUT_API */
         }
 
+       ts = ts_open (tsdevice, 0);
+
        if (!ts) {
-               perror("ts_open");
+               perror (tsdevice);
                exit(1);
        }
 
@@ -70,28 +142,39 @@ int main()
                close_framebuffer();
                exit(1);
        }
-       close_framebuffer();
-       if (open_framebuffer()) {
-               close_framebuffer();
-               exit(1);
-       }
 
        x = xres/2;
        y = yres/2;
 
-       setcolors(0x48ff48,0x880000);
+       for (i = 0; i < NR_COLORS; i++)
+               setcolor (i, palette [i]);
 
-       put_string(xres/2,yres/4,"TSLIB test program",1);
-       put_string(xres/2,yres/4+20,"Touch screen to move crosshair",1);
+       /* Initialize buttons */
+       memset (&buttons, 0, sizeof (buttons));
+       buttons [0].w = buttons [1].w = xres / 4;
+       buttons [0].h = buttons [1].h = 20;
+       buttons [0].x = xres / 4 - buttons [0].w / 2;
+       buttons [1].x = (3 * xres) / 4 - buttons [0].w / 2;
+       buttons [0].y = buttons [1].y = 10;
+       buttons [0].text = "Drag";
+       buttons [1].text = "Draw";
 
-       put_cross(x,y,1);
+       refresh_screen ();
 
        while (1) {
                struct ts_sample samp;
                int ret;
 
+               /* Show the cross */
+               if ((mode & 15) != 1)
+                       put_cross(x, y, 2 | XORMODE);
+
                ret = ts_read(ts, &samp, 1);
 
+               /* Hide it */
+               if ((mode & 15) != 1)
+                       put_cross(x, y, 2 | XORMODE);
+
                if (ret < 0) {
                        perror("ts_read");
                        close_framebuffer();
@@ -101,14 +184,30 @@ int main()
                if (ret != 1)
                        continue;
 
+               for (i = 0; i < NR_BUTTONS; i++)
+                       if (button_handle (&buttons [i], &samp))
+                               switch (i) {
+                               case 0:
+                                       mode = 0;
+                                       refresh_screen ();
+                                       break;
+                               case 1:
+                                       mode = 1;
+                                       refresh_screen ();
+                                       break;
+                               }
+
                printf("%ld.%06ld: %6d %6d %6d\n", samp.tv.tv_sec, samp.tv.tv_usec,
                        samp.x, samp.y, samp.pressure);
 
                if (samp.pressure > 0) {
-                       put_cross(x, y, 0);
+                       if (mode == 0x80000001)
+                               line (x, y, samp.x, samp.y, 2);
                        x = samp.x;
                        y = samp.y;
-                       put_cross(x, y, 1);
-               }
+                       mode |= 0x80000000;
+               } else
+                       mode &= ~0x80000000;
        }
+       close_framebuffer();
 }