首页 理论教育深入剖析Linux内核设备驱动的USB总线驱动框架

深入剖析Linux内核设备驱动的USB总线驱动框架

【摘要】:USB总线主设备框架还是以bus_type作为入口来了解总线框架。

1.总线相关以及核心框架

针对USB功能,Linux内核中提供了主设备和从设备两个不同的框架,这里主要介绍作为主设备的框架。USB总线主设备框架还是以bus_type作为入口来了解总线框架。

978-7-111-49426-3-Chapter07-166.jpg

usb_bus_type中重要的是usb_device_match,下面来了解细节:

978-7-111-49426-3-Chapter07-167.jpg

978-7-111-49426-3-Chapter07-168.jpg

从分析中可知,USB总线框架主要管理的是两类设备,分别是usb_device和usb_inter-face。从USB规范的角度可知usb_interface更专注于功能,应该是获得描述符之后才创建的,而usb_device则对应于USB物理设备。这样就从逻辑功能和物理层面都对设备进行管理,从管理层次上来说也是完整的。对应的驱动包括usb_device_driver和usb_driver,其中usb_device_driver对应于usb_device,而usb_driver则对应于usb_interface。usb_device_driver主要用于实现设备发现,而usb_driver则主要实现与功能模块的关联以及电源管理相关的功能。

像其他总线设备一样,总线控制器负责总线事务的交互。USB主设备总线框架就是对以上内容的管理,具体架构如图7-14所示。

978-7-111-49426-3-Chapter07-169.jpg

图7-14 Linux USB主设备总线架构

从图7-14可见,USB总线框架各模块划分,包括host software主要负责协议相关的部分,包括枚举设备、数据传输等;USBDI(USB driver interface)主要负责屏蔽USB细节,为其他功能框架使用USB总线传输的接口层;USBD(即USB driver)负责USB设备的功能关联;HCDI则是屏蔽不同总线控制器之间的差别;最后Host Controller Driver是具体的总线控制器的驱动,相应地负责与总线控制器交互完成总线传输。

这样整体框架从层次的角度就完整了。

2.总线控制器相关

USB总线框架对总线控制器的管理主要是通过usb_hcd来实现的,其详细分析如下:

978-7-111-49426-3-Chapter07-170.jpg

978-7-111-49426-3-Chapter07-171.jpg

从管理实体中可见,其中除了自身的属性和状态之外还包含了root hub相关的信息,这与硬件及规范一致。另外重要的就是hc_driver,其中包含实际操作的接口,负责总线传输。由于USB总线控制器有不同的类型,如OHCI、EHCI、UHCI、XHCI等,这里usb_hcd是对所有这些总线控制器共性的抽象,相应的hcd_priv指向不同控制器私有的属性,主要是定义不同的传输排列方式以及控制状态寄存器等。这里与其他总线控制器实体不同的是没有设备模型的实体,主要是由于USB总线控制器与root hub的亲密关系,而root hub本身就是设备,而设备的层次关系通过usb_bus中的controller进行关联。

关于总线控制器,USB框架提供了创建以及注册管理的接口。首先来了解创建的接口usb_create_hcd:

978-7-111-49426-3-Chapter07-172.jpg

从分析中可见,USB总线控制器的操作已经与USB总线以及root hub的操作相结合,这与它们之间的紧密关系是分不开的。

对于注册与管理接口,USB框架的接口为usb_add_hcd,主要功能是初始化并注册总线控制器,其中同样包括注册USB总线以及创建并注册root hub。在调用了usb_add_hcd时,就创建了总线,从而可以进行设备发现以及驱动功能绑定的工作。

框架提供了统一的传输以及其他总线控制器功能操作接口,具体如下:

978-7-111-49426-3-Chapter07-173.jpg

这样总线控制器的底层与上层就完整了。

3.总线设备相关

USB设备在总线框架中已经有所介绍,主要由usb_device和usb_interface共同完成。先来了解usb_device的详细信息:(www.chuimin.cn)

978-7-111-49426-3-Chapter07-174.jpg

978-7-111-49426-3-Chapter07-175.jpg

从分析中可见,总线规范中关于设备的各种属性都在usb_device中有了体现。再来看看interface的管理实体:

978-7-111-49426-3-Chapter07-176.jpg

usb_interface会在枚举时创建usb_host_interface,其中包含了endpoint的信息,这与总线规范是一致的,另外通过interface_to_usbdev可以关联到usb_device(通过dev的parent关联的),这样设备层面就都关联在一起了。

总线设备最重要的功能就是设备发现,USB总线的设备发现流程如图7-15所示。

这里主要是hub的功能,最终会通过usb_new_device来将usb_device注册进系统,相应的usb_device是通过usb_alloc_dev进行分配的,在usb_new_device中会读取描述符,在注册之后就会进行对应设备驱动的match工作。在总线框架中可知,usb_device直接返回的值为1,这是由于系统中只有一个对应于usb_device的驱动,即usb_generic_driver,细节如下:

978-7-111-49426-3-Chapter07-177.jpg

图7-15 Linux USB设备发现流程

978-7-111-49426-3-Chapter07-178.jpg

接下来设备发现的功能由generic_probe实现,下面来看看细节:

978-7-111-49426-3-Chapter07-179.jpg

978-7-111-49426-3-Chapter07-180.jpg

这里主要是读取配置信息,并进行配置。在usb_set_configuration中会根据设备的属性创建所有的usb_interface并注册。这样USB系统就开始对功能驱动的匹配工作,相应的进入到USB总线match工作的后半部分,即usb_interface相关的部分,找到相应的驱动再执行probe,从而完成整个设备发现及驱动绑定的功能。

4.总线传输接口

USB总线传输主要是实现USB总线规范中的四种传输,在Linux USB框架中通过urb进行管理,主要内容如下:

978-7-111-49426-3-Chapter07-181.jpg

978-7-111-49426-3-Chapter07-182.jpg

USB总线的传输是以urb为核心展开的。具体的流程如图7-16所示。

为了简化USB总线传输操作,USB总线框架提供了如下接口以实现几种类型的总线传输功能:

978-7-111-49426-3-Chapter07-183.jpg

978-7-111-49426-3-Chapter07-184.jpg

978-7-111-49426-3-Chapter07-185.jpg

图7-16 Linux USB总线传输流程图

USB总线框架已经为主要功能都提供了统一的操作,并提供了良好的接口供驱动开发。