10. input子系统


1. 输入子系统概述

作用
Linux输入子系统为各类输入设备(如键盘、鼠标、触摸屏)提供统一的驱动框架,实现:

  • 统一驱动接口:标准化设备驱动开发。

  • 兼容性:支持不同厂商设备无缝接入。

  • 事件抽象:将硬件信号转换为标准输入事件(如按键、坐标)。

核心组件

  • 设备驱动层:直接操作硬件(如读取GPIO状态)。

  • 核心层:管理设备与事件处理模块的交互。

  • 事件处理层:向用户空间提供设备节点(如/dev/input/eventX)。 alt text


2. 设备节点与输入设备的关联

设备节点类型

  • 通用节点/dev/input/eventX(X为数字)。

  • 专用节点:如/dev/input/mouse0(直接标识设备类型)。

确定设备节点的方法

  1. 查看设备信息

    cat /proc/bus/input/devices
    

    输出示例:

    I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
    N: Name="AT Translated Set 2 keyboard"
    P: Phys=isa0060/serio0/input0
    H: Handlers=sysrq kbd event1
    
    • 关键字段
      H: Handlers=event1表示设备节点为/dev/input/event1

  2. 试探性测试

    sudo hexdump /dev/input/event1  # 按下键盘按键观察输出
    sudo cat /dev/input/mouse0      # 移动鼠标观察输出
    

3. RK3568开发板输入设备实例

开发板输入设备

  • 触摸屏、红外接收器、ADC按键、耳机接口。

查看设备节点

ls /dev/input/  # 输出:event0 event1 event2 event3 event4

详细设备信息

cat /proc/bus/input/devices

输出示例:

# 触摸屏
N: Name="Goodix Capacitive TouchScreen"
H: Handlers=event2

# ADC按键
N: Name="adc-keys"
H: Handlers=event3

测试设备事件

hexdump /dev/input/event2  # 触摸屏幕查看坐标事件
hexdump /dev/input/event3  # 按下ADC按键查看按键事件

4. 输入事件解析

事件结构体(参考linux/input.h):

struct input_event {
    struct timeval time;  // 时间戳
    __u16 type;           // 事件类型(如EV_KEY、EV_ABS)
    __u16 code;           // 事件代码(如KEY_A、ABS_X)
    __s32 value;          // 事件值(如1表示按下,0表示释放)
};

常见事件类型

  • EV_KEY:按键事件(如键盘、按键)。

  • EV_ABS:绝对坐标事件(如触摸屏)。

  • EV_REL:相对坐标事件(如鼠标)。


5. 编写输入设备驱动(示例)

步骤

  1. 注册输入设备

    #include <linux/input.h>
    
    struct input_dev *input_dev = input_allocate_device();
    input_dev->name = "Custom Input Device";
    set_bit(EV_KEY, input_dev->evbit);    // 支持按键事件
    set_bit(KEY_A, input_dev->keybit);     // 定义按键A
    input_register_device(input_dev);     // 注册设备
    
  2. 上报事件(在中断中触发):

    input_report_key(input_dev, KEY_A, 1);  // 按下按键A
    input_sync(input_dev);                  // 同步事件
    
  3. 用户空间读取事件

    // 示例应用:读取事件并打印
    struct input_event ev;
    int fd = open("/dev/input/event2", O_RDONLY);
    read(fd, &ev, sizeof(ev));
    printf("Type: %d, Code: %d, Value: %d\n", ev.type, ev.code, ev.value);
    

6. 常见问题与调试

问题1:设备节点未生成

  • 原因:驱动未正确注册或设备树配置错误。

  • 解决:检查dmesg日志,确认驱动加载成功。

问题2:事件无响应

  • 调试方法

    evtest /dev/input/event2  # 交互式测试工具
    

问题3:多设备冲突

  • 解决:在设备树中禁用默认驱动(如心跳灯)。


总结

Linux输入子系统通过标准化接口简化了输入设备驱动开发,开发者只需关注硬件操作和事件上报。通过/proc/bus/input/deviceshexdump工具可快速验证设备节点与硬件的对应关系,结合事件结构体和驱动API,能高效实现自定义输入设备驱动。