已经看了很长时间USB的驱动了。USB是目前看到最复杂的驱动,内容很多,但网上分析USB驱动的资料很少,因此我在学习的过程中走了很多弯路。在这里记录自己的学习过程,希望可以帮到其他研究USB驱动的同事。先推荐一本书:Bootstrap Yourself With Linux-USB Stack
首先,USB的驱动分成两部分:host和gadget。usb是一个host driven的协议,即host是完全主动,每次通信过程都是由host发起的,包括读和写。而device只负责回应,不能主动去读写。另外,虽然usb有四种传输(在很多书中都有介绍),但是usb的传输和其他的通信方式都一样,都是基于硬件中断的。无论在host方还是device方,都是产生中断之后,进行相应的处理。因此,中断函数是很多处理过程的入口点。这里的硬件中断和四种传输方式中的中断传输是完全不同的概念。
在LDD中,说不介绍gadget部分的驱动,但是它提到了configuration\interface\endpoint等概念。其实这些设置在host和gadget上面都有,在gadget的驱动里负责实现 configuration\interface,在host的驱动中,主要是得到gadget的configuration和interface,进而对gadget进行控制。
本文以s3c2440上的gadget驱动为例,分析gadget的驱动。 在以后的文章中在分析host的驱动。因为gadget的驱动相对简单。
首先,usb的驱动都是分层的。gadget部分的驱动分层如下:
其中,1.usb device controller就是具体的硬件,对应到2440的usb device controller。在数据手册上面可以看到相应的说明。2440还有一个usb host controller。这是两个不同的硬件,分别用于实现2440的usb device 和 usb host功能,在使用时,各用各的,没有相互的影响。
2. device firmware driver。这是最低层的驱动实现,其实这部分的驱动就是负责直接控制 device controller硬件的。对应的文件是usb/gadget/s3c2410_udc.c。在这部分文件中,可以配置相应的寄存器,获取硬件资源等。device controller也是实现成了一个platform device的。
3. chapter 9-- Driver/usb device framework。按照我的理解,这部分的驱动主要是一个中间层,在这部分实现了 usb 枚举的过程(在device部分是被动的,主要是如何回应host 发过来的请求。),实现从 frimware driver 和 class driver 的通信。我们可以对应到 composite.c 这个文件。
4. usb class driver。这部分驱动是要实现具体的功能的。比如最常用的u盘的功能、usb 鼠标的功能。我们以zero.c驱动为例进行分析,这个驱动可以实现的功能是可以将host发送过来的消息 回送 给主机。相当于是一个echo的作用。
从上面的分析,可以看出,firmware driver负责控制硬件,class driver 负责处理具体的业务,完成具体的功能。device frimwork负责处理其他的事情。上面就是usb device部分的分层模型。
通常,在一般介绍usb驱动的资料中,上来就介绍几个usb相关的结构体,每个结构体都很大,让人看了根本摸不到头脑。我觉得这里的分层模型是更重要的。
前面转载了两篇介绍usb 枚举过程的博客,都是写的很好的。网上的资料中,最丰富的算是 linux那些事之USB。不得不佩服写相关博客的那位博主,真是相当有才。深入分析usb的同时穿插着各种各种段子,我强忍着剧烈痛苦看了一个星期,收获不大,不得不说那个博文太过庞杂。
下面,具体分析各层。首先,是s3c2410_udc.c文件。这个文件中先是按照platform device,实现了基本的probe函数等。
/*
* probe - binds to the platform device
*/
static int s3c2410_udc_probe(struct platform_device *pdev)
{
struct s3c2410_udc *udc = &memory;
struct device *dev = &pdev->dev;
int retval;
int irq;
dev_dbg(dev, "%s()\n", __func__);
usb_bus_clock = clk_get(NULL, "usb-bus-gadget&