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

Reply via email to