You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更精准读取/dev/input/mice设备的鼠标移动数据?

问题原因

你遇到的快速移动鼠标时计数不准的问题,根源是没有正确解析PS/2鼠标协议的扩展数据包:

  • /dev/input/mice遵循PS/2鼠标协议,默认发送3字节数据包,位移范围限制在-128到127之间。
  • 当鼠标快速移动导致位移超过单字节范围时,会自动发送6字节的扩展数据包,用来传递更大范围的16位位移值。
  • 你的代码直接读取6字节数据,且只提取buf[1]和buf[2]这两个低字节位移值,完全忽略了扩展包中的高字节数据,导致快速移动时丢失了大部分位移信息,累加的x_total自然远低于预期值。
解决方案

需要严格按照PS/2鼠标协议规范解析数据包:

  1. 先读取第一个字节(标志位),通过标志位的第3位判断是否为扩展数据包。
  2. 根据数据包类型,读取完整的3字节(普通包)或6字节(扩展包)数据。
  3. 对扩展包,组合低字节和高字节得到完整的16位位移值,再进行累加计算。
修改后的代码
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <stdio.h>

int main() {
    int fd;
    fd_set readfds;
    int screen_x = 1920;
    int screen_y = 1080;
    int x_total = 0, y_total = 0;

    fd = open("/dev/input/mice", O_RDONLY);
    if (fd == -1) {
        printf("Error Opening /dev/input/mice\n");
        return 1;
    }

    while(1) {
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
        select(fd+1, &readfds, NULL, NULL, NULL);

        if(FD_ISSET(fd, &readfds)) { 
            unsigned char flags;
            // 先读取标志位字节
            if(read(fd, &flags, 1) <= 0) {  
                continue;  
            }

            int packet_size = (flags & 0x08) ? 6 : 3; // 扩展包6字节,普通包3字节
            unsigned char buf[6];
            buf[0] = flags;

            // 读取剩余字节,确保数据包完整
            if(read(fd, buf + 1, packet_size - 1) != packet_size - 1) {
                continue;
            }

            int x, y;
            if(packet_size == 3) {
                // 普通3字节包,直接取带符号单字节位移
                x = (signed char)buf[1];
                y = (signed char)buf[2];
            } else {
                // 6字节扩展包,组合低字节与高字节为完整16位位移
                x = (signed char)buf[1] | (buf[4] << 8);
                y = (signed char)buf[2] | (buf[5] << 8);
            }

            printf("x=%d, y=%d\n", x, y);
            x_total += x;
            y_total += y;
            printf("x_total: %d; y_total: %d\n", x_total, y_total);
        }  
    }
    close(fd);
    return 0;
}
额外说明
  • PS/2鼠标6字节扩展包的固定格式为:标志位字节 + x低字节 + y低字节 + 固定0x00字节 + x高字节 + y高字节。
  • 读取时必须确保完整读取整个数据包,避免因分段读取导致解析错误。
  • 测试时仍可使用xdotool mousemove 960 540将光标定位到屏幕中心,再快速移动验证结果准确性。

内容的提问来源于stack exchange,提问作者Xuan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:30:54