输入子系统(1):数据结构总结
来源:互联网 发布:java哈希表 编辑:程序博客网 时间:2024/05/20 23:34
1:概述
输入子系统在linux内核中使用广泛,按键,鼠标,sensor类,touch等驱动都会用到输入子系统。输入子系统的结构分为以下三层:
1.1:设备驱动层
这一层需要用户在设备驱动中去实现,调用核心层的函数接口,完成输入设备的注册和并将发生的事件上报给子系统核心层;
1.2:输入子系统核心层
为驱动层和事件处理层提供函数接口,并且注册input字符设备,主设备号是13,次设备号为0~255,接受来自驱动层的上报事件,并最终通过事件处理层的接口,上报给用户,为设备驱动层和事件处理层架起一座桥梁;
1.3:事件处理层
实现了和用户层的接口,所有用户的操作都是通过事件处理层提供的接口进行;
2:输入子系统中重要的数据结构
2.1:input类数据结构:input_handle input_handler input_dev
input_dev:代表一个输入设备,需要用户去填充并注册进内核,一个input_dev只能代表一个输入设备;
struct input_dev {const char *name; //输入设备名字const char *phys; //设备在系统中的物理路径const char *uniq; //设备唯一标识符struct input_id id; //设备ID,与input_handler匹配时会用到unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; //支持的所有事件类型unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; //支持的按键键值unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; //支持相对事件的子事件unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; //支持绝对事件的子事件 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; //支持的其它事件类型unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; //支持的led灯事件unsigned long sndbit[BITS_TO_LONGS(SND_CNT)]; //支持的声效事件unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; //支持的力反馈事件unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; //支持的开关事件unsigned int hint_events_per_packet;unsigned int keycodemax; //键值表大小unsigned int keycodesize; //键值表中元素个数void *keycode; //设备的键值表int (*setkeycode)(struct input_dev *dev,const struct input_keymap_entry *ke, //配置键值表 unsigned int *old_keycode);int (*getkeycode)(struct input_dev *dev, struct input_keymap_entry *ke); //获取键值表struct ff_device *ff;unsigned int repeat_key; //保存上一个键值struct timer_list timer;int rep[REP_CNT];struct input_mt_slot *mt;int mtsize;int slot;int trkid;struct input_absinfo *absinfo;unsigned long key[BITS_TO_LONGS(KEY_CNT)]; //记录按键的当前状态unsigned long led[BITS_TO_LONGS(LED_CNT)];unsigned long snd[BITS_TO_LONGS(SND_CNT)];unsigned long sw[BITS_TO_LONGS(SW_CNT)];//操作接口,比如打开/sys/input/event0的时候会调用open函数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 input_handle __rcu *grab; //当前使用的handle spinlock_t event_lock;struct mutex mutex;unsigned int users;bool going_away;bool sync;struct device dev;struct list_headh_list; //链表头节点,用来将input_handle挂在这个头节点上struct list_headnode; //链表节点,用来挂在input_dev_list上};input_handler:代表某一类输入设备对应的事件处理逻辑,也就是一个input_handler可以对于那个很多个输入设备和输入设备节点;
struct input_handler {void *private;//操作方法void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);bool (*match)(struct input_handler *handler, struct input_dev *dev);int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);void (*disconnect)(struct input_handle *handle);void (*start)(struct input_handle *handle);const struct file_operations *fops;int minor; //input_handler对应的最小次设备号const char *name;const struct input_device_id *id_table; //用于和input_dev进行匹配struct list_headh_list; //链表头节点,用于将input_handle挂在这个上面struct list_headnode; //链表节点,用于挂在input_handler_list上};input_handle:使input_dev和input_handler建立起对应关系;
struct input_handle {void *private;int open;const char *name;struct input_dev *dev; //指向input_devstruct input_handler *handler; //指向input_handlerstruct list_headd_node; //挂在input_dev的h_list上struct list_headh_node; //挂在input_handler的h_list上};2.2:evdev类数据结构:evdev evdev_client
evdev:代表一个具体的事件设备event,和input_dev对应,当注册input_dev时,如果匹配成功,内核会建立一个与之对应的evdev结构,一个evdev就是一个字符节点,比如:/dev/input/event0;
evdev_client:当open一个event节点的时候,会创建evdev_client结构体,用于保存设备驱动上报的事件;
2.3:table类数据结构:evdev_table input_table
evdev_table:存放evdev的数组,table大小为32,也就是说最大有32个event节点;
input_table:存放input_handler结构的数组,大小为8,内核总共支持256个输入字符设备,主设备号为13,次设备为0~255,内核按照输入字符设备次设备号的不同,将这些设备号对应到8个input_handler,即一个input_handler对应32个输入字符设备节点,比如:evdev_handler对应的字符设备次设备号是从64开始的,比如有一个输入字符设备节点的次设备号是64,所以input_table[64>>5]中的input_handler就是此输入设备对应的input_handler;
3:上述数据结构直接的关系
3.1:输入子系统会维护evdev_table和input_table两个表,用来存放event和input_handler;
3.2:input_dev和input_handler会互相匹配,匹配成功后调用input_handler中的connect进行连接,连接的时候创建evdev结构并创建文件节点;
3.3:当用户空间open一个输入设备节点(/dev/input/event0)的时候,会依据设备节点的次设备号找到对应的input_handler,调用input_handler中的文件操作open函数,并创建evdev_client结构;
3.4:下面用一张图表现这些关系,图片来自网络:
3.5:先通过对数据结构的认识,大概有个感性了解,随后的章节参考内核代码,去认识这些数据结构,肯定会更加清晰;
- 输入子系统(1):数据结构总结
- 输入子系统总结
- linux输入子系统(1)
- linux输入子系统(1)
- linux输入子系统(1)
- Linux输入子系统-数据结构关系
- 对输入子系统分析总结
- 对输入子系统分析总结
- 对输入子系统分析总结
- Input输入子系统个人总结
- 6410之输入子系统(1)
- Linux输入子系统框架分析(1)
- Android输入子系统分析(1)
- 输入子系统(四)
- linux驱动子系统之输入子系统(1)
- linux驱动子系统之输入子系统(1)
- linux驱动子系统之输入子系统(1)
- Linux输入子系统框架 ---- 高手总结
- 数据结构--线性表
- yii 2.0设置默认值
- Mac下编写bash脚本并运行
- select函数详解
- 几种自旋锁SpinLock,TicketLock,CLHLock,以及可重入实现要点,非阻塞锁实现要点
- 输入子系统(1):数据结构总结
- 三年技术!该如何选择!
- 全球最牛的28个大数据可视化应用案例
- zstu 4245 KI的斐波那契(2016年新生赛暨全国新生邀请赛)
- 计算一条语句中字母,数字,字符的个数
- iPhone历代产品,从3GS到7Plus详尽参数
- c++虚函数实现基本原理
- 业务流程&系统用例
- Spring开发入门环境搭建篇