一、概论:

在STM32_USB-FS-Device_Lib_V4.1.0的Custom_HID工程基础上进行修改;

开发一款设备,有三个HID接口,mouse+pen+自定义HID

其中:0_HID 是mouse(端点1 IN);1_HID 是pen(端点2 IN);2_HID 是自定义(端点3 IN-OUT)。

在设备管理器和bus hound可以看到如下:

二、修改步骤:

1、修改设备$$配置描述符


/* USB Standard Device Descriptor */
const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ_DEVICE_DESC] =
{
0x12, /*bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
0x10, /*bcdUSB */
0x01,
0x00, /*bDeviceClass*/
0x00, /*bDeviceSubClass*/
0x00, /*bDeviceProtocol*/
0x40, /*bMaxPacketSize:64 bytes*/
LOBYTE(USBD_VID), /*idVendor*/
HIBYTE(USBD_VID), /*idVendor*/
LOBYTE(USBD_PID), /*idVendor*/
HIBYTE(USBD_PID), /*idVendor*/
0x00, /*bcdDevice rel. 00.00*/
0x00,
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
USBD_IDX_PRODUCT_STR, /*Index of product string*/
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
USBD_CFG_MAX_NUM /*bNumConfigurations*/
}; /* CustomHID_DeviceDescriptor */ /* USB Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] =
{
/************** Configuration Descriptor Bus Powered, 100 mA ****************/
0x09, /* bLength: Configuration Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
0x5b, /* wTotalLength: Bytes returned */
0x00,
0x03, /* bNumInterfaces: 1 interface *///3个HID接口
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration*/
0xA0, /* bmAttributes: Self powered:C0 Bus Powered, Remote Wakeup:A0 */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ // 0/0 HID 1 Endpoint IN of 端点1
/************** Descriptor of 0/0 HID interface ****************/
/* 09 */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x00, /* iInterface: Index of string descriptor */
/******************** Descriptor of 0/0 HID ********************/
/* 18 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x00, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
sizeof(mouse_ReportDescriptor)&0xFF, /* wItemLength: Total length of Report descriptor :177 bytes*/
(sizeof(mouse_ReportDescriptor)>>)&0xFF,
/******************** Descriptor of 0/0 HID endpoints :1IN ******************/
/* 27 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x81, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
0x08, /* wMaxPacketSize: 8 Bytes max */
0x00,
0x04, /* bInterval: Polling Interval (4 ms) */ // 1/0 HID 1 Endpoint IN of 端点2
/************** Descriptor of 1/0 HID interface ****************/
/* 34 */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x00, /* iInterface: Index of string descriptor */
/******************** Descriptor of 1/0 HID ********************/
/* 43 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x00, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
sizeof(pen_ReportDescriptor)&0xFF, /* wItemLength: Total length of Report descriptor :237 bytes*/
(sizeof(pen_ReportDescriptor)>>)&0xFF,
/******************** Descriptor of 1/0 HID endpoints :2 IN ******************/
/* 52 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x82, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
0x40, /* wMaxPacketSize: 64 Bytes max */
0x00,
0x03, /* bInterval: Polling Interval (3 ms) */ // 2/0 HID 1 Endpoint IN /1 Endpoint OUT of 端点3
/************** Descriptor of 2/0 HID interface ****************/
/* 59 */
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
0x03, /* bInterfaceClass: HID */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x00, /* iInterface: Index of string descriptor */
/******************** Descriptor of 2/0 HID ********************/
/* 68 */
0x09, /* bLength: HID Descriptor size */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
0x00, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
0x22, /* bDescriptorType */
sizeof(HID_driver_ReportDescriptor)&0xFF, /* wItemLength: Total length of Report descriptor :36 bytes*/
(sizeof(HID_driver_ReportDescriptor)>>)&0xFF,
/******************** Descriptor of 2/0 HID endpoints :3 In, Interrupt, 3 ms******************/
/* 77 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x83, /* bEndpointAddress: Endpoint Address (IN) */
0x03, /* bmAttributes: Interrupt endpoint */
0x0A, /* wMaxPacketSize: 10 Bytes max */
0x00,
0x03, /* bInterval: Polling Interval (3 ms) */
/******************** Descriptor of 2/0 HID endpoints :3 Out, Interrupt, 3 ms******************/
/* 84 */
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x03, /* bEndpointAddress: Endpoint Address (out) */
0x03, /* bmAttributes: Interrupt endpoint */
0x0A, /* wMaxPacketSize: 10 Bytes max */
0x00,
0x0A, /* bInterval: Polling Interval (10 ms) */
}; /* CustomHID_ConfigDescriptor */

2、分别修改报告描述符

 /* 以下分别是三个报告描述符 */
/*Interface 0 HID Report Descriptor Mouse*/
const uint8_t mouse_ReportDescriptor[mouse_SIZ_REPORT_DESC] =
{
/*******************************mouse 1******************************************/
0x05, 0x01,/*USAGE_PAGE (Generic Desktop)*/
0x09, 0x02,/*USAGE (Mouse)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x09,//Report ID (9)
0x09, 0x01,//Usage (Pointer)
0xA1, 0x00,//Collection (Physical) 0x05, 0x09,//Usage Page (Button)
0x19, 0x01,//USAGE_MINIMUM(1)
0x29, 0x03,//USAGE_MAXIMUM(3)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0x01,//LOGICAL_MAXIMUM (1)
0x75, 0x01,//REPORT_SIZE (1)
0x95, 0x03,//Report Count (3)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x05,//Report Count (5)
0x81, 0x01,//Input (Cnst,Ary,Abs) 0x05, 0x01,//Usage Page (Generic Desktop)
0x09, 0x30,//Usage (X)
0x09, 0x31,//Usage (Y)
0x26, 0xFF,0x7F,//Logical Maximum (32767)
0x95, 0x02,//Report Count (2)
0x75, 0x10,//Report Size (16)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x05, 0x0D,//Usage Page (Digitizer)
0x09, 0x30,//Usage (Tip Pressure)
0x26, 0xFF,0x07,//Logical Maximum (2047)
0x95, 0x01,//Report Count (1)
0x75, 0x10,//Report Size (16)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0xC0,//End Collection
0xC0,//End Collection /*******************************mouse 2-75******************************************/
0x05, 0x01,/*USAGE_PAGE (Generic Desktop)*/
0x09, 0x02,/*USAGE (Mouse)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x01,//Report ID (1)
0x09, 0x01,//Usage (Pointer)
0xA1, 0x00,//Collection (Physical) 0x05, 0x09,//Usage Page (Button)
0x19, 0x01,//USAGE_MINIMUM(1)
0x29, 0x05,//USAGE_MAXIMUM(5)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0x01,//LOGICAL_MAXIMUM (1)
0x75, 0x01,//REPORT_SIZE (1)
0x95, 0x05,//Report Count (5)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x03,//Report Count (3)
0x81, 0x01,//Input (Cnst,Ary,Abs) 0x05, 0x01,//Usage Page (Generic Desktop)
0x09, 0x30,//Usage (X)
0x09, 0x31,//Usage (Y)
0x95, 0x02,//Report Count (2)
0x75, 0x10,//Report Size (16)
0x16, 0x00,0x80,//Logical Minimum (-32767)
0x26, 0xFF,0x7F,//Logical Maximum (32767)
0x81, 0x06,//Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 0x09, 0x38,//Usage (Wheel)
0x15, 0x81,//Logical Minimum (-127)
0x25, 0x7F,//Logical Maximum (127)
0x95, 0x01,//Report Count (1)
0x75, 0x08,//Report Size (8)
0x81, 0x06,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x05, 0x0C,//Usage Page (Consumer Devices)
0x0A, 0x38,0x02,//Usage (AC Pan)47)
0x95, 0x01,//Report Count (1)
0x75, 0x08,//Report Size (8)
0x81, 0x06,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0xC0,//End Collection
0xC0,//End Collection /********************************Keyboard-40*******************************************/
0x05, 0x01,/*USAGE_PAGE (Generic Desktop)*/
0x09, 0x06,/*USAGE (Keyboard)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x06,//Report ID (6)--------------------------无驱动按键使用此report
0x05, 0x07,//Usage Page (Keyboard/Keypad)
0x19, 0xE0,//USAGE_MINIMUM(Keyboard Left Control)
0x29, 0xE7,//USAGE_MAXIMUM(Keyboard Right GUI)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0x01,//LOGICAL_MAXIMUM (1)
0x75, 0x01,//REPORT_SIZE (1)
0x95, 0x08,//Report Count (8)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x05, 0x07,//Usage Page (Keyboard/Keypad)
0x19, 0x00,//Usage Minimum (Undefined)
0x29, 0xFF,//Usage Maximum
0x26, 0xFF,0x00,//Logical Maximum (255)
0x95, 0x06,//Report Count (6)
0x75, 0x10,//Report Size (8)
0x81, 0x00,//Input (Data,Ary,Abs) 0xC0//End Collection
}; /*Interface 1 HID Report Descriptor Pen*/
const uint8_t pen_ReportDescriptor[pen_SIZ_REPORT_DESC] =
{
/*******************************pen 1****x2**************************************/
0x05, 0x0D,/*Usage Page (Digitizer)*/
0x09, 0x02,/*Usage (Pen)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x07,//Report ID (7)
0x09, 0x20,//Usage (Stylus)
0xA1, 0x00,//Collection (Physical) 0x09, 0x42,//Usage (Tip Switch)
0x09, 0x44,//Usage (Barrel Switch)
0x09, 0x45,//Usage (Eraser)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0x01,//LOGICAL_MAXIMUM (1)
0x75, 0x01,//REPORT_SIZE (1)
0x95, 0x03,//Report Count (3)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x02,//Report Count (2)
0x81, 0x03,//Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x09, 0x32,//Usage (In Range)
0x95, 0x01,//Report Count (1)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x02,//Report Count (2)
0x81, 0x03,//Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x01,//Report Count (1)
0x75, 0x10,//Report Size (16)
0x35, 0x00,//Physical Minimum (0) 0xA4,//Push
0x05, 0x01,//Usage Page (Generic Desktop)
0x09, 0x30,//Usage (X)
0x65, 0x13,//Unit (Eng Lin: Length (in))
0x55, 0x0D,//Unit Exponent (-3)
0x46, 0xC1,0x28,//Physical Maximum (10433)
0x46, 0xC2,0x65,//Logical Maximum (26050)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x31,//Usage (Y)
0x46, 0x9B,0x18,//Physical Maximum (6299)
0x26, 0x80,0x3E,//Logical Maximum (16000)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xB4,//Pop 0x09, 0x30,//Usage (Tip Pressure)
0x45, 0x00,//Physical Maximum (0)
0x26, 0xFF,0x1F,//Logical Maximum (8191)
0x81, 0x42,//Input (Data,Var,Abs,NWrp,Lin,Pref,Null,Bit)
0x09, 0x3D,//Usage (X Tilt)
0x15, 0x81,//Logical Minimum (-127)
0x25, 0x7F,//Logical Maximum (127)
0x95, 0x01,//Report Count (1)
0x75, 0x08,//Report Size (8)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x09, 0x3E,//Usage (Y Tilt)
0x15, 0x81,//Logical Minimum (-127)
0x25, 0x7F,//Logical Maximum (127)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xC0,//End Collection
0xC0,//End Collection /*******************************pen 2******************************************/
0x05, 0x0D,/*Usage Page (Digitizer)*/
0x09, 0x02,/*Usage (Pen)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x08,//Report ID (8)
0x09, 0x20,//Usage (Stylus)
0xA1, 0x00,//Collection (Physical) 0x09, 0x42,//Usage (Tip Switch)
0x09, 0x44,//Usage (Barrel Switch)
0x09, 0x45,//Usage (Eraser)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0x01,//LOGICAL_MAXIMUM (1)
0x75, 0x01,//REPORT_SIZE (1)
0x95, 0x03,//Report Count (3)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x02,//Report Count (2)
0x81, 0x03,//Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x09, 0x32,//Usage (In Range)
0x95, 0x01,//Report Count (1)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x02,//Report Count (2)
0x81, 0x03,//Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x95, 0x01,//Report Count (1)
0x75, 0x10,//Report Size (16)
0x35, 0x00,//Physical Minimum (0) 0xA4,//Push
0x05, 0x01,//Usage Page (Generic Desktop)
0x09, 0x30,//Usage (X)
0x65, 0x13,//Unit (Eng Lin: Length (in))
0x55, 0x0D,//Unit Exponent (-3)
0x46, 0xC1,0x28,//Physical Maximum (10433)
0x46, 0xC2,0x65,//Logical Maximum (26050)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x31,//Usage (Y)
0x46, 0x9B,0x18,//Physical Maximum (6299)
0x26, 0x80,0x3E,//Logical Maximum (16000)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xB4,//Pop 0x09, 0x30,//Usage (Tip Pressure)
0x45, 0x00,//Physical Maximum (0)
0x26, 0xFF,0x1F,//Logical Maximum (8191)
0x81, 0x42,//Input (Data,Var,Abs,NWrp,Lin,Pref,Null,Bit)
0x09, 0x3D,//Usage (X Tilt)
0x15, 0x81,//Logical Minimum (-127)
0x25, 0x7F,//Logical Maximum (127)
0x95, 0x01,//Report Count (1)
0x75, 0x08,//Report Size (8)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x09, 0x3E,//Usage (Y Tilt)
0x15, 0x81,//Logical Minimum (-127)
0x25, 0x7F,//Logical Maximum (127)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xC0,//End Collection
0xC0,//End Collection
/*******************************Vendor-Defined 4-23*****************************************/
0x06, 0x03,0xFF,/*Usage Page (Vendor-Defined 4)*/
0x09, 0x000,/*Usage (Undefined)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x0B,//Report ID (11)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0xFF,0x00,//LOGICAL_MAXIMUM (255)
0x09, 0x00,//Usage (Undefined)
0x75, 0x08,//REPORT_SIZE (8)
0x95, 0x3F,//Report Count (63)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xC0//End Collection
};
/*Interface 2 HID Report Descriptor */
const uint8_t HID_driver_ReportDescriptor[HID_driver_SIZ_REPORT_DESC] =
{
/********************************Vendor-Defined 11**36*****************************************/
0x06, 0x0A,0xFF,/*Usage Page (Vendor-Defined 11)*/
0x09, 0x01,/*Usage (Vendor-Defined 1)*/
0xA1, 0x01,/*COLLECTION (Application)*/ 0x85, 0x02,//Report ID (2)--------------------------驱动使用此report
0x09, 0x02,//Usage (Vendor-Defined 2)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0xFF,0x00,//LOGICAL_MAXIMUM (255)
0x75, 0x08,//REPORT_SIZE (8)
0x95, 0x09,//Report Count (9)
0x81, 0x02,//Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 0x09, 0x03,//Usage (Vendor-Defined 3)
0x75, 0x08,//REPORT_SIZE (8)
0x95, 0x07,//Report Count (7)
0x15, 0x00,//LOGICAL_MINIMUM (0)
0x25, 0xFF,0x00,//LOGICAL_MAXIMUM (255)
0x91, 0x02,//Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 0xC0,//End Collection
};

3、在usb_des.h 文件定义报告描述符的大小及定义reportdescriptor并屏蔽原来的Custom_HID不需要的定义

#define mouse_SIZ_REPORT_DESC                   0x00B1            //0HID 报告描述符大小177BYTE
#define pen_SIZ_REPORT_DESC 0x00ED //1HID 报告描述符大小237BYTE
#define HID_driver_SIZ_REPORT_DESC 0x0024 //2HID 报告描述符大小177BYTE
//报告描述符定义
extern const uint8_t mouse_ReportDescriptor[mouse_SIZ_REPORT_DESC];
extern const uint8_t pen_ReportDescriptor[pen_SIZ_REPORT_DESC];
extern const uint8_t HID_driver_ReportDescriptor[HID_driver_SIZ_REPORT_DESC];

4、重点修改usb_pro.h文件

4.1 新增:ONE_DESCRIPTOR XX_Report_Descriptor及ONE_DESCRIPTOR XX_Hid_Descriptor函数,去除原来Custom_HID的。

/************分别获取3个HID的报告描述符****************/
ONE_DESCRIPTOR mouse_Report_Descriptor = //用于获得报告描述符
{
(uint8_t *)mouse_ReportDescriptor,
mouse_SIZ_REPORT_DESC
};
ONE_DESCRIPTOR pen_Report_Descriptor =
{
(uint8_t *)pen_ReportDescriptor,
pen_SIZ_REPORT_DESC
};
ONE_DESCRIPTOR HID_driver_Report_Descriptor =
{
(uint8_t *)HID_driver_ReportDescriptor,
HID_driver_SIZ_REPORT_DESC
}; /************分别获取3个HID的配置描述符中的HID描述****************/
//mouse_OFF_HID_DESC/pen_OFF_HID_DESC/HID_driver_OFF_HID_DESC
//是HID描述在配置描述符中的偏移量
ONE_DESCRIPTOR mouse_Hid_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor + mouse_OFF_HID_DESC,
CUSTOMHID_SIZ_HID_DESC
};
ONE_DESCRIPTOR pen_Hid_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor + pen_OFF_HID_DESC,
CUSTOMHID_SIZ_HID_DESC
};
ONE_DESCRIPTOR HID_driver_Hid_Descriptor =
{
(uint8_t*)CustomHID_ConfigDescriptor + HID_driver_OFF_HID_DESC,
CUSTOMHID_SIZ_HID_DESC
};

4.2 XX_OFF_HID_DESC是HID描述符在usb_des.h文件中配置描述符函数CustomHID_ConfigDescriptor的偏移量

所以在usb_des.h 文件定义:

//ONE_DESCRIPTOR XX_Hid_Descriptor 偏移量定义
#define mouse_OFF_HID_DESC        0x12 //18
#define pen_OFF_HID_DESC        0x28 //43
#define HID_driver_OFF_HID_DESC       0x44 //68

4.3修改void CustomHID_Reset(void)函数中相关端点的定义,

void CustomHID_Reset(void)
{
/* Set CustomHID_DEVICE as not configured */
pInformation->Current_Configuration = ;
pInformation->Current_Interface = ;/*the default Interface*/ /* Current Feature initialization */
pInformation->Current_Feature = CustomHID_ConfigDescriptor[]; SetBTABLE(BTABLE_ADDRESS); /* Initialize Endpoint 0 */
SetEPType(ENDP0, EP_CONTROL);
SetEPTxStatus(ENDP0, EP_TX_STALL);
SetEPRxAddr(ENDP0, ENDP0_RXADDR);
SetEPTxAddr(ENDP0, ENDP0_TXADDR);
Clear_Status_Out(ENDP0);
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
SetEPRxValid(ENDP0); /* Initialize Endpoint 1 IN 8 byte*/
SetEPType(ENDP1, EP_INTERRUPT);
SetEPTxAddr(ENDP1, ENDP1_TXADDR);
SetEPTxCount(ENDP1, );
SetEPTxStatus(ENDP1, EP_TX_NAK); /* Initialize Endpoint 2 IN 10 byte*/
SetEPType(ENDP2, EP_INTERRUPT);
SetEPTxAddr(ENDP2, ENDP2_TXADDR);
SetEPTxCount(ENDP2, );
SetEPTxStatus(ENDP2, EP_TX_NAK); /* Initialize Endpoint 3 IN 10 byte*/
SetEPType(ENDP3, EP_BULK);
SetEPTxAddr(ENDP3, ENDP3_TXADDR);
SetEPTxCount(ENDP3, ); //设置发送的长度
SetEPTxStatus(ENDP3, EP_TX_NAK); //设置发送端点非应答
//SetEPRxStatus(ENDP3, EP_RX_DIS); //设置接受端点关闭 /* Initialize Endpoint 3 OUT 64 byte max */
SetEPType(ENDP3, EP_BULK);
SetEPRxAddr(ENDP3, ENDP3_RXADDR);
SetEPRxCount(ENDP3, );
SetEPRxStatus(ENDP3, EP_RX_VALID);
//SetEPTxStatus(ENDP3, EP_TX_DIS); /* Set this device to response on default address */
SetDeviceAddress();
bDeviceState = ATTACHED;
}

及usb_conf.h文件相关端点地址定义:

#define EP_NUM     (3)     //修改支持的端点数量by linxw

/*-------------------------------------------------------------*/
/* -------------- Buffer Description Table -----------------*/
/*-------------------------------------------------------------*/
/* buffer table base address */
#define BTABLE_ADDRESS (0x00) /* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80) /* EP1 */
/* tx buffer base address */
#define ENDP1_TXADDR (0xC0) //ENDP0_TXADDR+0x40开始 /* EP2 */
/* tx buffer base address */
#define ENDP2_TXADDR (0x100) //ENDP1_TXADDR+0x40开始 /* EP3 */
/* tx buffer base address */
#define ENDP3_TXADDR (0x140) //ENDP2_TXADDR+0x40开始
#define ENDP3_RXADDR (0x180)

4.4修改RESULT CustomHID_Data_Setup(uint8_t RequestNo相关HID配置

/*******************************************************************************
* Function Name : CustomHID_Data_Setup
* Description : Handle the data class specific requests.
*这个函数对不同的接口进行区分,USBwIndex0反应出接口数量,不同接口返回不同的报告描述符
*第0接口:返回mouse相关的描述符
*第1接口:返回prn相关的描述符
*第2接口:返回driver相关的描述符
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/ RESULT CustomHID_Data_Setup(uint8_t RequestNo)
{
uint8_t *(*CopyRoutine)(uint16_t); if (pInformation->USBwIndex != )
return USB_UNSUPPORT; CopyRoutine = NULL; if ((RequestNo == GET_DESCRIPTOR)
&& (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
&& (pInformation->USBwIndex0 < ))
{
//在下面对3个接口进行区分
//CopyRoutine是指针函数,以指示运行哪个函数
//需要构建6个函数 XX_GetReportDescriptor 和 XX_GetHIDDescriptor
if (pInformation->USBwValue1 == REPORT_DESCRIPTOR)
{
//判断
if (pInformation->USBwIndex0 == )
{
CopyRoutine = mouse_GetReportDescriptor;
}
else if (pInformation->USBwIndex0 == )
{
CopyRoutine = pen_GetReportDescriptor;
}
else if (pInformation->USBwIndex0 == )
{
CopyRoutine = HID_driver_GetReportDescriptor;
} }
else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE)
{
//判断
if (pInformation->USBwIndex0 == )
{
CopyRoutine = mouse_GetHIDDescriptor;
}
else if (pInformation->USBwIndex0 == )
{
CopyRoutine = pen_GetHIDDescriptor;
}
else if (pInformation->USBwIndex0 == )
{
CopyRoutine = HID_driver_GetHIDDescriptor;
} } } /* End of GET_DESCRIPTOR */ /*** GET_PROTOCOL, GET_REPORT, SET_REPORT ***/
//这部分看是否需要更改
else if ( (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) )
{
switch( RequestNo )
{
case GET_PROTOCOL:
CopyRoutine = CustomHID_GetProtocolValue;
break;
case SET_REPORT:
CopyRoutine = CustomHID_SetReport_Feature;
Request = SET_REPORT;
break;
default:
break;
}
} if (CopyRoutine == NULL)
{
return USB_UNSUPPORT;
} pInformation->Ctrl_Info.CopyData = CopyRoutine;
pInformation->Ctrl_Info.Usb_wOffset = ;
(*CopyRoutine)();
return USB_SUCCESS;
}

4.5以上CustomHID_Data_Setup函数需要构建6个函数:

在usb_prop.h增加函数的定义并去除无关的Custom_HID函数定义:

//新增函数定义
uint8_t *mouse_GetReportDescriptor(uint16_t Length);
uint8_t *pen_GetReportDescriptor(uint16_t Length);
uint8_t *HID_driver_GetReportDescriptor(uint16_t Length);

uint8_t *mouse_GetHIDDescriptor(uint16_t Length);
uint8_t *pen_GetHIDDescriptor(uint16_t Length);
uint8_t *HID_driver_GetHIDDescriptor(uint16_t Length);

在usb_proc.c定义:

/*******************************************************************************
* Function Name : XX_GetReportDescriptor.
* Description : Gets the HID report descriptor.
* Input : Length
* Output : None.
* Return : The address of the configuration descriptor.
*******************************************************************************/
uint8_t *mouse_GetReportDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &mouse_Report_Descriptor);
}
uint8_t *pen_GetReportDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &pen_Report_Descriptor);
}
uint8_t *HID_driver_GetReportDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &HID_driver_Report_Descriptor);
} /*******************************************************************************
* Function Name : XX_GetHIDDescriptor.
* Description : Gets the HID descriptor.
* Input : Length
* Output : None.
* Return : The address of the configuration descriptor.
*******************************************************************************/
uint8_t *mouse_GetHIDDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &mouse_Hid_Descriptor);
}
uint8_t *pen_GetHIDDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &pen_Hid_Descriptor);
}
uint8_t *HID_driver_GetHIDDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &HID_driver_Hid_Descriptor);
}

5、完成测试:

枚举成功,but在bus hound下看到,每一个HID的枚举,主机PC发送set_idle。设备并没有解析,出现stall pid错误,虽然不影响HID的使用,看着别扭,于是查找了大量的文件,了解清楚,

最终,在固件库usb_proc.c文件里,修改以下函数,

出现的stall pid现象:

CustomHID_NoData_Setup:资料下载链接https://download.csdn.net/download/weixin_43245044/11052195
RESULT CustomHID_NoData_Setup(uint8_t RequestNo)
{
if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
&& (RequestNo == SET_PROTOCOL))
{
return CustomHID_SetProtocol();
}
//增加对PC端set_idle 请求的回应,不回复---by linxw
if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
&& (RequestNo == SET_IDLE))
{
return USB_SUCCESS;
}
else
{
return USB_UNSUPPORT;
}
}

STM32 USB-三个HID-interface 复合(组合)设备的代码实现-基于固件库(原创)的更多相关文章

  1. 【STM32学习笔记1】基于固件库的STM32_MDK工程模版

    文章包含STM32固件库介绍和工程模板搭建两方面内容. 一.STM32固件库介绍 要建立工程模板,首先要对STM32的固件库有所了解.STM32的固件可以从ST官网下载,网址为:http://www. ...

  2. STM32基于固件库新建MDK工程模板(精简版)

    上个博文理论讲解的东西太多,太复杂,这里把所有步骤全部贴出 1.新建一个工程文件夹LED 2.LED文件夹下建立如下文件夹 3.Project –>New Uvision Project 到US ...

  3. STM32组合设备实现USB转双串口

    USB转双串口,核心技术就在于组合设备(USB Composite)的实现,组合设备的实现,其核心技术在于描述符的实现,下面我们先给出描述符:设备描述符 [C] 纯文本查看 复制代码 ? 00001 ...

  4. STM32 寄存器库和固件库

    寄存器和固件库开发的差别和联系 固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道.向上提供用户函数调用的接口(API). 在 51 的开发中我们经常的作法是直接操作寄存器,比方要控制 ...

  5. USB组合设备 Interface Association Descriptor (IAD)

    Communication Device Class,简称CDCUSB Compound Device,USB复合设备USB Composite Device,USB组合设备 摘要USB复合设备 Co ...

  6. STM32 USB 问题汇总(转)

    源:STM32 USB 问题汇总 汇总1:STM32的USB例程修改步骤,来自http://blog.csdn.net/cy757/archive/2010/01/01/5117610.aspx 以下 ...

  7. Android USB Host与HID通讯 (二)

    不好意思,从上一篇到现在确实比较忙,中间又外出了一段时间,虽然也上LOFTER,或者看到一些朋友QQ上加我,给我发信息询问,有些看到了有些可能没看到,偶尔回复了一两个,也不咋的详细,在此我想说,一方面 ...

  8. USB Compound Device,USB复合设备 ; USB Composite Device,USB组合设备【转】

    本文转载自:https://blog.csdn.net/autumn20080101/article/details/52776863 科普下USB复合设备和USB组合设备的区别. 关键字 Commu ...

  9. STM32 USB Virtual COM

    STM32 USB Virtual COM USB转串口的功能实现   这次讲的是如何实现USB转串口功能的实现.首先看看工程的布局吧: 我们主要要介绍的文件的在USB_User这个组文件.从上面的截 ...

随机推荐

  1. Spine用于Timeline(NullReferenceException: Object reference not set to an instance of an object pine.Unity.Editor.AnimationReferenceAssetEditor.OnInspectorGUI ())

    报错信息:Spine.Unity.Editor.AnimationReferenceAssetEditor.OnInspectorGUI () (at Assets/Extention/Spine/E ...

  2. python常见的数据转化函数

    python常用类型转换函数 函数格式 使用示例 描述 int(x [,base]) int("8")   可以转换的包括String类型和其他数字类型,但是会丢失精度       ...

  3. 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165326

    kali的安装及配置 目录 下载 安装 相关配置 一.下载 官方下载网址https://www.kali.org/downloads/ 选择64位的.iso文件下载 返回 二.安装kali 打开VMw ...

  4. python编程从入门到实践 alien invasion 项目源码

    现在上传一个 python编程从入门到实践 alien invasion 项目源码 以供大家学习参考 跟官方版本可能不太一样,因为是自己写的 也算是给新手一个参考 我用的环境是pycharm 可能需要 ...

  5. VBA在WORD应用中如何将格式应用于选定内容

    下列示例使用 Selection 属性将字符和段落格式应用于选定文本.使用 Font 属性获得字体格式的属性和方法,使用 ParagraphFormat 属性获得段落格式的属性和方法. Sub For ...

  6. JS查看对象属性的方式

    var person = { type: 'person', say: function(){ console.log("Hellow World!") } } //以person ...

  7. A The Empire Age

    1月28日 Description 帝国时代3是一款十分刺激的RTS游戏.你需要控制自己的一块殖民地,发展殖民地的经济和军事,最终打败其他殖民地.小L是这个游戏的狂热爱好者.一次小L打算打AI试试身手 ...

  8. 搭建vue的开发环境

    随手笔记:win7 64bit 1.安装node,直接从node官网下载,安装即可. 2.命令行输入 node -v 查看是否安装成功,显示node的版本号即安装成功.安装成功后,输入node,进入n ...

  9. PHP基本随笔

    1:制作一个永不重复的数字: private function getMillisecond(){ list($t1, $t2) = explode(' ', microtime()); return ...

  10. ngix请求转发

    实际运用中,当我们有对用户隐藏真实url的需求时,可以使用ngix转发. 1.转发所有请求: location / { proxy_pass http://localhost:8080 ; } 2.转 ...