2014-11-21 9 views
4

gpio-keys 장치 드라이버를 사용하여 Linux가 실행되는 임베디드 장치의 일부 단추를 처리하고 있습니다. 사용자 공간의 응용 프로그램은 /dev/input/eventX을 열고 루프에서 입력 이벤트를 읽을 수 있습니다.Linux 입력 장치 이벤트, 초기 상태 검색 방법

제 질문은 버튼의 초기 상태를 얻는 방법입니다. 이것을 위해 사용할 수있는 ioctl 호출 (EVIOCGKEY)이 있습니다. 그러나 먼저 이것을 확인한 다음 /dev/input/eventX에서 읽기 시작하면 상태가 바뀌지 않았 음을 보장 할 방법이 없습니다.

제안 사항?

답변

6

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에 의해보고 된 상태와 일치하는지 확인합니다.

+0

매우 도움이됩니다. – Grodriguez