首先,什么是linux的子系统:
输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动通过Driver->Input core->Event handler->user space的顺序到达用户控件的应用程序。
驱动层:将底层的硬件输入转化为统一事件形式,向输入核心(Input Core)汇报。
Input Core:承上启下, 为驱动层 提供输入设备注册与操作接口,如:input_register_device;通知事件处理层对事件进行处理;在/Proc下产生相应的设备信息。
事件处理层:主要是和用户空间交互。(Linux中在用户空间将所有的设备都当初文件来处理,由于在一般的驱动程序中都有提供fops接口,以及在/dev下会生成相应的设备文件nod,这些操作在输入子系统中由事件处理层完成)。
////////////////////////////////////////////////////////////////////////////////////////////
实现设备驱动核心工作是:向系统报告按键等输入事件(event,通过input_event结构描述),不再需要关心文件操作接口(如何理解)。驱动报告事件经过inputCore和Eventhandler到达用户空间。
一些驱动相关的函数:
设备注册------------属于在驱动程序中使用?不在用户代码中用?
注册输入设备函数:int input_register_device(struct input_dev *dev)
注销输入设备函数:void input_unregister_device(struct input_dev *dev)
初始化(事件支持):
set_bit()告诉input输入子系统支持哪些事件,哪些按键。例如:
set_bit(EV_KEY,button_dev.evbit) (其中button_dev是 struct input_dev类型)
struct input_dev中有两个成员:evbit,keybit----------怎么与input.h中定义的input_event不一样呢,难道这里说的是内核空间的同名结构体??
evbit: 事件类型(包括 EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)
keybit:与某种事件类型对应的按键类型(eg. 当事件类型为EV_KEY时, 包括KEY_F11,BTN_LEFT, BTN_0, BTN_1 ,BTN_MIDDLE等 )
报告事件:
用于报告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)
报告结束:
input_sync()同步用于告诉input core子系统报告结束。
实例:触摸屏设备驱动中,一次点击的整个报告过程如下:
input_reprot_abs(input_dev,ABS_X,x); //x坐标
input_reprot_abs(input_dev,ABS_Y,y); // y坐标
input_reprot_abs(input_dev,ABS_PRESSURE,1);
input_sync(input_dev);//同步结束
实例分析(按键中断程序):
//按键初始化
static int __init button_init(void)//申请中断
{
if(request_irq(BUTTON_IRQ, button_interrupt,0,”button”,NUll))
return –EBUSY;
set_bit(EV_KEY,button_dev.evbit); //支持EV_KEY事件
set_bit(BTN_0,button_dev.keybit); //支持设备两个键
set_bit(BTN_1,button_dev.keybit); //
input_register_device(&button_dev);//注册input设备
}
/*在按键中断中报告事件*/
Static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)
{
input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));//读取寄存器BUTTON_PORT0的值
input_report_key(&button_dev,BTN_1,inb(BUTTON_PORT1));
input_sync(&button_dev);
}
总结:input子系统仍然是字符设备驱动程序,但是代码量减少很多,input子系统只需要完成两个工作:初始化和事件报告(这里在linux中是通过中断来实现的)。读者不妨用sourceinsignt 输入input_init去搜关于输入子系统的实现.
例子:https://www.cnblogs.com/myblesh/articles/2367648.html
////////////////////////////////////////////////////////////////////////////////////////////
输入子系统内核代码分析:
https://www.cnblogs.com/lifexy/p/7542989.html
ref: