USB驱动——描述符

USB描述符的分类与介绍

USB的符述符分为几类?有人可能会答:设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符等。但这里说的不是这样的。上面的几类描述符属于USB标准描述符。另外还有HID描述符和Hub描述符。所以分类是这样的:
1. 标准描述符
            1) 设备描述符
             2) 配置描述符
             3) 字符串描述符
             4) 接口描述符
             5) 端点描述符
             6) 设备限定描述符
             7) 其他速率配置描述符
2. HID描述符
3. Hub描述符

1 标准描述符

标准描述符是指一组设备描述符,包括设备描述符、配置描述符、字符串描述符、接口描述符、端点描述符、设备限定描述符和其他速率配置描述符。这七种描述符具有类似的格式,比如说它们的第一个字段都是bLength,第二个字段都是bDescriptorType。七种描述符在使用时以bDescriptorType字段来区分。描述符类型与对应的bDescriptorType字段值对应关系为:

  1.1 设备描述符

设备描述符描述的是设备的整体信息,与设备本身一一对应,一个设备只能有一个设备描述符。在主机对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设备所支持的配置数。


  1. 就像我们平时程序设计经常使用的方法一样,一个对象由一个结构体来表示,但还会再用来一个结构体来描述这个对象的一些属性。usb驱动框架也采用了这样的设计思想,usb框架中每一个组成部分都用两个结构体来描述:一个结构体表示成员组成,另一个结构体表示属性组成。Linux-USB核心定义了4个usb描述符。

  2. struct usb_device  <--->  struct usb_device_descriptor
  3. struct usb_host_config; <--> struct usb_config_descriptor
  4. struct usb_host_interface; <--> struct usb_interface_descriptor
  5. 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


1.3 字符串描述符
在USB协议中字符串描述符是可选的。字符串描述符用于保存一些供应商名称、产品序列号等文本信息。它的长度是不固定的,随字符串的数量和信息的长度变化而变化。其格式如下:

 
1.4 接口描述符
接口是端点的集合,负责完成USB的特定功能,例如数据的输入输出。接口描述符用于描述一个接口,包含了接口的特性,如端点个数,所属设备类和子类等。它有9个字段,共9字节。其格式如下:


接口描述

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


struct _STRING_DEscriptOR_STRUCT

{

BYTE bLength; //设备描述符的字节数大小,为0x12

BYTE bDescriptorType; //描述符类型编号,为0x01

BYTE SomeDescriptor[36]; //UNICODE编码的字符串

}


其他的描述符略。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值