CH592_Makefile_Template/profile/hidkbdservice.c
2023-12-21 22:46:50 +07:00

638 lines
20 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : hidkbdservice.c
* Author : WCH
* Version : V1.0
* Date : 2018/12/10
* Description : 键盘服务
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "CONFIG.h"
#include "hidkbdservice.h"
#include "hiddev.h"
#include "battservice.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
// HID service
const uint8_t hidServUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(HID_SERV_UUID), HI_UINT16(HID_SERV_UUID)};
// HID Boot Keyboard Input Report characteristic
const uint8_t hidBootKeyInputUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(BOOT_KEY_INPUT_UUID), HI_UINT16(BOOT_KEY_INPUT_UUID)};
// HID Boot Keyboard Output Report characteristic
const uint8_t hidBootKeyOutputUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(BOOT_KEY_OUTPUT_UUID), HI_UINT16(BOOT_KEY_OUTPUT_UUID)};
// HID Information characteristic
const uint8_t hidInfoUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(HID_INFORMATION_UUID), HI_UINT16(HID_INFORMATION_UUID)};
// HID Report Map characteristic
const uint8_t hidReportMapUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(REPORT_MAP_UUID), HI_UINT16(REPORT_MAP_UUID)};
// HID Control Point characteristic
const uint8_t hidControlPointUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(HID_CTRL_PT_UUID), HI_UINT16(HID_CTRL_PT_UUID)};
// HID Report characteristic
const uint8_t hidReportUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(REPORT_UUID), HI_UINT16(REPORT_UUID)};
// HID Protocol Mode characteristic
const uint8_t hidProtocolModeUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(PROTOCOL_MODE_UUID), HI_UINT16(PROTOCOL_MODE_UUID)};
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
// HID Information characteristic value
static const uint8_t hidInfo[HID_INFORMATION_LEN] = {
LO_UINT16(0x0111), HI_UINT16(0x0111), // bcdHID (USB HID version)
0x00, // bCountryCode
HID_FEATURE_FLAGS // Flags
};
// HID Report Map characteristic value
static const uint8_t hidReportMap[] = {
0x05, 0x01, // Usage Pg (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection: (Application)
//
0x05, 0x07, // Usage Pg (Key Codes)
0x19, 0xE0, // Usage Min (224)
0x29, 0xE7, // Usage Max (231)
0x15, 0x00, // Log Min (0)
0x25, 0x01, // Log Max (1)
//
// Modifier byte
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input: (Data, Variable, Absolute)
//
// Reserved byte
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input: (Constant)
//
// LED report
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Pg (LEDs)
0x19, 0x01, // Usage Min (1)
0x29, 0x05, // Usage Max (5)
0x91, 0x02, // Output: (Data, Variable, Absolute)
//
// LED report padding
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output: (Constant)
//
// Key arrays (6 bytes)
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Log Min (0)
0x25, 0x65, // Log Max (101)
0x05, 0x07, // Usage Pg (Key Codes)
0x19, 0x00, // Usage Min (0)
0x29, 0x65, // Usage Max (101)
0x81, 0x00, // Input: (Data, Array)
//
0xC0 // End Collection
};
// HID report map length
uint16_t hidReportMapLen = sizeof(hidReportMap);
// HID report mapping table
static hidRptMap_t hidRptMap[HID_NUM_REPORTS];
/*********************************************************************
* Profile Attributes - variables
*/
// HID Service attribute
static const gattAttrType_t hidService = {ATT_BT_UUID_SIZE, hidServUUID};
// Include attribute (Battery service)
static uint16_t include = GATT_INVALID_HANDLE;
// HID Information characteristic
static uint8_t hidInfoProps = GATT_PROP_READ;
// HID Report Map characteristic
static uint8_t hidReportMapProps = GATT_PROP_READ;
// HID External Report Reference Descriptor
static uint8_t hidExtReportRefDesc[ATT_BT_UUID_SIZE] =
{LO_UINT16(BATT_LEVEL_UUID), HI_UINT16(BATT_LEVEL_UUID)};
// HID Control Point characteristic
static uint8_t hidControlPointProps = GATT_PROP_WRITE_NO_RSP;
static uint8_t hidControlPoint;
// HID Protocol Mode characteristic
static uint8_t hidProtocolModeProps = GATT_PROP_READ | GATT_PROP_WRITE_NO_RSP;
uint8_t hidProtocolMode = HID_PROTOCOL_MODE_REPORT;
// HID Report characteristic, key input
static uint8_t hidReportKeyInProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
static uint8_t hidReportKeyIn;
static gattCharCfg_t hidReportKeyInClientCharCfg[GATT_MAX_NUM_CONN];
// HID Report Reference characteristic descriptor, key input
static uint8_t hidReportRefKeyIn[HID_REPORT_REF_LEN] =
{HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT};
// HID Report characteristic, LED output
static uint8_t hidReportLedOutProps = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP;
static uint8_t hidReportLedOut;
// HID Report Reference characteristic descriptor, LED output
static uint8_t hidReportRefLedOut[HID_REPORT_REF_LEN] =
{HID_RPT_ID_LED_OUT, HID_REPORT_TYPE_OUTPUT};
// HID Boot Keyboard Input Report
static uint8_t hidReportBootKeyInProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
static uint8_t hidReportBootKeyIn;
static gattCharCfg_t hidReportBootKeyInClientCharCfg[GATT_MAX_NUM_CONN];
// HID Boot Keyboard Output Report
static uint8_t hidReportBootKeyOutProps = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP;
static uint8_t hidReportBootKeyOut;
// Feature Report
static uint8_t hidReportFeatureProps = GATT_PROP_READ | GATT_PROP_WRITE;
static uint8_t hidReportFeature;
// HID Report Reference characteristic descriptor, Feature
static uint8_t hidReportRefFeature[HID_REPORT_REF_LEN] =
{HID_RPT_ID_FEATURE, HID_REPORT_TYPE_FEATURE};
/*********************************************************************
* Profile Attributes - Table
*/
static gattAttribute_t hidAttrTbl[] = {
// HID Service
{
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8_t *)&hidService /* pValue */
},
// Included service (battery)
{
{ATT_BT_UUID_SIZE, includeUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)&include},
// HID Information characteristic declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidInfoProps},
// HID Information characteristic
{
{ATT_BT_UUID_SIZE, hidInfoUUID},
GATT_PERMIT_ENCRYPT_READ,
0,
(uint8_t *)hidInfo},
// HID Control Point characteristic declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidControlPointProps},
// HID Control Point characteristic
{
{ATT_BT_UUID_SIZE, hidControlPointUUID},
GATT_PERMIT_ENCRYPT_WRITE,
0,
&hidControlPoint},
// HID Protocol Mode characteristic declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidProtocolModeProps},
// HID Protocol Mode characteristic
{
{ATT_BT_UUID_SIZE, hidProtocolModeUUID},
GATT_PERMIT_ENCRYPT_READ | GATT_PERMIT_ENCRYPT_WRITE,
0,
&hidProtocolMode},
// HID Report Map characteristic declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidReportMapProps},
// HID Report Map characteristic
{
{ATT_BT_UUID_SIZE, hidReportMapUUID},
GATT_PERMIT_ENCRYPT_READ,
0,
(uint8_t *)hidReportMap},
// HID External Report Reference Descriptor
{
{ATT_BT_UUID_SIZE, extReportRefUUID},
GATT_PERMIT_READ,
0,
hidExtReportRefDesc
},
// HID Report characteristic, key input declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidReportKeyInProps},
// HID Report characteristic, key input
{
{ATT_BT_UUID_SIZE, hidReportUUID},
GATT_PERMIT_ENCRYPT_READ,
0,
&hidReportKeyIn},
// HID Report characteristic client characteristic configuration
{
{ATT_BT_UUID_SIZE, clientCharCfgUUID},
GATT_PERMIT_READ | GATT_PERMIT_ENCRYPT_WRITE,
0,
(uint8_t *)&hidReportKeyInClientCharCfg},
// HID Report Reference characteristic descriptor, key input
{
{ATT_BT_UUID_SIZE, reportRefUUID},
GATT_PERMIT_READ,
0,
hidReportRefKeyIn},
// HID Report characteristic, LED output declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidReportLedOutProps},
// HID Report characteristic, LED output
{
{ATT_BT_UUID_SIZE, hidReportUUID},
GATT_PERMIT_ENCRYPT_READ | GATT_PERMIT_ENCRYPT_WRITE,
0,
&hidReportLedOut},
// HID Report Reference characteristic descriptor, LED output
{
{ATT_BT_UUID_SIZE, reportRefUUID},
GATT_PERMIT_READ,
0,
hidReportRefLedOut},
// HID Boot Keyboard Input Report declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidReportBootKeyInProps},
// HID Boot Keyboard Input Report
{
{ATT_BT_UUID_SIZE, hidBootKeyInputUUID},
GATT_PERMIT_ENCRYPT_READ,
0,
&hidReportBootKeyIn},
// HID Boot Keyboard Input Report characteristic client characteristic configuration
{
{ATT_BT_UUID_SIZE, clientCharCfgUUID},
GATT_PERMIT_READ | GATT_PERMIT_ENCRYPT_WRITE,
0,
(uint8_t *)&hidReportBootKeyInClientCharCfg},
// HID Boot Keyboard Output Report declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidReportBootKeyOutProps},
// HID Boot Keyboard Output Report
{
{ATT_BT_UUID_SIZE, hidBootKeyOutputUUID},
GATT_PERMIT_ENCRYPT_READ | GATT_PERMIT_ENCRYPT_WRITE,
0,
&hidReportBootKeyOut},
// Feature Report declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&hidReportFeatureProps},
// Feature Report
{
{ATT_BT_UUID_SIZE, hidReportUUID},
GATT_PERMIT_ENCRYPT_READ | GATT_PERMIT_ENCRYPT_WRITE,
0,
&hidReportFeature},
// HID Report Reference characteristic descriptor, feature
{
{ATT_BT_UUID_SIZE, reportRefUUID},
GATT_PERMIT_READ,
0,
hidReportRefFeature},
};
// Attribute index enumeration-- these indexes match array elements above
enum
{
HID_SERVICE_IDX, // HID Service
HID_INCLUDED_SERVICE_IDX, // Included Service
HID_INFO_DECL_IDX, // HID Information characteristic declaration
HID_INFO_IDX, // HID Information characteristic
HID_CONTROL_POINT_DECL_IDX, // HID Control Point characteristic declaration
HID_CONTROL_POINT_IDX, // HID Control Point characteristic
HID_PROTOCOL_MODE_DECL_IDX, // HID Protocol Mode characteristic declaration
HID_PROTOCOL_MODE_IDX, // HID Protocol Mode characteristic
HID_REPORT_MAP_DECL_IDX, // HID Report Map characteristic declaration
HID_REPORT_MAP_IDX, // HID Report Map characteristic
HID_EXT_REPORT_REF_DESC_IDX, // HID External Report Reference Descriptor
HID_REPORT_KEY_IN_DECL_IDX, // HID Report characteristic, key input declaration
HID_REPORT_KEY_IN_IDX, // HID Report characteristic, key input
HID_REPORT_KEY_IN_CCCD_IDX, // HID Report characteristic client characteristic configuration
HID_REPORT_REF_KEY_IN_IDX, // HID Report Reference characteristic descriptor, key input
HID_REPORT_LED_OUT_DECL_IDX, // HID Report characteristic, LED output declaration
HID_REPORT_LED_OUT_IDX, // HID Report characteristic, LED output
HID_REPORT_REF_LED_OUT_IDX, // HID Report Reference characteristic descriptor, LED output
HID_BOOT_KEY_IN_DECL_IDX, // HID Boot Keyboard Input Report declaration
HID_BOOT_KEY_IN_IDX, // HID Boot Keyboard Input Report
HID_BOOT_KEY_IN_CCCD_IDX, // HID Boot Keyboard Input Report characteristic client characteristic configuration
HID_BOOT_KEY_OUT_DECL_IDX, // HID Boot Keyboard Output Report declaration
HID_BOOT_KEY_OUT_IDX, // HID Boot Keyboard Output Report
HID_FEATURE_DECL_IDX, // Feature Report declaration
HID_FEATURE_IDX, // Feature Report
HID_REPORT_REF_FEATURE_IDX // HID Report Reference characteristic descriptor, feature
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
/*********************************************************************
* PROFILE CALLBACKS
*/
// Service Callbacks
gattServiceCBs_t hidKbdCBs = {
HidDev_ReadAttrCB, // Read callback function pointer
HidDev_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn Hid_AddService
*
* @brief Initializes the HID Service by registering
* GATT attributes with the GATT server.
*
* @return Success or Failure
*/
bStatus_t Hid_AddService(void)
{
uint8_t status = SUCCESS;
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, hidReportKeyInClientCharCfg);
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, hidReportBootKeyInClientCharCfg);
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService(hidAttrTbl, GATT_NUM_ATTRS(hidAttrTbl), GATT_MAX_ENCRYPT_KEY_SIZE, &hidKbdCBs);
// Set up included service
Batt_GetParameter(BATT_PARAM_SERVICE_HANDLE,
&GATT_INCLUDED_HANDLE(hidAttrTbl, HID_INCLUDED_SERVICE_IDX));
// Construct map of reports to characteristic handles
// Each report is uniquely identified via its ID and type
// Key input report
hidRptMap[0].id = hidReportRefKeyIn[0];
hidRptMap[0].type = hidReportRefKeyIn[1];
hidRptMap[0].handle = hidAttrTbl[HID_REPORT_KEY_IN_IDX].handle;
hidRptMap[0].cccdHandle = hidAttrTbl[HID_REPORT_KEY_IN_CCCD_IDX].handle;
hidRptMap[0].mode = HID_PROTOCOL_MODE_REPORT;
// LED output report
hidRptMap[1].id = hidReportRefLedOut[0];
hidRptMap[1].type = hidReportRefLedOut[1];
hidRptMap[1].handle = hidAttrTbl[HID_REPORT_LED_OUT_IDX].handle;
hidRptMap[1].cccdHandle = 0;
hidRptMap[1].mode = HID_PROTOCOL_MODE_REPORT;
// Boot keyboard input report
// Use same ID and type as key input report
hidRptMap[2].id = hidReportRefKeyIn[0];
hidRptMap[2].type = hidReportRefKeyIn[1];
hidRptMap[2].handle = hidAttrTbl[HID_BOOT_KEY_IN_IDX].handle;
hidRptMap[2].cccdHandle = hidAttrTbl[HID_BOOT_KEY_IN_CCCD_IDX].handle;
hidRptMap[2].mode = HID_PROTOCOL_MODE_BOOT;
// Boot keyboard output report
// Use same ID and type as LED output report
hidRptMap[3].id = hidReportRefLedOut[0];
hidRptMap[3].type = hidReportRefLedOut[1];
hidRptMap[3].handle = hidAttrTbl[HID_BOOT_KEY_OUT_IDX].handle;
hidRptMap[3].cccdHandle = 0;
hidRptMap[3].mode = HID_PROTOCOL_MODE_BOOT;
// Feature report
hidRptMap[4].id = hidReportRefFeature[0];
hidRptMap[4].type = hidReportRefFeature[1];
hidRptMap[4].handle = hidAttrTbl[HID_FEATURE_IDX].handle;
hidRptMap[4].cccdHandle = 0;
hidRptMap[4].mode = HID_PROTOCOL_MODE_REPORT;
// Battery level input report
Batt_GetParameter(BATT_PARAM_BATT_LEVEL_IN_REPORT, &(hidRptMap[5]));
// Setup report ID map
HidDev_RegisterReports(HID_NUM_REPORTS, hidRptMap);
return (status);
}
/*********************************************************************
* @fn Hid_SetParameter
*
* @brief Set a HID Kbd parameter.
*
* @param id - HID report ID.
* @param type - HID report type.
* @param uuid - attribute uuid.
* @param len - length of data to right.
* @param pValue - pointer to data to write. This is dependent on
* the input parameters and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return GATT status code.
*/
uint8_t Hid_SetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint8_t len, void *pValue)
{
bStatus_t ret = SUCCESS;
switch(uuid)
{
case REPORT_UUID:
if(type == HID_REPORT_TYPE_OUTPUT)
{
if(len == 1)
{
hidReportLedOut = *((uint8_t *)pValue);
}
else
{
ret = ATT_ERR_INVALID_VALUE_SIZE;
}
}
else if(type == HID_REPORT_TYPE_FEATURE)
{
if(len == 1)
{
hidReportFeature = *((uint8_t *)pValue);
}
else
{
ret = ATT_ERR_INVALID_VALUE_SIZE;
}
}
else
{
ret = ATT_ERR_ATTR_NOT_FOUND;
}
break;
case BOOT_KEY_OUTPUT_UUID:
if(len == 1)
{
hidReportBootKeyOut = *((uint8_t *)pValue);
}
else
{
ret = ATT_ERR_INVALID_VALUE_SIZE;
}
break;
default:
// ignore the request
break;
}
return (ret);
}
/*********************************************************************
* @fn Hid_GetParameter
*
* @brief Get a HID Kbd parameter.
*
* @param id - HID report ID.
* @param type - HID report type.
* @param uuid - attribute uuid.
* @param pLen - length of data to be read
* @param pValue - pointer to data to get. This is dependent on
* the input parameters and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return GATT status code.
*/
uint8_t Hid_GetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint16_t *pLen, void *pValue)
{
switch(uuid)
{
case REPORT_UUID:
if(type == HID_REPORT_TYPE_OUTPUT)
{
*((uint8_t *)pValue) = hidReportLedOut;
*pLen = 1;
}
else if(type == HID_REPORT_TYPE_FEATURE)
{
*((uint8_t *)pValue) = hidReportFeature;
*pLen = 1;
}
else
{
*pLen = 0;
}
break;
case BOOT_KEY_OUTPUT_UUID:
*((uint8_t *)pValue) = hidReportBootKeyOut;
*pLen = 1;
break;
default:
*pLen = 0;
break;
}
return (SUCCESS);
}
/*********************************************************************
*********************************************************************/