赞
踩
原文地址:http://blog.csdn.net/ghostyu/article/details/8114929
和i2c驱动类似,usb驱动架构中也有usb-core这样的框架,为上层设备驱动程序提供封装后的方便使用的api函数,为底层与硬件相关的代码封装提供总线接入功能。
撇开复杂的usb协议,我们先认知linux驱动中的usb框架,至于细节的实现,需要漫长的代码。在我们还不知道它长什么样的时候就去讨论内部的实现机制就毫无意义的。
图1
准确的说,图1是不完整的usb驱动架构,但是有助于对架构的理解。不光是i2c,linux均是以这样的架构呈现。
对于我们初学者来说,先接触一下usb协议的基本概念,然后在分析一个代表性的usb设备驱动,这样是一个有效的学习usb驱动的途径。
之后,在深入usb协议再分析usb-core。
linux内核源码中的/drivers/usb/usb-skeleton.c 文件为我们提供了一个最基础的usb驱动程序,即usb骨架程序,可以看做这是一个最简单的usb设备驱动实例,尽管具体的usb设备驱动千差万别,但其骨架则万变不离其宗。
我们的usb驱动开发也从他开始。
linux USB驱动程序需要做的第一件事件就是在linux usb子系统里注册,这个子系统就是usb-core,同事提供一些相关信息,例如这个驱动程序支持哪种设备,当被支持的设备从系统插入或者拔出时,会有哪些动作,所有这些信息都传送到usb子系统中,在usb-skeleton.c 中是这样表示的。
其实在2.4的内核中struct usb_driver skel_driver中还有file_operations的一个成员(现在被移到了usb_class_driver中),大多数usb驱动程序需要钩住另外一个驱动系统,usb驱动往往不是单独存在的,例如scsi、网络(usb网卡)、或者tty(usb转串口)子系统,这些驱动程序在其他驱动系统中注册,同事任何用户空间的交互操作(open、read、write、ioctl等)通过那些借口提供,比如我们把scsi设备驱动作为我们usb驱动钩住的另外一个驱动系统,那么我们此sub设备的read、write等操作,就相应按scsi设备的read、write函数进行访问。但如果没有一个匹配的驱动系统可以使用时,那我们就要自己处理与用户空间的read、write等交互函数,在usb_class_driver中提供注册file_operations的函数指针,这样就可以与用户空间实现方便的交互。
当usb设备插入时,为了使hotplug系统自动装载驱动程序,还需要创建一个table,如下:
现在,usb-skeleton驱动就已经和设备绑定上了,任何用户态程序要操作此设备都可以通过file_operations结构所定义的函数进行了,
在skel_write中,有一个usb_fill_bulk_urb函数,实现urb系统callbak和我们自己的skel_write_bulk_callback回调函数。然后调用usb_submit_urb函数想目标端口提交写入的数据。
read函数与write函数稍有不同在于,read并没有用urb将数据从设备传送到驱动程序,而是用usb_bulk_msg函数代替,所以read能够不需要创建urbs和操作urb函数的情况下来读取设备数据到驱动程序,或者发送数据给设备。当对usb设备进行一次读或者写是,usb_bulk_msg函数是非常有用的,然后,当你需要连续的对设备进行读写是,最好自己建立自己的urbs。下面是代码展示。
有了上面的理解,usb驱动架构可以如图2所示
图2
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。