一、概论:

在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. require和load的不同之处

    require和load最大的不同之处在于,require就算调用多次也不会重新加载已经加载过的文件.Ruby会持续追踪已经被请求的那些文件而不会重复加载它们.而load命令总是会加载所请求的命令,不 ...

  2. python中的lambda表达式

    lambda是python中匿名函数的写法  我们可以在不定义函数名的情况下一边定义并调用这个函数 例子: 普通方法定义函数:def  plus(a,b): return a+b lambda方法  ...

  3. commons-lang常用方法

    跟java.lang这个包的作用类似,Commons Lang这一组API也是提供一些基础的.通用的操作和处理,如自动生成toString()的结果.自动实现hashCode()和equals()方法 ...

  4. .Net Core+Angular6 学习 第一部分(创建web api)

    . 创建.net core web api 1.1 选择一个empty 模式,里面只有简单的2个class 1.2 配置web api 的路由. 1.2.1 打开Startup.cs,首先引用conf ...

  5. TCP学习总结(四)

    TCP连接管理 TCP运输连接有3个阶段, 即: 连接建立,数据传送和连接释放. 1. TCP的连接建立(3次握手) TCP连接的建立采用客户服务器方式.主动发起连接建立的应用进程叫做客户(clien ...

  6. mybatics 与jpa

    mybatics,dao层接口,mapper: public interface UserMapper { @Select("SELECT * FROM T_ROLE WHERE ROLE_ ...

  7. kaptcha生成java验证码

    kaptcha工作的原理是调用 com.google.code.kaptcha.servlet.KaptchaServlet,生成一个图片.同时将生成的验证码字符串放到 HttpSession中. 1 ...

  8. mysql 实现 sqlserver的row_number over() 方法

    1.创建表 CREATE TABLE `heyf_t10` ( `empid` int(11) DEFAULT NULL, `deptid` int(11) DEFAULT NULL, `salary ...

  9. Sharepoint 2016 配置FBA(四)添加用户到Membership数据库

    现在还不能用FBA登录,因为数据库还没有用户. 有一些方法来管理membership数据库,有可以用IIS来管理.推荐使用 SharePoint 2016 FBA Pack(https://share ...

  10. 转自CSDN-详述 Java 中的别名现象

    在任何编程语言中,赋值操作都是最常见的操作之一,Java 自然也不例外.赋值时,使用赋值操作符=,它的意思是:“将等号右边的值(右值),复制给左边的值(左值)”.右值可以是任何常数.变量或者表达式(只 ...