一、将Tiny6410一线触摸程序改成输入设备(input device)

由于友善一线触摸下位机不开源,所以只能在官方提供的内核模块上进行修改。

官方源代码:http://pan.baidu.com/s/1bog4rZD

1、修改模块加载函数

 1 static int __init dev_init(void)
 2 {
 3     int ret;
 4 #ifdef TS_INPUT_DRIVER
 5     /* alloc input system device */
 6     ts.input = input_allocate_device();
 7     
 8     ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 9     ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
10     
11     input_set_abs_params(ts.input, ABS_X, 0, 0xFFFF, 0, 0);
12     input_set_abs_params(ts.input, ABS_Y, 0, 0xFFFF, 0, 0);
13 
14     ts.input->name = "Tiny6410 TouchScreen";
15     ts.input->id.bustype = BUS_HOST;
16     ts.input->id.vendor = 0xDEAD;
17     ts.input->id.product = 0xBEEF;
18     ts.input->id.version = 0x0102;
19 
20 
21     set_pin_up();
22     set_pin_value(1);
23     set_pin_as_output();
24     setup_irq(IRQ_TIMER3, &timer_for_1wire_irq);
25     ret = init_timer_for_1wire();
26     if(ret < 0)
27     {
28         printk(TOUCH_DEVICE_NAME"timer init failed\n");
29         goto timer_err;
30     }
31     init_timer(&one_wire_timer);
32     one_wire_timer_proc(0);
33     create_proc_read_entry("driver/one-wire-info", 0, NULL, read_proc, NULL);
34 
35     /* register to the input system */
36     ret = input_register_device(ts.input);
37     if(ret < 0)
38     {
39         printk(TOUCH_DEVICE_NAME"failed to register input device\n");
40         goto timer_err;
41     }
42     
43     return 0;
44 timer_err:
45     free_irq(IRQ_TIMER3, &timer_for_1wire_irq);
46 
47 #else
48 
49     ret = misc_register(&ts_misc) | misc_register(&bl_misc) ;
50     set_pin_up();
51     set_pin_value(1);
52     set_pin_as_output();
53 
54     if (ret == 0) {
55         setup_irq(IRQ_TIMER3, &timer_for_1wire_irq);
56         ret = init_timer_for_1wire();
57         init_timer(&one_wire_timer);
58         one_wire_timer_proc(0);
59         create_proc_read_entry("driver/one-wire-info", 0, NULL, read_proc, NULL);
60     }
61     
62     if (ret == 0) {
63         printk (TOUCH_DEVICE_NAME"\tinitialized\n");
64         printk (BACKLIGHT_DEVICE_NAME"\tinitialized\n");
65     }
66 #endif
67 
68     return ret;
69 }

 

在这个函数中提交输入的事件EV_KEY、EV_ABS、BTN_TOUCH,并注册输入设备到系统。

 

2、向输入子系统报告输入事件

修改源代码notify_ts_data()函数:

 1 static inline void notify_ts_data(unsigned x, unsigned y, unsigned down)
 2 {
 3     if (!down && !(ts_status &(1U << 31))) {
 4         // up repeat, give it up
 5 #ifdef TS_INPUT_DRIVER
 6         input_report_key(ts.input, BTN_TOUCH, 0);
 7         input_sync(ts.input);
 8 #endif
 9         return;
10     }
11 #ifdef TS_INPUT_DRIVER
12     ts.xp = x;
13     ts.yp = y;
14     //printk("ts.xp = %ld,ts.yp = %ld\n",ts.xp,ts.yp);
15     input_report_abs(ts.input, ABS_X, ts.xp);
16     input_report_abs(ts.input, ABS_Y, ts.yp);
17 
18     input_report_key(ts.input, BTN_TOUCH, 1);
19     input_sync(ts.input);
20 #else
21     ts_status = ((x << 16) | (y)) | (down << 31);
22     ts_ready = 1;
23     wake_up_interruptible(&ts_waitq);
24 #endif
25 }

 

这个函数在按键按下时向输入子系统报告X/Y轴坐标的AD值和按键按下标志,在按键释放时报告按键释放标志。

 

3、修改模块卸载函数

 1 static void __exit dev_exit(void)
 2 {
 3     exitting = 1;
 4 #ifdef TS_INPUT_DRIVER
 5     input_unregister_device(ts.input);
 6 #endif
 7     remove_proc_entry("driver/one-wire-info", NULL);
 8     del_timer_sync(&one_wire_timer);
 9     free_irq(IRQ_TIMER3, &timer_for_1wire_irq);
10 #ifndef TS_INPUT_DRIVER
11     misc_deregister(&ts_misc);
12     misc_deregister(&bl_misc);
13 #endif
14 }

 

在模块卸载函数中卸载输入设备。

 

二、移植tslib到开发板

tslib源码下载:http://pan.baidu.com/s/1qXuqPdU

编译工具:arm-linux-gcc

1、下载源码并解压

tar xzbf tslib-1.4.tar.gz

 

2、修改源码

打开源码tslib/plugins/input-raw.c文件

首先修改check_fd()函数,由于设备驱动没有用到ioctl,所以这个检测函数直接返回0。但是设备驱动用到了同步所以要把using_syn = 1:

 1 static int check_fd(struct tslib_input *i)
 2 {
 3     struct tsdev *ts = i->module.dev;
 4     int version;
 5     u_int32_t bit;
 6     u_int64_t absbit;
 7 /*
 8     if (! ((ioctl(ts->fd, EVIOCGVERSION, &version) >= 0) &&
 9         (version == EV_VERSION) &&
10         (ioctl(ts->fd, EVIOCGBIT(0, sizeof(bit) * 8), &bit) >= 0) &&
11         (bit & (1 << EV_ABS)) &&
12         (ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(absbit) * 8), &absbit) >= 0) &&
13         (absbit & (1 << ABS_X)) &&
14         (absbit & (1 << ABS_Y)) && (absbit & (1 << ABS_PRESSURE)))) {
15         fprintf(stderr, "selected device is not a touchscreen I understand\n");
16         return -1;
17     }
18 */
19     printf("selected device!\n");
20     //if (bit & (1 << EV_SYN))
21         i->using_syn = 1;
22 
23     return 0;
24 }

 

修改ts_input_read()函数,根据设备驱动程序可以知道,设备驱动提交BTN_TOUCH表示触摸屏有无按下,且设备驱动没有提交ABS_PRESSURE

 1 static int ts_input_read(struct tslib_module_info *inf,
 2              struct ts_sample *samp, int nr)
 3 {
 4     struct tslib_input *i = (struct tslib_input *)inf;
 5     struct tsdev *ts = inf->dev;
 6     struct input_event ev;
 7     int ret = nr;
 8     int total = 0;
 9 
10     if (i->sane_fd == 0)
11         i->sane_fd = check_fd(i);
12 
13     if (i->sane_fd == -1)
14         return 0;
15 
16     if (i->using_syn) {
17         while (total < nr) 
18         {
19             ret = read(ts->fd, &ev, sizeof(struct input_event));
20             if (ret < (int)sizeof(struct input_event)) {
21                 total = -1;
22                 break;
23             }
24             switch (ev.type) 
25             {
26             case EV_KEY:
27                 switch (ev.code) 
28                 {
29                 case BTN_TOUCH:
30                     if (ev.value == 0) 
31                     {
32                         /* pen up */
33                         samp->x = 0;
34                         samp->y = 0;
35                         //samp->pressure = 0;
36                         i->current_p = 0;
37                         samp->tv = ev.time;
38                         //samp++;
39                         //total++;
40                         printf("key_up\n");
41                     }
42                     else if(ev.value == 1)
43                     {
44                         i->current_p = 1;
45                         printf("key_down\n");
46                     }
47                     break;
48                 }
49                 break;
50             case EV_SYN:
51                 /* Fill out a new complete event */
52                 samp->x = i->current_x;
53                 samp->y = i->current_y;
54                 samp->pressure = i->current_p;
55                 samp->tv = ev.time;
56     #ifdef DEBUG
57                 fprintf(stderr, "RAW---------------------> %d %d %d %d.%d\n",
58                         samp->x, samp->y, samp->pressure, samp->tv.tv_sec,
59                         samp->tv.tv_usec);
60     #endif         /*DEBUG*/
61                 samp++;
62                 total++;
63                 break;
64             case EV_ABS:
65                 switch (ev.code) 
66                 {
67                 case ABS_X:
68                     i->current_x = ev.value;
69                     break;
70                 case ABS_Y:
71                     i->current_y = ev.value;
72                     break;
73                 /*
74                 case ABS_PRESSURE:
75                     i->current_p = ev.value;
76                     break;
77                 */
78                 }
79                 break;
80             }
81         }
82         ret = total;
83     } 
84     return ret;
85 }

 

红色为修改的地方,修改之后保存退出。

3、安装

# ./autogen.sh
#./configure --host=arm-linux ac_cv_func_malloc_0_nonnull=yes --cache-file=arm-linux.cache -prefix=/usr/local/tslib
# make
# sudo make install

 

-prefix=/usr/local/tslib 表示安装的路径

./autogen.sh可能会报错:

ming@ubuntu:~/windowsshar/tslib$ ./autogen.sh 
./autogen.sh: 4: ./autogen.sh: autoreconf: not found

 

解决办法:

1 sudo apt-get install automake
2 sudo apt-get install autogen
3 sudo apt-get install autoconf

 

4、修改配置文件

sudo vim /usr/local/tslib/etc/ts.conf

把第二行module_raw input前面的#号去掉(注意顶格)。

5、把/usr/local/下面编译好的tslib文件拷贝到开发板目录的/usr/local目录下(usr下面没有local文件夹就创建一个)

sudo cp -r /usr/local/tslib xxx/usr/local/

 

6、打开开发板/etc/profile文件

vi /etc/profile

 

在文件后面添加下面内容:

1 export TSLIB_ROOT=/usr/local/tslib
2 export TSLIB_TSDEVICE=/dev/event1
3 export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
4 export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts
5 export TSLIB_CALIBFILE=/etc/pointercal
6 export TSLIB_CONSOLEDEVICE=none
7 export TSLIB_FBDEVICE=/dev/fb0
8 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib

 

TSLIB_TSDEVICE=/dev/event1指明触摸屏设备,我的为/dev/event1
export TSLIB_FBDEVICE=/dev/fb0指明液晶显示设备

7、重启开发板(因为修改了profile,这个操作是必须的。当然也可以用source命令)

8、进入开发板/usr/local/tslib/bin目录,运行ts_calibrate程序进行屏幕校准。

1 cd /usr/local/tslib/bin/
2 ./ts_calibrate

 

结果出现下面问题:

-/bin/sh: ./ts_calibrate: not found

 

在Linux系统下用arm-linux-readelf查看下ts_calibreate运行所需要的库:

1 ming@ubuntu:~/windowsshar/nfs/rootfs/usr/local/tslib/bin$ arm-linux-readelf -d ts_calibrate 
2 
3 Dynamic section at offset 0x2ef8 contains 28 entries:
4   Tag        Type                         Name/Value
5  0x00000001 (NEEDED)                     Shared library: [libts-0.0.so.0]
6  0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
7  0x00000001 (NEEDED)                     Shared library: [libc.so.6]
8  0x0000000f (RPATH)                      Library rpath: [/usr/local/tslib/lib]
9  0x0000001d (RUNPATH)                    Library runpath: [/usr/local/tslib/lib]

 

发现需要三个库libts-0.0.so.0 libdl.so.2 libc.so.6 ,其中libts-0.0.so.0是tslib自己提供的,所以需要从arm-linux-gcc里面的arm-none-linux-gnueabi/lib下面拷贝后两个库到开发板/lib目录下:

1 cd xxx/arm-liunx-gcc/xxx/arm-none-linux-gnueabi/lib
2 sudo cp libdl.so.2 libc.so.6 xxx/lib

 

再次运行ts_calibrate程序,还是一样的问题,再用arm-linux-readelf查看下ts_calibreate运行所需要的库:

1 ming@ubuntu:~/windowsshar/nfs/rootfs/usr/local/tslib/bin$ arm-linux-readelf -a ts_calibrate | grep "lib"
2       [Requesting program interpreter: /lib/ld-linux.so.3]
3  0x00000001 (NEEDED)                     Shared library: [libts-0.0.so.0]
4  0x00000001 (NEEDED)                     Shared library: [libdl.so.2]
5  0x00000001 (NEEDED)                     Shared library: [libc.so.6]
6  0x0000000f (RPATH)                      Library rpath: [/usr/local/tslib/lib]
7  0x0000001d (RUNPATH)                    Library runpath: [/usr/local/tslib/lib]

 

换一种方式,直接筛选"lib",发现还有一个库没有拷贝ld-linux.so.3,把这个库也拷贝进去:

cd xxx/arm-liunx-gcc/xxx/arm-none-linux-gnueabi/lib
sudo cp ld-linux.so.3 xxx/lib

 

再次运行,成功!

校准完成之后运行ts_test程序

 

posted on 2016-01-15 21:27  青春没有尾巴  阅读(1369)  评论(0编辑  收藏  举报