Input subsystem I

Input subsystem概述

1.1.input子系统概述

The kernel’s input subsystem was created to unify scattered drivers that handle diverse classes of data-input devices such as keyboards, mouse, touch screens, hummer.

Advantages of Input Subsystem.
1. Uniform handling of functionally similar input devices even when they are physically different.Example : Mouse, keyboard,Power keys.
2. An easy event interface for dispatching input reports to user applications. Your driver does not have to create and manage /dev nodes and related access methods Instead we can simply invoke the APIs.

1.2. input子系统结构

输入子系统(Input Subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler)、输入子系统核心层(InputCore)和输入子系统设备驱动层, 如图1-1。这里写图片描述
设备驱动层 提供对硬件寄存器的读写访问,将底层硬件对用户输入访问的响应转换为标准的输入事件,再通过核心层提交给事件处理层;
输入设备的驱动部分不在用关心对设备文件的操作,只需关心各硬件寄存器的操作和提交的输入事件
核心层 对下提供了设备驱动层的编程接口,对上又提供了事件处理层的编程接口;
事件处理层 为用户空间的程序提供统一访问设备的接口(设备节点),以及处理驱动层提交来的事件。
/dev/input目录下显示的是已经注册在内核中的设备编程接口,用户通过open这些设备文件来打开不同的输入设备进行硬件操作。
输入子系统由内核代码drivers/input/input.c构成,它的存在屏蔽了用户到设备驱动的交互细节,为设备驱动层和事件处理层提供了相互通信的统一界面。

参考:EssentialLinuxDeviceDrivers书中Chapter7:Input Drivers
Figure 7.1 illustrates the operation of the input subsystem.
The subsystem contains two classes of drivers that work in tandem: event drivers and device drivers.

Event drivers are responsible for interfacing with applications, whereas device drivers are responsible for low-level communication with input devices.

Because event drivers are standardized and available for all input classes, you are more likely to implement a device driver than an event driver. Your device driver can use a suitable existing event driver via the input core to interface with user applications.
EssentialLinuxDeviceDrivers

2 Input subsystem core 架构分析

2.1 input subsystem 数据结构
  input_dev 是硬件驱动层,代表一个input输入设备。
  input_handler 是事件处理层,代表一个事件处理器。
  input_handle 属于核心层,代表一个配对的input设备与input事件处理器。 

struct input_dev {
    ..........
    struct input_id id; //标识设备驱动特征
    unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//设备所支持的事件
    unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//KEY事件支持的编码
    unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//REL事件支持的编码
    .....
    int (*open)(struct input_dev *dev);
    void (*close)(struct input_dev *dev);
    int (*flush)(struct input_dev *dev, struct file *file);
    int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
    struct device dev;
    .......
    struct list_head    h_list;//handle的链表
    struct list_head    node;
};
struct input_handler {
    void *private;
    void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//input core事件处理函数
    bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//分离出常规事件
    bool (*match)(struct input_handler *handler, struct input_dev *dev);//当匹配handler和设备的时候调用
    int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);//当handler和设备匹配的后调用
    void (*disconnect)(struct input_handle *handle);
    void (*start)(struct input_handle *handle);//在connect之后调用start
    const struct file_operations *fops;
    int minor;
    const char *name;
    const struct input_device_id *id_table;
    struct list_head    h_list;//handle的链表
    struct list_head    node;
};
struct input_handle {
    void *private;
    int open;//打开标志
    const char *name;
    struct input_dev *dev;
    struct input_handler *handler;
    struct list_head    d_node;//input_dev的链表
    struct list_head    h_node;//handler的链表
};

所有的input_dev 用双向链表 input_dev_list 连起来,如图所示1-3:
input_dev_list
在调用int input_register_device(struct input_dev *dev) 的时候,会将新的 input_dev 加入到这个链表中。
所有的input_handler 用双向链表 input_handler_list 连起来, 如图所示1-4:
input_hander_list
在调用 int input_register_handler(struct input_handler *handler) 的时候,会将新的 input_handler 加入到这个链表中。
每个input_dev 和 input_handler 是要关联上才能工作的,在注册 input_dev 或者 input_handler的时候,就遍历上面的列表,找到相匹配的,然后调用 input_handler 的 connect函数来将它们联系到一起。
通常在input_handler 的 connect函数中,就会创建 input_handle, input_handle就是负责将 input_dev 和 input_handler 联系在一起的,如图1-5所示:
这里写图片描述
其中: input_dev 中的 h_node 是 input_handle 链表的list节点,也就是说,一个input_dev,可以对应多个 input_handle.
当设备产生 input event 的时候,例如按下了一个键,驱动就会调用 input_handler 中的 event 函数,同时,如果input_dev 支持的话,也会调用 input_dev 的 event 函数。
这样,设备产生的事件就会被驱动记录下来。当用户层的程序需要获知这些事件的时候,会调用 input_handler中的 struct file_operations *fops 中的相应函数,例如 read 等等。
参考:
The Linux USB Input Subsystem: Part I
Part II
input子系统全面分析
input子系统分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值