- const uint8_t g_hidConfigDescriptor[] =
- {
- // configuration_descriptor hid_configuration_descriptor
- 0x09, // Length
- 0x02, // Type
- HID_CONFIG_DESCRIPTOR_SIZE&0xff,HID_CONFIG_DESCRIPTOR_SIZE>>8,// Totallength (= 9+9+9+7+7)
- 0x03, // NumInterfaces ?????
- 0x01, // bConfigurationValue
- 0x00, // iConfiguration ??????????
- 0x80, // bmAttributes
- 0xc0, // MaxPower (in 2mA units)
- // interface_descriptor hid_interface_descriptor
- 0x09, // bLength
- 0x04, // bDescriptorType
- 0x00, // bInterfaceNumber ???,???????????
- 0x00, // bAlternateSetting ???????
- 0x02, // bNumEndpoints ??????????,?0?????????0
- 0x03, // bInterfaceClass (3 = HID)
- 0x00, // bInterfaceSubClass
- 0x00, // bInterfaceProcotol
- 0x04, // iInterface Index of string descriptor
- // class_descriptor hid_descriptor
- 0x09, // bLength
- 0x21, // bDescriptorType
- 0x01,0x01, // bcdHID
- 0x00, // bCountryCode
- 0x01, // bNumDescriptors
- 0x22, // bDescriptorType
- HID_GAMEPAD_REPORT_DESCRIPTOR_SIZE,0X00, // wItemLength (tot. len. of report descriptor)
- // IN endpoint (mandatory for HID)
- // endpoint1_descriptor hid_endpoint_in_descriptor
- 0x07, // bLength
- 0x05, // bDescriptorType
- 0x81, // bEndpointAddress
- 0x03, // bmAttributes 00-????,01-????,10-???,11-????
- 0x40,0x00, // MaxPacketSize (LITTLE ENDIAN)
- 10, // bInterval
- // OUT endpoint (optional for HID)
- // endpoint1_descriptor hid_endpoint_out_descriptor
- 0x07, // bLength
- 0x05, // bDescriptorType
- 0x01, // bEndpointAddress
- 0x03, // bmAttributes
- 0x40,0x00, // MaxPacketSize (LITTLE ENDIAN)
- 10, // bInterval
- // interface_descriptor hid_interface_descriptor 222222222222222222222222222222
- 0x09, // bLength
- 0x04, // bDescriptorType
- 0x01, // bInterfaceNumber ???,???????????
- 0x00, // bAlternateSetting ???????
- 0x02, // bNumEndpoints ??????????,?0?????????0
- 0x03, // bInterfaceClass (3 = HID)
- 0x01, // bInterfaceSubClass 0-nosub,1-bootclass,2-reserved
- 0x01, // bInterfaceProcotol 0-No,1-keyboard,2-mouse,
- 0x05, // iInterface Index of string descriptor
- // class_descriptor hid_descriptor
- 0x09, // bLength
- 0x21, // bDescriptorType
- 0x01,0x01, // bcdHID
- 0x00, // bCountryCode
- 0x01, // bNumDescriptors
- 0x22, // bDescriptorType
- HID_KEYBOARD_REPORT_DESCRIPTOR_SIZE,0x00,// wItemLength (tot. len. of report descriptor)
- // IN endpoint (mandatory for HID)
- // endpoint1_descriptor hid_endpoint_in_descriptor
- 0x07, // bLength
- 0x05, // bDescriptorType
- 0x82, // bEndpointAddress
- 0x03, // bmAttributes 00-????,01-????,10-???,11-????
- 0x40,0x00, // MaxPacketSize (LITTLE ENDIAN)
- 0x0a, // bInterval
- // OUT endpoint (optional for HID)
- // endpoint1_descriptor hid_endpoint_out_descriptor
- 0x07, // bLength
- 0x05, // bDescriptorType
- 0x02, // bEndpointAddress
- 0x03, // bmAttributes
- 0x40,0x00, // MaxPacketSize (LITTLE ENDIAN)
- 0x0a, // bInterval
- /************** Descriptor of Mouse HID interface ****************/
- /* 09 */
- 0x09, /*bLength: Interface Descriptor size*/
- 0x04, /*bDescriptorType: Interface descriptor type*/
- 0x02, /*bInterfaceNumber: Number of Interface*/
- 0x00, /*bAlternateSetting: Alternate setting*/
- 0x01, /*bNumEndpoints*/
- 0x03, /*bInterfaceClass: CUSTOM_HID*/
- 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
- 0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
- 0X06, /*iInterface: Index of string descriptor*/
- /******************** Descriptor of CUSTOM_HID *************************/
- /* 18 */
- 0x09, /*bLength: CUSTOM_HID Descriptor size*/
- 0x21, /*bDescriptorType: CUSTOM_HID*/
- 0x11, /*bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number*/
- 0x01,
- 0x00, /*bCountryCode: Hardware target country*/
- 0x01, /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/
- 0x22, /*bDescriptorType*/
- HID_MOUSE_REPORT_DESCRIPTOR_SIZE,0x00,/*wItemLength: Total length of Report descriptor*/
-
- /******************** Descriptor of Custom HID endpoints ********************/
- /* 27 */
- 0x07, /*bLength: Endpoint Descriptor size*/
- 0x05, /*bDescriptorType:*/
- 0x83, /*bEndpointAddress: Endpoint Address (IN)*/
- 0x03, /*bmAttributes: Interrupt endpoint*/
- 0x40,0x00, /*wMaxPacketSize: 4 Byte max */
- 0x08, /*bInterval: Polling Interval (20 ms)*/
- /* 34 */
- };
其次就是3个设备的报告描述符
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] HID report descriptor
- */
- const uint8_t g_hidGamepadReportDescriptor[] =
- {
- 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
- 0x09, 0x05, // USAGE (Game Pad)
- 0xa1, 0x01, // COLLECTION (Application)
- 0x09, 0x01, // USAGE (Pointer)
- 0xa1, 0x00, // COLLECTION (Physical)
- 0x09, 0x30, // USAGE (X)
- 0x09, 0x31, // USAGE (Y)
- 0x09, 0x33, // USAGE (RX)
- 0x09, 0x34, // USAGE (RY)
- 0x15, 0x81, // LOGICAL_MINIMUM (-127)
- 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x04, // REPORT_COUNT (4)
- 0x81, 0x02, // INPUT (Data,Var,Abs)
- 0xc0, // END_COLLECTION
-
- 0x09, 0x36, // USAGE (Silder)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x81, 0x02, // INPUT (Data,Var,Abs)
-
- 0x09, 0x39, // USAGE (Hat switch)
- 0x15, 0x01, // LOGICAL_MINIMUM (1)
- 0x25, 0x08, // LOGICAL_MAXIMUM (8)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x81, 0x42, // INPUT (Data,Var,Abs,Null)
-
- 0x05, 0x09, // USAGE_PAGE (Button)
- 0x19, 0x01, // USAGE_MINIMUM (Button 1)
- 0x29, 0x10, // USAGE_MAXIMUM (Button 16)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x25, 0x01, // LOGICAL_MAXIMUM (1)
- 0x75, 0x01, // REPORT_SIZE (1)
- 0x95, 0x10, // REPORT_COUNT (16)
- 0x81, 0x02, // INPUT (Data,Var,Abs)
-
- 0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
- 0x09, 0x01, // USAGE (Vendor Usage 1)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x04, // REPORT_COUNT (4)
- 0x91, 0x02, // OUTPUT (Data,Var,Abs)
-
- 0xc0 // END_COLLECTION
- };
- const uint8_t g_hidKeyboardReportDescriptor[]=
- {
- 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
- 0x09, 0x06, // USAGE (Keyboard)
- 0xa1, 0x01, // COLLECTION (Application)
-
- 0x05, 0x07, // USAGE_PAGE (Keyboard)
- 0x19, 0xE0, // USAGE_MINIMUM (Keyboard LeftControl)
- 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)
-
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x81, 0x03, // INPUT (Cnst,Var,Abs)
- 0x05, 0x07, // USAGE_PAGE (Keyboard)
- 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
- 0x29, 0xdd, // USAGE_MAXIMUM (Keyboard Application)
- 0x95, 0x06, // REPORT_COUNT (6)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x25, 0xdd, // LOGICAL_MAXIMUM (164)
- 0x81, 0x00, // INPUT (Data,Ary,Abs)
- 0x05, 0x08, // USAGE_PAGE (LEDs)
- 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
- 0x29, 0x05, // USAGE_MAXIMUM (Kana)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x25, 0x01, // LOGICAL_MAXIMUM (1)
- 0x95, 0x05, // REPORT_COUNT (5)
- 0x75, 0x01, // REPORT_SIZE (1)
- 0x91, 0x02, // OUTPUT (Data,Var,Abs)
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x75, 0x03, // REPORT_SIZE (3)
- 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
-
- 0xc0 // END_COLLECTION
- };
- const uint8_t g_hidMouseReportDescriptor[]=
- {
- 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_MINIMUM (Button 1)
- 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
- 0x25, 0x01, // LOGICAL_MAXIMUM (1)
- 0x95, 0x03, // REPORT_COUNT (3)
- 0x75, 0x01, // REPORT_SIZE (1)
- 0x81, 0x02, // INPUT (Data,Var,Abs)
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x75, 0x05, // REPORT_SIZE (5)
- 0x81, 0x01, // INPUT (Cnst,Ary,Abs)
-
- 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
- 0x09, 0x30, // USAGE (X)
- 0x09, 0x31, // USAGE (Y)
- 0x15, 0x81, // LOGICAL_MINIMUM (-127)
- 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x02, // REPORT_COUNT (2)
- 0x81, 0x06, // INPUT (Data,Var,Rel)
-
- 0x09, 0x38, // USAGE (Wheel)
- 0x15, 0x81, // LOGICAL_MINIMUM (-127)
- 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
- 0x75, 0x08, // REPORT_SIZE (8)
- 0x95, 0x01, // REPORT_COUNT (1)
- 0x81, 0x06, // INPUT (Data,Var,Rel)
-
- 0xc0, // END_COLLECTION
-
- 0xc0
- };
- /** Device descriptor */
- const USB_Descriptor_T s_deviceDescriptor = {g_hidDeviceDescriptor, HID_DEVICE_DESCRIPTOR_SIZE};
- /** Config descriptor */
- const USB_Descriptor_T s_configDescriptor = {g_hidConfigDescriptor, HID_CONFIG_DESCRIPTOR_SIZE};
- /** String descriptor */
- const USB_Descriptor_T s_stringDescriptor[] =
- {
- {g_hidLandIDString, HID_LANGID_STRING_SIZE},
- {g_hidVendorString, HID_VENDOR_STRING_SIZE},
- {g_hidProductString, HID_PRODUCT_STRING_SIZE},
- {g_hidSerialString, HID_SERIAL_STRING_SIZE},
- {g_Class1StringDesc, 16},
- {g_Class2StringDesc, 18},
- {g_Class3StringDesc, 12},
- };
- const USB_Descriptor_T s_reportDescriptor[] =
- {
- {g_hidGamepadReportDescriptor, HID_GAMEPAD_REPORT_DESCRIPTOR_SIZE},
- {g_hidKeyboardReportDescriptor, HID_KEYBOARD_REPORT_DESCRIPTOR_SIZE},
- {g_hidMouseReportDescriptor, HID_MOUSE_REPORT_DESCRIPTOR_SIZE},
- };
接着就是USB端点的初始化。本次要使用端点1,端点2的输入输出端点,端点3的输入端点。
初始化如下:
- void HidMouse_Reset(void)
- {
- uint8_t i;
- s_usbConfigStatus = 0; //usb not config,disable send data
-
- USBD_SetBufferTable(USB_BUFFER_TABLE_ADDR);
- //endpoint 0 init
- USBD_ResetEPKind(USBD_EP_0);
-
- USBD_SetEPType(USBD_EP_0, USBD_EP_TYPE_CONTROL);
- USBD_SetEPTxStatus(USBD_EP_0, USBD_EP_STATUS_STALL);
- USBD_SetEPTxAddr(USBD_EP_0, USB_EP0_TX_ADDR);
-
- USBD_SetEPRxStatus(USBD_EP_0, USBD_EP_STATUS_VALID);
- USBD_SetEPRxAddr(USBD_EP_0, USB_EP0_RX_ADDR);
- USBD_SetEPRxCnt(USBD_EP_0, USB_EP_PACKET_SIZE);
- //ep1 gamepad
- USBD_SetEPType(USBD_EP_1, USBD_EP_TYPE_INTERRUPT);
- USBD_SetEPTxAddr(USBD_EP_1, USB_EP1_TX_ADDR);
- USBD_SetEPTxCnt(USBD_EP_1, 8);
- USBD_SetEPRxAddr(USBD_EP_1, USB_EP1_RX_ADDR);
- USBD_SetEPRxCnt(USBD_EP_1, 4);
- USBD_SetEPRxTxStatus(USBD_EP_1, USBD_EP_STATUS_VALID, USBD_EP_STATUS_VALID);
- //EP2 keyboard
- USBD_SetEPType(USBD_EP_2, USBD_EP_TYPE_INTERRUPT);
- USBD_SetEPTxAddr(USBD_EP_2, USB_EP2_TX_ADDR);
- USBD_SetEPTxCnt(USBD_EP_2, 8);
- USBD_SetEPRxAddr(USBD_EP_2, USB_EP2_RX_ADDR);
- USBD_SetEPRxCnt(USBD_EP_2, 1);
- USBD_SetEPRxTxStatus(USBD_EP_2, USBD_EP_STATUS_VALID, USBD_EP_STATUS_VALID);
- //EP3 mouse
- USBD_SetEPType(USBD_EP_3, USBD_EP_TYPE_INTERRUPT);
- USBD_SetEPTxAddr(USBD_EP_3, USB_EP3_TX_ADDR);
- USBD_SetEPTxCnt(USBD_EP_3, 4);
- USBD_SetEPRxAddr(USBD_EP_3, USB_EP3_RX_ADDR);
- USBD_SetEPRxCnt(USBD_EP_3, 8);
- USBD_SetEPRxTxStatus(USBD_EP_3,USBD_EP_STATUS_VALID, USBD_EP_STATUS_DISABLE );
-
- //endpoint addr
- for(i = 0; i < USB_EP_NUM; i++)
- {
- USBD_SetEpAddr((USBD_EP_T)i, i);
- }
-
- USBD_SetDeviceAddr(0);
- USBD_Enable();
- }
下面说一下端点Buffer地址设置,这里容易搞错。
/** EP0 Tx address */
#define USB_EP0_TX_ADDR (0X40)
/** EP0 Rx address */
#define USB_EP0_RX_ADDR (0X80)
/** EP1 Tx address */
#define USB_EP1_TX_ADDR (0XC0)
/** EP1 Rx address */
#define USB_EP1_RX_ADDR (0XD0)
/** EP2 Tx address */
#define USB_EP2_TX_ADDR (0XE0)
/** EP2 Rx address */
#define USB_EP2_RX_ADDR (0XF0)
/** EP3 Tx address */
#define USB_EP3_TX_ADDR (0X100)
/** EP3 Rx address */
#define USB_EP3_RX_ADDR (0X110)
首先端点buffer地址为什么要从0x40开始,因为这个MCU有8个端点,每个端点又分输入输出。
而且每个端点有buffer起始地址和数据长度空间都占4字节。使用1个输入端点就要增加8字节,1个输出端点也要8字节。
本次使用了端点0,1,2,3。所以地址至少要7*8=56字节即0x38。后面地址就要根据每个端点的数据包长度来修改buffer地址。
最后就是按键模拟,及USB数据发送过程处理
- void HidMouse_Proc(void)
- {
-
- static int8_t x = 0;
- static int8_t y = 0;
- uint8_t buffer[8] = {0, 0, 0, 0};
- uint8_t buffer1[8] = {0, 0, 0, 0};
- uint8_t buffer2[4] = {0, 0, 0, 0};
- if(!s_usbConfigStatus)
- {
- return;
- }
- if(g_time_tick == 0)
- {
- g_time_tick = 10;
- /** Right key */
- if(!GPIO_ReadInputBit(GPIOA, GPIO_PIN_0))
- {
- GPIOE->ODATA ^= GPIO_PIN_5;
- x -= 10;
- buffer[5] = 3;
- buffer[6] |= 0x01;
- buffer1[2] = 0x20;
- buffer2[1] = -5;
- }else
- {
- buffer[6] &= ~0x01;
- buffer1[2] = 0;
- buffer2[1] = 0;
- }
-
- /** Left key */
- if(!GPIO_ReadInputBit(GPIOA, GPIO_PIN_1))
- {
- GPIOE->ODATA ^= GPIO_PIN_6;
- x += 10;
- buffer[5] = 7;
- buffer[6] |= 0x02;
- buffer1[3] = 0x21;
- buffer2[1] = 5;
- }else
- {
- buffer[6] &= ~0x02;
- buffer1[3] = 0;
- }
-
- buffer[0] = x;
- buffer[1] = y;
- if(s_statusEP_in[1])
- {
- s_statusEP_in[1] = 0; //send over flag
- USBD_WriteDataToEP(USBD_EP_1, buffer, sizeof(buffer)); //write data to buffer
- USBD_SetEPTxStatus(USBD_EP_1, USBD_EP_STATUS_VALID); //send data valid
- }
-
- if(s_statusEP_in[2])
- {
- s_statusEP_in[2] = 0; //send over flag
- USBD_WriteDataToEP(USBD_EP_2, buffer1, sizeof(buffer1)); //write data to buffer
- USBD_SetEPTxStatus(USBD_EP_2, USBD_EP_STATUS_VALID); //send data valid
- }
-
- if(s_statusEP_in[3])
- {
- s_statusEP_in[3] = 0; //send over flag
- USBD_WriteDataToEP(USBD_EP_3, buffer2, sizeof(buffer2)); //write data to buffer
- USBD_SetEPTxStatus(USBD_EP_3, USBD_EP_STATUS_VALID); //send data valid
- }
-
- }
- }
程序: