2011-10-05 14 views
14

Tengo un dispositivo USB RFID que se registra como un dispositivo HID (un teclado USB más o menos).Necesito interceptar eventos del teclado HID (y luego bloquearlos)

Estoy buscando una forma de capturar esta entrada, y bloquearla/filtrarla antes de que golpee el controlador de eventos del teclado normal (y saca el código RFID de 10 dígitos a la consola).

Por supuesto, tengo que capturar exclusivamente este dispositivo y dejar solo la entrada del teclado real (o pasarlo).

Mi idea inicial era bloquear el dispositivo en UDEV (por lo que el módulo usbhid/event/kbd kernel no se enlazaba a él) y escribir mi propio controlador básico para este dispositivo, pero no sé por dónde empezar , o si eso incluso funciona

Lo que sería genial (y no estoy seguro de que se pueda hacer) - es si escribo un módulo de filtro de eventos que pueda estar en línea con el controlador de eventos y capture (luego filtre) el entrada apropiada de la unidad de RFID, pero deje que todo lo demás pase. Me imagino que tal módulo no requeriría mucho código, y sería el más práctico.

¿Ayuda?

[EDIT: Debo añadir que Xorg NO está instalado - consola sólo]

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) 
+0

Creo que [este SO post] (http://stackoverflow.com/questions/1698423/how-can-you -take-ownership-of-a-hid-device) podría tener la respuesta que estoy buscando ... – Litch

Respuesta

6

Puede usar ioctl EVIOCGRAB en un dispositivo de evento para capturar de manera exclusiva.

16

Así que nos prepararon rápidamente una aplicación de prueba de concepto de acuerdo con ese post que encontré here

Hace exactamente lo que necesito - solo aunque me gustaría compartir mi solución de todos modos.

#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; 
} 
+0

debe llamar a sleep() antes de tomar la entrada, de lo contrario puede bloquear la versión ENTER al ejecutar el binario compilado. – olivervbk

+0

@Litch No entendí cómo se filtran los eventos. Acabas de bloquearlos, pero ¿cómo vas a propagar los eventos? – WscriChy

+0

@ WscriChy No creo que Litch intentara propagar los eventos. Para empezar, su base de código era el consumidor. Estoy buscando una solución similar. En mi caso, sin embargo, tengo que interceptar parte de los eventos que salen del feed de entrada, pero propagar otros ... por lo que mi tarea se parece más a la que estás pensando. – Svartalf

0

Ungrabbing requiere un parámetro de "falso" valor, como a continuación:

result = ioctl(fevdev, EVIOCGRAB, 0); 
Cuestiones relacionadas