Les périphériques obtiennent très probablement un fichier /dev/input/
nommé eventN
où N correspond aux différents périphériques tels que la souris, le clavier, la prise, les boutons d'alimentation, etc.
ls -l /dev/input/by-{path,id}/
devrait vous donner un indice.
Regardez aussi:
cat /proc/bus/input/devices
Où la Sysfs
valeur est le chemin sous /sys
.
Vous pouvez tester par exemple
cat /dev/input/event2 # if 2 is kbd.
Pour implémenter, utilisez ioctl et vérifiez les périphériques + moniteur.
EDIT 2:
D'ACCORD. Je développe cette réponse en partant de l'hypothèse que l' /dev/input/eventN
on utilise.
Une façon pourrait être:
Au démarrage boucle tous les event
fichiers trouvés dans /dev/input/
. Utilisez ioctl()
pour demander des bits d'événement:
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
puis vérifiez si EV_KEY
-bit est défini.
IFF réglé puis vérifiez les clés:
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
Par exemple, si les touches numériques sont intéressantes, vérifiez si les bits pour KEY_0
- KEY9
et KEY_KP0
pour KEY_KP9
.
Les clés IFF ont été trouvées, puis démarrent la surveillance du fichier d'événements dans le thread.
Retour à 1.
De cette façon, vous devriez pouvoir surveiller tous les appareils qui répondent aux critères souhaités. Vous ne pouvez pas seulement vérifier car, EV_KEY
par exemple, le bouton d'alimentation aura ce bit défini, mais il n'aura évidemment pas KEY_A
défini etc.
J'ai vu des faux positifs pour les clés exotiques, mais pour les clés normales, cela devrait suffire. Il n'y a pas de préjudice direct dans la surveillance, par exemple un fichier d'événements pour le bouton d'alimentation ou une prise, mais ceux-ci n'émettront pas les événements en question (aka. Mauvais code).
Plus en détail ci-dessous.
EDIT 1:
En ce qui concerne "Expliquez cette dernière déclaration…" . Aller ici dans le stackoverflow … mais:
Un exemple rapide et sale en C. Vous devrez implémenter divers codes pour vérifier que vous obtenez réellement le bon périphérique, traduire le type d'événement, le code et la valeur. Typiquement, clé en bas, clé en haut, répétition de clé, code de clé, etc.
Je n'ai pas le temps (et c'est trop ici) d'ajouter le reste.
Découvrez linux/input.h
, des programmes comme dumpkeys
, le code du noyau, etc. pour les codes de mappage. Par exempledumpkeys -l
De toute façon:
Exécuter comme par exemple:
# ./testprog /dev/input/event2
Code:
#include <stdio.h>
#include <string.h> /* strerror() */
#include <errno.h> /* errno */
#include <fcntl.h> /* open() */
#include <unistd.h> /* close() */
#include <sys/ioctl.h> /* ioctl() */
#include <linux/input.h> /* EVIOCGVERSION ++ */
#define EV_BUF_SIZE 16
int main(int argc, char *argv[])
{
int fd, sz;
unsigned i;
/* A few examples of information to gather */
unsigned version;
unsigned short id[4]; /* or use struct input_id */
char name[256] = "N/A";
struct input_event ev[EV_BUF_SIZE]; /* Read up to N events ata time */
if (argc < 2) {
fprintf(stderr,
"Usage: %s /dev/input/eventN\n"
"Where X = input device number\n",
argv[0]
);
return EINVAL;
}
if ((fd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr,
"ERR %d:\n"
"Unable to open `%s'\n"
"%s\n",
errno, argv[1], strerror(errno)
);
}
/* Error check here as well. */
ioctl(fd, EVIOCGVERSION, &version);
ioctl(fd, EVIOCGID, id);
ioctl(fd, EVIOCGNAME(sizeof(name)), name);
fprintf(stderr,
"Name : %s\n"
"Version : %d.%d.%d\n"
"ID : Bus=%04x Vendor=%04x Product=%04x Version=%04x\n"
"----------\n"
,
name,
version >> 16,
(version >> 8) & 0xff,
version & 0xff,
id[ID_BUS],
id[ID_VENDOR],
id[ID_PRODUCT],
id[ID_VERSION]
);
/* Loop. Read event file and parse result. */
for (;;) {
sz = read(fd, ev, sizeof(struct input_event) * EV_BUF_SIZE);
if (sz < (int) sizeof(struct input_event)) {
fprintf(stderr,
"ERR %d:\n"
"Reading of `%s' failed\n"
"%s\n",
errno, argv[1], strerror(errno)
);
goto fine;
}
/* Implement code to translate type, code and value */
for (i = 0; i < sz / sizeof(struct input_event); ++i) {
fprintf(stderr,
"%ld.%06ld: "
"type=%02x "
"code=%02x "
"value=%02x\n",
ev[i].time.tv_sec,
ev[i].time.tv_usec,
ev[i].type,
ev[i].code,
ev[i].value
);
}
}
fine:
close(fd);
return errno;
}
EDIT 2 (suite):
Notez que si vous regardez, /proc/bus/input/devices
vous avez une lettre au début de chaque ligne. Ici B
signifie bitmap. C'est par exemple:
B: PROP=0
B: EV=120013
B: KEY=20000 200 20 0 0 0 0 500f 2100002 3803078 f900d401 feffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7
Chacun de ces bits correspond à une propriété de l'appareil. Ce qui signifie par bitmap, 1 indique qu'une propriété est présente, comme défini dans linux/input.h
. :
B: PROP=0 => 0000 0000
B: EV=120013 => 0001 0010 0000 0000 0001 0011 (Event types sup. in this device.)
| | | ||
| | | |+-- EV_SYN (0x00)
| | | +--- EV_KEY (0x01)
| | +------- EV_MSC (0x04)
| +----------------------- EV_LED (0x11)
+--------------------------- EV_REP (0x14)
B: KEY=20... => OK, I'm not writing out this one as it is a bit huge.
B: MSC=10 => 0001 0000
|
+------- MSC_SCAN
B: LED=7 => 0000 0111 , indicates what LED's are present
|||
||+-- LED_NUML
|+--- LED_CAPSL
+---- LED_SCROLL
Jetez un oeil /drivers/input/input.{h,c}
dans l'arborescence des sources du noyau. Beaucoup de bon code là-bas. (Par exemple, les propriétés des appareils sont produites par cette fonction .)
Chacune de ces cartes de propriété peut être atteinte par ioctl
. Par exemple, si vous souhaitez vérifier quelles propriétés de LED sont disponibles, dites:
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), &ledbit);
Regardez la définition de struct input_dev
in input.h
pour savoir comment ledbit
sont définis.
Pour vérifier l'état des LED, dites:
ioctl(fd, EVIOCGLED(sizeof(ledbit)), &ledbit);
Si le bit 1 dans ledbit
est 1, le verrouillage numérique est allumé. Si le bit 2 est 1, le verrouillage des majuscules est allumé, etc.
input.h
a les différentes définitions.
Remarques concernant la surveillance des événements:
Le pseudo-code de surveillance pourrait être quelque chose dans le sens de:
WHILE TRUE
READ input_event
IF event->type == EV_SYN THEN
IF event->code == SYN_DROPPED THEN
Discard all events including next EV_SYN
ELSE
This marks EOF current event.
FI
ELSE IF event->type == EV_KEY THEN
SWITCH ev->value
CASE 0: Key Release (act accordingly)
CASE 1: Key Press (act accordingly)
CASE 2: Key Autorepeat (act accordingly)
END SWITCH
FI
END WHILE
Quelques documents liés:
Documentation/input/input.txt
, esp. note section 5.
Documentation/input/event-codes.txt
, La description de divers événements , etc. Prenez note à ce qui est mentionné dans , par exemple à EV_SYN
propos deSYN_DROPPED
Documentation/input
... lisez le reste si vous voulez.
/dev/disk/by-id/
sont à mon humble avis créées parudev
- la question est de savoir si elles sont disponibles dans ce cas particulier (plateforme embarquée).by-id
c'est correct. Par exemple, mon clavier USB est disponible en tant que/dev/input/by-id/usb-_USB_Keyboard-event-kbd
et/dev/input/by-path/pci-0000:00:1d.2-usb-0:2:1.0-event-kbd
.