diff options
author | Chris Larson <clarson@kergoth.com> | 2004-01-30 06:09:28 +0000 |
---|---|---|
committer | Chris Larson <clarson@kergoth.com> | 2004-01-30 06:09:28 +0000 |
commit | 441c7b32a32c831e43c44b5db49f23e2d95140d2 (patch) | |
tree | babc9aa51040b64a0f3527777cff2a72c2d6e8cd /tslib | |
parent | 847378e2a71e72956f122787b96ff4d6aea65e9f (diff) |
Merge openembedded@openembedded.bkbits.net:packages
into direwolf.itg.ti.com:/home/kergoth/coding/projects/user/oe-metadata/packages
2004/01/30 00:08:43-06:00 ti.com!kergoth
tslib patch cleanup.. making the raw patches, among others, apply on top of the new patch from Andrew Zabolotny.
BKrev: 4019f518rIvSI5i-3tsO1t0-Jg0OFg
Diffstat (limited to 'tslib')
-rw-r--r-- | tslib/tslib.oe | 6 | ||||
-rw-r--r-- | tslib/tslib/doc.patch (renamed from tslib/tslib/configure.patch) | 0 | ||||
-rw-r--r-- | tslib/tslib/pthres.patch | 295 | ||||
-rw-r--r-- | tslib/tslib/raw-hwread.patch (renamed from tslib/tslib/envvar_doc.patch) | 0 | ||||
-rw-r--r-- | tslib/tslib/raw.patch | 923 | ||||
-rw-r--r-- | tslib/tslib/zap.patch | 1684 |
6 files changed, 2905 insertions, 3 deletions
diff --git a/tslib/tslib.oe b/tslib/tslib.oe index 7303fe9fea..cc62df3a0a 100644 --- a/tslib/tslib.oe +++ b/tslib/tslib.oe @@ -5,16 +5,16 @@ RDEPENDS = libc6 SRC_URI = cvs://cvs:@pubcvs.arm.linux.org.uk/mnt/src/cvsroot;module=tslib SRC_URI_append=" file://${FILESDIR}/automake.patch;patch=1" +SRC_URI_append=" file://${FILESDIR}/doc.patch;patch=1" SRC_URI_append=" file://${FILESDIR}/zap.patch;patch=1" SRC_URI_append=" file://${FILESDIR}/pthres.patch;patch=1" +SRC_URI_append=" file://${FILESDIR}/raw.patch;patch=1" +SRC_URI_append=" file://${FILESDIR}/raw-hwread.patch;patch=1" #SRC_URI_append=" file://${FILESDIR}/collie-module.patch;patch=1" -#SRC_URI_append=" file://${FILESDIR}/configure.patch;patch=1" #SRC_URI_append=" file://${FILESDIR}/devfs.patch;patch=1" -#SRC_URI_append=" file://${FILESDIR}/envvar_doc.patch;patch=1" #SRC_URI_append=" file://${FILESDIR}/event1.patch;patch=1" #SRC_URI_append=" file://${FILESDIR}/multievent.patch;patch=1" #SRC_URI_append=" file://${FILESDIR}/pointercal.patch;patch=1" -#SRC_URI_append=" file://${FILESDIR}/raw.patch;patch=1" #SRC_URI_append=" file://${FILESDIR}/ts_calibrate.patch;patch=1" S = ${WORKDIR}/${PN} diff --git a/tslib/tslib/configure.patch b/tslib/tslib/doc.patch index e69de29bb2..e69de29bb2 100644 --- a/tslib/tslib/configure.patch +++ b/tslib/tslib/doc.patch diff --git a/tslib/tslib/pthres.patch b/tslib/tslib/pthres.patch index e69de29bb2..b4bafcbf60 100644 --- a/tslib/tslib/pthres.patch +++ b/tslib/tslib/pthres.patch @@ -0,0 +1,295 @@ + +# +# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher +# + +--- tslib/configure.in~tslib-pthres ++++ tslib/configure.in +@@ -10,6 +10,8 @@ + [ "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") + + AC_MSG_CHECKING(--enable-debug argument) + AC_ARG_ENABLE(debug, [ --enable-debug Enable debug messages from filters [default=no]], +--- tslib/plugins/Makefile.am~tslib-pthres ++++ tslib/plugins/Makefile.am +@@ -19,7 +19,7 @@ + LIBS = + plugindir = $(PLUGIN_DIR) + +-EXTRA_LTLIBRARIES = variance.la dejitter.la linear.la ++EXTRA_LTLIBRARIES = variance.la dejitter.la linear.la pthres.la + plugin_LTLIBRARIES = $(PLUGINS) + + variance_la_SOURCES = variance.c +@@ -30,3 +30,6 @@ + + linear_la_SOURCES = linear.c + linear_la_LDFLAGS = -module $(LTVSN) ++ ++pthres_la_SOURCES = pthres.c ++pthres_la_LDFLAGS = -module $(LTVSN) +--- /dev/null ++++ tslib/plugins/pthres.c +@@ -0,0 +1,157 @@ ++/* ++ * tslib/plugins/pthres.c ++ * ++ * Copyright (C) 2003 Texas Instruments, Inc. ++ * ++ * Based on: ++ * tslib/plugins/linear.c ++ * Copyright (C) 2001 Russell King. ++ * ++ * This file is placed under the LGPL. Please see the file ++ * COPYING for more details. ++ * ++ * Ensure a release is always pressure 0, and that a press is always >=1. ++ */ ++#include <stdlib.h> ++#include <string.h> ++#include <sys/types.h> ++#include <stdio.h> ++#include <unistd.h> ++#include <errno.h> ++#include <limits.h> ++ ++#include "tslib.h" ++#include "tslib-filter.h" ++ ++struct tslib_pthres { ++ struct tslib_module_info module; ++ int pmin; ++ int pmax; ++}; ++ ++static int ++pthres_read(struct tslib_module_info *info, struct ts_sample *samp, int nr) ++{ ++ struct tslib_pthres *p = (struct tslib_pthres *)info; ++ int ret; ++ static int xsave = 0, ysave = 0; ++ static int press = 0; ++ ++ ret = info->next->ops->read(info->next, samp, nr); ++ if (ret >= 0) { ++ int nr = 0, i; ++ struct ts_sample *s; ++ ++ for (s = samp, i = 0; i < ret; i++, s++) { ++ if (s->pressure < p->pmin) { ++ if (press != 0) { ++ /* release */ ++ press = 0; ++ s->pressure = 0; ++ s->x = xsave; ++ s->y = ysave; ++ } else { ++ /* release with no press, outside bounds, dropping */ ++ int left = ret - nr - 1; ++ if (left > 0) { ++ memmove(s, s + 1, left * sizeof(struct ts_sample)); ++ s--; ++ continue; ++ } ++ break; ++ } ++ } else { ++ if (s->pressure > p->pmax) { ++ /* pressure outside bounds, dropping */ ++ int left = ret - nr - 1; ++ if (left > 0) { ++ memmove(s, s + 1, left * sizeof(struct ts_sample)); ++ s--; ++ continue; ++ } ++ break; ++ } ++ /* press */ ++ press = 1; ++ xsave = s->x; ++ ysave = s->y; ++ } ++ nr++; ++ } ++ return nr; ++ } ++ return ret; ++} ++ ++static int pthres_fini(struct tslib_module_info *info) ++{ ++ free(info); ++ return 0; ++} ++ ++static const struct tslib_ops pthres_ops = ++{ ++ read: pthres_read, ++ fini: pthres_fini, ++}; ++ ++static int threshold_vars(struct tslib_module_info *inf, char *str, void *data) ++{ ++ struct tslib_pthres *p = (struct tslib_pthres *)inf; ++ unsigned long v; ++ int err = errno; ++ ++ v = strtoul(str, NULL, 0); ++ ++ if (v == ULONG_MAX && errno == ERANGE) ++ return -1; ++ ++ errno = err; ++ switch ((int)data) { ++ case 0: ++ p->pmin = v; ++ break; ++ ++ case 1: ++ p->pmax = v; ++ break; ++ ++ default: ++ return -1; ++ } ++ return 0; ++} ++ ++ ++static const struct tslib_vars pthres_vars[] = ++{ ++ { "pmin", (void *)0, threshold_vars }, ++ { "pmax", (void *)1, threshold_vars } ++}; ++ ++#define NR_VARS (sizeof(pthres_vars) / sizeof(pthres_vars[0])) ++ ++struct tslib_module_info *mod_init(struct tsdev *dev, const char *params) ++{ ++ ++ struct tslib_pthres *p; ++ ++ p = malloc(sizeof(struct tslib_pthres)); ++ if (p == NULL) ++ return NULL; ++ ++ p->module.ops = &pthres_ops; ++ ++ p->pmin = 1; ++ p->pmax = INT_MAX; ++ ++ /* ++ * Parse the parameters. ++ */ ++ if (tslib_parse_vars(&p->module, pthres_vars, NR_VARS, params)) { ++ free(p); ++ return NULL; ++ } ++ ++ return &p->module; ++} +--- tslib/etc/ts.conf~tslib-pthres ++++ tslib/etc/ts.conf +@@ -1,3 +1,4 @@ +-module variance delta=30 pthreshold=1 +-module dejitter delta=100 pthreshold=1 ++module pthres pmin=1 ++module variance delta=30 ++module dejitter delta=100 + module linear +--- tslib/plugins/variance.c~tslib-pthres ++++ tslib/plugins/variance.c +@@ -33,7 +33,6 @@ + + struct tslib_variance { + struct tslib_module_info module; +- unsigned int pthreshold; + unsigned int delta; + struct ts_sample last; + struct ts_sample noise; +@@ -62,7 +61,7 @@ + } else if (!info->next->ops->read(info->next, &cur, 1)) + return count; + +- if (cur.pressure < var->pthreshold) { ++ 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 +@@ -151,10 +150,6 @@ + var->delta = v; + break; + +- case 2: +- var->pthreshold = v; +- break; +- + default: + return -1; + } +@@ -164,7 +159,6 @@ + static const struct tslib_vars variance_vars[] = + { + { "delta", (void *)1, variance_limit }, +- { "pthreshold", (void *)2, variance_limit } + }; + + #define NR_VARS (sizeof(variance_vars) / sizeof(variance_vars[0])) +@@ -180,7 +174,6 @@ + var->module.ops = &variance_ops; + + var->delta = 30; +- var->pthreshold = 1; + var->flags = 0; + + if (tslib_parse_vars(&var->module, variance_vars, NR_VARS, params)) { +--- tslib/plugins/dejitter.c~tslib-pthres ++++ tslib/plugins/dejitter.c +@@ -63,7 +63,6 @@ + + struct tslib_dejitter { + struct tslib_module_info module; +- unsigned int pthreshold; + unsigned int delta; + unsigned int x; + unsigned int y; +@@ -110,7 +109,7 @@ + + ret = info->next->ops->read(info->next, samp, nr); + for (s = samp; ret > 0; s++, ret--) { +- if (s->pressure < djt->pthreshold) { ++ if (s->pressure == 0) { + /* + * Pen was released. Reset the state and + * forget all history events. +@@ -184,10 +183,6 @@ + djt->delta = v; + break; + +- case 2: +- djt->pthreshold = v; +- break; +- + default: + return -1; + } +@@ -197,7 +192,6 @@ + static const struct tslib_vars dejitter_vars[] = + { + { "delta", (void *)1, dejitter_limit }, +- { "pthreshold", (void *)2, dejitter_limit } + }; + + #define NR_VARS (sizeof(dejitter_vars) / sizeof(dejitter_vars[0])) +@@ -213,7 +207,6 @@ + djt->module.ops = &dejitter_ops; + + djt->delta = 100; +- djt->pthreshold = 1; + djt->head = 0; + + if (tslib_parse_vars(&djt->module, dejitter_vars, NR_VARS, params)) { diff --git a/tslib/tslib/envvar_doc.patch b/tslib/tslib/raw-hwread.patch index e69de29bb2..e69de29bb2 100644 --- a/tslib/tslib/envvar_doc.patch +++ b/tslib/tslib/raw-hwread.patch diff --git a/tslib/tslib/raw.patch b/tslib/tslib/raw.patch index e69de29bb2..8f7f0dffe0 100644 --- a/tslib/tslib/raw.patch +++ b/tslib/tslib/raw.patch @@ -0,0 +1,923 @@ + +# +# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher +# + +--- tslib/src/tslib-private.h~raw ++++ tslib/src/tslib-private.h +@@ -21,6 +21,9 @@ + 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. */ + #ifdef USE_INPUT_API + int current_x; + int current_y; +@@ -29,7 +32,9 @@ + }; + + 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 +--- tslib/src/ts_attach.c~raw ++++ tslib/src/ts_attach.c +@@ -10,6 +10,8 @@ + * + * Attach a filter to a touchscreen device. + */ ++#include <stdlib.h> ++ + #include "config.h" + + #include "tslib-private.h" +@@ -22,3 +24,30 @@ + + 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; ++} +--- tslib/src/ts_config.c~raw ++++ tslib/src/ts_config.c +@@ -11,6 +11,7 @@ + * Read the configuration and load the appropriate drivers. + */ + #include "config.h" ++#include <stdlib.h> + #include <stdio.h> + #include <string.h> + #include <stdlib.h> +@@ -29,8 +30,16 @@ + return ts_load_module(ts, tok, rest); + } + ++static int ts_opt_module_raw(struct tsdev *ts, char *rest) ++{ ++ char *tok = strsep(&rest, " \t"); ++ ++ return ts_load_module_raw(ts, tok, rest); ++} ++ + static struct opt options[] = { + { "module", ts_opt_module }, ++ { "module_raw", ts_opt_module_raw }, + }; + + #define NR_OPTS (sizeof(options) / sizeof(options[0])) +--- tslib/src/ts_load_module.c~raw ++++ tslib/src/ts_load_module.c +@@ -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; +@@ -63,7 +63,11 @@ + + 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); +@@ -71,3 +75,14 @@ + + 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); ++} +--- tslib/src/ts_open.c~raw ++++ tslib/src/ts_open.c +@@ -60,7 +60,7 @@ + goto close; + #endif /* USE_INPUT_API */ + +- __ts_attach(ts, &__ts_raw); ++ __ts_attach_raw(ts, &__ts_raw); + } + + return ts; +--- tslib/src/Makefile.am~raw ++++ tslib/src/Makefile.am +@@ -17,7 +17,7 @@ + lib_LTLIBRARIES = libts.la + libts_la_SOURCES = ts_attach.c ts_close.c ts_config.c ts_error.c \ + ts_fd.c ts_load_module.c ts_open.c ts_parse_vars.c \ +- ts_read.c ts_read_raw.c ++ ts_read.c ts_read_raw.c ts_read_raw_module.c + libts_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -release $(LT_RELEASE) -export-dynamic + libts_la_LIBADD = -ldl +--- tslib/src/ts_read_raw.c~raw ++++ tslib/src/ts_read_raw.c +@@ -1,378 +1,28 @@ + /* + * 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$ +- * + * 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; +- char *tseventtype=NULL; +- char *defaulttseventtype="UCB1x00"; +-#endif /* USE_INPUT_API */ +- int ret; +- int total = 0; +- +-#ifdef USE_INPUT_API +-#ifdef EV_SYN +- /* This version uses EV_SYN */ +- while (total < nr) { +- ret = read(ts->fd, &ev, sizeof(struct input_event)); +- if (ret < sizeof(struct input_event)) { +- total = -1; +- break; +- } +- +- switch (ev.type) { +- case EV_SYN: +- /* Fill out a new complete event */ +- samp->x = ts->current_x; +- samp->y = ts->current_y; +- samp->pressure = ts->current_p; +- samp->tv = ev.time; +-#ifdef DEBUG +- fprintf(stderr,"RAW---------------------> %d %d %d %d.%d\n", +- samp->x, samp->y, samp->pressure, samp->tv.tv_sec, samp->tv.tv_usec); +-#endif /*DEBUG*/ +- samp++; +- total++; +- break; +- case EV_ABS: +- switch (ev.code) { +- case ABS_X: +- ts->current_x = ev.value; +- break; +- case ABS_Y: +- ts->current_y = ev.value; +- break; +- case ABS_PRESSURE: +- ts->current_p = ev.value; +- break; +- } +- break; +- } +- } +- ret = total; +-#else /* This version doesn't use EV_SYN */ +- /* 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; ++ int result = ts->list_raw->ops->read(ts->list, samp, nr); + #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; ++ fprintf(stderr,"TS_READ_RAW----> x = %d, y = %d, pressure = %d\n", samp->x, samp->y, samp->pressure); + #endif +- +-#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; +-#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); ++ 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, +-}; +--- /dev/null ++++ tslib/src/ts_read_raw_module.c +@@ -0,0 +1,374 @@ ++/* ++ * tslib/src/ts_read_raw_module.c ++ * ++ * Original version: ++ * Copyright (C) 2001 Russell King. ++ * ++ * Rewritten for the Linux input device API: ++ * Copyright (C) 2002 Nicolas Pitre ++ * ++ * This file is placed under the LGPL. Please see the file ++ * COPYING for more details. ++ * ++ * $Id$ ++ * ++ * Read raw pressure, x, y, and timestamp from a touchscreen device. ++ */ ++#include "config.h" ++ ++#include <stdio.h> ++ ++#include <stdlib.h> ++#ifdef HAVE_UNISTD_H ++#include <unistd.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" ++ ++static int __ts_read_raw(struct tslib_module_info *inf, struct ts_sample *samp, int nr) ++{ ++ struct tsdev *ts = inf->dev; ++#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; ++ char *tseventtype=NULL; ++ char *defaulttseventtype="UCB1x00"; ++#endif /* USE_INPUT_API */ ++ int ret; ++ int total = 0; ++ ++#ifdef USE_INPUT_API ++#ifdef EV_SYN ++ /* This version uses EV_SYN */ ++ while (total < nr) { ++ ret = read(ts->fd, &ev, sizeof(struct input_event)); ++ if (ret < sizeof(struct input_event)) { ++ total = -1; ++ break; ++ } ++ ++ switch (ev.type) { ++ case EV_SYN: ++ /* Fill out a new complete event */ ++ samp->x = ts->current_x; ++ samp->y = ts->current_y; ++ samp->pressure = ts->current_p; ++ samp->tv = ev.time; ++#ifdef DEBUG ++ fprintf(stderr,"RAW---------------------> %d %d %d %d.%d\n", ++ samp->x, samp->y, samp->pressure, samp->tv.tv_sec, samp->tv.tv_usec); ++#endif /*DEBUG*/ ++ samp++; ++ total++; ++ break; ++ case EV_ABS: ++ switch (ev.code) { ++ case ABS_X: ++ ts->current_x = ev.value; ++ break; ++ case ABS_Y: ++ ts->current_y = ev.value; ++ break; ++ case ABS_PRESSURE: ++ ts->current_p = ev.value; ++ break; ++ } ++ break; ++ } ++ } ++ ret = total; ++#else /* This version doesn't use EV_SYN */ ++ /* 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; ++#endif ++ ++#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; ++#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 const struct tslib_ops __ts_raw_ops = ++{ ++ read: __ts_read_raw, ++}; ++ ++struct tslib_module_info __ts_raw = ++{ ++ next: NULL, ++ ops: &__ts_raw_ops, ++}; diff --git a/tslib/tslib/zap.patch b/tslib/tslib/zap.patch index e69de29bb2..1c57b7b059 100644 --- a/tslib/tslib/zap.patch +++ b/tslib/tslib/zap.patch @@ -0,0 +1,1684 @@ + +# +# Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher +# + +--- tslib/etc/ts.conf~tslib ++++ tslib/etc/ts.conf +@@ -1,3 +1,3 @@ +-module variance xlimit=50 ylimit=50 pthreshold=1 +-module dejitter xdelta=10 ydelta=10 pthreshold=1 ++module variance delta=30 pthreshold=1 ++module dejitter delta=100 pthreshold=1 + module linear +--- tslib/plugins/dejitter.c~tslib ++++ tslib/plugins/dejitter.c +@@ -1,5 +1,5 @@ + /* +- * tslib/plugins/threshold.c ++ * tslib/plugins/dejitter.c + * + * Copyright (C) 2001 Russell King. + * +@@ -8,7 +8,19 @@ + * + * $Id$ + * +- * 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> +@@ -20,74 +32,144 @@ + #include "tslib.h" + #include "tslib-filter.h" + +-#define NR_LAST 4 ++/** ++ * 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. ++ */ + +-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; ++#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 ... */ + }; + +-static int threshold_read(struct tslib_module_info *info, struct ts_sample *samp, int nr) ++struct ts_hist { ++ int x; ++ int y; ++ int p; ++}; ++ ++struct tslib_dejitter { ++ struct tslib_module_info module; ++ unsigned int pthreshold; ++ 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) + { +- struct tslib_threshold *thr = (struct tslib_threshold *)info; ++ 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_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 < djt->pthreshold) { ++ /* ++ * 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; + } ++ } + ++ 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++; + +- samp[nr++] = *s; ++ /* 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 +181,11 @@ + errno = err; + switch ((int)data) { + case 1: +- thr->xdelta = v; ++ djt->delta = v; + break; + + case 2: +- thr->ydelta = v; +- break; +- +- case 3: +- thr->pthreshold = v; ++ djt->pthreshold = v; + break; + + default: +@@ -116,35 +194,33 @@ + 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 }, ++ { "pthreshold", (void *)2, 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->pthreshold = 1; ++ 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; + } +--- tslib/plugins/linear.c~tslib ++++ tslib/plugins/linear.c +@@ -74,6 +74,7 @@ + static int linear_fini(struct tslib_module_info *info) + { + free(info); ++ return 0; + } + + static const struct tslib_ops linear_ops = +@@ -104,7 +105,6 @@ + struct tslib_linear *lin; + struct stat sbuf; + int pcal_fd; +- int a[7]; + char pcalbuf[200]; + int index; + char *tokptr; +--- tslib/plugins/variance.c~tslib ++++ tslib/plugins/variance.c +@@ -8,165 +8,124 @@ + * + * $Id$ + * +- * 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 pthreshold; ++ 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; ++ struct ts_sample cur; ++ int count = 0, dist; + +- nr++; ++ 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)) ++ return count; + +- var->nr = 0; +- continue; +- } else if (var->nr == -1) { +- /* +- * Pen was pressed. Inform upper layers +- * immediately. +- */ +- samp[nr] = *s; +- nr++; ++ if (cur.pressure < var->pthreshold) { ++ /* 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); ++ /* drop the previous event.. the only way to ensure ++ * that this release is communicated in -this- ts_read, ++ * rather than the next -CL */ ++ var->last.pressure = cur.pressure; ++ goto acceptsample; ++ } else ++ var->flags |= VAR_PENDOWN; + +- 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 (!(var->flags & VAR_LASTVALID)) { ++ var->last = cur; ++ var->flags |= VAR_LASTVALID; ++ continue; ++ } + +- var->nr++; ++ 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 (var->nr == NR_LAST) { +- if (variance_calculate(var, samp + nr, s)) +- nr++; +- var->nr = 0; +- } ++ 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 = +@@ -189,14 +148,10 @@ + errno = err; + switch ((int)data) { + case 1: +- var->xlimit = v; ++ var->delta = v; + break; + + case 2: +- var->ylimit = v; +- break; +- +- case 3: + var->pthreshold = v; + break; + +@@ -208,9 +163,8 @@ + + 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 }, ++ { "pthreshold", (void *)2, variance_limit } + }; + + #define NR_VARS (sizeof(variance_vars) / sizeof(variance_vars[0])) +@@ -225,15 +179,16 @@ + + var->module.ops = &variance_ops; + +- var->nr = -1; +- var->xlimit = 160; +- var->ylimit = 160; +- var->pthreshold = 100; ++ var->delta = 30; ++ var->pthreshold = 1; ++ 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; + } +--- tslib/src/ts_config.c~tslib ++++ tslib/src/ts_config.c +@@ -13,6 +13,7 @@ + #include "config.h" + #include <stdio.h> + #include <string.h> ++#include <stdlib.h> + + #include "tslib-private.h" + +--- tslib/src/ts_load_module.c~tslib ++++ tslib/src/ts_load_module.c +@@ -42,6 +42,9 @@ + strcat(fn, module); + strcat(fn, ".so"); + ++#ifdef DEBUG ++ printf ("Loading module %s\n", fn); ++#endif + handle = dlopen(fn, RTLD_NOW); + if (!handle) + return -1; +--- tslib/src/ts_read.c~tslib ++++ tslib/src/ts_read.c +@@ -40,7 +40,8 @@ + // 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~tslib ++++ tslib/src/ts_read_raw.c +@@ -81,14 +81,53 @@ + struct arctic2_ts_event *aevt; + struct collie_ts_event *collie_evt; + struct corgi_ts_event *corgi_evt; ++ char *tseventtype=NULL; ++ char *defaulttseventtype="UCB1x00"; + #endif /* USE_INPUT_API */ + int ret; + int total = 0; + +- char *tseventtype=NULL; +- char *defaulttseventtype="UCB1x00"; +- + #ifdef USE_INPUT_API ++#ifdef EV_SYN ++ /* This version uses EV_SYN */ ++ while (total < nr) { ++ ret = read(ts->fd, &ev, sizeof(struct input_event)); ++ if (ret < sizeof(struct input_event)) { ++ total = -1; ++ break; ++ } ++ ++ switch (ev.type) { ++ case EV_SYN: ++ /* Fill out a new complete event */ ++ samp->x = ts->current_x; ++ samp->y = ts->current_y; ++ samp->pressure = ts->current_p; ++ samp->tv = ev.time; ++#ifdef DEBUG ++ fprintf(stderr,"RAW---------------------> %d %d %d %d.%d\n", ++ samp->x, samp->y, samp->pressure, samp->tv.tv_sec, samp->tv.tv_usec); ++#endif /*DEBUG*/ ++ samp++; ++ total++; ++ break; ++ case EV_ABS: ++ switch (ev.code) { ++ case ABS_X: ++ ts->current_x = ev.value; ++ break; ++ case ABS_Y: ++ ts->current_y = ev.value; ++ break; ++ case ABS_PRESSURE: ++ ts->current_p = ev.value; ++ break; ++ } ++ break; ++ } ++ } ++ ret = total; ++#else /* This version doesn't use EV_SYN */ + /* 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; +@@ -179,6 +218,8 @@ + + if (ret) ret = -1; + if (total) ret = total; ++#endif ++ + #else + tseventtype = getenv("TSLIB_TSEVENTTYPE"); + if(tseventtype==NULL) tseventtype=defaulttseventtype; +--- tslib/src/tslib-private.h~tslib ++++ tslib/src/tslib-private.h +@@ -21,6 +21,11 @@ + struct tsdev { + int fd; + struct tslib_module_info *list; ++#ifdef USE_INPUT_API ++ int current_x; ++ int current_y; ++ int current_p; ++#endif + }; + + int __ts_attach(struct tsdev *ts, struct tslib_module_info *info); +--- tslib/tests/fbutils.c~tslib ++++ tslib/tests/fbutils.c +@@ -14,22 +14,34 @@ + + #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 @@ + + 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 @@ + 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 @@ + + 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; ++ 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 (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; ++#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 ++} + +- 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; +- } ++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; ++ int i; ++ for (i = 0; *s; i++, x += font_vga_8x8.width, s++) ++ put_char (x, y, *s, colidx); ++} + +- 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; +- } +- } +- } +- } ++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; + +-void put_string(int x, int y, char *s, int color) ++#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) + { +- int i; +- for(i=0;i<strlen(s);i++) { +- put_char( (x + font_vga_8x8.width* (i - strlen(s)/2)), y, s[i], 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 setcolors(int bgcolor, int fgcolor) { +-/* No longer implemented +- unsigned short red[2], green[2], blue[2]; ++void pixel (int x, int y, unsigned colidx) ++{ ++ unsigned xormode; ++ union multiptr loc; + +- 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 ((x < 0) || (x >= var.xres_virtual) || ++ (y < 0) || (y >= var.yres_virtual)) ++ return; + +- if(var.bits_per_pixel==8) { +- if (ioctl(fb_fd, FBIOPUTCMAP, &cmap) < 0) { +- perror("ioctl FBIOPUTCMAP"); +- close(fb_fd); ++ 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 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; ++ } ++ } ++} +--- tslib/tests/fbutils.h~tslib ++++ tslib/tests/fbutils.h +@@ -10,10 +10,26 @@ + * + */ + ++#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 */ +--- tslib/tests/ts_calibrate.c~tslib ++++ tslib/tests/ts_calibrate.c +@@ -15,18 +15,26 @@ + #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" + ++static int palette [] = ++{ ++ 0x000000, 0xffe080, 0xffffff, 0xe0c0a0 ++}; ++#define NR_COLORS (sizeof (palette) / sizeof (palette [0])) ++ + typedef struct { + int x[5], xfb[5]; + int y[5], yfb[5]; +@@ -35,22 +43,24 @@ + + static void sig(int sig) + { +- close_framebuffer(); +- fflush(stderr); +- printf("signal %d caught\n", sig); +- fflush(stdout); +- exit(1); ++ 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) ++ ++static void getxy(struct tsdev *ts, int *x, int *y) + { + #define MAX_SAMPLES 128 + struct ts_sample samp[MAX_SAMPLES]; +@@ -104,7 +114,7 @@ + else + *x = (samp[middle-1].x + samp[middle].x) / 2; + } +- if (x) { ++ if (y) { + qsort(samp, index, sizeof(struct ts_sample), sort_by_y); + if (index & 1) + *y = samp[middle].y; +@@ -193,10 +203,40 @@ + + } + ++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 +271,46 @@ + 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; +- +- 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]); ++ 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"); + +- 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; + } +--- tslib/tests/ts_print.c~tslib ++++ tslib/tests/ts_print.c +@@ -23,7 +23,6 @@ + int main() + { + struct tsdev *ts; +- int x, y; + char *tsdevice=NULL; + + if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) { +--- tslib/tests/ts_print_raw.c~tslib ++++ tslib/tests/ts_print_raw.c +@@ -23,7 +23,6 @@ + int main() + { + struct tsdev *ts; +- int x, y; + char *tsdevice=NULL; + + if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) { +--- tslib/tests/ts_test.c~tslib ++++ tslib/tests/ts_test.c +@@ -14,18 +14,39 @@ + + #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 @@ + 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,9 +118,9 @@ + signal(SIGINT, sig); + signal(SIGTERM, sig); + +- if( (tsdevice = getenv("TSLIB_TSDEVICE")) != NULL ) { +- ts = ts_open(tsdevice,0); +- } else { ++ if ((tsdevice = getenv("TSLIB_TSDEVICE")) != NULL) { ++ ts = ts_open(tsdevice,0); ++ } else { + #ifdef USE_INPUT_API + ts = ts_open("/dev/input/event0", 0); + #else +@@ -70,28 +142,37 @@ + 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 */ ++ put_cross(x, y, 2 | XORMODE); ++ + ret = ts_read(ts, &samp, 1); + ++ /* Hide it */ ++ put_cross(x, y, 2 | XORMODE); ++ + if (ret < 0) { + perror("ts_read"); + close_framebuffer(); +@@ -101,14 +182,30 @@ + 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(); + } |