2014-03-05 267 views
2

下面的代码只适用于一个输入设备。不幸的是,我需要捕获大约12个不同的HID设备(RFID阅读器),所以我想知道是否有人知道如何使代码适应12种不同的输入?捕捉HID键盘事件

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

回答

2

为每个设备呼叫open(),然后用select()(或(e)poll())来监控所有的文件描述符在一起,这样就可以检测出哪些设备可用的数据则是从read()在任何给定的时刻。

更新:例如:

struct event_device 
{ 
    char *device; 
    int fd; 
}; 

int main(int argc, char* argv[]) 
{ 
    struct input_event ev[64]; 
    int numevents; 
    int result = 0; 
    int size = sizeof(struct input_event); 
    int rd; 
    char name[256]; 
    char* device[12]; 
    event_device evdevs[12], *evdev; 
    int numevdevs = 0; 
    fd_set fds; 
    int maxfd; 

    device[0] = "/dev/input/event3"; 
    device[1] = "/dev/input/event4"; 
    // and so on... 

    for (int i = 0; i < 12; ++i) { 
     evdev = &evdevs[numevdevs]; 

     evdev->device = device[i]; 
     evdev->fd = open(evdev->device, O_RDONLY); 
     if (evdev->fd == -1) { 
      printf("Failed to open event device: %s.\n", evdev->device); 
      continue; 
     } 
     ++numevdevs; 

     memset(name, 0, sizeof(name)); 
     result = ioctl(evdev->fd, EVIOCGNAME(sizeof(name)), name); 
     printf ("Reading From : %s (%s)\n", evdev->device, name); 

     printf("Getting exclusive access: "); 
     result = ioctl(evdev->fd, EVIOCGRAB, 1); 
     printf("%s\n", (result == 0) ? "SUCCESS" : "FAILURE"); 
    } 

    if (numevdevs == 0) { 
     exit(1); 
    } 

    while (1) 
    { 
     FD_ZERO(&fds); 
     maxfd = -1; 

     for (int i = 0; i < numevdevs; ++i) { 
      evdev = &evdevs[i]; 
      FD_SET(evdev->fd, &fds); 
      if (maxfd < evdev->fd) maxfd = evdev->fd; 
     } 

     result = select(maxfd+1, &fds, NULL, NULL, NULL); 
     if (result == -1) { 
      break;   
     } 

     for (int i = 0; i < numevdevs; ++i) { 
      evdev = &evdevs[i]; 

      if (!FD_ISSET(evdev->fd, &fds)) { 
       continue; 
      } 

      if ((rd = read(evdev->fd, ev, size * 64)) < size) { 
       continue; 
      } 

      numevents = rd/size; 
      for (int j = 0; j < numevents; ++j) { 
       printf ("%s: Type[%d] Code[%d] Value[%d]\n", evdev->device, ev[j].type, ev[j].code, ev[j].value); 
      } 
     } 
    } 

    printf("Exiting.\n"); 

    for (int i = 0; i < numevdevs; ++i) { 
     evdev = &evdevs[i]; 
     result = ioctl(evdev->fd, EVIOCGRAB, 0); 
     close(evdev->); 
    } 

    return 0; 
} 
+0

我试过,但didn't工作。看来input_event只有一个,即使我有两个或更多的设备。有什么方法可以检查事件代码(ev [1] .code)哪个设备正在发送该信息? –

+0

不幸的是,你必须监视每个设备并检测每个设备何时给你一个事件。事件本身并不识别发送它的设备。我用一个例子更新了我的答案。 –

+0

非常感谢!它真的按我的意愿工作! –