USB驱动作为一个系统,集成了众多的驱动模块,注册过程非常复杂。从USB监控软件系统的角度来说,USB主机驱动主要包含: 1) USB核驱动; 2) 主机控制器驱动; 3) 集线器驱动
在USB系统驱动加载的过程中,创建了集线器的线程(khubd),并且一直查询相应的线程事务。HCD驱动中,将集线器作为一个设备添加到主机控制器驱动中,然后进行集线器端口的初始化。在USB服务器主机看来,根集线器本身也是USB主机的设备。USB主机驱动加载完成之后,即开始注册根集线器,并且作为一个设备加载到主机驱动之中。
USB Core的初始化
subsys_initcall()是一个宏,可以理解为module_init()。由于此部分代码非常重要,开发者把它看作一个子系统,而不仅仅是一个模块。USB Core这个模块代表的不是某一个设备,而是所有USB设备赖以生存的模块。在Linux中,像这样一个类别的设备驱动被归结为一个子系统。subsys_initcall(usb_init)告诉我们,usb_init才是真正的初始化函数,而usb_exit将是整个USB子系统结束时的清理函数。
4.1.3 注册集线器
USB主机和USB设备之间进行数据交互,USB服务器设备本身并没有总线控制权,U盘被动地接收USB Server主机发送过来的信息并做出响应。USB主机控制器与根集线器构成了主机系统,然后外接其它的USB设备。
1、URB传输过程
USB Server初始化过程中,无论是主机控制器驱动还是根集线器驱动,都是通过URB传输获取设备信息。
三种事务传输模式下的URB初始化函数有很多相似之处,主要参数含义如下:
2、 申请URB
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
为urb分配内存并执行初始化。
3、初始化URB
初始化具体的urb包
不同的传输模式下,驱动为之申请不同的URB。其中,Linux内核只支持同步传输外的三种传输事件,ISO事务需要手工进行初始化工作。控制传输事务、批量传输事务、中断传输事务API如上所示。
4、提交URB
URB初始化完成之后,USBD开始通过usb_start_wait_urb()提交urb请求(它调用usb_submit_urb来真正的发送URB请求),添加completition函数。
接下来,从message.c传到主机控制器(hcd.c),开始真正的usb_hcd_submit_urb()。此时,根据是否为根集线器,进入不同的工作队列。