2010-03-30 31 views
4

我正在写一个Perl脚本,它从臭名昭着的/dev/input/event*中读取数据,但我没有找到将内核生成的密钥代码转换为ASCII的方法。如何在Linux中将Linux密钥从/ dev/input/event *转换为ASCII?

我在说这个表中的linux键码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 2018-02-02 03:56:02

1

例1只给你回相同的密钥代码值已经来自linux内核。例如,您获得KEY_A 0x1e用于'a'按键。你想要的是(和我想要的)是ascii转换,所以如果按'a'我想看到0x61为小写字母,0x41为大写字母。

+0

KeySym ks = XKeycodeToKeysym(dpy,keycode + min_keycode,modifier);'([link](http://tronche.com/gui/x/xlib/utilities/keyboard/XKeycodeToKeysym) .html)) 应该已经给你了widechar(unicode)... 'printf(“wide char:%lc \ n”,(wchar_t)ks);' – olivervbk 2013-09-17 02:10:38