作者:Bright-Ho
联系方式:[email protected]
input输入子系统之“事件处理层”分析:
注意:我们现在只是涉及输入子系统的框架;具体细节会涉及到硬件的工作原理,在后面我们写驱动的时候会说到细节方面;
这一节,我们接触到了“事件处理层”;事件处理层包含了evdev.c(事件设备),tsdev.c(触摸屏设备),keyborad.c(键盘设备),以及mousedev.c(鼠标设备)等;
我们选取evdev.c(事件设备)内核源代码进行分析;该代码位于:drivers/input中;
上一节,我们说到,input_handler这个结构体就是在evdev.c这个事件处理文件中构造出来的;接下来,我们就继续分析“事件处理层”的代码;分析事件设备evdev.c的代码;
(1)入口函数evdev_init();
static int __init evdev_init(void)
{
return input_register_handler(&evdev_handler);
}
static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
里面直接调用input_register_handler(&evdev_handler);该函数是“核心层”提供的;
前面一节我们大概分析了该函数;这里最重要的是evdev_handler结构体;之前分析核心层的代码时候,一直都有evdev_handler这个结构体的出现,我们一直在寻找该结构的源头,现在我们清楚了,该结构体在“事件处理层”实现的;那么现在我们来分析input_handler结构体的成员;
evdev_connect函数:当dev和handler匹配成功后,就会调用该函数建立“连接”,怎么建立连接呢?对于每个不同的handler都有不同的连接方式,也就是不同的设备,有不同的连接方式。后面具体讲到设备驱动的时候,会讲到如何连接;
evdev_fops结构:该结构很重要,这个结构就是最终提供给应用层的调用接口,open,read,write,等;
evdev_ids:就是id号,用来匹配硬件设备和事件处理的;一旦匹配成功,就会调用connect函数建立“连接”;
EVDEV_MINOR_BASE:次设备号;
"evdev":名字;
那么这里重点看一下evdev_fops结构,也就是file_operations结构;我们自己写字符设备驱动的时候,就是自己构造这个结构,然后,通过register_chadev()函数来注册;那么引入“输入子系统”后,这个file_operations结构,就是由具体的“事件处理层”来实现;
不用我们自己手动实现!
609 static const struct file_operations evdev_fops = {
610 .owner = THIS_MODULE,
611 .read = evdev_read,
612 .write = evdev_write,
613 .poll = evdev_poll,
614 .open = evdev_open,
615 .release = evdev_release,
616 .unlocked_ioctl = evdev_ioctl,
617 #ifdef CONFIG_COMPAT
618 .compat_ioctl = evdev_ioctl_compat,
619 #endif
620 .fasync = evdev_fasync,
621 .flush = evdev_flush
622 };
应用程序open,read,write一个设备文件,就会调用到“事件处理层”里面提供的接口,这里就暂时不讲各个接口里面具体怎么实现的,等到讲到具体的硬件设备的时候,再来讲解;这里重点是讲解输入子系统的框架!!!
总结:“事件处理层”做了哪些事情?
(1)构造一个input_handler结构体,该结构体包含了,事件上报函数 evdev_event;设备和事件处理的连接函数evdev_connect; id号:evdev_ids用于匹配设备和事件处理;evdev_fops结构:驱动接口;
(2)调用核心层提供的注册函数input_register_handler(&evdev_handler);
该函数把input_handler结构体:
先放入一个input_table[]数组;
然后再把该结构体放入input_handler_list的链表;
把设备链表里面的每一项设备取出来和input_handler进行匹配,一旦匹配成功就调用input_handler结构里面的connect连接函数,把设备和事件连接在一起;当应用程序open,read,write,设备接口的时候就会调用“事件处理层”里面提供的file_operations里的面的驱动接口来处理具体的硬件设备;
下一节我们继续讲解设备驱动层的东西;