6

Linux を実行している組み込みデバイスのいくつかのボタンを処理するために、gpio-keysデバイス ドライバーを使用しています。ユーザー空間のアプリケーションは/dev/input/eventX、ループ内で入力イベントを開いて読み取ることができます。

私の質問は、ボタンの初期状態を取得する方法です。EVIOCGKEYこれに使用できるioctl 呼び出し ( ) がありますが、最初にこれを確認してから から読み取りを開始する/dev/input/eventXと、その間に状態が変化しなかったことを保証する方法はありません。

助言がありますか?

4

1 に答える 1

10

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);
            }
        }
    }
}

起動後、プログラムは意図的に 5 秒間待機します。その間にいくつかのキーを押して、バッファーを埋めます。私のシステムでは、約 70 文字を入力してSYN_DROPPED. 処理コードは、イベントがioctlEV_KEYによって報告された状態と一致しているかどうかをチェックします。EVIOCGKEY

于 2014-11-26T08:57:37.653 に答える