USB学习笔记(3)HID应用分析

USB学习笔记(3)HID应用分析

本文根据前面对USB系统的了解,和USB协议的学习,列出鼠标,键盘,多媒体控制器,自定义HID设备等HID设备的各种描述符。

前景提要:每个设备有且仅有一个设备描述符,至少要有一个配置描述符,在设备描述符中规定了该设备有多少中配置;配置描述符集合信息包括:配置描述符>接口描述符>HID描述符(如果是HID类)>端点描述符,

1. Mouse(鼠标)

① 描述符

一个设备描述符,一个配置描述符,一个接口描述符,一个hid描述符,一个端点描述符,一个语言ID描述符,N个字符串描述符,一个报告描述符

//设备描述符
const u8 DeviceDescriptor[18] =
{
    0x12,   /*bLength *///该描述符长度
    0x01,   /*bDescriptorType*///描述符类型:0x01表示设备描述符
    0x00,   /*bcdUSB *///USB协议版本 2.0
    0x02,
    0x00,   /*bDeviceClass*///设备所使用的类代码,一般为0
    0x00,   /*bDeviceSubClass*///设备所使用的子类代码,类代码为0,子类代码也为0
    0x00,   /*bDeviceProtocol*///设备所使用的协议
    0x40,   /*bMaxPacketSize*///端点0最大包长,0x40,64个字节
    0x83,   /*idVendor (0x0483)*///VID 厂商ID,自定义
    0x04,
    0x50,   /*idProduct = 0x5750*///PID 产品ID,自定义
    0x57,
    0x00,   /*bcdDevice rel. 2.00*///产品版本号,自定义
    0x02,
    1,      /*Index of string descriptor describing manufacturer *///厂商字符串描述符索引值,如果没有则为0                                             
    2,      /*Index of string descriptor describing product *///产品字符串描述符索引值	                                             
    3,      /*Index of string descriptor describing the device serial number *///设备序列号字符串索引值
                                             
    0x01,   /*bNumConfigurations*///表示支持多少种配置
}

//配置描述符集合
const u8 ConfigDescriptor[9+9+9+7] =
{
	//配置描述符
    0x09,   /* bLength: Configuation Descriptor size *///描述符长度,9字节
    0x02,   /* bDescriptorType: Configuration *///描述符类型:配置描述符为0x02
    0x22,   /* wTotalLength: Bytes returned *///配置描述符集合总长度     
    0x00,
    0x01,   /* bNumInterfaces: 1 interface *///表示该配置所支持的接口数量
    0x01,   /* bConfigurationValue: Configuration value *///表示该配置集合的配置值,在设置配置请求中,主机会发送对应的配置值,表示设置了该配置
    0,      /* iConfiguration: Index of string descriptor describing the configuration*///配置字符串索引                                  
    0xC0,   /* bmAttributes: Bus powered *//*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits *///描述设备特性    
    0x32,   /* MaxPower 100 mA: this current is used for detecting Vbus *///设备需要的最大电流

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x01,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x01,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x02,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x82,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点2输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间
}; 

//语言ID描述符
const u8 StringLangID[4] =
{
    0x04,   /* bLength: LanguageID Descriptor size */
    0x03,   /* bDescriptorType: LanguageID */
    0x09,   /* 0x0409 表示美式英语 */
    0x04
}

//N个字符串描述符


//报告描述符
const u8 ReportDescriptor[CUSTOMHID_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) *///主条目:开集合:物理型

	0x05, 0x09,     /* USAGE_PAGE (Button) *///全局:用途页:按键
	0x19, 0x01,     /* USAGE_MIN (Button1) *///局部:用途最小值:鼠标左键
	0x29, 0x03,	    /* USAGE_MAX (Button3) *///局部:用途最大值:鼠标右键		
	0x15, 0x00,     /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,     /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x03,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,     /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,     /* INPUT(Data,Var,Abs) *///主条目:说明有三个长度为1的数据域

	0x95, 0x01,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x05,     /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,     /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为5的数据固定数据域,为了和前面的3位补齐为一个字节
	
	0x05, 0x01,     /* USAGE_PAGE(Generic Desktop) *///全局:用途页:桌面应用
	0x09, 0x30,     /* USAGE(X) *///局部:用途:X轴
	0x09, 0x31,     /* USAGE(Y) *///局部:用途:Y轴
	0x09, 0x38,     /* USAGE(Wheel) *///局部:用途:滚轮		
	0x15, 0x81,     /* LOGICAL_MIN (-127) *///全局:返回逻辑最小值:-127
	0x25, 0x7f,     /* LOGICAL_MAX (127) *///全局:返回逻辑最大值:127
	
	0x95, 0x03,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,     /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x06,     /* INPUT(Data,Var,Rel) *///主条目:说明有三个长度为8的数据域

	0xc0,           /* END_COLLECTION *///主条目:关集合
    0xc0            /* END_COLLECTION *///主条目:关集合
};

② 报告的输入

总共返回四个字节的数据:buf[4]

buf[0]:【D0:左键是否按下】【D1:中键是否按下】【D2:右键是否按下】

buf[1]: X轴移动的位置,负值表示左移,正值表示右移

buf[2]: Y轴移动的位置,负值表示上移,正值表示下移

buf[3]: 滚轮滑动的位置,负值表示下滚,正值表示上滚

2. Keyboard(键盘)

① 描述符

一个设备描述符,一个配置描述符,一个接口描述符,一个hid描述符,两个端点描述符,一个语言ID描述符,N个字符串描述符,一个报告描述符

//设备描述符
const u8 DeviceDescriptor[18] =
{
    0x12,   /*bLength *///该描述符长度
    0x01,   /*bDescriptorType*///描述符类型:0x01表示设备描述符
    0x00,   /*bcdUSB *///USB协议版本 2.0
    0x02,
    0x00,   /*bDeviceClass*///设备所使用的类代码,一般为0
    0x00,   /*bDeviceSubClass*///设备所使用的子类代码,类代码为0,子类代码也为0
    0x00,   /*bDeviceProtocol*///设备所使用的协议
    0x40,   /*bMaxPacketSize*///端点0最大包长,0x40,64个字节
    0x83,   /*idVendor (0x0483)*///VID 厂商ID,自定义
    0x04,
    0x50,   /*idProduct = 0x5750*///PID 产品ID,自定义
    0x57,
    0x00,   /*bcdDevice rel. 2.00*///产品版本号,自定义
    0x02,
    1,      /*Index of string descriptor describing manufacturer *///厂商字符串描述符索引值,如果没有则为0                                             
    2,      /*Index of string descriptor describing product *///产品字符串描述符索引值	                                             
    3,      /*Index of string descriptor describing the device serial number *///设备序列号字符串索引值
                                             
    0x01,   /*bNumConfigurations*///表示支持多少种配置
}

//配置描述符集合
const u8 ConfigDescriptor[9+9+9+7+7] =
{
	//配置描述符
    0x09,   /* bLength: Configuation Descriptor size *///描述符长度,9字节
    0x02,   /* bDescriptorType: Configuration *///描述符类型:配置描述符为0x02
    0x29,   /* wTotalLength: Bytes returned *///配置描述符集合总长度     
    0x00,
    0x01,   /* bNumInterfaces: 1 interface *///表示该配置所支持的接口数量
    0x01,   /* bConfigurationValue: Configuration value *///表示该配置集合的配置值,在设置配置请求中,主机会发送对应的配置值,表示设置了该配置
    0,      /* iConfiguration: Index of string descriptor describing the configuration*///配置字符串索引                                  
    0xC0,   /* bmAttributes: Bus powered *//*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits *///描述设备特性    
    0x32,   /* MaxPower 100 mA: this current is used for detecting Vbus *///设备需要的最大电流

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x02,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x01,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x01,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符

	//第一个端点输入
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x82,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点2输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间

	//第二个端点输出
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x01,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点1输出
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间
}; 

//语言ID描述符
const u8 StringLangID[4] =
{
    0x04,   /* bLength: LanguageID Descriptor size */
    0x03,   /* bDescriptorType: LanguageID */
    0x09,   /* 0x0409 表示美式英语 */
    0x04
}

//N个字符串描述符


//报告描述符
const u8 ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
{
    0x05, 0x01,         /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面应用
    0x09, 0x06,         /* USAGE (Keyboard) *///局部:用途:键盘
    0xa1, 0x01,         /* COLLECTION (Application) *///主条目:开集合:应用型

	//输入报告
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0xe0,         /* USAGE_MIN (Keyboard LeftControl) *///局部:用途最小值:键盘左ctrl键
	0x29, 0xe7,         /* USAGE_MAX (Keyboard Right GUI) *///局部:用途最大值:键盘右WIN键		
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x08,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,         /* INPUT(Data,Var,Abs) *///主条目:说明有八个长度为1的数据域//总共8个特殊按键

	0x95, 0x01,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,	        /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,         /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为8的数据固定数据域,保留
	
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0x00,         /* USAGE_MIN (Reserved) *///局部:用途最小值:0表示没有按键按下
	0x29, 0x65,         /* USAGE_MAX (其他按键的键值) *///局部:用途最大值:0x65		
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x26, 0x00,	0xFF,   /* LOGICAL_MAX *///全局:返回逻辑最大值:255
	0x95, 0x06,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,	        /* REPORT_SIZE *///全局:一个数据域的位长度
	0x81, 0x00,         /* INPUT(Data,Ary,Abs) *///主条目:说明有6个长度为8的数据域(数组)//总共显示6个按键按下


	//输出报告
	0x05, 0x08,         /* USAGE_PAGE (LED) *///全局:用途页:指示灯
	0x19, 0x01,         /* USAGE_MIN (Num Lock) *///局部:用途最小值:数字键盘灯
	0x29, 0x05,         /* USAGE_MAX (Kana) *///局部:用途最大值:Kana灯
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x05,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x91, 0x02,         /* OUTPUT(Data,Var,Abs) *///主条目

	0x95, 0x03,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x91, 0x03,         /* OUTPUT(Cnst,Var,Abs) *///主条目

    0xc0                /* END_COLLECTION *///主条目:关集合
};

② 报告的输入

总共输入8个字节的数据:buf[8]

buf[0]: 8个特殊按键是否被按下,【D0~7】分别是左Ctrl,左Shift,左Alt,左WIN,右Ctrl,右Shift,右Alt,右WIN

buf[1]: 0x00,常数

buf[2:7]: 分别表示被按下的按键键值

③ 报告输出

总共输出1个字节的数据:buf

buf:【D0~4】5个led的显示,0关1开

3. 带鼠标功能的USB键盘(方法一)

① 描述符

只使用一个接口,但是使用两个应用集合和两个报告

//设备描述符
const u8 DeviceDescriptor[18] =
{
    0x12,   /*bLength *///该描述符长度
    0x01,   /*bDescriptorType*///描述符类型:0x01表示设备描述符
    0x00,   /*bcdUSB *///USB协议版本 2.0
    0x02,
    0x00,   /*bDeviceClass*///设备所使用的类代码,一般为0
    0x00,   /*bDeviceSubClass*///设备所使用的子类代码,类代码为0,子类代码也为0
    0x00,   /*bDeviceProtocol*///设备所使用的协议
    0x40,   /*bMaxPacketSize*///端点0最大包长,0x40,64个字节
    0x83,   /*idVendor (0x0483)*///VID 厂商ID,自定义
    0x04,
    0x50,   /*idProduct = 0x5750*///PID 产品ID,自定义
    0x57,
    0x00,   /*bcdDevice rel. 2.00*///产品版本号,自定义
    0x02,
    1,      /*Index of string descriptor describing manufacturer *///厂商字符串描述符索引值,如果没有则为0                                             
    2,      /*Index of string descriptor describing product *///产品字符串描述符索引值	                                             
    3,      /*Index of string descriptor describing the device serial number *///设备序列号字符串索引值
                                             
    0x01,   /*bNumConfigurations*///表示支持多少种配置
}

//配置描述符集合
const u8 ConfigDescriptor[9+9+9+7+7] =
{
	//配置描述符
    0x09,   /* bLength: Configuation Descriptor size *///描述符长度,9字节
    0x02,   /* bDescriptorType: Configuration *///描述符类型:配置描述符为0x02
    41,	    /* wTotalLength: Bytes returned *///配置描述符集合总长度     
    0x00,
    0x01,   /* bNumInterfaces: 1 interface *///表示该配置所支持的接口数量
    0x01,   /* bConfigurationValue: Configuration value *///表示该配置集合的配置值,在设置配置请求中,主机会发送对应的配置值,表示设置了该配置
    0,      /* iConfiguration: Index of string descriptor describing the configuration*///配置字符串索引                                  
    0xC0,   /* bmAttributes: Bus powered *//*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits *///描述设备特性    
    0x32,   /* MaxPower 100 mA: this current is used for detecting Vbus *///设备需要的最大电流

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x02,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x01,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x02,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符
	//第一个端点输入
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x82,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点2输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间

	//第二个端点输出
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x01,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点1输出
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间
}; 

//语言ID描述符
const u8 StringLangID[4] =
{
    0x04,   /* bLength: LanguageID Descriptor size */
    0x03,   /* bDescriptorType: LanguageID */
    0x09,   /* 0x0409 表示美式英语 */
    0x04
}

//N个字符串描述符


//报告描述符
const u8 ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
{
	//USB鼠标部分
    0x05, 0x01,     /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面应用
    0x09, 0x02,     /* USAGE (Mouse) *///局部:用途:鼠标
    0xa1, 0x01,     /* COLLECTION (Application) *///主条目:开集合:应用型
	
	0x85, 0x01,     /* Report ID(1) *///全局,报告ID

	0x09, 0x01,     /* USAGE (Pointer) *///局部:用途:指针
	0xa1, 0x00,     /* COLLECTION (Physical) *///主条目:开集合:物理型

	0x05, 0x09,     /* USAGE_PAGE (Button) *///全局:用途页:按键
	0x19, 0x01,     /* USAGE_MIN (Button1) *///局部:用途最小值:鼠标左键
	0x29, 0x03,	    /* USAGE_MAX (Button3) *///局部:用途最大值:鼠标右键		
	0x15, 0x00,	    /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,	    /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x03,	    /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,     /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,     /* INPUT(Data,Var,Abs) *///主条目:说明有三个长度为1的数据域

	0x95, 0x01,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x05,     /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,     /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为5的数据固定数据域,为了和前面的3位补齐为一个字节
	
	0x05, 0x01,     /* USAGE_PAGE(Generic Desktop) *///全局:用途页:桌面应用
	0x09, 0x30,     /* USAGE(X) *///局部:用途:X轴
	0x09, 0x31,     /* USAGE(Y) *///局部:用途:Y轴
	0x09, 0x38,     /* USAGE(Wheel) *///局部:用途:滚轮		
	0x15, 0x81,     /* LOGICAL_MIN (-127) *///全局:返回逻辑最小值:-127
	0x25, 0x7f,     /* LOGICAL_MAX (127) *///全局:返回逻辑最大值:127
	
	0x95, 0x03,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,	    /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x06,     /* INPUT(Data,Var,Rel) *///主条目:说明有三个长度为8的数据域

	0xc0,           /* END_COLLECTION *///主条目:关集合
    0xc0            /* END_COLLECTION *///主条目:关集合


	//键盘部分
    0x05, 0x01,         /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面应用
    0x09, 0x06,         /* USAGE (Keyboard) *///局部:用途:键盘
    0xa1, 0x01,         /* COLLECTION (Application) *///主条目:开集合:应用型

	0x85, 0x02,	        /* Report ID(2) *///全局,报告ID

	//输入报告
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0xe0,         /* USAGE_MIN (Keyboard LeftControl) *///局部:用途最小值:键盘左ctrl键
	0x29, 0xe7,	        /* USAGE_MAX (Keyboard Right GUI) *///局部:用途最大值:键盘右WIN键		
	0x15, 0x00,	        /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,	        /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x08,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,	        /* INPUT(Data,Var,Abs) *///主条目:说明有八个长度为1的数据域//总共8个特殊按键

	0x95, 0x01,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,	        /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,         /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为8的数据固定数据域,保留
	
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0x00,         /* USAGE_MIN (Reserved) *///局部:用途最小值:0表示没有按键按下
	0x29, 0x65,         /* USAGE_MAX (其他按键的键值) *///局部:用途最大值:0x65		
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x26, 0x00,	0xFF,   /* LOGICAL_MAX *///全局:返回逻辑最大值:255
	0x95, 0x06,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,         /* REPORT_SIZE *///全局:一个数据域的位长度
	0x81, 0x00,	        /* INPUT(Data,Ary,Abs) *///主条目:说明有6个长度为8的数据域(数组)//总共显示6个按键按下


	//输出报告
	0x05, 0x08,         /* USAGE_PAGE (LED) *///全局:用途页:指示灯
	0x19, 0x01,         /* USAGE_MIN (Num Lock) *///局部:用途最小值:数字键盘灯
	0x29, 0x05,         /* USAGE_MAX (Kana) *///局部:用途最大值:Kana灯
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x05,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x91, 0x02,         /* OUTPUT(Data,Var,Abs) *///主条目

	0x95, 0x03,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x91, 0x03,         /* OUTPUT(Cnst,Var,Abs) *///主条目

    0xc0                /* END_COLLECTION *///主条目:关集合
};

4. 带鼠标功能的USB键盘(方法二)

使用两个接口,一个接口实现键盘功能,一个接口实现鼠标功能

//设备描述符
const u8 DeviceDescriptor[18] =
{
    0x12,   /*bLength *///该描述符长度
    0x01,   /*bDescriptorType*///描述符类型:0x01表示设备描述符
    0x00,   /*bcdUSB *///USB协议版本 2.0
    0x02,
    0x00,   /*bDeviceClass*///设备所使用的类代码,一般为0
    0x00,   /*bDeviceSubClass*///设备所使用的子类代码,类代码为0,子类代码也为0
    0x00,   /*bDeviceProtocol*///设备所使用的协议
    0x40,   /*bMaxPacketSize*///端点0最大包长,0x40,64个字节
    0x83,   /*idVendor (0x0483)*///VID 厂商ID,自定义
    0x04,
    0x50,   /*idProduct = 0x5750*///PID 产品ID,自定义
    0x57,
    0x00,   /*bcdDevice rel. 2.00*///产品版本号,自定义
    0x02,
    1,      /*Index of string descriptor describing manufacturer *///厂商字符串描述符索引值,如果没有则为0                                             
    2,      /*Index of string descriptor describing product *///产品字符串描述符索引值	                                             
    3,      /*Index of string descriptor describing the device serial number *///设备序列号字符串索引值
                                             
    0x01,   /*bNumConfigurations*///表示支持多少种配置
}

//配置描述符集合
const u8 ConfigDescriptor[9+9+9+7+9+9+7+7] =
{
	//配置描述符
    0x09,   /* bLength: Configuation Descriptor size *///描述符长度,9字节
    0x02,   /* bDescriptorType: Configuration *///描述符类型:配置描述符为0x02
    0x22,   /* wTotalLength: Bytes returned *///配置描述符集合总长度     
    0x00,
    0x02,   /* bNumInterfaces: 1 interface *///表示该配置所支持的接口数量
    0x01,   /* bConfigurationValue: Configuration value *///表示该配置集合的配置值,在设置配置请求中,主机会发送对应的配置值,表示设置了该配置
    0,      /* iConfiguration: Index of string descriptor describing the configuration*///配置字符串索引                                  
    0xC0,   /* bmAttributes: Bus powered *//*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits *///描述设备特性    
    0x32,   /* MaxPower 100 mA: this current is used for detecting Vbus *///设备需要的最大电流

	//鼠标部分第一个接口

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x01,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x01,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x02,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    MOUSE_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x83,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点3输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间

	//键盘部分第二个接口

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x02,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x01,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x01,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    KEYBOARD_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符
	//第一个端点输入
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x82,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点2输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间

	//第二个端点输出
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x01,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点1输出
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间
}; 

//语言ID描述符
const u8 StringLangID[4] =
{
    0x04,   /* bLength: LanguageID Descriptor size */
    0x03,   /* bDescriptorType: LanguageID */
    0x09,   /* 0x0409 表示美式英语 */
    0x04
}

//N个字符串描述符


//报告描述符--鼠标部分
const u8 MouseReportDescriptor[MOUSE_SIZ_REPORT_DESC] =
{
	//USB鼠标部分
    0x05, 0x01,     /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面应用
    0x09, 0x02,     /* USAGE (Mouse) *///局部:用途:鼠标
    0xa1, 0x01,     /* COLLECTION (Application) *///主条目:开集合:应用型
	
	0x85, 0x01,     /* Report ID(1) *///全局,报告ID

	0x09, 0x01,     /* USAGE (Pointer) *///局部:用途:指针
	0xa1, 0x00,     /* COLLECTION (Physical) *///主条目:开集合:物理型

	0x05, 0x09,     /* USAGE_PAGE (Button) *///全局:用途页:按键
	0x19, 0x01,     /* USAGE_MIN (Button1) *///局部:用途最小值:鼠标左键
	0x29, 0x03,     /* USAGE_MAX (Button3) *///局部:用途最大值:鼠标右键		
	0x15, 0x00,	    /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,     /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x03,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,     /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,     /* INPUT(Data,Var,Abs) *///主条目:说明有三个长度为1的数据域

	0x95, 0x01,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x05,     /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,     /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为5的数据固定数据域,为了和前面的3位补齐为一个字节
	
	0x05, 0x01,     /* USAGE_PAGE(Generic Desktop) *///全局:用途页:桌面应用
	0x09, 0x30,     /* USAGE(X) *///局部:用途:X轴
	0x09, 0x31,     /* USAGE(Y) *///局部:用途:Y轴
	0x09, 0x38,     /* USAGE(Wheel) *///局部:用途:滚轮		
	0x15, 0x81,     /* LOGICAL_MIN (-127) *///全局:返回逻辑最小值:-127
	0x25, 0x7f,     /* LOGICAL_MAX (127) *///全局:返回逻辑最大值:127
	
	0x95, 0x03,     /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,     /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x06,     /* INPUT(Data,Var,Rel) *///主条目:说明有三个长度为8的数据域

	0xc0,           /* END_COLLECTION *///主条目:关集合
    0xc0            /* END_COLLECTION *///主条目:关集合
};

//报告描述符--键盘部分
const u8 KeyboardReportDescriptor[KEYBOARD_SIZ_REPORT_DESC] =
{
	//键盘部分
    0x05, 0x01,         /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面应用
    0x09, 0x06,         /* USAGE (Keyboard) *///局部:用途:键盘
    0xa1, 0x01,         /* COLLECTION (Application) *///主条目:开集合:应用型

	0x85, 0x02,         /* Report ID(2) *///全局,报告ID

	//输入报告
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0xe0,         /* USAGE_MIN (Keyboard LeftControl) *///局部:用途最小值:键盘左ctrl键
	0x29, 0xe7,         /* USAGE_MAX (Keyboard Right GUI) *///局部:用途最大值:键盘右WIN键		
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x08,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,         /* INPUT(Data,Var,Abs) *///主条目:说明有八个长度为1的数据域//总共8个特殊按键

	0x95, 0x01,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,         /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,     	/* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为8的数据固定数据域,保留
	
	0x05, 0x07,     	/* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0x00,     	/* USAGE_MIN (Reserved) *///局部:用途最小值:0表示没有按键按下
	0x29, 0x65,     	/* USAGE_MAX (其他按键的键值) *///局部:用途最大值:0x65		
	0x15, 0x00,     	/* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x26, 0x00,	0xFF,   /* LOGICAL_MAX *///全局:返回逻辑最大值:255
	0x95, 0x06,     	/* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,     	/* REPORT_SIZE *///全局:一个数据域的位长度
	0x81, 0x00,     	/* INPUT(Data,Ary,Abs) *///主条目:说明有6个长度为8的数据域(数组)//总共显示6个按键按下


	//输出报告
	0x05, 0x08,     	/* USAGE_PAGE (LED) *///全局:用途页:指示灯
	0x19, 0x01,     	/* USAGE_MIN (Num Lock) *///局部:用途最小值:数字键盘灯
	0x29, 0x05,     	/* USAGE_MAX (Kana) *///局部:用途最大值:Kana灯
	0x15, 0x00,     	/* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,     	/* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x05,     	/* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,     	/* REPORT_SIZE *///全局:一个数据域的位长度	
	0x91, 0x02,     	/* OUTPUT(Data,Var,Abs) *///主条目

	0x95, 0x03,     	/* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,     	/* REPORT_SIZE *///全局:一个数据域的位长度		
	0x91, 0x03,     	/* OUTPUT(Cnst,Var,Abs) *///主条目

    0xc0     	     	/* END_COLLECTION *///主条目:关集合
};

5. 多媒体控制器

① 描述符

//设备描述符
const u8 DeviceDescriptor[18] =
{
    0x12,   /*bLength *///该描述符长度
    0x01,   /*bDescriptorType*///描述符类型:0x01表示设备描述符
    0x00,   /*bcdUSB *///USB协议版本 2.0
    0x02,
    0x00,   /*bDeviceClass*///设备所使用的类代码,一般为0
    0x00,   /*bDeviceSubClass*///设备所使用的子类代码,类代码为0,子类代码也为0
    0x00,   /*bDeviceProtocol*///设备所使用的协议
    0x40,   /*bMaxPacketSize*///端点0最大包长,0x40,64个字节
    0x83,   /*idVendor (0x0483)*///VID 厂商ID,自定义
    0x04,
    0x50,   /*idProduct = 0x5750*///PID 产品ID,自定义
    0x57,
    0x00,   /*bcdDevice rel. 2.00*///产品版本号,自定义
    0x02,
    1,      /*Index of string descriptor describing manufacturer *///厂商字符串描述符索引值,如果没有则为0                                             
    2,      /*Index of string descriptor describing product *///产品字符串描述符索引值	                                             
    3,      /*Index of string descriptor describing the device serial number *///设备序列号字符串索引值
                                             
    0x01,   /*bNumConfigurations*///表示支持多少种配置
}

//配置描述符集合
const u8 ConfigDescriptor[9+9+9+7] =
{
	//配置描述符
    0x09,   /* bLength: Configuation Descriptor size *///描述符长度,9字节
    0x02,   /* bDescriptorType: Configuration *///描述符类型:配置描述符为0x02
    0x22,   /* wTotalLength: Bytes returned *///配置描述符集合总长度     
    0x00,
    0x01,   /* bNumInterfaces: 1 interface *///表示该配置所支持的接口数量
    0x01,   /* bConfigurationValue: Configuration value *///表示该配置集合的配置值,在设置配置请求中,主机会发送对应的配置值,表示设置了该配置
    0,      /* iConfiguration: Index of string descriptor describing the configuration*///配置字符串索引                                  
    0xC0,   /* bmAttributes: Bus powered *//*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits *///描述设备特性    
    0x32,   /* MaxPower 100 mA: this current is used for detecting Vbus *///设备需要的最大电流

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x01,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x00,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x00,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x82,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点2输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间
}; 

//语言ID描述符
const u8 StringLangID[4] =
{
    0x04,   /* bLength: LanguageID Descriptor size */
    0x03,   /* bDescriptorType: LanguageID */
    0x09,   /* 0x0409 表示美式英语 */
    0x04
}

//N个字符串描述符


//报告描述符
const u8 ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
{
    0x05, 0x0c,         /* USAGE_PAGE (Consumer) *///全局:用途页:用户
    0x09, 0x01,         /* USAGE (Consumer Control) *///局部:用途:用户控制
    0xa1, 0x01,         /* COLLECTION (Application) *///主条目:开集合:应用型
	
	0x09, 0xea,         /* USAGE (Volume Decrement) *///局部:用途:音量减
	0x09, 0xe9,         /* USAGE (Volume Increment) *///局部:用途:音量加
	0x09, 0xe2,         /* USAGE (Mute) *///局部:用途:静音
	0x09, 0xcd,         /* USAGE (Play/Pause) *///局部:用途:播放暂停
	0x0a, 0x23, 0x02,   /* USAGE (AC Home) *///局部:用途:打开浏览器0x0223
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x05,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,         /* INPUT(Data,Var,Abs) *///主条目:说明有5个长度为1的数据域

	0x05, 0x01,         /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面
	0x09, 0x82,         /* USAGE(System Sleep)*///局部:用途:系统待机
	0x09, 0x81,         /* USAGE(System Power down)*///局部:用途:系统关机
	0x95, 0x02,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,         /* INPUT(Data,Var,Abs) *///主条目:说明有2个长度为1的数据域

	0x95, 0x01,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x03,         /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为1的常数

    0xc0                /* END_COLLECTION *///主条目:关集合
};

② 报告的输入

总共输入1个字节的数据:buf

buf:【D0~6】分别是音量减,音量加,静音,播放暂停,打开浏览器,系统待机,系统关机,【D7】填充位,无意义

6. 自定义HID设备

① 描述符

//设备描述符
const u8 DeviceDescriptor[18] =
{
    0x12,   /*bLength *///该描述符长度
    0x01,   /*bDescriptorType*///描述符类型:0x01表示设备描述符
    0x00,   /*bcdUSB *///USB协议版本 2.0
    0x02,
    0x00,   /*bDeviceClass*///设备所使用的类代码,一般为0
    0x00,   /*bDeviceSubClass*///设备所使用的子类代码,类代码为0,子类代码也为0
    0x00,   /*bDeviceProtocol*///设备所使用的协议
    0x40,   /*bMaxPacketSize*///端点0最大包长,0x40,64个字节
    0x83,   /*idVendor (0x0483)*///VID 厂商ID,自定义
    0x04,
    0x50,   /*idProduct = 0x5750*///PID 产品ID,自定义
    0x57,
    0x00,   /*bcdDevice rel. 2.00*///产品版本号,自定义
    0x02,
    1,      /*Index of string descriptor describing manufacturer *///厂商字符串描述符索引值,如果没有则为0                                             
    2,      /*Index of string descriptor describing product *///产品字符串描述符索引值	                                             
    3,      /*Index of string descriptor describing the device serial number *///设备序列号字符串索引值
                                             
    0x01,   /*bNumConfigurations*///表示支持多少种配置
}

//配置描述符集合
const u8 ConfigDescriptor[9+9+9+7+7] =
{
	//配置描述符
    0x09,   /* bLength: Configuation Descriptor size *///描述符长度,9字节
    0x02,   /* bDescriptorType: Configuration *///描述符类型:配置描述符为0x02
    0x29,   /* wTotalLength: Bytes returned *///配置描述符集合总长度     
    0x00,
    0x01,   /* bNumInterfaces: 1 interface *///表示该配置所支持的接口数量
    0x01,   /* bConfigurationValue: Configuration value *///表示该配置集合的配置值,在设置配置请求中,主机会发送对应的配置值,表示设置了该配置
    0,      /* iConfiguration: Index of string descriptor describing the configuration*///配置字符串索引                                  
    0xC0,   /* bmAttributes: Bus powered *//*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits *///描述设备特性    
    0x32,   /* MaxPower 100 mA: this current is used for detecting Vbus *///设备需要的最大电流

    //接口描述符
    0x09,   /* bLength: Interface Descriptor size *///描述符长度
    0x04,   /* bDescriptorType: Interface descriptor type *///描述符类型:0x03表示接口描述符
    0x00,   /* bInterfaceNumber: Number of Interface *///表示该接口的编号,从0开始递增
    0x00,   /* bAlternateSetting: Alternate setting *///表示该接口的备用接口编号,从0开始递增
    0x02,   /* bNumEndpoints *///该接口使用的非0端点的端点数
    0x03,   /* bInterfaceClass: HID *///该接口所使用的类
    0x00,   /* bInterfaceSubClass : 1=BOOT, 0=no boot *///该接口所使用的子类
    0x00,   /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse *///该接口所使用的协议
    0,      /* iInterface: Index of string descriptor *///接口描述符索引
    
	//HID描述符
    0x09,   /* bLength: HID Descriptor size *///描述符长度
    0x21,   /* bDescriptorType: HID *///描述符类型:0x21表示HID描述符
    0x10,   /* bcdHID: HID Class Spec release number *///HID协议版本号 1.1
    0x01,
    0x00,   /* bCountryCode: Hardware target country *///国家代码
    0x01,   /* bNumDescriptors: Number of HID class descriptors to follow *///下级描述符数量
    0x22,   /* bDescriptorType *///下级描述符类型:0x22表示报告描述符
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor *///报告描述符长度
    0x00,
    
	//端点描述符

	//第一个端点输入
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x82,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点2输入
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间

	//第二个端点输出
    0x07,   /* bLength: Endpoint Descriptor size *///该描述符长度
    0x05,   /* bDescriptorType: *///描述符类型:0x05表示端点描述符
    0x01,   /* bEndpointAddress: Endpoint Address (IN) *///该端点地址:方向+端点号,端点1输出
    // bit 3...0 : the endpoint number
    // bit 6...4 : reserved
    // bit 7     : 0(OUT), 1(IN)
    0x03,   /* bmAttributes: Interrupt endpoint *///该端点属性
    0x40,   /* wMaxPacketSize: 64 Bytes max *///该端点支持的最大包长度
    0x00,
    0x0A,   /* bInterval: Polling Interval (10 ms) *///端点查询时间
}; 

//语言ID描述符
const u8 StringLangID[4] =
{
    0x04,   /* bLength: LanguageID Descriptor size */
    0x03,   /* bDescriptorType: LanguageID */
    0x09,   /* 0x0409 表示美式英语 */
    0x04
}

//N个字符串描述符


//报告描述符
const u8 ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
{
    0x05, 0x01,         /* USAGE_PAGE (Generic Desktop) *///全局:用途页:桌面应用
    0x09, 0x06,         /* USAGE (Keyboard) *///局部:用途:键盘
    0xa1, 0x01,         /* COLLECTION (Application) *///主条目:开集合:应用型

	//输入报告
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0xe0,         /* USAGE_MIN (Keyboard LeftControl) *///局部:用途最小值:键盘左ctrl键
	0x29, 0xe7,         /* USAGE_MAX (Keyboard Right GUI) *///局部:用途最大值:键盘右WIN键		
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x08,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x81, 0x02,         /* INPUT(Data,Var,Abs) *///主条目:说明有八个长度为1的数据域//总共8个特殊按键

	0x95, 0x01,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,         /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x81, 0x03,         /* INPUT(Cnst,Var,Abs) *///主条目:说明有1个长度为8的数据固定数据域,保留
	
	0x05, 0x07,         /* USAGE_PAGE (Keyboard) *///全局:用途页:键盘
	0x19, 0x00,         /* USAGE_MIN (Reserved) *///局部:用途最小值:0表示没有按键按下
	0x29, 0x65,         /* USAGE_MAX (其他按键的键值) *///局部:用途最大值:0x65		
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x26, 0x00,	0xFF,   /* LOGICAL_MAX *///全局:返回逻辑最大值:255
	0x95, 0x06,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x08,         /* REPORT_SIZE *///全局:一个数据域的位长度
	0x81, 0x00,         /* INPUT(Data,Ary,Abs) *///主条目:说明有6个长度为8的数据域(数组)//总共显示6个按键按下


	//输出报告
	0x05, 0x08,         /* USAGE_PAGE (LED) *///全局:用途页:指示灯
	0x19, 0x01,         /* USAGE_MIN (Num Lock) *///局部:用途最小值:数字键盘灯
	0x29, 0x05,         /* USAGE_MAX (Kana) *///局部:用途最大值:Kana灯
	0x15, 0x00,         /* LOGICAL_MIN *///全局:返回逻辑最小值:0
	0x25, 0x01,         /* LOGICAL_MAX *///全局:返回逻辑最大值:1
	0x95, 0x05,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度	
	0x91, 0x02,         /* OUTPUT(Data,Var,Abs) *///主条目

	0x95, 0x03,         /* REPORT_COUNT *///全局:数据域数量
	0x75, 0x01,         /* REPORT_SIZE *///全局:一个数据域的位长度		
	0x91, 0x03,         /* OUTPUT(Cnst,Var,Abs) *///主条目

    0xc0                /* END_COLLECTION *///主条目:关集合
};

我的个人博客网址:一个点的频率 希望大家关注一下,谢谢!!!

你可能感兴趣的:(USB学习笔记,usb,stm32)