【问题标题】:Capture HID keyboard event捕获 HID 键盘事件
【发布时间】:2014-03-05 21:06:28
【问题描述】:

以下代码仅适用于一种输入设备。不幸的是,我需要捕获大约 12 种不同的 HID 设备(RFID 阅读器),所以我想知道是否有人知道如何调整代码以使用 12 种不同的输入?

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

【问题讨论】:

    标签: c++ c linux input hid


    【解决方案1】:

    为每个设备调用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;
    }
    

    【讨论】:

    • 我试过了,但没用。似乎 input_event 只有一个,即使我有两个或更多设备。有什么方法可以检查事件代码(ev[1].code)哪个设备正在发送该信息?
    • 不幸的是,您必须监控每个设备并检测每个设备何时为您提供事件。事件本身并不能识别发送它的设备。我已经用一个例子更新了我的答案。
    • 要“取消抓取”设备,您应该在代码末尾将 0 而不是 1 传递给 ioctl
    猜你喜欢
    • 1970-01-01
    • 2020-03-10
    • 2012-02-01
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    相关资源
    最近更新 更多