كيف يمكنني ترجمة رموز مفاتيح Linux من/dev/input/event* إلى ASCII في Perl؟

StackOverflow https://stackoverflow.com/questions/2547616

  •  23-09-2019
  •  | 
  •  

سؤال

أنا أكتب نصًا بيرل يقرأ البيانات من الشهرة /dev/input/event* ولم أجد طريقة لترجمة رموز المفاتيح التي تم إنشاؤها بواسطة kernel إلى ASCII.

أنا أتحدث عن رموز مفاتيح Linux في هذا الجدول هنا ولا يمكنني العثور على شيء من شأنه أن يساعدني في ترجمتها دون ترميز صفيف في البرنامج النصي. هل فاتني شيء؟

أرغب في تخطي جزء المصفوفة لأنه لا يبدو ممارسة جيدة ، لذلك أي فكرة؟ قون

هل كانت مفيدة؟

المحلول

إنها في الأساس مشكلة في الخريطة. عليك أن تأخذ رمز المفاتيح والبحث عن مكافئ ASCII. ماذا عن "جزء الصفيف" هل تعتقد أنه ليس ممارسة جيدة؟

لم أر وحدة لهذا النمط على CPAN ، لكن هذا يعني أن لديك فرصة لتكون أول من يقوم بتحميله. قون

نصائح أخرى

لسوء الحظ ، أنا لا أبرمج في بيرل ولكن هنا مثال بسيط مكتوب في 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

مثال 1 يمنحك فقط نفس قيم رمز المفاتيح التي تأتي بالفعل من Kernel Linux. على سبيل المثال ، يمكنك الحصول على key_a 0x1e للحصول على مفتاح "A". ما تريده هو (وما أريده) هو تحويل ASCII ، لذا إذا تم الضغط على "A" ، فأنا أريد أن أرى 0x61 للحالة السفلية و 0x41 للحالة العليا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top