usb标准描述符之技巧
usb是个通用的总线,端口都是统一的。但是usb设备却各种各样,例如usb鼠标,usb键盘,u盘等等,那么usb主机是如何识别出不同的设备的呢?这就要依赖于描述符了。
usb的描述符主要有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,hid描述符,报告描述符等等。
一个usb设备有一个设备描述符,设备描述符里面决定了该设备有多少种配置,每种配置描述符对应着配置描述符;而在配置描述符中又定义了该配置里面有多少个接口,每个接口有对应的接口描述符;在接口描述符里面又定义了该接口有多少个端点,每个端点对应一个端点描述符;端点描述符定义了端点的大小,类型等等。由此我们可以看出,usb的描述符之间的关系是一层一层的,最上一层是设备描述符,下面是配置描述符,再下面是接口描述符,再下面是端点描述符。在获取描述符时,先获取设备描述符,然后再获取配置描述符,根据配置描述符中的配置集合长度,一次将配置描述符、接口描述符、端点描述符一起一次读回。其中可能还会有获取设备序列号,厂商字符串,产品字符串等。
每种描述符都有自己独立的编号,如下:
#define device_descriptor 0x01 //设备描述符
#define configuration_descriptor 0x02 //配置描述符
#define string_descriptor 0x03 //字符串描述符
#define interface_descriptor 0x04 //接口描述符
#define endpoint_descriptor 0x05 //端点描述符
下面分别详细介绍一下各描述符。
1.设备描述符
//定义标准的设备描述符结构
typedef struct _device_dcescriptor_struct
{
byte blength; //设备描述符的字节数大小
byte bdescriptortype; //设备描述符类型编号
word bcdusb; //usb版本号
byte bdeviceclass; //usb分配的设备类代码
byte bdevicesubclass; //usb分配的子类代码
byte bdeviceprotocol; //usb分配的设备协议代码
byte bmaxpacketsize0; //端点0的最大包大小
word idvendor; //厂商编号
word idproduct; //产品编号
word bcddevice; //设备出厂编号
byte imanufacturer; //设备厂商字符串的索引
byte iproduct; //描述产品字符串的索引
byte iserialnumber; //描述设备序列号字符串的索引
byte bnumconfigurations; //可能的配置数量
}
device_descriptor_struct, * pdevice_descriptor_struct;
//实际的设备描述符示例
code device_descriptor_struct device_descriptor= //设备描述符
{
sizeof(device_descriptor_struct), //设备描述符的字节数大小,这里是18字节
device_descriptor, //设备描述符类型编号,设备描述符是01
0x1001, //usb版本号,这里是usb01.10,即usb1.1。由于51是大端模式,所以高低字节交换
0x00, //usb分配的设备类代码,0表示类型在接口描述符中定义
0x00, //usb分配的子类代码,上面一项为0时,本项也要设置为0
0x00, //usb分配的设备协议代码,上面一项为0时,本项也要设置为0
0x10, //端点0的最大包大小,这里为16字节
0x7104, //厂商编号,这个是需要跟usb组织申请的id号,表示厂商代号。
0xf0ff, //该产品的编号,跟厂商编号一起配合使用,让主机注册该设备并加载相应的驱动程序
0x0100, //设备出厂编号
0x01, //设备厂商字符串的索引,在获取字符串描述符时,使用该索引号来识别不同的字符串
0x02, //描述产品字符串的索引,同上
0x03, //描述设备序列号字符串的索引,同上
0x01 //可能的配置数为1,即该设备只有一个配置
};
2.配置描述符
//定义标准的配置描述符结构
typedef struct _configuration_descriptor_struct
{
byte blength; //配置描述符的字节数大小
byte bdescriptortype; //配置描述符类型编号
word wtotallength; //此配置返回的所有数据大小
byte bnuminterfaces; //此配置所支持的接口数量
byte bconfigurationvalue; //set_configuration命令所需要的参数值
byte iconfiguration; //描述该配置的字符串的索引值
byte bmattributes; //供电模式的选择
byte maxpower; //设备从总线提取的最大电流
}
configuration_descriptor_struct, * pconfiguration_descriptor_struct;
2.接口描述符
//定义标准的接口描述符结构
typedef struct _interface_descriptor_struct
{
byte blength; //接口描述符的字节数大小
byte bdescriptortype; //接口描述符的类型编号
byte binterfacenumber; //该接口的编号
byte balternatesetting; //备用的接口描述符编号
byte bnumendpoints; //该接口使用的端点数,不包括端点0
byte binterfaceclass; //接口类型
byte binterfacesubclass; //接口子类型
byte binterfaceprotocol; //接口遵循的协议
byte iinterface; //描述该接口的字符串索引值
}
interface_descriptor_struct, * pinterface_descriptor_struct;
4.端点描述符
//定义标准的端点描述符结构
typedef struct _endpoint_descriptor_struct
{
byte blegth; //端点描述符字节数大小
byte bdescriptortype; //端点描述符类型编号
byte bendpointaddress; //端点地址及输入输出属性
byte bmattributes; //端点的传输类型属性
word wmaxpacketsize; //端点收、发的最大包大小
byte binterval; //主机查询端点的时间间隔
}
endpoint_descriptor_struct, * pendpoint_descriptor_struct;
下面是一个配置描述符集合的定义
typedef struct _con_int_endp_descriptor_struct
{
configuration_descriptor_struct configuration_descriptor;
interface_descriptor_struct interface_descritor;
endpoint_descriptor_struct endpoint_descriptor[endpoint_number];
}con_int_endp_descriptor_struct;
配置描述符集合的示例
code con_int_endp_descriptor_struct con_int_endp_descriptor= //配置描述符集合
{
//configuration_descriptor //配置描述符
{
sizeof(configuration_descriptor_struct), //配置描述符的字节数大小,这里为9
configuration_descriptor, //配置描述符类型编号,配置描述符为2
(sizeof(configuration_descriptor_struct)+
sizeof(interface_descriptor_struct)+
sizeof(endpoint_descriptor_struct)*endpoint_number)*256+
(sizeof(configuration_descriptor_struct)+
sizeof(interface_descriptor_struct)+
sizeof(endpoint_descriptor_struct)*endpoint_number)/256, //配置描述符集合的总大小
0x01, //只包含一个接口
0x01, //该配置的编号
0x00, //iconfiguration字段
0x80, //采用总线供电,不支持远程唤醒
0xc8 //从总线获取最大电流400ma
},
//interface_descritor //接口描述符
{
sizeof(interface_descriptor_struct), //接口描述符的字节数大小,这里为9
interface_descriptor, //接口描述符类型编号,接口描述符为3
0x00, //接口编号为4
0x00, //该接口描述符的编号为0
endpoint_number, //非0端点数量为2,只使用端点主端点输入和输出
0x08, //定义为usb大容量存储设备
0x06, //使用的子类,为简化块命令
0x50, //使用的协议,这里使用单批量传输协议
0x00 //接口描述符字符串索引,为0,表示没有字符串
},
//endpoint_descriptor[]
{
{ //主端点输入描述
sizeof(endpoint_descriptor_struct), //端点描述符的字节数大小,这里为7
endpoint_descriptor, //端点描述符类型编号,端点描述符为5
main_point_in, //端点号,主输入端点
endpoint_type_bulk, //使用的传输类型,批量传输
0x4000, //该端点支持的最大包尺寸,64字节
0x00 //中断扫描时间,对批量传输无效
},
{ //主端点输出描述
sizeof(endpoint_descriptor_struct), //端点描述符的字节数大小,这里为7
endpoint_descriptor, //端点描述符类型编号,端点描述符为5
main_point_out, //端点号,主输出端点
endpoint_type_bulk, //使用的传输类型,批量传输
0x4000, //该端点支持的最大包尺寸,64字节
0x00 //中断扫描时间,对批量传输无效
}
}
};
其中关于端点的类型定义如下
//定义的端点类型
#define endpoint_type_control 0x00 //控制传输
#define endpoint_type_isochronous 0x01 //同步传输
#define endpoint_type_bulk 0x02 //批量传输
#define endpoint_type_interrupt 0x03 //中断传输
端点号的定义如下
#define main_point_out 0x02 //2号输出端点
#define main_point_in 0x82 //2号输入端点
你见过有四个管脚的LED灯吗?
iOS11推出两个Beta版本之后公测版正式发布?现在可以下载iOS11公测版系统了
简谈FPGA研发设计相关规范(企业中很实用)
工业4.0时代下的智能电网如何建设
三星Galaxy Note 21仍将发布!但不在研发Galaxy Note 22
usb标准描述符之技巧
在智慧城市里建设智能电网的四大意义
智慧无线灌溉在园林中的应用
热像仪保养维修小技巧有哪些呢
放大器中的交叉失真波形及传递特性摘要
英特尔i9系列曝光目前核心数产品Core i9-7920X:24个框框
肉制品检测仪器设备特点【莱恩德LD-R】
四维图新与腾讯双方子公司联手 深度挖掘无人驾驶
水平垂直燃烧试验机:基本原理、使用方法及应用价值
信号发生器的的划分及选型注意事项
迈宝智能获千万级天使轮融资,外骨骼机器人如何服务于物流行业?
比特币多头蠢蠢欲动,现在是看涨不追涨阶段
数字PFC整体控制框图
微软开放嵌入版.Net源码 免除相关授权费
安立公司 PIM Master™ 荣获 Frost & Sullivan 颁发创新奖