这里的排版很乱,不知道怎么搞的,这里的好一些: http://tubocurarine.is-programmer.com/posts/26968.html
学习一下 Linux 下的 USB 相关的一些知识,做个记录。
当在 USB 下谈到设备 (device) 时,我们需要多加注意, 区分下面几个术语: 设备 (device)、功能 (function)、配置 (configration) 、接口 (interfaces) 和端点 (End Points)。
- device 可以是连接到 USB 总线上的任何东西,比如摄像头、U 盘等等。 而每一个设备,又可能由多个功能单元组成,从而提供多个功能 (function) 。 每个功能单元,都可能有各自的驱动。
- 每个设备都提供了一套或者多套配置 (Configuration) 。配置决定了设备的总体特性,例如, 一个设备可能提供了两套配置:一个用于使用外部电源时,另外一个用于由 USB 总线供电时。
- 每个配置由若干接口 (interfaces) 组成,每个接口都可以提供不同的设置 (Setting) 选项。 以摄像头为例,一个摄像头可能提供三个接口:一个是使能麦克,一个使能摄像头,或者两个都使能。 使用不同的接口,可能会导致设备占用的带宽的不同。
- 每个接口都通过驱动来控制若干端点 (EndPoints)。
USB 设备根据其用于,可以分为若干类。 Linux 内核中,按照这些分类来组织驱动,可参考 drivers/usb/Readme :
- core/ : USB 子系统的核心代码,包括 usbfs 文件以及 hub 类 (class) 的驱动
- host/ : USB host controller 驱动,包括 UHCI, OHCI, EHCI 等。
- gadget/ : USB 外部控制器驱动, 以及与外部控制器交互的若干部件的驱动。
- image/ : 图像相关驱动,如扫描仪、数码相机等。
- ../input/ : 输入相关驱动,如键盘、鼠标,触摸屏等。
- ../media/ : 多媒体驱动,如摄像头等。
- ../net/ : 网卡驱动。
- serial/ : USB/串口转接器的驱动。
- storage/: 存储相关,如 U 盘。
USB 标准规定了四种不同的传输模式:控制传输 (Control transfer), 批量传输 (Bulk transfer), 中断传输 (Interrupt transfer) 和等时传输 (Isochronous transfer)。
-
控制传输:
控制传输用来在对设备进行配置的时候,传输控制信息, 占用的带宽较小。 该过程中控制信息通过预先定义的命令 (Commands) 来表示,这些命令包括 GET_STATUS, SET_INTERFACE 等等, 这些命令可以在 USB 标准中查到。 Linux 内核代码中,这些命令都是预先定义的,以 USB_REQ_ 开头的变量, 位于 include/usb/ch9.h 中。 例如:
/* * Standard requests, for the bRequest field of a SETUP packet. * * These are qualified by the bRequestType field, so that for example * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved * by a GET_STATUS request. */ #define USB_REQ_GET_STATUS 0x00 #define USB_REQ_CLEAR_FEATURE 0x01 #define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_SET_DESCRIPTOR 0x07
USB Standard 中仅定义了所有设备都需要支持的的命令的最小集, 在此之外,厂商还可以根据自己的设备来自行添加所需的命令。
-
批量传输 (Bulk transfer:)
批量传输一般用于数据传输,该传输可能会占用所有的带宽。 这种操作下,数据的传输必需在由总线保证的安全情况下进行, 换句话说, 一块数据必需不变地传输到目的设备上。 U 盘和扫描仪等设备都大量的使用批量传输。
-
中断传输 (Interrupt transfer)
中断传输与批量传输类似,但是它会定期的发生。 两次中断传输的间隔,在一定的范围内,可以由驱动自行设置。
-
等时传输 (Isochronous transfer)
等时传输是几种传输模式中比较特殊的一种。 这种模式下,数据的传输采用了一个固定的、预定义的带宽。 该传输适用于需要持续的数据流,同时可以容忍偶尔的数据丢失的情况下, 比如摄像头。
USB 子系统主要任务包括:
- 注册和管理设备驱动。
- 为 USB 设备寻找驱动,并初始化和配置设备。
- 在内核中表现设备的树形结构。
- 与设备交互。
在 Linux 内核中, 该完成这些任务的子系统由两层构成。
-
Host Controller 驱动
即主控制器驱动。 控制器向 USB 链提供连接选项,并向终端设备提供电路上的通讯。 控制器本身则必需连接到其他系统总线上。 当前, USB 控制器主要可分为 OHCI, EHCI 和 UHCI 几类。
-
终端设备驱动
设备驱动负责与各个 USB 设备打交道,并将该设备的功能提供给内核的其他部分。 设备驱动通过标准化的接口来与 host controller 通讯,从而分离了控制器类型和设备驱动。
其中:
-
busnum & bus_name:
用于在全局中唯一标识该总线:前者为用于注册是使用的 Number , 后者为描述性的字符串。
-
controller:
由于总线也是一个设备, usb_bus 中通过做为通用设备模型的 controller 来表明构成该总线的设备实例。
-
bus_list:
一个表头,用于将该 usb_bus 添加到全局的链表中,便于管理。
-
root_hub:
root_hub 实际上是一个虚拟出来的实例(参考第一小节),用于表示树形结构的根。
-
devmap:
一个 bitmap , 用于记录该总线上已经分配了哪些 USB Number, 还有剩余。
其中:
-
devnum:
Device Number, 该设备号为该设备在 USB 总线上的地址, 在整个 USB 树形结构中是全局唯一的。
-
state & speed:
表示设备的状态和速度,具体参考下面的定义:
enum usb_device_speed { USB_SPEED_UNKNOWN = 0, /* enumerating */ USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ USB_SPEED_HIGH, /* usb 2.0 */ USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ USB_SPEED_SUPER, /* usb 3.0 */ }; enum usb_device_state { /* NOTATTACHED isn't in the USB spec, and this state acts * the same as ATTACHED ... but it's clearer this way. */ USB_STATE_NOTATTACHED = 0, /* chapter 9 and authentication (wireless) device states */ USB_STATE_ATTACHED, USB_STATE_POWERED, /* wired */ USB_STATE_RECONNECTING, /* auth */ USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_DEFAULT, /* limited function */ USB_STATE_ADDRESS, USB_STATE_CONFIGURED, /* most functions */ USB_STATE_SUSPENDED /* NOTE: there are actually four different SUSPENDED * states, returning to POWERED, DEFAULT, ADDRESS, or * CONFIGURED respectively when SOF tokens flow again. * At this level there's no difference between L1 and L2 * suspend states. (L2 being original USB 1.1 suspend.) */ };
-
devpath:
表示了该设备在 USB 树形结构中的位置。
-
parent:
设备挂在的 hub 。
-
bus:
表明了该设备位于那个总线上。 usb_bus 的介绍在前面小节。
其他的成员变量,可以参考该结构定义之前的注释。
其中:
-
name
驱动名字,全局唯一,一般用于管理用途。
-
drvwrap
该结构是 Linux 内核模型中通用驱动的一个包装,定义如下:
struct usbdrv_wrap { struct device_driver driver; int for_devices; };
其中,
- driver 是通用驱动
- for_devices 用于区分该驱动是接口驱动还是设备驱动:
- for_devices = 0: 接口驱动
- for_devices = 1: 设备驱动
-
id_table
与 pci_driver 类似, USB 设备驱动通过 id_table 来表明该驱动所能驱动的设备。
其定义如下:
struct usb_device_id { /* which fields to match against? */ __u16 match_flags; /* Used for product specific matches; range is inclusive */ __u16 idVendor; __u16 idProduct; __u16 bcdDevice_lo; __u16 bcdDevice_hi; /* Used for device class matches */ __u8 bDeviceClass; __u8 bDeviceSubClass; __u8 bDeviceProtocol; /* Used for interface class matches */ __u8 bInterfaceClass; __u8 bInterfaceSubClass; __u8 bInterfaceProtocol; /* not matched against */ kernel_ulong_t driver_info; };
其中的 match_flags 是一个 flag , 用于说明在确定某一设备是否该由该驱动进行管理时, 应该比较的成员变量。
-
probe 与其他函数指针
若干操作函数。其中, probe 会在为设备找到驱动或者为驱动找到了设备后调用。