一、drivers/usb目录结构
atm cdns3 class core dwc3 gadget image Kconfig misc mtu3 phy roles storage usbip
c67x00 chipidea common dwc2 early host isp1760 Makefile mon musb renesas_usbhs serial typec usb-skeleton.c
usb-skeleton.c
是一个简单地USB驱动框架。core
实现一些核心功能,为别的驱动程序提供服务,例如,申请内存,实现所有设备都要用到的公共函数、初始化整个USB系统,初始化Root hub,主机控制器公共代码等。host
不同类型的主机控制器的代码。gadget
包括UDC
驱动和gadget
驱动:
UDC
这个是针对具体的CPU平台的,gadget
驱动主要包括,file_storage等。
二、USB Core
- 内核里面的USB子系统
- USB主机控制器(HCD),提供主机控制器硬件的抽象。
- 在写USB驱动的时候,只能调用core的接口,core会将请求发送给HCD执行。

wc
命令可以统计文件字数或者行数。- USB子系统的入口是
usb_init
函数,主要完成初始化动作,之后它所使用的资源就会被释放掉。 - linux设备模型:
- bus_type:device *dev_root表示总线有哪些设备
- device:我们可以知道 struct device 中的 bus 表示这个设备连到哪个总线上,driver 表示这个设备的驱动是什么。
- device_driver;struct device_driver 中的 bus 表示这个驱动属于哪个总线
kobject
是总线、设备和驱动等对象的基类,实现了一些公共的接口。
kset
是同种类型kobject
对象的集合,也可以说是对象的容器。- c通过在结构体中嵌入
kobject
来实现继承,kobject
中包含了parent
成员,指向上一层节点。
kset
通过链表来实现。klist
包含一个链表和一个自旋锁bus_type
中有两条链表,分别是设备列表和驱动列表。- 内核要求每出现一个设备或者驱动就要想总线汇报(注册)。
- 在系统初始化的时候,会扫描连接了哪些设备,并为每一个设备建立一个
device
的变量。每次有一个驱动程序,就要准备一个device_driver
变量。并将这些变量分别插入devices
和drivers
链表。这样总线就能找到每个设备和每个驱动。
- 而设备和驱动是怎么关联起来的呢?
- 现在我们的两个链表有了,但这两个链表是相互独立的,没有关联起来。
- 每当有一个新的设备接进来的时候,设备就会去
drivers
链表中查找,有没有适合自己的驱动,如果找到了就通过函数device_bind_driver
将device
中的driver
指向找到的那个驱动。而这个驱动也会把这个设备加入到它的klist_devices
链表中。
usb_bus_type
用来注册总线,落实设备模型。
match
函数指针负责匹配设备和驱动。match
指向usb_device_match
方法,这个方法里面,会区别device
和interface
,分别进行处理。
interface 设备接口
- 设备可以有多个接口,每个接口对应着一个功能,每个接口对应着一个驱动。
device
落实到USB子系统里面就成了两个结构:一个是usb_device
,一个是usb_interface
。- 设备可以有多个配置,配置里面可以包含一个或者多个接口,接口通常具有一个或者多个设置。
minor
是分配给设备的次设备号。linux
所有的硬件设备都是用文件来表示的,俗称设备文件,在/dev
目录下,ls -l
可以查看设备的主设备号
和次设备号
。主设备号,决定了你应该加载哪个驱动,次设备号决定驱动应该操作那个设备。usbfs
提供了用户空间直接访问USB硬件设备的接口。usbfs_driver
用来完成这件事情。usb_devio_init
中USB_DEVICE_DEV
使用了USB_DEVICE_MAJOR
,用来让用户空间可以通过usbfs
访问内核设备。- linux系统为USB设备预留的主设备号是
USB_MAJOR
,在usb_major_init
里面注册了字符设备。 /proc/devices
文件显示了当前系统已经分配出去的主设备号。- 通常来说,USB设备并不会用到预留的这个主设备号,而是使用与其关联的子系统的设备号。
- 如果usb设备没有与其他任何子系统相关联,就需要通过
usb_register_dev
函数注册,或得主设备号USB_MAJOR
。 - 如果关联了其他子系统,就需要在对应驱动程序的
probe
函数中使用相应的注册函数。 - USB 接口关联有其他子系统,也就是说不使用
USB_MAJOR
作为主设备号时,struct usb_interface
的字段 minor
可以忽略。minor
只在 USB_MAJOR
起作用时才起作用. needs_remote_wakeup
表示挂起的设备是否可以给主机发信号,用来唤醒自己或者主机。usb_dev
基本可以忽略。