read()
까지 evdev 장치 queue events이므로 대부분의 경우 장치를 열고 ioctl()
을 실행하고 즉시 이벤트를 읽기 시작해야합니다. 드라이버가 대기열에서 일부 이벤트를 삭제 한 경우 sends you a SYN_DROPPED
event이므로 발생한 상황을 감지 할 수 있습니다. The libevdev documentation에는 그 상황을 어떻게 처리해야하는지에 대한 아이디어가 있습니다. 내가 읽은 방식대로 다시 시도해야합니다. 즉, 보류중인 모든 이벤트를 삭제하고 SYN_DROPPED
이벤트가 없어 질 때까지 ioctl()
을 다시 실행해야합니다.
#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);
}
}
}
}
시작한 후, 프로그램이 의도적으로 5 초 기다립니다 :
나는이 방법이 작동하는지 확인하기 위해이 코드를 사용했다. 그 시간에 일부 키를 눌러 버퍼를 채우십시오. 내 시스템에서는
SYN_DROPPED
을 트리거하기 위해 약 70자를 입력해야합니다.
EV_KEY
처리 코드는 이벤트가
EVIOCGKEY
ioctl에 의해보고 된 상태와 일치하는지 확인합니다.
매우 도움이됩니다. – Grodriguez