Skip to content

Instantly share code, notes, and snippets.

@zhustec
Last active August 16, 2024 08:10
Show Gist options
  • Select an option

  • Save zhustec/792f5ed5e24a7d5e9ca11ffa87fea732 to your computer and use it in GitHub Desktop.

Select an option

Save zhustec/792f5ed5e24a7d5e9ca11ffa87fea732 to your computer and use it in GitHub Desktop.
Linux input event, including Mouse, Keyboard, Touchpad.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <linux/input.h>
#define KEYBOARD_DEVPATH "/dev/input/event3"
#define MOUSE_DEVPATH "/dev/input/event5"
#define TOUCHPAD_DEVPATH "/dev/input/event11"
extern int errno;
fd_set fds;
int keyboard_fd, mouse_fd, touchpad_fd;
int open_devpath(int *pfd, char *path)
{
int fd;
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd <= 0)
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return -1;
}
else
{
*pfd = fd;
return 0;
}
}
void reset_fdset()
{
FD_ZERO(&fds);
FD_SET(keyboard_fd, &fds);
FD_SET(mouse_fd, &fds);
FD_SET(touchpad_fd, &fds);
}
void handle_keyboard_event(const struct input_event *piev)
{
printf("Keyboard Event - ");
switch (piev->type)
{
// 键盘按键按压或释放事
case EV_KEY:
printf("%d %s", piev->code, piev->value ? "Pressed" : "Released");
break;
// 键盘按键持续按压不释放会一直产生此事件,且 piev->value 为持续按下的按键编号
case EV_MSC:
printf("stay pressed: %d %d", piev->code, piev->value);
break;
// 同步事件
case EV_SYN:
printf("---------------------------------------------------------");
break;
default:
printf("Unkown Event: %d, %d, %d", piev->type, piev->code, piev->value);
}
printf("\n");
}
void handle_mouse_event(const struct input_event *piev)
{
printf(" Mouse Event - ");
switch (piev->type)
{
// 鼠标左键、右键、中键等按键按压或释放
case EV_KEY:
switch (piev->code)
{
case BTN_LEFT:
printf("left is %s", piev->value ? "Pressed" : "Released");
break;
case BTN_RIGHT:
printf("right is %s", piev->value ? "Pressed" : "Released");
break;
case BTN_MIDDLE:
printf("middle is %s", piev->value ? "Pressed" : "Released");
break;
// 其他按键未列出
default:
printf("unkown EV_KEY: %d %d", piev->code, piev->value);
}
break;
// 鼠标移动或滚轮滚动时产生事件
case EV_REL:
switch (piev->code)
{
// 鼠标左右移动
case REL_X:
if (piev->value > 0)
printf("right %d", piev->value);
else if (piev->value < 0)
printf("left %d", -piev->value);
break;
// 鼠标上下移动
case REL_Y:
if (piev->value > 0)
printf("down %d", piev->value);
else if (piev->value < 0)
printf("up %d", -piev->value);
break;
// 鼠标滚轮上下滚动
case REL_WHEEL:
if (piev->value == 1)
printf("scroll up\n");
else if (piev->value == -1)
printf("scroll down\n");
else
printf("scoll unkown\n");
break;
default:
printf("unkown EV_REL: %d %d", piev->code, piev->value);
}
break;
// 鼠标按键按下或释放同时产生此事件,value 值 - 左:589825,右:589826,中:589827,不知是不是 Magic Number
case EV_MSC:
printf("stay pressed: %d %d", piev->code, piev->value);
break;
// 同步事件
case EV_SYN:
printf("---------------------------------------------------------");
break;
default:
printf("Unkown Event: %d, %d, %d", piev->type, piev->code, piev->value);
}
printf("\n");
}
void handle_touchpad_event(const struct input_event *piev)
{
printf("Touchpad Event - ");
switch (piev->type)
{
// 触摸板按键及触摸
case EV_KEY:
switch (piev->code)
{
// 触摸板下面按键触发,可通过用手指甲触发来避免 BTN_TOUCH 事件
case BTN_LEFT:
printf("left %s", piev->value ? "Pressed" : "Released");
break;
// 只要有手指触碰,就会产生此事件
case BTN_TOUCH:
printf("touch %s", piev->value ? "Pressed" : "Release");
break;
// 1 指
case BTN_TOOL_FINGER:
printf("1 finger %s", piev->value ? "Pressed" : "Release");
break;
// 2 指
case BTN_TOOL_DOUBLETAP:
printf("2 finger %s", piev->value ? "Pressed" : "Release");
break;
// 3 指
case BTN_TOOL_TRIPLETAP:
printf("3 finger %s", piev->value ? "Pressed" : "Release");
break;
// 4 指
case BTN_TOOL_QUADTAP:
printf("4 finger %s", piev->value ? "Pressed" : "Release");
break;
// 5 指
case BTN_TOOL_QUINTTAP:
printf("5 finger %s", piev->value ? "Pressed" : "Release");
break;
default:
printf("unkown EV_KEY: %d %d", piev->code, piev->value);
}
break;
case EV_ABS:
switch (piev->code)
{
// 多指操作时产生多个事件,每个之后紧跟一对 ABS_MT_POSITION_{X, Y} 事件
case ABS_MT_SLOT:
printf("ABS_SLOT: %d", piev->value);
break;
// 当前手指 x 向绝对位置
case ABS_MT_POSITION_X:
printf("position x: %d", piev->value);
break;
// 当前手指 y 向绝对位置
case ABS_MT_POSITION_Y:
printf("position y: %d", piev->value);
break;
// 当前 x 向绝对位置,指示第一个检测出来的手指
case ABS_X:
printf("x: %d", piev->value);
break;
// 当前 y 向绝对位置,指示第一个检测出来的手指
case ABS_Y:
printf("y: %d", piev->value);
break;
// 手指释放时产生此事件,且 value 恒为 -1
case ABS_MT_TRACKING_ID:
printf("ABS_MT_TRACKING_ID: %d", piev->value);
break;
default:
printf("unkown EV_ABS: %d %d", piev->code, piev->value);
}
break;
case EV_MSC:
switch (piev->code)
{
// 每次都会产生,为一个时间戳,暂未搞清
case MSC_TIMESTAMP:
printf("timestamp: %d", piev->value);
break;
default:
printf("unkown EV_MSC: %d %d", piev->code, piev->value);
}
break;
// 同步事件
case EV_SYN:
printf("---------------------------------------------------------");
break;
default:
printf("Unkown Event: %d, %d, %d", piev->type, piev->code, piev->value);
}
printf("\n");
}
int main(int argc, char const *argv[])
{
struct input_event iev;
open_devpath(&keyboard_fd, KEYBOARD_DEVPATH);
open_devpath(&mouse_fd, MOUSE_DEVPATH);
open_devpath(&touchpad_fd, TOUCHPAD_DEVPATH);
reset_fdset();
while (select(6, &fds, NULL, NULL, NULL) > 0)
{
if (FD_ISSET(keyboard_fd, &fds))
{
if (read(keyboard_fd, &iev, sizeof(iev)) == sizeof(iev))
handle_keyboard_event(&iev);
}
else if (FD_ISSET(mouse_fd, &fds))
{
if (read(mouse_fd, &iev, sizeof(iev)) == sizeof(iev))
handle_mouse_event(&iev);
}
else if (FD_ISSET(touchpad_fd, &fds))
{
if (read(touchpad_fd, &iev, sizeof(iev)) == sizeof(iev))
handle_touchpad_event(&iev);
}
reset_fdset();
}
close(keyboard_fd);
close(mouse_fd);
close(touchpad_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment