★什么是Linux输入子系统?为何引入Linux输入子系统?
Linux输入子系统是为多种不同的输入设备提供一种统一的机制,将它们归属到统一架构下面。在输入子系统以前,输入设备(鼠标、键盘)都是采用字符设备或者混杂设备进行处理。因此就会产生一个问题,如何将硬件不同、类型不同的输入设备进行统一的处理,才有了后面的Linux输入子系统。
★Linux输入子系统的层次结构
Linux输入子系统分为三个层次:设备驱动层、核心层、事件处理层。一个输入事件(鼠标产生的事件)会通过设备驱动层、核心层、事件处理层、到达用户空间最终到达应用程序。
(注:图片来源http://www.cnblogs.com/cute/archive/2011/08/30/2159305.html)
★Linux输入子系统的分层
(注:图片来源http://www.cnblogs.com/cute/archive/2011/08/30/2159305.html)
★Linux输入子系统之设备驱动层
◇作用
驱动层主要负责与硬件打交道。对硬件设备的访问,中断设置,将硬件产生的事件转换为核心层定义的规范提交给事件处理层。
◇重要的数据结构
输入设备数据结构:input_dev
struct input_dev {
const char *name;//提供给用户的输入设备的名称
const char *phys;//提供给编程者的设备节点的名称
const char *uniq;//指定唯一的ID号
struct input_id id;//输入设备标识ID,用于和事件处理层进行匹配
/**BITS_TO_LONGS的作用:求一个数是几个long的长度**/
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)];//记录设备支持的指示灯
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 *mt;
struct input_absinfo *absinfo;
unsigned long key[BITS_TO_LONGS(KEY_CNT)]; //按键的状态
unsigned long led[BITS_TO_LONGS(LED_CNT)]; //LED的状态
unsigned long snd[BITS_TO_LONGS(SND_CNT)]; //声音的状态
unsigned long sw[BITS_TO_LONGS(SW_CNT)]; //开关的状态
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;
spinlock_t event_lock;
struct mutex mutex; //用于open、close函数的连续访问互斥
unsigned int users; //设备使用计数器
bool going_away;
struct device dev;
struct list_head h_list; //handle列表
struct list_head node; //input_dev链表
unsigned int num_vals;
unsigned int max_vals;
struct input_value *vals;
bool devres_managed;
};
◇重要的函数
分配与注册一个输入设备
分配:
Struct input_dev *input_allocate_device*(void);//分配一个输入设备结构体的指针。
注册:
int input_register_device(struct input_dev *dev);
这个函数把dev输入设备挂在输入设备链表中,并且通知事件处理层调用connect函数完成设备和事件处理的绑定,
当用户打开设备时,便能够调用到相应的事件处理接口获得硬件上报的数据了。
◇事件的支持
对于一个设备驱动,要使用set_bit()函数来告诉输入子系统它支持哪些事件,例如:
set_bit(nuc970_keycode[i], input_kp_dev->keybit);设置按键的类型。在input_dev结构体下有两个数组
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//支持的事件类型
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//支持的按键类型
事件类型:#define EV_SYN 0x00 //同步事件
#define EV_KEY 0x01 //按键事件
#define EV_REL 0x02 //相对坐标
#define EV_ABS 0x03 //绝对坐标
#define EV_MSC 0x04 //其他
#define EV_SW 0x05 //开关
#define EV_LED 0x11 //按键/设备灯
#define EV_SND 0x12 //声音
#define EV_REP 0x14 //重复
#define EV_FF 0x15 //力反馈
#define EV_PWR 0x16 //电源
#define EV_FF_STATUS 0x17 //力反馈状态
#define EV_MAX 0x1f //事件类型最大个数和提供位掩码支持
#define EV_CNT (EV_MAX+1)
◇事件的报告当事件发生时,驱动程序会向核心层(input core)来报告EV_KEY,EV_REL,EV_ABS等事件,报告函数为:
Void input_report_key(struct input_dev *dev,unsigned int code, int value) //报告键值
Void input_report_rel(struct input_dev *dev,unsigned int code, int value) //报告相对坐标
Void input_report_abs(struct input_dev *dev,unsigned int code, int value) //报告绝对坐标
Void input_sync(struct input_dev *dev);//报告同步事件
◇释放与注销设备Void input_free_device(struct input_dev *dev);
Void input_unregister_device(struct input_dev *);
参考资料:
http://7071976.blog.51cto.com/7061976/1398175
http://blog.youkuaiyun.com/voice_shen/article/details/7005681
http://blog.youkuaiyun.com/ielife/article/details/7798952
http://www.chengxuyuans.com/Linux/66974.html
https://sites.google.com/site/rgbbones2/inputsubsystem
http://blog.chinaunix.net/uid/23770712/list/2.html
http://www.cnblogs.com/cute/archive/2011/08/30/2159305.html