BLE芯片DA145XX系列:HOGP功能实现

DA145XX协议芯片支持配置HOGP功能。即模拟蓝牙键鼠之类的设备,实现和手机绑定后,靠近设备手机自动回连设备的功能。实现HOGP功能需要对默认SDK做特殊配置,具体流程如下:

1、配置宏定义

da1458x_config_basic.h文件:

/****************************************************************************************************************/
/* Enables the BLE security functionality in TASK_APP. If not defined BLE security related code is compiled out.*/
/****************************************************************************************************************/
#define CFG_APP_SECURITY

user_config.h文件:
(1)、对SMP参数的配置,具体根据项目需求配置做配置
(2)、配置广播内容,需要特定的广播内容,才能正常在手机蓝牙系统用界面实现设备信息

/******************************************************************************************* Security configuration******************************************************************************************//************************************************************* Device IO Capability (@see gap_io_cap)** - GAP_IO_CAP_DISPLAY_ONLY          Display Only* - GAP_IO_CAP_DISPLAY_YES_NO        Display Yes No* - GAP_IO_CAP_KB_ONLY               Keyboard Only* - GAP_IO_CAP_NO_INPUT_NO_OUTPUT    No Input No Output* - GAP_IO_CAP_KB_DISPLAY            Keyboard Display** Select only one option.*************************************************************/
#define USER_CFG_FEAT_IO_CAP    GAP_IO_CAP_NO_INPUT_NO_OUTPUT/************************************************************* OOB information (@see gap_oob)** - GAP_OOB_AUTH_DATA_NOT_PRESENT    OOB Data not present* - GAP_OOB_AUTH_DATA_PRESENT        OOB data present** Select only one option.* Note: OOB is only supported with Legacy Pairing*************************************************************/
#define USER_CFG_FEAT_OOB       GAP_OOB_AUTH_DATA_NOT_PRESENT/************************************************************* Authentication Requirements (@see gap_auth_mask)** - GAP_AUTH_NONE      None* - GAP_AUTH_BOND      Bond* - GAP_AUTH_MITM      MITM* - GAP_AUTH_SEC       Secure Connection* - GAP_AUTH_KEY       Keypress Notification (Not Supported)** Any combination of the above.*************************************************************/
#define USER_CFG_FEAT_AUTH_REQ  (GAP_AUTH_BOND | GAP_AUTH_MITM | GAP_AUTH_SEC)/************************************************************* Encryption Max key size (7 to 16) - USER_CFG_FEAT_KEY_SIZE*************************************************************/
#define USER_CFG_FEAT_KEY_SIZE  KEY_LEN/************************************************************* Device security requirements (@see gap_sec_req)** - GAP_NO_SEC                 No security (no authentication and encryption)* - GAP_SEC1_NOAUTH_PAIR_ENC   Unauthenticated pairing with encryption* - GAP_SEC1_AUTH_PAIR_ENC     Authenticated pairing with encryption* - GAP_SEC1_SEC_PAIR_ENC      Authenticated LE Secure Connections pairing with encryption* - GAP_SEC2_NOAUTH_DATA_SGN   Unauthenticated pairing with data signing* - GAP_SEC2_AUTH_DATA_SGN     Authentication pairing with data signing** Select only one option.*************************************************************/
#define USER_CFG_FEAT_SEC_REQ   GAP_SEC1_NOAUTH_PAIR_ENC/*************************************************************************************** Initiator key distribution (@see gap_kdist)** - GAP_KDIST_NONE             No Keys to distribute* - GAP_KDIST_ENCKEY           LTK (Encryption key) in distribution* - GAP_KDIST_IDKEY            IRK (ID key)in distribution* - GAP_KDIST_SIGNKEY          CSRK (Signature key) in distribution** Any combination of the above***************************************************************************************/
#define USER_CFG_FEAT_INIT_KDIST (GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY)/*************************************************************************************** Responder key distribution (@see gap_kdist)** - GAP_KDIST_NONE             No Keys to distribute* - GAP_KDIST_ENCKEY           LTK (Encryption key) in distribution* - GAP_KDIST_IDKEY            IRK (ID key)in distribution* - GAP_KDIST_SIGNKEY          CSRK (Signature key) in distribution** Any combination of the above***************************************************************************************/
#define USER_CFG_FEAT_RESP_KDIST (GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY)/// Advertising data
#define USER_ADVERTISE_DATA         ("\x03"\ADV_TYPE_APPEARANCE\ADV_APPEARANCE_KEYBOARD\"\x03"\ADV_TYPE_INCOMPLETE_LIST_16BIT_SERVICE_IDS\ADV_UUID_HUMAN_INTERFACE_DEVICE_SERVICE)

user_profiles_config.h文件:
配置SDK开启HOGP功能

/***************************************************************************************/
/* Used BLE profiles (used by "rwprf_config.h").                                       */
/***************************************************************************************/
#define CFG_PRF_HOGPD/************************************************************* CUSTS1 security requirements (@see app_prf_srv_perm)** - SRV_PERM_DISABLE       Disable access* - SRV_PERM_ENABLE        Enable access* - SRV_PERM_UNAUTH        Access Requires Unauthenticated link* - SRV_PERM_AUTH          Access Requires Authenticated link* - SRV_PERM_SECURE        Access Requires Authenticated Secure Connection Pairing** Select only one option.*************************************************************/
#define APP_CUSTS1_SEC_REQ  SRV_PERM_UNAUTH

user_callback_config.h文件:
引入部分头文件定义,配置SMP相关的回调函数,部分函数可以调用库,也可以自己根据实现

#if (BLE_APP_SEC)
#include "app_bond_db.h"
#endif // (BLE_APP_SEC)#if (BLE_HID_DEVICE)
#include "app_hogpd.h"
#endifstatic const struct app_callbacks user_app_callbacks = {.app_on_connection                  = user_app_connection,.app_on_disconnect                  = user_app_disconnect,.app_on_update_params_rejected      = NULL,.app_on_update_params_complete      = NULL,.app_on_set_dev_config_complete     = default_app_on_set_dev_config_complete,.app_on_adv_nonconn_complete        = NULL,.app_on_adv_undirect_complete       = user_app_adv_undirect_complete,.app_on_adv_direct_complete         = NULL,.app_on_db_init_complete            = default_app_on_db_init_complete,.app_on_scanning_completed          = NULL,.app_on_adv_report_ind              = NULL,.app_on_get_dev_name                = default_app_on_get_dev_name,.app_on_get_dev_appearance          = default_app_on_get_dev_appearance,.app_on_get_dev_slv_pref_params     = default_app_on_get_dev_slv_pref_params,.app_on_set_dev_info                = default_app_on_set_dev_info,.app_on_data_length_change          = NULL,.app_on_update_params_request       = default_app_update_params_request,.app_on_generate_static_random_addr = default_app_generate_static_random_addr,.app_on_svc_changed_cfg_ind         = NULL,.app_on_get_peer_features           = NULL,
#if (BLE_APP_SEC).app_on_pairing_request             = user_app_on_pairing_request,.app_on_tk_exch                     = user_app_on_tk_exch,.app_on_irk_exch                    = NULL,.app_on_csrk_exch                   = default_app_on_csrk_exch,.app_on_ltk_exch                    = default_app_on_ltk_exch,.app_on_pairing_succeeded           = user_app_on_pairing_succeeded,.app_on_encrypt_ind                 = NULL,.app_on_encrypt_req_ind             = user_app_on_encrypt_req_ind,.app_on_security_req_ind            = NULL,.app_on_addr_solved_ind             = default_app_on_addr_solved_ind,.app_on_addr_resolve_failed         = default_app_on_addr_resolve_failed,
#if !defined (__DA14531_01__) && !defined (__DA14535__).app_on_ral_cmp_evt                 = default_app_on_ral_cmp_evt,.app_on_ral_size_ind                = NULL,.app_on_ral_addr_ind                = NULL,
#endif // not for DA14531-01, DA14535
#endif // (BLE_APP_SEC)
};#if (BLE_APP_SEC)
static const struct app_bond_db_callbacks user_app_bond_db_callbacks = {.app_bdb_init                       = default_app_bdb_init,.app_bdb_get_size                   = default_app_bdb_get_size,.app_bdb_add_entry                  = default_app_bdb_add_entry,.app_bdb_remove_entry               = default_app_bdb_remove_entry,.app_bdb_search_entry               = default_app_bdb_search_entry,.app_bdb_get_number_of_stored_irks  = default_app_bdb_get_number_of_stored_irks,.app_bdb_get_stored_irks            = default_app_bdb_get_stored_irks,.app_bdb_get_device_info_from_slot  = default_app_bdb_get_device_info_from_slot,
};
#endif // (BLE_APP_SEC)#define app_process_catch_rest_cb       user_catch_rest_hndlstatic const struct arch_main_loop_callbacks user_app_main_loop_callbacks = {.app_on_init            = user_app_init,// By default the watchdog timer is reloaded and resumed when the system wakes up.// The user has to take into account the watchdog timer handling (keep it running,// freeze it, reload it, resume it, etc), when the app_on_ble_powered() is being// called and may potentially affect the main loop..app_on_ble_powered     = NULL,// By default the watchdog timer is reloaded and resumed when the system wakes up.// The user has to take into account the watchdog timer handling (keep it running,// freeze it, reload it, resume it, etc), when the app_on_system_powered() is being// called and may potentially affect the main loop..app_on_system_powered  = NULL,.app_before_sleep       = NULL,.app_validate_sleep     = NULL,.app_going_to_sleep     = NULL,.app_resume_from_sleep  = NULL,
};// Place in this structure the app_<profile>_db_create and app_<profile>_enable functions
// for SIG profiles that do not have this function already implemented in the SDK
// or if you want to override the functionality. Check the prf_func array in the SDK
// for your reference of which profiles are supported.
static const struct prf_func_callbacks user_prf_funcs[] =
{
#if BLE_HID_DEVICE{TASK_ID_HOGPD,			app_hogpd_create_db, app_hogpd_enable},
#endif{TASK_ID_INVALID,    NULL, NULL}   // DO NOT MOVE. Must always be last
};

2、实现SMP相关自定义函数

user_app_init里的两段代码,第一段使IOS客户端也实现重连功能,第二段会使BLE连接GATT通讯必须要先完成SMP配对后才可进行

//处理配对请求
void user_app_on_pairing_request(uint8_t conidx, struct gapc_bond_req_ind const *param)
{if(System_Sta.hogp_switch){app_easy_security_send_pairing_rsp(conidx, param);}else{app_easy_security_reject_encryption(conidx);}
}//蓝牙安全认证配对成功回调
void user_app_on_pairing_succeeded(uint8_t conidx)
{if (app_sec_env[conidx].auth & GAP_AUTH_BOND){app_easy_security_bdb_add_entry(&app_sec_env[0]);	//添加绑定信息}
}//交换TK回调
void user_app_on_tk_exch(uint8_t conidx,struct gapc_bond_req_ind const * param)
{app_easy_security_accept_encryption(conidx);
}//收到安全连接检查请求
//HOGP回连后,会触发该回调
void user_app_on_encrypt_req_ind(uint8_t conidx,struct gapc_encrypt_req_ind const *param)
{const struct app_sec_bond_data_env_tag *pbd = NULL;pbd = app_easy_security_bdb_search_entry(SEARCH_BY_EDIV_TYPE, (void *) &param->ediv, 2);// If peer has been found in DBif(pbd){// Store device bond data to security environmentapp_sec_env[conidx] = *pbd;// Accept encryptionapp_easy_security_accept_encryption(conidx);}// If peer has not been found in DBelse{// Reject encryption, disconnectapp_easy_security_reject_encryption(conidx);}
}//处理APP事件回调
void user_catch_rest_hndl(ke_msg_id_t const msgid,void const *param,ke_task_id_t const dest_id,ke_task_id_t const src_id)
{switch(msgid){//添加:26xx HID事件
#if BLE_HID_DEVICEcase HOGPD_REPORT_UPD_RSP:case HOGPD_PROTO_MODE_REQ_IND:case HOGPD_NTF_CFG_IND:case HOGPD_CTNL_PT_IND:case HOGPD_REPORT_REQ_IND:{app_hogpd_process_handler(msgid, param, dest_id, src_id);break;}
#endif // BLE_HID_DEVICEdefault:break;}
}//APP初始化
void user_app_init(void)
{
//额外添加以下代码:#if (BLE_HID_DEVICE)app_set_prf_srv_perm(TASK_ID_DISS, SRV_PERM_UNAUTH);app_set_prf_srv_perm(TASK_ID_BASS, SRV_PERM_UNAUTH);app_set_prf_srv_perm(TASK_ID_HOGPD, SRV_PERM_UNAUTH);
#endif#if (BLE_APP_SEC)// Set service security requirementsapp_set_prf_srv_perm(TASK_ID_CUSTS1, SRV_PERM_UNAUTH);// Fetch bond data from the external memoryapp_set_prf_srv_perm(TASK_ID_GATT_CLIENT, SRV_PERM_UNAUTH);app_easy_security_bdb_init();
#endif // (BLE_APP_SEC)	
}

3、添加相关的库文件到项目中

app_security.c
app_security_task.c
app_easy_security.c
app_bond_db.c
这些文件在sdk\app_modules\src目录下引入

hogpd.c
hogpd_task.c
这些文件在sdk\ble_stack\profiles\hogp目录下引入

4、实现部分HOGP相关文件,配置HOGP相关的参数信息
具体可以参考github上官方的HOGP工程示例
https://github.com/dialog-semiconductor/BLE_SDK6_examples
项目下的示例工程:
interfaces/HID-Gamepad-Digitizer
具体要实现以下文件,可根据自身的业务逻辑进行修改:
app_hogpd.c

/******************************************************************************************** \file app_hogpd.c** \brief Keyboard (HID) over GATT Application entry point.** Copyright (C) 2020 Dialog Semiconductor.* This computer program includes Confidential, Proprietary Information  * of Dialog Semiconductor. All Rights Reserved.** <bluetooth.support@diasemi.com>******************************************************************************************//*** \addtogroup USER* \{* \addtogroup PROFILE* \{* \addtogroup APP_HOGPD** \{*//** INCLUDE FILES*****************************************************************************************/#include "rwip_config.h"             // SW configuration#if (BLE_HID_DEVICE)#include <user_hogpd_config.h>
#include "app_hogpd.h"
#include "prf_utils.h"
//#include "port_platform.h"
#include "app_prf_perm_types.h"
#include "arch_console.h"uint16_t report_ntf;
uint8_t hogpd_conidx;#define REPORT_TO_MASK(index) (HOGPD_CFG_REPORT_NTF_EN << index)#if HID_NUM_OF_REPORTS > HOGPD_NB_REPORT_INST_MAX#error "Maximum munber of HID reports exceeded. Please increase HOGPD_NB_REPORT_INST_MAX"
#endif/******************************************************************************************* @brief Enables the HOGPD profile ** @param   None** @return  void*****************************************************************************************/
void app_hogpd_enable(uint8_t conidx)
{   // Allocate the message//arch_printf("app_hogpd_enable\n");struct hogpd_enable_req * req = KE_MSG_ALLOC(HOGPD_ENABLE_REQ, prf_get_task_from_id(TASK_ID_HOGPD), TASK_APP,hogpd_enable_req);hogpd_conidx = conidx;// Fill in the parameter structurereq->conidx = hogpd_conidx;report_ntf = 0;//report_ntf = 1;//#ifdef ALWAYS_ENALBE_REPORTS   int i;for (i=0; i<HID_NUM_OF_REPORTS; i++) {if((hogpd_reports[i].cfg & HOGPD_CFG_REPORT_IN) == HOGPD_CFG_REPORT_IN) {report_ntf |= REPORT_TO_MASK(i); }}        
//#endifreq->ntf_cfg[0] = report_ntf;// Send the messageke_msg_send(req);    
}/******************************************************************************************* \brief Creates the HID over GATT database** \param   None*****************************************************************************************/
void app_hogpd_create_db(void)
{   struct hogpd_db_cfg* db_cfg;struct gapm_profile_task_add_cmd *req = KE_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD,TASK_GAPM, TASK_APP,gapm_profile_task_add_cmd, sizeof(struct hogpd_db_cfg));// Fill messagereq->operation = GAPM_PROFILE_TASK_ADD;req->prf_task_id = TASK_ID_HOGPD;req->app_task = TASK_APP;req->sec_lvl = get_user_prf_srv_perm(TASK_ID_HOGPD);req->start_hdl = 0;// Set parametersdb_cfg = (struct hogpd_db_cfg*) req->param;struct hogpd_hids_cfg *cfg = &db_cfg->cfg[0];              db_cfg->hids_nb = 1;struct hids_hid_info *hid_info = &cfg->hid_info;        cfg->svc_features |= HOGPD_CFG_BOOT_KB_WR;cfg->report_nb = HID_NUM_OF_REPORTS;uint8_t i;for(i = 0; i < HID_NUM_OF_REPORTS; i++) {cfg->report_id[i]=hogpd_reports[i].id;cfg->report_char_cfg[i]=hogpd_reports[i].cfg;}for(i = HID_NUM_OF_REPORTS; i< HOGPD_NB_REPORT_INST_MAX;i++){cfg->report_id[i]=0;cfg->report_char_cfg[i]=0;}hid_info->bcdHID = 0x100;hid_info->bCountryCode = 0;hid_info->flags = HIDS_REMOTE_WAKE_CAPABLE; ke_msg_send(req);      
}bool app_hogpd_send_report(uint8_t report_idx, uint8_t *data, uint16_t length, enum hogpd_report_type type)
{struct hogpd_report_upd_req *req;// Allocate the messagereq = KE_MSG_ALLOC_DYN(HOGPD_REPORT_UPD_REQ, prf_get_task_from_id(TASK_ID_HOGPD), TASK_APP, hogpd_report_upd_req, length);if (!req) {return false;}req->conidx = hogpd_conidx;struct hogpd_report_info *report = &req->report;// Fill in the parameter structure// TODO: find the index from the report numberreport->hid_idx = 0;ASSERT_ERROR((type != HOGPD_BOOT_KEYBOARD_INPUT_REPORT && type != HOGPD_BOOT_MOUSE_INPUT_REPORT) || report_idx == 0 );ASSERT_ERROR((type != HOGPD_BOOT_KEYBOARD_INPUT_REPORT && type != HOGPD_BOOT_MOUSE_INPUT_REPORT) || length <= HOGPD_BOOT_REPORT_MAX_LEN);ASSERT_ERROR((type == HOGPD_BOOT_KEYBOARD_INPUT_REPORT || type == HOGPD_BOOT_MOUSE_INPUT_REPORT) || length <= HOGPD_REPORT_MAX_LEN);report->type = type;report->idx =  report_idx;report->length = length;memcpy(report->value, data, length);            ke_msg_send(req);    return true;
}uint8_t app_hogpd_get_protocol_mode(void)
{struct hogpd_env_tag* hogpd_env = PRF_ENV_GET(HOGPD, hogpd);return hogpd_env->svcs[0].proto_mode;
}uint16_t app_hogpd_report_handle(uint8_t report_nb)
{ASSERT_WARNING(report_nb<HOGPD_NB_REPORT_INST_MAX);struct hogpd_env_tag* hogpd_env = PRF_ENV_GET(HOGPD, hogpd);return hogpd_get_att_handle(hogpd_env, 0, HOGPD_IDX_REPORT_VAL, report_nb);    
}#endif/*** \}* \}* \}*/

app_hogpd.h

/******************************************************************************************** \file app_hogpd.h** \brief Keyboard (HID) Application entry point header file.** Copyright (C) 2020 Dialog Semiconductor.* This computer program includes Confidential, Proprietary Information  * of Dialog Semiconductor. All Rights Reserved.** <bluetooth.support@diasemi.com>******************************************************************************************/#ifndef _APP_HOGPD_H_
#define _APP_HOGPD_H_/*** \addtogroup USER* \{* \addtogroup PROFILE* \{* \addtogroup APP_HOGPD** \brief HOGPD Profile application implementation** \{*/#if (BLE_HID_DEVICE)#include "hogpd.h"
#include "hogpd_task.h"/******************************************************************************************* \brief Enables the HOGPD profile ** \param   conidx*****************************************************************************************/
void app_hogpd_enable(uint8_t conidx);/******************************************************************************************* \brief Creates the HID over GATT database*****************************************************************************************/
void app_hogpd_create_db(void);/******************************************************************************************* \brief    *****************************************************************************************/
bool app_hogpd_send_report(uint8_t report_idx, uint8_t *data, uint16_t length, enum hogpd_report_type type);/******************************************************************************************* \brief   *****************************************************************************************/
uint8_t app_hogpd_get_protocol_mode(void);uint16_t app_hogpd_report_handle(uint8_t report_nb);#endif/*** \}* \}* \}*/#endif // _APP_HOGPD_H_

app_hogpd_task.c

/******************************************************************************************** \file app_hogpd_task.c** \brief HID Keyboard handlers.** Copyright (C) 2020 Dialog Semiconductor.* This computer program includes Confidential, Proprietary Information  * of Dialog Semiconductor. All Rights Reserved.** <bluetooth.support@diasemi.com>******************************************************************************************//*** \addtogroup USER* \{* \addtogroup PROFILE* \{* \addtogroup APP_HOGPD** \{*//** INCLUDE FILES*****************************************************************************************/#include "rwip_config.h"               // SW configuration#if (BLE_HID_DEVICE)#include "app_hogpd_task.h"
#include <user_hogpd_config.h>
#include "app_entry_point.h"#include "uart.h"extern uint16_t report_ntf;#define REPORT_MAP_LEN sizeof(report_map)/******************************************************************************************* \brief   *****************************************************************************************/
static void app_hogpd_report_upd_rsp_handler(void const *param)
{struct hogpd_report_upd_rsp *par = (struct hogpd_report_upd_rsp *)param;//Clear pending ack's for param->report_nb == 0 (normal key report) and == 2 (ext. key report)switch (par->status) {case PRF_ERR_UNEXPECTED_LEN:break;case PRF_ERR_NTF_DISABLED:break;case PRF_ERR_REQ_DISALLOWED:break;case PRF_ERR_INVALID_PARAM:break;case PRF_ERR_FEATURE_NOT_SUPPORTED:break;}        
}__INLINE void app_hogpd_call_store_attibute_callback(uint16_t uuid, int attr_num, int value)
{//if(hogpd_params.store_attribute_callback !=NULL) {//    hogpd_params.store_attribute_callback(uuid, attr_num, value);//}
}/******************************************************************************************* \brief   *****************************************************************************************/
static void app_hogpd_proto_mode_ind_handler(void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id)
{struct hogpd_proto_mode_req_ind *par = (struct hogpd_proto_mode_req_ind *)param;if (hogpd_params.boot_protocol_mode) {app_hogpd_call_store_attibute_callback(ATT_CHAR_PROTOCOL_MODE, 0, par->proto_mode);} else if (par->proto_mode == HOGP_BOOT_PROTOCOL_MODE) {ASSERT_WARNING(0);}struct hogpd_proto_mode_cfm *prot_cfm = KE_MSG_ALLOC(HOGPD_PROTO_MODE_CFM, src_id, dest_id,hogpd_proto_mode_cfm);prot_cfm->conidx = par->conidx;prot_cfm->status = GAP_ERR_NO_ERROR;prot_cfm->hid_idx = par->hid_idx;prot_cfm->proto_mode = par->proto_mode;ke_msg_send(prot_cfm);
}/******************************************************************************************* \brief   *****************************************************************************************/
static void app_hogpd_ntf_config_ind_handler(void const *param)
{struct hogpd_ntf_cfg_ind *ind = (struct hogpd_ntf_cfg_ind *)param;uint16_t i;uint16_t new_ntf = ind->ntf_cfg[0];uint16_t ntf_xor = new_ntf ^ report_ntf;if(ntf_xor & 0x01) {app_hogpd_call_store_attibute_callback(ATT_CHAR_BOOT_KB_IN_REPORT, 0, new_ntf & 0x01);}uint8_t index=9;for (i=0x8000; i!=0x0020; i >>= 1 ) {if(ntf_xor & i) {app_hogpd_call_store_attibute_callback(ATT_CHAR_REPORT, index, (new_ntf & i) ? 1 : 0);}index--;}report_ntf = new_ntf;
}/******************************************************************************************* \brief   *****************************************************************************************/
static void app_hogpd_ctnl_pt_ind_handler(void const *param)
{struct hogpd_ctnl_pt_ind *ind = (struct hogpd_ctnl_pt_ind *)param;app_hogpd_call_store_attibute_callback(ATT_CHAR_HID_CTNL_PT, 0, ind->hid_ctnl_pt);
}/******************************************************************************************* \brief   *****************************************************************************************/
static void app_hogpd_report_ind_handler(void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id)
{struct hogpd_report_req_ind *par = (struct hogpd_report_req_ind *)param;uint8_t dummy_data[] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};uint8_t i;uint16_t report_length = 0;uint8_t *report_data = NULL;if(par->operation == HOGPD_OP_REPORT_READ) {        switch(par->report.type) {case HOGPD_REPORT:for(i = 0; i < HID_NUM_OF_REPORTS; i++) {if( i == par->report.idx ) {report_data = dummy_data;report_length = hogpd_reports[par->report.idx].size;if(hogpd_reports[i].read_callback != NULL) {(hogpd_reports[i].read_callback)(KE_IDX_GET(src_id), report_data, &report_length);}break;}}            break;case HOGPD_REPORT_MAP:report_length = REPORT_MAP_LEN;report_data = (uint8_t *)report_map;break;case HOGPD_BOOT_KEYBOARD_INPUT_REPORT:case HOGPD_BOOT_KEYBOARD_OUTPUT_REPORT:default: break;            }                }if(par->operation == HOGPD_OP_REPORT_WRITE && par->report.type == HOGPD_REPORT) {for(i = 0; i < HID_NUM_OF_REPORTS; i++) {if( i == par->report.idx ) {if(hogpd_reports[i].write_callback != NULL) {(hogpd_reports[i].write_callback)(KE_IDX_GET(src_id), &par->report);}break;}}            }struct hogpd_report_cfm * cfm = KE_MSG_ALLOC_DYN(HOGPD_REPORT_CFM,src_id, dest_id,hogpd_report_cfm,report_length);cfm->conidx         = KE_IDX_GET(src_id);cfm->status         = ATT_ERR_NO_ERROR;cfm->operation      = par->operation;cfm->report.hid_idx = par->report.hid_idx;cfm->report.idx     = par->report.idx;cfm->report.type    = par->report.type;cfm->report.length = report_length;memcpy(cfm->report.value, report_data, report_length);ke_msg_send(cfm);
}// Called when the Service Changed indication has been successfully received by the Host
enum process_event_response app_hogpd_process_handler(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id)
{switch(msgid) {case HOGPD_REPORT_UPD_RSP:app_hogpd_report_upd_rsp_handler(param);break;case HOGPD_PROTO_MODE_REQ_IND:app_hogpd_proto_mode_ind_handler(param, dest_id, src_id);break;case HOGPD_NTF_CFG_IND:app_hogpd_ntf_config_ind_handler(param);break;case HOGPD_CTNL_PT_IND:app_hogpd_ctnl_pt_ind_handler(param);break;case HOGPD_REPORT_REQ_IND:app_hogpd_report_ind_handler(param, dest_id, src_id);break;default:return PR_EVENT_UNHANDLED;}return PR_EVENT_HANDLED;
}#endif/*** \}* \}* \}*/

app_hogpd_task.h

/******************************************************************************************** \file app_hogpd_task.h** \brief HID Keyboard handlers header file.** Copyright (C) 2020 Dialog Semiconductor.* This computer program includes Confidential, Proprietary Information  * of Dialog Semiconductor. All Rights Reserved.** <bluetooth.support@diasemi.com>******************************************************************************************/#ifndef _APP_HOGPD_TASK_H_
#define _APP_HOGPD_TASK_H_/*** \addtogroup USER* \{* \addtogroup PROFILE* \{* \addtogroup APP_HOGPD** \brief HOGPD Profile application implementation** \{*/#include "ke_msg.h"
#include "hogpd.h"
#include "gattc_task.h"
#include "app_hogpd_defs.h"/** FUNCTION DECLARATIONS*****************************************************************************************//******************************************************************************************* \brief   Called when the Service Changed indication has been successfully received by the Host*          * \param[in] msgid* \param[in] param* \param[in] dest_id* \param[in] src_id** \return enum process_event_response******************************************************************************************/
enum process_event_response app_hogpd_process_handler(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id);/*** \}* \}* \}*/#endif // _APP_HOGPD_TASK_H_

user_hogpd_config.h
该文件会影响手机连接读取设备信息的HID配置,手机系统可能会根据这些参数将设备识别为不同的蓝牙外设并进行相关配置

/******************************************************************************************** \file user_hogpd_config.h** \brief HOGPDD configuration file.** Copyright (C) 2017 Dialog Semiconductor.* This computer program includes Confidential, Proprietary Information  * of Dialog Semiconductor. All Rights Reserved.** <bluetooth.support@diasemi.com>******************************************************************************************/#ifndef _USER_HOGPD_CONFIG_H_
#define _USER_HOGPD_CONFIG_H_/******************************************************************************************* \addtogroup CONFIGURATION* \{* \addtogroup PROFILE_CONFIG* \{* \addtogroup HOGPD_CFG** \brief BLE HOGPD profile configuration* \{*****************************************************************************************/#include "app_hogpd_defs.h"
#include "hogpd.h"
#include "hogpd_task.h"#define CFG_USE_DIGITIZER   (0)
#define CFG_USE_JOYSTICKS		(0)#define HID_MOUSE_MOTION_REPORT_ID       	0x01 // Mouse motion report
#define HID_MOUSE_MOTION_REPORT_SIZE     	8    // The size of the mouse motion report#define HID_GAMEPAD_AXIS_REPORT_ID        		0x02 // Mouse buttons report
#define HID_GAMEPAD_AXIS_REPORT_SIZE	        			4    // The size of the Mouse buttons report#define HID_GAMEPAD_BUTTONS_REPORT_ID     		0x03 // Advanced buttons report
#define HID_GAMEPAD_BUTTONS_REPORT_SIZE   		2    // The size of the advanced buttons reportenum hogpd_indexes {HID_MOUSE_MOTION_REPORT_IDX = 0,HID_GAMEPAD_AXIS_REPORT_IDX,
//		HID_GAMEPAD_BUTTONS_REPORT_IDX,HID_NUM_OF_REPORTS // Don't remove this.
};static const hogpd_reports_t hogpd_reports[HID_NUM_OF_REPORTS] = 
{[HID_MOUSE_MOTION_REPORT_IDX]  = {.id             = HID_MOUSE_MOTION_REPORT_ID,           .size           = HID_MOUSE_MOTION_REPORT_SIZE,     .cfg            = HOGPD_CFG_REPORT_IN | HOGPD_REPORT_NTF_CFG_MASK | HOGPD_CFG_REPORT_WR, .read_callback  = NULL,.write_callback = NULL},[HID_GAMEPAD_AXIS_REPORT_IDX]  	 = {.id           = HID_GAMEPAD_AXIS_REPORT_ID,           .size           = HID_GAMEPAD_AXIS_REPORT_SIZE,     .cfg            = HOGPD_CFG_REPORT_IN | HOGPD_REPORT_NTF_CFG_MASK | HOGPD_CFG_REPORT_WR, .read_callback  = NULL,.write_callback = NULL},																	//	[HID_GAMEPAD_BUTTONS_REPORT_IDX]    = {.id        = HID_GAMEPAD_BUTTONS_REPORT_ID,           
//                                    .size           = HID_GAMEPAD_BUTTONS_REPORT_SIZE,     
//                                    .cfg            = HOGPD_CFG_REPORT_IN | HOGPD_REPORT_NTF_CFG_MASK | HOGPD_CFG_REPORT_WR,
//                                    .read_callback  = NULL,
//                                    .write_callback = NULL},																	
};static const hogpd_params_t hogpd_params = {
/******************************************************************************************* Use BOOT MODE                                                                        *****************************************************************************************/.boot_protocol_mode   = true,//false,/******************************************************************************************* Include BATT in HID                                                                  *****************************************************************************************/.batt_external_report = false,/******************************************************************************************* Set RemoteWakeup mode. Remote Host may not handle properly remote wakeup when the * inactivity timeout is on. Some Hosts do not expect to receive LL_TERMINATE_IND from * Wakeup capable devices while they are sleeping.*****************************************************************************************/.remote_wakeup        = false,/******************************************************************************************* Set normally connectable mode                                                                *****************************************************************************************/
#ifdef NORMALLY_CONNECTABLE    .normally_connectable = true,
#else.normally_connectable = false,
#endif  /******************************************************************************************* \brief Callback for storing CCC and attributes*****************************************************************************************/
#ifdef HAS_CONNECTION_FSM.store_attribute_callback = user_store_ccc,
#else.store_attribute_callback = NULL,
#endif
};// Report Descriptor == Report Map (HID1_11.pdf section E.6)
static const uint8_t report_map[]  =
{HID_USAGE_PAGE          (HID_USAGE_PAGE_GENERIC_DESKTOP),                   // USAGE_PAGE (Generic Desktop)HID_USAGE               (HID_GEN_DESKTOP_USAGE_MOUSE),                    	// USAGE (Gamepad)HID_COLLECTION          (HID_APPLICATION),                                  // COLLECTION (Application)HID_REPORT_ID           (HID_GAMEPAD_AXIS_REPORT_ID),                                             // REPORT_ID (1)HID_COLLECTION          (HID_LOGICAL),                                      // COLLECTION (Logical)HID_USAGE               (HID_GEN_DESKTOP_USAGE_X),                          // USAGE (X)HID_USAGE               (HID_GEN_DESKTOP_USAGE_Y),                          // USAGE (Y)HID_USAGE               (HID_GEN_DESKTOP_USAGE_Z),                          // USAGE (Z)HID_USAGE               (HID_GEN_DESKTOP_USAGE_RZ),                         // USAGE (RZ)//HID_USAGE               (HID_GEN_DESKTOP_USAGE_RY),                         // USAGE (RY)//HID_USAGE               (HID_GEN_DESKTOP_USAGE_RZ),                         // USAGE (RZ)HID_LOGICAL_MIN_8       (0x00),                                             // LOGICAL_MINIMUM (0)HID_LOGICAL_MAX_8       (0xff),                                       // LOGICAL_MAXIMUM (255)HID_PHYSICAL_MIN_8      (0x00),                                             // PHYSICAL_MINIMUM (0)HID_PHYSICAL_MAX_8      (0xff),                                       // PHYSICAL_MAXIMUM (255)HID_REPORT_SIZE         (0x08),                                             // REPORT_SIZE (8)HID_REPORT_COUNT        (0x04),                                             // REPORT_COUNT (3)HID_INPUT               (HID_DATA_BIT | HID_VAR_BIT | HID_ABS_BIT),         // INPUT (Data,Var,Abs)HID_END_COLLECTION,                                                         //   END_COLLECTION//				HID_REPORT_ID           (HID_GAMEPAD_BUTTONS_REPORT_ID),                                             // REPORT_ID (2)    
//				HID_COLLECTION          (HID_LOGICAL),                                      // COLLECTION (Logical)
//						HID_USAGE_PAGE          (HID_USAGE_PAGE_BUTTONS),                           // USAGE_PAGE (Buttons)
//						HID_USAGE_MIN_8         (0x01),                                             // USAGE_MINIMUM (Button A)
//						HID_USAGE_MAX_8         (0x08),                                             // USAGE_MAXIMUM (Button R1)
//						HID_REPORT_COUNT        (0x08),                                             // REPORT_COUNT (16)
//						HID_REPORT_SIZE         (0x01),                                             // REPORT_SIZE (1)
//						HID_LOGICAL_MAX_8       (0x01),                                             // LOGICAL_MAXIMUM (1)
//						HID_LOGICAL_MIN_8       (0x00),                                             // LOGICAL_MINIMUM (0)
//						HID_INPUT               (HID_DATA_BIT | HID_VAR_BIT | HID_ABS_BIT),         // Input (Data, Variable, Absolute)
//						
//				HID_USAGE_PAGE          (HID_USAGE_PAGE_BUTTONS),                           // USAGE_PAGE (Buttons)
//						HID_USAGE_MIN_8         (0x09),                                             // USAGE_MINIMUM (Button R2)
//						HID_USAGE_MAX_8         (0x0F),                                             // USAGE_MAXIMUM (Button TR)
//						HID_REPORT_COUNT        (0x07),                                             // REPORT_COUNT (16)
//						HID_REPORT_SIZE         (0x01),                                             // REPORT_SIZE (1)
//						HID_LOGICAL_MAX_8       (0x01),                                             // LOGICAL_MAXIMUM (1)
//						HID_LOGICAL_MIN_8       (0x00),                                             // LOGICAL_MINIMUM (0)
//						HID_INPUT               (HID_DATA_BIT | HID_VAR_BIT | HID_ABS_BIT),         // Input (Data, Variable, Absolute)
//						HID_REPORT_COUNT        (0x01),                                             //1 bit padding
//						HID_INPUT               (HID_CONST_BIT | HID_ARY_BIT | HID_ABS_BIT),        //  Input (Cnst,Ary,Abs) 
//						//HID_REPORT_COUNT        (0x01),                                             // Report Count (1)
//						//HID_REPORT_SIZE         (0x06),                                             // Report Size (6)
//						//HID_INPUT               (HID_CONST_BIT),                                    // Input (Constant) for padding    
//				HID_END_COLLECTION,                          //   END_COLLECTIONHID_END_COLLECTION                           // END_COLLECTION
};#endif // _USER_HOGPD_CONFIG_H_

app_hogpd_defs.h
该文件无需修改,直接使用官方HOGP示例工程内的文件即可

至此SDK已经具备实现HOGP功能的相关配置。

5、解决6.20以上版本SDKHOGP功能编译错误
使用ARM compiler6编译器,工程默认开启Link-Time Optimization编译后,会导致hogpd_task..c内部的函数编译报错:
Error: L6137E: Symbol gattc_read_req_ind_handler was not preserved by the LTO codegen but is needed by the image.
应该是编译器将该函数优化掉了,主要是这几个函数在SDK的其它地方被配置成了ROM调用,这里实际是这几个函数和那边重名了。要解决这个文件,可以将函数名自行做修改(加了一个my_的前缀),防止其被优化掉:

const struct ke_msg_handler hogpd_default_state[] =
{{ HOGPD_ENABLE_REQ,              (ke_msg_func_t) hogpd_enable_req_handler },{ HOGPD_REPORT_UPD_REQ,          (ke_msg_func_t) hogpd_report_upd_req_handler },{ HOGPD_REPORT_CFM,              (ke_msg_func_t) hogpd_report_cfm_handler },{ HOGPD_PROTO_MODE_CFM,          (ke_msg_func_t) hogpd_proto_mode_cfm_handler },{ GATTC_ATT_INFO_REQ_IND,        (ke_msg_func_t) my_gattc_att_info_req_ind_handler },{ GATTC_WRITE_REQ_IND,           (ke_msg_func_t) my_gattc_write_req_ind_handler },{ GATTC_READ_REQ_IND,            (ke_msg_func_t) my_gattc_read_req_ind_handler },{ GATTC_CMP_EVT,                 (ke_msg_func_t) my_gattc_cmp_evt_handler },
};

注意函数的定义处也要做对应修改。修改后,编译即可正常通过。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/22036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java自学阶段二:JavaWeb开发06(mybatis学习)

目录&#xff1a; 学习目标mybatis的基础用法&#xff08;新增、删除、修改、查询&#xff09; 一&#xff1a;学习目标&#xff1a; 1&#xff09;了解mybatis的基础概念&#xff1b; 2&#xff09;学会mybatis的基础用法&#xff1b; 二、mybatis的基础概念&#xff1a; M…

手把手教你改进YOLOv8小目标检测(多尺度特征融合iAFF)

1,YOLOv8改进策略指南 YOLOv8是目标检测领域中一个重要的模型,它在YOLO系列的基础上进行了进一步的改进和优化。 根据搜索结果,YOLOv8的一些改进策略包括: 注意力机制的增加:通过引入注意力机制,可以提高模型对目标特征的捕捉能力,从而提升检测性能2369。 卷积和Block的…

Unity Obi Rope失效

文章目录 前言一、WebGL端Obi Rope失效二、Obi Rope 固定不牢三、使用Obi后卡顿总结 前言 Obi 是一款基于粒子的高级物理引擎&#xff0c;可模拟各种可变形材料的行为。 使用 Obi Rope&#xff0c;你可以在几秒内创建绳索和杆子&#xff0c;同时完全控制它们的形状和行为&…

scipy.io.loadmat加载.mat文件,出现KeyError: ‘xxx‘

源代码&#xff1a; input_image loadmat(rC:\Users\admin\Downloads\Indian_Pines\SVM/aa.mat)[aa] #影像图 错误显示&#xff1a; 解决方法&#xff1a; 因为loadmat函数读取出来的高光谱数据是dict格式的所以需要定位才能进行后续操作&#xff0c;定位通常是通过列名&a…

运筹说 第116期 | 算法介绍之排队论

在这个快节奏的时代&#xff0c;无论是线上购物、线下服务&#xff0c;还是工业生产&#xff0c;我们都不可避免地与“排队”打交道。今天小编将带你一起探索利用Python和MATLAB这两种编程工具&#xff0c;来求解排队论中的常见模型和排队优化问题。我们将从排队论的基础模型开…

U盘杀毒是否会导致文件丢失?误删文件如何恢复?

在数字化时代&#xff0c;U盘作为便携的数据存储设备&#xff0c;广泛应用于我们的日常生活与工作中。然而&#xff0c;随着网络环境的复杂化&#xff0c;U盘也时常成为病毒传播的媒介。因此&#xff0c;对U盘进行杀毒成为保护数据安全的重要步骤。但许多用户担心&#xff0c;给…

centos安装vscode的教程

centos安装vscode的教程 步骤一&#xff1a;打开vscode官网找到历史版本 历史版本链接 步骤二&#xff1a;找到文件下载的位置 在命令行中输入&#xff08;稍等片刻即可打开&#xff09;&#xff1a; /usr/share/code/bin/code关闭vscode后&#xff0c;可在应用程序----编程…

Java 线程间信息传递方式

方法一&#xff1a; 将共享数据定义为静态类变量 适合全局共享数据的场景&#xff0c;即进程内所有线程可访问。 将数据对象定义为静态类变量&#xff0c;进程内的所有线程即可在数据对象允许的范围内实现访问数据对象。 方法二&#xff1a; 使用volatile关键字在线程之间共享…

浏览器是如何解析CSS选择器的

在生成渲染树的过程中&#xff0c;渲染引擎会根据选择器提供的信息来遍历 DOM 树&#xff0c;找到对应的 DOM 节点后将样式规则附加到上面。 来看一段样式选择器代码、以及一段要应用样式的 HTML&#xff1a; css: .mod-nav h3 span {font-size: 16px; } html: <div c…

10Linux 进程管理学习笔记

Linux 进程管理 目录 文章目录 Linux 进程管理一.进程1.显示当前进程状态(ps)进程树(pstree)1.1实时显示进程信息(top)顶部概览信息&#xff1a;CPU 状态&#xff1a;内存状态&#xff1a;进程信息表头&#xff1a;进程列表&#xff1a;1.2(htop) 2.终止进程(kill)2.1通过名称…

Jetson Orin Nano安装使用;cuda、pytorch安装;yolo使用

参考: https://blog.csdn.net/q839039228/article/details/126278528 1、jtop工具安装 安装jtop资源查看: sudo apt update sudo apt upgrade安装: sudo apt install curl nanosudo pip install jetson-stats查看: jtop 按2查看GPU 按3查看CPU 2、JetPack套件 参…

修改云主机配置 - 内存增容

文章目录 一、修改云主机配置缘由二、修改云主机配置步骤1、查看云主机概述2、查看master云主机3、更改master云主机配置4、查看master云主机 三、使用Spark Shell玩Saprk SQL1、启动HDFS服务2、启动Spark集群3、启动集群模式Spark Shell4、读取文件生成单例数据帧5、将单列数据…

C语言----字符串、字符数组

一、定义 C语言中的字符串是以字符数组的形态存在的 在C语言中&#xff0c;没有字符串类型&#xff0c;字符串实际上是使用空字符\0结尾的一维字符数组。因此&#xff0c;\0是用于标记字符串的结束。 二 、如何创建字符串&#xff1f; 1.通过字符数组来创建字符串&#xff0…

某黑产组织最新攻击样本利用BYVOD技术的详细分析

前言概述 最近一两年BYVOD技术被广泛应用到了各种黑产攻击、APT攻击以及勒索病毒攻击活动当中&#xff0c;笔者近期在对某黑产组织进行跟踪&#xff0c;捕获到该组织的最新攻击样本&#xff0c;通过某安全厂商的驱动漏洞&#xff0c;利用BYVOD技术对抗其他安全软件包括各种EDR…

单片机+M26429+PAM8403+MH-M18无线蓝牙音频功放设计 原理图PCB源程序

目录 功能描述&#xff1a; 原理图 PCB ​代码 资料下载地址&#xff1a;单片机M26429PAM8403MH-M18无线蓝牙音频功放设计 原理图PCB源程序 功能描述&#xff1a; 1&#xff0c;无线蓝牙连接&#xff0c;手机可控制歌曲音频选择。 2&#xff0c;音频声音的大小可控制一排…

博客摘录「 Nuplayer 音视频同步学习笔记」2024年4月9日

4. AVsync Audio更新锚点时间 (1) AVsync原理 系统时间和媒体时间应该是线性关系: (mediaTimeUs - anchorTimeMediaUs) PlaybackRate*(nowUs - anchorTimeRealUs)。 所以理论上&#xff0c;我们可以根据锚点, 计算出任意一点的媒体时间对应的系统时间(Buffer应该播放的时间).…

三维模型轻量化工具:手工模型、BIM、倾斜摄影等皆可用!

老子云是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让一切3D模型在全网多端轻量化处理与展示&#xff0c;为行业数字化转型升级与数字孪生应用提供成套的3D可视化技术、产品与服务。 老子云是全球领先的数字孪生引擎技术及服务提供商&#xff0c;它专注于让…

Docker安装Bitbucket

centos7版本 [rootlocalhost ~]# cat /etc/os-release NAME"CentOS Linux" VERSION"7 (Core)" ID"centos" ID_LIKE"rhel fedora" VERSION_ID"7" PRETTY_NAME"CentOS Linux 7 (Core)" ANSI_COLOR"0;31"…

sectigo和certum ip ssl证书的区别

IP SSL证书是一种数字证书&#xff0c;为客户端和服务器之间的信息传输提供加密服务。但是和应用比较广泛的域名SSL证书相比&#xff0c;IP SSL证书是为只有公网IP地址的网站准备的数字证书。市场上常见的IP SSL证书品牌就是Sectigo和Certum&#xff0c;那么&#xff0c;这两种…

[AI Google] Ask Photos: 使用Gemini搜索照片的新方法

借助Gemini模型&#xff0c;将Google Photos提升到一个新的水平。 Google Photos是我们最早以AI为核心构建的产品之一&#xff0c;让你能够搜索照片和视频中的人、宠物、地点等。现在&#xff0c;我们通过我们最强大的AI模型Gemini对Google Photos进行重大升级。通过Ask Photos…