by Chris Larson <kergoth@handhelds.org> and others.
See ChangeLog for all the details.
-Doug Lowder <douglowder@mac.com>
+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.
-$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
=======
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.
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
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
=================
----------------
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
--------------
-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]],
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'
-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
# 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)
/*
- * 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;
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:
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;
}
* 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
*/
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 }
};
struct tslib_linear *lin;
struct stat sbuf;
int pcal_fd;
- int a[7];
char pcalbuf[200];
int index;
char *tokptr;
* 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)
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:
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]))
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;
}
# 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
* 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"
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;
+}
* 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;
* 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.
*/
#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;
strcat(fn, module);
strcat(fn, ".so");
+#ifdef DEBUG
+ printf ("Loading module %s\n", fn);
+#endif
handle = dlopen(fn, RTLD_NOW);
if (!handle)
return -1;
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);
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);
+}
* 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.
*/
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;
* 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.
*/
// 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;
/*
* 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,
-};
*
* 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.
*/
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
*
* 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.
*/
/*
* Returns the file descriptor in use for the touchscreen device.
- * (not currently implemented)
*/
int ts_fd(struct tsdev *);
# 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
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
#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";
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;
}
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;
}
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;
+ }
+ }
+}
*
*/
+#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 */
* 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];
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) {
}
+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];
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;
}
int main()
{
struct tsdev *ts;
- int x, y;
char *tsdevice=NULL;
if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
int main()
{
struct tsdev *ts;
- int x, y;
char *tsdevice=NULL;
if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) {
* 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();
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;
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);
}
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();
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();
}