在linux下用ioctl重新映射键盘

在linux下用ioctl重新映射键盘,c,linux,keyboard-events,ioctl,C,Linux,Keyboard Events,Ioctl,实际上,我正在尝试编写一个小程序,以捕获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 co

实际上,我正在尝试编写一个小程序,以捕获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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
静态常量字符*常量evval[3]={
“释放”,
“按下”,
“重复”
};
内部主(空)
{
const char*dev=“/dev/input/event2”;
结构输入\事件ev;
(三);
int-fd;
字符名[256]=“未知”;
//int码[2];
//代码[0]=58;/*M键帽*/
//代码[1]=49;/*分配给N*/
fd=打开(仅适用于开发人员);
如果(fd==-1){
fprintf(标准,“无法打开%s:%s.\n”,开发人员,strerror(errno));
返回退出失败;
}
如果(ioctl(fd,eviogname(sizeof(name)),name)>0)
{
printf(“%s上的设备称其名称为“%s”\n”,dev,name);
}
/*
int err=ioctl(fd、EVIOCSKEYCODE、代码);
如果(错误){
perror(“evdev ioctl”);
}*/
而(1){
n=读取(fd和ev,ev大小);
如果(n==(ssize_t)-1){
如果(errno==EINTR)
继续;
其他的
打破
}否则
如果(n!=电动汽车的尺寸){
errno=EIO;
打破
}

如果(ev.type==ev_KEY&&ev.value>=0&&ev.value使用EVIOCGRAB ioctl抓取输入设备,以便通过读取事件来消耗它们。通常(未抓取)在读取事件时不会消耗事件。ioctl采用附加参数,
(int)1
进行抓取,
(int)0
进行释放

要重新注入任何事件,只需将它们写入
uinput
设备。参见示例a。(事件结构是相同的类型,您只需先将
struct uinput\u user\u dev
结构写入
uinput
设备,即可描述新的输入设备(它提供映射的事件)。)


换句话说,您不需要重新映射:您需要消费和转发。

因此,如果我理解,我会从我的真实事件设备抓取,但我会写入虚拟的“uinput”设备?正确吗?@sigzegv:是的。请注意,您只需要使用ioctl一次;然后您就可以正常读取事件。ioctl只是告诉内核您通过读取事件来消耗事件。通常,在未捕获模式下,即使您读取了事件,内核和其他应用程序也会处理事件。