TSLib ported to Android for touchscreen calibration. (转) [复制链接]

Since Android doesn't provide a calibration tool, tslib can be used to calibrate the touchscreen . The values obtained from ts_calibrate in pointercal file can be used in android frameworks/services/java/com/android/server/InputDevice.java to have the correct screen coordinates.

ts_calibrate can be run from a serial console along with android with the proper environment variables set (these variables are documented in Android.mk too), the default values are:



export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_CONFFILE=/system/etc/ts.conf
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_PLUGINDIR=/system/lib
export TSLIB_CONSOLEDEVICE=/dev/tty
export TSLIB_FBDEVICE=/dev/graphics/fb0


To compile tslib for your device make a link for bionic/libc/include/fcntl.h to bionic/libc/include/sys/fcntl.h import build/envsetup.sh and execute make or m.

To make tslib build everytime you build your android distribution copy the android-tslib folder to android external/ folder.

Download:
GIT:   git clone git://git.linuxconsulting.ro/android-tslib.git
HTTP:
[url]http://git.linuxconsulting.ro [/url]
转载2:Android
Porting(Touch Screen)I found there are so many questions of touch screen aksed by Android engineers, I have made the wm9713 touch screen work OK, so shared my experience out. This blog page is written by English,  hope all engineers can read it.

Hardware: PXA270, wm9713 touch screen, LCD 480x272
My kernel is the offical kernel from Android(2.6.25), but it does not support the wm97xx touch screen. It is luck that the kernel 2.6.26 is merged the wm97xx touch screen driver. So I should porting the wm97xx touch screen driver from 2.6.26 to 2.6.25.

First step, diff the other touch screen drivers in drivers/input/touchscreen, I found there are almost no changes, so it is safe to copy the wm97xx drivers from 2.6.26 to 2.6.25. Modify the drivers/input/touchscreen/Kconfig and Makefile, copy the linux/wm97xx.h.  But there is anothor  problem, the wm9713 touch screen  is dependent the AC97, so the AC97 sound bus should be configured. It is easy to complie the driver successfully.(the mainstone accelate driver does not compiled in ... it is the result of many tries!)

Booting the kernel, the device for touch screen can be foud in /dev/event1 (event0 for the keypad). Write a test program for touch screen:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/input.h>
#define TS_DEV "/dev/event1"
static int ts_fd = -1;

static int init_device()
{
        if((ts_fd = open(TS_DEV, O_RDONLY)) < 0)
        {
                printf("Error open %s\n", TS_DEV);
                return -1;
        }
        return ts_fd;
}

int main()
{
        int i;
        struct input_event data;
        if(init_device() < 0)
                return -1;
        while(1)
        {
                read(ts_fd, &data, sizeof(data));
                if (data.type == EV_KEY)
                {
                        printf("type: EV_KEY, event = %s, value = %d\n",
                                data.code == BTN_TOUCH ? "BTN_TOUCH" : "Unkown", data.value);
                }
                else if(data.type == EV_ABS)
                {
                        printf("type: EV_ABS, event = %s, value = %d\n",
                                data.code == ABS_X ? "ABS_X" :
                                data.code == ABS_Y ? "ABS_Y" :
                                data.code == ABS_PRESSURE ? "ABS_PRESSURE" :
                                "Unkown", data.value);
                }
                else if (data.type == EV_SYN)
                {
                        printf("type: EV_SYN, event = %s, value = %d\n",
                                data.code == SYN_REPORT ? "SYN_REPORT" : "Unkown", data.value);
                }
                else
                {
                        printf("type: 0x%x, event = 0x%x, value = %d\n", data.type, data.code, data.value);
                }
        }
        return 0;
}

The test program can catch the touch screen data(x, y, pressure), the dirver seems work ok.

Run the Android system, but the system does not response to the touch screen ....
According to the Google search, check /dev/input/event1, /proc/bus/input/devices ... all seem OK.

Some very important hints from the talk between two Android hackers: http://androidzaurus.seesaa.net/article/90045743.html
And some important words: " It seems Android wants to know not only pressure becomes zero but also pendown becomes zero. Only two lines but very precious lines." from http://androidzaurus.seesaa.net/article/96581331.html

So check my driver and test again.
the test program reports that the X Y coordinate is very large(350-3900 for X, 320-3750 for Y, defined in driver), but the LCD is 480x270, and the Adroid use the abusolute touch screen coordinate, which is same to LCD. calibrate should be done, but the Android doe not do this.

Download the tslib-1.4.tar.gz, compile, run the ts_calibrate, and run ts_test, the touch screen works OK. and calibrate coefficent is record in /etc/pointercal.

But how to use the calibrate result for Android? Confused for hours ... I cann't change the Adroid input action, so I should do the calibrate in my driver. Reading the tslib source code, got the idea. I found a formula in tslib/plugins/linear.c

                      xtemp = samp->x; ytemp = samp->y;
                        samp->x =       ( lin->a[2] +
                                        lin->a[0]*xtemp +
                                        lin->a[1]*ytemp ) / lin->a[6];
                        samp->y =       ( lin->a[5] +
                                        lin->a[3]*xtemp +
                                        lin->a[4]*ytemp ) / lin->a[6];
and the lin->a[] is read from the /etc/pointercal. But the division "/"  is hard for Linux kernel. Surprised that the a[6] is 65536, and can do the /65536 by >>16.

Coding in wm9713 driver: drivers/input/touchscreen/wm97xx-core.c, function: static int wm97xx_read_samples(struct wm97xx *wm)
define the coeficient table, change the last variable valure from 65536 to 16.
int axis_table[] = {-8360, 32, 32753552, 24, 4983, -1685240, 16}; // from /etc/pointercal by ts_calibrate

#ifdef TS_ABS_XY
                int xraw, yraw, xtmp, ytmp;
                dev_dbg(wm->dev,
                        "pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
                        data.x >> 12, data.x & 0xfff, data.y >> 12,
                        data.y & 0xfff, data.p >> 12, data.p & 0xfff);
                xraw = (data.x & 0xfff);
                yraw = (data.y & 0xfff);
                xtmp = (axis_table[2] + axis_table[0]*xraw + axis_table[1]*yraw )
                        >> axis_table[6];
                ytmp = (axis_table[5] + axis_table[3]*xraw + axis_table[4]*yraw )
                        >> axis_table[6];

                input_report_abs(wm->input_dev, ABS_X, xtmp);
                input_report_abs(wm->input_dev, ABS_Y, ytmp);
#else
                input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
                input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);

#endif


Run the test program again, it is great that the touch screen coordinate is same to the LCD, Run Android system, but the system does not response to the touch screen. Hear broken ...

Check driver,  input_report_key... is not added according to http://androidzaurus.seesaa.net/article/96581331.html
(1)
if (rc & RC_PENUP) {
                if (wm->pen_is_down) {
                        wm->pen_is_down = 0;
                        dev_dbg(wm->dev, "pen up\n");
                        input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
                        input_report_key(wm->input_dev, BTN_TOUCH, wm->pen_is_down);
                        input_sync(wm->input_dev);

(2)
                input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
                wm->pen_is_down = 1;
                input_report_key(wm->input_dev, BTN_TOUCH, wm->pen_is_down);

                input_sync(wm->input_dev);

Run test program again, but can't catch the EV_KEY event, confused ... trace the kernel source code, found some bit map should be masked.
and in static int wm97xx_probe(struct device *dev)

        set_bit(EV_ABS, wm->input_dev->evbit);
        set_bit(ABS_X, wm->input_dev->absbit);
        set_bit(ABS_Y, wm->input_dev->absbit);
        set_bit(ABS_PRESSURE, wm->input_dev->absbit);

so, the bit mask should be done for EV_KEY
        set_bit(EV_KEY, wm->input_dev->evbit);
        set_bit(BTN_TOUCH, wm->input_dev->keybit);


Run the test program, the EV_KEY can be catched now. Run Android, touch the screen, the icon can be actived by touch... great successfully ...

Good lucky to all Android workers!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值