This patch implements a straight-forward touch screen calibration for
Linux input devices that return absolute coordinates. It can
automagically recalibrate on the fly if it receives a pointer
coordinate that's outside its calibrated area. It reads a static
calibration from the environment. If it recalibrates on the fly, it
writes the new calibration out to a file in /var/run/ in a format that
can be sourced on boot to provide the calibration environment
variables.
Limitations and work to be done:
* Instead of environment variables, it would be nice if the
configuration were instead read from the directfbrc file. (see
tscal_load)
* The display screen width and height are currently read from
environment variables. It'd be nice if it got these values internally
from DirectFB.
* This calibration only supports an orthogonal transformation. That is
to say, it's no help if your touch screen is rotated with respect to
your display screen.
* This calibration information could potentially be provided back to
the kernel using EVIOCSABS (event input/output control set absolute).
As far as I know though, no touch panel driver currently does anything
with these values. It is a convenient inter-process place to store
these values though. Calibration information could also potentially be
pulled from EVIOCGABS, if a calibration utility were to set these
values.
I'd appreciate any comments. Cheers!
Shaun
? inputdrivers/linux_input/tscal.c
? inputdrivers/linux_input/tscal.h
Index: inputdrivers/linux_input/Makefile.am
===================================================================
RCS file: /cvs/directfb/DirectFB/inputdrivers/linux_input/Makefile.am,v
retrieving revision 1.12
diff -u -u -r1.12 Makefile.am
--- inputdrivers/linux_input/Makefile.am 3 Feb 2005 18:38:06 -0000
1.12
+++ inputdrivers/linux_input/Makefile.am 31 Jan 2006 21:36:26 -0000
@@ -17,7 +17,9 @@
libdirectfb_linux_input_la_SOURCES = \
input_fake.h \
- linux_input.c
+ linux_input.c \
+ tscal.c \
+ tscal.h
libdirectfb_linux_input_la_LDFLAGS = \
-export-dynamic \
Index: inputdrivers/linux_input/linux_input.c
===================================================================
RCS file: /cvs/directfb/DirectFB/inputdrivers/linux_input/linux_input.c,v
retrieving revision 1.43
diff -u -u -r1.43 linux_input.c
--- inputdrivers/linux_input/linux_input.c 26 Nov 2005 14:32:26 -0000
1.43
+++ inputdrivers/linux_input/linux_input.c 31 Jan 2006 21:36:27 -0000
@@ -74,6 +74,7 @@
#include <core/input_driver.h>
+#include "tscal.h"
DFB_INPUT_DRIVER( linux_input )
@@ -550,29 +551,34 @@
abs_event( struct input_event *levt,
DFBInputEvent *devt )
{
+ static struct tscal tscal;
+
switch (levt->code) {
case ABS_X:
devt->axis = DIAI_X;
+ devt->axisabs = tscal_scale(&tscal, &tscal.x, levt->value);
break;
case ABS_Y:
devt->axis = DIAI_Y;
+ devt->axisabs = tscal_scale(&tscal, &tscal.y, levt->value);
break;
case ABS_Z:
case ABS_WHEEL:
devt->axis = DIAI_Z;
+ devt->axisabs = levt->value;
break;
default:
if (levt->code >= ABS_PRESSURE || levt->code > DIAI_LAST)
return 0;
devt->axis = levt->code;
+ devt->axisabs = levt->value;
}
devt->type = DIET_AXISMOTION;
devt->flags |= DIEF_AXISABS;
- devt->axisabs = levt->value;
return 1;
}
--- /dev/null 2006-01-24 10:51:06.091423008 -0700
+++ inputdrivers/linux_input/tscal.c 2006-01-31 14:36:03.000000000 -0700
@@ -0,0 +1,133 @@
+/* Touch screen calibration.
+ * Written by Shaun Jackman <[EMAIL PROTECTED]>.
+ * Copyright 2006 Pathway Connectivity
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "tscal.h"
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define DIRECTFB_TS_CONF "/var/run/directfb/touchscreen.conf"
+
+/*
+ * Returns the specified environment variable as an integer.
+ */
+static int envtoi(const char *name, int def)
+{
+ const char *value = getenv(name);
+ if (value == NULL)
+ return def;
+ return atoi(value);
+}
+
+/*
+ * Prints the touch screen calibration.
+ */
+static int tscal_print(struct tscal *tscal, const char *s)
+{
+ return fprintf(stderr, "(*) DirectFB/Input: %s (%d,%d)-(%d,%d)\n",
+ s, tscal->x.min, tscal->y.min, tscal->x.max,
tscal->y.max);
+}
+
+/*
+ * Loads the touch screen calibration.
+ */
+static void tscal_load(struct tscal *tscal)
+{
+ tscal->x.min = envtoi("DIRECTFB_TS_XMIN", INT_MAX);
+ tscal->x.max = envtoi("DIRECTFB_TS_XMAX", 0);
+ tscal->y.min = envtoi("DIRECTFB_TS_YMIN", INT_MAX);
+ tscal->y.max = envtoi("DIRECTFB_TS_YMAX", 0);
+ tscal->x.scale = envtoi("DIRECTFB_WIDTH", 800);
+ tscal->y.scale = envtoi("DIRECTFB_HEIGHT", 600);
+ tscal_print(tscal, "Touchscreen calibrated");
+}
+
+/*
+ * Saves touch screen calibration.
+ */
+static int tscal_save(const struct tscal *tscal)
+{
+ FILE *conf;
+ const char *path = getenv("DIRECTFB_TS_CONF");
+ if (path == NULL)
+ path = DIRECTFB_TS_CONF;
+ conf = fopen(path, "w");
+ if (conf == NULL) {
+ static int warned;
+ if (!warned) {
+ fprintf(stderr, "(!) DirectFB/Input: ");
+ perror(path);
+ warned = 1;
+ }
+ return -1;
+ }
+
+ fprintf(conf,
+ "DIRECTFB_TS_XMIN=%u\n"
+ "DIRECTFB_TS_XMAX=%u\n"
+ "DIRECTFB_TS_YMIN=%u\n"
+ "DIRECTFB_TS_YMAX=%u\n"
+ "DIRECTFB_WIDTH=%u\n"
+ "DIRECTFB_HEIGHT=%u\n",
+ tscal->x.min,
+ tscal->x.max,
+ tscal->y.min,
+ tscal->y.max,
+ tscal->x.scale,
+ tscal->y.scale);
+ fclose(conf);
+ return 0;
+}
+
+/*
+ * Automagic recalibration.
+ */
+static void tscal_recalibrate(struct tscal *tscal,
+ struct tscal_scale *scale, unsigned value)
+{
+ int recalibrated = 0;
+ if (value < scale->min) {
+ scale->min = value;
+ recalibrated = 1;
+ }
+ if (value > scale->max) {
+ scale->max = value;
+ recalibrated = 1;
+ }
+ if (recalibrated) {
+ tscal_print(tscal, "Touchscreen recalibrated");
+ tscal_save(tscal);
+ }
+}
+
+/*
+ * Scales a touch screen coordinate.
+ */
+unsigned tscal_scale(struct tscal *tscal,
+ struct tscal_scale *scale, unsigned value)
+{
+ if (scale->scale == 0)
+ tscal_load(tscal);
+ tscal_recalibrate(tscal, scale, value);
+ if (scale->max <= scale->min)
+ return scale->scale / 2;
+ return scale->scale * (value - scale->min) /
+ (scale->max - scale->min);
+}
--- /dev/null 2006-01-24 10:51:06.091423008 -0700
+++ inputdrivers/linux_input/tscal.h 2006-01-31 14:36:14.000000000 -0700
@@ -0,0 +1,21 @@
+#ifndef _INPUT_TSCAL_H
+#define _INPUT_TSCAL_H
+
+/*
+ * Touch screen calibration scale structure.
+ */
+struct tscal_scale {
+ unsigned min, max, scale;
+};
+
+/*
+ * Touch screen calibration structure.
+ */
+struct tscal {
+ struct tscal_scale x, y;
+};
+
+unsigned tscal_scale(struct tscal *tscal,
+ struct tscal_scale *scale, unsigned value);
+
+#endif /* _INPUT_TSCAL_H */
_______________________________________________
directfb-dev mailing list
[email protected]
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev