USB描述符的分类与介绍
USB的符述符分为几类?有人可能会答:设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符等。但这里说的不是这样的。上面的几类描述符属于USB标准描述符。另外还有HID描述符和Hub描述符。所以分类是这样的:
1. 标准描述符
1) 设备描述符
2) 配置描述符
3) 字符串描述符
4) 接口描述符
5) 端点描述符
6) 设备限定描述符
7) 其他速率配置描述符
2. HID描述符
3. Hub描述符
1 标准描述符
标准描述符是指一组设备描述符,包括设备描述符、配置描述符、字符串描述符、接口描述符、端点描述符、设备限定描述符和其他速率配置描述符。这七种描述符具有类似的格式,比如说它们的第一个字段都是bLength,第二个字段都是bDescriptorType。七种描述符在使用时以bDescriptorType字段来区分。描述符类型与对应的bDescriptorType字段值对应关系为:
设备描述符描述的是设备的整体信息,与设备本身一一对应,一个设备只能有一个设备描述符。在主机对USB设备枚举的过程中,首先要做的就是获取设备描述符,以对设备有一个整体的了解。
设备描述符由14个字段组成,总长度18字节:
这些字段都有一个小写字母表示的前缀,它们所表示的意思如下:
b 表一个字节,=8bits;
w 表一个字,=16bits;
bm 表按位寻址;
bcd 用BCD码表示;
i 表索引值
id 表标识码
各字段含义:
bLength: 表示描述符的长度,对于设备描述符来说,其值为18,即0x12。
bDescriptorType: 描述符类型,对应表1中的值,设备描述符为0x01。
bcdUSB:该设备遵循的USB版本号,以BCD码表示,USB1.1为0x0101,USB2.0为0x0200。
bDeviceClass:该设备所属的标准设备类,USB协议中对常见的设备进行了分类。该字段值为0x01~0xFE时,表示是USB协议中已定义的设备类,常用的HID设备类编号为0x03,其它设备类编号参:http://www.usb.org/developers/defined_class
bDeviceProtocol:用于表示USB设备类所采用的设备类协议,其值和bDeviceClass和bDeviceSubClass有关。当此字段为0时,表示不使用任何设备类协议。如果该USB设备属于某个设备类和设备子类,则应该继续指明所采用的设备类协议。当该字段为0xFF时,表明设备类协议由供应商自定义。
bMaxPacketSize0:用于表示在USB设备中,端点0所支持最大数据包的长度,它以字节为单位。对于低速USB设备,bMaxPacketSize0为8;对于全速USB设备,bMaxPacketSize0为8、16、32、64;对于高速USB设备,bMaxPacketSize0为64。
IdVendor:用于表示USB设备供应商的ID。USB组织中规定每种产品都必须包含一个供应商ID,这样可以使主机加载合适的驱动程序。
idProduct:用于表示USB产品的ID,由设备供应商提供。idProduct用于表示特定的USB设备,在USB设备上电的时候可以帮助USB主机选择合适的驱动程序。
bcdDevice:用于表示USB设备的版本号,它以BCD码的形式表示。一般来说bcdDevcie由设备供应商指定,在USB设备上电的时候可以帮助USB主机选择合适的驱动程序。
iManufacturer:用于表示供应商字符串描述符的索引值。具体字符串的内容在后面字符串描述符中定义。如果没有供应商字符串,可以置0。
iSerialNumber:用于表示设备序列号字符串描述符的索引值,如果没有,可以置为0。
bNumConfigurations:用于表示该USB设备所支持的配置数。
-
就像我们平时程序设计经常使用的方法一样,一个对象由一个结构体来表示,但还会再用来一个结构体来描述这个对象的一些属性。usb驱动框架也采用了这样的设计思想,usb框架中每一个组成部分都用两个结构体来描述:一个结构体表示成员组成,另一个结构体表示属性组成。Linux-USB核心定义了4个usb描述符。
- struct usb_device <---> struct usb_device_descriptor
- struct usb_host_config; <--> struct usb_config_descriptor
- struct usb_host_interface; <--> struct usb_interface_descriptor
- struct usb_host_endpoint; <--> struct usb_endpoint_descriptor
由此可见 struct usb_device的名称应该改为 struct usb_host_device
设备描述
linux内核使用struct usb_device来描述一个usb设备
struct usb_device
{
int devnum; usb设备号char devpath [16]; 设备id字符串
enum usb_device_state state; 设备状态:未连接,已配置
enum usb_device_speed speed; 高速,全速,低速
struct usb_tt *tt;
int ttport;
unsigned int toggle[2];
struct usb_device *parent;
struct usb_bus *bus;
struct usb_host_endpoint ep0;
struct device dev;
struct usb_device_descriptor descriptor; usb设备描述符
struct usb_host_config *config;
struct usb_host_config *actconfig;
struct usb_host_endpoint *ep_in[16];
struct usb_host_endpoint *ep_out[16];
char **rawdescriptors;
unsigned short bus_mA;
u8 portnum;
u8 level;
unsigned can_submit:1;
unsigned discon_suspended:1;
unsigned persist_enabled:1;
unsigned have_langid:1;
unsigned authorized:1;
unsigned authenticated:1;
unsigned wusb:1;
int string_langid;
/* static strings from the device */
char *product;
char *manufacturer;
char *serial;
struct list_head filelist;
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *usb_classdev;
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry;
#endif
int maxchild;
struct usb_device *children[USB_MAXCHILDREN];
int pm_usage_cnt;
u32 quirks;
atomic_t urbnum;
unsigned long active_duration;
#ifdef CONFIG_PM
struct delayed_work autosuspend;
struct work_struct autoresume;
struct mutex pm_mutex;
unsigned long last_busy;int autosuspend_delay;
unsigned long connect_time;
unsigned auto_pm:1;
unsigned do_remote_wakeup:1;
unsigned reset_resume:1;
unsigned autosuspend_disabled:1;
unsigned autoresume_disabled:1;
unsigned skip_sys_resume:1;
#endif
struct wusb_dev *wusb_dev;
};
linux内核使用struct usb_device_descriptor来对应usb描述符中的设备描述符
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
__u8 bLength;描述符长度,固定为0x12
__u8 bDescriptorType;设备描述符类型,固定为0x01
__le16 bcdUSB;规范发布号。表示本设备能适用哪种协议,如2.0=0200
__u8 bDeviceClass;类型代码
__u8 bDeviceSubClass;子类型代码
__u8 bDeviceProtocol;协议代码
__u8 bMaxPacketSize0;端点0最大分组大小
__le16 idVendor;供应商ID
__le16 idProduct;产品ID,由厂家自行设置
__le16 bcdDevice;设备出厂编码,由厂家自行设置
__u8 iManufacturer;厂商描述符字符串索引,索引到对应的字符串描述符。为0表示没有。
__u8 iProduct;产品描述符字符串索引
__u8 iSerialNumber;设备序列号字符串索引
__u8 bNumConfigurations;可能的配置数。
} __attribute__ ((packed)); 按字节对齐
上面的这个结构是根据usb协议而来的
Table 9-8. Standard Device Descriptor
1.2 配置描述符
一个USB设备可以有多种配置,不同的配置使设备工作在不同的状态下,每个配置必须有一个配置描述符。其格式包括8个字段,共9字节。
配置描述
linux内核使用struct usb_host_config来描述一个usb配置:
struct usb_host_config{
struct usb_config_descriptor desc; 配置描述符
char *string; /* iConfiguration string, if present */配置的字符串(如果存在)
/* List of any Interface Association Descriptors in this
* configuration. */
struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
/* the interfaces associated with this configuration,
* stored in no particular order */
struct usb_interface *interface[USB_MAXINTERFACES];接口链表
/* Interface information available even when this is not the
* active configuration */
struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
unsigned char *extra; /* Extra descriptors */
int extralen;
};
配置描述
linux内核使用struct usb_config_descriptor来对应usb描述符中的配置描述符
struct usb_config_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 wTotalLength;
__u8 bNumInterfaces;
__u8 bConfigurationValue;
__u8 iConfiguration;
__u8 bmAttributes;
__u8 bMaxPower;
} __attribute__ ((packed));
上面的这个结构是根据usb协议而来的
Table 9-10. Standard Configuration Descriptor
接口描述
linux 内核使用struct usb_interface来描述usb接口。
struct usb_interface
{
/* array of alternate settings for this interface,
* stored in no particular order */
struct usb_host_interface *altsetting; 接口设置数组
struct usb_host_interface *cur_altsetting; /* the currently当前设置
* active alternate setting */
unsigned num_altsetting; /* number of alternate settings */设置数
/* If there is an interface association descriptor then it will list
* the associated interfaces */
struct usb_interface_assoc_descriptor *intf_assoc;
int minor; /* minor number this interface is
* bound to */
enum usb_interface_condition condition; /* state of binding */
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
unsigned ep_devs_created:1; /* endpoint "devices" exist */
unsigned unregistering:1; /* unregistration is in progress */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
unsigned needs_binding:1; /* needs delayed unbind/rebind */
unsigned reset_running:1;
struct device dev; /* interface specific device info */
struct device *usb_dev;
int pm_usage_cnt; /* usage counter for autosuspend */
struct work_struct reset_ws; /* for resets in atomic context */
};
一个配置包含一个或多个接口,一个接口包含一个或多个设置
struct usb_host_interface {
struct usb_interface_descriptor desc;接口描述符
/* array of desc.bNumEndpoint endpoints associated with this
* interface setting. these will be in no particular order.
*/
struct usb_host_endpoint *endpoint;接口包含的端点不包含0号端点,它是控制端点。
char *string; /* iInterface string, if present */
unsigned char *extra; /* Extra descriptors */
int extralen;
};
接口描述
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;接口包含的端点个数,不包含0号端点,它是控制端点。
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
} __attribute__ ((packed));
上面的这个结构是根据usb协议而来的
Table 9-12. Standard Interface Descriptor
1.5 端点描述符
端点描述符用于指出USB端点的特性,包括其所支持的传输类型、传输方向等信息。USB中规定,端点0没有端点描述符,其余端点必须包含端点描述符。端点描述符由6个字段组成,共7个字节。其格式如下:
端点描述
struct usb_host_endpoint {
struct usb_endpoint_descriptor desc;端点描述符
struct list_head urb_list;
void *hcpriv;
struct ep_device *ep_dev; /* For sysfs info */
unsigned char *extra; /* Extra descriptors */
int extralen;
int enabled;
};
端点描述
struct usb_endpoint_descriptor
{
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress;
__u8 bmAttributes;
__le16 wMaxPacketSize;
__u8 bInterval;
/* NOTE: these two are _only_ in audio endpoints. */
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
Table 9-13. Standard Endpoint Descriptor
{
BYTE bLength; //设备描述符的字节数大小,为0x12
BYTE bDescriptorType; //描述符类型编号,为0x01
BYTE SomeDescriptor[36]; //UNICODE编码的字符串
}
其他的描述符略。。。