开发环境:win7
开发板 :51单片机 + pdiusbd12 芯片
前言:
在上一节的末尾,usb设备接收到了主机发送过来的数据 0x80 0x06 0x00 0x02 0x00 0x00 0xFF 0x00
通过查看 :
usb鼠标_USB标准请求之设备描述符(5)
可知主机是为了获取设备的配置描述符。
每个 USB 设备至少有一个配置描述符,在当前例子中,只有一个配置描述符。
每个配置描述符都有附属描述符,包括一个或多个接口描述符以及可选的端点描述符。主机通过发送 Get Descriptor 请求,
且使设置事务中wValue字段的高字节等于 02h,wLength 字段等于 wTotalLength 的方式,取得配置描述符及其附属描述符。
1,配置描述符
sTotalLength 等于配置描述符以及其所有附属描述符(接口/端点 等描述符)的字节总和。
bNumInterfaces 是接口配置中接口的数目,其最小值为01h。
bConfigurationValue ,主机用 Set Configuration 请求来选择配置,用 Get Configuration 请求来获取当前配置的数目。
其值必须为 01h或是更高值。取值为0的Set Device请求会使设备进入未配置状态(Not Configured state)。
iConfiguration 是一个索引,指向描述配置的字符串。若没有字符描述符,该值为 0.
bmAttribute 会将bit[6] 表示供电方式,当bit[6] 等于1时,表示设备是自供电的;当 bit[6] 为0时,表示设备是总线供电的。
bit[5]表示是否支持远程唤醒,当bit[5]等于1时,表示支持远程唤醒。为了与USB1.0兼容,bit[7]必须为1 ,bit[4~0] 保留,必须置为0。
bMaxPower 表示设备要求多少的总线电流。对于 USB2.0 ,bMaxPower 以 2mA 为单位,如果设备要求200mA,则bMaxPower 等于(200/2)= 100。对于超高速应用,bMaxPower以 8 mA 为单位。设备可请求的最大总线电流时:对于USB2.0 为 500 mA,对于 超高速应用为 900mA。如果所请求的电流不可用,主机将拒绝对设备进行配置。
-
typedef struct _configuration_descriptor
-
{
-
uint8_t bLength; // 配置描述符的字节数大小(09h)
-
uint8_t bDescriptorType; // 配置描述符类型编号(02h)
-
uint16_t sTotalLength; // 配置描述符及其全部附属描述符(接口,端点描述符)的字节数
-
uint8_t bNumInterfaces; // 配置中接口的数目
-
uint8_t bConfigurationValue;// Set/Get Configuration 请求的标识符
-
uint8_t iConfiguration; // 配置字符串描述符的索引
-
uint8_t bmAttributes; // 供电模式的选择,自供电,总想供电和远程唤醒的设置
-
uint8_t bMaxPower; // 设备从总线提取的最大电流,以2mA(USB2.0) 或 8mA(超高频)为单位所要求的总想功耗
-
}configuration_descriptor_t;
2,接口配置描述符
一个配置可含有多个同时行动的接口。这个接口可能联合于某个功能,也可能不相关。每个接口都有它自己的接口描述符和附属描述符。所有这些接口也可拥有一个或多个替代的接口设置,这些设置是互斥的,每次只有一个被激活。每个设置含有一个接口描述符及所属的附属描述符。使用等时传输的设备拥有替代的接口配置,因为缺省接口请求不了等时带宽。
bInterfaceNumber 用于确认接口。在复合设备中,配置拥有多个同时活动的接口,每个接口的描述符中,该字段取值必须唯一。缺省接口的该值为00h。
bAlternateSetting 用于确认缺省接口的设置或替代设置。对于每个 bInterfaceNumber,设备将提供一个bAlternateSetting 字段为 00h的接口描述符,这是缺省的设置。替代设置的描述符的bInterfaceNumber 字段于缺省设备的取值相同,但 bAlternateSetting 的取值唯一,随所需描述符的最后5个字节的取值而不同。对于每个 bInterfaceNumber,每次只有一个bAlternateSetting 可被激活。替代设置可使主机能够请求带有不同带宽或其他要求和性能的接口。 Get Interface请求会取得当前被激活的bAlternateSetting。 Set Interface 请求可选择特定bInterfaceNumber 所对应的bAlternateSetting.
bNumEndpoints 等于除端点0外接口所支持的端点数目。对于只支持端点0的设备,这个字段为0.
bInterfaceClass 除了用于由接口规定的设备外,其他与设备描述符中bDeviceClass字段相同。
bInterfaceSubClass 除带有由接口定义的类的设备外,此字段于设备描述符中的bDeviceSubClass 相同。若 bInterfaceClass 等于00h,bInterfaceSubClass 也必须等于 00h。若 bInterfaceClass 取从 01h到FEh的值,bInterfaceSubClass则等于00h或等于一个为接口的类定义的值。FFh表明为厂商定义的子类。
bInterfaceProtocol 除了带有接口定义的类的设备外,此字段于设备描述符中的bDeviceProtocol相同。此字段可为所选bInterfaceClass和bInterfaceSubClass 所规定的协议。若bInterfaceClass取从01h到FEh的值,bInterfaceProtocol必须等于00h,或等于为接口的类定义的值。FFh表明为厂商定义的协议。
iInterface 是指向描述接口的字符串的索引。若没有字符串描述符,该值为0.
-
typedef struct _initerface_descriptor
-
{
-
uint8_t bLength; // 接口描述符的字节数大小(09h)
-
uint8_t bDescriptorType; // 接口描述符的类型编号
-
uint8_t bInterfaceNumber; // 该接口的编号
-
uint8_t bAltenateSetting; // 备用的接口描述符编号
-
uint8_t bNumEndpoints; // 该接口使用的端点数,不包括端点0
-
uint8_t bInterfaceClass; // 接口类型
-
uint8_t bInterfaceSubClass; // 接口子类型
-
uint8_t bInterfaceProtocol; // 接口遵循的协议
-
uint8_t iInterface; // 描述该接口的字符串索引值
-
}interface_descriptor_t;
3,HID描述符
详情请看:
usb鼠标_配置描述符集合(7)之 HID
4,端点描述符
音频1.0类中的设备,将端点描述符拓展为两个额外的关于音频专属信息的字节。这是唯一被允许的改变标准描述符类型长度的操作。在需要的地方,类和其他规范应当定义单独的返回拓展信息的描述符。例如,USB3.0定义了endpoint companion(端点伙伴)描述符,来返回超高速专属端点信息。
bEndpointAddress 规定了端点的数目和方向。bit[3~0]是端点号,低速设备可最多拥有3个端点号(通常取值为0~2),而全速和高速设备可拥有16个端点号(0~15)。bit[4~6]保留,必须设置为0。bit[7] 为方向,OUT为0,IN为1.
bmAttributes ,bit[1~0]规定了端点所支持的传输方式:00 为控制协议,01为等时传输,10为批量传输,11为中断传输。
bit[7~6] 保留,必须置为0。
对于等时端点,bit[5~2]可表明一个同步类型和数据或反馈的使用类型。
对于超高速中断端点,bit[5~4]表明Notification(通知)或Periodic(周期)的适用类型。
wMaxPacketSize 规定了端点在一个事务中可传输的最大数据字节数。所允许的值会随着设备的速度和传输类型而改变。
对于USB2.0,bit[10~0]是最大信息包尺寸,范围是0~1024。bit[12~11]表明高手中断或等时端点在每个微帧所支持的额外事务数目:00表明没有额外事务(事务总数是每个微帧1个),01表示有1个额外事务(事务总数是每个微帧2个),10表示2个额外事务(事务总数为每微帧3个),11表示保留。对于USB1.x,其范围是0到1023.bit[15~11]保留,必须置为0
bInterval 规定中断和等时端点的服务时距。服务时距(service interval)是一个周期,主机必须在这个周期内安排端点事务。这个周期是帧(低俗和全速),微帧(高速)或总线时距(超高速)的整数倍。对于低速中断端点,bInterval为最大等待时间,单位为ms,取值范围是10到255。对于usb1.x设备中的全速中断端点及等时端点,时距等于以ms为单位的bInterval。对于中断端点,可能的取值范围是1~255;对于usb1.x的等时端点,此值为1。对于usb2.0设备中的全速的等时端点,允许取值范围1到16,且时距按(以ms为单位)2^(bInterval-1)计算,时间范围是1ms到32.768s。对于高速和超高速端点,此值以125us为单位。中断和等时端点的取值为1到16,时距为2^(bInterval-1)计算,允许的时间范围是125us到4.096s。
对于高速批量和控制OUT端点,此字段可含有一个最大NAK速率,即传输中要符合这个字段的要求。设备典型地将此值设为0,对于其他批量和控制传输,此值保留。
-
typedef struct _endpoint_descriptor
-
{
-
uint8_t bLength; // 端点描述符字节数大小
-
uint8_t bDescriptorType; // 端点描述符类型编号
-
uint8_t bEndpointAddress; // 端点地址及输入输出属性
-
uint8_t bmAttributes; // 端点的传输类型属性
-
uint16_t wMaxPacketSize; // 端点收、发的最大包字节大小
-
uint8_t bInterval; // 主机查询端点的时间间隔
-
}endpoint_descritpor_t;
5,功能实现
-
#define ENDPOINT_MAX 2
-
-
-
-
typedef struct _configuration_set
-
{
-
configuration_descriptor_t configuration;
-
interface_descriptor_t interface;
-
hid_descriptor_t hid;
-
endpoint_descritpor_t endpoint[ENDPOINT_MAX];
-
}configuration_set_t;
-
int32_t init_configuration_descriptor(configuration_descriptor_t * con)
-
{
-
int32_t ret = 0;
-
-
con->bLength = sizeof(configuration_descriptor_t);
-
con->bDescriptorType = DESC_TYPE_CONFIGURATION; // 配置描述符类型编号(02h)
-
con->sTotalLength = SWAP16(sizeof(configuration_set_t)); // 配置描述符及其全部附属描述符(接口,端点描述符)的字节数
-
con->bNumInterfaces = 0x01; // 配置中接口的数目
-
con->bConfigurationValue= 0x01; // Set/Get Configuration 请求的标识符
-
con->iConfiguration = 0x00; // 配置字符串描述符的索引
-
con->bmAttributes = 0xA0; // 供电模式的选择,自供电,总想供电和远程唤醒的设置
-
con->bMaxPower = 0xc8; // 设备从总线提取的最大电流,以2mA(USB2.0) 或 8mA(超高频)为单位所要求的总想功耗
-
-
-
return ret;
-
}
-
-
-
int32_t init_interface_descriptor(interface_descriptor_t * interface)
-
{
-
int32_t ret = 0;
-
-
interface->bLength = sizeof(interface_descriptor_t); //接口描述符的字节数大小
-
interface->bDescriptorType = DESC_TYPE_INTERFACE; //接口描述符类型编号
-
interface->bInterfaceNumber = 0x00; //接口编号为0
-
interface->bAltenateSetting = 0x00; //该接口描述符的编号
-
interface->bNumEndpoints = ENDPOINT_MAX; //非0端点数量为2,只使用端点主端点输入和输出
-
interface->bInterfaceClass = 0x03; //人机接口设备(HID)类
-
interface->bInterfaceSubClass = 0x01; //使用的子类:支持BIOS根启动Boot的子类
-
interface->bInterfaceProtocol = 0x02; //使用的协议:鼠标
-
interface->iInterface = 0x00; //接口描述符字符串索引
-
-
-
return ret;
-
}
-
void init_configuration_set(configuration_set_t *set)
-
{
-
init_configuration_descriptor(&(set->configuration));
-
init_interface_descriptor(&(set->interface));
-
-
// hid
-
{
-
set->hid.bLength = sizeof(hid_descriptor_t); //HID描述符的字节数大小
-
set->hid.bDescriptorType = DESC_TYPE_HID; //HID描述符类型编号
-
set->hid.bcdHID = SWAP16(0x0110); //HID类协议版本号,为1.1
-
set->hid.bCountryCode = 0x21; //固件的国家地区代号,0x21为美国
-
set->hid.bNumDescriptors = HID_SUB_DESCRIPTOR_MAX; //下级描述符的数量
-
-
set->hid.hidSubDescriptors[0].bDescriptorType = DESC_TYPE_REPORT; //下级描述符为报告描述符
-
set->hid.hidSubDescriptors[0].wDescriptorLength = SWAP16(sizeof(MouseReportDescriptor)); //下级描述符的长度
-
}
-
-
//endpoint
-
{
-
set->endpoint[0].bLength = sizeof(endpoint_descritpor_t);//端点描述符的字节数大小
-
set->endpoint[0].bDescriptorType = DESC_TYPE_ENDPOINT; //端点描述符类型编号
-
set->endpoint[0].bEndpointAddress = MAIN_POINT_IN; //端点号,主输入端点
-
set->endpoint[0].bmAttributes = TRANSFER_INTERRUPT; //使用的传输类型:中断传输
-
set->endpoint[0].wMaxPacketSize = SWAP16(0x0040); //该端点支持的最大包尺寸,64字节
-
set->endpoint[0].bInterval = 0x0A; //中断扫描时间:设置为10ms
-
-
-
set->endpoint[1].bLength = sizeof(endpoint_descritpor_t);//端点描述符的字节数大小
-
set->endpoint[1].bDescriptorType = DESC_TYPE_ENDPOINT; //端点描述符类型编号
-
set->endpoint[1].bEndpointAddress = MAIN_POINT_OUT; //端点号,主输出端点
-
set->endpoint[1].bmAttributes = TRANSFER_INTERRUPT; //使用的传输类型:中断传输
-
set->endpoint[1].wMaxPacketSize = SWAP16(0x0040); //该端点支持的最大包尺寸,64字节
-
set->endpoint[1].bInterval = 0x0A; //中断扫描时间:设置为10ms
-
}
-
}
6,运行结果
7,待解决问题:字符串描述符的实现
8,源码
mouse.zip
欲知详情,请看下回分解
阅读(1555) | 评论(0) | 转发(0) |