Gro*_*uez 6 linux embedded linux-kernel evdev
我正在使用gpio-keys设备驱动程序来处理运行Linux的嵌入式设备中的一些按钮.用户空间中的应用程序只能/dev/input/eventX在循环中打开和读取输入事件.
我的问题是如何获得按钮的初始状态.有一个ioctl call(EVIOCGKEY)可以用于此,但是如果我先检查这个然后开始读取/dev/input/eventX,就无法保证状态之间没有变化.
有什么建议?
evdev设备将事件排队,直到你为止read(),所以在大多数情况下打开设备,执行ioctl()并立即开始从中读取事件应该有效.如果驱动程序从队列中删除了一些事件,它会向您发送一个SYN_DROPPED事件,以便您可以检测发生这种情况的情况.libevdev文档对如何处理这种情况有一些想法; 我读它的方式你应该只是重试,即删除所有挂起的事件,并重做ioctl()直到没有更多的SYN_DROPPED事件.
我使用此代码验证此方法是否有效:
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <string.h>
#define EVDEV "/dev/input/event9"
int main(int argc, char **argv) {
unsigned char key_states[KEY_MAX/8 + 1];
struct input_event evt;
int fd;
memset(key_states, 0, sizeof(key_states));
fd = open(EVDEV, O_RDWR);
ioctl(fd, EVIOCGKEY(sizeof(key_states)), key_states);
// Create some inconsistency
printf("Type (lots) now to make evdev drop events from the queue\n");
sleep(5);
printf("\n");
while(read(fd, &evt, sizeof(struct input_event)) > 0) {
if(evt.type == EV_SYN && evt.code == SYN_DROPPED) {
printf("Received SYN_DROPPED. Restart.\n");
fsync(fd);
ioctl(fd, EVIOCGKEY(sizeof(key_states)), key_states);
}
else if(evt.type == EV_KEY) {
// Ignore repetitions
if(evt.value > 1) continue;
key_states[evt.code / 8] ^= 1 << (evt.code % 8);
if((key_states[evt.code / 8] >> (evt.code % 8)) & 1 != evt.value) {
printf("Inconsistency detected: Keycode %d is reported as %d, but %d is stored\n", evt.code, evt.value,
(key_states[evt.code / 8] >> (evt.code % 8)) & 1);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
启动后,程序会故意等待5秒钟.在那段时间点击一些键来填充缓冲区.在我的系统上,我需要输入大约70个字符来触发a SYN_DROPPED.该EV_KEY处理代码检查,如果该事件是由报告的状态保持一致EVIOCGKEY的ioctl.
| 归档时间: |
|
| 查看次数: |
2493 次 |
| 最近记录: |