加载中…
个人资料
无语僧314
无语僧314
  • 博客等级:
  • 博客积分:0
  • 博客访问:238,488
  • 关注人气:29
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

USB 协议分析 设置USB地址 和 配置-字符串描述符

(2012-08-14 16:57:31)
标签:

描述符

主控器

字符串

设备地址

配置

it

分类: 外围器件接口

USB协议深入分析 设置USB地址

 
前面已经解释主控器怎么样发送设备描述符下来,然后设备返回相应的设备描述符。下一步主控器的动作是做什么呢?由于在USB总线上的设备有很多,为了区分不同的设备通讯,就需要给每个设备分配一个地址,这跟网络中的IP地址是一样的,或者跟MAC地址也是一样的。因而,接着下来就是主控器分配地址给设备,USB的设备地址是从1开始到127。下面就是接收到主控器发下来的数据包:
00 05 01 00 00 00 00 00
USB_SETUP_PACKET定义具体地分析这个数据,就可以知道应做什么样的响应了。下面就来解释这个操作。
先取得bmRequestType的类型,也就是第一个字节,它是00。从USB协议里查看,它的方向位是主控器发送给设备,由D6D5位就知道它是USB协议里定义的标准请求,由D4-D0位知道它是USB设备接收这个包数据。
bRequest是05,从前面已经介绍的类型,就知道它是设置地址,如下:
SET_ADDRESS             5
所以这个包需要按设置地址的格式去解释后面的数据。
 
由于USB协议可以知道,USB的设备地址放在字段wValue里,因它的值是01 00,按小端格式解释就是0x0001了。其它相应的字段wIndexwLength应都是0,如果是其它非0的数据,是没有定义的。
 
USB的串行引擎通过这个地址来判断是否接收总线上的数据,如果发送的地址跟它一致,就会接收主控器发过来的数据,当然从这个设备发送出去的数据也带有这个地址,因此就可以让主控器识别不同的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
分析上面的数据如下:
bmRequestType是80,表示方向USB设备发送给主控器,接收设备是USB设备。
bRequest是06,表示这是获取描述符。GET_DESCRIPTOR         6
wValue是00 02。低字节表示偏移地址00,高字节表示描述符的类型。如下:
CONFIGURATION          2
所以这里的返回的设备描述符是配置描述符。
wIndex是00 00。
wLength是09 00。它表示返回描述符的长度。这里是9个字节。
接着下来,就是设备返回配置描述符给主控器,发送的数据如下:
09 02 22 00 01 01 00 01 32
发送的数据是按下面的结构来定义,这也是在USB协议里定义的格式。如下:
typedef struct _USB_CONFIGURATION_DESCRIPTOR {
 BYTE bLength;
 BYTE bDescriptorType;
 WORD wTotalLength;
 BYTE bNumInterfaces;
 BYTE bConfigurationValue;
 BYTE iConfiguration;
 BYTE bmAttributes;
 BYTE MaxPower;
} USB_CONFIGURATION_DESCRIPTOR;
 
bLength是配置的长度,也就是配置结构的整个长度。在这里9个字节。
bDescriptorType是描述符的类型,这里配置描述符,所以设置为02。
wTotalLength是所有配置设置的结构长度。包括配置描述符、接口描述符、HID或者其它描述符和端点描述符的长度。这里是22 00,也就是0x0022个字节。
bNumInterfaces是接口个数,这里一个。
bConfigurationValue是配置的个数,当设置配置时发送的值。这时设置为1个配置。
iConfiguration是说明配置的字符的偏移值。这里是0。
bmAttributes是配置特性,D7位保留。D6位是说明是否自供电。D5位是否支持远程唤醒。D4—D0是保留,设置为0。
MaxPower是使用的功率,它采用电流来表示。每2mA为单位,比如它的值是50时就表示是100mA的电流消耗。
通过这样说明,主控器就知道这个设备是什么样的设备,有多少功能。
 
 
USB协议深入分析 字符串描述符
上一次说到把配置描述符返回给主控器那里了,现在接着下来,就会收到主控器发来字符串描述符。如果在设备描述符那里指定没有字符串描述的话,在这里是不会收到字符串描述符的。由于我在设备描述符里指定有字符串描述符的偏移地址,因此,就收到主控器发出请求字符串描述符。收到的数据如下:
80 06 00 03 00 00 FF 00
bmRequestType是80,表示方向USB设备发送给主控器,接收设备是USB设备。
bRequest是06,表示这是获取描述符。GET_DESCRIPTOR         6
wValue是00 03。低字节表示偏移地址00,高字节表示描述符的类型,如下:
STRING                   3
wIndex是00 00。
wLength是FF 00。它表示返回描述符的长度。这里是256个字节。
因此,这个获取字符串描述符,就是从字符串描述内存里,0偏移地址开始的位置读取第一个字符串描述符返回给主控器。接着就返回下面的数据给主控器:
04 03 09 04
上面的数据是按字符串描述符来组织的,它的结构,我定义结构如下:
typedef struct _USB_STRING_DESCRIPTOR {
 BYTE bLength;
 BYTE bDescriptorType;
 WORD bString;
} USB_STRING_DESCRIPTOR;
 
bLength是所有数据的长度。在这里是4。
bDescriptorType是描述类型,这里字符串描述符,所以它是3。
bString是可变的字符数组。不超过254个应都可以的,并且它是使用UNICODE编码的字符串。在这里是09 04,这是美国英语的标识,0x0409。如果想输入中文的标识,只要改为0x0804就可以了。
通过这个字符串描述符,主控器就知道字符串描述符是使用什么语言说明的了,这样就可以支持全世界的语言标识。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有