Linux下模拟输入设备发送event事件

Linux下的键盘输入设备上报event事件来让系统处理按键的按下和释放动作。实际应用中,会有需要判断外部信号后,模拟event事件,来让上层应用处理这个事件对应的业务功能。此时,可以使用uinput设备来实现这个功能,向uinput设备写入input_event结构的数据,会被模拟为标准的Linux event事件数据,从而让上层业务应用直接处理对应功能。

uinputUserspace Input,uinput 的实现是基于 Linux input子系统(Input Subsystem),允许用户空间程序创建虚拟的输入设备并向内核发送输入事件,比如键盘敲击、鼠标移动等,就像这些事件来自真实的物理设备一样。对于开发自定义输入设备驱动、自动化测试、游戏控制模拟以及各种人机交互实验等场景非常有用。

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

int main() {
    int fd;
    struct uinput_user_dev uidev;
    struct input_event ev;

    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if (fd < 0) {
        perror("Error opening /dev/uinput");
        return 1;
    }

    memset(&uidev, 0, sizeof(uidev));
    strncpy(uidev.name, "Virtual Keyboard", UINPUT_MAX_NAME_SIZE);
    uidev.id.bustype = BUS_USB;
    uidev.id.vendor = 0x1234;
    uidev.id.product = 0x5678;
    uidev.id.version = 1;

    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_KEYBIT, KEY_A);

    write(fd, &uidev, sizeof(uidev));
    ioctl(fd, UI_DEV_CREATE);

    while(1) {
	    sleep(2);

	    memset(&ev, 0, sizeof(ev));

	    ev.type = EV_KEY;
	    ev.code = KEY_A;
	    ev.value = 1; // press
	    write(fd, &ev, sizeof(ev));

	    ev.value = 0; // release
	    write(fd, &ev, sizeof(ev));

	    memset(&ev, 0, sizeof(ev));
	    ev.type = EV_SYN;
	    ev.code = SYN_REPORT;
	    ev.value = 0;
	    write(fd, &ev, sizeof(ev));
    }

    ioctl(fd, UI_DEV_DESTROY);
    close(fd);

    return 0;
}

运行程序后,系统会生成一个虚拟的input设备,可以使用cat命令来查看当前系统中的虚拟设备。

cat /proc/bus/input/devices
I: Bus=0003 Vendor=1234 Product=5678 Version=0001
N: Name="Virtual Keyboard"
P: Phys=
S: Sysfs=/devices/virtual/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=40000000

然后使用evtest命令来查看这个设备是否有上传event事件。

evtest /dev/input/event0
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x1234 product 0x5678 version 0x1
Input device name: "Virtual Keyboard"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 30 (KEY_A)
Properties:
Testing ... (interrupt to exit)
Event: time 1651254109.394687, type 1 (EV_KEY), code 30 (KEY_A), value 1
Event: time 1651254109.394687, type 1 (EV_KEY), code 30 (KEY_A), value 0
Event: time 1651254109.394687, -------------- SYN_REPORT ------------
Event: time 1651254111.394875, type 1 (EV_KEY), code 30 (KEY_A), value 1
Event: time 1651254111.394875, type 1 (EV_KEY), code 30 (KEY_A), value 0
Event: time 1651254111.394875, -------------- SYN_REPORT ------------

这里可以看到/dev/input/event0设备有上传了,类型为EV_KEY,键值为KEY_A的event事件。

相关新闻

联系我们

029-89197679

技术咨询:support@i2som.tech

商务合作:market@i2som.tech

工作时间:周一至周五,9:30-18:30,节假日休息