25.2 USB驱动程序框架

25.2  USB驱动程序框架

Linux内核提供了完整的USB驱动程序框架。USB总线采用树形结构,在一条总线上只能有唯一的主机设备。Linux内核从主机和设备两个角度观察USB总线结构。本节介绍Linux内核USB驱动程序框架。

25.2.1  Linux内核USB驱动框架

图25-2是Linux内核从主机和设备两个角度观察USB总线结构的示意图。

从图25-2中可以看出,Linux内核USB驱动是按照主机驱动和设备驱动两套体系实现的,下面介绍两套体系的结构和特点。

1.基本结构

图25-2的左侧是主机驱动结构。主机驱动的最底层是USB主机控制器,提供了OHCI/EHCI/UHCI这3种类型的总线控制功能。在USB控制器的上一层是主机控制器的驱动,分别对应OHCI/EHCI/UHCI这3种类型的总线接口。USB核心部分连接了USB控制器驱动和设备驱动,是两者之间的转换接口。USB设备驱动层提供了各种设备的驱动程序。

USB主机部分的设计结构完全是从USB总线特点出发的。在USB总线上可以连接各种不同类型的设备,包括字符设备、块设备和网络设备。所有类型的USB设备都是用相同的电气接口,使用的传输协议也基本相同。向用户提供某种特定类型的USB设备时,需要处理USB总线协议。内核完成所有的USB总线协议处理,并且向用户提供编程接口。

 
(点击查看大图)图25-2  Linux内核USB总线结构

图25-2右侧是设备驱动结构。与USB主机类似,USB设备提供了相同的层次结构与之对应。但是在USB设备一侧使用名为Gadget API的结构作为核心。Gadget API是Linux内核实现的对应USB设备的核心结构。Gadget API屏蔽了USB设备控制器的细节,控制具体的USB设备实现。

2.设备

每个USB设备提供了不同级别的配置信息。一个USB设备可以包含一个或多个配置,不同的配置使设备表现出不同的特点。其中,设备的配置是通过接口组成的。Linux内核定义了USB设备描述结构如下:

 
 
  1. struct usb_device_descriptor {  
  2.     __u8  bLength;              // 设备描述符长度  
  3.     __u8  bDescriptorType;      // 设备类型  
  4.  
  5.     __le16 bcdUSB;              // USB版本号(使用BCD编码)  
  6.     __u8  bDeviceClass;         // USB设备类型  
  7.     __u8  bDeviceSubClass;      // USB设备子类型  
  8.     __u8  bDeviceProtocol;      // USB设备协议号  
  9.     __u8  bMaxPacketSize0;      // 传输数据的最大包长  
  10.     __le16 idVendor;            // 厂商编号  
  11.     __le16 idProduct;           // 产品编号  
  12.     __le16 bcdDevice;           // 设备出厂号  
  13.     __u8  iManufacturer;        // 厂商字符串索引  
  14.     __u8  iProduct;             // 产品字符串索引  
  15.     __u8  iSerialNumber;        // 产品***索引  
  16.     __u8  bNumConfigurations;   // 最大的配置数量  
  17. } __attribute__ ((packed)); 

从usb_device_descriptor结构定义看出,一个设备描述符定义了与USB设备有关的所有信息。

3.接口

在USB体系中,接口是由多个端点组成的。一个接口代表一个基本的功能,是USB设备驱动程序控制的对象。一个USB设备最少有一个接口,功能复杂的USB设备可以有多个接口。接口描述定义如下:

 
 
  1. struct usb_interface_descriptor {  
  2.     __u8  bLength;              // 描述符长度  
  3.     __u8  bDescriptorType;      // 描述符类型  
  4.  
  5.     __u8  bInterfaceNumber;     // 接口编号  
  6.     __u8  bAlternateSetting;    // 备用接口编号  
  7.     __u8  bNumEndpoints;        // 端点数量  
  8.     __u8  bInterfaceClass;      // 接口类型  
  9.     __u8  bInterfaceSubClass;   // 接口子类型  
  10.     __u8  bInterfaceProtocol;   // 接口使用的协议  
  11.     __u8  iInterface;           // 接口索引字符串数值  
  12. } __attribute__ ((packed)); 

4.端点

端点是USB总线通信的基本形式,每个USB设备接口可以认为是端点的集合。主机只能通过端点与设备通信。USB体系结构规定每个端点都有一个唯一的地址,由设备地址和端点号决定端点地址。端点还包括了与主机通信用到的属性,如传输方式、总线访问频率、带宽和端点号等。端点的通信是单向的,通过端点传输的数据只能是从主机到设备或者从设备到主机。端点定义描述如下:

 
 
  1. struct usb_endpoint_descriptor {  
  2.     __u8  bLength;              // 描述符长度  
  3.     __u8  bDescriptorType;      // 描述符类型  
  4.  
  5.     __u8  bEndpointAddress;     // 端点地址  
  6.     __u8  bmAttributes;         // 端点属性  
  7.     __le16 wMaxPacketSize;      // 端点接收的最大数据包长度  
  8.     __u8  bInterval;            // 轮询端点的时间间隔  
  9.  
  10.     /* NOTE:  these two are _only_ in audio endpoints. */  
  11.     /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */  
  12.     __u8  bRefresh;  
  13.     __u8  bSynchAddress;  
  14. } __attribute__ ((packed)); 

5.配置

配置是一个接口的集合。Linux内核配置的定义如下:

 
 
  1. struct usb_config_descriptor {  
  2.     __u8  bLength;              // 描述符长度  
  3.     __u8  bDescriptorType;      // 描述符类型  
  4.  
  5.     __le16 wTotalLength;        // 配置返回数据长度  
  6.     __u8  bNumInterfaces;       // 最大接口数  
  7.     __u8  bConfigurationValue;  // 配置参数值  
  8.     __u8  iConfiguration;       // 配置描述字符串索引  
  9.     __u8  bmAttributes;         // 供电模式  
  10.     __u8  bMaxPower;            // 接口的最大电流  
  11. } __attribute__ ((packed)); 

配置描述符结构定义了配置的基本属性和接口数量等信息。