add app, profile
This commit is contained in:
parent
1294d9f0c0
commit
7500f5489a
530
app/hidkbd.c
Normal file
530
app/hidkbd.c
Normal file
@ -0,0 +1,530 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : hidkbd.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 "devinfoservice.h"
|
||||
#include "battservice.h"
|
||||
#include "hidkbdservice.h"
|
||||
#include "hiddev.h"
|
||||
#include "hidkbd.h"
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
// HID keyboard input report length
|
||||
#define HID_KEYBOARD_IN_RPT_LEN 8
|
||||
|
||||
// HID LED output report length
|
||||
#define HID_LED_OUT_RPT_LEN 1
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
// Param update delay
|
||||
#define START_PARAM_UPDATE_EVT_DELAY 12800
|
||||
|
||||
// Param update delay
|
||||
#define START_PHY_UPDATE_DELAY 1600
|
||||
|
||||
// HID idle timeout in msec; set to zero to disable timeout
|
||||
#define DEFAULT_HID_IDLE_TIMEOUT 60000
|
||||
|
||||
// Minimum connection interval (units of 1.25ms)
|
||||
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 8
|
||||
|
||||
// Maximum connection interval (units of 1.25ms)
|
||||
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 8
|
||||
|
||||
// Slave latency to use if parameter update request
|
||||
#define DEFAULT_DESIRED_SLAVE_LATENCY 0
|
||||
|
||||
// Supervision timeout value (units of 10ms)
|
||||
#define DEFAULT_DESIRED_CONN_TIMEOUT 500
|
||||
|
||||
// Default passcode
|
||||
#define DEFAULT_PASSCODE 0
|
||||
|
||||
// Default GAP pairing mode
|
||||
#define DEFAULT_PAIRING_MODE GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
|
||||
|
||||
// Default MITM mode (TRUE to require passcode or OOB when pairing)
|
||||
#define DEFAULT_MITM_MODE FALSE
|
||||
|
||||
// Default bonding mode, TRUE to bond
|
||||
#define DEFAULT_BONDING_MODE TRUE
|
||||
|
||||
// Default GAP bonding I/O capabilities
|
||||
#define DEFAULT_IO_CAPABILITIES GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT
|
||||
|
||||
// Battery level is critical when it is less than this %
|
||||
#define DEFAULT_BATT_CRITICAL_LEVEL 6
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
// Task ID
|
||||
static uint8_t hidEmuTaskId = INVALID_TASK_ID;
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL VARIABLES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL VARIABLES
|
||||
*/
|
||||
|
||||
// GAP Profile - Name attribute for SCAN RSP data
|
||||
static uint8_t scanRspData[] = {
|
||||
0x0D, // length of this data
|
||||
GAP_ADTYPE_LOCAL_NAME_COMPLETE, // AD Type = Complete local name
|
||||
'B',
|
||||
'L',
|
||||
'E',
|
||||
' ',
|
||||
'K',
|
||||
'e',
|
||||
'y',
|
||||
'b',
|
||||
'o',
|
||||
'a',
|
||||
'r',
|
||||
'd', // connection interval range
|
||||
0x05, // length of this data
|
||||
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
|
||||
LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL), // 100ms
|
||||
HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
|
||||
LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL), // 1s
|
||||
HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
|
||||
|
||||
// service UUIDs
|
||||
0x05, // length of this data
|
||||
GAP_ADTYPE_16BIT_MORE,
|
||||
LO_UINT16(HID_SERV_UUID),
|
||||
HI_UINT16(HID_SERV_UUID),
|
||||
LO_UINT16(BATT_SERV_UUID),
|
||||
HI_UINT16(BATT_SERV_UUID),
|
||||
|
||||
// Tx power level
|
||||
0x02, // length of this data
|
||||
GAP_ADTYPE_POWER_LEVEL,
|
||||
0 // 0dBm
|
||||
};
|
||||
|
||||
// Advertising data
|
||||
static uint8_t advertData[] = {
|
||||
// flags
|
||||
0x02, // length of this data
|
||||
GAP_ADTYPE_FLAGS,
|
||||
GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
|
||||
|
||||
// appearance
|
||||
0x03, // length of this data
|
||||
GAP_ADTYPE_APPEARANCE,
|
||||
LO_UINT16(GAP_APPEARE_HID_KEYBOARD),
|
||||
HI_UINT16(GAP_APPEARE_HID_KEYBOARD)};
|
||||
|
||||
// Device name attribute value
|
||||
static CONST uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "HID Keyboard";
|
||||
|
||||
// HID Dev configuration
|
||||
static hidDevCfg_t hidEmuCfg = {
|
||||
DEFAULT_HID_IDLE_TIMEOUT, // Idle timeout
|
||||
HID_FEATURE_FLAGS // HID feature flags
|
||||
};
|
||||
|
||||
static uint16_t hidEmuConnHandle = GAP_CONNHANDLE_INIT;
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL FUNCTIONS
|
||||
*/
|
||||
|
||||
static void hidEmu_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
|
||||
static void hidEmuSendKbdReport(uint8_t keycode);
|
||||
static uint8_t hidEmuRcvReport(uint8_t len, uint8_t *pData);
|
||||
static uint8_t hidEmuRptCB(uint8_t id, uint8_t type, uint16_t uuid,
|
||||
uint8_t oper, uint16_t *pLen, uint8_t *pData);
|
||||
static void hidEmuEvtCB(uint8_t evt);
|
||||
static void hidEmuStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent);
|
||||
|
||||
/*********************************************************************
|
||||
* PROFILE CALLBACKS
|
||||
*/
|
||||
|
||||
static hidDevCB_t hidEmuHidCBs = {
|
||||
hidEmuRptCB,
|
||||
hidEmuEvtCB,
|
||||
NULL,
|
||||
hidEmuStateCB};
|
||||
|
||||
/*********************************************************************
|
||||
* PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidEmu_Init
|
||||
*
|
||||
* @brief Initialization function for the HidEmuKbd App Task.
|
||||
* This is called during initialization and should contain
|
||||
* any application specific initialization (ie. hardware
|
||||
* initialization/setup, table initialization, power up
|
||||
* notificaiton ... ).
|
||||
*
|
||||
* @param task_id - the ID assigned by TMOS. This ID should be
|
||||
* used to send messages and set timers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void HidEmu_Init()
|
||||
{
|
||||
hidEmuTaskId = TMOS_ProcessEventRegister(HidEmu_ProcessEvent);
|
||||
|
||||
// Setup the GAP Peripheral Role Profile
|
||||
{
|
||||
uint8_t initial_advertising_enable = TRUE;
|
||||
|
||||
// Set the GAP Role Parameters
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
|
||||
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
|
||||
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
|
||||
}
|
||||
|
||||
// Set the GAP Characteristics
|
||||
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, (void *)attDeviceName);
|
||||
|
||||
// Setup the GAP Bond Manager
|
||||
{
|
||||
uint32_t passkey = DEFAULT_PASSCODE;
|
||||
uint8_t pairMode = DEFAULT_PAIRING_MODE;
|
||||
uint8_t mitm = DEFAULT_MITM_MODE;
|
||||
uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
|
||||
uint8_t bonding = DEFAULT_BONDING_MODE;
|
||||
GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
|
||||
GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
|
||||
GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
|
||||
GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
|
||||
GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
|
||||
}
|
||||
|
||||
// Setup Battery Characteristic Values
|
||||
{
|
||||
uint8_t critical = DEFAULT_BATT_CRITICAL_LEVEL;
|
||||
Batt_SetParameter(BATT_PARAM_CRITICAL_LEVEL, sizeof(uint8_t), &critical);
|
||||
}
|
||||
|
||||
// Set up HID keyboard service
|
||||
Hid_AddService();
|
||||
|
||||
// Register for HID Dev callback
|
||||
HidDev_Register(&hidEmuCfg, &hidEmuHidCBs);
|
||||
|
||||
// Setup a delayed profile startup
|
||||
tmos_set_event(hidEmuTaskId, START_DEVICE_EVT);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidEmu_ProcessEvent
|
||||
*
|
||||
* @brief HidEmuKbd Application Task event processor. This function
|
||||
* is called to process all events for the task. Events
|
||||
* include timers, messages and any other user defined events.
|
||||
*
|
||||
* @param task_id - The TMOS assigned task ID.
|
||||
* @param events - events to process. This is a bit map and can
|
||||
* contain more than one event.
|
||||
*
|
||||
* @return events not processed
|
||||
*/
|
||||
uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events)
|
||||
{
|
||||
static uint8_t send_char = 4;
|
||||
|
||||
if(events & SYS_EVENT_MSG)
|
||||
{
|
||||
uint8_t *pMsg;
|
||||
|
||||
if((pMsg = tmos_msg_receive(hidEmuTaskId)) != NULL)
|
||||
{
|
||||
hidEmu_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
|
||||
|
||||
// Release the TMOS message
|
||||
tmos_msg_deallocate(pMsg);
|
||||
}
|
||||
|
||||
// return unprocessed events
|
||||
return (events ^ SYS_EVENT_MSG);
|
||||
}
|
||||
|
||||
if(events & START_DEVICE_EVT)
|
||||
{
|
||||
return (events ^ START_DEVICE_EVT);
|
||||
}
|
||||
|
||||
if(events & START_PARAM_UPDATE_EVT)
|
||||
{
|
||||
// Send connect param update request
|
||||
GAPRole_PeripheralConnParamUpdateReq(hidEmuConnHandle,
|
||||
DEFAULT_DESIRED_MIN_CONN_INTERVAL,
|
||||
DEFAULT_DESIRED_MAX_CONN_INTERVAL,
|
||||
DEFAULT_DESIRED_SLAVE_LATENCY,
|
||||
DEFAULT_DESIRED_CONN_TIMEOUT,
|
||||
hidEmuTaskId);
|
||||
|
||||
return (events ^ START_PARAM_UPDATE_EVT);
|
||||
}
|
||||
|
||||
if(events & START_PHY_UPDATE_EVT)
|
||||
{
|
||||
// start phy update
|
||||
PRINT("Send Phy Update %x...\n", GAPRole_UpdatePHY(hidEmuConnHandle, 0,
|
||||
GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0));
|
||||
|
||||
return (events ^ START_PHY_UPDATE_EVT);
|
||||
}
|
||||
|
||||
if(events & START_REPORT_EVT)
|
||||
{
|
||||
hidEmuSendKbdReport(send_char);
|
||||
send_char += 3;
|
||||
if(send_char >= 29)
|
||||
send_char = 4;
|
||||
hidEmuSendKbdReport(0x00);
|
||||
tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 2000);
|
||||
return (events ^ START_REPORT_EVT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidEmu_ProcessTMOSMsg
|
||||
*
|
||||
* @brief Process an incoming task message.
|
||||
*
|
||||
* @param pMsg - message to process
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidEmu_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
|
||||
{
|
||||
switch(pMsg->event)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidEmuSendKbdReport
|
||||
*
|
||||
* @brief Build and send a HID keyboard report.
|
||||
*
|
||||
* @param keycode - HID keycode.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidEmuSendKbdReport(uint8_t keycode)
|
||||
{
|
||||
uint8_t buf[HID_KEYBOARD_IN_RPT_LEN];
|
||||
|
||||
buf[0] = 0; // Modifier keys
|
||||
buf[1] = 0; // Reserved
|
||||
buf[2] = keycode; // Keycode 1
|
||||
buf[3] = 0; // Keycode 2
|
||||
buf[4] = 0; // Keycode 3
|
||||
buf[5] = 0; // Keycode 4
|
||||
buf[6] = 0; // Keycode 5
|
||||
buf[7] = 0; // Keycode 6
|
||||
|
||||
HidDev_Report(HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT,
|
||||
HID_KEYBOARD_IN_RPT_LEN, buf);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidEmuStateCB
|
||||
*
|
||||
* @brief GAP state change callback.
|
||||
*
|
||||
* @param newState - new state
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidEmuStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent)
|
||||
{
|
||||
switch(newState & GAPROLE_STATE_ADV_MASK)
|
||||
{
|
||||
case GAPROLE_STARTED:
|
||||
{
|
||||
uint8_t ownAddr[6];
|
||||
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddr);
|
||||
GAP_ConfigDeviceAddr(ADDRTYPE_STATIC, ownAddr);
|
||||
PRINT("Initialized..\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case GAPROLE_ADVERTISING:
|
||||
if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
|
||||
{
|
||||
PRINT("Advertising..\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case GAPROLE_CONNECTED:
|
||||
if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
|
||||
{
|
||||
gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *)pEvent;
|
||||
|
||||
// get connection handle
|
||||
hidEmuConnHandle = event->connectionHandle;
|
||||
tmos_start_task(hidEmuTaskId, START_PARAM_UPDATE_EVT, START_PARAM_UPDATE_EVT_DELAY);
|
||||
PRINT("Connected..\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case GAPROLE_CONNECTED_ADV:
|
||||
if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
|
||||
{
|
||||
PRINT("Connected Advertising..\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case GAPROLE_WAITING:
|
||||
if(pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT)
|
||||
{
|
||||
PRINT("Waiting for advertising..\n");
|
||||
}
|
||||
else if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
|
||||
{
|
||||
PRINT("Disconnected.. Reason:%x\n", pEvent->linkTerminate.reason);
|
||||
}
|
||||
else if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
|
||||
{
|
||||
PRINT("Advertising timeout..\n");
|
||||
}
|
||||
// Enable advertising
|
||||
{
|
||||
uint8_t initial_advertising_enable = TRUE;
|
||||
// Set the GAP Role Parameters
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAPROLE_ERROR:
|
||||
PRINT("Error %x ..\n", pEvent->gap.opcode);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidEmuRcvReport
|
||||
*
|
||||
* @brief Process an incoming HID keyboard report.
|
||||
*
|
||||
* @param len - Length of report.
|
||||
* @param pData - Report data.
|
||||
*
|
||||
* @return status
|
||||
*/
|
||||
static uint8_t hidEmuRcvReport(uint8_t len, uint8_t *pData)
|
||||
{
|
||||
// verify data length
|
||||
if(len == HID_LED_OUT_RPT_LEN)
|
||||
{
|
||||
// set LEDs
|
||||
return SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATT_ERR_INVALID_VALUE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidEmuRptCB
|
||||
*
|
||||
* @brief HID Dev report callback.
|
||||
*
|
||||
* @param id - HID report ID.
|
||||
* @param type - HID report type.
|
||||
* @param uuid - attribute uuid.
|
||||
* @param oper - operation: read, write, etc.
|
||||
* @param len - Length of report.
|
||||
* @param pData - Report data.
|
||||
*
|
||||
* @return GATT status code.
|
||||
*/
|
||||
static uint8_t hidEmuRptCB(uint8_t id, uint8_t type, uint16_t uuid,
|
||||
uint8_t oper, uint16_t *pLen, uint8_t *pData)
|
||||
{
|
||||
uint8_t status = SUCCESS;
|
||||
|
||||
// write
|
||||
if(oper == HID_DEV_OPER_WRITE)
|
||||
{
|
||||
if(uuid == REPORT_UUID)
|
||||
{
|
||||
// process write to LED output report; ignore others
|
||||
if(type == HID_REPORT_TYPE_OUTPUT)
|
||||
{
|
||||
status = hidEmuRcvReport(*pLen, pData);
|
||||
}
|
||||
}
|
||||
|
||||
if(status == SUCCESS)
|
||||
{
|
||||
status = Hid_SetParameter(id, type, uuid, *pLen, pData);
|
||||
}
|
||||
}
|
||||
// read
|
||||
else if(oper == HID_DEV_OPER_READ)
|
||||
{
|
||||
status = Hid_GetParameter(id, type, uuid, pLen, pData);
|
||||
}
|
||||
// notifications enabled
|
||||
else if(oper == HID_DEV_OPER_ENABLE)
|
||||
{
|
||||
tmos_start_task(hidEmuTaskId, START_REPORT_EVT, 500);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidEmuEvtCB
|
||||
*
|
||||
* @brief HID Dev event callback.
|
||||
*
|
||||
* @param evt - event ID.
|
||||
*
|
||||
* @return HID response code.
|
||||
*/
|
||||
static void hidEmuEvtCB(uint8_t evt)
|
||||
{
|
||||
// process enter/exit suspend or enter/exit boot mode
|
||||
return;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
77
app/hidkbd_main.c
Normal file
77
app/hidkbd_main.c
Normal file
@ -0,0 +1,77 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : main.c
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2020/08/06
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/* 头文件包含 */
|
||||
#include "CONFIG.h"
|
||||
#include "HAL.h"
|
||||
#include "hiddev.h"
|
||||
#include "hidkbd.h"
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL TYPEDEFS
|
||||
*/
|
||||
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
|
||||
|
||||
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
|
||||
const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x03};
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Main_Circulation
|
||||
*
|
||||
* @brief 主循环
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
__HIGH_CODE
|
||||
__attribute__((noinline))
|
||||
void Main_Circulation()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
TMOS_SystemProcess();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn main
|
||||
*
|
||||
* @brief 主函数
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE)
|
||||
PWR_DCDCCfg(ENABLE);
|
||||
#endif
|
||||
SetSysClock(CLK_SOURCE_PLL_60MHz);
|
||||
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
|
||||
GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
|
||||
GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
GPIOA_SetBits(bTXD1);
|
||||
GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
|
||||
UART1_DefInit();
|
||||
#endif
|
||||
PRINT("%s\n", VER_LIB);
|
||||
CH59x_BLEInit();
|
||||
HAL_Init();
|
||||
GAPRole_PeripheralInit();
|
||||
HidDev_Init();
|
||||
HidEmu_Init();
|
||||
Main_Circulation();
|
||||
}
|
||||
|
||||
/******************************** endfile @ main ******************************/
|
62
app/include/hidkbd.h
Normal file
62
app/include/hidkbd.h
Normal file
@ -0,0 +1,62 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : hidkbd.h
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef HIDKBD_H
|
||||
#define HIDKBD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* INCLUDES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// Task Events
|
||||
#define START_DEVICE_EVT 0x0001
|
||||
#define START_REPORT_EVT 0x0002
|
||||
#define START_PARAM_UPDATE_EVT 0x0004
|
||||
#define START_PHY_UPDATE_EVT 0x0008
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
/*
|
||||
* Task Initialization for the BLE Application
|
||||
*/
|
||||
extern void HidEmu_Init(void);
|
||||
|
||||
/*
|
||||
* Task Event Processor for the BLE Application
|
||||
*/
|
||||
extern uint16_t HidEmu_ProcessEvent(uint8_t task_id, uint16_t events);
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
584
profile/battservice.c
Normal file
584
profile/battservice.c
Normal file
@ -0,0 +1,584 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : battservice.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 "hiddev.h"
|
||||
#include "battservice.h"
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// ADC voltage levels
|
||||
#define BATT_ADC_LEVEL_3V 409
|
||||
#define BATT_ADC_LEVEL_2V 273
|
||||
|
||||
#define BATT_LEVEL_VALUE_IDX 2 // Position of battery level in attribute array
|
||||
#define BATT_LEVEL_VALUE_CCCD_IDX 3 // Position of battery level CCCD in attribute array
|
||||
|
||||
#define BATT_LEVEL_VALUE_LEN 1
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*/
|
||||
// Battery service
|
||||
const uint8_t battServUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(BATT_SERV_UUID), HI_UINT16(BATT_SERV_UUID)};
|
||||
|
||||
// Battery level characteristic
|
||||
const uint8_t battLevelUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(BATT_LEVEL_UUID), HI_UINT16(BATT_LEVEL_UUID)};
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL VARIABLES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL VARIABLES
|
||||
*/
|
||||
|
||||
// Application callback
|
||||
static battServiceCB_t battServiceCB;
|
||||
|
||||
// Measurement setup callback
|
||||
static battServiceSetupCB_t battServiceSetupCB = NULL;
|
||||
|
||||
// Measurement teardown callback
|
||||
static battServiceTeardownCB_t battServiceTeardownCB = NULL;
|
||||
|
||||
// Measurement calculation callback
|
||||
static battServiceCalcCB_t battServiceCalcCB = NULL;
|
||||
|
||||
static uint16_t battMinLevel = BATT_ADC_LEVEL_2V; // For VDD/3 measurements
|
||||
static uint16_t battMaxLevel = BATT_ADC_LEVEL_3V; // For VDD/3 measurements
|
||||
|
||||
// Critical battery level setting
|
||||
static uint8_t battCriticalLevel;
|
||||
|
||||
// ADC channel to be used for reading
|
||||
//static uint8_t battServiceAdcCh = HAL_ADC_CHANNEL_VDD;
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Attributes - variables
|
||||
*/
|
||||
|
||||
// Battery Service attribute
|
||||
static const gattAttrType_t battService = {ATT_BT_UUID_SIZE, battServUUID};
|
||||
|
||||
// Battery level characteristic
|
||||
static uint8_t battLevelProps = GATT_PROP_READ | GATT_PROP_NOTIFY;
|
||||
static uint8_t battLevel = 100;
|
||||
static gattCharCfg_t battLevelClientCharCfg[GATT_MAX_NUM_CONN];
|
||||
|
||||
// HID Report Reference characteristic descriptor, battery level
|
||||
static uint8_t hidReportRefBattLevel[HID_REPORT_REF_LEN] = {
|
||||
HID_RPT_ID_BATT_LEVEL_IN, HID_REPORT_TYPE_INPUT};
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Attributes - Table
|
||||
*/
|
||||
|
||||
static gattAttribute_t battAttrTbl[] = {
|
||||
// Battery Service
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
|
||||
GATT_PERMIT_READ, /* permissions */
|
||||
0, /* handle */
|
||||
(uint8_t *)&battService /* pValue */
|
||||
},
|
||||
|
||||
// Battery Level Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&battLevelProps},
|
||||
|
||||
// Battery Level Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, battLevelUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&battLevel},
|
||||
|
||||
// Battery Level Client Characteristic Configuration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, clientCharCfgUUID},
|
||||
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
|
||||
0,
|
||||
(uint8_t *)&battLevelClientCharCfg},
|
||||
|
||||
// HID Report Reference characteristic descriptor, batter level input
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, reportRefUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
hidReportRefBattLevel}
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL FUNCTIONS
|
||||
*/
|
||||
static bStatus_t battReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
|
||||
static bStatus_t battWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
|
||||
static void battNotifyCB(linkDBItem_t *pLinkItem);
|
||||
static uint8_t battMeasure(void);
|
||||
static void battNotifyLevel(void);
|
||||
|
||||
/*********************************************************************
|
||||
* PROFILE CALLBACKS
|
||||
*/
|
||||
// Battery Service Callbacks
|
||||
gattServiceCBs_t battCBs = {
|
||||
battReadAttrCB, // Read callback function pointer
|
||||
battWriteAttrCB, // Write callback function pointer
|
||||
NULL // Authorization callback function pointer
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_AddService
|
||||
*
|
||||
* @brief Initializes the Battery Service by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
bStatus_t Batt_AddService(void)
|
||||
{
|
||||
uint8_t status = SUCCESS;
|
||||
|
||||
// Initialize Client Characteristic Configuration attributes
|
||||
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, battLevelClientCharCfg);
|
||||
|
||||
// Register GATT attribute list and CBs with GATT Server App
|
||||
status = GATTServApp_RegisterService(battAttrTbl,
|
||||
GATT_NUM_ATTRS(battAttrTbl),
|
||||
GATT_MAX_ENCRYPT_KEY_SIZE,
|
||||
&battCBs);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_Register
|
||||
*
|
||||
* @brief Register a callback function with the Battery Service.
|
||||
*
|
||||
* @param pfnServiceCB - Callback function.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void Batt_Register(battServiceCB_t pfnServiceCB)
|
||||
{
|
||||
battServiceCB = pfnServiceCB;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_SetParameter
|
||||
*
|
||||
* @brief Set a Battery Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t Batt_SetParameter(uint8_t param, uint8_t len, void *value)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case BATT_PARAM_CRITICAL_LEVEL:
|
||||
battCriticalLevel = *((uint8_t *)value);
|
||||
|
||||
// If below the critical level and critical state not set, notify it
|
||||
if(battLevel < battCriticalLevel)
|
||||
{
|
||||
battNotifyLevel();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_GetParameter
|
||||
*
|
||||
* @brief Get a Battery Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param value - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t Batt_GetParameter(uint8_t param, void *value)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
switch(param)
|
||||
{
|
||||
case BATT_PARAM_LEVEL:
|
||||
*((uint8_t *)value) = battLevel;
|
||||
break;
|
||||
|
||||
case BATT_PARAM_CRITICAL_LEVEL:
|
||||
*((uint8_t *)value) = battCriticalLevel;
|
||||
break;
|
||||
|
||||
case BATT_PARAM_SERVICE_HANDLE:
|
||||
*((uint16_t *)value) = GATT_SERVICE_HANDLE(battAttrTbl);
|
||||
break;
|
||||
|
||||
case BATT_PARAM_BATT_LEVEL_IN_REPORT:
|
||||
{
|
||||
hidRptMap_t *pRpt = (hidRptMap_t *)value;
|
||||
|
||||
pRpt->id = hidReportRefBattLevel[0];
|
||||
pRpt->type = hidReportRefBattLevel[1];
|
||||
pRpt->handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
|
||||
pRpt->cccdHandle = battAttrTbl[BATT_LEVEL_VALUE_CCCD_IDX].handle;
|
||||
pRpt->mode = HID_PROTOCOL_MODE_REPORT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_MeasLevel
|
||||
*
|
||||
* @brief Measure the battery level and update the battery
|
||||
* level value in the service characteristics. If
|
||||
* the battery level-state characteristic is configured
|
||||
* for notification and the battery level has changed
|
||||
* since the last measurement, then a notification
|
||||
* will be sent.
|
||||
*
|
||||
* @return Success
|
||||
*/
|
||||
bStatus_t Batt_MeasLevel(void)
|
||||
{
|
||||
uint8_t level;
|
||||
|
||||
level = battMeasure();
|
||||
|
||||
// If level has gone down
|
||||
if(level < battLevel)
|
||||
{
|
||||
// Update level
|
||||
battLevel = level;
|
||||
|
||||
// Send a notification
|
||||
battNotifyLevel();
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_Setup
|
||||
*
|
||||
* @brief Set up which ADC source is to be used. Defaults to VDD/3.
|
||||
*
|
||||
* @param adc_ch - ADC Channel, e.g. HAL_ADC_CHN_AIN6
|
||||
* @param minVal - max battery level
|
||||
* @param maxVal - min battery level
|
||||
* @param sCB - HW setup callback
|
||||
* @param tCB - HW tear down callback
|
||||
* @param cCB - percentage calculation callback
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void Batt_Setup(uint8_t adc_ch, uint16_t minVal, uint16_t maxVal,
|
||||
battServiceSetupCB_t sCB, battServiceTeardownCB_t tCB,
|
||||
battServiceCalcCB_t cCB)
|
||||
{
|
||||
//battServiceAdcCh = adc_ch;
|
||||
battMinLevel = minVal;
|
||||
battMaxLevel = maxVal;
|
||||
|
||||
battServiceSetupCB = sCB;
|
||||
battServiceTeardownCB = tCB;
|
||||
battServiceCalcCB = cCB;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn battReadAttrCB
|
||||
*
|
||||
* @brief Read an attribute.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be read
|
||||
* @param pLen - length of data to be read
|
||||
* @param offset - offset of the first octet to be read
|
||||
* @param maxLen - maximum length of data to be read
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
static bStatus_t battReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
|
||||
{
|
||||
uint16_t uuid;
|
||||
bStatus_t status = SUCCESS;
|
||||
|
||||
// Make sure it's not a blob operation (no attributes in the profile are long)
|
||||
if(offset > 0)
|
||||
{
|
||||
return (ATT_ERR_ATTR_NOT_LONG);
|
||||
}
|
||||
|
||||
uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
|
||||
// Measure battery level if reading level
|
||||
if(uuid == BATT_LEVEL_UUID)
|
||||
{
|
||||
uint8_t level;
|
||||
|
||||
level = battMeasure();
|
||||
|
||||
// If level has gone down
|
||||
if(level < battLevel)
|
||||
{
|
||||
// Update level
|
||||
battLevel = level;
|
||||
}
|
||||
|
||||
*pLen = 1;
|
||||
pValue[0] = battLevel;
|
||||
}
|
||||
else if(uuid == GATT_REPORT_REF_UUID)
|
||||
{
|
||||
*pLen = HID_REPORT_REF_LEN;
|
||||
tmos_memcpy(pValue, pAttr->pValue, HID_REPORT_REF_LEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_ATTR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn battWriteAttrCB
|
||||
*
|
||||
* @brief Validate attribute data prior to a write operation
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be written
|
||||
* @param len - length of data
|
||||
* @param offset - offset of the first octet to be written
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
static bStatus_t battWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
|
||||
{
|
||||
bStatus_t status = SUCCESS;
|
||||
|
||||
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
switch(uuid)
|
||||
{
|
||||
case GATT_CLIENT_CHAR_CFG_UUID:
|
||||
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
|
||||
offset, GATT_CLIENT_CFG_NOTIFY);
|
||||
if(status == SUCCESS)
|
||||
{
|
||||
uint16_t charCfg = BUILD_UINT16(pValue[0], pValue[1]);
|
||||
|
||||
if(battServiceCB)
|
||||
{
|
||||
(*battServiceCB)((charCfg == GATT_CFG_NO_OPERATION) ? BATT_LEVEL_NOTI_DISABLED : BATT_LEVEL_NOTI_ENABLED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = ATT_ERR_ATTR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn battNotifyCB
|
||||
*
|
||||
* @brief Send a notification of the level state characteristic.
|
||||
*
|
||||
* @param connHandle - linkDB item
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void battNotifyCB(linkDBItem_t *pLinkItem)
|
||||
{
|
||||
if(pLinkItem->stateFlags & LINK_CONNECTED)
|
||||
{
|
||||
uint16_t value = GATTServApp_ReadCharCfg(pLinkItem->connectionHandle,
|
||||
battLevelClientCharCfg);
|
||||
if(value & GATT_CLIENT_CFG_NOTIFY)
|
||||
{
|
||||
attHandleValueNoti_t noti;
|
||||
|
||||
noti.pValue = GATT_bm_alloc(pLinkItem->connectionHandle, ATT_HANDLE_VALUE_NOTI,
|
||||
BATT_LEVEL_VALUE_LEN, NULL, 0);
|
||||
if(noti.pValue != NULL)
|
||||
{
|
||||
noti.handle = battAttrTbl[BATT_LEVEL_VALUE_IDX].handle;
|
||||
noti.len = BATT_LEVEL_VALUE_LEN;
|
||||
noti.pValue[0] = battLevel;
|
||||
|
||||
if(GATT_Notification(pLinkItem->connectionHandle, ¬i, FALSE) != SUCCESS)
|
||||
{
|
||||
GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn battMeasure
|
||||
*
|
||||
* @brief Measure the battery level with the ADC and return
|
||||
* it as a percentage 0-100%.
|
||||
*
|
||||
* @return Battery level.
|
||||
*/
|
||||
static uint8_t battMeasure(void)
|
||||
{
|
||||
uint16_t adc;
|
||||
uint8_t percent;
|
||||
|
||||
// Call measurement setup callback
|
||||
if(battServiceSetupCB != NULL)
|
||||
{
|
||||
battServiceSetupCB();
|
||||
}
|
||||
|
||||
// Configure ADC and perform a read
|
||||
adc = 300;
|
||||
// Call measurement teardown callback
|
||||
if(battServiceTeardownCB != NULL)
|
||||
{
|
||||
battServiceTeardownCB();
|
||||
}
|
||||
|
||||
if(adc >= battMaxLevel)
|
||||
{
|
||||
percent = 100;
|
||||
}
|
||||
else if(adc <= battMinLevel)
|
||||
{
|
||||
percent = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(battServiceCalcCB != NULL)
|
||||
{
|
||||
percent = battServiceCalcCB(adc);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t range = battMaxLevel - battMinLevel + 1;
|
||||
|
||||
// optional if you want to keep it even, otherwise just take floor of divide
|
||||
// range += (range & 1);
|
||||
range >>= 2; // divide by 4
|
||||
|
||||
percent = (uint8_t)((((adc - battMinLevel) * 25) + (range - 1)) / range);
|
||||
}
|
||||
}
|
||||
|
||||
return percent;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn battNotifyLevelState
|
||||
*
|
||||
* @brief Send a notification of the battery level state
|
||||
* characteristic if a connection is established.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void battNotifyLevel(void)
|
||||
{
|
||||
// Execute linkDB callback to send notification
|
||||
linkDB_PerformFunc(battNotifyCB);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_HandleConnStatusCB
|
||||
*
|
||||
* @brief Battery Service link status change handler function.
|
||||
*
|
||||
* @param connHandle - connection handle
|
||||
* @param changeType - type of change
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void Batt_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
|
||||
{
|
||||
// Make sure this is not loopback connection
|
||||
if(connHandle != LOOPBACK_CONNHANDLE)
|
||||
{
|
||||
// Reset Client Char Config if connection has dropped
|
||||
if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
|
||||
((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
|
||||
(!linkDB_Up(connHandle))))
|
||||
{
|
||||
GATTServApp_InitCharCfg(connHandle, battLevelClientCharCfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
588
profile/devinfoservice.c
Normal file
588
profile/devinfoservice.c
Normal file
@ -0,0 +1,588 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : devinfoservice.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 "devinfoservice.h"
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*/
|
||||
// Device information service
|
||||
const uint8_t devInfoServUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(DEVINFO_SERV_UUID), HI_UINT16(DEVINFO_SERV_UUID)};
|
||||
|
||||
// System ID
|
||||
const uint8_t devInfoSystemIdUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(SYSTEM_ID_UUID), HI_UINT16(SYSTEM_ID_UUID)};
|
||||
|
||||
// Model Number String
|
||||
const uint8_t devInfoModelNumberUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(MODEL_NUMBER_UUID), HI_UINT16(MODEL_NUMBER_UUID)};
|
||||
|
||||
// Serial Number String
|
||||
const uint8_t devInfoSerialNumberUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(SERIAL_NUMBER_UUID), HI_UINT16(SERIAL_NUMBER_UUID)};
|
||||
|
||||
// Firmware Revision String
|
||||
const uint8_t devInfoFirmwareRevUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(FIRMWARE_REV_UUID), HI_UINT16(FIRMWARE_REV_UUID)};
|
||||
|
||||
// Hardware Revision String
|
||||
const uint8_t devInfoHardwareRevUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(HARDWARE_REV_UUID), HI_UINT16(HARDWARE_REV_UUID)};
|
||||
|
||||
// Software Revision String
|
||||
const uint8_t devInfoSoftwareRevUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(SOFTWARE_REV_UUID), HI_UINT16(SOFTWARE_REV_UUID)};
|
||||
|
||||
// Manufacturer Name String
|
||||
const uint8_t devInfoMfrNameUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(MANUFACTURER_NAME_UUID), HI_UINT16(MANUFACTURER_NAME_UUID)};
|
||||
|
||||
// IEEE 11073-20601 Regulatory Certification Data List
|
||||
const uint8_t devInfo11073CertUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(IEEE_11073_CERT_DATA_UUID), HI_UINT16(IEEE_11073_CERT_DATA_UUID)};
|
||||
|
||||
// PnP ID
|
||||
const uint8_t devInfoPnpIdUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(PNP_ID_UUID), HI_UINT16(PNP_ID_UUID)};
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL VARIABLES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL VARIABLES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Attributes - variables
|
||||
*/
|
||||
|
||||
// Device Information Service attribute
|
||||
static const gattAttrType_t devInfoService = {ATT_BT_UUID_SIZE, devInfoServUUID};
|
||||
|
||||
// System ID characteristic
|
||||
static uint8_t devInfoSystemIdProps = GATT_PROP_READ;
|
||||
static uint8_t devInfoSystemId[DEVINFO_SYSTEM_ID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
// Model Number String characteristic
|
||||
static uint8_t devInfoModelNumberProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfoModelNumber[] = "Model Number";
|
||||
|
||||
// Serial Number String characteristic
|
||||
static uint8_t devInfoSerialNumberProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfoSerialNumber[] = "Serial Number";
|
||||
|
||||
// Firmware Revision String characteristic
|
||||
static uint8_t devInfoFirmwareRevProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfoFirmwareRev[] = "Firmware Revision";
|
||||
|
||||
// Hardware Revision String characteristic
|
||||
static uint8_t devInfoHardwareRevProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfoHardwareRev[] = "Hardware Revision";
|
||||
|
||||
// Software Revision String characteristic
|
||||
static uint8_t devInfoSoftwareRevProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfoSoftwareRev[] = "Software Revision";
|
||||
|
||||
// Manufacturer Name String characteristic
|
||||
static uint8_t devInfoMfrNameProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfoMfrName[] = "Manufacturer Name";
|
||||
|
||||
// IEEE 11073-20601 Regulatory Certification Data List characteristic
|
||||
static uint8_t devInfo11073CertProps = GATT_PROP_READ;
|
||||
static const uint8_t devInfo11073Cert[] = {
|
||||
DEVINFO_11073_BODY_EXP, // authoritative body type
|
||||
0x00, // authoritative body structure type
|
||||
// authoritative body data follows below:
|
||||
'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l'};
|
||||
|
||||
// System ID characteristic
|
||||
static uint8_t devInfoPnpIdProps = GATT_PROP_READ;
|
||||
static uint8_t devInfoPnpId[DEVINFO_PNP_ID_LEN] = {
|
||||
1, // Vendor ID source (1=Bluetooth SIG)
|
||||
LO_UINT16(0x07D7), HI_UINT16(0x07D7), // Vendor ID (WCH)
|
||||
LO_UINT16(0x0000), HI_UINT16(0x0000), // Product ID (vendor-specific)
|
||||
LO_UINT16(0x0110), HI_UINT16(0x0110) // Product version (JJ.M.N)
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Attributes - Table
|
||||
*/
|
||||
|
||||
static gattAttribute_t devInfoAttrTbl[] = {
|
||||
// Device Information Service
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
|
||||
GATT_PERMIT_READ, /* permissions */
|
||||
0, /* handle */
|
||||
(uint8_t *)&devInfoService /* pValue */
|
||||
},
|
||||
|
||||
// System ID Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoSystemIdProps},
|
||||
|
||||
// System ID Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoSystemIdUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoSystemId},
|
||||
|
||||
// Model Number String Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoModelNumberProps},
|
||||
|
||||
// Model Number Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoModelNumberUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoModelNumber},
|
||||
|
||||
// Serial Number String Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoSerialNumberProps},
|
||||
|
||||
// Serial Number Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoSerialNumberUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoSerialNumber},
|
||||
|
||||
// Firmware Revision String Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoFirmwareRevProps},
|
||||
|
||||
// Firmware Revision Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoFirmwareRevUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoFirmwareRev},
|
||||
|
||||
// Hardware Revision String Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoHardwareRevProps},
|
||||
|
||||
// Hardware Revision Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoHardwareRevUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoHardwareRev},
|
||||
|
||||
// Software Revision String Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoSoftwareRevProps},
|
||||
|
||||
// Software Revision Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoSoftwareRevUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoSoftwareRev},
|
||||
|
||||
// Manufacturer Name String Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoMfrNameProps},
|
||||
|
||||
// Manufacturer Name Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoMfrNameUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoMfrName},
|
||||
|
||||
// IEEE 11073-20601 Regulatory Certification Data List Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfo11073CertProps},
|
||||
|
||||
// IEEE 11073-20601 Regulatory Certification Data List Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfo11073CertUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfo11073Cert},
|
||||
|
||||
// PnP ID Declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&devInfoPnpIdProps},
|
||||
|
||||
// PnP ID Value
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, devInfoPnpIdUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
(uint8_t *)devInfoPnpId}};
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL FUNCTIONS
|
||||
*/
|
||||
static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
|
||||
|
||||
/*********************************************************************
|
||||
* PROFILE CALLBACKS
|
||||
*/
|
||||
// Device Info Service Callbacks
|
||||
gattServiceCBs_t devInfoCBs = {
|
||||
devInfo_ReadAttrCB, // Read callback function pointer
|
||||
NULL, // Write callback function pointer
|
||||
NULL // Authorization callback function pointer
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* NETWORK LAYER CALLBACKS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn DevInfo_AddService
|
||||
*
|
||||
* @brief Initializes the Device Information service by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
bStatus_t DevInfo_AddService(void)
|
||||
{
|
||||
// Register GATT attribute list and CBs with GATT Server App
|
||||
return GATTServApp_RegisterService(devInfoAttrTbl,
|
||||
GATT_NUM_ATTRS(devInfoAttrTbl),
|
||||
GATT_MAX_ENCRYPT_KEY_SIZE,
|
||||
&devInfoCBs);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn DevInfo_SetParameter
|
||||
*
|
||||
* @brief Set a Device Information parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to write
|
||||
* @param value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case DEVINFO_SYSTEM_ID:
|
||||
tmos_memcpy(devInfoSystemId, value, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn DevInfo_GetParameter
|
||||
*
|
||||
* @brief Get a Device Information parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param value - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t DevInfo_GetParameter(uint8_t param, void *value)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case DEVINFO_SYSTEM_ID:
|
||||
tmos_memcpy(value, devInfoSystemId, sizeof(devInfoSystemId));
|
||||
break;
|
||||
|
||||
case DEVINFO_MODEL_NUMBER:
|
||||
tmos_memcpy(value, devInfoModelNumber, sizeof(devInfoModelNumber));
|
||||
break;
|
||||
case DEVINFO_SERIAL_NUMBER:
|
||||
tmos_memcpy(value, devInfoSerialNumber, sizeof(devInfoSerialNumber));
|
||||
break;
|
||||
|
||||
case DEVINFO_FIRMWARE_REV:
|
||||
tmos_memcpy(value, devInfoFirmwareRev, sizeof(devInfoFirmwareRev));
|
||||
break;
|
||||
|
||||
case DEVINFO_HARDWARE_REV:
|
||||
tmos_memcpy(value, devInfoHardwareRev, sizeof(devInfoHardwareRev));
|
||||
break;
|
||||
|
||||
case DEVINFO_SOFTWARE_REV:
|
||||
tmos_memcpy(value, devInfoSoftwareRev, sizeof(devInfoSoftwareRev));
|
||||
break;
|
||||
|
||||
case DEVINFO_MANUFACTURER_NAME:
|
||||
tmos_memcpy(value, devInfoMfrName, sizeof(devInfoMfrName));
|
||||
break;
|
||||
|
||||
case DEVINFO_11073_CERT_DATA:
|
||||
tmos_memcpy(value, devInfo11073Cert, sizeof(devInfo11073Cert));
|
||||
break;
|
||||
|
||||
case DEVINFO_PNP_ID:
|
||||
tmos_memcpy(value, devInfoPnpId, sizeof(devInfoPnpId));
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn devInfo_ReadAttrCB
|
||||
*
|
||||
* @brief Read an attribute.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be read
|
||||
* @param pLen - length of data to be read
|
||||
* @param offset - offset of the first octet to be read
|
||||
* @param maxLen - maximum length of data to be read
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
|
||||
{
|
||||
bStatus_t status = SUCCESS;
|
||||
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
|
||||
switch(uuid)
|
||||
{
|
||||
case SYSTEM_ID_UUID:
|
||||
// verify offset
|
||||
if(offset >= sizeof(devInfoSystemId))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length
|
||||
*pLen = MIN(maxLen, (sizeof(devInfoSystemId) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoSystemId[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case MODEL_NUMBER_UUID:
|
||||
// verify offset
|
||||
if(offset >= (sizeof(devInfoModelNumber) - 1))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length (exclude null terminating character)
|
||||
*pLen = MIN(maxLen, ((sizeof(devInfoModelNumber) - 1) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoModelNumber[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case SERIAL_NUMBER_UUID:
|
||||
// verify offset
|
||||
if(offset >= (sizeof(devInfoSerialNumber) - 1))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length (exclude null terminating character)
|
||||
*pLen = MIN(maxLen, ((sizeof(devInfoSerialNumber) - 1) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoSerialNumber[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRMWARE_REV_UUID:
|
||||
// verify offset
|
||||
if(offset >= (sizeof(devInfoFirmwareRev) - 1))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length (exclude null terminating character)
|
||||
*pLen = MIN(maxLen, ((sizeof(devInfoFirmwareRev) - 1) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoFirmwareRev[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case HARDWARE_REV_UUID:
|
||||
// verify offset
|
||||
if(offset >= (sizeof(devInfoHardwareRev) - 1))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length (exclude null terminating character)
|
||||
*pLen = MIN(maxLen, ((sizeof(devInfoHardwareRev) - 1) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoHardwareRev[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case SOFTWARE_REV_UUID:
|
||||
// verify offset
|
||||
if(offset >= (sizeof(devInfoSoftwareRev) - 1))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length (exclude null terminating character)
|
||||
*pLen = MIN(maxLen, ((sizeof(devInfoSoftwareRev) - 1) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoSoftwareRev[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case MANUFACTURER_NAME_UUID:
|
||||
// verify offset
|
||||
if(offset >= (sizeof(devInfoMfrName) - 1))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length (exclude null terminating character)
|
||||
*pLen = MIN(maxLen, ((sizeof(devInfoMfrName) - 1) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoMfrName[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE_11073_CERT_DATA_UUID:
|
||||
// verify offset
|
||||
if(offset >= sizeof(devInfo11073Cert))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length
|
||||
*pLen = MIN(maxLen, (sizeof(devInfo11073Cert) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfo11073Cert[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
case PNP_ID_UUID:
|
||||
// verify offset
|
||||
if(offset >= sizeof(devInfoPnpId))
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length
|
||||
*pLen = MIN(maxLen, (sizeof(devInfoPnpId) - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, &devInfoPnpId[offset], *pLen);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
*pLen = 0;
|
||||
status = ATT_ERR_ATTR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
1182
profile/hiddev.c
Normal file
1182
profile/hiddev.c
Normal file
@ -0,0 +1,1182 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : hiddev.c
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2018/12/10
|
||||
* Description : HID 设备任务处理程序
|
||||
*********************************************************************************
|
||||
* 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 "battservice.h"
|
||||
#include "scanparamservice.h"
|
||||
#include "devinfoservice.h"
|
||||
#include "hidkbd.h"
|
||||
#include "hiddev.h"
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
// Battery measurement period in (625us)
|
||||
#define DEFAULT_BATT_PERIOD 15000
|
||||
|
||||
// TRUE to run scan parameters refresh notify test
|
||||
#define DEFAULT_SCAN_PARAM_NOTIFY_TEST TRUE
|
||||
|
||||
// Advertising intervals (units of 625us, 160=100ms)
|
||||
#define HID_INITIAL_ADV_INT_MIN 48
|
||||
#define HID_INITIAL_ADV_INT_MAX 80
|
||||
#define HID_HIGH_ADV_INT_MIN 32
|
||||
#define HID_HIGH_ADV_INT_MAX 48
|
||||
#define HID_LOW_ADV_INT_MIN 160
|
||||
#define HID_LOW_ADV_INT_MAX 160
|
||||
|
||||
// Advertising timeouts in sec
|
||||
#define HID_INITIAL_ADV_TIMEOUT 60
|
||||
#define HID_HIGH_ADV_TIMEOUT 5
|
||||
#define HID_LOW_ADV_TIMEOUT 0
|
||||
|
||||
// Heart Rate Task Events
|
||||
#define START_DEVICE_EVT 0x0001
|
||||
#define BATT_PERIODIC_EVT 0x0002
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*/
|
||||
|
||||
// Task ID
|
||||
uint8_t hidDevTaskId;
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL VARIABLES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL VARIABLES
|
||||
*/
|
||||
|
||||
// GAP State
|
||||
static gapRole_States_t hidDevGapState = GAPROLE_INIT;
|
||||
|
||||
// TRUE if connection is secure
|
||||
static uint8_t hidDevConnSecure = FALSE;
|
||||
|
||||
// GAP connection handle
|
||||
static uint16_t gapConnHandle;
|
||||
|
||||
// Status of last pairing
|
||||
static uint8_t pairingStatus = SUCCESS;
|
||||
|
||||
static hidRptMap_t *pHidDevRptTbl;
|
||||
|
||||
static uint8_t hidDevRptTblLen;
|
||||
|
||||
static hidDevCB_t *pHidDevCB;
|
||||
|
||||
static hidDevCfg_t *pHidDevCfg;
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL FUNCTIONS
|
||||
*/
|
||||
|
||||
static void hidDev_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
|
||||
static void hidDevProcessGattMsg(gattMsgEvent_t *pMsg);
|
||||
static void hidDevProcessGAPMsg(gapRoleEvent_t *pEvent);
|
||||
static void hidDevDisconnected(void);
|
||||
static void hidDevGapStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent);
|
||||
static void hidDevParamUpdateCB(uint16_t connHandle, uint16_t connInterval,
|
||||
uint16_t connSlaveLatency, uint16_t connTimeout);
|
||||
static void hidDevPairStateCB(uint16_t connHandle, uint8_t state, uint8_t status);
|
||||
static void hidDevPasscodeCB(uint8_t *deviceAddr, uint16_t connectionHandle,
|
||||
uint8_t uiInputs, uint8_t uiOutputs);
|
||||
static void hidDevBattCB(uint8_t event);
|
||||
static void hidDevScanParamCB(uint8_t event);
|
||||
static void hidDevBattPeriodicTask(void);
|
||||
|
||||
static hidRptMap_t *hidDevRptByHandle(uint16_t handle);
|
||||
static hidRptMap_t *hidDevRptById(uint8_t id, uint8_t type);
|
||||
static hidRptMap_t *hidDevRptByCccdHandle(uint16_t handle);
|
||||
|
||||
static uint8_t hidDevSendReport(uint8_t id, uint8_t type, uint8_t len, uint8_t *pData);
|
||||
static void hidDevHighAdvertising(void);
|
||||
static void hidDevLowAdvertising(void);
|
||||
static void hidDevInitialAdvertising(void);
|
||||
static uint8_t hidDevBondCount(void);
|
||||
static uint8_t HidDev_sendNoti(uint16_t handle, uint8_t len, uint8_t *pData);
|
||||
/*********************************************************************
|
||||
* PROFILE CALLBACKS
|
||||
*/
|
||||
|
||||
// GAP Role Callbacks
|
||||
static gapRolesCBs_t hidDev_PeripheralCBs = {
|
||||
hidDevGapStateCB, // Profile State Change Callbacks
|
||||
NULL, // When a valid RSSI is read from controller
|
||||
hidDevParamUpdateCB
|
||||
};
|
||||
|
||||
// Bond Manager Callbacks
|
||||
static gapBondCBs_t hidDevBondCB = {
|
||||
hidDevPasscodeCB,
|
||||
hidDevPairStateCB
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Init
|
||||
*
|
||||
* @brief Initialization function for the Hid Dev Task.
|
||||
* This is called during initialization and should contain
|
||||
* any application specific initialization (ie. hardware
|
||||
* initialization/setup, table initialization, power up
|
||||
* notificaiton ... ).
|
||||
*
|
||||
* @param task_id - the ID assigned by TMOS. This ID should be
|
||||
* used to send messages and set timers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void HidDev_Init()
|
||||
{
|
||||
hidDevTaskId = TMOS_ProcessEventRegister(HidDev_ProcessEvent);
|
||||
|
||||
// Setup the GAP Bond Manager
|
||||
{
|
||||
uint8_t syncWL = TRUE;
|
||||
|
||||
// If a bond is created, the HID Device should write the address of the
|
||||
// HID Host in the HID Device controller's white list and set the HID
|
||||
// Device controller's advertising filter policy to 'process scan and
|
||||
// connection requests only from devices in the White List'.
|
||||
GAPBondMgr_SetParameter(GAPBOND_AUTO_SYNC_WL, sizeof(uint8_t), &syncWL);
|
||||
}
|
||||
|
||||
// Set up services
|
||||
GGS_AddService(GATT_ALL_SERVICES); // GAP
|
||||
GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
|
||||
DevInfo_AddService();
|
||||
Batt_AddService();
|
||||
ScanParam_AddService();
|
||||
|
||||
// Register for Battery service callback
|
||||
Batt_Register(hidDevBattCB);
|
||||
|
||||
// Register for Scan Parameters service callback
|
||||
ScanParam_Register(hidDevScanParamCB);
|
||||
|
||||
// Setup a delayed profile startup
|
||||
tmos_set_event(hidDevTaskId, START_DEVICE_EVT);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_ProcessEvent
|
||||
*
|
||||
* @brief Hid Dev Task event processor. This function
|
||||
* is called to process all events for the task. Events
|
||||
* include timers, messages and any other user defined events.
|
||||
*
|
||||
* @param task_id - The TMOS assigned task ID.
|
||||
* @param events - events to process. This is a bit map and can
|
||||
* contain more than one event.
|
||||
*
|
||||
* @return events not processed
|
||||
*/
|
||||
uint16_t HidDev_ProcessEvent(uint8_t task_id, uint16_t events)
|
||||
{
|
||||
//VOID task_id; // TMOS required parameter that isn't used in this function
|
||||
|
||||
if(events & SYS_EVENT_MSG)
|
||||
{
|
||||
uint8_t *pMsg;
|
||||
|
||||
if((pMsg = tmos_msg_receive(hidDevTaskId)) != NULL)
|
||||
{
|
||||
hidDev_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
|
||||
|
||||
// Release the TMOS message
|
||||
tmos_msg_deallocate(pMsg);
|
||||
}
|
||||
|
||||
// return unprocessed events
|
||||
return (events ^ SYS_EVENT_MSG);
|
||||
}
|
||||
|
||||
if(events & START_DEVICE_EVT)
|
||||
{
|
||||
// Start the Device
|
||||
GAPRole_PeripheralStartDevice(hidDevTaskId, &hidDevBondCB, &hidDev_PeripheralCBs);
|
||||
|
||||
return (events ^ START_DEVICE_EVT);
|
||||
}
|
||||
|
||||
if(events & BATT_PERIODIC_EVT)
|
||||
{
|
||||
// Perform periodic battery task
|
||||
hidDevBattPeriodicTask();
|
||||
|
||||
return (events ^ BATT_PERIODIC_EVT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Register
|
||||
*
|
||||
* @brief Register a callback function with HID Dev.
|
||||
*
|
||||
* @param pCfg - Parameter configuration.
|
||||
* @param pfnServiceCB - Callback function.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void HidDev_Register(hidDevCfg_t *pCfg, hidDevCB_t *pCBs)
|
||||
{
|
||||
pHidDevCB = pCBs;
|
||||
pHidDevCfg = pCfg;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_RegisterReports
|
||||
*
|
||||
* @brief Register the report table with HID Dev.
|
||||
*
|
||||
* @param numReports - Length of report table.
|
||||
* @param pRpt - Report table.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void HidDev_RegisterReports(uint8_t numReports, hidRptMap_t *pRpt)
|
||||
{
|
||||
pHidDevRptTbl = pRpt;
|
||||
hidDevRptTblLen = numReports;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Report
|
||||
*
|
||||
* @brief Send a HID report.
|
||||
*
|
||||
* @param id - HID report ID.
|
||||
* @param type - HID report type.
|
||||
* @param len - Length of report.
|
||||
* @param pData - Report data.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
uint8_t HidDev_Report(uint8_t id, uint8_t type, uint8_t len, uint8_t *pData)
|
||||
{
|
||||
// if connected
|
||||
if(hidDevGapState == GAPROLE_CONNECTED)
|
||||
{
|
||||
// if connection is secure
|
||||
if(hidDevConnSecure)
|
||||
{
|
||||
// send report
|
||||
return hidDevSendReport(id, type, len, pData);
|
||||
}
|
||||
}
|
||||
// else if not already advertising
|
||||
else if(hidDevGapState != GAPROLE_ADVERTISING)
|
||||
{
|
||||
// if bonded
|
||||
if(hidDevBondCount() > 0)
|
||||
{
|
||||
// start high duty cycle advertising
|
||||
hidDevHighAdvertising();
|
||||
}
|
||||
// else not bonded
|
||||
else
|
||||
{
|
||||
// start initial advertising
|
||||
hidDevInitialAdvertising();
|
||||
}
|
||||
}
|
||||
return bleNotReady;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Close
|
||||
*
|
||||
* @brief Close the connection or stop advertising.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void HidDev_Close(void)
|
||||
{
|
||||
uint8_t param;
|
||||
|
||||
// if connected then disconnect
|
||||
if(hidDevGapState == GAPROLE_CONNECTED)
|
||||
{
|
||||
GAPRole_TerminateLink(gapConnHandle);
|
||||
}
|
||||
// else stop advertising
|
||||
else
|
||||
{
|
||||
param = FALSE;
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_SetParameter
|
||||
*
|
||||
* @brief Set a HID Dev parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param pValue - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t HidDev_SetParameter(uint8_t param, uint8_t len, void *pValue)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case HIDDEV_ERASE_ALLBONDS:
|
||||
if(len == 0)
|
||||
{
|
||||
// Drop connection
|
||||
if(hidDevGapState == GAPROLE_CONNECTED)
|
||||
{
|
||||
GAPRole_TerminateLink(gapConnHandle);
|
||||
}
|
||||
|
||||
// Erase bonding info
|
||||
GAPBondMgr_SetParameter(GAPBOND_ERASE_ALLBONDS, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = bleInvalidRange;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_GetParameter
|
||||
*
|
||||
* @brief Get a HID Dev parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param pValue - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t HidDev_GetParameter(uint8_t param, void *pValue)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_PasscodeRsp
|
||||
*
|
||||
* @brief Respond to a passcode request.
|
||||
*
|
||||
* @param status - SUCCESS if passcode is available, otherwise
|
||||
* see @ref SMP_PAIRING_FAILED_DEFINES.
|
||||
* @param passcode - integer value containing the passcode.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void HidDev_PasscodeRsp(uint8_t status, uint32_t passcode)
|
||||
{
|
||||
// Send passcode response
|
||||
GAPBondMgr_PasscodeRsp(gapConnHandle, status, passcode);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_ReadAttrCB
|
||||
*
|
||||
* @brief HID Dev attribute read callback.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be read
|
||||
* @param pLen - length of data to be read
|
||||
* @param offset - offset of the first octet to be read
|
||||
* @param maxLen - maximum length of data to be read
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
bStatus_t HidDev_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
|
||||
{
|
||||
bStatus_t status = SUCCESS;
|
||||
hidRptMap_t *pRpt;
|
||||
|
||||
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
|
||||
// Only report map is long
|
||||
if(offset > 0 && uuid != REPORT_MAP_UUID)
|
||||
{
|
||||
return (ATT_ERR_ATTR_NOT_LONG);
|
||||
}
|
||||
|
||||
if(uuid == REPORT_UUID ||
|
||||
uuid == BOOT_KEY_INPUT_UUID ||
|
||||
uuid == BOOT_KEY_OUTPUT_UUID ||
|
||||
uuid == BOOT_MOUSE_INPUT_UUID)
|
||||
{
|
||||
// find report ID in table
|
||||
if((pRpt = hidDevRptByHandle(pAttr->handle)) != NULL)
|
||||
{
|
||||
// execute report callback
|
||||
status = (*pHidDevCB->reportCB)(pRpt->id, pRpt->type, uuid,
|
||||
HID_DEV_OPER_READ, pLen, pValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pLen = 0;
|
||||
}
|
||||
}
|
||||
else if(uuid == REPORT_MAP_UUID)
|
||||
{
|
||||
// verify offset
|
||||
if(offset >= hidReportMapLen)
|
||||
{
|
||||
status = ATT_ERR_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine read length
|
||||
*pLen = MIN(maxLen, (hidReportMapLen - offset));
|
||||
|
||||
// copy data
|
||||
tmos_memcpy(pValue, pAttr->pValue + offset, *pLen);
|
||||
}
|
||||
}
|
||||
else if(uuid == HID_INFORMATION_UUID)
|
||||
{
|
||||
*pLen = HID_INFORMATION_LEN;
|
||||
tmos_memcpy(pValue, pAttr->pValue, HID_INFORMATION_LEN);
|
||||
}
|
||||
else if(uuid == GATT_REPORT_REF_UUID)
|
||||
{
|
||||
*pLen = HID_REPORT_REF_LEN;
|
||||
tmos_memcpy(pValue, pAttr->pValue, HID_REPORT_REF_LEN);
|
||||
}
|
||||
else if(uuid == PROTOCOL_MODE_UUID)
|
||||
{
|
||||
*pLen = HID_PROTOCOL_MODE_LEN;
|
||||
pValue[0] = pAttr->pValue[0];
|
||||
}
|
||||
else if(uuid == GATT_EXT_REPORT_REF_UUID)
|
||||
{
|
||||
*pLen = HID_EXT_REPORT_REF_LEN;
|
||||
tmos_memcpy(pValue, pAttr->pValue, HID_EXT_REPORT_REF_LEN);
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_WriteAttrCB
|
||||
*
|
||||
* @brief HID Dev attribute read callback.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be written
|
||||
* @param len - length of data
|
||||
* @param offset - offset of the first octet to be written
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
bStatus_t HidDev_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
|
||||
{
|
||||
uint16_t uuid;
|
||||
bStatus_t status = SUCCESS;
|
||||
hidRptMap_t *pRpt;
|
||||
|
||||
// Make sure it's not a blob operation (no attributes in the profile are long)
|
||||
if(offset > 0)
|
||||
{
|
||||
return (ATT_ERR_ATTR_NOT_LONG);
|
||||
}
|
||||
|
||||
uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
|
||||
if(uuid == REPORT_UUID ||
|
||||
uuid == BOOT_KEY_OUTPUT_UUID)
|
||||
{
|
||||
// find report ID in table
|
||||
if((pRpt = hidDevRptByHandle(pAttr->handle)) != NULL)
|
||||
{
|
||||
// execute report callback
|
||||
status = (*pHidDevCB->reportCB)(pRpt->id, pRpt->type, uuid,
|
||||
HID_DEV_OPER_WRITE, &len, pValue);
|
||||
}
|
||||
}
|
||||
else if(uuid == HID_CTRL_PT_UUID)
|
||||
{
|
||||
// Validate length and value range
|
||||
if(len == 1)
|
||||
{
|
||||
if(pValue[0] == HID_CMD_SUSPEND || pValue[0] == HID_CMD_EXIT_SUSPEND)
|
||||
{
|
||||
// execute HID app event callback
|
||||
(*pHidDevCB->evtCB)((pValue[0] == HID_CMD_SUSPEND) ? HID_DEV_SUSPEND_EVT : HID_DEV_EXIT_SUSPEND_EVT);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_INVALID_VALUE_SIZE;
|
||||
}
|
||||
}
|
||||
else if(uuid == GATT_CLIENT_CHAR_CFG_UUID)
|
||||
{
|
||||
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
|
||||
offset, GATT_CLIENT_CFG_NOTIFY);
|
||||
if(status == SUCCESS)
|
||||
{
|
||||
uint16_t charCfg = BUILD_UINT16(pValue[0], pValue[1]);
|
||||
|
||||
// find report ID in table
|
||||
if((pRpt = hidDevRptByCccdHandle(pAttr->handle)) != NULL)
|
||||
{
|
||||
// execute report callback
|
||||
(*pHidDevCB->reportCB)(pRpt->id, pRpt->type, uuid,
|
||||
(charCfg == GATT_CLIENT_CFG_NOTIFY) ? HID_DEV_OPER_ENABLE : HID_DEV_OPER_DISABLE,
|
||||
&len, pValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(uuid == PROTOCOL_MODE_UUID)
|
||||
{
|
||||
if(len == HID_PROTOCOL_MODE_LEN)
|
||||
{
|
||||
if(pValue[0] == HID_PROTOCOL_MODE_BOOT ||
|
||||
pValue[0] == HID_PROTOCOL_MODE_REPORT)
|
||||
{
|
||||
pAttr->pValue[0] = pValue[0];
|
||||
|
||||
// execute HID app event callback
|
||||
(*pHidDevCB->evtCB)((pValue[0] == HID_PROTOCOL_MODE_BOOT) ? HID_DEV_SET_BOOT_EVT : HID_DEV_SET_REPORT_EVT);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_INVALID_VALUE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDev_ProcessTMOSMsg
|
||||
*
|
||||
* @brief Process an incoming task message.
|
||||
*
|
||||
* @param pMsg - message to process
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDev_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
|
||||
{
|
||||
switch(pMsg->event)
|
||||
{
|
||||
case GATT_MSG_EVENT:
|
||||
{
|
||||
hidDevProcessGattMsg((gattMsgEvent_t *)pMsg);
|
||||
break;
|
||||
}
|
||||
|
||||
case GAP_MSG_EVENT:
|
||||
{
|
||||
hidDevProcessGAPMsg((gapRoleEvent_t *)pMsg);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevProcessGattMsg
|
||||
*
|
||||
* @brief Process GATT messages
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevProcessGattMsg(gattMsgEvent_t *pMsg)
|
||||
{
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevProcessGAPMsg
|
||||
*
|
||||
* @brief Process an incoming task message.
|
||||
*
|
||||
* @param pMsg - message to process
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevProcessGAPMsg(gapRoleEvent_t *pEvent)
|
||||
{
|
||||
switch(pEvent->gap.opcode)
|
||||
{
|
||||
case GAP_SCAN_REQUEST_EVENT:
|
||||
{
|
||||
PRINT("recv scan Req addr ");
|
||||
for(int i = 0; i < B_ADDR_LEN; i++)
|
||||
PRINT("%02x ", pEvent->scanReqEvt.scannerAddr[i]);
|
||||
PRINT("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case GAP_PHY_UPDATE_EVENT:
|
||||
{
|
||||
PRINT("Phy update Rx:%x Tx:%x ..\n", pEvent->linkPhyUpdate.connRxPHYS, pEvent->linkPhyUpdate.connTxPHYS);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevHandleConnStatusCB
|
||||
*
|
||||
* @brief Reset client char config.
|
||||
*
|
||||
* @param connHandle - connection handle
|
||||
* @param changeType - type of change
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevHandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
|
||||
{
|
||||
uint8_t i;
|
||||
hidRptMap_t *p = pHidDevRptTbl;
|
||||
uint16_t retHandle;
|
||||
gattAttribute_t *pAttr;
|
||||
|
||||
// Make sure this is not loopback connection
|
||||
if(connHandle != LOOPBACK_CONNHANDLE)
|
||||
{
|
||||
if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
|
||||
((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
|
||||
(!linkDB_Up(connHandle))))
|
||||
{
|
||||
for(i = hidDevRptTblLen; i > 0; i--, p++)
|
||||
{
|
||||
if(p->cccdHandle != 0)
|
||||
{
|
||||
if((pAttr = GATT_FindHandle(p->cccdHandle, &retHandle)) != NULL)
|
||||
{
|
||||
GATTServApp_InitCharCfg(connHandle, (gattCharCfg_t *)pAttr->pValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevDisconnected
|
||||
*
|
||||
* @brief Handle disconnect.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevDisconnected(void)
|
||||
{
|
||||
// Reset client characteristic configuration descriptors
|
||||
Batt_HandleConnStatusCB(gapConnHandle, LINKDB_STATUS_UPDATE_REMOVED);
|
||||
ScanParam_HandleConnStatusCB(gapConnHandle, LINKDB_STATUS_UPDATE_REMOVED);
|
||||
hidDevHandleConnStatusCB(gapConnHandle, LINKDB_STATUS_UPDATE_REMOVED);
|
||||
|
||||
// Reset state variables
|
||||
hidDevConnSecure = FALSE;
|
||||
hidProtocolMode = HID_PROTOCOL_MODE_REPORT;
|
||||
|
||||
// if bonded and normally connectable start advertising
|
||||
if((hidDevBondCount() > 0) &&
|
||||
(pHidDevCfg->hidFlags & HID_FLAGS_NORMALLY_CONNECTABLE))
|
||||
{
|
||||
hidDevLowAdvertising();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevGapStateCB
|
||||
*
|
||||
* @brief Notification from the profile of a state change.
|
||||
*
|
||||
* @param newState - new state
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevGapStateCB(gapRole_States_t newState, gapRoleEvent_t *pEvent)
|
||||
{
|
||||
uint8_t param;
|
||||
// if connected
|
||||
if(newState == GAPROLE_CONNECTED)
|
||||
{
|
||||
gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *)pEvent;
|
||||
|
||||
// get connection handle
|
||||
gapConnHandle = event->connectionHandle;
|
||||
|
||||
// connection not secure yet
|
||||
hidDevConnSecure = FALSE;
|
||||
|
||||
// don't start advertising when connection is closed
|
||||
param = FALSE;
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), ¶m);
|
||||
}
|
||||
// if disconnected
|
||||
else if(hidDevGapState == GAPROLE_CONNECTED &&
|
||||
newState != GAPROLE_CONNECTED)
|
||||
{
|
||||
hidDevDisconnected();
|
||||
|
||||
if(pairingStatus == SMP_PAIRING_FAILED_CONFIRM_VALUE)
|
||||
{
|
||||
// bonding failed due to mismatched confirm values
|
||||
hidDevInitialAdvertising();
|
||||
|
||||
pairingStatus = SUCCESS;
|
||||
}
|
||||
}
|
||||
// if started
|
||||
else if(newState == GAPROLE_STARTED)
|
||||
{
|
||||
// nothing to do for now!
|
||||
}
|
||||
|
||||
if(pHidDevCB && pHidDevCB->pfnStateChange)
|
||||
{
|
||||
// execute HID app state change callback
|
||||
(*pHidDevCB->pfnStateChange)(newState, pEvent);
|
||||
}
|
||||
|
||||
hidDevGapState = newState;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevParamUpdateCB
|
||||
*
|
||||
* @brief Parameter update complete callback
|
||||
*
|
||||
* @param connHandle - connect handle
|
||||
* connInterval - connect interval
|
||||
* connSlaveLatency - connect slave latency
|
||||
* connTimeout - connect timeout
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevParamUpdateCB(uint16_t connHandle, uint16_t connInterval,
|
||||
uint16_t connSlaveLatency, uint16_t connTimeout)
|
||||
{
|
||||
PRINT("Update %d - Int 0x%x - Latency %d\n", connHandle, connInterval, connSlaveLatency);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevPairStateCB
|
||||
*
|
||||
* @brief Pairing state callback.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevPairStateCB(uint16_t connHandle, uint8_t state, uint8_t status)
|
||||
{
|
||||
if(state == GAPBOND_PAIRING_STATE_COMPLETE)
|
||||
{
|
||||
if(status == SUCCESS)
|
||||
{
|
||||
hidDevConnSecure = TRUE;
|
||||
}
|
||||
|
||||
pairingStatus = status;
|
||||
}
|
||||
else if(state == GAPBOND_PAIRING_STATE_BONDED)
|
||||
{
|
||||
if(status == SUCCESS)
|
||||
{
|
||||
hidDevConnSecure = TRUE;
|
||||
|
||||
#if DEFAULT_SCAN_PARAM_NOTIFY_TEST == TRUE
|
||||
ScanParam_RefreshNotify(gapConnHandle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(state == GAPBOND_PAIRING_STATE_BOND_SAVED)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevPasscodeCB
|
||||
*
|
||||
* @brief Passcode callback.
|
||||
*
|
||||
* @param deviceAddr - address of device to pair with, and could be either public or random.
|
||||
* @param connectionHandle - connection handle
|
||||
* @param uiInputs - pairing User Interface Inputs - Ask user to input passcode
|
||||
* @param uiOutputs - pairing User Interface Outputs - Display passcode
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevPasscodeCB(uint8_t *deviceAddr, uint16_t connectionHandle,
|
||||
uint8_t uiInputs, uint8_t uiOutputs)
|
||||
{
|
||||
if(pHidDevCB && pHidDevCB->passcodeCB)
|
||||
{
|
||||
// execute HID app passcode callback
|
||||
(*pHidDevCB->passcodeCB)(deviceAddr, connectionHandle, uiInputs, uiOutputs);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t passkey;
|
||||
GAPBondMgr_GetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, &passkey);
|
||||
|
||||
// Send passcode response
|
||||
GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passkey);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevBattCB
|
||||
*
|
||||
* @brief Callback function for battery service.
|
||||
*
|
||||
* @param event - service event
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevBattCB(uint8_t event)
|
||||
{
|
||||
if(event == BATT_LEVEL_NOTI_ENABLED)
|
||||
{
|
||||
tmos_start_task(hidDevTaskId, BATT_PERIODIC_EVT, DEFAULT_BATT_PERIOD);
|
||||
}
|
||||
else if(event == BATT_LEVEL_NOTI_DISABLED)
|
||||
{
|
||||
// stop periodic measurement
|
||||
tmos_stop_task(hidDevTaskId, BATT_PERIODIC_EVT);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevScanParamCB
|
||||
*
|
||||
* @brief Callback function for scan parameter service.
|
||||
*
|
||||
* @param event - service event
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevScanParamCB(uint8_t event)
|
||||
{
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevBattPeriodicTask
|
||||
*
|
||||
* @brief Perform a periodic task for battery measurement.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void hidDevBattPeriodicTask(void)
|
||||
{
|
||||
// perform battery level check
|
||||
Batt_MeasLevel();
|
||||
|
||||
// Restart timer
|
||||
tmos_start_task(hidDevTaskId, BATT_PERIODIC_EVT, DEFAULT_BATT_PERIOD);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevRptByHandle
|
||||
*
|
||||
* @brief Find the HID report structure for the given handle.
|
||||
*
|
||||
* @param handle - ATT handle
|
||||
*
|
||||
* @return Pointer to HID report structure
|
||||
*/
|
||||
static hidRptMap_t *hidDevRptByHandle(uint16_t handle)
|
||||
{
|
||||
uint8_t i;
|
||||
hidRptMap_t *p = pHidDevRptTbl;
|
||||
|
||||
for(i = hidDevRptTblLen; i > 0; i--, p++)
|
||||
{
|
||||
if(p->handle == handle && p->mode == hidProtocolMode)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevRptByCccdHandle
|
||||
*
|
||||
* @brief Find the HID report structure for the given CCC handle.
|
||||
*
|
||||
* @param handle - ATT handle
|
||||
*
|
||||
* @return Pointer to HID report structure
|
||||
*/
|
||||
static hidRptMap_t *hidDevRptByCccdHandle(uint16_t handle)
|
||||
{
|
||||
uint8_t i;
|
||||
hidRptMap_t *p = pHidDevRptTbl;
|
||||
|
||||
for(i = hidDevRptTblLen; i > 0; i--, p++)
|
||||
{
|
||||
if(p->cccdHandle == handle)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevRptById
|
||||
*
|
||||
* @brief Find the HID report structure for the Report ID and type.
|
||||
*
|
||||
* @param id - HID report ID
|
||||
* @param type - HID report type
|
||||
*
|
||||
* @return Pointer to HID report structure
|
||||
*/
|
||||
static hidRptMap_t *hidDevRptById(uint8_t id, uint8_t type)
|
||||
{
|
||||
uint8_t i;
|
||||
hidRptMap_t *p = pHidDevRptTbl;
|
||||
|
||||
for(i = hidDevRptTblLen; i > 0; i--, p++)
|
||||
{
|
||||
if(p->id == id && p->type == type && p->mode == hidProtocolMode)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevSendReport
|
||||
*
|
||||
* @brief Send a HID report.
|
||||
*
|
||||
* @param id - HID report ID.
|
||||
* @param type - HID report type.
|
||||
* @param len - Length of report.
|
||||
* @param pData - Report data.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static uint8_t hidDevSendReport(uint8_t id, uint8_t type, uint8_t len, uint8_t *pData)
|
||||
{
|
||||
hidRptMap_t *pRpt;
|
||||
gattAttribute_t *pAttr;
|
||||
uint16_t retHandle;
|
||||
uint8_t state = bleNoResources;
|
||||
|
||||
// get att handle for report
|
||||
if((pRpt = hidDevRptById(id, type)) != NULL)
|
||||
{
|
||||
// if notifications are enabled
|
||||
if((pAttr = GATT_FindHandle(pRpt->cccdHandle, &retHandle)) != NULL)
|
||||
{
|
||||
uint16_t value;
|
||||
|
||||
value = GATTServApp_ReadCharCfg(gapConnHandle, (gattCharCfg_t *)pAttr->pValue);
|
||||
if(value & GATT_CLIENT_CFG_NOTIFY)
|
||||
{
|
||||
// Send report notification
|
||||
state = HidDev_sendNoti(pRpt->handle, len, pData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevSendNoti
|
||||
*
|
||||
* @brief Send a HID notification.
|
||||
*
|
||||
* @param handle - Attribute handle.
|
||||
* @param len - Length of report.
|
||||
* @param pData - Report data.
|
||||
*
|
||||
* @return Success or failure.
|
||||
*/
|
||||
static uint8_t HidDev_sendNoti(uint16_t handle, uint8_t len, uint8_t *pData)
|
||||
{
|
||||
uint8_t status;
|
||||
attHandleValueNoti_t noti;
|
||||
|
||||
noti.pValue = GATT_bm_alloc(gapConnHandle, ATT_HANDLE_VALUE_NOTI, len, NULL, 0);
|
||||
if(noti.pValue != NULL)
|
||||
{
|
||||
noti.handle = handle;
|
||||
noti.len = len;
|
||||
tmos_memcpy(noti.pValue, pData, len);
|
||||
|
||||
// Send notification
|
||||
status = GATT_Notification(gapConnHandle, ¬i, FALSE);
|
||||
if(status != SUCCESS)
|
||||
{
|
||||
GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = bleMemAllocError;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevHighAdvertising
|
||||
*
|
||||
* @brief Start advertising at a high duty cycle.
|
||||
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void hidDevHighAdvertising(void)
|
||||
{
|
||||
uint8_t param;
|
||||
|
||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, HID_HIGH_ADV_INT_MIN);
|
||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, HID_HIGH_ADV_INT_MAX);
|
||||
GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, HID_HIGH_ADV_TIMEOUT);
|
||||
|
||||
param = TRUE;
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), ¶m);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevLowAdvertising
|
||||
*
|
||||
* @brief Start advertising at a low duty cycle.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void hidDevLowAdvertising(void)
|
||||
{
|
||||
uint8_t param;
|
||||
|
||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, HID_LOW_ADV_INT_MIN);
|
||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, HID_LOW_ADV_INT_MAX);
|
||||
GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, HID_LOW_ADV_TIMEOUT);
|
||||
|
||||
param = TRUE;
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), ¶m);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevInitialAdvertising
|
||||
*
|
||||
* @brief Start advertising for initial connection
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static void hidDevInitialAdvertising(void)
|
||||
{
|
||||
uint8_t param;
|
||||
|
||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, HID_INITIAL_ADV_INT_MIN);
|
||||
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, HID_INITIAL_ADV_INT_MAX);
|
||||
GAP_SetParamValue(TGAP_LIM_ADV_TIMEOUT, HID_INITIAL_ADV_TIMEOUT);
|
||||
|
||||
param = TRUE;
|
||||
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), ¶m);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn hidDevBondCount
|
||||
*
|
||||
* @brief Gets the total number of bonded devices.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return number of bonded devices.
|
||||
*/
|
||||
static uint8_t hidDevBondCount(void)
|
||||
{
|
||||
uint8_t bondCnt = 0;
|
||||
|
||||
GAPBondMgr_GetParameter(GAPBOND_BOND_COUNT, &bondCnt);
|
||||
|
||||
return (bondCnt);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
637
profile/hidkbdservice.c
Normal file
637
profile/hidkbdservice.c
Normal file
@ -0,0 +1,637 @@
|
||||
/********************************** (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);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
172
profile/include/battservice.h
Normal file
172
profile/include/battservice.h
Normal file
@ -0,0 +1,172 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : battservice.h
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2018/12/11
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef BATTSERVICE_H
|
||||
#define BATTSERVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* INCLUDES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// Battery Service Get/Set Parameters
|
||||
#define BATT_PARAM_LEVEL 0
|
||||
#define BATT_PARAM_CRITICAL_LEVEL 1
|
||||
#define BATT_PARAM_SERVICE_HANDLE 2
|
||||
#define BATT_PARAM_BATT_LEVEL_IN_REPORT 3
|
||||
|
||||
// Callback events
|
||||
#define BATT_LEVEL_NOTI_ENABLED 1
|
||||
#define BATT_LEVEL_NOTI_DISABLED 2
|
||||
|
||||
// HID Report IDs for the service
|
||||
#define HID_RPT_ID_BATT_LEVEL_IN 4 // Battery Level input report ID
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
// Battery Service callback function
|
||||
typedef void (*battServiceCB_t)(uint8_t event);
|
||||
|
||||
// Battery measure HW setup function
|
||||
typedef void (*battServiceSetupCB_t)(void);
|
||||
|
||||
// Battery measure percentage calculation function
|
||||
typedef uint8_t (*battServiceCalcCB_t)(uint16_t adcVal);
|
||||
|
||||
// Battery measure HW teardown function
|
||||
typedef void (*battServiceTeardownCB_t)(void);
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Callbacks
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* API FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_AddService
|
||||
*
|
||||
* @brief Initializes the Battery service by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
extern bStatus_t Batt_AddService(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_Register
|
||||
*
|
||||
* @brief Register a callback function with the Battery Service.
|
||||
*
|
||||
* @param pfnServiceCB - Callback function.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void Batt_Register(battServiceCB_t pfnServiceCB);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_SetParameter
|
||||
*
|
||||
* @brief Set a Battery Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
extern bStatus_t Batt_SetParameter(uint8_t param, uint8_t len, void *value);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_GetParameter
|
||||
*
|
||||
* @brief Get a Battery parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param value - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
extern bStatus_t Batt_GetParameter(uint8_t param, void *value);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_MeasLevel
|
||||
*
|
||||
* @brief Measure the battery level and update the battery
|
||||
* level value in the service characteristics. If
|
||||
* the battery level-state characteristic is configured
|
||||
* for notification and the battery level has changed
|
||||
* since the last measurement, then a notification
|
||||
* will be sent.
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
extern bStatus_t Batt_MeasLevel(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_Setup
|
||||
*
|
||||
* @brief Set up which ADC source is to be used. Defaults to VDD/3.
|
||||
*
|
||||
* @param adc_ch - ADC Channel, e.g. HAL_ADC_CHN_AIN6
|
||||
* @param minVal - max battery level
|
||||
* @param maxVal - min battery level
|
||||
* @param sCB - HW setup callback
|
||||
* @param tCB - HW tear down callback
|
||||
* @param cCB - percentage calculation callback
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
extern void Batt_Setup(uint8_t adc_ch, uint16_t minVal, uint16_t maxVal,
|
||||
battServiceSetupCB_t sCB, battServiceTeardownCB_t tCB,
|
||||
battServiceCalcCB_t cCB);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Batt_HandleConnStatusCB
|
||||
*
|
||||
* @brief Battery Service link status change handler function.
|
||||
*
|
||||
* @param connHandle - connection handle
|
||||
* @param changeType - type of change
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void Batt_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BATTSERVICE_H */
|
109
profile/include/devinfoservice.h
Normal file
109
profile/include/devinfoservice.h
Normal file
@ -0,0 +1,109 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : devinfoservice.h
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2018/12/11
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef DEVINFOSERVICE_H
|
||||
#define DEVINFOSERVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* INCLUDES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// Device Information Service Parameters
|
||||
#define DEVINFO_SYSTEM_ID 0
|
||||
#define DEVINFO_MODEL_NUMBER 1
|
||||
#define DEVINFO_SERIAL_NUMBER 2
|
||||
#define DEVINFO_FIRMWARE_REV 3
|
||||
#define DEVINFO_HARDWARE_REV 4
|
||||
#define DEVINFO_SOFTWARE_REV 5
|
||||
#define DEVINFO_MANUFACTURER_NAME 6
|
||||
#define DEVINFO_11073_CERT_DATA 7
|
||||
#define DEVINFO_PNP_ID 8
|
||||
|
||||
// IEEE 11073 authoritative body values
|
||||
#define DEVINFO_11073_BODY_EMPTY 0
|
||||
#define DEVINFO_11073_BODY_IEEE 1
|
||||
#define DEVINFO_11073_BODY_CONTINUA 2
|
||||
#define DEVINFO_11073_BODY_EXP 254
|
||||
|
||||
// System ID length
|
||||
#define DEVINFO_SYSTEM_ID_LEN 8
|
||||
|
||||
// PnP ID length
|
||||
#define DEVINFO_PNP_ID_LEN 7
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Callbacks
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* API FUNCTIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
* DevInfo_AddService- Initializes the Device Information service by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
*/
|
||||
|
||||
extern bStatus_t DevInfo_AddService(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn DevInfo_SetParameter
|
||||
*
|
||||
* @brief Set a Device Information parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value);
|
||||
|
||||
/*
|
||||
* DevInfo_GetParameter - Get a Device Information parameter.
|
||||
*
|
||||
* param - Profile parameter ID
|
||||
* value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*/
|
||||
extern bStatus_t DevInfo_GetParameter(uint8_t param, void *value);
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DEVINFOSERVICE_H */
|
441
profile/include/hiddev.h
Normal file
441
profile/include/hiddev.h
Normal file
@ -0,0 +1,441 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : hiddev.h
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2018/12/11
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef HIDDEV_H
|
||||
#define HIDDEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* INCLUDES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// HID Device Parameters
|
||||
#define HIDDEV_ERASE_ALLBONDS 0 // Erase all of the bonded devices. Write Only. No Size.
|
||||
|
||||
// HID read/write operation
|
||||
#define HID_DEV_OPER_WRITE 0 // Write operation
|
||||
#define HID_DEV_OPER_READ 1 // Read operation
|
||||
#define HID_DEV_OPER_ENABLE 2 // Notification enabled for report ID
|
||||
#define HID_DEV_OPER_DISABLE 3 // Notifications disabled for report ID
|
||||
|
||||
// HID callback events
|
||||
#define HID_DEV_SUSPEND_EVT 0 // HID suspend
|
||||
#define HID_DEV_EXIT_SUSPEND_EVT 1 // HID exit suspend
|
||||
#define HID_DEV_SET_BOOT_EVT 2 // HID set boot mode
|
||||
#define HID_DEV_SET_REPORT_EVT 3 // HID set report mode
|
||||
|
||||
/* HID Report type */
|
||||
#define HID_REPORT_TYPE_INPUT 1
|
||||
#define HID_REPORT_TYPE_OUTPUT 2
|
||||
#define HID_REPORT_TYPE_FEATURE 3
|
||||
|
||||
/* HID information flags */
|
||||
#define HID_FLAGS_REMOTE_WAKE 0x01 // RemoteWake
|
||||
#define HID_FLAGS_NORMALLY_CONNECTABLE 0x02 // NormallyConnectable
|
||||
|
||||
/* Control point commands */
|
||||
#define HID_CMD_SUSPEND 0x00 // Suspend
|
||||
#define HID_CMD_EXIT_SUSPEND 0x01 // Exit Suspend
|
||||
|
||||
/* HID protocol mode values */
|
||||
#define HID_PROTOCOL_MODE_BOOT 0x00 // Boot Protocol Mode
|
||||
#define HID_PROTOCOL_MODE_REPORT 0x01 // Report Protocol Mode
|
||||
|
||||
/* Attribute value lengths */
|
||||
#define HID_PROTOCOL_MODE_LEN 1 // HID Protocol Mode
|
||||
#define HID_INFORMATION_LEN 4 // HID Information
|
||||
#define HID_REPORT_REF_LEN 2 // HID Report Reference Descriptor
|
||||
#define HID_EXT_REPORT_REF_LEN 2 // External Report Reference Descriptor
|
||||
|
||||
// HID Keyboard/Keypad Usage IDs (subset of the codes available in the USB HID Usage Tables spec)
|
||||
#define HID_KEYBOARD_RESERVED 0 // 0x00 - No event inidicated
|
||||
#define HID_KEYBOARD_A 4 // 0x04 - Keyboard a and A
|
||||
#define HID_KEYBOARD_B 5 // 0x05 - Keyboard b and B
|
||||
#define HID_KEYBOARD_C 6 // 0x06 - Keyboard c and C
|
||||
#define HID_KEYBOARD_D 7 // 0x07 - Keyboard d and D
|
||||
#define HID_KEYBOARD_E 8 // 0x08 - Keyboard e and E
|
||||
#define HID_KEYBOARD_F 9 // 0x09 - Keyboard f and F
|
||||
#define HID_KEYBOARD_G 10 // 0x0A - Keyboard g and G
|
||||
#define HID_KEYBOARD_H 11 // 0x0B - Keyboard h and H
|
||||
#define HID_KEYBOARD_I 12 // 0x0C - Keyboard i and I
|
||||
#define HID_KEYBOARD_J 13 // 0x0D - Keyboard j and J
|
||||
#define HID_KEYBOARD_K 14 // 0x0E - Keyboard k and K
|
||||
#define HID_KEYBOARD_L 15 // 0x0F - Keyboard l and L
|
||||
#define HID_KEYBOARD_M 16 // 0x10 - Keyboard m and M
|
||||
#define HID_KEYBOARD_N 17 // 0x11 - Keyboard n and N
|
||||
#define HID_KEYBOARD_O 18 // 0x12 - Keyboard o and O
|
||||
#define HID_KEYBOARD_P 19 // 0x13 - Keyboard p and p
|
||||
#define HID_KEYBOARD_Q 20 // 0x14 - Keyboard q and Q
|
||||
#define HID_KEYBOARD_R 21 // 0x15 - Keyboard r and R
|
||||
#define HID_KEYBOARD_S 22 // 0x16 - Keyboard s and S
|
||||
#define HID_KEYBOARD_T 23 // 0x17 - Keyboard t and T
|
||||
#define HID_KEYBOARD_U 24 // 0x18 - Keyboard u and U
|
||||
#define HID_KEYBOARD_V 25 // 0x19 - Keyboard v and V
|
||||
#define HID_KEYBOARD_W 26 // 0x1A - Keyboard w and W
|
||||
#define HID_KEYBOARD_X 27 // 0x1B - Keyboard x and X
|
||||
#define HID_KEYBOARD_Y 28 // 0x1C - Keyboard y and Y
|
||||
#define HID_KEYBOARD_Z 29 // 0x1D - Keyboard z and Z
|
||||
#define HID_KEYBOARD_1 30 // 0x1E - Keyboard 1 and !
|
||||
#define HID_KEYBOARD_2 31 // 0x1F - Keyboard 2 and @
|
||||
#define HID_KEYBOARD_3 32 // 0x20 - Keyboard 3 and #
|
||||
#define HID_KEYBOARD_4 33 // 0x21 - Keyboard 4 and %
|
||||
#define HID_KEYBOARD_5 34 // 0x22 - Keyboard 5 and %
|
||||
#define HID_KEYBOARD_6 35 // 0x23 - Keyboard 6 and ^
|
||||
#define HID_KEYBOARD_7 36 // 0x24 - Keyboard 7 and &
|
||||
#define HID_KEYBOARD_8 37 // 0x25 - Keyboard 8 and *
|
||||
#define HID_KEYBOARD_9 38 // 0x26 - Keyboard 9 and (
|
||||
#define HID_KEYBOARD_0 39 // 0x27 - Keyboard 0 and )
|
||||
#define HID_KEYBOARD_RETURN 40 // 0x28 - Keyboard Return (ENTER)
|
||||
#define HID_KEYBOARD_ESCAPE 41 // 0x29 - Keyboard ESCAPE
|
||||
#define HID_KEYBOARD_DELETE 42 // 0x2A - Keyboard DELETE (Backspace)
|
||||
#define HID_KEYBOARD_TAB 43 // 0x2B - Keyboard Tab
|
||||
#define HID_KEYBOARD_SPACEBAR 44 // 0x2C - Keyboard Spacebar
|
||||
#define HID_KEYBOARD_MINUS 45 // 0x2D - Keyboard - and (underscore)
|
||||
#define HID_KEYBOARD_EQUAL 46 // 0x2E - Keyboard = and +
|
||||
#define HID_KEYBOARD_LEFT_BRKT 47 // 0x2F - Keyboard [ and {
|
||||
#define HID_KEYBOARD_RIGHT_BRKT 48 // 0x30 - Keyboard ] and }
|
||||
#define HID_KEYBOARD_BACK_SLASH 49 // 0x31 - Keyboard \ and |
|
||||
#define HID_KEYBOARD_SEMI_COLON 51 // 0x33 - Keyboard ; and :
|
||||
#define HID_KEYBOARD_SGL_QUOTE 52 // 0x34 - Keyboard ' and "
|
||||
#define HID_KEYBOARD_GRV_ACCENT 53 // 0x35 - Keyboard Grave Accent and Tilde
|
||||
#define HID_KEYBOARD_COMMA 54 // 0x36 - Keyboard , and <
|
||||
#define HID_KEYBOARD_DOT 55 // 0x37 - Keyboard . and >
|
||||
#define HID_KEYBOARD_FWD_SLASH 56 // 0x38 - Keyboard / and ?
|
||||
#define HID_KEYBOARD_CAPS_LOCK 57 // 0x39 - Keyboard Caps Lock
|
||||
#define HID_KEYBOARD_F1 58 // 0x3A - Keyboard F1
|
||||
#define HID_KEYBOARD_F2 59 // 0x3B - Keyboard F2
|
||||
#define HID_KEYBOARD_F3 60 // 0x3C - Keyboard F3
|
||||
#define HID_KEYBOARD_F4 61 // 0x3D - Keyboard F4
|
||||
#define HID_KEYBOARD_F5 62 // 0x3E - Keyboard F5
|
||||
#define HID_KEYBOARD_F6 63 // 0x3F - Keyboard F6
|
||||
#define HID_KEYBOARD_F7 64 // 0x40 - Keyboard F7
|
||||
#define HID_KEYBOARD_F8 65 // 0x41 - Keyboard F8
|
||||
#define HID_KEYBOARD_F9 66 // 0x42 - Keyboard F9
|
||||
#define HID_KEYBOARD_F10 67 // 0x43 - Keyboard F10
|
||||
#define HID_KEYBOARD_F11 68 // 0x44 - Keyboard F11
|
||||
#define HID_KEYBOARD_F12 69 // 0x45 - Keyboard F12
|
||||
#define HID_KEYBOARD_PRNT_SCREEN 70 // 0x46 - Keyboard Print Screen
|
||||
#define HID_KEYBOARD_SCROLL_LOCK 71 // 0x47 - Keyboard Scroll Lock
|
||||
#define HID_KEYBOARD_PAUSE 72 // 0x48 - Keyboard Pause
|
||||
#define HID_KEYBOARD_INSERT 73 // 0x49 - Keyboard Insert
|
||||
#define HID_KEYBOARD_HOME 74 // 0x4A - Keyboard Home
|
||||
#define HID_KEYBOARD_PAGE_UP 75 // 0x4B - Keyboard PageUp
|
||||
#define HID_KEYBOARD_DELETE_FWD 76 // 0x4C - Keyboard Delete Forward
|
||||
#define HID_KEYBOARD_END 77 // 0x4D - Keyboard End
|
||||
#define HID_KEYBOARD_PAGE_DOWN 78 // 0x4E - Keyboard PageDown
|
||||
#define HID_KEYBOARD_RIGHT_ARROW 79 // 0x4F - Keyboard RightArrow
|
||||
#define HID_KEYBOARD_LEFT_ARROW 80 // 0x50 - Keyboard LeftArrow
|
||||
#define HID_KEYBOARD_DOWN_ARROW 81 // 0x51 - Keyboard DownArrow
|
||||
#define HID_KEYBOARD_UP_ARROW 82 // 0x52 - Keyboard UpArrow
|
||||
#define HID_KEYBPAD_NUM_LOCK 83 // 0x53 - Keypad Num Lock and Clear
|
||||
#define HID_KEYBPAD_DIVIDE 84 // 0x54 - Keypad /
|
||||
#define HID_KEYBOARD_MULTIPLY 85 // 0x55 - Keypad *
|
||||
#define HID_KEYBOARD_SUBTRACT 86 // 0x56 - Keypad -
|
||||
#define HID_KEYBPAD_ADD 87 // 0x57 - Keypad +
|
||||
#define HID_KEYBPAD_ENTER 88 // 0x58 - Keypad ENTER
|
||||
#define HID_KEYBPAD_1 89 // 0x59 - Keypad 1 and End
|
||||
#define HID_KEYBPAD_2 90 // 0x5A - Keypad 2 and Down Arrow
|
||||
#define HID_KEYBPAD_3 91 // 0x5B - Keypad 3 and PageDn
|
||||
#define HID_KEYBPAD_4 92 // 0x5C - Keypad 4 and Lfet Arrow
|
||||
#define HID_KEYBPAD_5 93 // 0x5D - Keypad 5
|
||||
#define HID_KEYBPAD_6 94 // 0x5E - Keypad 6 and Right Arrow
|
||||
#define HID_KEYBPAD_7 95 // 0x5F - Keypad 7 and Home
|
||||
#define HID_KEYBPAD_8 96 // 0x60 - Keypad 8 and Up Arrow
|
||||
#define HID_KEYBPAD_9 97 // 0x61 - Keypad 9 and PageUp
|
||||
#define HID_KEYBPAD_0 98 // 0x62 - Keypad 0 and Insert
|
||||
#define HID_KEYBPAD_DOT 99 // 0x63 - Keypad . and Delete
|
||||
#define HID_KEYBOARD_MUTE 127 // 0x7F - Keyboard Mute
|
||||
#define HID_KEYBOARD_VOLUME_UP 128 // 0x80 - Keyboard Volume up
|
||||
#define HID_KEYBOARD_VOLUME_DOWN 129 // 0x81 - Keyboard Volume down
|
||||
#define HID_KEYBOARD_LEFT_CTRL 224 // 0xE0 - Keyboard LeftContorl
|
||||
#define HID_KEYBOARD_LEFT_SHIFT 225 // 0xE1 - Keyboard LeftShift
|
||||
#define HID_KEYBOARD_LEFT_ALT 226 // 0xE2 - Keyboard LeftAlt
|
||||
#define HID_KEYBOARD_LEFT_GUI 227 // 0xE3 - Keyboard LeftGUI
|
||||
#define HID_KEYBOARD_RIGHT_CTRL 228 // 0xE4 - Keyboard LeftContorl
|
||||
#define HID_KEYBOARD_RIGHT_SHIFT 229 // 0xE5 - Keyboard LeftShift
|
||||
#define HID_KEYBOARD_RIGHT_ALT 230 // 0xE6 - Keyboard LeftAlt
|
||||
#define HID_KEYBOARD_RIGHT_GUI 231 // 0xE7 - Keyboard RightGUI
|
||||
|
||||
#define HID_MOUSE_BUTTON_LEFT 253
|
||||
#define HID_MOUSE_BUTTON_MIDDLE 254
|
||||
#define HID_MOUSE_BUTTON_RIGHT 255
|
||||
|
||||
// HID Consumer Usage IDs (subset of the codes available in the USB HID Usage Tables spec)
|
||||
#define HID_CONSUMER_POWER 48 // 0x30 - Power
|
||||
#define HID_CONSUMER_RESET 49 // 0x31 - Reset
|
||||
#define HID_CONSUMER_SLEEP 50 // 0x32 - Sleep
|
||||
|
||||
#define HID_CONSUMER_MENU 64 // 0x40 - Menu
|
||||
#define HID_CONSUMER_SELECTION 128 // 0x80 - Selection
|
||||
#define HID_CONSUMER_ASSIGN_SEL 129 // 0x81 - Assign Selection
|
||||
#define HID_CONSUMER_MODE_STEP 130 // 0x82 - Mode Step
|
||||
#define HID_CONSUMER_RECALL_LAST 131 // 0x83 - Recall Last
|
||||
#define HID_CONSUMER_QUIT 148 // 0x94 - Quit
|
||||
#define HID_CONSUMER_HELP 149 // 0x95 - Help
|
||||
#define HID_CONSUMER_CHANNEL_UP 156 // 0x9C - Channel Increment
|
||||
#define HID_CONSUMER_CHANNEL_DOWN 157 // 0x9D - Channel Decrement
|
||||
|
||||
#define HID_CONSUMER_PLAY 176 // 0xB0 - Play
|
||||
#define HID_CONSUMER_PAUSE 177 // 0xB1 - Pause
|
||||
#define HID_CONSUMER_RECORD 178 // 0xB2 - Record
|
||||
#define HID_CONSUMER_FAST_FORWARD 179 // 0xB3 - Fast Forward
|
||||
#define HID_CONSUMER_REWIND 180 // 0xB4 - Rewind
|
||||
#define HID_CONSUMER_SCAN_NEXT_TRK 181 // 0xB5 - Scan Next Track
|
||||
#define HID_CONSUMER_SCAN_PREV_TRK 182 // 0xB6 - Scan Previous Track
|
||||
#define HID_CONSUMER_STOP 183 // 0xB7 - Stop
|
||||
#define HID_CONSUMER_EJECT 184 // 0xB8 - Eject
|
||||
#define HID_CONSUMER_RANDOM_PLAY 185 // 0xB9 - Random Play
|
||||
#define HID_CONSUMER_SELECT_DISC 186 // 0xBA - Select Disk
|
||||
#define HID_CONSUMER_ENTER_DISC 187 // 0xBB - Enter Disc
|
||||
#define HID_CONSUMER_REPEAT 188 // 0xBC - Repeat
|
||||
#define HID_CONSUMER_STOP_EJECT 204 // 0xCC - Stop/Eject
|
||||
#define HID_CONSUMER_PLAY_PAUSE 205 // 0xCD - Play/Pause
|
||||
#define HID_CONSUMER_PLAY_SKIP 206 // 0xCE - Play/Skip
|
||||
|
||||
#define HID_CONSUMER_VOLUME 224 // 0xE0 - Volume
|
||||
#define HID_CONSUMER_BALANCE 225 // 0xE1 - Balance
|
||||
#define HID_CONSUMER_MUTE 226 // 0xE2 - Mute
|
||||
#define HID_CONSUMER_BASS 227 // 0xE3 - Bass
|
||||
#define HID_CONSUMER_VOLUME_UP 233 // 0xE9 - Volume Increment
|
||||
#define HID_CONSUMER_VOLUME_DOWN 234 // 0xEA - Volume Decrement
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
// HID report mapping table
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; // Handle of report characteristic
|
||||
uint16_t cccdHandle; // Handle of CCCD for report characteristic
|
||||
uint8_t id; // Report ID
|
||||
uint8_t type; // Report type
|
||||
uint8_t mode; // Protocol mode (report or boot)
|
||||
} hidRptMap_t;
|
||||
|
||||
// HID dev configuration structure
|
||||
typedef struct
|
||||
{
|
||||
uint32_t idleTimeout; // Idle timeout in milliseconds
|
||||
uint8_t hidFlags; // HID feature flags
|
||||
|
||||
} hidDevCfg_t;
|
||||
|
||||
/*********************************************************************
|
||||
* Global Variables
|
||||
*/
|
||||
|
||||
// These variables are defined in the service .c file that uses HID Dev
|
||||
|
||||
// HID report map length
|
||||
extern uint16_t hidReportMapLen;
|
||||
|
||||
// HID protocol mode
|
||||
extern uint8_t hidProtocolMode;
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Callbacks
|
||||
*/
|
||||
|
||||
// HID Report callback
|
||||
typedef uint8_t (*hidDevReportCB_t)(uint8_t id, uint8_t type, uint16_t uuid,
|
||||
uint8_t oper, uint16_t *pLen, uint8_t *pData);
|
||||
|
||||
// HID event callback
|
||||
typedef void (*hidDevEvtCB_t)(uint8_t evt);
|
||||
|
||||
// HID passcode callback
|
||||
typedef void (*hidDevPasscodeCB_t)(uint8_t *deviceAddr, uint16_t connectionHandle,
|
||||
uint8_t uiInputs, uint8_t uiOutputs);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
hidDevReportCB_t reportCB;
|
||||
hidDevEvtCB_t evtCB;
|
||||
hidDevPasscodeCB_t passcodeCB;
|
||||
gapRolesStateNotify_t pfnStateChange; //!< Whenever the device changes state
|
||||
} hidDevCB_t;
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Init
|
||||
*
|
||||
* @brief Initialization function for the Hid Dev Task.
|
||||
* This is called during initialization and should contain
|
||||
* any application specific initialization (ie. hardware
|
||||
* initialization/setup, table initialization, power up
|
||||
* notificaiton ... ).
|
||||
*
|
||||
* @param task_id - the ID assigned by TMOS. This ID should be
|
||||
* used to send messages and set timers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
extern void HidDev_Init(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_ProcessEvent
|
||||
*
|
||||
* @brief Hid Dev Task event processor. This function
|
||||
* is called to process all events for the task. Events
|
||||
* include timers, messages and any other user defined events.
|
||||
*
|
||||
* @param task_id - The TMOS assigned task ID.
|
||||
* @param events - events to process. This is a bit map and can
|
||||
* contain more than one event.
|
||||
*
|
||||
* @return events not processed
|
||||
*/
|
||||
extern uint16_t HidDev_ProcessEvent(uint8_t task_id, uint16_t events);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Register
|
||||
*
|
||||
* @brief Register a callback function with HID Dev.
|
||||
*
|
||||
* @param pCfg - Parameter configuration.
|
||||
* @param pCBs - Callback function.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void HidDev_Register(hidDevCfg_t *pCfg, hidDevCB_t *pCBs);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_RegisterReports
|
||||
*
|
||||
* @brief Register the report table with HID Dev.
|
||||
*
|
||||
* @param numReports - Length of report table.
|
||||
* @param pRpt - Report table.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void HidDev_RegisterReports(uint8_t numReports, hidRptMap_t *pRpt);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Report
|
||||
*
|
||||
* @brief Send a HID report.
|
||||
*
|
||||
* @param id - HID report ID.
|
||||
* @param type - HID report type.
|
||||
* @param len - Length of report.
|
||||
* @param pData - Report data.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern uint8_t HidDev_Report(uint8_t id, uint8_t type, uint8_t len, uint8_t *pData);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_Close
|
||||
*
|
||||
* @brief Close the connection or stop advertising.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void HidDev_Close(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_SetParameter
|
||||
*
|
||||
* @brief Set a HID Dev parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param pValue - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
extern bStatus_t HidDev_SetParameter(uint8_t param, uint8_t len, void *pValue);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_GetParameter
|
||||
*
|
||||
* @brief Get a HID Dev parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param pValue - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
extern bStatus_t HidDev_GetParameter(uint8_t param, void *pValue);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_PasscodeRsp
|
||||
*
|
||||
* @brief Respond to a passcode request.
|
||||
*
|
||||
* @param status - SUCCESS if passcode is available, otherwise
|
||||
* see @ref SMP_PAIRING_FAILED_DEFINES.
|
||||
* @param passcode - integer value containing the passcode.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
extern void HidDev_PasscodeRsp(uint8_t status, uint32_t passcode);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_ReadAttrCB
|
||||
*
|
||||
* @brief HID Dev attribute read callback.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be read
|
||||
* @param pLen - length of data to be read
|
||||
* @param offset - offset of the first octet to be read
|
||||
* @param maxLen - maximum length of data to be read
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
extern bStatus_t HidDev_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HidDev_WriteAttrCB
|
||||
*
|
||||
* @brief HID Dev attribute read callback.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be written
|
||||
* @param len - length of data
|
||||
* @param offset - offset of the first octet to be written
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
extern bStatus_t HidDev_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HIDDEV_H */
|
112
profile/include/hidkbdservice.h
Normal file
112
profile/include/hidkbdservice.h
Normal file
@ -0,0 +1,112 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : hidkbdservice.h
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef HIDKBDSERVICE_H
|
||||
#define HIDKBDSERVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* INCLUDES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// Number of HID reports defined in the service
|
||||
#define HID_NUM_REPORTS 7
|
||||
|
||||
// HID Report IDs for the service
|
||||
#define HID_RPT_ID_KEY_IN 0 // Keyboard input report ID
|
||||
#define HID_RPT_ID_MOUSE_IN 1 // Mouse input report ID
|
||||
#define HID_RPT_ID_LED_OUT 0 // LED output report ID
|
||||
#define HID_RPT_ID_FEATURE 0 // Feature report ID
|
||||
|
||||
// HID feature flags
|
||||
#define HID_FEATURE_FLAGS HID_FLAGS_REMOTE_WAKE
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Callbacks
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* API FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Hid_AddService
|
||||
*
|
||||
* @brief Initializes the HID service for keyboard by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
extern bStatus_t Hid_AddService(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @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.
|
||||
*/
|
||||
extern uint8_t Hid_SetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint8_t len,
|
||||
void *pValue);
|
||||
|
||||
/*********************************************************************
|
||||
* @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.
|
||||
*/
|
||||
extern uint8_t Hid_GetParameter(uint8_t id, uint8_t type, uint16_t uuid, uint16_t *pLen, void *pValue);
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HIDKBDSERVICE_H */
|
133
profile/include/scanparamservice.h
Normal file
133
profile/include/scanparamservice.h
Normal file
@ -0,0 +1,133 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : scanparamservice.h
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2018/12/11
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SCANPARAMSERVICE_H
|
||||
#define SCANPARAMSERVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* INCLUDES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
// Scan Characteristic Lengths
|
||||
#define SCAN_INTERVAL_WINDOW_CHAR_LEN 4
|
||||
#define SCAN_PARAM_REFRESH_LEN 1
|
||||
|
||||
// Scan Parameter Refresh Values
|
||||
#define SCAN_PARAM_REFRESH_REQ 0x00
|
||||
|
||||
// Callback events
|
||||
#define SCAN_INTERVAL_WINDOW_SET 1
|
||||
|
||||
// Get/Set parameters
|
||||
#define SCAN_PARAM_PARAM_INTERVAL 0
|
||||
#define SCAN_PARAM_PARAM_WINDOW 1
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Callbacks
|
||||
*/
|
||||
|
||||
// Scan Parameters Service callback function
|
||||
typedef void (*scanParamServiceCB_t)(uint8_t event);
|
||||
|
||||
/*********************************************************************
|
||||
* API FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_AddService
|
||||
*
|
||||
* @brief Initializes the Service by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
extern bStatus_t ScanParam_AddService(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_Register
|
||||
*
|
||||
* @brief Register a callback function with the Scan Parameters Service.
|
||||
*
|
||||
* @param pfnServiceCB - Callback function.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void ScanParam_Register(scanParamServiceCB_t pfnServiceCB);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_SetParameter
|
||||
*
|
||||
* @brief Set a Scan Parameters Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
extern bStatus_t ScanParam_SetParameter(uint8_t param, uint8_t len, void *value);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_GetParameter
|
||||
*
|
||||
* @brief Get a Scan Parameters Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param value - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
extern bStatus_t ScanParam_GetParameter(uint8_t param, void *value);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_RefreshNotify
|
||||
*
|
||||
* @brief Notify the peer to refresh the scan parameters.
|
||||
*
|
||||
* @param connHandle - connection handle
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
extern void ScanParam_RefreshNotify(uint16_t connHandle);
|
||||
|
||||
extern void ScanParam_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SCANPARAMSERVICE_H */
|
405
profile/scanparamservice.c
Normal file
405
profile/scanparamservice.c
Normal file
@ -0,0 +1,405 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : scanparamservice.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 "scanparamservice.h"
|
||||
|
||||
/*********************************************************************
|
||||
* MACROS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* TYPEDEFS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* GLOBAL VARIABLES
|
||||
*/
|
||||
// Scan parameters service
|
||||
const uint8_t scanParamServUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(SCAN_PARAM_SERV_UUID), HI_UINT16(SCAN_PARAM_SERV_UUID)};
|
||||
|
||||
// Scan interval window characteristic
|
||||
const uint8_t scanIntervalWindowUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(SCAN_INTERVAL_WINDOW_UUID), HI_UINT16(SCAN_INTERVAL_WINDOW_UUID)};
|
||||
|
||||
// Scan parameter refresh characteristic
|
||||
const uint8_t scanParamRefreshUUID[ATT_BT_UUID_SIZE] = {
|
||||
LO_UINT16(SCAN_REFRESH_UUID), HI_UINT16(SCAN_REFRESH_UUID)};
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL VARIABLES
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* EXTERNAL FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL VARIABLES
|
||||
*/
|
||||
|
||||
// Application callback
|
||||
static scanParamServiceCB_t scanParamServiceCB;
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Attributes - variables
|
||||
*/
|
||||
|
||||
// Scan Parameters Service attribute
|
||||
static const gattAttrType_t scanParamService = {ATT_BT_UUID_SIZE, scanParamServUUID};
|
||||
|
||||
// Scan Interval Window characteristic
|
||||
static uint8_t scanIntervalWindowProps = GATT_PROP_WRITE_NO_RSP;
|
||||
static uint8_t scanIntervalWindow[SCAN_INTERVAL_WINDOW_CHAR_LEN];
|
||||
|
||||
// Scan Parameter Refresh characteristic
|
||||
static uint8_t scanParamRefreshProps = GATT_PROP_NOTIFY;
|
||||
static uint8_t scanParamRefresh[SCAN_PARAM_REFRESH_LEN];
|
||||
static gattCharCfg_t scanParamRefreshClientCharCfg[GATT_MAX_NUM_CONN];
|
||||
|
||||
/*********************************************************************
|
||||
* Profile Attributes - Table
|
||||
*/
|
||||
|
||||
static gattAttribute_t scanParamAttrTbl[] = {
|
||||
// Scan Parameters Service attribute
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
|
||||
GATT_PERMIT_READ, /* permissions */
|
||||
0, /* handle */
|
||||
(uint8_t *)&scanParamService /* pValue */
|
||||
},
|
||||
|
||||
// Scan Interval Window declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&scanIntervalWindowProps},
|
||||
|
||||
// Scan Interval Window characteristic
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, scanIntervalWindowUUID},
|
||||
GATT_PERMIT_ENCRYPT_WRITE,
|
||||
0,
|
||||
scanIntervalWindow},
|
||||
|
||||
// Scan Parameter Refresh declaration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, characterUUID},
|
||||
GATT_PERMIT_READ,
|
||||
0,
|
||||
&scanParamRefreshProps},
|
||||
|
||||
// Scan Parameter Refresh characteristic
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, scanParamRefreshUUID},
|
||||
0,
|
||||
0,
|
||||
scanParamRefresh},
|
||||
|
||||
// Scan Parameter Refresh characteristic client characteristic configuration
|
||||
{
|
||||
{ATT_BT_UUID_SIZE, clientCharCfgUUID},
|
||||
GATT_PERMIT_READ | GATT_PERMIT_ENCRYPT_WRITE,
|
||||
0,
|
||||
(uint8_t *)&scanParamRefreshClientCharCfg}
|
||||
};
|
||||
|
||||
// Attribute index enumeration-- these indexes match array elements above
|
||||
enum
|
||||
{
|
||||
SCAN_PARAM_SERVICE_IDX, // Scan Parameters Service
|
||||
SCAN_PARAM_INTERVAL_DECL_IDX, // Scan Interval Window declaration
|
||||
SCAN_PARAM_INTERVAL_IDX, // Scan Interval Window characteristic
|
||||
SCAN_PARAM_REFRESH_DECL_IDX, // Scan Parameter Refresh declaration
|
||||
SCAN_PARAM_REFRESH_IDX, // Scan Parameter Refresh characteristic
|
||||
SCAN_PARAM_REFRESH_CCCD_IDX // Scan Parameter Refresh characteristic client characteristic configuration
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* LOCAL FUNCTIONS
|
||||
*/
|
||||
static bStatus_t scanParamWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
|
||||
static bStatus_t scanParamReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
|
||||
|
||||
/*********************************************************************
|
||||
* PROFILE CALLBACKS
|
||||
*/
|
||||
|
||||
// Service Callbacks
|
||||
gattServiceCBs_t scanParamCBs = {
|
||||
scanParamReadAttrCB, // Read callback function pointer
|
||||
scanParamWriteAttrCB, // Write callback function pointer
|
||||
NULL // Authorization callback function pointer
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* PUBLIC FUNCTIONS
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_AddService
|
||||
*
|
||||
* @brief Initializes the Battery Service by registering
|
||||
* GATT attributes with the GATT server.
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
bStatus_t ScanParam_AddService(void)
|
||||
{
|
||||
uint8_t status = SUCCESS;
|
||||
|
||||
// Initialize Client Characteristic Configuration attributes
|
||||
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, scanParamRefreshClientCharCfg);
|
||||
|
||||
// Register GATT attribute list and CBs with GATT Server App
|
||||
status = GATTServApp_RegisterService(scanParamAttrTbl, GATT_NUM_ATTRS(scanParamAttrTbl), GATT_MAX_ENCRYPT_KEY_SIZE,
|
||||
&scanParamCBs);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_Register
|
||||
*
|
||||
* @brief Register a callback function with the Battery Service.
|
||||
*
|
||||
* @param pfnServiceCB - Callback function.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
extern void ScanParam_Register(scanParamServiceCB_t pfnServiceCB)
|
||||
{
|
||||
scanParamServiceCB = pfnServiceCB;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_SetParameter
|
||||
*
|
||||
* @brief Set a Battery Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param len - length of data to right
|
||||
* @param value - pointer to data to write. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t ScanParam_SetParameter(uint8_t param, uint8_t len, void *value)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_GetParameter
|
||||
*
|
||||
* @brief Get a Battery Service parameter.
|
||||
*
|
||||
* @param param - Profile parameter ID
|
||||
* @param value - pointer to data to get. This is dependent on
|
||||
* the parameter ID and WILL be cast to the appropriate
|
||||
* data type (example: data type of uint16_t will be cast to
|
||||
* uint16_t pointer).
|
||||
*
|
||||
* @return bStatus_t
|
||||
*/
|
||||
bStatus_t ScanParam_GetParameter(uint8_t param, void *value)
|
||||
{
|
||||
bStatus_t ret = SUCCESS;
|
||||
switch(param)
|
||||
{
|
||||
case SCAN_PARAM_PARAM_INTERVAL:
|
||||
*((uint16_t *)value) = BUILD_UINT16(scanIntervalWindow[0],
|
||||
scanIntervalWindow[1]);
|
||||
break;
|
||||
|
||||
case SCAN_PARAM_PARAM_WINDOW:
|
||||
*((uint16_t *)value) = BUILD_UINT16(scanIntervalWindow[2],
|
||||
scanIntervalWindow[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = INVALIDPARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_RefreshNotify
|
||||
*
|
||||
* @brief Notify the peer to refresh the scan parameters.
|
||||
*
|
||||
* @param connHandle - connection handle
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void ScanParam_RefreshNotify(uint16_t connHandle)
|
||||
{
|
||||
uint16_t value;
|
||||
|
||||
value = GATTServApp_ReadCharCfg(connHandle, scanParamRefreshClientCharCfg);
|
||||
if(value & GATT_CLIENT_CFG_NOTIFY)
|
||||
{
|
||||
attHandleValueNoti_t noti;
|
||||
|
||||
noti.pValue = GATT_bm_alloc(connHandle, ATT_HANDLE_VALUE_NOTI,
|
||||
SCAN_PARAM_REFRESH_LEN, NULL, 0);
|
||||
if(noti.pValue != NULL)
|
||||
{
|
||||
// send notification
|
||||
noti.handle = scanParamAttrTbl[SCAN_PARAM_REFRESH_CCCD_IDX].handle;
|
||||
noti.len = SCAN_PARAM_REFRESH_LEN;
|
||||
noti.pValue[0] = SCAN_PARAM_REFRESH_REQ;
|
||||
|
||||
if(GATT_Notification(connHandle, ¬i, FALSE) != SUCCESS)
|
||||
{
|
||||
GATT_bm_free((gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn scanParamReadAttrCB
|
||||
*
|
||||
* @brief GATT read callback.
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be read
|
||||
* @param pLen - length of data to be read
|
||||
* @param offset - offset of the first octet to be read
|
||||
* @param maxLen - maximum length of data to be read
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
static bStatus_t scanParamReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
|
||||
{
|
||||
bStatus_t status = SUCCESS;
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn scanParamWriteAttrCB
|
||||
*
|
||||
* @brief Validate attribute data prior to a write operation
|
||||
*
|
||||
* @param connHandle - connection message was received on
|
||||
* @param pAttr - pointer to attribute
|
||||
* @param pValue - pointer to data to be written
|
||||
* @param len - length of data
|
||||
* @param offset - offset of the first octet to be written
|
||||
*
|
||||
* @return Success or Failure
|
||||
*/
|
||||
static bStatus_t scanParamWriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
|
||||
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
|
||||
{
|
||||
uint16_t uuid;
|
||||
bStatus_t status = SUCCESS;
|
||||
|
||||
// Make sure it's not a blob operation (no attributes in the profile are long)
|
||||
if(offset > 0)
|
||||
{
|
||||
return (ATT_ERR_ATTR_NOT_LONG);
|
||||
}
|
||||
|
||||
uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
|
||||
// Only one writeable attribute
|
||||
if(uuid == SCAN_INTERVAL_WINDOW_UUID)
|
||||
{
|
||||
if(len == SCAN_INTERVAL_WINDOW_CHAR_LEN)
|
||||
{
|
||||
uint16_t interval = BUILD_UINT16(pValue[0], pValue[1]);
|
||||
uint16_t window = BUILD_UINT16(pValue[0], pValue[1]);
|
||||
|
||||
// Validate values
|
||||
if(window <= interval)
|
||||
{
|
||||
tmos_memcpy(pAttr->pValue, pValue, len);
|
||||
|
||||
(*scanParamServiceCB)(SCAN_INTERVAL_WINDOW_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_INVALID_VALUE_SIZE;
|
||||
}
|
||||
}
|
||||
else if(uuid == GATT_CLIENT_CHAR_CFG_UUID)
|
||||
{
|
||||
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
|
||||
offset, GATT_CLIENT_CFG_NOTIFY);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_ATTR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ScanParam_HandleConnStatusCB
|
||||
*
|
||||
* @brief Service link status change handler function.
|
||||
*
|
||||
* @param connHandle - connection handle
|
||||
* @param changeType - type of change
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ScanParam_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
|
||||
{
|
||||
// Make sure this is not loopback connection
|
||||
if(connHandle != LOOPBACK_CONNHANDLE)
|
||||
{
|
||||
// Reset Client Char Config if connection has dropped
|
||||
if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
|
||||
((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
|
||||
(!linkDB_Up(connHandle))))
|
||||
{
|
||||
GATTServApp_InitCharCfg(connHandle, scanParamRefreshClientCharCfg);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user