2011-10-05 6 views
14

Mam urządzenie RFID USB, które rejestruje się jako urządzenie HID (klawiatura USB mniej lub więcej).Konieczność przechwycenia zdarzeń klawiatury HID (a następnie ich zablokowanie)

Szukam sposobu przechwytywania tego wejścia i blokowania/filtrowania go, zanim trafi on w zwykły moduł obsługi zdarzeń klawiatury (i wyświetli 10-cyfrowy kod RFID do konsoli).

Oczywiście musiałbym przechwycić wyłącznie to urządzenie i pozostawić prawdziwe wejście klawiatury samodzielnie (lub przekazać je dalej).

Moim początkowym pomysłem było zablokowanie urządzenia w UDEV (więc moduł jądra usbhid/event/kbd nie był do niego podłączony) i napisanie własnego podstawowego sterownika dla tego urządzenia - ale nie wiem od czego zacząć , lub jeśli to nawet zadziała.

Co byłoby świetne (i nie jestem pewien, czy coś takiego można zrobić) - jest, jeśli napiszę moduł filtru zdarzeń, który może siedzieć w linii ze sterownikiem zdarzeń i przechwycić (a następnie filtrować) odpowiednie wejście z urządzenia RFID, ale niech wszystko inne przejdzie. Wyobrażam sobie, że taki moduł nie wymagałby wiele kodu i byłby najbardziej praktyczny.

Pomoc?

[EDIT: Dodam że Xorg nie jest zainstalowany - konsola tylko]

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 

Więcej informacji:

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

myślę [to SO post] (http://stackoverflow.com/questions/1698423/how-can-you -take-ownership-of-a-hid-device) może mieć odpowiedź, której szukam ... – Litch

Odpowiedz

6

Można użyć EVIOCGRAB ioctl na urządzeniu zdarzenia uchwycić go wyłącznie.

16

Więc bita proof-of-concept aplikacji zgodnie z tym poście znalazłem here

Robi dokładnie to, czego wymaga - tak jakbym dzielić moje rozwiązanie i tak.

#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

powinien wywołać sleep() przed wejściem do przechwytywania, w przeciwnym razie może zablokować wydanie ENTER podczas wykonywania skompilowanego pliku binarnego. – olivervbk

+0

@Litch Nie rozumiem, jak filtrować zdarzenia. Po prostu je zablokowałeś, ale jak zamierzasz propagować te wydarzenia? – WscriChy

+0

@WscriChy Nie sądzę, że Litch próbował propagować zdarzenia. Jego baza kodów była na początku konsumentem. Szukam podobnego rozwiązania. Jednak w moim przypadku muszę przechwycić część wydarzeń wychodzących z kanału wejściowego, ale propagować innych ... więc moje zadanie jest bardziej podobne do tego, o którym myślisz. – Svartalf

0

Ungrabbing wymaga "false" parametr wartości, jak poniżej:

result = ioctl(fevdev, EVIOCGRAB, 0);