Linux学习笔记--获取输入设备信息
打开设备文件
fd = open(argv[1], O_RDWR);
以读写方式打开指定的输入设备文件(如 /dev/input/event0
)。
获取设备标识信息
err = ioctl(fd, EVIOCGID, &id);
if (err == 0) {printf("bustype = 0x%x\n", id.bustype);printf("vendor = 0x%x\n", id.vendor);printf("product = 0x%x\n", id.product);printf("version = 0x%x\n", id.version);
}
使用 EVIOCGID
ioctl 命令获取设备的总线类型、厂商ID、产品ID和版本号。
获取支持的事件类型
char *ev_names[] = {"EV_SYN ", "EV_KEY ", "EV_REL ", "EV_ABS ", "EV_MSC ", "EV_SW ", "NULL ", ... // 省略部分
};len = ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
if (len > 0 && len <= sizeof(evbit)) {printf("support ev type: ");for (i = 0; i < len; i++) {byte = ((unsigned char *)evbit)[i];for (bit = 0; bit < 8; bit++) {if (byte & (1<<bit)) {printf("%s ", ev_names[i*8 + bit]);}}}printf("\n");
}
使用 EVIOCGBIT
获取设备支持的事件类型位图,然后逐位检查并打印支持的事件类型名称。
EVIOCGBIT(0, sizeof(evbit))
:
这是一个宏,用于生成获取事件类型位图的 ioctl 命令
第一个参数
0
表示获取基本事件类型(EV_*)第二个参数
sizeof(evbit)
指定缓冲区大小返回值
len
是实际写入的字节数
&evbit
: 指向unsigned int evbit[2]
的指针,用于接收位图数据
事件类型位图的结构
在 Linux 输入子系统中,设备支持的事件类型用一个位图表示:
每个位代表一种事件类型
如果某位被设置为 1,表示设备支持该事件类型
事件类型定义(在 linux/input.h
中):
#define EV_SYN 0x00 // 同步事件
#define EV_KEY 0x01 // 按键事件
#define EV_REL 0x02 // 相对坐标事件(如鼠标移动)
#define EV_ABS 0x03 // 绝对坐标事件(如触摸屏)
#define EV_MSC 0x04 // 杂项事件
// ... 其他事件类型
外层循环:遍历字节
i
从 0 到len-1
,遍历位图中的每个字节byte = ((unsigned char *)evbit)[i]
:将evbit
强制转换为字节数组,取第 i 个字节
内层循环:遍历位
bit
从 0 到 7,遍历字节中的每个位if (byte & (1<<bit))
:检查第 bit 位是否被设置1<<bit
:创建只有第 bit 位为 1 的掩码byte & (1<<bit)
:如果结果不为 0,说明该位被设置
计算事件类型编号
i*8 + bit
:计算当前位对应的事件类型编号i*8
:当前字节的起始位位置+ bit
:在字节内的位偏移
ev_names[i*8 + bit]
:从名称数组中获取对应的事件类型名称
示例说明
假设设备支持以下事件类型:
EV_SYN (0)
EV_KEY (1)
EV_ABS (3)
那么位图可能看起来像:
字节0: 00001011 (二进制)位: 76543210|||||||||||||||+-- EV_SYN (0)||||||+--- EV_KEY (1) |||||+---- 不支持||||+----- EV_ABS (3)++++------ 其他不支持
解析过程:
i=0, byte=00001011 (二进制)
bit=0: 00001011 & 00000001 = 1 → 支持 EV_SYN
bit=1: 00001011 & 00000010 = 2 → 支持 EV_KEY
bit=2: 00001011 & 00000100 = 0 → 不支持
bit=3: 00001011 & 00001000 = 8 → 支持 EV_ABS
其他位都为 0 → 不支持
输出:support ev type: EV_SYN EV_KEY EV_ABS
这种位图机制高效地表示了设备支持的大量事件类型,节省了内存和传输开销。
运行:
./01_get_input_info /dev/input/event0
输出:
bustype = 0x3
vendor = 0x46d
product = 0xc52b
version = 0x111
support ev type: EV_SYN EV_KEY EV_MSC EV_LED