2010-03-30 5 views
4

J'écris un script Perl qui lit les données de l'infâme /dev/input/event* et je n'ai pas trouvé un moyen de traduire les codes clés générés par le noyau en ASCII. Je parle des codes de clés Linux dans ce tableau here et je n'arrive pas à trouver quelque chose qui m'aiderait à les traduire sans coder en dur un tableau dans le script. Est-ce que je manque quelque chose?Comment puis-je traduire les codes-clés Linux de/dev/input/event * en ASCII en Perl?

Je voudrais sauter la partie tableau parce que cela ne semble pas être une bonne pratique, donc une idée? :)

Répondre

5

C'est fondamentalement un problème de carte. Vous devez prendre un code clé et rechercher son équivalent ASCII. Qu'en est-il de la «partie tableau», à votre avis, n'est-ce pas une bonne pratique?

Je n'ai pas vu de module pour cela sur CPAN, mais cela signifie que vous avez une chance d'être le premier à le télécharger. :)

9

Malheureusement, je ne programme pas en Perl mais voici un exemple simple écrit en C. Peut-être que cela pourrait quand même vous aider.

/* 
* 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; 
} 

Pour générer le parse.h, mettez ceci dans votre 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 

Ensuite, l'utiliser comme ceci:

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

Merci pour le partage. Je l'ai trouvé utile avec ARM7 sur un appareil qui lit un code à barres. – shwink

1

Exemple 1 ne vous rend la même clé les valeurs de code qui proviennent déjà du noyau linux. Par exemple vous obtenez KEY_A 0x1e pour une touche 'a'. Ce que vous voulez est (et ce que je veux) est la conversion ascii donc si 'a' est pressé je veux voir 0x61 pour les minuscules et 0x41 pour les majuscules.

+0

Conversion du code clé ci-dessus en un Keysym avec 'KeySym ks = XKeycodeToKeysym (dpy, code clé + minkeycode, modificateur);' ([lien] (http://tronche.com/gui/x/xlib/utilities/keyboard/XKeycodeToKeysym .html)) devrait déjà vous donner le widechar (unicode) ... 'printf (" large char:% lc \ n ", (wchar_t) ks);' – olivervbk

Questions connexes