Input subsystem I

来源:互联网 发布:汽车租赁源码 编辑:程序博客网 时间:2024/06/07 02:19

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