我正在使用gpio-keys設備驅動程序來處理運行Linux的嵌入式設備中的某些按鈕。用戶空間中的應用程序可以打開/dev/input/eventX
並在循環中讀取輸入事件。Linux輸入設備事件,如何檢索初始狀態
我的問題是如何獲得按鈕的初始狀態。有一個ioctl電話(EVIOCGKEY
)可以用於此,但是如果我首先檢查這個,然後開始從/dev/input/eventX
讀取,則無法保證狀態在兩者之間沒有變化。
有什麼建議嗎?
我正在使用gpio-keys設備驅動程序來處理運行Linux的嵌入式設備中的某些按鈕。用戶空間中的應用程序可以打開/dev/input/eventX
並在循環中讀取輸入事件。Linux輸入設備事件,如何檢索初始狀態
我的問題是如何獲得按鈕的初始狀態。有一個ioctl電話(EVIOCGKEY
)可以用於此,但是如果我首先檢查這個,然後開始從/dev/input/eventX
讀取,則無法保證狀態在兩者之間沒有變化。
有什麼建議嗎?
evdev設備queue events直到你read()
他們,所以在大多數情況下打開設備,做ioctl()
並立即開始從它讀取事件應該工作。如果驅動程序從隊列中刪除了一些事件,它會sends you a SYN_DROPPED
event,因此您可以檢測發生的情況。 The libevdev documentation對如何處理這種情況有一些想法;我讀它的方式,你應該簡單地重試,即放棄所有未決的事件,並重做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);
}
}
}
}
啓動後,節目刻意等待5秒。在那段時間打一些鑰匙來填充緩衝區。在我的系統中,我需要輸入約70個字符才能觸發SYN_DROPPED
。 EV_KEY
處理代碼檢查事件是否與EVIOCGKEY
ioctl報告的狀態一致。
這是非常有幫助的。 – Grodriguez 2014-11-26 16:25:59