linux驱动之input子系统及分层/分离设计思想

本人对linux一直都比较感兴趣,苦于工作一直没有机会好好的深入了解,作为工作将近8年的工程师来说实在也是件憾事,不过还好,手头还算宽裕,买了不少开发板,不过大部分都是上灰阶段……真是暴殄天物啊……

业余时间也只是断断续续的学习下,还未系统性的去钻研,很多知识点还未形成一个完整的知识体系,所以最近开始做些深入的学习;

先讲讲linux驱动:

linux驱动之前分为字符驱动、块驱动、网络设备驱动,如果只是简单的写驱动的话其实和裸机的单板驱动没太大区别,大部分工作还是设置寄存器,然后添加驱动的入口函数,创建设备节点之类的,多了一些linux驱动框架的东西,如果把这些框架记住,勉强也是能写个可以用的底层驱动的;

不过linux做了不少优化,比如将驱动分为多个子系统模块、采用分层/分离的思想来设计,为什么这么优化? 相信写过裸机驱动的都会有这种经历:很多的驱动都有通用的东西,没有谁写裸机驱动从0开始,大部分人是从之前的代码里面拷过来,然后修改某些不一样的东西,比如寄存器之类的;linux分层/分离的思想就是如此,把共性提取出来当做一部分放入driver目录,另一部分当做易变部分也放入driver目录,这个易变的部分就是和你所用的硬件相关的配置,比如有占用哪几个IO口,IO口的地址等等……

那内核是如何将这两部分结合起来的?也就是说如何把这2个东西对应起来?linux驱动模型 采用总线管理的模式,比如platform虚拟总线,这个东西其实就是个虚拟的的东西,只是为了帮你做driver端与device端匹配、维护下注册的driver链表和device链表而已,貌似没有其他更加重要的作用,所以你写驱动的话不采用这个总线,也是可以写好一个驱动的;至于具体的如何做匹配,可以参考内核目录driver/base下的platform.c文件,里面就是这个总线的机制:简单来说就是稳定的driver端向这个文件祖册driver,device也向这个文件注册设备,然后开始查找祖册的链表里面是否有和自己名字一样的东西,有的话就开始connect,connect成功后就调用driver端的probe函数,然后就成功建立了匹配,一个设备也就动态的加入了系统;

除了platfform总线,还有实实在在存在的总线:比如I2C总线、USB总线、PCI总线等等……采用这些总线就可以不用platform虚拟总线了。

以上便是linux分层/分离思想的简单介绍;

对于input子系统和LCD驱动接口:

内核针对字符设备做了个输入子系统input接口,将一个字符设备驱动分层了3部分:事件相关的、input内核相关的、底层驱动相关的;简单的归纳就是:底层驱动完成硬件相关的配置初始化,以及硬件数据的读取,向input内核注册该设备;而事件相关的也会向内核注册该事件可以处理哪些类型的事件,额,貌似比较绕口,其实就是系统提前帮你预定好了不少事件,然后它自认为自己可以处理匹配所有类型的事件了(evdev.c函数),这些事件包括按键、键盘、鼠标之类的输入设备事件;那么这个事件是怎么通过input内核来找到注册的设备?事件和设备驱动都有个id号,input内核通过对比两者注册的时候带入的id号来匹配(input_register_handler与input_register_device中分别调用input_attach_handler函数进行匹配),如果匹配的话,就会建立一个handle处理结构体,里面分别加入了两个东西的信息,通过handle结构体,彼此就可以找到了,就跟找了个中介没啥两样;具体的可以看input.c函数。

对于input输入子系统,也可以采用platform的分离结构,driver端向platform虚拟总线注册设备驱动:platform_driver_register ( struct platform_driver *drv ),device端向platform虚拟总线注册设备:platform_device_register ( struct platform_device *pdev ),在driver端和device端匹配成功后,在driver端的probe函数里面调用input_register_device(struct input_dev *input),这样就完成了一个输入子系统的分层/分离设计;

LCD字符设备也是一样的处理:向platform虚拟总线注册设备驱动:platform_driver_register ( struct platform_driver *drv ),device端向platform虚拟总线注册设备:platform_device_register ( struct platform_device *pdev ),在driver端和device端匹配成功后,在driver端的probe函数里面调用register_framebuffer ( struct fb_info *fb_info ),这样就完成了一个LCD设备的分层/分离设计;

特别提醒:platform虚拟总线不是写驱动必须的,完全是为了通用化设计、方便硬件移植而设计的,有兴趣的可以用,没兴趣的完全可以把这玩意儿扔掉。

是不是很简单?框架是比较简单,不过要写好一个稳定好用的驱动还是很难的,还得靠经验积累,以及调试能力。

以上均为个人原创,如有不足,欢迎指正!正如本人博客名,小菜鸟一个,扔扔石头就行,别开枪!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值