6

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

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

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

4

4 回答 4

10

不幸的是,我没有用 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
于 2010-03-31T15:55:31.403 回答
5

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

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

于 2010-03-30T18:54:01.333 回答
1

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

于 2011-12-08T22:04:44.720 回答
0

为了从条形码阅读器读取条形码,我错过了一个简单的应用程序,可以将纯击键输入字符串。到目前为止,进行完整的键盘翻译要容易得多,因为条形码通常包含大部分数字和一些正常的 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
于 2020-07-30T05:27:48.347 回答