嵌入式linux下的触屏模拟

最近博主我接到要求,要对研发的一个产品的触摸屏进行测试,大概内容就是要不断地随机点击触摸屏,来测试软件会不会意外退出(鲁棒性验证)。这里我把开发过程记录下来,方便参考。

我们的触摸屏使用的是ads7846这一款触摸屏控制器,找到内核下对应的驱动文件:/drivers/input/touchscreen/ads7846.c。

接下来就要开始修改这个驱动了。我的修改思路是这样的:在这个驱动的基础上增加一个外节点,比如叫做input_emu。然后应用层通过ioctl来操作这个设备节点,从而触发定时器。在这个定时器里面来上报坐标、键值、压力这些关键信息,从而模拟点击这个过程:

1.修改ads7846_probe函数,增加如下几句代码,从而建立input_emu这个节点:

	major = register_chrdev(0, "touch_emulate", &touch_emulate_fops);
	cls = class_create(THIS_MODULE, "touch_emulate");
	device_create(cls, NULL, MKDEV(major, 0), NULL, "input_emu"); /* /dev/input_emu */
	emulate_dev = ts;
	init_timer(&touch_emulate_timer);
	touch_emulate_timer.function = touch_timer_function;

           2.构建touch_emulate_fops结构体,touch_emulate_ioctl函数以及touch_timer_function定时器服务函数:

long touch_emulate_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	switch(cmd)
	{
		case EMULATE_START:
		{
			touch_emulate_timer.expires = jiffies + 1; //10ms后执行,1HZ定义是100
			add_timer(&touch_emulate_timer); //将定时器加入定时器等待队列中
			printk("touch_emulate_ioctl add_timer\n");
			break;
		}
		case EMULATE_STOP:
		{
			del_timer(&touch_emulate_timer);
			printk("touch_emulate_ioctl del_timer\n");
			break;
		}
		default:
			break;
	}

	return 0;
}

struct file_operations touch_emulate_fops = {
	.owner 			= 	THIS_MODULE,
	.unlocked_ioctl 	= 	touch_emulate_ioctl,
};

void touch_timer_function(unsigned long data)
{
	static unsigned int x = 0;
	static unsigned int y = 0;

	/* 随机生成坐标,范围: 2bytes, 0-65535 */
	get_random_bytes(&x, 2);
	get_random_bytes(&y, 2);
	x = (x % 4096); //ads7846的采样精度为12位,范围是0-4096,把随机生成的值限制在该范围。
	y = (y % 4096);

	/* 模拟触屏事件,上报坐标值 */
	input_report_abs(emulate_dev->input, ABS_X, x);
	input_report_abs(emulate_dev->input, ABS_Y, y);
	input_report_abs(emulate_dev->input, ABS_PRESSURE, 1);
	/* BTN_TOUCH为点击事件,单点触摸中需要上报点击事件*/
	input_report_key(emulate_dev->input, BTN_TOUCH, 1); //上报BTN_TOUCH按键值按下     
	input_sync(emulate_dev->input); //上报同步事件,通知系统有事件上报

	/* 松开*/
	input_report_abs(emulate_dev->input, ABS_PRESSURE, 0); //上报压力值为0
	input_report_key(emulate_dev->input, BTN_TOUCH, 0); //上报BTN_TOUCH按键值松开   
	input_sync(emulate_dev->input);

	mod_timer(&touch_emulate_timer, jiffies + 1 * HZ);
}

            3.重新编译内核(或者重新编译模块,这个得看内核配置中该驱动的配置模式)。

            4.编写控制程序来开启或者关闭这个模拟的功能:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
 #include <sys/ioctl.h>
 
#define EMULATE_START    	1
#define EMULATE_STOP      	0

/* Usage:
 * ./touch_emulate start 
 * ./touch_emulate stop 
 */

void print_usage(char *file)
{
	printf("Usage:\n");
	printf("%s start\n", file);
	printf("%s stop\n", file);
}

int main(int argc, char **argv)
{
	int fd;

	if(argc != 2)
	{
		print_usage(argv[0]);
		return -1;			
	}

	fd = open("/dev/input_emu", O_RDWR);
	if(fd < 0)
	{
		printf("Can't open /dev/input_emu!\n");
		return -1;
	}

	if (strcmp(argv[1], "start") == 0)
	{
		ioctl(fd, EMULATE_START);
	}
	else if(strcmp(argv[1], "stop") == 0)
	{
		ioctl(fd, EMULATE_STOP);
	}
	else
	{
		print_usage(argv[0]);
		return -1;
	}
	
	return 0;
}

           5.测试:

重新加载这个驱动,然后运行编译好的控制程序:

./touch_emulate start

通过hexdump来观察输出:

           cat /dev/input/touchscreen0 | hexdump

输出以下信息:

0000f00 2d42 5780 22b5 0000 0003 0000 00a8 0000
0000f10 2d42 5780 22b5 0000 0003 0001 07eb 0000
0000f20 2d42 5780 22b5 0000 0003 0018 0001 0000
0000f30 2d42 5780 22b5 0000 0001 014a 0001 0000
0000f40 2d42 5780 22b5 0000 0000 0000 0000 0000
0000f50 2d42 5780 22dc 0000 0003 0018 0000 0000
0000f60 2d42 5780 22dc 0000 0001 014a 0000 0000
0000f70 2d42 5780 22dc 0000 0000 0000 0000 0000

 

分析输出信息:


hexdump序列号              秒                  微秒            type         code            value

                                                           绝对坐标事件   code=ABS_X       X坐标值
   0000f00             2d42 5780            22b5 0000          0003         0000          00a8 0000
                                                           绝对坐标事件   code=ABS_Y       Y坐标值
   0000f10             2d42 5780            22b5 0000          0003         0001          07eb 0000
																	  code=ABS_PRESSURE     压力值
   0000f20             2d42 5780            22b5 0000          0003         0018          0001 0000
                                                             键盘事件    code=触摸按键    value=1(按下)
   0000f30             2d42 5780            22b5 0000          0001         014a          0001 0000
															 同步事件
   0000f40             2d42 5780            22b5 0000          0000         0000          0000 0000
   
   0000f50             2d42 5780            22dc 0000          0003         0018          0000 0000
   0000f60             2d42 5780            22dc 0000          0001         014a          0000 0000
   0000f70             2d42 5780            22dc 0000          0000         0000          0000 0000

可以看到,输出的顺序和我们定时器里面的上报顺序是一样的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值