linux - Necesidad de interceptar eventos del teclado HID(y luego bloquearlos)
keyboard-events (3)
Tengo un dispositivo USB RFID que se registra como un dispositivo HID (un teclado USB más o menos).
Estoy buscando una forma de capturar esta entrada y bloquearla / filtrarla antes de que llegue al controlador de eventos del teclado (y envía el código RFID de 10 dígitos a la consola).
Por supuesto, tendría que capturar exclusivamente solo este dispositivo y dejar la entrada del teclado real sola (o pasarla).
Mi idea inicial fue bloquear el dispositivo en UDEV (por lo que el módulo del kernel usbhid / event / kbd no se unió a él) y escribir mi propio controlador básico para este dispositivo, pero no sé por dónde empezar, o si Incluso trabajaré.
Lo que sería genial (y no estoy seguro de si se puede hacer tal cosa) es si escribo un módulo de filtro de eventos que pueda estar en línea con el controlador de eventos y capturar (luego filtrar) la entrada apropiada del Unidad RFID, pero deja pasar todo lo demás. Me imagino que un módulo de este tipo no requeriría mucho código y sería el más práctico.
¿Ayuda?
[EDITAR: debo agregar que Xorg NO está instalado - solo consola]
cat /proc/bus/input:
I: Bus=0003 Vendor=0419 Product=0912 Version=0100
N: Name="NewRoad Sem. NewRoad System PS2 Interface"
P: Phys=usb-0000:00:1d.3-2/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.3/usb5/5-2/5-2:1.0/input/input20
U: Uniq=
H: Handlers=sysrq kbd mouse0 event3
B: PROP=0
B: EV=120017
B: KEY=70000 0 0 e080ffdf01cfffff fffffffffffffffe
B: REL=103
B: MSC=10
B: LED=1f
Más información:
lsusb -d 0419:0912 -v
Bus 005 Device 019: ID 0419:0912 Samsung Info. Systems America, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0419 Samsung Info. Systems America, Inc.
idProduct 0x0912
bcdDevice 0.01
iManufacturer 1 NewRoad Sem.
iProduct 2 NewRoad System PS2 Interface
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 4
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 5
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.00
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 119
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 10
Device Status: 0x0000
(Bus Powered)
Así que preparé una aplicación de prueba de concepto de acuerdo con la publicación que encontré here
Hace exactamente lo que necesito, aunque de todos modos compartiría mi solución.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termios.h>
#include <signal.h>
int main(int argc, char* argv[])
{
struct input_event ev[64];
int fevdev = -1;
int result = 0;
int size = sizeof(struct input_event);
int rd;
int value;
char name[256] = "Unknown";
char *device = "/dev/input/event3";
fevdev = open(device, O_RDONLY);
if (fevdev == -1) {
printf("Failed to open event device./n");
exit(1);
}
result = ioctl(fevdev, EVIOCGNAME(sizeof(name)), name);
printf ("Reading From : %s (%s)/n", device, name);
printf("Getting exclusive access: ");
result = ioctl(fevdev, EVIOCGRAB, 1);
printf("%s/n", (result == 0) ? "SUCCESS" : "FAILURE");
while (1)
{
if ((rd = read(fevdev, ev, size * 64)) < size) {
break;
}
value = ev[0].value;
if (value != '' '' && ev[1].value == 1 && ev[1].type == 1) {
printf ("Code[%d]/n", (ev[1].code));
}
}
printf("Exiting./n");
result = ioctl(fevdev, EVIOCGRAB, 1);
close(fevdev);
return 0;
}
Puede usar EVIOCGRAB ioctl en un dispositivo de evento para capturarlo exclusivamente.
Ungrabbing requiere un parámetro de valor "falso", como se muestra a continuación:
result = ioctl(fevdev, EVIOCGRAB, 0);