在Linux下使用ioctl重新映射键盘

4

我正在尝试编写一个小程序,在Linux下捕获特定USB键盘的全局键盘输入。

我正在使用以下代码进行测试:

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>

static const char *const evval[3] = {
    "RELEASED",
    "PRESSED ",
    "REPEATED"
};

int main(void)
{
    const char *dev = "/dev/input/event2";
    struct input_event ev;
    ssize_t n;
    int fd;
    char name[256]= "Unknown";

//    int codes[2];

//    codes[0] = 58; /* M keycap */
//    codes[1] = 49; /* assign to N */

    fd = open(dev, O_RDONLY);
    if (fd == -1) {
        fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
        return EXIT_FAILURE;
    }

    if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) 
    {
        printf("The device on %s says its name is '%s'\n", dev, name);
    }

    /*
    int err = ioctl(fd, EVIOCSKEYCODE, codes);
    if (err) {
        perror("evdev ioctl");
    }*/

    while (1) {
        n = read(fd, &ev, sizeof ev);
        if (n == (ssize_t)-1) {
            if (errno == EINTR)
                continue;
            else
                break;
        } else
        if (n != sizeof ev) {
            errno = EIO;
            break;
        }

        if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
            printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);

    }

    fflush(stdout);
    fprintf(stderr, "%s.\n", strerror(errno));

    return EXIT_FAILURE;
}

问题在于我不知道如何用其他键来更改某些输入键。我尝试通过调用 write() 函数,修改当前输入事件的事件代码,但发送的键仍然是之前的那个键。我还尝试使用 ioctl 与 EVIOCSKEYCODE,但调用失败并出现“无效参数”错误(我也不确定是否正确调用了它)。

请问如何正确更改输出键?

1个回答

3
使用EVIOCGRAB ioctl来获取输入设备,以便通过读取事件来消耗它们。通常情况下(未获取),当您读取事件时,它们不会被消耗。ioctl需要一个附加参数,(int)1表示获取,(int)0表示释放。
要重新注入任何事件,只需将它们写入uinput设备即可。例如,参见此处的鼠标示例。(事件结构是相同类型的,您只需要首先向uinput设备写入一个struct uinput_user_dev结构来描述您的新输入设备(提供映射的事件))。
换句话说,您不需要重新映射:您只需消耗和转发即可。

所以如果我理解正确,我从我的真实事件设备中获取数据,但是我将数据写入虚拟的“uinput”设备?这样对吗? - sigz
@sigzegv:是的。请注意,您只需要使用一次ioctl;然后您可以正常读取事件。ioctl只是告诉内核,通过读取它们来消耗事件。通常,在未抓取模式下,即使您读取它们,事件也会被内核和其他应用程序处理。 - Nominal Animal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接