【问题标题】:How can I translate Linux keycodes from /dev/input/event* to ASCII in Perl?如何在 Perl 中将 Linux 键码从 /dev/input/event* 转换为 ASCII?
【发布时间】:2010-03-30 18:27:08
【问题描述】:

我正在编写一个从臭名昭著的/dev/input/event* 读取数据的 Perl 脚本,但我没有找到将内核生成的关键代码转换为 ASCII 的方法。

我说的是这张表here 中的 linux 键码,我似乎找不到可以帮助我翻译它们的东西,而无需将数组硬编码到脚本中。我错过了什么吗?

我想跳过数组部分,因为这似乎不是一个好习惯,所以有什么想法吗? :)

【问题讨论】:

    标签: linux perl ascii keycode


    【解决方案1】:

    很遗憾,我不会用 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
    

    【讨论】:

    • 感谢分享。我发现它在读取条形码的设备上使用 ARM7 很有用。
    【解决方案2】:

    这基本上是一个地图问题。您必须获取一个键码并查找其 ASCII 等价物。 “数组部分”你认为不是一个好的做法吗?

    我没有在 CPAN 上看到此模块,但这意味着您有机会成为第一个上传它的人。 :)

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 使用 KeySym ks = XKeycodeToKeysym(dpy, keycode+min_keycode, modifier); (link) 将上面的键码转换为 Keysym 应该已经为您提供了宽字符(unicode)...printf ("wide char:%lc\n", (wchar_t)ks);
      【解决方案4】:

      为了从条形码阅读器读取条形码,我错过了一个简单的应用程序,可以将纯击键输入字符串。到目前为止,进行完整的键盘翻译要容易得多,因为条形码通常包含大部分数字和一些正常的 ascii 字符。 所以,也许,这个简单的 python3 脚本可以帮助其他人开始。它需要python3-evdev 作为库。 当然,您可能需要调整InputDevice。这适用于曼哈顿读者。

      from evdev import InputDevice, categorize, ecodes
      
      dev = InputDevice('/dev/input/by-id/usb-040b_6543-if01-event-kbd')
      
      print(dev)
      
      shiftPressed = False
      ctrlPressed = False
      string = ""
      
      for event in dev.read_loop():
          if event.type == ecodes.EV_KEY:
              keyEvent = categorize(event)
              # handle release of special keys
              if keyEvent.keystate == 0:
                  if keyEvent.keycode=="KEY_LEFTSHIFT":
                      shiftPressed = False
                      continue
                  if keyEvent.keycode=="KEY_LEFTCTRL":
                      ctrlPressed = False
                      continue
              # handle key presses
              if keyEvent.keystate == 1:
                  if keyEvent.keycode=="KEY_LEFTSHIFT":
                      shiftPressed = True
                      continue
                  if keyEvent.keycode=="KEY_LEFTCTRL":
                      ctrlPressed = True
                      continue
                  if ctrlPressed:
                      continue
      
                  key = keyEvent.keycode[4:]
      
                  if key == "ENTER":
                      print(string)
                      string = ""
                      continue
      
                  dict2 = {"Z" : "Y", "Y": "Z"}
                  if key in dict2:
                      key = dict2[key]
      
                  if not (shiftPressed):
                      key = key.lower()
                  else:
                      dict = {"0" : "=",
                              "1" : "!",
                              "2" : "\"",
                              "3" : "§",
                              "4" : "$",
                              "5" : "%",
                              "6" : "&",
                              "7" : "/",
                              "8" : "(",
                              "9" : ")"}
                      if key in dict:
                          key = dict[key]
                  string+=key
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-20
        • 1970-01-01
        • 2021-10-13
        • 1970-01-01
        • 2011-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多