2 个接口的自定义 HID 设备
已经在项目中应用,无私分享给大家。
本代码实现了一个 USB device 使用两个接口描述符成功枚举,并使用 2 对端点和 PC 通讯。PC 上的上位机可以正常识别两个接口设备。使用 0x01 0x81 和 0x02 0x82 端点通讯
/*
* 设备描述符
*/
#define SIZEOF_DEVICE_DESCRIPTOR 0x12
#define DESC_TYPE_DEVICE 0x01
#define USB_VID 0x351E
#define USB_PID 0x025a
#define USB_STR_INDEX_SERNUM 3
#define VER_FW_H 0x02 // Device release number, in binary-coded decimal
#define VER_FW_L 0x00 // Device release number, in binary-coded decimal
#define USB1_ENDP0_SIZE 0x40
/*-----------------------------------------------------------------------------+
| Device Descriptor
|-----------------------------------------------------------------------------*/
const unsigned char usb1HIDDevDescr[SIZEOF_DEVICE_DESCRIPTOR] = {
SIZEOF_DEVICE_DESCRIPTOR, // Length of this descriptor
DESC_TYPE_DEVICE, // Type code of this descriptor
0x00, 0x02, // Release of USB spec
0xEF, // Device's base class code
0x02, // Device's sub class code
0x01, // Device's protocol type code
USB1_ENDP0_SIZE, // End point 0's packet size
USB_VID&0xFF, USB_VID>>8, // Vendor ID for device, TI=0x0451
// You can order your own VID at www.usb.org"
USB_PID&0xFF, USB_PID>>8, // Product ID for device,
// this ID is to only with this example
VER_FW_L, VER_FW_H, // Revision level of device
1, // Index of manufacturer name string desc
2, // Index of product name string desc
USB_STR_INDEX_SERNUM, // Index of serial number string desc
1 // Number of configurations supported
};
#define HID_NUM_INTERFACES 2 // Total Number of HIDs implemented. should set to 0 if there are no HIDs implemented.
//***********************************************************************************************
// DESCRIPTOR CONSTANTS
//***********************************************************************************************
#define MAX_STRING_DESCRIPTOR_INDEX 6
#define report_desc_size_HID0 36
#define report_desc_size_HID1 36
#define CONFIG_STRING_INDEX 4
#define INTF_STRING_INDEX 5
#define USB_CONFIG_VALUE 0x01
#define USB_SUPPORT_REM_WAKE 0x00
// Controls whether the application is self-powered to any degree. Should be
// set to 0x40, unless the USB device is fully supplied by the bus.
#define USB_SUPPORT_SELF_POWERED 0x80
// Controls what the device reports to the host regarding how much power it will
// consume from VBUS. Expressed in 2mA units; that is, the number of mA
// communicated is twice the value of this field.
#define USB_MAX_POWER 0x32
#define SIZEOF_INTERFACE_DESCRIPTOR 0x09
#define DESC_TYPE_INTERFACE 0x04
#define DESC_TYPE_CONFIG 0x02
#define SIZEOF_CONFIG_DESCRIPTOR 0x09
#define SIZEOF_ENDPOINT_DESCRIPTOR 0x07
#define DESC_TYPE_ENDPOINT 0x05
#define EP_DESC_ATTR_TYPE_INT 0x03
/* Structure for generic part of configuration descriptor */
struct abromConfigurationDescriptorGenric
{
unsigned char sizeof_config_descriptor; // bLength
unsigned char desc_type_config; // bDescriptorType: 2
unsigned char sizeof_configuration_descriptor1; // wTotalLength
unsigned char sizeof_configuration_descriptor2;
unsigned char usb_num_configurations; // bNumInterfaces
unsigned char bconfigurationvalue; // bConfigurationValue
unsigned char config_string_index; // iConfiguration Description offset
unsigned char mattributes; // bmAttributes, bus power, remote wakeup
unsigned char usb_max_power; // Max. Power Consumption at 2mA unit
};
/**************************************HID descriptor structure *************************/
struct abromConfigurationDescriptorHid
{
//INTERFACE DESCRIPTOR (9 bytes)
unsigned char sizeof_interface_descriptor; // Desc Length
unsigned char desc_type_interface; // DescriptorType
unsigned char interface_number_hid; // Interface number
unsigned char balternatesetting; // Any alternate settings if supported
unsigned char bnumendpoints; // Number of end points required
unsigned char binterfaceclass; // Class ID
unsigned char binterfacesubclass; // Sub class ID
unsigned char binterfaceprotocol; // Protocol
unsigned char intf_string_index; // String Index
//hid descriptor (9 bytes)
unsigned char blength_hid_descriptor; // HID Desc length
unsigned char hid_descriptor_type; // HID Desc Type
unsigned char hidrevno1; // Rev no
unsigned char hidrevno2; // Rev no - 2nd part
unsigned char tcountry; // Country code
unsigned char numhidclasses; // Number of HID classes to follow
unsigned char report_descriptor_type; // Report desc type
unsigned char tlength; // Total length of report descriptor
unsigned char size_rep_desc;
//input end point descriptor (7 bytes)
unsigned char size_inp_endpoint_descriptor; // End point desc size
unsigned char desc_type_inp_endpoint; // Desc type
unsigned char hid_inep_addr; // Input end point address
unsigned char ep_desc_attr_type_inp_int; // Type of end point
unsigned char inp_wmaxpacketsize1; // Max packet size
unsigned char inp_wmaxpacketsize2;
unsigned char inp_binterval; // bInterval in ms
// Output end point descriptor; (7 bytes)
unsigned char size_out_endpoint_descriptor; // Output endpoint desc size
unsigned char desc_type_out_endpoint; // Desc type
unsigned char hid_outep_addr; // Output end point address
unsigned char ep_desc_attr_type_out_int; // End point type
unsigned char out_wmaxpacketsize1; // Max packet size
unsigned char out_wmaxpacketsize2;
unsigned char out_binterval; // bInterval in ms
};
/* Global structure having Generic,CDC,HID, MSC structures */
struct abromConfigurationDescriptorGroup
{
/* Generic part of config descriptor */
const struct abromConfigurationDescriptorGenric abromConfigurationDescriptorGenric;
/* HID descriptor structure */
const struct abromConfigurationDescriptorHid stHid[HID_NUM_INTERFACES];
};
#ifndef WBVAL
#define WBVAL(x) (unsigned char)((x) & 0xFF), (unsigned char)(((x) >> 8) & 0xFF)
#endif
/*!< USBD CONFIG */
#define USBD_MAX_POWER 0xfa
#define USBD_CONFIG_DESCRIPTOR_SIZE (65+9-8 + 7)
#define HID_IF0_STRING (0x04)
const unsigned char HID_Interface0String[] = {
// String index6, Interface String
26, // Length of this string descriptor
3, // bDescriptorType
'H',0x00,'I',0x00,'D',0x00,' ',0x00,'P',0x00,'a',0x00,
'c',0x00,'k',0x00,'D',0x00,'a',0x00,'t',0x00,'a',0x00
};
#define HID_IF1_STRING (0x05)
const unsigned char HID_Interface1String[] = {
// String index5, Interface String
16, // Length of this string descriptor
3, // bDescriptorType
'H',0x00,'I',0x00,'D',0x00,' ',0x00,'C',0x00,'M',0x00,
'D',0x00,
};
/*!< USBD ENDPOINT CONFIG */
#define USBD_IF0_AL0_EP0_ADDR 0x01
#define USBD_IF0_AL0_EP0_SIZE (512)
#define USBD_IF0_AL0_EP0_INTERVAL 0x01
#define USBD_IF0_AL0_EP1_ADDR 0x81
#define USBD_IF0_AL0_EP1_SIZE 0x40
#define USBD_IF0_AL0_EP1_INTERVAL 0x01
#define USBD_IF1_AL0_EP0_ADDR 0x02
#define USBD_IF1_AL0_EP0_SIZE (512)
#define USBD_IF1_AL0_EP0_INTERVAL 0x01
#define USBD_IF1_AL0_EP1_ADDR 0x82
#define USBD_IF1_AL0_EP1_SIZE 0x40
#define USBD_IF1_AL0_EP1_INTERVAL 0x01
/*!< USBD HID CONFIG */
#define USBD_HID_VERSION 0x0111
#define USBD_HID_COUNTRY_CODE 0
#define USBD_IF0_AL0_HID_REPORT_DESC_SIZE (sizeof(HidReportDescr0))
#define USBD_IF1_AL0_HID_REPORT_DESC_SIZE (sizeof(HidReportDescr1))
#define EPIN_SIZE (0x40)
unsigned char const HidReportDescr0[]=
{
//vendor
0x06, 0x00, 0xFF, //Usage Page (Vendor-Defined 29)
0x09, 0x92, //Usage (Vendor-Defined 146)
0xA1, 0x01, //Collection (Application)
0x19, 0x00, //Usage Minimum (Undefined)
0x2A, 0xFF, 0x00, //Usage Maximum (Vendor-Defined 255)
0x15, 0x00, //Logical Minimum (0)
0x26, 0xFF, 0x00, //Logical Maximum (255)
0x75, 0x08, //Report Size (8)
0x95, 0x40, //Report Count (63)
0x91, 0x00, //Output (Data,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)
0x19, 0x00, //Usage Minimum (Undefined)
0x2a, 0xFF, 0x00, //Usage Maximum (Vendor-Defined 255)
0x81, 0x00, //Input (Data,Ary,Abs)
0xC0, //End Collection
};
unsigned char const HidReportDescr1[]=
{
0x06, 0x00, 0xFF, //Usage Page (Vendor-Defined 29)
0x09, 0x92, //Usage (Vendor-Defined 146)
0xA1, 0x01, //Collection (Application)
0x19, 0x00, //Usage Minimum (Undefined)
0x2A, 0xFF, 0x00, //Usage Maximum (Vendor-Defined 255)
0x15, 0x00, //Logical Minimum (0)
0x26, 0xFF, 0x00, //Logical Maximum (255)
0x75, 0x08, //Report Size (8)
0x95, 0x40, //Report Count (63)
0x91, 0x00, //Output (Data,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)
0x19, 0x00, //Usage Minimum (Undefined)
0x2a, 0xFF, 0x00, //Usage Maximum (Vendor-Defined 255)
0x81, 0x00, //Input (Data,Ary,Abs)
0xC0, //End Collection
};
const unsigned char HIDCfgDescr[] = {
//配置描述符
/********************************************** Config Descriptor */
0x09, /*!< bLength */
0x02, /*!< bDescriptorType */
//整个数组的长度
WBVAL(USBD_CONFIG_DESCRIPTOR_SIZE), /*!< wTotalLength */
//设备接口的数目 本设备有2个接口描述符
0x02, /*!< bNumInterfaces */
0x01, /*!< bConfigurationValue */
0x00, /*!< iConfiguration */
0xa0, /*!< bmAttributes */
USBD_MAX_POWER, /*!< bMaxPower */
// 接口描述符 0
/********************************************** Interface 0 Alternate 0 Descriptor */
0x09, /*!< bLength */
0x04, /*!< bDescriptorType */
0x00, /*!< bInterfaceNumber */
0x00, /*!< bAlternateSetting */
0x02, /*!< bNumEndpoints */
//接口类型,USB规范有明确定义 03 为 HID 类设备
0x03, /*!< bInterfaceClass */
0x00, /*!< bInterfaceSubClass */
0x00, /*!< bInterfaceProtocol */
HID_IF0_STRING, /*!< iInterface */
//HID 类接口需要配置 HID 设备类型,所以需要 HID 描述符
/********************************************** Class Specific Descriptor of HID */
0x09, /*!< bLength */
0x21, /*!< bDescriptorType */
WBVAL(USBD_HID_VERSION), /*!< bcdHID */
USBD_HID_COUNTRY_CODE, /*!< bCountryCode */
0x01, /*!< bNumDescriptors */
0x22, /*!< bDescriptorType */
// 表明 HID report 描述符的长度
WBVAL(USBD_IF0_AL0_HID_REPORT_DESC_SIZE), /*!< wItemLength */
// 端点描述符
/********************************************** Endpoint 0 Descriptor */
0x07, /*!< bLength */
0x05, /*!< bDescriptorType */
//端点地址
USBD_IF0_AL0_EP0_ADDR, /*!< bEndpointAddress */
0x03, /*!< bmAttributes */
WBVAL(USBD_IF0_AL0_EP0_SIZE), /*!< wMaxPacketSize */
USBD_IF0_AL0_EP0_INTERVAL, /*!< bInterval */
/********************************************** Endpoint 1 Descriptor */
0x07, /*!< bLength */
0x05, /*!< bDescriptorType */
USBD_IF0_AL0_EP1_ADDR, /*!< bEndpointAddress */
0x03, /*!< bmAttributes */
WBVAL(USBD_IF0_AL0_EP1_SIZE), /*!< wMaxPacketSize */
USBD_IF0_AL0_EP1_INTERVAL, /*!< bInterval */
// 接口描述符 1
/********************************************** Interface 1 Alternate 0 Descriptor */
0x09, /*!< bLength */
0x04, /*!< bDescriptorType */
0x01, /*!< bInterfaceNumber */
0x00, /*!< bAlternateSetting */
0x02, /*!< bNumEndpoints */
0x03, /*!< bInterfaceClass */
0x00, /*!< bInterfaceSubClass */
0x00, /*!< bInterfaceProtocol */
HID_IF1_STRING, /*!< iInterface */
/********************************************** Class Specific Descriptor of HID */
0x09, /*!< bLength */
0x21, /*!< bDescriptorType */
WBVAL(USBD_HID_VERSION), /*!< bcdHID */
USBD_HID_COUNTRY_CODE, /*!< bCountryCode */
0x01, /*!< bNumDescriptors */
0x22, /*!< bDescriptorType */
WBVAL(USBD_IF1_AL0_HID_REPORT_DESC_SIZE), /*!< wItemLength */
/********************************************** Endpoint 0 Descriptor */
0x07, /*!< bLength */
0x05, /*!< bDescriptorType */
USBD_IF1_AL0_EP0_ADDR, /*!< bEndpointAddress */
0x03, /*!< bmAttributes */
WBVAL(USBD_IF1_AL0_EP0_SIZE), /*!< wMaxPacketSize */
USBD_IF1_AL0_EP0_INTERVAL, /*!< bInterval */
/********************************************** Endpoint 0 Descriptor */
0x07, /*!< bLength */
0x05, /*!< bDescriptorType */
USBD_IF1_AL0_EP1_ADDR, /*!< bEndpointAddress */
0x03, /*!< bmAttributes */
WBVAL(USBD_IF1_AL0_EP1_SIZE), /*!< wMaxPacketSize */
USBD_IF1_AL0_EP1_INTERVAL, /*!< bInterval */
};