2010-03-30 7 views
4

나는 악명 높은 /dev/input/event*에서 데이터를 읽는 Perl 스크립트를 작성 중이며 커널로 생성 된 키 코드를 ASCII로 변환하는 방법을 찾지 못했습니다.Perl에서/dev/input/event *의 Linux 키 코드를 ASCII로 변환하려면 어떻게해야합니까?

나는이 테이블에있는 리눅스 키 코드에 대해 얘기하고 있습니다. here 나는 스크립트에 배열을 하드 코딩하지 않고도 번역 할 수있는 뭔가를 찾지 못하는 것 같습니다. 내가 놓친 게 있니?

나는 좋은 연습이 아니기 때문에 배열 부분을 건너 뛰고 싶습니다. 그래서 어떤 생각입니까? :)

답변

5

기본적으로지도 문제입니다. 키 코드를 가져 와서 ASCII 코드를 찾아야합니다. "배열 부분"은 좋은 연습이 아니라고 생각합니까?

CPAN에서이 모듈을 보지 못했지만 업로드 할 수있는 기회가 있음을 의미합니다. :)

9

불행히도, 나는 Perl로 프로그래밍하지 않지만 여기에 C로 작성된 간단한 예제가 있습니다. 그럼에도 불구하고 아마도 도움이 될 것입니다.

/* 
* Based on keytable.c by Mauro Carvalho Chehab 
* 
* This program is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published by 
* the Free Software Foundation, version 2 of the License. 
* 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
* GNU General Public License for more details. 
*/ 

#include <stdlib.h> 
#include <stdio.h> 
#include <fcntl.h> 

#include <linux/input.h> 

#include <string.h> 
#include <linux/input.h> 
#include <sys/ioctl.h> 

#define KEY_RELEASE 0 
#define KEY_PRESS 1 
#define KEY_KEEPING_PRESSED 2 

#include "parse.h" 

void prtcode(int codes) { 
    struct parse_key *p; 

    for (p = keynames; p->name != NULL; p++) { 
     if (p->value == (unsigned) codes) { 
      printf("scancode %s (0x%02x)\n", p->name, codes); 
      return; 
     } 
    } 

    if (isprint(codes)) { 
     printf("scancode '%c' (0x%02x)\n", codes, codes); 
    } else { 
     printf("scancode 0x%02x\n", codes); 
    } 
} 

int main (int argc, char *argv[]) { 
    int i, fd; 
    struct input_event ev[64]; 

    if (argc != 2) { 
     fprintf(stderr, "usage: %s event-device (/dev/input/eventX)\n", argv[0]); 
     return 1; 
    } 

    if ((fd = open(argv[1], O_RDONLY)) < 0) { 
     perror("Couldn't open input device"); 
     return 1; 
    } 

    while (1) { 
     size_t rb = read(fd, ev, sizeof(ev)); 

     if (rb < (int) sizeof(struct input_event)) { 
      perror("short read"); 
      return 1; 
     } 

     for (i = 0; i < (int) (rb/sizeof(struct input_event)); i++) { 
      if (EV_KEY == ev[i].type) { 
       if ((ev[i].value == KEY_PRESS) || (ev[i].value == KEY_KEEPING_PRESSED)) { 
        prtcode(ev[i].code); 
        printf("type %d code %d value %d\n", ev[i].type, ev[i].code, ev[i].value); 
        printf("\n"); 
       } 
      } 
     } 
    } 

    return 0; 
} 

parse.h를 생성 들어, Makefile에이를 넣어 :

parse.h: /usr/include/linux/input.h 
    @echo generating parse.h 
    @echo -en "struct parse_key {\n\tchar *name;\n\tunsigned int value;\n} " >parse.h 
    @echo -en "keynames[] = {\n" >>parse.h 

    @more /usr/include/linux/input.h |perl -n \ 
    -e 'if (m/^\#define\s+(KEY_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \ 
    -e '{ printf "\t{\"%s\", %s},\n",$$1,$$2; }' \ 
    -e 'if (m/^\#define\s+(BTN_[^\s]+)\s+(0x[\d\w]+|[\d]+)/) ' \ 
    -e '{ printf "\t{\"%s\", %s},\n",$$1,$$2; }' \ 
    >> parse.h 
    @echo -en "\t{ NULL, 0}\n};\n" >>parse.h 

를 그런 다음, 다음과 같이 사용 :

./keytable /dev/input/by-path/platform-i8042-serio-0-event-kbd 
+0

공유해 주셔서 감사합니다. 바코드를 읽는 장치에서 ARM7을 사용하는 것이 유용하다는 것을 알게되었습니다. – shwink

1

예 1 위로 동일한 키를 당신에게 제공 이미 리눅스 커널에서 온 코드 값. 예를 들어 'a'키를 누를 때 KEY_A 0x1e를 얻습니다. 당신이 원한다면 (그리고 내가 원하는 것은) 아스키 변환이므로 'a'를 누르면 소문자는 0x61을, 대문자는 0x41을보고 싶습니다.

+0

키섬으로 위의 키 코드 변환'KeySym ks = XKeycodeToKeysym (dpy, keycode + min_keycode, modifier);'([링크] (http://tronche.com/gui/x/xlib/utilities/keyboard/XKeycodeToKeysym) .wtml)) 은 이미 widechar (유니 코드)를 제공해야합니다 ... 'printf ("넓은 문자 : % lc \ n", (wchar_t) ks);' – olivervbk