c++ - 捕获HID键盘事件

标签 c++ c linux input hid

下面的代码仅适用于一种输入设备。不幸的是,我需要捕获大约 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;
}

最佳答案

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

关于c++ - 捕获HID键盘事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22209267/

相关文章:

c - 确定以像素为单位的棋盘尺寸

c - 如何在netfilter返回NF_DROP后停止后续数据包?

java - 在 Linux 终端中编译项目不起作用

c++ - 如何实现类似 "single instance"的设计?

c - C中的直角三角形

c++ - 如何从 QStringList 中删除空字符串和空字符串?

linux - 需要一些关于 shell 脚本的帮助(使用 grep 命令)

linux - Squid3 用户验证但没有数据服务器

c++ - 在 Rcpp 中为具有重复迭代的模型正确设置 GSL RNG 种子

c++ - 在 C++ 中循环生成随机对象