Lo más probable es que los dispositivos obtengan un archivo con /dev/input/
nombre eventN
donde N es los diversos dispositivos, como mouse, teclado, conector, botones de encendido, etc.
ls -l /dev/input/by-{path,id}/
debería darte una pista.
Mira también:
cat /proc/bus/input/devices
Donde el Sysfs
valor es el camino bajo /sys
.
Puedes probar por ej.
cat /dev/input/event2 # if 2 is kbd.
Para implementar use ioctl y verifique dispositivos + monitor.
EDITAR 2:
OKAY. Estoy ampliando esta respuesta en función de la suposición /dev/input/eventN
utilizada.
Una forma podría ser:
En el bucle de inicio todos los event
archivos encontrados en /dev/input/
. Use ioctl()
para solicitar bits de eventos:
ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
luego verifique si EV_KEY
-bit está configurado.
IFF configurado y luego verifique las claves:
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), &keybit);
Por ejemplo, si las teclas numéricas son interesantes, compruebe si los bits para KEY_0
- KEY9
y KEY_KP0
para KEY_KP9
.
Se encontraron claves IFF y luego comienza a monitorear el archivo de eventos en el hilo.
Regresar a 1.
De esta manera, debe controlar todos los dispositivos que cumplan con los criterios deseados. No solo puede comprobarlo, por EV_KEY
ejemplo, el botón de encendido tendrá este bit establecido, pero obviamente no tendrá KEY_A
configurado etc.
He visto falsos positivos para claves exóticas, pero para claves normales esto debería ser suficiente. No hay ningún daño directo en la supervisión, por ejemplo, el archivo de eventos para el botón de encendido o un conector, pero usted no emitirá eventos en cuestión (también conocido como código incorrecto).
Más en detalle a continuación.
EDITAR 1:
En lo que respecta a "Explicar esa última declaración ..." . Pasando por la tierra de stackoverflow aquí ... pero:
Una muestra rápida y sucia en C. Tendrá que implementar varios códigos para verificar que realmente obtiene el dispositivo correcto, traducir el tipo de evento, el código y el valor. Por lo general, tecla abajo, tecla arriba, tecla repetida, código clave, etc.
No tengo tiempo, (y es demasiado aquí), para agregar el resto.
Echa un vistazo a linux/input.h
programas como dumpkeys
código de kernel, etc. para códigos de mapeo. P.ejdumpkeys -l
De todos modos:
Ejecutar como por ejemplo:
# ./testprog /dev/input/event2
Código:
#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;
}
EDITAR 2 (continuación):
Tenga en cuenta que si observa /proc/bus/input/devices
, tiene una letra al comienzo de cada línea. Aquí B
significa mapa de bits. Eso es por ejemplo:
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
Cada uno de esos bits corresponde a una propiedad del dispositivo. Que por medio de mapa de bits, 1 indican una propiedad está presente, como se define en 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
Echa un vistazo al /drivers/input/input.{h,c}
árbol de fuentes del núcleo. Un montón de buen código allí. (Por ejemplo, las propiedades de los dispositivos son producidas por esta función ).
Cada uno de estos mapas de propiedades puede ser alcanzado por ioctl
. Por ejemplo, si desea verificar qué propiedades de LED están disponibles, diga:
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), &ledbit);
Mira la definición de struct input_dev
in input.h
para ver cómo ledbit
se definen.
Para verificar el estado de los LED, diga:
ioctl(fd, EVIOCGLED(sizeof(ledbit)), &ledbit);
Si el bit 1 de entrada ledbit
es 1, se enciende el bloqueo numérico. Si el bit 2 es 1, se enciende el bloqueo de mayúsculas, etc.
input.h
tiene los distintos define.
Notas cuando se trata de monitoreo de eventos:
El seudocódigo para el monitoreo podría ser algo en la dirección 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
Algunos documentos relacionados:
Documentation/input/input.txt
esp. nota sección 5.
Documentation/input/event-codes.txt
, descripción de varios eventos, etc. Tome nota de lo que se menciona, por ejemplo, EV_SYN
sobreSYN_DROPPED
Documentation/input
... lee el resto si quieres.
/dev/disk/by-id/
están creadas porudev
: la pregunta es si está disponible en este caso particular (plataforma integrada).by-id
es correcto Por ejemplo, mi teclado USB está disponible como/dev/input/by-id/usb-_USB_Keyboard-event-kbd
y/dev/input/by-path/pci-0000:00:1d.2-usb-0:2:1.0-event-kbd
.