USB描述符

一.设备描述符配置包

typedef struct
{
    uint8_t bmRequestType;
    uint8_t bRequest;
    uint16_t wValue;
    uint16_t wIndex;
    uint16_t wLength;
}USB_SETUP_PACKET;

​ 假设数据包为:80 06 00 01 00 00 40 00

  1. bmRequestType

    bit 7: data transfer direction 传输方向
           0:HOST-to-device 下传
           1:Device-to-host 上传
    bit 6-5: Type 请求类型
             0:Standard 标准请求
             1:Class 类请求
             2:Vendor 厂商请求
             3:Reserved 保留
    bit 4-0: Recipient 接收对象
             0:Device 设备接收
             1:Interface 接口接收
             2:Endpoint 端点接收
             3:Other 其他
             4-31:Reserved 保留
    
  2. bRequest描述符的请求类型

    GET_STATUS				0
    CLEAR_FEATURE			1
    Reserved for future use	2
    SET_FEATURE				3
    Reserved for future use	4
    SET_ADDRESS				5
    GET_DESCRIPTOR			6
    SET_DESCRIPTOR			7
    GET_CONFIGUARTION		8
    SET_CONFIGUARTION		9
    GET_INTERFACE			10
    SET_INTERFACE			11
    SYNCH_FRAME				12
    

    06:表示GET_DESCRIPTOR,可以得知主机想要获取USB设备的描述符,但是还不清楚具体是什么类型的描述符。

  3. wValue

    GET_DESCRIPTOR这个字节中,低字节表示描述符的索引,高字节表示描述符的类型,高字节的类型如下:

    DEVICE						1
    CONFIGUARTION				2
    STRING						3
    INTERFACE					4
    ENDPOINT					5
    DEVICE_QUALIFIER			6
    OTHER_SPEED_CONFIGURATION	7
    INTERFACE_POWER1 			8
    

    wVlaue:00 01:表示从偏移地址0开始读取描述符,01表示设备描述符。

  4. wIndex是根据不同的请求而设置不同的值,一般用来说明端点号或者说明接口标识,在获取描述符里,设置为0,或者是语言ID,在这个发送的描述符里,它是设置为00 00

  5. wLength是根据请求来决定下一阶段发送数据的长度。前面请求第一个字节里,已经说明下一阶段数据传送的方向,这里说明了传送数据的长度,不管是发送数据还是接收数据,都不要超过这个数据长度,在这个获取设备描述符里,它的长度是40 00,按小端格式解释,就是64个字节。

二.回应设备描述符

typedef struct
{
    u8 bLength;             //描述结构体大小
    u8 bDescriptorType;     //描述符类型
    u16 bcdUSB;             //USB版本号
    u8 bDeviceClass;        //设备类代码
    u8 bDeviceSubClass;     //子类代码
    u8 bDeviceProtocol;     //设备协议代码
    u8 bMaxPacketSize0;     //端点0的最大包大小
    u16 idVendor;           //生产厂商编号
    u16 idProduct;          //产品编号
    u16 bcdDevice;          //设备出厂编号
    u8 iManufacturer;       //设备厂商字符串索引
    u8 iProduct;            //产品描述字符串索引
    u8 iSeriaNumber;        //设备序列号字符串索引
    u8 bNumConfigurations;  //当前速度下载能支持的配置数量
}

​ 返回给主控制器的数据结构就是上面的内容,只要把上面的结构体填写合适的内容,就可以发送给主控制器,12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01

  1. bLength是本结构体的大小,本次返回的结构体长度是0X12,也就是18个字节。

  2. bDescriptorType是描述符的类型,它的定义跟主控制器发下来的描述符类型是一样的,如下:

    DEVICE						1
    CONFIGUARTION				2
    STRING						3
    INTERFACE					4
    ENDPOINT					5
    DEVICE_QUALIFIER			6
    OTHER_SPEED_CONFIGURATION	7
    INTERFACE_POWER1 			8
    

    由于返回的是设备描述符,所以就选择了0x01,用这个类型来区分不同的描述符。

  3. bcdUSBUSB发布的版本协议,USB1.1表示为0x0110.

  4. bDeviceClass是设备分类,当它的值是0时,表示所有接口在配置描述符里,并且所有接口是独立的。当它的值是1FEH时,表示不同的接口关联的。当它的值是FFH时,它是厂商自己定义的。在这个设备里,它的值为0.

  5. bDeviceSubClass是设备子分类码,当前面的bDeviceClass值是0时,这里一定要设置为0,其他就根据USB-IF组织定义的编码。

  6. bDeviceProtocols是设备使用的协议,如果使用USB-IF组织定义的协议,就需要设置这里的值,如果不使用,就直接设置为0,如果厂商自己定义的可以设置为FFH,以上三个值,在本设备中全部设置为0.

  7. bMaxPacketSize0是端点0收发最大包的大小,仅允许设置8、16、32、64中的任何一个大小。

  8. idVendor是厂商标识,由USB-IF分配的编码,这里使用0x8000.

  9. idProduct是厂商定义的产品标识,可以让操作系统加载不同的驱动程序。

  10. bcdDevice是用BCD表示的设备发布的版本号,这里是1.00.

  11. iManufacturer是厂商字符串的偏移值,这个值主要说明了它在字符串描述符里的偏移位置,如果它设置为0,表示没有厂商字符串,在这里是0x04.

  12. iProduct是产品字符串的偏移值…,在这里是0x2C.

  13. iSerialNumber是序列号字符串的偏移值…,在这里是0x4A.

  14. bNumConfigurations是配置描述符的个数,在这里只使用了一个配置描述符,所以设置为1.

三.设置USB地址

​ 前面已经解释了主控制器怎样发送设备描述符下来,然后设备返回相应的设备描述符,下一步就是主控制器分配地址给设备,USB的设备地址是从1开始到127,下面就是接收到主控制器发下来的数据包:00 05 01 00 00 00 00 00.

​ 由USB_SETUP_PACKET定义具体的分析这个数据,就知道应做什么样的响应了。先取得bmRequestType的类型,也就是第一个字节,它是00,从USB协议里查看,它的方向位是主控制器发送给设备,由bit5和bit6位可以得知它是USB协议里定义的标准请求,由bit4-0位知道它是USB设备接收这个包数据。

bRequest05,为设置地址SET_ADDRESS,所以这个包需要按设置地址的格式去解释后面的数据。

wValue存放USB的设备地址,因为它的值是01 00,按小端格式解释就是0x0001.

USB的串行引擎通过这个地址来判断是否接收总线上的数据,如果发送的地址跟它一致,就会接收主控制器发过来的数据,当然从这个设备发出去的数据也带有这个地址,因此就可以让主控制器识别不同的USB设备数据了。

四.配置描述符

​ 在有了设备地址后,主机会再次发送获取上面已经读取的设备描述符:80 06 00 01 00 00 12 00,然后USB设备也再次回应它,但这次发送的长度是0x0012了,不会是第一次64个字节长度了。接着USB设备就返回下面的描述符给主控制器,也就是第一次已经发送的设备描述符,如下:12 01 10 01 00 00 00 40 00 80 00 80 00 01 04 2C 4A 01,这样分配地址之后,再次获取设备描述符成功了。

​ 接着就是主控制器获取配置描述符,下面就是收到的配置描述符数据:80 06 00 02 00 00 09 00,分析以上数据:

  1. bmRequestType:80,表示方向是从USB设备发送给主机,接收设备是USB设备。

  2. bRequest:06,表示获取描述符,GET_DESCRIPTOR

  3. wValue:00 02,低字节表示偏移地址00,高字节表示描述符的类型,CONFIGURATION,返回的是配置描述符。

  4. wIndex:00 00

  5. wLength:09 00,表示返回描述符的长度,这里是9个字节

    接下来就是设备返回配置描述符给主控制器,发送的数据如下:09 02 22 00 01 01 00 01 32,发送的数据是按下面的结构来定义,这也是在USB协议里定义的格式:

    typedef struct 
    {
        u8 bLength;             //描述结构体大小
        u8 bDescriptorType;     //描述符类型
        u16 wTotallLength;      //配置描述符集合总长度
        u8 bNumInterfaces;      //配置支持的接口数
        u8 bConfigurationValue; //该配置的值
        u8 iConfiguartion;      //描述该配置的字符串索引值
        u8 bmAttributes;        //供电模式选择
        u8 bMaxPower;           //设备需要的最大电源
    }
    
    1. bLength配置的长度,也就是配置结构的整个长度,这里为9字节。
    2. bDescriptorType是描述符的类型,这里是配置描述符,所以设置为02
    3. wTotallLength是所有配置设置的结构长度,包括配置描述符、接口描述符、HID描述符、端点描述符或者其他描述符。这里是22 00,也就是0x0022个字节。
    4. bNumInterfaces是接口个数,这里一个。
    5. bConfigurationValue是配置的个数,当设置配置时发送的值,这个设置为1个配置。
    6. iConfiguration是说明配置的字符的偏移,这里是0
    7. bMAttributes是配置特性,D7位保留,D6位是说明是否自供电,D5位是否支持远程唤醒,D4-D0是保留。
    8. bMaxPower是使用的功率,它采用电流来表示,每2mA为单位,通过这样的说明,主控制器就知道这个设备是什么样的的设备,有多少功能。

    五.字符串描述符

    ​ 如果在设备描述符那里指定没有字符串描述符的话,在这里是不会收到字符串描述符的,由于我在设备描述符里有字符串描述符的偏移地址,因此,就收到主控制器发出请求字符串描述符,收到的数据如下:80 06 00 03 00 00 FF 00

    1. bmRequestType:80表示方向是从USB设备发送给主控制器,接收设备是USB设备。

    2. bRequest:06表示这是获取描述符,GET_DESCRIPTOR

    3. wValue:00 03,低字节表示偏移地址00,高字节表示描述符的类型STRING

    4. wIndex:00 00

    5. wLength:FF 00,它表示返回描述符的长度,这里是256个字节。

      因此,这个获取字符串描述符,就是从字符串描述符内存里,0偏移地址开始的位置读取第一个字符串描述符返回给主控制器。接着就返回下面的数据给主控制器:04 03 09 04

      typedef struct
      {
          u8 bLength;
          u8 bDescriptorType;
          u16 bString;
      }
      
      1. bLength是所有数据的长度,这里为4。

      2. bDescriptorType是描述类型,这里字符串描述符,所以这是3.

      3. bString是可变的字符串数组,不超过254个都应该是可以的,并且它是使用UNICODE编码的字符串,在这里09 04,这是美国英语的标识,0x0409。如果想输入中文的标识,只要改为0x0804就可以了。

        通过这个字符串描述符,主控制器就知道字符串描述符是使用什么语言说明的了,这样就可以支持全世界的语言标识。

      原文链接:https://www.cnblogs.com/Daniel-G/p/3993883.html

上一篇:Linux(十)redis数据库安装及相关操作


下一篇:产品经理必知的英文缩写