概述
试验一:
Device:Beagle Board
System:Android GingerBread2.3.4
getevent
然后Beagle Board Android里鼠标点击左键动作,主机串口产生输出如下:
# Click the right-bottom corner:
/dev/input/event2: 0004 0004 00090001
/dev/input/event2: 0001 0110 00000001
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0004 0004 00090001
/dev/input/event2: 0001 0110 00000000
/dev/input/event2: 0000 0000 00000000
# Click somewhere:
/dev/input/event2: 0004 0004 00090001
/dev/input/event2: 0001 0110 00000001
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0004 0004 00090001
/dev/input/event2: 0001 0110 00000000
/dev/input/event2: 0000 0000 00000000
然后试验由主机串口发出相同的events,看看是否会产生同样的动作?
将鼠标置于Beagle Board屏幕左下角或右下角的翻屏指示处(发出的events预期产生click动作,但是位置坐标还得由鼠标选定),主机串口输入如下命令:
sendevent /dev/input/event2 4 4 589825
sendevent /dev/input/event2 1 272 1
sendevent /dev/input/event2 0 0 0
sendevent /dev/input/event2 4 4 589825
sendevent /dev/input/event2 1 272 0
sendevent /dev/input/event2 0 0 0
Beagle Board Android没反应,说明系统有问题!
试验二:
Device:Beagle Board
System:Android GingerBread2.3.4
修改Beagle Board Android源代码,即修改文件
/home/tomxue/Tom/Source_Code/Android/rowboat-android/TI_Android_GingerBread_2_3_4Sources/kernel/drivers/input/evdev.c
--- evdev.c 2012-09-20 20:41:56.623617427 +0800
+++ evdev_modified.c 2012-09-20 20:42:37.872802833 +0800
@@ -347,8 +347,9 @@
goto out;
}
- input_inject_event(&evdev->handle,
- event.type, event.code, event.value);
+ printk("Tom Xue position 1...................................");
+ evdev_event(&evdev->handle,event.type, event.code, event.value);
+
retval += input_event_size();
}
然后,重新编译kernel,用生成的uImage替换SD卡内的uImage,重启(注意要设置bootargs参数,再reset)
再做上面的试验一,这次,events从主机串口发送之后,Beagle Board Android界面上可以看出,屏幕被切换了!试验成功!
接下来探讨一下深层原因...
先把上面的改动(evdev.c)复原,然后在kernel代码中插入一些打印函数如下:
--- input.c 2012-09-20 19:54:55.571647181 +0800
+++ input-modified.c 2012-09-20 19:53:57.098325853 +0800
@@ -332,11 +332,15 @@
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
dev->sync = false;
- if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
+ if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) {
+ printk("input_handle_event INPUT_PASS_TO_DEVICEn");
dev->event(dev, type, code, value);
+ }
- if (disposition & INPUT_PASS_TO_HANDLERS)
+ if (disposition & INPUT_PASS_TO_HANDLERS) {
+ printk("input_handle_event INPUT_PASS_TO_HANDLERSn");
input_pass_event(dev, src_handler, type, code, value);
+ }
}
/**
@@ -389,15 +393,20 @@
struct input_handle *grab;
unsigned long flags;
+ printk(KERN_INFO "the device name is %s", dev->name);
+ printk(KERN_INFO "input_inject_event position 1n");
+
if (is_event_supported(type, dev->evbit, EV_MAX)) {
+ printk(KERN_INFO "input_inject_event position 2n");
spin_lock_irqsave(&dev->event_lock, flags);
rcu_read_lock();
grab = rcu_dereference(dev->grab);
- if (!grab || grab == handle)
+ if (!grab || grab == handle) {
+ printk(KERN_INFO "input_inject_event position 3n");
input_handle_event(dev, handle->handler,
type, code, value);
-
+ }
rcu_read_unlock();
spin_unlock_irqrestore(&dev->event_lock, flags);
还有头文件drivers/input/input.h中,增加printk输出
static inline void input_sync(struct input_dev *dev)
{
input_event(dev, EV_SYN, SYN_REPORT, 0);
printk("to verify that input_sync is called insteadn");
}
然后,在Beagle Board Android屏幕上任意位置点击鼠标左键,可以在主机串口中看到getevent的输出如下:
# input_handle_event INPUT_PASS_TO_DEVICE
input_handle_event INPUT_PASS_TO_HANDLERS
input_handle_event INPUT_PASS_TO_HANDLERS
input_handle_event INPUT_PASS_TO_HANDLERS
to verify that input_sync is called instead
input_handle_event INPUT_PASS_TO_DEVICE
input_handle_event INPUT_PASS_TO_HANDLERS
input_handle_event INPUT_PASS_TO_HANDLERS
input_handle_event INPUT_PASS_TO_HANDLERS
to verify that input_sync is called instead
根据代码的改动(printk输出)分析一下,可以确定 “ 实际鼠标动作” 调用函数顺序如下:
input_handle_event
input_sync
input_handle_event
input_sync
将鼠标置于左下角或右下角的翻屏指示处,主机串口输入如下命令(做 “ 模拟鼠标动作”):
sendevent /dev/input/event2 4 4 589825
sendevent /dev/input/event2 1 272 1
sendevent /dev/input/event2 0 0 0
sendevent /dev/input/event2 4 4 589825
sendevent /dev/input/event2 1 272 0
sendevent /dev/input/event2 0 0 0
然后,查看Beagle Board的dmesg打印输出如下:
# sendevent /dev/input/event2 4 4 589825
event2 1 272 0
sendevent /dev/input/event2 0 0 0the device name is USB Optical Mouse
input_inject_event position 1
input_inject_event position 2
input_inject_event position 3
input_handle_event INPUT_PASS_TO_DEVICE
input_handle_event INPUT_PASS_TO_HANDLERS
# sendevent /dev/input/event2 1 272 1
the device name is USB Optical Mouse
input_inject_event position 1
input_inject_event position 2
input_inject_event position 3
input_handle_event INPUT_PASS_TO_HANDLERS
# sendevent /dev/input/event2 0 0 0
the device name is USB Optical Mouse
input_inject_event position 1
input_inject_event position 2
input_inject_event position 3
input_handle_event INPUT_PASS_TO_HANDLERS
# sendevent /dev/input/event2 4 4 589825
the device name is USB Optical Mouse
input_inject_event position 1
input_inject_event position 2
input_inject_event position 3
input_handle_event INPUT_PASS_TO_DEVICE
input_handle_event INPUT_PASS_TO_HANDLERS
# sendevent /dev/input/event2 1 272 0
the device name is USB Optical Mouse
input_inject_event position 1
input_inject_event position 2
input_inject_event position 3
input_handle_event INPUT_PASS_TO_HANDLERS
# sendevent /dev/input/event2 0 0 0
the device name is USB Optical Mouse
input_inject_event position 1
input_inject_event position 2
input_inject_event position 3
input_handle_event INPUT_PASS_TO_HANDLERS
以上调试信息说明input_inject_event()和它所调用的函数input_handle_event()都得到了完全执行,也即把event传递给了handler
根据代码的改动(printk输出)分析一下, 模拟鼠标动作的函数调用顺序如下:
input_inject_event->input_handle_event->input_pass_event->(handle->handler->event)
而这个event通常就应该是evdev_event()函数(但貌似GingerBread2.3.4不是这样的,或者函数调用出错)
static inline void input_sync(struct input_dev *dev)
{
input_event(dev, EV_SYN, SYN_REPORT, 0);
}
那么把input_inject_event()替换成evdev_event()为什么成功了呢?
看看下面的函数调用即可知,evdev_event()中通过kill_fasync()将EV_SYN事件通知了用户空间进程,由后者完成对EV_SYN的处理
evdev_event->evdev_pass_event->
do {
client->buffer[client->head++] = *event;
client->head &= client->bufsize - 1;
} while (client->head == client->tail);
...
if (event->type == EV_SYN)
kill_fasync(&client->fasync, SIGIO, POLL_IN);
注:
其实evdev_event()的重点在于将event放入buffer中,这个buffer定义为evdev_client的input_event[]数组;
而evdev_read()函数将会把该buffer中的event传至用户空间,进而触发相应的动作
结论:
从以上分析可知,Beagle Board Android GingerBread2.3.4下的模拟鼠标动作最终没能成功调用evdev_event()函数,导致其无法报告EV_SYN事件,进而失败。
试验三:
Device:HTC Android phone
System:Android GingerBread4.0.3
主机串口试图捕获触摸动作产生的events:
tomxue@ubuntu:~$ adb shell getevent
add device 1: /dev/input/event5
name: "proximity"
add device 2: /dev/input/event4
name: "lightsensor-level"
add device 3: /dev/input/event3
name: "pyramid-keypad"
add device 4: /dev/input/event2
name: "cy8c-touchscreen"
add device 5: /dev/input/event1
name: "rcp_events"
add device 6: /dev/input/event0
name: "h2w headset"
/dev/input/event2: 0003 0030 00000032
/dev/input/event2: 0003 0032 00000032
/dev/input/event2: 0003 003a 00000032
/dev/input/event2: 0003 0035 000003a5
/dev/input/event2: 0003 0036 00000378
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0001 014a 00000001
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0003 0030 0000000d
/dev/input/event2: 0003 0032 0000000d
/dev/input/event2: 0003 003a 0000000d
/dev/input/event2: 0003 0035 0000039f
/dev/input/event2: 0003 0036 0000037c
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0001 014a 00000000
/dev/input/event2: 0000 0000 00000000
# click again on the right-bottom corner: (App Evernote is there)
/dev/input/event2: 0003 0030 0000002d
/dev/input/event2: 0003 0032 0000002d
/dev/input/event2: 0003 003a 0000002d
/dev/input/event2: 0003 0035 000003a4
/dev/input/event2: 0003 0036 00000386
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0001 014a 00000001
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0003 0030 0000002d
/dev/input/event2: 0003 0032 0000002d
/dev/input/event2: 0003 003a 0000002d
/dev/input/event2: 0003 0035 000003a5
/dev/input/event2: 0003 0036 00000386
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0000 0000 00000000
/dev/input/event2: 0000 0002 00000000
/dev/input/event2: 0001 014a 00000000
/dev/input/event2: 0000 0000 00000000
于是 模拟触摸事件的script被写成这样:
adb shell sendevent /dev/input/event2 3 48 51
adb shell sendevent /dev/input/event2 3 50 51
adb shell sendevent /dev/input/event2 3 58 51
adb shell sendevent /dev/input/event2 3 53 937
adb shell sendevent /dev/input/event2 3 54 913
adb shell sendevent /dev/input/event2 0 2 0
adb shell sendevent /dev/input/event2 1 330 1
adb shell sendevent /dev/input/event2 0 0 0
adb shell sendevent /dev/input/event2 3 48 51
adb shell sendevent /dev/input/event2 3 50 51
adb shell sendevent /dev/input/event2 3 58 51
adb shell sendevent /dev/input/event2 3 53 937
adb shell sendevent /dev/input/event2 3 54 913
adb shell sendevent /dev/input/event2 0 2 0
adb shell sendevent /dev/input/event2 0 0 0
adb shell sendevent /dev/input/event2 0 2 0
adb shell sendevent /dev/input/event2 1 330 0
adb shell sendevent /dev/input/event2 0 0 0
通过主机串口下执行:
./script
发现HTC Android phone上的Evernote图标出现的不是单击效果,而是 缓慢单击的效果:不是打开应用,而是询问是否要拖动后删除它...
猜测是否上述的脚本命令执行效率的问题?将上面的script前面的adb shell字样去掉,将其传至HTC phone /data目录下,执行,以为效率提高会导致不一样的结果,可是结果还是一样的...
结论:
那么试验三表明HTC Android phone至少可以响应模拟触摸事件
而试验一和试验二显示Beagle Board Android GingerBread2.3.4必须改动源码才能正确响应模拟鼠标动作
最后
以上就是健忘秋天为你收集整理的Linux下如何模拟touch事件?结论: 的全部内容,希望文章能够帮你解决Linux下如何模拟touch事件?结论: 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复