uinput模拟触摸屏双指放大与缩小

uinput模拟触摸屏双指放⼤与缩⼩
uinput模拟触摸屏双指放⼤与缩⼩
前⾔
有时为了获取某种事件,需要使⽤uinput来创建⼀个虚拟的设备,通过先配置好设备属性,将预定好的input event序列写⼊/dev/uinput 设备⽂件,便可在没有硬件设备的情况下获得所需设备的某个事件。
本⽂主要以分析代码的⽅式讲解如何利⽤uinput模拟触摸屏的双指放⼤与缩⼩,就像在⼿机上双指放⼤缩⼩⾼德地图那样。
另外:
需包含头⽂件 #include <linux/uinput.h> ,其他头⽂件根据需要添加
查看当前所有设备使⽤ sudo lsinput
实时获取某个设备发⽣的事件使⽤ sudo input-events 后接设备号
查看⼿机的输⼊设备 adb shell getevent -p
获取⼿机底层发送的事件,例如:adb shell getevent -l /dev/input/event2
涉及到⽂件的路径如下:
/usr/include/linux/input.h
/usr/include/linux/input-event-codes.h
/usr/include/linux/uinput.h
创建虚拟设备并配置属性
这部分的代码如下,最好将其写⼊独⽴的线程中,现在便开始分析
int fd, rc;
struct uinput_user_dev uidev;
...
int VirtualDevice::create_virtual_touchscreen()
{
//打开uinput⽂件
fd =open("/dev/uinput", O_WRONLY);
if(fd <0){
printf("Unable to open /dev/uinput\n");
return-1;
}
//配置设备属性
ioctl(fd, UI_SET_EVBIT, EV_ABS);//⽀持触摸
ioctl(fd, UI_SET_EVBIT, EV_SYN);//⽀持同步,⽤于report
橡塑发泡保温材料
//multitouch对应的属性,即input_event结构体中的type
ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT);//⽀持⼏个触摸点
ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);//接触⾯直径⼤⼩,这⾥没⽤MINOR
ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);//x坐标
ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);//y坐标
ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);//对某⼀次触摸的标记,按键码ID
ioctl(fd, UI_SET_ABSBIT, ABS_MT_PRESSURE);//触摸的压⼒
//对当前设备设置以上属性的数值范围
memset(&uidev,0,sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE,"kydroid_touchscreen");
//以上 kydroid_touchscreen 为设备名
微波加热器
uidev.id.bustype = BUS_USB;
uidev.id.vendor  =0x1;
uidev.id.product =0x1;
uidev.id.version =1;
uidev.absmin[ABS_MT_POSITION_X]=0;
uidev.absmax[ABS_MT_POSITION_X]=1919;//坐标x的最⼤最⼩值,笔者的屏幕为显⽰器
uidev.absfuzz[ABS_MT_POSITION_X]=0;
uidev.absflat[ABS_MT_POSITION_X]=0;
uidev.absmin[ABS_MT_POSITION_Y]=0;
uidev.absmax[ABS_MT_POSITION_Y]=1199;//坐标y的最⼤最⼩值
uidev.absfuzz[ABS_MT_POSITION_Y]=0;
半有源rfiduidev.absflat[ABS_MT_POSITION_Y]=0;
uidev.absmin[ABS_MT_PRESSURE]=0;
uidev.absmax[ABS_MT_PRESSURE]=100;//触摸压⼒的最⼤最⼩值
uidev.absfuzz[ABS_MT_PRESSURE]=0;
uidev.absflat[ABS_MT_PRESSURE]=0;
uidev.absmax[ABS_MT_SLOT]=9;//同时⽀持最多9个触点
uidev.absmax[ABS_MT_TOUCH_MAJOR]=16;//与屏接触⾯的最⼤值
uidev.absmax[ABS_MT_TRACKING_ID]=65535;//按键码ID累计叠加最⼤值
//利⽤以上属性创建设备
rc =write(fd,&uidev,sizeof(uidev));
if(rc !=sizeof(uidev)){
printf("Unable to write uidev to fd\n");
return-1;
}
rc =ioctl(fd, UI_DEV_CREATE);
if(rc <0){
printf("Unable to create UINPUT device.\n");
return-1;
}
while(1){
sleep(3);//使程序⼀直运⾏,否则退出后设备就不存在了
}
return1;
}
写⼊单个事件
传⼊函数get_events_then_send()的参数依次为input_event结构体的type、code、value。
int VirtualDevice::get_events_then_send(int eventType,int eventCode,int eventValue)体香糖
{
struct input_event ev;//input_event定义在 /usr/include/linux/input.h
memset(&ev,0,sizeof(struct input_event));
//将事件存⼊结构体
ev.value = eventValue;
/
/写⼊到设备的事件⽂件/dev/uinput,在/dev/input/eventX⽂件中可查看
if(write(fd,&ev,sizeof(struct input_event))<0){
char* mesg =strerror(errno);
printf("nibiru uinput errormag info :%s\n",mesg);
return-1;
}
return1;
}
创建事件序列
可以先参考从⼿机中抓取出来的双指放⼤缩⼩的序列,命令为adb shell getevent -l /dev/input/event2,将后⾯的event2换成当前触摸屏对应的⽂件。下⽅代码模拟单次放⼤或缩⼩。
int id =0;
...
合成绝缘子void VirtualDevice::img_change(int type)
{
{
int x0 =600, y0 =600, x1 =1200, y1 =600;//两个触点落下的位置
//两个触点依次落下事件
usleep(20*1000);//事件间隔
id +=1;
this->get_events_then_send(EV_ABS, ABS_MT_SLOT,0);
this->get_events_then_send(EV_ABS, ABS_MT_TRACKING_ID, id);
this->get_events_then_send(EV_ABS, ABS_MT_TOUCH_MAJOR,4);
this->get_events_then_send(EV_ABS, ABS_MT_PRESSURE,80);
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_X, x0 );//落点x坐标
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_Y, y0 );//落点y坐标
this->get_events_then_send(EV_SYN, SYN_REPORT,0);//事件分批次上报,以使输出设备做出反应usleep(1*1000);
id +=1;
this->get_events_then_send(EV_ABS, ABS_MT_SLOT,1);
this->get_events_then_send(EV_ABS, ABS_MT_TRACKING_ID, id);
this->get_events_then_send(EV_ABS, ABS_MT_TOUCH_MAJOR,5);
this->get_events_then_send(EV_ABS, ABS_MT_PRESSURE,80);
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_X, x1 );
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_Y, y1 );
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
//两个触点分别左右移动实现放⼤或缩⼩
usleep(20*1000);
for(int i=0;i<50;i++){
if(type ==0){//放⼤
x0 -=3;
x1 +=3;
}else{//缩⼩
x0 +=3;
x1 -=3;
}
/
/移动过后,两个触点所处的状态
usleep(40*1000);
this->get_events_then_send(EV_ABS, ABS_MT_SLOT,0);
this->get_events_then_send(EV_ABS, ABS_MT_PRESSURE,80);
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_X, x0 );
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
this->get_events_then_send(EV_ABS, ABS_MT_SLOT,1);
this->get_events_then_send(EV_ABS, ABS_MT_PRESSURE,80);
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_X, x1 );
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
}
/
/两指依次离开屏幕
usleep(10*1000);
this->get_events_then_send(EV_ABS, ABS_MT_SLOT,1);
this->get_events_then_send(EV_ABS, ABS_MT_PRESSURE,0);//压⼒变为0
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_X, x1 );
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
this->get_events_then_send(EV_ABS, ABS_MT_TRACKING_ID,-1);//-1表⽰抬起
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
usleep(10*1000);
this->get_events_then_send(EV_ABS, ABS_MT_SLOT,0);
this->get_events_then_send(EV_ABS, ABS_MT_PRESSURE,0);
this->get_events_then_send(EV_ABS, ABS_MT_POSITION_X, x0 );
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
this->get_events_then_send(EV_ABS, ABS_MT_TRACKING_ID,-1);
this->get_events_then_send(EV_SYN, SYN_REPORT,0);
}
注意:不同设备的事件序列可能不同,如果程序运⾏没有反应,可以更改⼀下上⽅的序列。
程序运⾏过程
新建线程执⾏create_virtual_touchscreen(),使设备⼀直存在。调⽤img_change(int type),其中type值为0时模拟放⼤,为1时模拟缩⼩。img_change()中按事件序列依次调⽤get_events_then_send()来写⼊事件,事件写⼊后输出设备会做出反应。这样根据type的值每执⾏⼀次img_change(),以⾼德地图为例,可以看到地图的放⼤或缩⼩。
人工智能建站
uinput模拟触摸屏双指放⼤与缩⼩的内容就讲解到这⾥了,运⾏程序时看到窗⼝画⾯放⼤缩⼩,是不是很有趣呢。

本文发布于:2024-09-23 22:35:19,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/283157.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:设备   事件   属性   触点   模拟
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议