04 STM32F103 USB固件开发-移植JoyStickMouse-(3)(USB描述符详解)

STM32F103 USB固件开发-移植JoyStickMouse-(3)(USB描述符详解)


1.USB设备描述符简介

USB描述符结构如下(图片引用自USB中文网):

设备描述符:主要向主机说明设备类型、USB版本号、PID、VID等,是主机读取的第一个配置,一个设备能有有一个。
配置描述符:一个设备可以有一个或多个,描述设备的供电方式、最大功耗、接口数量。配置描述符在USB设备的枚举过程中,需要获取两次:第一次只获取配置描述符的基本长度9字节,获取后从wTotalLength字节中解析出配置描述符的总长度,然后再次获取全部的描述符。
接口描述符:具体功能的体现,接口的编号、接口的端点数量、接口所使用的类、子类、协议等。
**端点描述符:**端点号及方向、端点的传输类型(控制、同步、批量、中断等),最大包长度、查寻时间间隔等。
字符串描述符:不是必须的,采用unicode编码,主要是提供一些方便人们阅读的厂商或设备名称等文字信息。
HID描述符:HID描述符的主要作用是用来识别HID通信所使用的额外描述符。

2.常用描述符详解

USB 设备描述符
struct _DEVICE_DESCRIPTOR_STRUCT 
{ 
    BYTE bLength;           //设备描述符的字节数大小,为0x12 
    BYTE bDescriptorType;   //描述符类型编号,为0x01 
    WORD bcdUSB;            //USB版本号 
    BYTE bDeviceClass;      //USB分配的设备类代码,0x01~0xfe为标准设备类,0xff为厂商自定义类型 
                            //0x00不是在设备描述符中定义的,如HID 
    BYTE bDeviceSubClass;   //usb分配的子类代码,同上,值由USB规定和分配的 
    BYTE bDeviceProtocol;   //USB分配的设备协议代码,同上 
    BYTE bMaxPacketSize0;   //端点0的最大包的大小 
    WORD idVendor;          //厂商编号 
    WORD idProduct;         //产品编号 
    WORD bcdDevice;         //设备出厂编号 
    BYTE iManufacturer;     //描述厂商字符串的索引 
    BYTE iProduct;          //描述产品字符串的索引 
    BYTE iSerialNumber;     //描述设备序列号字符串的索引 
    BYTE bNumConfiguration; //可能的配置数量 
}


配置描述符
struct _CONFIGURATION_DESCRIPTOR_STRUCT 
{ 
  BYTE bLength;           //配置描述符的字节数大小,固定为9字节
  BYTE bDescriptorType;   //描述符类型编号,为0x02 
  WORD wTotalLength;     //配置所返回的所有数量的大小 
  BYTE bNumInterface;     //此配置所支持的接口数量 
  BYTE bConfigurationVale;   //Set_Configuration命令需要的参数值 
  BYTE iConfiguration;       //描述该配置的字符串的索引值 
  BYTE bmAttribute;           //供电模式的选择 
  BYTE MaxPower;             //设备从总线提取的最大电流 
}CONFIGURATION_DESCRIPTOR_STRUCT


接口描述符
struct _INTERFACE_DESCRIPTOR_STRUCT 
{ 
    BYTE bLength;           //设备描述符的字节数大小,为0x09 
    BYTE bDescriptorType;   //描述符类型编号,为0x04
    BYTE bInterfaceNumber; //接口的编号 
    BYTE bAlternateSetting;//备用的接口描述符编号 
    BYTE bNumEndpoints;     //该接口使用端点数,不包括端点0 
    BYTE bInterfaceClass;   //接口类型 
    BYTE bInterfaceSubClass;//接口子类型 
    BYTE bInterfaceProtocol;//接口所遵循的协议 
    BYTE iInterface;         //描述该接口的字符串索引值 
}INTERFACE_DESCRIPTOR_STRUCT


端点描述符
struct _ENDPOIN_DESCRIPTOR_STRUCT 
{ 
    BYTE bLength;           //设备描述符的字节数大小,为0x7 
    BYTE bDescriptorType;   //描述符类型编号,为0x05
    BYTE bEndpointAddress; //端点地址及输入输出属性 
    BYTE bmAttribute;       //端点的传输类型属性 
    WORD wMaxPacketSize;   //端点收、发的最大包的大小 
    BYTE bInterval;         //主机查询端点的时间间隔 
} ENDPOIN_DESCRIPTOR_STRUCT



字符串描述符
typedef struct _USB_STRING_DESCRIPTOR {
    UCHAR   bLength;
    UCHAR   bDescriptorType;
    WCHAR   bString[1];
} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;

HID描述符(图片来自USB中文网)
在这里插入图片描述

3.JoyStickMouse 例程各段描述符解析

/* USB Standard Device Descriptor 设备描述符
 */
const uint8_t Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{
    0x12,                       //bLength:设备描述符的字节数大小,为0x12
    USB_DEVICE_DESCRIPTOR_TYPE, //bDescriptorType:描述符类型编号,为0x01表示设备描述符
    0x00,                       //bcdUSB:USB版本号,二个字节表示,USB 2.0 设备拥有 0x0200 值, USB 1.1 设备拥有0x0110 值
    0x02,
    0x00,                       //bDeviceClass:USB所属设备类 [USB设备类型定义](https://www.usbzh.com/article/detail-221.html)
    0x00,                       //bDeviceSubClass:USB设备所属设备子类
    0x00,                       //bDeviceProtocol:USB设备所用的设备类协议
    0x40,                       //bMaxPacketSize:端点0的最大包的大小
    0x83,                       //idVendor (0x0483):厂商编号
    0x04,
    0x10,                       //idProduct = 0x5710:产品编号
    0x57,
    0x00,                       //bcdDevice rel. 2.00:设备出厂编号
    0x02,
    1,                          //iManufacturer:描述厂商字符串的索引 
    2,                          //iProduct:描述产品字符串的索引 
    3,                          //iSerialNumber:描述设备序列号字符串的索引
    0x01                        //bNumConfigurations:可能的配置数量
  };
/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
  {
  	// Configuration
    0x09, 		   //bLength: 配置描述符的字节数大小,固定为9字节
    USB_CONFIGURATION_DESCRIPTOR_TYPE, //bDescriptorType: 描述符类型编号,为0x02表示配置描述符
    JOYSTICK_SIZ_CONFIG_DESC,		   //wTotalLength 2个字节: 配置所返回的所有数量的大小
    0x00,
    0x01,         //bNumInterfaces: 此配置所支持的接口数量 
    0x01,         //bConfigurationValue: Set_Configuration命令需要的参数值
    0x00,         //iConfiguration: 描述该配置的字符串的索引值 
    0xE0,         //bmAttributes: 供电模式的选择 
    0x32,         //MaxPower 100 mA: 设备从总线提取的最大电流
	
	// Interface
    /************** Descriptor of Joystick Mouse interface ****************/
    /* 09 */
    0x09,         //bLength: 设备描述符的字节数大小,为0x09 
    USB_INTERFACE_DESCRIPTOR_TYPE,//bDescriptorType: 描述符类型编号,为0x04表示接口描述符类型
    0x00,         //bInterfaceNumber: 接口的编号
    0x00,         //bAlternateSetting: 备用的接口描述符编号
    0x01,         //bNumEndpoints:该接口使用端点数,不包括端点0 
    0x03,         //bInterfaceClass: 接口类型,参考[Windows定义的USB设备类型bInterfaceClass](https://www.usbzh.com/article/detail-864.html)
    0x01,         //bInterfaceSubClass : 接口子类型,对于HID接口,bInterfaceSubClass仅用于设备是否支持启动接口
    0x02,         //nInterfaceProtocol : 接口所遵循的协议,对于HID接口:0=none, 1=keyboard, 2=mouse*/
    0,            //iInterface: 描述该接口的字符串索引值

	// HID描述符
    /******************** Descriptor of Joystick Mouse HID ********************/
    /* 18 */
    0x09,         //bLength: 描述符字节数
    HID_DESCRIPTOR_TYPE, //bDescriptorType: 0x21 = HID描述符
    0x00,         //bcdHID 2个字节: HID规范版本号(BCD)
    0x01,
    0x00,         //bCountryCode: 硬件设备所在国家的国家代码
    0x01,         //bNumDescriptors: 类别描述符数目(至少有一个报表描述符)
    0x22,         //bDescriptorType:该类别描述符的类型
    JOYSTICK_SIZ_REPORT_DESC,//wItemLength 2个字节: 该类别描述符的总长度
    0x00,
    /******************** Descriptor of Joystick Mouse endpoint ********************/
    /* 27 */
    0x07,          //bLength:设备描述符的字节数大小,为0x7 
    USB_ENDPOINT_DESCRIPTOR_TYPE, //bDescriptorType:描述符类型编号,0x05表示端点描述符类型

    0x81,          //bEndpointAddress: 端点地址及输入输出属性
    0x03,          //bmAttributes: 端点的传输类型属性,0x3表示中断类型
    0x04,          //wMaxPacketSize 2个字节: 端点收、发的最大包的大小
    0x00,
    0x20,          //bInterval: 主机查询端点的时间间隔
    /* 34 */
  }
  ; /* MOUSE_ConfigDescriptor */

4.JoyStickMouse HID报告描述符分析

const uint8_t Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] ={
    0x05,0x01,          /* Usage Page(Generic Desktop) */
    0x09,0x02,          /* Usage(Mouse) */
    0xA1,0x01,          /* Collection(Application) */
 
	0x09,0x01,          /* Usage(Pointer) */
    0xA1,0x00,          /* Collection(Physical) 8 */
    0x05,0x09,          /* Usage Page(Buttons) */
    0x19,0x01,          /* Usage Minimum(1)	*/
    0x29,0x03,          /* Usage Maximum(3) */
    0x15,0x00,          /* Logical Minimum(0) 16 */
    0x25,0x01,          /* Logical Maximum(1) */
    0x95,0x03,          /* Report Count(3) */
    0x75,0x01,          /* Report Size(1) */
    0x81,0x02,          /* Input(Variable) 24 */
    0x95,0x01,          /* Report Count(1) */
    0x75,0x05,          /* Report Size(5) */
    0x81,0x01,          /* Input(Constant,Array) */
    0x05,0x01,          /* Usage Page(Generic Desktop)	32 */
    0x09,0x30,          /* Usage(X axis) */
    0x09,0x31,          /* Usage(Y axis) */
    0x09,0x38,          /* Usage(Wheel) */
    0x15,0x81,          /* Logical Minimum(-127) 40 */
    0x25,0x7F,          /* Logical Maximum(127) */
    0x75,0x08,          /* Report Size(8) */    
    0x95,0x03,          /* Report Count(3) */
    0x81,0x06,          /* Input(Variable, Relative) 48 */
    0xC0,          		/* END_COLLECTION */

    0x09,0x3c,			/* USAGE (Motion Wakeup) */
    0x05,0xff,			/* USAGE_PAGE(Reserved or Other) */
	0x09,0x01,			/* Usage(Pointer) */		    
    0x15,0x00,			/* Logical Minimum(0) */
    0x25,0x01,			/* Logical Maximum(1) */
    0x75,0x01,			/* Report Size(1) */
    0x95,0x02,			/* Report Count(2) */    
    0xb1,0x22,			/* FEATURE (Data,Var,Abs,NPrf) */
    0x75,0x06,			/* Report Size(6) */ 
    0x95,0x01,			/* Report Count(1) */   
    0xb1,0x01,			/* FEATURE (Cnst,Ary,Abs) */
    
    0xc0,				/* END_COLLECTION 74 */
}; /* Joystick_ReportDescriptor */

Collection:表示集合,有四种类型Collection Physical(实体,CP)、Collection Application(应用,CA)、Collection Logical(逻辑,CL)、Vendor Defined(自定义,VD)。
这里只所以使用CA和CP是USB HID规范规定的,在HID Usage Tables1.22的30页有规定,如下:
在这里插入图片描述

关于这个HID的数据结构,我的解析如下(如果有错误欢迎指出,我是才开始学习HSB HID协议):
在这里插入图片描述
解析如下:

  1. 报告描述符有三段,第一段Buttos,1个BYTE表示,BIT0-BIT2分别表示三个按键,BI3-BI5表示填充位,报告的类型是INPUT。第2段用3字节表示(不包括REPORT ID)。第一个BYTE表示X轴移植,第2个BYTE表示Y轴偏移,第3个BYTE表示中间的滚轮的偏移,报告的类型是INPUT。第3段表示鼠标移动后的唤醒功能,只使用了BIT0-BIT1,BIT2-BIT7是填充位,报告类型是FEATURE.
  2. 如何查看是填充字段?INUPT/OUTPUT/FEATURE的第一人字段是Constant则表示是一个常量,不可变,用作填充。
  3. HID 报告中是以多少位的?我看了许多报告,目前都是以8BIT对齐,也就是一个BYTE。
  4. 代码中发送的报告是第二个报告,也就是X轴、Y轴偏移,ID默认为0,不带滚轮,所以BIT3默认是0。代码如下:
    在这里插入图片描述

4.备注

现在的代码里面只使用的第二段的HID报告,向主机报告了鼠标的位移。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值