Tslib Manual Calibrate On Android
--by ONCE
1.android 的坐标转换处理
This implementation is a linear transformation using 7 parameters
(a, b, c, d, e, f and s) to transform the device coordinates (Xd, Yd)
into screen coordinates (Xs, Ys) using the following equations:
s*Xs = a*Xd + b*Yd + c
s*Ys = d*Xd + e*Yd + f
Xs,Ys:LCD 坐标(也就是所谓的绝对坐标)
Xd,Yd:触摸屏坐标
在编译好了的 ANDROID 根文件系统的 system/etc/pointercal 这个文件
内,存放着 7 个数,
这 7 个数就是对应上面公式的 a,b,c,d,e,f,s
比如我原来的:
+----+-----+--------+------+--+--------+----+
a | b | c |d |e | f |s |
+----+-----+--------+------+--+--------+----+
|-411|37818|-3636780|-51325|39|47065584|6553|
+----+-----+--------+------+--+--------+----+
2.tslib 库的移植
首先下载到一份 tslib 的代码,我用的是 tslib011.tar.gz(该包由
luzhuwei 同学友情赞助)。
将 tslib 解压到 external/下
要将一份代码编译到 android 里面去 其实没什么其他工作 主要就是那
个 Android.mk 文件的编写。网上找找 自己改改也就出来了。我的
Android.mk 文件内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
TSLIB_PLUGINDIR := /system/lib/ts/plugins
LOCAL_SRC_FILES := /
src/ts_attach.c /
src/ts_close.c /
src/ts_config.c /
src/ts_error.c /
src/ts_fd.c /
src/ts_load_module.c /
src/ts_open.c /
src/ts_parse_vars.c /
src/ts_read.c /
src/ts_read_raw.c /
src/ts_read_raw_module.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl
LOCAL_MODULE := libts
include $(BUILD_SHARED_LIBRARY)
#
# plugin: input-raw
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/input-raw.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/input-raw
include $(BUILD_SHARED_LIBRARY)
#
# plugin: pthres
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/pthres.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/pthres
include $(BUILD_SHARED_LIBRARY)
#
# plugin: linear
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/linear.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/linear
include $(BUILD_SHARED_LIBRARY)
#
# plugin: dejitter
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/dejitter.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/dejitter
include $(BUILD_SHARED_LIBRARY)
#
# plugin: variance
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/variance.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/variance
include $(BUILD_SHARED_LIBRARY)
#
# ts_calibrate
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_calibrate.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
tests/ts_calibrate.h /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_calibrate
include $(BUILD_EXECUTABLE)
#
# ts_test
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_test.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_test
include $(BUILD_EXECUTABLE)
#
# ts_print
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_print.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_print
include $(BUILD_EXECUTABLE)
#
# ts_print_raw
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_print_raw.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_print_raw
include $(BUILD_EXECUTABLE)
#
# ts_harvest
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_harvest.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_harvest
include $(BUILD_EXECUTABLE)
我真不愿意粘帖上面的这个文件...太大 不过方便后人拷贝。
这里要注意是我们需要修改一下 tslib 的几个相关文件,因为 android
里的部分设备文件位置比较特殊。还有就是 tslib 里的部分变量他是
定义在 Makefile 里的 我们要把它定义到我们的文件中去。
首先 fb0 的位置变了: tests/fbutils.c
static char *defaultfbdevice = "/dev/fb0";
static char *defaultfbdevice = "/dev/graphics/fb0";
其次 plugins 的目录变了 src/ts_load_module.c
#define PLUGIN_DIR "/system/lib/ts/plugins/"
最后 config 文件的位置变了 src/ts_config.c
#define TS_CONF "/system/etc/ts.conf"
最后的最后不得不提到我们的配置文件 ts.conf。其他都不要动 但是
必须将它的 module_raw input 注释出来。并且 因为我们的 input 模块
编译出来之后我们命名为 input-raw 了 所以这里得改成
module_raw input-raw
下面就是编译了。发现错误就手工拷贝一下编出来的库到需要它在的
目录。
3. ts_calibrate 生成 pointercal
这里要首先不启动 android,然后进命令行手工启动 ts_calibrate 程序。
然后在屏幕上校验,完成后会生成一个正确的 pointercal 文件。
4.Android 读取校验文件 pointercal
如果要让我们的 android 被校验 那莪没我们就要按上面的公式 将
android 读取坐标部分替换掉。
“system/etc/pointercal”这个文件是被 java 程序读取使用的,文件目录:
f rameworks/base/services/java/com/android/server/InputDevice.java
看了一下这个文件的代码 发现要被修改的坐标为
if (device.absX != null) {
//xxw added
if (device.tInfo != null){
scaledX = (device.tInfo.x1 * x + device.tInfo.y1 * y +
device.tInfo.z1)/ device.tInfo.s;
Log.i("XXW","x: "+x);
Log.i("XXW","trans x: "+scaledX);
}
else//end
scaledX = ((scaledX-device.absX.minValue)
/ device.absX.range) * w;
}
if (device.absY != null) {
//xxw added
if (device.tInfo != null){
scaledY = (device.tInfo.x2 * x + device.tInfo.y2 * y +
device.tInfo.z2) / device.tInfo.s;
Log.i("XXW","y: "+y);
Log.i("XXW","trans y: "+scaledY);
}
else //end
scaledY = ((scaledY-device.absY.minValue)
/ device.absY.range) * h;
}
对照上面的公式其实很容易理解 在注释 xxw 和 end 之间的代码就是
我修改的代码。其中的 device.tInfo 是我定义的一个结构,这个结构
是用来读取 pointercal 文件里的 7 个数字得到的对应的值,具体结构
如下:
static class TransformInfo {
float x1;
float y1;
float z1;
float x2;
float y2;
float z2;
float s;
};
读取文件的代码 我放在 InputDevice 的构造函数里:
//xxw added
TransformInfo t = null;
try {Log.i("XXW","InputDevice! try");
FileInputStream is = new FileInputStream(CALIBRATION_FILE);
byte[] mBuffer = new byte[64];
int len = is.read(mBuffer);
is.close();
if (len > 0) {Log.i("XXW","InputDevice! len>0");
int i;
for (i = 0 ; i < len ; i++) {
if (mBuffer[i] == '/n' || mBuffer[i] == 0) {
break;
}
}
len = i;
}Log.i("XXW","InputDevice! len"+len);
StringTokenizer st = new StringTokenizer( new String(mBuffer, 0, 0,
len));
t = new TransformInfo ();
t.x1 = Integer.parseInt( st.nextToken() ); Log.i("XXW", "t.x1"+t.x1);
t.y1 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.y1"+t.y1);
t.z1 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.z1"+t.z1);
t.x2 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.x2"+t.x2);
t.y2 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.y2"+t.y2);
t.z2 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.z2"+t.z2);
t.s = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.s"+t.s);
} catch (java.io.FileNotFoundException e) {Log.i("XXW",
"FileNotFound!");
} catch (java.io.IOException e) {Log.i("XXW", "IOException");
}
tInfo = t;
Log.i("XXW","InputDevice end!");
}
其中 static final String CALIBRATION_FILE = "/etc/pointercal";
这个时候点击一下屏幕看看是不是准确就知道是不是成功了。这里要
注意的是因为是在 InputDevice 里读取的文件 所以当我们中途替换了
pointercal 文件的时候 android 并不会再去读取这个文件。所以当我们
用 ts_calibrate 程序生成 pointercal 文件之后需要重启一下。同样 当我
们修改或者删除了那个文件 我们也是需要重启的。所以这个文档 的
名字叫手工校验。
PS:
如何自动化?
如何用 android 应用程序校验而不是命令行?
如何不需要重启也能实现?
请听下回分解。