本帖最后由 袁胜富 于 2023-3-9 22:48 编辑
一、概述
在自动化测试项目中,在启动测试按钮等功能的实现具有一定的抉择,最近做项目一开始的方案是利用串口发数据向下位机读取启动引脚的状态,但是由于系统的实时性响应需要很快,数据不停的发,以及其他操作导致系统不稳定,通信时常出现断开现象,软件改来改去没有得到最大的改善于是就考虑使用主板冗余的一个USB端口开模拟HIDKeyboar的方式来模拟键盘按键按下,然后软件采用全局热键的方式来进行设备测试的启停,经过这么一改,目前来说,没有发现问题。所以USB模拟HIDKeyboard用在一些测试场合是很不错的一个选择。借此机会,向大家介绍一下APM32F107VCT6使用USB模拟键盘。
二、实现过程
USB开发方面的例程极海半导体官网有相关的例程,HIDKeyBoard是在HID例程修改而来的。
usbd_hidkeyboard.h头文件
/* Define to prevent recursive inclusion */
#ifndef _USBD_HIDKEYBOARD_H_
#define _USBD_HIDKEYBOARD_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_HID_Class
@{
*/
/** @defgroup USBD_HID_Macros Macros
@{
*/
#define USBD_HID_KEYBOARD_REPORT_DESC_SIZE 62
#define USBD_HID_KEYBOARDDESC_SIZE 9
#define USBD_HID_KEYBOARDFS_INTERVAL 10
#define USBD_HID_KEYBOARDHS_INTERVAL 7
#define USBD_HID_KEYBOARDIN_EP_ADDR 0x81
#define USBD_HID_KEYBOARDIN_EP_SIZE 0x08
#define USBD_HID_KEYBOARDFS_MP_SIZE 0x40
#define USBD_CLASS_SET_IDLE 0x0A
#define USBD_CLASS_GET_IDLE 0x02
#define USBD_CLASS_SET_REPORT 0x09
#define USBD_CLASS_GET_REPORT 0x01
#define USBD_CLASS_SET_PROTOCOL 0x0B
#define USBD_CLASS_GET_PROTOCOL 0x03
/**@} end of group USBD_HID_Macros*/
/** @defgroup USBD_HID_Enumerates Enumerates
@{
*/
/**
* @brief HID state type
*/
typedef enum
{
USBD_HID_IDLE,
USBD_HID_BUSY,
} USBD_HID_STATE_T;
/**@} end of group USBD_HID_Enumerates*/
/** @defgroup USBD_HID_Structures Structures
@{
*/
/**
* @brief HID information management
*/
typedef struct
{
uint8_t state;
uint8_t epInAddr;
uint8_t altSettingStatus;
uint8_t idleStatus;
uint8_t protocol;
} USBD_HID_INFO_T;
extern USBD_CLASS_T USBD_HID_CLASS;
/**@} end of group USBD_HID_Structures*/
/** @defgroup USBD_HID_Functions Functions
@{
*/
uint8_t USBD_HID_ReadInterval(USBD_INFO_T* usbInfo);
USBD_STA_T USBD_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length);
#endif
usbd_hidkeyboard.c源文件
/*!
* @file usbd_hid.c
*
* @brief usb device hid class handler
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_hidkeyboard.h"
#include "usbd_stdReq.h"
#include "usbd_dataXfer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** @addtogroup APM32_USB_Library
@{
*/
/** @addtogroup USBD_HID_Class
@{
*/
/** @defgroup USBD_HID_Functions Functions
@{
*/
static USBD_STA_T USBD_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex);
static USBD_STA_T USBD_HID_SOFHandler(USBD_INFO_T* usbInfo);
static USBD_STA_T USBD_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req);
static USBD_STA_T USBD_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum);
static USBD_DESC_INFO_T USBD_HID_ReportDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_HID_DescHandler(uint8_t usbSpeed);
/**@} end of group USBD_HID_Functions */
/** @defgroup USBD_HID_Structures Structures
@{
*/
/* HID class handler */
USBD_CLASS_T USBD_HID_CLASS =
{
/* Class handler */
"Class HID",
NULL,
USBD_HID_ClassInitHandler,
USBD_HID_ClassDeInitHandler,
USBD_HID_SOFHandler,
/* Control endpoint */
USBD_HID_SetupHandler,
NULL,
NULL,
/* Specific endpoint */
USBD_HID_DataInHandler,
NULL,
NULL,
NULL,
};
/**@} end of group USBD_HID_Structures*/
/** @defgroup USBD_HID_Variables Variables
@{
*/
/**
* @brief HID descriptor
*/
uint8_t USBD_HIDDesc[USBD_HID_KEYBOARDDESC_SIZE] =
{
/* bLength */
0x09,
/* bDescriptorType: HID */
USBD_DESC_HID,
/* bcdHID */
0x11, 0x01,
/* bCountryCode */
0x00,
/* bNumDescriptors */
0x01,
/* bDescriptorType */
USBD_DESC_HID_REPORT,
/* wItemLength */
USBD_HID_KEYBOARD_REPORT_DESC_SIZE & 0xFF, USBD_HID_KEYBOARD_REPORT_DESC_SIZE >> 8,
};
/**
* @brief HID mouse report descriptor
*/
uint8_t USBD_HIDReportDesc[USBD_HID_KEYBOARD_REPORT_DESC_SIZE] =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xE0, // Usage Minimum (224)
0x29, 0xE7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data,Variable,Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant)
0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x03, // Usage Maximum (3)
0x91, 0x02, // Output (Data,Variable,Absolute)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x91, 0x01, // Output (Constant,Array,Absolute)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0x91, // Usage Maximum (145)
0x81, 0x00, // Input(Data,Array,Absolute)
0xC0 // End Collection */
};
/**@} end of group USBD_HID_Variables*/
/** @defgroup USBD_HID_Functions Functions
@{
*/
/*!
* @brief USB device HID configuration handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_ClassInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID;
/* Link class data */
usbInfo->devClass[usbInfo->classID]->classData = (USBD_HID_INFO_T*)malloc(sizeof(USBD_HID_INFO_T));
usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
memset(usbDevHID, 0, sizeof(USBD_HID_INFO_T));
USBD_USR_Debug("USBD_HID_INFO_T size %d\r\n", sizeof(USBD_HID_INFO_T));
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
usbDevHID->epInAddr = USBD_HID_KEYBOARDIN_EP_ADDR;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_HID_KEYBOARDFS_INTERVAL;
}
else
{
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = USBD_HID_KEYBOARDHS_INTERVAL;
}
/* Open endpoint */
USBD_EP_OpenCallback(usbInfo, usbDevHID->epInAddr, EP_TYPE_INTERRUPT, USBD_HID_KEYBOARDIN_EP_SIZE);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = ENABLE;
usbDevHID->state = USBD_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device HID reset handler
*
* @param usbInfo: usb device information
*
* @param cfgIndex: configuration index
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_ClassDeInitHandler(USBD_INFO_T* usbInfo, uint8_t cfgIndex)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
/* Close HID EP */
USBD_EP_CloseCallback(usbInfo, usbDevHID->epInAddr);
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].interval = 0;
usbInfo->devEpIn[usbDevHID->epInAddr & 0x0F].useStatus = DISABLE;
if (usbInfo->devClass[usbInfo->classID]->classData != NULL)
{
free(usbInfo->devClass[usbInfo->classID]->classData);
usbInfo->devClass[usbInfo->classID]->classData = 0;
}
return usbStatus;
}
/*!
* @brief USB device HID SOF handler
*
* @param usbInfo: usb device information
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_SOFHandler(USBD_INFO_T* usbInfo)
{
USBD_STA_T usbStatus = USBD_BUSY;
return usbStatus;
}
/*!
* @brief USB device HID SETUP handler
*
* @param usbInfo: usb device information
*
* @param req: setup request
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_SetupHandler(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
USBD_DESC_INFO_T descInfo;
uint8_t request;
uint8_t reqType;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
uint16_t wLength = req->DATA_FIELD.wLength[0] | req->DATA_FIELD.wLength[1] << 8;
uint16_t status = 0x0000;
if (usbDevHID == NULL)
{
USBD_USR_LOG("usbDevHID is NULL");
return USBD_FAIL;
}
request = req->DATA_FIELD.bRequest;
reqType = usbInfo->reqSetup.DATA_FIELD.bmRequest.REQ_TYPE_B.type;
switch (reqType)
{
case USBD_REQ_TYPE_STANDARD:
switch (request)
{
/* HID descriptor */
case USBD_STD_GET_DESCRIPTOR:
switch (req->DATA_FIELD.wValue[1])
{
case USBD_DESC_HID_REPORT:
descInfo = USBD_HID_ReportDescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
case USBD_DESC_HID:
descInfo = USBD_HID_DescHandler(usbInfo->devSpeed);
descInfo.size = descInfo.size < wLength ? descInfo.size : wLength;
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
if (descInfo.desc != NULL)
{
USBD_CtrlSendData(usbInfo, descInfo.desc, descInfo.size);
}
break;
case USBD_STD_GET_STATUS:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&status, 2);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_GET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->altSettingStatus, 1);
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_SET_INTERFACE:
if (usbInfo->devState == USBD_DEV_CONFIGURE)
{
usbDevHID->altSettingStatus = wValue;
}
else
{
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
}
break;
case USBD_STD_CLEAR_FEATURE:
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_CLASS:
switch (request)
{
case USBD_CLASS_SET_IDLE:
usbDevHID->idleStatus = req->DATA_FIELD.wValue[1];
break;
case USBD_CLASS_GET_IDLE:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->idleStatus, 1);
break;
case USBD_CLASS_SET_PROTOCOL:
usbDevHID->protocol = req->DATA_FIELD.wValue[0];
break;
case USBD_CLASS_GET_PROTOCOL:
USBD_CtrlSendData(usbInfo, (uint8_t*)&usbDevHID->protocol, 1);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
}
break;
case USBD_REQ_TYPE_VENDOR:
USBD_REQ_CtrlError(usbInfo, req);
usbStatus = USBD_FAIL;
break;
default:
usbStatus = USBD_FAIL;
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
/*!
* @brief USB device HID IN data handler
*
* @param usbInfo: usb device information
*
* @param epNum: endpoint number
*
* @retval USB device operation status
*/
static USBD_STA_T USBD_HID_DataInHandler(USBD_INFO_T* usbInfo, uint8_t epNum)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
usbDevHID->state = USBD_HID_IDLE;
return usbStatus;
}
/*!
* @brief USB device HID report descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_HID_ReportDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDReportDesc;
descInfo.size = sizeof(USBD_HIDReportDesc);
return descInfo;
}
/*!
* @brief USB device HID descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_HID_DescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_HIDDesc;
descInfo.size = sizeof(USBD_HIDDesc);
return descInfo;
}
/*!
* @brief USB device HID send report descriptor
*
* @param usbInfo: usb device information
*
* @param report: report buffer
*
* @param length: report data length
*
* @retval usb descriptor information
*/
USBD_STA_T USBD_HID_TxReport(USBD_INFO_T* usbInfo, uint8_t* report, uint16_t length)
{
USBD_STA_T usbStatus = USBD_OK;
USBD_HID_INFO_T* usbDevHID = (USBD_HID_INFO_T*)usbInfo->devClass[usbInfo->classID]->classData;
if (usbDevHID == NULL)
{
return USBD_FAIL;
}
switch (usbInfo->devState)
{
case USBD_DEV_CONFIGURE:
if (usbDevHID->state == USBD_HID_IDLE)
{
usbDevHID->state = USBD_HID_BUSY;
USBD_EP_TransferCallback(usbInfo, usbDevHID->epInAddr, report, length);
}
break;
default:
break;
}
return usbStatus;
}
/*!
* @brief USB device HID read interval
*
* @param usbInfo: usb device information
*
* @retval usb interval
*/
uint8_t USBD_HID_ReadInterval(USBD_INFO_T* usbInfo)
{
uint8_t interval;
if (usbInfo->devSpeed == USBD_SPEED_FS)
{
interval = USBD_HID_KEYBOARDFS_INTERVAL;
}
else
{
interval = ((1 << (USBD_HID_KEYBOARDHS_INTERVAL - 1)) / 8);
}
return interval;
}usbd_descriptor.h头文件
/*!
* @file usbd_descriptor.h
*
* @brief usb device descriptor
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USBD_DESCRIPTOR_H_
#define _USBD_DESCRIPTOR_H_
/* Includes */
#include "usbd_core.h"
/** @addtogroup Examples
* @brief OTGD HID examples
@{
*/
/** @addtogroup OTGD_HID
@{
*/
/** @defgroup OTGD_HID_Macros Macros
@{
*/
#define USBD_DEVICE_DESCRIPTOR_SIZE 18
#define USBD_CONFIG_DESCRIPTOR_SIZE 34
#define USBD_SERIAL_STRING_SIZE 26
#define USBD_LANGID_STRING_SIZE 4
#define USBD_DEVICE_QUALIFIER_DESCRIPTOR_SIZE 10
#define USBD_BOS_DESCRIPTOR_SIZE 12
#define USBD_DEVICE_CAPABILITY_TYPE 0x10
#define USBD_20_EXTENSION_TYPE 0x02
#define USBD_HID_ITF_CLASS_ID 0x03
#define USBD_HID_SUB_CLASS_BOOT 0x01
#define USBD_HID_SUB_CLASS_NBOOT 0x00
#define USBD_HID_ITF_PORTOCOL_NONE 0x00
#define USBD_HID_ITF_PORTOCOL_KEYBOARD 0x01
#define USBD_HID_ITF_PORTOCOL_MOUSE 0x02
/**@} end of group OTGD_HID_Macros*/
/** @defgroup OTGD_HID_Variables Variables
@{
*/
extern USBD_DESC_T USBD_DESC_FS;
/**@} end of group OTGD_HID_Variables*/
/** @defgroup OTGD_HID_Functions Functions
@{
*/
/**@} end of group OTGD_HID_Functions */
/**@} end of group OTGD_HID */
/**@} end of group Examples */
#endif
usbd_descriptor.c头文件
/*!
* @file usbd_descriptor.c
*
* @brief usb device descriptor configuration
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usbd_descriptor.h"
#include "usbd_hidkeyboard.h"
#include <stdio.h>
#include <string.h>
/** @addtogroup Examples
* @brief OTGD HID examples
@{
*/
/** @addtogroup OTGD_HID
@{
*/
/** @defgroup OTGD_HID_Macros Macros
@{
*/
#define USBD_GEEHY_VID 12619
#define USBD_FS_PID 1001
#define USBD_LANGID_STR 0x0409
#define USBD_MANUFACTURER_STR "Geehy"
#define USBD_PRODUCT_STR "APM32 HIDKeyboard"
#define USBD_CONFIGURATION_STR "HIDKeyboard Config"
#define USBD_INTERFACE_STR "HIDKeyboard Interface"
/**@} end of group OTGD_HID_Macros*/
/** @defgroup OTGD_HID_Functions Functions
@{
*/
static USBD_DESC_INFO_T USBD_FS_DeviceDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_FS_ConfigDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_FS_InterfaceDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_FS_LangIdDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_FS_ManufacturerDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_FS_ProductDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_FS_SerialDescHandler(uint8_t usbSpeed);
#if USBD_SUP_LPM
static USBD_DESC_INFO_T USBD_FS_BosDescHandler(uint8_t usbSpeed);
#endif
static USBD_DESC_INFO_T USBD_OtherSpeedConfigDescHandler(uint8_t usbSpeed);
static USBD_DESC_INFO_T USBD_DevQualifierDescHandler(uint8_t usbSpeed);
/**@} end of group OTGD_HID_Functions */
/** @defgroup OTGD_HID_Structures Structures
@{
*/
/* USB device descripotr handler */
USBD_DESC_T USBD_DESC_FS =
{
"HID Keyborad Descriptor",
USBD_FS_DeviceDescHandler,
USBD_FS_ConfigDescHandler,
USBD_FS_InterfaceDescHandler,
USBD_FS_LangIdDescHandler,
USBD_FS_ManufacturerDescHandler,
USBD_FS_ProductDescHandler,
USBD_FS_SerialDescHandler,
#if USBD_SUP_LPM
USBD_FS_BosDescHandler,
#endif
NULL,
USBD_OtherSpeedConfigDescHandler,
USBD_DevQualifierDescHandler,
};
/**@} end of group OTGD_HID_Structures*/
/** @defgroup OTGD_HID_Variables Variables
@{
*/
/**
* @brief Device descriptor
*/
uint8_t USBD_DeviceDesc[USBD_DEVICE_DESCRIPTOR_SIZE] =
{
/* bLength */
0x12,
/* bDescriptorType */
USBD_DESC_DEVICE,
/* bcdUSB */
#if USBD_SUP_LPM
0x01, /*<! For resume test of USBCV3.0. Only support LPM USB device */
#else
0x00,
#endif
0x02,
/* bDeviceClass */
0x00,
/* bDeviceSubClass */
0x00,
/* bDeviceProtocol */
0x00,
/* bMaxPacketSize */
USBD_EP0_PACKET_MAX_SIZE,
/* idVendor */
USBD_GEEHY_VID & 0xFF, USBD_GEEHY_VID >> 8,
/* idProduct */
USBD_FS_PID & 0xFF, USBD_FS_PID >> 8,
/* bcdDevice = 2.00 */
0x00, 0x02,
/* Index of string descriptor describing manufacturer */
USBD_DESC_STR_MFC,
/* Index of string descriptor describing product */
USBD_DESC_STR_PRODUCT,
/* Index of string descriptor describing the device serial number */
USBD_DESC_STR_SERIAL,
/* bNumConfigurations */
USBD_SUP_CONFIGURATION_MAX_NUM,
};
/**
* @brief Configuration descriptor
*/
uint8_t USBD_ConfigDesc[USBD_CONFIG_DESCRIPTOR_SIZE] =
{
/* bLength */
0x09,
/* bDescriptorType */
USBD_DESC_CONFIGURATION,
/* wTotalLength */
USBD_CONFIG_DESCRIPTOR_SIZE & 0xFF,
USBD_CONFIG_DESCRIPTOR_SIZE >> 8,
/* bNumInterfaces */
0x01,
/* bConfigurationValue */
0x01,
/* iConfiguration */
0x00,
/* bmAttributes */
#if USBD_SUP_SELF_PWR
0xE0,
#else
0xA0,
#endif
/* MaxPower */
0x32,
/* HID Keyboard Interface */
/* bLength */
0x09,
/* bDescriptorType */
USBD_DESC_INTERFACE,
/* bInterfaceNumber */
0x00,
/* bAlternateSetting */
0x00,
/* bNumEndpoints */
0x01,
/* bInterfaceClass */
USBD_HID_ITF_CLASS_ID,
/* bInterfaceSubClass */
USBD_HID_SUB_CLASS_BOOT,
/* bInterfaceProtocol */
USBD_HID_ITF_PORTOCOL_KEYBOARD,
/* iInterface */
0x00,
/* HID descriptor of Keyboard */
/* bLength */
0x09,
/* bDescriptorType: HID */
USBD_DESC_HID,
/* bcdHID */
0x11, 0x01,
/* bCountryCode */
0x00,
/* bNumDescriptors */
0x01,
/* bDescriptorType */
USBD_DESC_HID_REPORT,
/* wItemLength */
USBD_HID_KEYBOARD_REPORT_DESC_SIZE & 0xFF, USBD_HID_KEYBOARD_REPORT_DESC_SIZE >> 8,
/* HID Keyboard Endpoint */
/* bLength */
0x07,
/* bDescriptorType: Endpoint */
USBD_DESC_ENDPOINT,
/* bEndpointAddress */
USBD_HID_KEYBOARDIN_EP_ADDR,
/* bmAttributes */
0x03,
/* wMaxPacketSize: */
USBD_HID_KEYBOARDIN_EP_SIZE & 0xFF,
USBD_HID_KEYBOARDIN_EP_SIZE >> 8,
/* bInterval: */
USBD_HID_KEYBOARDFS_INTERVAL,
};
/**
* @brief Other speed configuration descriptor
*/
uint8_t USBD_OtherSpeedCfgDesc[USBD_CONFIG_DESCRIPTOR_SIZE] =
{
/* bLength */
0x09,
/* bDescriptorType */
USBD_DESC_OTHER_SPEED,
/* wTotalLength */
USBD_CONFIG_DESCRIPTOR_SIZE & 0xFF,
USBD_CONFIG_DESCRIPTOR_SIZE >> 8,
/* bNumInterfaces */
0x01,
/* bConfigurationValue */
0x01,
/* iConfiguration */
0x00,
/* bmAttributes */
#if USBD_SUP_SELF_PWR
0xE0,
#else
0xA0,
#endif
/* MaxPower */
0x32,
/* HID Mouse Interface */
/* bLength */
0x09,
/* bDescriptorType */
USBD_DESC_INTERFACE,
/* bInterfaceNumber */
0x00,
/* bAlternateSetting */
0x00,
/* bNumEndpoints */
0x01,
/* bInterfaceClass */
USBD_HID_ITF_CLASS_ID,
/* bInterfaceSubClass */
USBD_HID_SUB_CLASS_BOOT,
/* bInterfaceProtocol */
USBD_HID_ITF_PORTOCOL_MOUSE,
/* iInterface */
0x00,
/* HID descriptor of Mouse */
/* bLength */
0x09,
/* bDescriptorType: HID */
USBD_DESC_HID,
/* bcdHID */
0x11, 0x01,
/* bCountryCode */
0x00,
/* bNumDescriptors */
0x01,
/* bDescriptorType */
USBD_DESC_HID_REPORT,
/* wItemLength */
USBD_HID_KEYBOARD_REPORT_DESC_SIZE & 0xFF, USBD_HID_KEYBOARD_REPORT_DESC_SIZE >> 8,
/* HID Mouse Endpoint */
/* bLength */
0x07,
/* bDescriptorType: Endpoint */
USBD_DESC_ENDPOINT,
/* bEndpointAddress */
USBD_HID_KEYBOARDIN_EP_ADDR,
/* bmAttributes */
0x03,
/* wMaxPacketSize: */
USBD_HID_KEYBOARDIN_EP_SIZE & 0xFF,
USBD_HID_KEYBOARDIN_EP_SIZE >> 8,
/* bInterval: */
USBD_HID_KEYBOARDFS_INTERVAL,
};
#if USBD_SUP_LPM
/**
* @brief BOS descriptor
*/
uint8_t USBD_BosDesc[USBD_BOS_DESCRIPTOR_SIZE] =
{
/* bLength */
0x05,
/* bDescriptorType */
USBD_DESC_BOS,
/* wtotalLength */
0x0C, 0x00,
/* bNumDeviceCaps */
0x01,
/* Device Capability */
/* bLength */
0x07,
/* bDescriptorType */
USBD_DEVICE_CAPABILITY_TYPE,
/* bDevCapabilityType */
USBD_20_EXTENSION_TYPE,
/* bmAttributes */
0x02, 0x02, 0x00, 0x00,
};
#endif
/**
* @brief Serial string descriptor
*/
uint8_t USBD_SerialStrDesc[USBD_SERIAL_STRING_SIZE] =
{
USBD_SERIAL_STRING_SIZE,
USBD_DESC_STRING,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'0', 0,
'1', 0
};
/**
* @brief Language ID string descriptor
*/
uint8_t USBD_LandIDStrDesc[USBD_LANGID_STRING_SIZE] =
{
/* Size */
USBD_LANGID_STRING_SIZE,
/* bDescriptorType */
USBD_DESC_STRING,
USBD_LANGID_STR & 0xFF, USBD_LANGID_STR >> 8
};
/**
* @brief Device qualifier descriptor
*/
uint8_t USBD_DevQualifierDesc[USBD_DEVICE_QUALIFIER_DESCRIPTOR_SIZE] =
{
/* Size */
USBD_DEVICE_QUALIFIER_DESCRIPTOR_SIZE,
/* bDescriptorType */
USBD_DESC_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
USBD_HID_KEYBOARDFS_MP_SIZE, /* In FS device*/
0x01,
0x00,
};
/**@} end of group OTGD_HID_Variables*/
/** @defgroup OTGD_HID_Functions Functions
@{
*/
/*!
* @brief USB device convert ascii string descriptor to unicode format
*
* @param desc : descriptor string
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_DESC_Ascii2Unicode(uint8_t* desc)
{
USBD_DESC_INFO_T descInfo;
uint8_t* buffer;
uint8_t str[USBD_SUP_STR_DESC_MAX_NUM];
uint8_t* unicode = str;
uint16_t length;
uint8_t index = 0;
if (desc == NULL)
{
descInfo.desc = NULL;
descInfo.size = 0;
}
else
{
buffer = desc;
length = (strlen((char*)buffer) * 2) + 2;
/* Get unicode descriptor */
unicode[index] = length;
index++;
unicode[index] = USBD_DESC_STRING;
index++;
while (*buffer != '\0')
{
unicode[index] = *buffer;
buffer++;
index++;
unicode[index] = 0x00;
index++;
}
}
descInfo.desc = unicode;
descInfo.size = length;
return descInfo;
}
/*!
* @brief USB device FS device descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_DeviceDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_DeviceDesc;
descInfo.size = sizeof(USBD_DeviceDesc);
return descInfo;
}
/*!
* @brief USB device FS configuration descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_ConfigDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_ConfigDesc;
descInfo.size = sizeof(USBD_ConfigDesc);
return descInfo;
}
#if USBD_SUP_LPM
/*!
* @brief USB device FS BOS descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_BosDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_BosDesc;
descInfo.size = sizeof(USBD_BosDesc);
return descInfo;
}
#endif
/*!
* @brief USB device FS interface descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_InterfaceDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo = USBD_DESC_Ascii2Unicode((uint8_t*)USBD_INTERFACE_STR);
return descInfo;
}
/*!
* @brief USB device FS LANG ID string descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_LangIdDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_LandIDStrDesc;
descInfo.size = sizeof(USBD_LandIDStrDesc);
return descInfo;
}
/*!
* @brief USB device FS manufacturer string descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_ManufacturerDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo = USBD_DESC_Ascii2Unicode((uint8_t*)USBD_MANUFACTURER_STR);
return descInfo;
}
/*!
* @brief USB device FS product string descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_ProductDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo = USBD_DESC_Ascii2Unicode((uint8_t*)USBD_PRODUCT_STR);
return descInfo;
}
/*!
* @brief USB device FS serial string descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_FS_SerialDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
descInfo.desc = USBD_SerialStrDesc;
descInfo.size = sizeof(USBD_SerialStrDesc);
return descInfo;
}
/*!
* @brief USB device other speed configuration descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_OtherSpeedConfigDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
/* Use FS configuration */
descInfo.desc = USBD_OtherSpeedCfgDesc;
descInfo.size = sizeof(USBD_OtherSpeedCfgDesc);
return descInfo;
}
/*!
* @brief USB device device qualifier descriptor
*
* @param usbSpeed : usb speed
*
* @retval usb descriptor information
*/
static USBD_DESC_INFO_T USBD_DevQualifierDescHandler(uint8_t usbSpeed)
{
USBD_DESC_INFO_T descInfo;
/* Use FS configuration */
descInfo.desc = USBD_DevQualifierDesc;
descInfo.size = sizeof(USBD_DevQualifierDesc);
return descInfo;
}
usb_device_user.h头文件
/*!
* @file usb_device_user.h
*
* @brief usb device user function
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Define to prevent recursive inclusion */
#ifndef _USB_DEVICE_USER_H_
#define _USB_DEVICE_USER_H_
/* Includes */
#include "apm32f10x.h"
#include "usbd_core.h"
/** @addtogroup Examples
* @brief OTGD HID examples
@{
*/
/** @addtogroup OTGD_HID
@{
*/
/** @defgroup OTGD_HID_Enumerates Enumerates
@{
*/
/**
* @brief USB device application status
*/
typedef enum
{
USBD_APP_IDLE,
USBD_APP_SUSPEND,
USBD_APP_READY,
} USBD_APP_STA_T;
/**@} end of group OTGD_HID_Enumerates*/
/** @defgroup OTGD_HID_Variables Variables
@{
*/
extern USBD_APP_STA_T gUsbDevAppStatus;
extern USBD_INFO_T gUsbDeviceFS;
/**@} end of group OTGD_HID_Variables*/
/** @defgroup OTGD_HID_Functions Functions
@{
*/
void USB_DeviceInit(void);
void USB_DeviceReset(void);
void USB_DevUserApplication(void);
/**@} end of group OTGD_HID_Functions */
/**@} end of group OTGD_HID */
/**@} end of group Examples */
#endif
usb_device_user.c源文件
/*!
* @file usb_device_user.c
*
* @brief usb device user configuration
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "usb_device_user.h"
#include "usbd_descriptor.h"
#include "usbd_hid.h"
#include <stdio.h>
/** @addtogroup Examples
* @brief OTGD HID examples
@{
*/
/** @addtogroup OTGD_HID
@{
*/
/** @defgroup OTGD_HID_Variables Variables
@{
*/
USBD_INFO_T gUsbDeviceFS;
USBD_APP_STA_T gUsbDevAppStatus = USBD_APP_IDLE;
/**@} end of group OTGD_HID_Variables*/
/** @defgroup OTGD_HID_Functions Functions
@{
*/
/*!
* @brief User application
*
* @param None
*
* @retval None
*/
__weak void USB_DevUserApplication(void)
{
static USBD_APP_STA_T preAppStatus = USBD_APP_IDLE;
uint8_t status = gUsbDevAppStatus;
if (preAppStatus != gUsbDevAppStatus)
{
switch (status)
{
case USBD_APP_SUSPEND:
USBD_USR_LOG("USBD_APP_SUSPEND");
break;
case USBD_APP_READY:
USBD_USR_LOG("USBD_APP_READY");
break;
}
preAppStatus = gUsbDevAppStatus;
}
}
/*!
* @brief USB device user handler
*
* @param usbInfo
*
* @param userStatus
*
* @retval None
*/
static void USB_DevUserHandler(USBD_INFO_T* usbInfo, uint8_t userStatus)
{
switch (userStatus)
{
case USBD_USER_RESET:
break;
case USBD_USER_RESUME:
break;
case USBD_USER_SUSPEND:
gUsbDevAppStatus = USBD_APP_SUSPEND;
break;
case USBD_USER_CONNECT:
break;
case USBD_USER_DISCONNECT:
break;
case USBD_USER_ERROR:
USBD_USR_Debug("User error");
break;
default:
break;
}
}
/*!
* @brief USB device init
*
* @param None
*
* @retval None
*/
void USB_DeviceInit(void)
{
/* USB device and class init */
USBD_Init(&gUsbDeviceFS, USBD_SPEED_FS, &USBD_DESC_FS, &USBD_HID_CLASS, USB_DevUserHandler);
}
/*!
* @brief USB device reset
*
* @param None
*
* @retval None
*/
void USB_DeviceReset(void)
{
USBD_DeInit(&gUsbDeviceFS);
}
/**@} end of group OTGD_HID_Functions */
/**@} end of group OTGD_HID */
/**@} end of group Examples */
Keyboard.h头文件
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include "usbd_hidkeyboard.h"
//================================================================================
//================================================================================
// Keyboard
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
typedef struct
{
void (*begin)(void);
size_t (*write)(uint8_t k);
size_t (*press)(uint8_t k);
size_t (*release)(uint8_t k);
void (*releaseAll)(void);
void (*printf)(char *fmt,...);
}_KeyBorad;
extern _KeyBorad KeyBorad;
// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct {
uint8_t modifiers;
uint8_t reserved;
uint8_t keys[6];
} KeyReport;
void sendReport(KeyReport *keys);
void begin(void);
size_t write(uint8_t k);
size_t press(uint8_t k);
size_t release(uint8_t k);
void releaseAll(void);
#endif/*KEYBOARD_H*/
Keyboard.c源文件
#include "Keyboard.h"
#include "String.h"
#include "Stdlib.h"
#include "Stdio.h"
#include "Stdarg.h"
#include "board.h"
#include "bsp_delay.h"
#include "apm32f10x_misc.h"
#include "apm32f10x_usart.h"
#include "usb_device_user.h"
#include "usbd_hidkeyboard.h"
#include <stdio.h>
//================================================================================
//================================================================================
// Keyboard
/**
* @brief User application state
*/
KeyReport _keyReport;
void begin(void)
{
/* Init USB device */
USB_DeviceInit();
}
void sendReport(KeyReport *keys)
{
uint8_t buf[8] = {keys->modifiers, keys->reserved, keys->keys[0], keys->keys[1],
keys->keys[2], keys->keys[3], keys->keys[4], keys->keys[5]
};
USBD_HID_TxReport(&gUsbDeviceFS, (uint8_t*)buf, 8);/*端点上传数据*/
//delay required to prevent persistent key when call print
APM_DelayMs(10);
}
//extern const uint8_t _asciimap[128] PROGMEM;
#define SHIFT 0x80
const uint8_t _asciimap[128] = {
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e | SHIFT, // !
0x34 | SHIFT, // "
0x20 | SHIFT, // #
0x21 | SHIFT, // $
0x22 | SHIFT, // %
0x24 | SHIFT, // &
0x34, // '
0x26 | SHIFT, // (
0x27 | SHIFT, // )
0x25 | SHIFT, // *
0x2e | SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33 | SHIFT, // :
0x33, // ;
0x36 | SHIFT, // <
0x2e, // =
0x37 | SHIFT, // >
0x38 | SHIFT, // ?
0x1f | SHIFT, // @
0x04 | SHIFT, // A
0x05 | SHIFT, // B
0x06 | SHIFT, // C
0x07 | SHIFT, // D
0x08 | SHIFT, // E
0x09 | SHIFT, // F
0x0a | SHIFT, // G
0x0b | SHIFT, // H
0x0c | SHIFT, // I
0x0d | SHIFT, // J
0x0e | SHIFT, // K
0x0f | SHIFT, // L
0x10 | SHIFT, // M
0x11 | SHIFT, // N
0x12 | SHIFT, // O
0x13 | SHIFT, // P
0x14 | SHIFT, // Q
0x15 | SHIFT, // R
0x16 | SHIFT, // S
0x17 | SHIFT, // T
0x18 | SHIFT, // U
0x19 | SHIFT, // V
0x1a | SHIFT, // W
0x1b | SHIFT, // X
0x1c | SHIFT, // Y
0x1d | SHIFT, // Z
0x2f, // [
0x31, // bslash
0x23 | SHIFT, // ^
0x2d | SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f | SHIFT, // {
0x31 | SHIFT, // |
0x30 | SHIFT, // }
0x35 | SHIFT, // ~
0 // DEL
};
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
size_t press(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1 << (k - 128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i = 0; i < 6; i++) {
if (_keyReport.keys == 0x00) {
_keyReport.keys = k;
break;
}
}
if (i == 6) {
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t release(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i = 0; i < 6; i++) {
if (0 != k && _keyReport.keys == k) {
_keyReport.keys = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void releaseAll(void)
{
_keyReport.keys[0] = 0;
_keyReport.keys[1] = 0;
_keyReport.keys[2] = 0;
_keyReport.keys[3] = 0;
_keyReport.keys[4] = 0;
_keyReport.keys[5] = 0;
_keyReport.modifiers = 0;
sendReport(&_keyReport);
}
size_t write(uint8_t c)
{
uint8_t p = press(c); // Keydown
release(c); // Keyup
return p; // just return the result of press() since release() almost always returns 1
}
/**
* 自动格式输出
*/
void print(char *fmt,...)
{
char T1_Bufferr[128];
uint16_t i,j;
va_list ap;
va_start(ap,fmt);
vsprintf(T1_Bufferr,fmt,ap);
va_end(ap);
i=strlen(T1_Bufferr);
for(j=0;j<i;j++)
{
write(T1_Bufferr[j]);
}
}
//结构体初始化
_KeyBorad KeyBorad =
{
begin,
write,
press,
release,
releaseAll,
print
};
main.c源文件
/*!
* @file main.c
*
* @brief Main program body
*
* @version V1.0.0
*
* @date 2023-01-16
*
* @attention
*
* Copyright (C) 2023 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
* The program is only for reference, which is distributed in the hope
* that it will be useful and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
* and limitations under the License.
*/
/* Includes */
#include "board.h"
#include "bsp_delay.h"
#include "apm32f10x_misc.h"
#include "apm32f10x_usart.h"
#include "usb_device_user.h"
#include "usbd_hidkeyboard.h"
#include <stdio.h>
#include "Keyboard.h"
#define DEBUG_USART USART1
/*!
* @brief Main program
*
* @param None
*
* @retval int
*/
int main(void)
{
/* Set the Vector Table base address at 0x08000000 */
NVIC_ConfigVectorTable(NVIC_VECT_TAB_FLASH, 0x0000);
USART_Config_T usartConfigStruct;
/* USART configuration */
USART_ConfigStructInit(&usartConfigStruct);
usartConfigStruct.baudRate = 115200;
usartConfigStruct.mode = USART_MODE_TX_RX;
usartConfigStruct.parity = USART_PARITY_NONE;
usartConfigStruct.stopBits = USART_STOP_BIT_1;
usartConfigStruct.wordLength = USART_WORD_LEN_8B;
usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
/* COM1 init*/
APM_MINI_COMInit(COM1, &usartConfigStruct);
APM_MINI_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);
APM_MINI_PBInit(BUTTON_KEY2, BUTTON_MODE_GPIO);
KeyBorad.begin();
printf("USB Device HIDKeyboard Application\r\n");
while (1)
{
if(!APM_MINI_PBGetState(BUTTON_KEY1))
{
APM_DelayMs(10);
if(!APM_MINI_PBGetState(BUTTON_KEY1))
{
KeyBorad.printf("Button1 Pressed\n");
}
while(!APM_MINI_PBGetState(BUTTON_KEY1));
}
if(!APM_MINI_PBGetState(BUTTON_KEY2))
{
APM_DelayMs(10);
if(!APM_MINI_PBGetState(BUTTON_KEY2))
{
KeyBorad.printf("Button2 Pressed\n");
}
while(!APM_MINI_PBGetState(BUTTON_KEY2));
}
}
}
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch: The characters that need to be send.
*
* @param *f: pointer to a FILE that can recording all information
* needed to control a stream
*
* @retval The characters that need to be send.
*/
int fputc(int ch, FILE* f)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, (uint8_t)ch);
/* wait for the data to be send */
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return (ch);
}
三、测试效果
按钮1按下文本里输入Button1 Pressed,按钮2按下文本里输入Button2 Pressed,如下图所示
打开设备管理器,会有HID Keyboard Device,如下图
四、使用感想
国产芯片越来越好了,USB还是挺不错的,接下来有空再测试其他功能模块。感谢极海半导体和21ic共同开展了此次评测活动,有幸参与其中。
|
共1人点赞
|
很好