0%

【Linux技术分享】UOS下实现键盘事件捕捉

在UOS系统下实现键盘的捕捉

在UOS系统下监听和触发键盘的事件,具体代码参考https://github.com/MecryWork/hotkey。参考博文https://www.jianshu.com/p/927fc573d081

/dev/input目录简介

  1. 首先linux是所有操作都是已文件形式处理,这个是真理。在我们输入键盘鼠标时,linux系统中记录都放在/dev/input目录下。我们ls下此目录可以看见绝大部分的事件处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    crw-rw----  1 root input 13, 65 6月  28 13:04 event1
    crw-rw---- 1 root input 13, 74 6月 28 13:04 event10
    crw-rw---- 1 root input 13, 75 6月 28 13:04 event11
    crw-rw---- 1 root input 13, 76 6月 28 13:04 event12
    crw-rw---- 1 root input 13, 77 6月 28 13:04 event13
    crw-rw---- 1 root input 13, 66 6月 28 13:04 event2
    crw-rw---- 1 root input 13, 67 6月 28 13:04 event3
    crw-rw---- 1 root input 13, 68 6月 28 13:04 event4
    crw-rw---- 1 root input 13, 69 6月 28 13:04 event5
    crw-rw---- 1 root input 13, 70 6月 28 13:04 event6
    crw-rw---- 1 root input 13, 71 6月 28 13:04 event7
    crw-rw---- 1 root input 13, 72 6月 28 13:04 event8
    crw-rw---- 1 root input 13, 73 6月 28 13:04 event9
  2. 使用cat /proc/bus/input/devices可以查看每一个event的具体操作,里面的H就是对应的时间操作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    I: Bus=0000 Vendor=0000 Product=0000 Version=0000
    N: Name="HDA ATI HDMI HDMI/DP,pcm=3"
    P: Phys=ALSA
    S: Sysfs=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1/input11
    U: Uniq=
    H: Handlers=event8
    B: PROP=0
    B: EV=21
    B: SW=140

    I: Bus=0000 Vendor=0000 Product=0000 Version=0000
    N: Name="HDA Intel PCH Rear Mic"
    P: Phys=ALSA
    S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input12
    U: Uniq=
    H: Handlers=event9
    B: PROP=0
    B: EV=21
    B: SW=10

    I: Bus=0000 Vendor=0000 Product=0000 Version=0000
    N: Name="HDA Intel PCH Front Mic"
    P: Phys=ALSA
    S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input13
    U: Uniq=
    H: Handlers=event10
    B: PROP=0
    B: EV=21
    B: SW=10

    input.h 文件

  3. linux/input.h文件中定义了event时间输入数据的结构图,该结构图的定义如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
    };

    struct timeval
    {
    __time_t tv_sec; /* Seconds. */
    __suseconds_t tv_usec; /* Microseconds. */
    };

    type,指事件类型,常见的事件类型有:

    EV_KEY,按键事件,键盘的按键,鼠标的左键右键等;

    EV_REL,相对坐标,主要用于鼠标的移动事件;

    EV_ABS,绝对坐标,主要用于触摸屏的移动事件。

    code 事件代码,当事件类型为EV_KEY时,该代码为设备键盘代码,在input.h文件中以KEY_开头定义;

    value 事件的值,当事件类型代码是EV_KEY时,按键操作值为1,释放操作值为0,事件类型代码为EV_REL是,value为正数值和负数值分别代表连个不同方向的值。

监听键盘事件

  1. 利用input_event结构体读取键盘事件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    int retval;
    fd_set readfds;
    struct timeval tv;
    int fd = open(dev, O_RDONLY);
    struct input_event event;
    if (fd < 0) {
    perror(dev);
    return;
    }

    while (1) {
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds);
    tv.tv_sec = timeout;//设置超时时间
    tv.tv_usec = 0;
    if ((retval = select(fd + 1, &readfds, NULL, NULL, &tv)) == 1) {
    if (read(fd, &event, sizeof(event)) == sizeof(event)) {
    if (event.type == EV_KEY) {
    if (event.value == 0 || event.value == 1) //根据value的值判断按下松开{
    printf("key %d %s\n", event.code, event.value ? "Pressed" : "Released");
    }
    } else {
    printf("type=%x %d %d\n", event.type, event.code, event.value);
    }
    }
    } else {
    break;
    }
    }
    close(fd);

传入键盘事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1. 利用`input_event`+`write`对键盘事件进行写入
void simulate_key(int fd, int kval)
{
struct input_event event;
gettimeofday(&event.time, 0);
//按下kval键
event.type = EV_KEY;
event.value = 1;
event.code = kval;
write(fd, &event, sizeof(event));
//同步,也就是把它报告给系统
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, 0);
//松开kval键
event.type = EV_KEY;
event.value = 0;
event.code = kval;
write(fd, &event, sizeof(event));
//同步,也就是把它报告给系统
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}