1854 lines
59 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
/*********************************************************************************************
* Filename : ble_hogp.c
* Description :
* Author :
* Email : zh-jieli.com
* Last modifiled : 2020-09-01 11:14
* Copyright:(c)JIELI 2011-2020 @ , All Rights Reserved.
*********************************************************************************************/
// *****************************************************************************
/* EXAMPLE_START
*
* @text All newer operating systems provide GATT Client functionality.
* The LE Counter examples demonstrates how to specify a minimal GATT Database
* with a custom GATT Service and a custom Characteristic that sends periodic
* notifications.
*/
// *****************************************************************************
#include "system/app_core.h"
#include "system/includes.h"
#include "app_config.h"
#include "app_action.h"
#include "btstack/btstack_task.h"
#include "btstack/bluetooth.h"
#include "user_cfg.h"
#include "vm.h"
#include "btcontroller_modules.h"
#include "bt_common.h"
#include "le_common.h"
#include "standard_hid.h"
#include "rcsp_bluetooth.h"
#include "JL_rcsp_api.h"
#include "update_loader_download.h"
#include "custom_cfg.h"
#include "ble_hogp_profile.h"
#include "gatt_common/le_gatt_common.h"
#include "app_comm_bt.h"
#if (TCFG_USER_BLE_ENABLE && CONFIG_HOGP_COMMON_ENABLE)
/* #if RCSP_BTMATE_EN */
/* #include "btstack/JL_rcsp_api.h" */
/* #include "rcsp_bluetooth.h" */
/* #endif */
#if LE_DEBUG_PRINT_EN
//#define log_info y_printf
#define log_info(x, ...) printf("[BLE_HOGP]" x " ", ## __VA_ARGS__)
#define log_info_hexdump put_buf
#else
#define log_info(...)
#define log_info_hexdump(...)
#endif
static u8 remote_ble_addr[7] = {0};
static void hid_timer_mouse_handler(void);
extern get_cur_bt_idx();
extern u8 get_key_timeout_flag();
#define EIR_TAG_STRING 0xd6, 0x05, 0x08, 0x00, 'J', 'L', 'A', 'I', 'S', 'D','K'
static const char user_tag_string[] = {EIR_TAG_STRING};
//用户可配对的这是样机跟客户开发的app配对的秘钥
//const u8 link_key_data[16] = {0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b};
#if CONFIG_BLE_HIGH_SPEED
//ATT发送的包长, note: 23 <=need >= MTU
#define ATT_LOCAL_MTU_SIZE (247)
#else
#define ATT_LOCAL_MTU_SIZE (64)
#endif
//ATT缓存的buffer支持缓存数据包个数
#define ATT_PACKET_NUMS_MAX (2)
//ATT缓存的buffer大小, note: need >= 23,可修改
#define ATT_SEND_CBUF_SIZE (ATT_PACKET_NUMS_MAX * (ATT_PACKET_HEAD_SIZE + ATT_LOCAL_MTU_SIZE))
static volatile hci_con_handle_t hogp_con_handle;
int ble_hid_timer_handle = 0;
//是否使能参数请求更新,0--disable, 1--enable
static uint8_t hogp_connection_update_enable = 1;
//连接参数表,按顺序优先请求,主机接受了就中止
static const struct conn_update_param_t Peripheral_Preferred_Connection_Parameters[] = {
{6, 9, 100, 600}, //android
/* {7, 7, 20, 300}, //mosue */
/* {20, 20, 20, 300}, //kb */
{12, 12, 30, 600}, //ios
{6, 12, 30, 600},// ios fast
};
//共可用的参数组数
#define CONN_PARAM_TABLE_CNT (sizeof(Peripheral_Preferred_Connection_Parameters)/sizeof(struct conn_update_param_t))
static u8 hogp_adv_data[ADV_RSP_PACKET_MAX];//max is 31
static u8 hogp_scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31
static u8 first_pair_flag; //第一次配对标记
static u8 is_hogp_active = 0; //不可进入sleep状态
static adv_cfg_t hogp_server_adv_config;
/*--------------------------------------------*/
//普通未连接广播周期 (unit:0.625ms)
#define ADV_INTERVAL_MIN (160 * 5)
/*------------------------------
,广,广;广
广,adv和rsp包
*/
#define PAIR_RECONNECT_ADV_EN 1 /*是否上电使用定向广播,优先绑定回连*/
//可选两种定向广播类型,
//ADV_DIRECT_IND (1.28s超时,interval 固定2ms)
//ADV_DIRECT_IND_LOW (interval 和 channel 跟普通广播设置一样)
//ADV_IND (无定向广播:interval 和 channel 跟普通广播设置一样)
static u8 pair_reconnect_adv_type = ADV_DIRECT_IND;
//等待回连状态下的广播周期 (unit:0.625ms)
#define PAIR_RECONNECT_ADV_INTERVAL (32) /*>=32, ADV_IND,ADV_DIRECT_IND_LOW,interval*/
static u32 pair_reconnect_adv_timeout = 5000;/*回连广播持续时间,ms*/
//广播通道设置置
static u8 le_adv_channel_sel = ADV_CHANNEL_ALL;
//--------------------------------------------
#define BLE_VM_HEAD_TAG (0xB35C)
#define BLE_VM_TAIL_TAG (0x5CB3)
struct pair_info_t {
u16 head_tag; //头标识
u8 pair_flag: 2; //配对信息是否有效
u8 direct_adv_cnt: 6; //定向广播次数
u8 direct_adv_flag: 1;
u8 peer_address_info[7]; //绑定的对方地址信息
u16 tail_tag;//尾标识
};
//配对信息表
static struct pair_info_t hogp_pair_info;
static u8 cur_peer_addr_info[7];//当前连接对方地址信息
#define REPEAT_DIRECT_ADV_COUNT (2)// *1.28s
//为了及时响应手机数据包某些流程会忽略进入latency的控制
//如下是定义忽略进入的interval个数
#define LATENCY_SKIP_INTERVAL_MIN (3)
#define LATENCY_SKIP_INTERVAL_KEEP (20)
#define LATENCY_SKIP_INTERVAL_LONG (0xffff)
//hid device infomation
static u8 Appearance[] = {BLE_APPEARANCE_GENERIC_HID & 0xff, BLE_APPEARANCE_GENERIC_HID >> 8}; //
static const char Manufacturer_Name_String[] = "zhuhai_jieli";
static const char Model_Number_String[] = "hid_mouse";
static const char Serial_Number_String[] = "000000";
static const char Hardware_Revision_String[] = "0.0.1";
static const char Firmware_Revision_String[] = "0.0.1";
static const char Software_Revision_String[] = "0.0.1";
static const u8 System_ID[] = {0, 0, 0, 0, 0, 0, 0, 0};
//定义的产品信息,for test
#define PNP_VID_SOURCE 0x02
#define PNP_VID 0x05ac //0x05d6
#define PNP_PID 0x022C //
#define PNP_PID_VERSION 0x011b //1.1.11
static u8 PnP_ID[] = {PNP_VID_SOURCE, PNP_VID & 0xFF, PNP_VID >> 8, PNP_PID & 0xFF, PNP_PID >> 8, PNP_PID_VERSION & 0xFF, PNP_PID_VERSION >> 8};
/* static const u8 PnP_ID[] = {0x02, 0x17, 0x27, 0x40, 0x00, 0x23, 0x00}; */
/* static const u8 PnP_ID[] = {0x02, 0xac, 0x05, 0x2c, 0x02, 0x1b, 0x01}; */
/* static const u8 hid_information[] = {0x11, 0x01, 0x00, 0x01}; */
/* static const u8 hid_information[] = {0x01, 0x01, 0x00, 0x03}; */
static const u8 hid_information[] = {0x11, 0x01, 0x00, 0x03};
static const u8 hid_information1[] = {0x00, 0x00, 0x00, 0x00};
static u8 *report_map; //描述符
static u16 report_map_size;//描述符大小
static u16 hogp_adv_timeout_number = 0;
#define HID_REPORT_MAP_DATA report_map
#define HID_REPORT_MAP_SIZE report_map_size
//report 发生变化通过service change 通知主机重新获取
static u8 hid_report_change = 0;
static u8 hid_battery_level = 88;
static u32 hid_battery_level_add_sum;/*电量采集累加*/
static u32 hid_battery_level_add_cnt;/*电量采集次数*/
#define HID_BATTERY_TIMER_SET (60000) /*定时检测电量变化的时间30~60*/
static u16 hid_battery_notify_timer_id;
static u8(*get_vbat_percent_call)(void) = NULL;
static void (*le_hogp_output_callback)(u8 *buffer, u16 size) = NULL;
//------------------------------------------------------
static void __hogp_resume_all_ccc_enable(u8 update_request);
static void __check_report_map_change(void);
void ble_hid_transfer_channel_recieve(u8 *packet, u16 size);
void ble_hid_transfer_channel_recieve1(u8 *packet, u16 size);
static uint16_t hogp_att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
static int hogp_att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
static int hogp_event_packet_handler(int event, u8 *packet, u16 size, u8 *ext_param);
static void hogp_adv_config_set(void);
static u8 hid_get_vbat_handle(void);
//------------------------------------------------------
static u8 multi_dev_adv_flag = 0; /*多地址设备切换广播*/
void set_multi_devices_adv_flag(u8 adv_flag)
{
multi_dev_adv_flag = adv_flag;
}
//输入passkey 加密
#define PASSKEY_ENABLE 0
static const sm_cfg_t hogp_sm_init_config = {
.slave_security_auto_req = 0,
.slave_set_wait_security = 0,
#if PASSKEY_ENABLE
.io_capabilities = IO_CAPABILITY_DISPLAY_ONLY,
#else
.io_capabilities = IO_CAPABILITY_NO_INPUT_NO_OUTPUT,
#endif
.authentication_req_flags = SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION,
.min_key_size = 7,
.max_key_size = 16,
.sm_cb_packet_handler = NULL,
};
const gatt_server_cfg_t hogp_server_init_cfg = {
.att_read_cb = &hogp_att_read_callback,
.att_write_cb = &hogp_att_write_callback,
.event_packet_handler = &hogp_event_packet_handler,
};
static gatt_ctrl_t hogp_gatt_control_block = {
//public
.mtu_size = ATT_LOCAL_MTU_SIZE,
.cbuffer_size = ATT_SEND_CBUF_SIZE,
.multi_dev_flag = 0,
//config
#if CONFIG_BT_GATT_SERVER_NUM
.server_config = &hogp_server_init_cfg,
#else
.server_config = NULL,
#endif
.client_config = NULL,
#if CONFIG_BT_SM_SUPPORT_ENABLE
.sm_config = &hogp_sm_init_config,
#else
.sm_config = NULL,
#endif
//cbk,event handle
.hci_cb_packet_handler = NULL,
};
/*************************************************************************************************/
/*!
* \brief app
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void __ble_bt_evnet_post(u32 arg_type, u8 priv_event, u8 *args, u32 value)
{
struct sys_event e;
e.type = SYS_BT_EVENT;
e.arg = (void *)arg_type;
e.u.bt.event = priv_event;
if (args) {
memcpy(e.u.bt.args, args, 7);
}
e.u.bt.value = value;
sys_event_notify(&e);
}
/*************************************************************************************************/
/*!
* \brief ble状态
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void __ble_state_to_user(u8 state, u8 reason)
{
static u8 ble_state = 0xff;
if (state != ble_state) {
log_info("ble_state:%02x===>%02x\n", ble_state, state);
ble_state = state;
__ble_bt_evnet_post(SYS_BT_EVENT_BLE_STATUS, state, NULL, reason);
}
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void __hogp_send_connetion_update_deal(u16 conn_handle)
{
if (hogp_connection_update_enable) {
if (0 == ble_gatt_server_connetion_update_request(conn_handle, Peripheral_Preferred_Connection_Parameters, CONN_PARAM_TABLE_CNT)) {
hogp_connection_update_enable = 0;
}
}
}
/*************************************************************************************************/
/*!
* \brief vm
*
* \param [in] rw_flag 0--read 1--write
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void __hogp_conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag)
{
int ret;
int vm_len = sizeof(struct pair_info_t);
log_info("-hogp_pair_info vm_do:%d\n", rw_flag);
if (rw_flag == 0) {
if (multi_dev_adv_flag) {
ret = syscfg_read(CFG_BLE_BONDING_REMOTE_INFO + get_cur_bt_idx(), (u8 *)info, vm_len);
} else {
ret = syscfg_read(CFG_BLE_BONDING_REMOTE_INFO, (u8 *)info, vm_len);
}
if (vm_len != ret) {
log_info("-null--\n");
memset(info, 0, vm_len);
}
if ((BLE_VM_HEAD_TAG == info->head_tag) && (BLE_VM_TAIL_TAG == info->tail_tag)) {
log_info("-exist--\n");
} else {
log_info("-reset vm--\n");
memset(info, 0, vm_len);
info->head_tag = BLE_VM_HEAD_TAG;
info->tail_tag = BLE_VM_TAIL_TAG;
}
} else {
if (multi_dev_adv_flag) {
syscfg_write(CFG_BLE_BONDING_REMOTE_INFO + get_cur_bt_idx(), (u8 *)info, vm_len);
} else {
syscfg_write(CFG_BLE_BONDING_REMOTE_INFO, (u8 *)info, vm_len);
}
}
log_info_hexdump(info, vm_len);
}
/*************************************************************************************************/
/*!
* \brief hid描述符
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static const u16 change_handle_table[2] = {ATT_CHARACTERISTIC_2a4b_01_VALUE_HANDLE, ATT_CHARACTERISTIC_2a4b_01_VALUE_HANDLE};
static void __check_report_map_change(void)
{
#if 0 //部分手机不支持
if (hid_report_change && first_pair_flag && ble_gatt_server_characteristic_ccc_get(hogp_con_handle, ATT_CHARACTERISTIC_2a05_01_CLIENT_CONFIGURATION_HANDLE)) {
log_info("###send services changed\n");
ble_comm_att_send_data(hogp_con_handle, ATT_CHARACTERISTIC_2a05_01_VALUE_HANDLE, change_handle_table, 4, ATT_OP_INDICATE);
hid_report_change = 0;
}
#endif
}
/*************************************************************************************************/
/*!
* \brief 使
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void __hogp_resume_all_ccc_enable(u8 update_request)
{
log_info("__hogp_resume_all_ccc_enable\n");
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a4d_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a4d_02_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a4d_04_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a4d_05_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a4d_06_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a4d_07_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_ae42_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_2a19_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
#if RCSP_BTMATE_EN
/* ble_gatt_server_characteristic_ccc_set(hogp_con_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY); */
/* ble_gatt_server_set_update_send(hogp_con_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, ATT_OP_AUTO_READ_CCC); */
/* set_rcsp_conn_handle(hogp_con_handle); */
#endif
if (update_request) {
__hogp_send_connetion_update_deal(hogp_con_handle);
}
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void __att_check_remote_result(u16 con_handle, remote_type_e remote_type)
{
log_info("le_hogp %02x:remote_type= %02x\n", con_handle, remote_type);
__ble_bt_evnet_post(SYS_BT_EVENT_FORM_COMMON, COMMON_EVENT_BLE_REMOTE_TYPE, NULL, remote_type);
//to do
}
/*************************************************************************************************/
/*!
* \brief gatt common hci & gatt
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static int hogp_event_packet_handler(int event, u8 *packet, u16 size, u8 *ext_param)
{
/* log_info("event: %02x,size= %d\n",event,size); */
switch (event) {
case GATT_COMM_EVENT_CAN_SEND_NOW:
#if TEST_AUDIO_DATA_UPLOAD
hogp_test_send_audio_data(0);
#endif
break;
case GATT_COMM_EVENT_SERVER_INDICATION_COMPLETE:
log_info("INDICATION_COMPLETE:con_handle= %04x,att_handle= %04x\n", \
little_endian_read_16(packet, 0), little_endian_read_16(packet, 2));
break;
case GATT_COMM_EVENT_CONNECTION_COMPLETE:
hogp_con_handle = little_endian_read_16(packet, 0);
first_pair_flag = 0;
memcpy(cur_peer_addr_info, ext_param + 7, 7);
log_info("connection_handle:%04x, rssi= %d\n", hogp_con_handle, ble_vendor_get_peer_rssi(hogp_con_handle));
log_info("peer_address_info:");
put_buf(cur_peer_addr_info, 7);
log_info("con_interval = %d\n", little_endian_read_16(ext_param, 14 + 0));
log_info("con_latency = %d\n", little_endian_read_16(ext_param, 14 + 2));
log_info("cnn_timeout = %d\n", little_endian_read_16(ext_param, 14 + 4));
if (little_endian_read_16(ext_param, 14 + 2)) {
//latency非0值
hogp_connection_update_enable = 0;
/* __hogp_resume_all_ccc_enable(0); */
} else {
hogp_connection_update_enable = 1;
}
if (ble_hid_timer_handle) {
log_info("mdy_timer= %d\n", (u32)(little_endian_read_16(ext_param, 14 + 0) * 1.25));
sys_s_hi_timer_modify(ble_hid_timer_handle, (u32)(little_endian_read_16(ext_param, 14 + 0) * 1.25));
}
if (little_endian_read_16(ext_param, 14 + 2)) {
ble_op_latency_skip(hogp_con_handle, LATENCY_SKIP_INTERVAL_KEEP); //
}
break;
case GATT_COMM_EVENT_DISCONNECT_COMPLETE:
log_info("disconnect_handle:%04x,reason= %02x\n", little_endian_read_16(packet, 0), packet[2]);
hogp_con_handle = 0;
if (8 == packet[2] && hogp_pair_info.pair_flag) {
//超时断开,有配对发定向广播
hogp_pair_info.direct_adv_cnt = REPEAT_DIRECT_ADV_COUNT;
hogp_adv_config_set();
}
break;
case GATT_COMM_EVENT_ENCRYPTION_CHANGE:
log_info("ENCRYPTION_CHANGE:handle=%04x,state=%d,process =%02x", little_endian_read_16(packet, 0), packet[2], packet[3]);
if (packet[3] == LINK_ENCRYPTION_RECONNECT) {
log_info("reconnect...\n");
if ((!hogp_pair_info.pair_flag) || memcmp(cur_peer_addr_info, hogp_pair_info.peer_address_info, 7)) {
log_info("update reconnect peer\n");
put_buf(cur_peer_addr_info, 7);
memcpy(hogp_pair_info.peer_address_info, cur_peer_addr_info, 7);
hogp_pair_info.pair_flag = 1;
__hogp_conn_pair_vm_do(&hogp_pair_info, 1);
}
__hogp_resume_all_ccc_enable(1);
//回连时,从配对表中获取
u8 tmp_buf[6];
u8 remote_type = 0;
swapX(&cur_peer_addr_info[1], tmp_buf, 6);
ble_list_get_remote_type(tmp_buf, cur_peer_addr_info[0], &remote_type);
log_info("list's remote_type:%d\n", remote_type);
__att_check_remote_result(hogp_con_handle, remote_type);
} else {
//只在配对时启动检查
log_info("first pair...\n");
memcpy(hogp_pair_info.peer_address_info, cur_peer_addr_info, 7);
att_server_set_check_remote(hogp_con_handle, __att_check_remote_result);
hogp_pair_info.pair_flag = 1;
__hogp_conn_pair_vm_do(&hogp_pair_info, 1);
}
__ble_state_to_user(BLE_PRIV_PAIR_ENCRYPTION_CHANGE, first_pair_flag);
break;
case GATT_COMM_EVENT_CONNECTION_UPDATE_COMPLETE:
log_info("conn_param update_complete:%04x\n", little_endian_read_16(packet, 0));
log_info("update_interval = %d\n", little_endian_read_16(ext_param, 6 + 0));
log_info("update_latency = %d\n", little_endian_read_16(ext_param, 6 + 2));
log_info("update_timeout = %d\n", little_endian_read_16(ext_param, 6 + 4));
if (ble_hid_timer_handle) {
log_info("mdy_timer= %d\n", (u32)(little_endian_read_16(ext_param, 6 + 0) * 1.25));
sys_s_hi_timer_modify(ble_hid_timer_handle, (u32)(little_endian_read_16(ext_param, 6 + 0) * 1.25));
}
break;
case GATT_COMM_EVENT_DIRECT_ADV_TIMEOUT:
log_info("DIRECT_ADV_TIMEOUT\n");
if (hogp_pair_info.direct_adv_cnt) {
hogp_pair_info.direct_adv_cnt--;
}
hogp_adv_config_set();
break;
case GATT_COMM_EVENT_ENCRYPTION_REQUEST:
first_pair_flag = 1;
memcpy(hogp_pair_info.peer_address_info, &packet[4], 7);
hogp_pair_info.pair_flag = 0;
__ble_state_to_user(BLE_PRIV_MSG_PAIR_CONFIRM, 0);
break;
case GATT_COMM_EVENT_SERVER_STATE:
log_info("server_state: %02x,%02x\n", little_endian_read_16(packet, 1), packet[0]);
__ble_state_to_user(packet[0], hogp_con_handle);
break;
case GATT_COMM_EVENT_CONNECTION_UPDATE_REQUEST_RESULT:
case GATT_COMM_EVENT_MTU_EXCHANGE_COMPLETE:
break;
default:
break;
}
return 0;
}
/*************************************************************************************************/
/*!
* \brief client
*
* \param [in]
*
* \return
*
* \note profile的读属性uuid DYNAMIC read_callback
*/
/*************************************************************************************************/
// ATT Client Read Callback for Dynamic Data
// - if buffer == NULL, don't copy data, just return size of value
// - if buffer != NULL, copy data and return number bytes copied
// @param con_handle of hci le connection
// @param attribute_handle to be read
// @param offset defines start of attribute value
// @param buffer
// @param buffer_size
//主机操作ATT read,协议栈回调处理
static uint16_t hogp_att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
{
uint16_t att_value_len = 0;
uint16_t handle = att_handle;
log_info("read_callback, handle= 0x%04x,buffer= %08x,offset= %04x\n", handle, (u32)buffer, offset);
switch (handle) {
case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: {
char *gap_name = ble_comm_get_gap_name();
att_value_len = strlen(gap_name);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &gap_name[offset], buffer_size);
att_value_len = buffer_size;
log_info("\n------read gap_name: %s\n", gap_name);
}
}
break;
case ATT_CHARACTERISTIC_2a01_01_VALUE_HANDLE:
att_value_len = sizeof(Appearance);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Appearance[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a04_01_VALUE_HANDLE:
att_value_len = 8;//fixed
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
log_info("\n------get Peripheral_Preferred_Connection_Parameters\n");
memcpy(buffer, &Peripheral_Preferred_Connection_Parameters[0], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a29_01_VALUE_HANDLE:
att_value_len = strlen(Manufacturer_Name_String);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Manufacturer_Name_String[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a24_01_VALUE_HANDLE:
att_value_len = strlen(Model_Number_String);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Model_Number_String[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a25_01_VALUE_HANDLE:
att_value_len = strlen(Serial_Number_String);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Serial_Number_String[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a27_01_VALUE_HANDLE:
att_value_len = strlen(Hardware_Revision_String);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Hardware_Revision_String[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a26_01_VALUE_HANDLE:
att_value_len = strlen(Firmware_Revision_String);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Firmware_Revision_String[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a28_01_VALUE_HANDLE:
att_value_len = strlen(Software_Revision_String);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &Software_Revision_String[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a23_01_VALUE_HANDLE:
att_value_len = sizeof(System_ID);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &System_ID[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a50_01_VALUE_HANDLE:
log_info("read PnP_ID\n");
att_value_len = sizeof(PnP_ID);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &PnP_ID[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a19_01_VALUE_HANDLE:
att_value_len = 1;
if (buffer) {
if (get_vbat_percent_call) {
hid_battery_level = hid_get_vbat_handle();
log_info("read vbat:%d\n", hid_battery_level);
}
buffer[0] = hid_battery_level;
}
break;
case ATT_CHARACTERISTIC_2a4b_01_VALUE_HANDLE:
att_value_len = HID_REPORT_MAP_SIZE;
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &HID_REPORT_MAP_DATA[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_2a4a_01_VALUE_HANDLE:
att_value_len = sizeof(hid_information);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
break;
}
if (buffer) {
memcpy(buffer, &hid_information[offset], buffer_size);
att_value_len = buffer_size;
}
break;
case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE:
att_value_len = sizeof(hid_information1);
if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
log_info("len is err");
break;
}
if (buffer) {
memcpy(buffer, &hid_information1[offset], buffer_size);
att_value_len = buffer_size;
put_buf(buffer, att_value_len);
}
/* __hogp_send_connetion_update_deal(connection_handle); */
break;
case ATT_CHARACTERISTIC_2a05_01_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a19_01_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_01_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_02_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_04_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_05_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_06_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_07_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_ae42_01_CLIENT_CONFIGURATION_HANDLE:
if (buffer) {
buffer[0] = ble_gatt_server_characteristic_ccc_get(hogp_con_handle, handle);
buffer[1] = 0;
}
att_value_len = 2;
break;
default:
break;
}
log_info("att_value_len= %d\n", att_value_len);
return att_value_len;
}
/*************************************************************************************************/
/*!
* \brief client
*
* \param [in]
*
* \return
*
* \note profile的读属性uuid DYNAMIC read_callback
*/
/*************************************************************************************************/
// ATT Client Write Callback for Dynamic Data
// @param con_handle of hci le connection
// @param attribute_handle to be written
// @param transaction - ATT_TRANSACTION_MODE_NONE for regular writes, ATT_TRANSACTION_MODE_ACTIVE for prepared writes and ATT_TRANSACTION_MODE_EXECUTE
// @param offset into the value - used for queued writes and long attributes
// @param buffer
// @param buffer_size
// @param signature used for signed write commmands
// @returns 0 if write was ok, ATT_ERROR_PREPARE_QUEUE_FULL if no space in queue, ATT_ERROR_INVALID_OFFSET if offset is larger than max buffer
//主机操作ATT write,协议栈回调处理
static int hogp_att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
{
int result = 0;
u16 tmp16;
u16 handle = att_handle;
log_info("write_callback, handle= 0x%04x,size = %d\n", handle, buffer_size);
switch (handle) {
case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE:
break;
case ATT_CHARACTERISTIC_2a4d_03_VALUE_HANDLE:
put_buf(buffer, buffer_size); //键盘led灯状态
if (le_hogp_output_callback) {
le_hogp_output_callback(buffer, buffer_size);
}
break;
case ATT_CHARACTERISTIC_2a05_01_CLIENT_CONFIGURATION_HANDLE:
ble_gatt_server_characteristic_ccc_set(connection_handle, handle, buffer[0]);
if (buffer[0]) {
__check_report_map_change();
}
break;
#if RCSP_BTMATE_EN
case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE:
ble_gatt_server_set_update_send(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, ATT_OP_AUTO_READ_CCC);
set_rcsp_conn_handle(connection_handle);
#if (0 == BT_CONNECTION_VERIFY)
JL_rcsp_auth_reset(); //hid设备试能nofity的时候reset auth保证APP可以重新连接
#endif
#if (TCFG_HID_AUTO_SHUTDOWN_TIME)
__ble_bt_evnet_post(SYS_BT_EVENT_FORM_COMMON, COMMON_EVENT_SHUTDOWN_DISABLE, NULL, 0);
/* auto_shutdown_disable(); */
#endif
#endif
case ATT_CHARACTERISTIC_ae42_01_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_01_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_02_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_04_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_05_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_06_CLIENT_CONFIGURATION_HANDLE:
case ATT_CHARACTERISTIC_2a4d_07_CLIENT_CONFIGURATION_HANDLE:
ble_op_latency_skip(hogp_con_handle, LATENCY_SKIP_INTERVAL_MIN); //
case ATT_CHARACTERISTIC_2a19_01_CLIENT_CONFIGURATION_HANDLE:
__hogp_send_connetion_update_deal(hogp_con_handle);
log_info("\n------write ccc:%04x,%02x\n", handle, buffer[0]);
#if RCSP_BTMATE_EN
//-----如果主机notify RCSP协议,从机告知主机存在此协议
if (handle == ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE) {
u8 data[1] = {0xff};
ble_comm_att_send_data(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, &data, 1, ATT_OP_NOTIFY);
}
#endif
ble_gatt_server_characteristic_ccc_set(hogp_con_handle, handle, buffer[0]);
break;
#if RCSP_BTMATE_EN
case ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE:
log_info("rcsp_read:%x\n", buffer_size);
put_buf(buffer, (buffer_size > 30) ? 30 : buffer_size);
hogp_connection_update_enable = 0;
ble_gatt_server_receive_update_data(NULL, buffer, buffer_size);
break;
#endif
case ATT_CHARACTERISTIC_ae41_01_VALUE_HANDLE:
ble_hid_transfer_channel_recieve(buffer, buffer_size);
break;
case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE:
tmp16 = sizeof(hid_information1);
if ((offset >= tmp16) || (offset + buffer_size) > tmp16) {
break;
}
log_info("cur_state:");
put_buf(hid_information1, tmp16);
memcpy(&hid_information1[offset], buffer, buffer_size);
log_info("new_state:");
put_buf(hid_information1, tmp16);
ble_hid_transfer_channel_recieve1(hid_information1, tmp16);
break;
default:
break;
}
return 0;
}
/*************************************************************************************************/
/*!
* \brief adv包buff
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static u8 adv_name_ok; //name 优先存放在ADV包
static int hogp_make_set_adv_data(u8 adv_reconnect)
{
u8 offset = 0;
u8 *buf = hogp_adv_data;
offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, FLAGS_GENERAL_DISCOVERABLE_MODE | FLAGS_EDR_NOT_SUPPORTED, 1);
offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS, HID_UUID_16, 2);
offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_APPEARANCE_DATA, Appearance, 2);
if (!adv_reconnect) {/*回连广播默认不填入名字*/
char *gap_name = ble_comm_get_gap_name();
u8 name_len = strlen(gap_name);
u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2);
if (name_len < vaild_len) {
offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)gap_name, name_len);
adv_name_ok = 1;
} else {
adv_name_ok = 0;
}
}
if (offset > ADV_RSP_PACKET_MAX) {
puts("***hogp_adv_data overflow!!!!!!\n");
return -1;
}
log_info("hogp_adv_data(%d):", offset);
log_info_hexdump(buf, offset);
hogp_server_adv_config.adv_data_len = offset;
hogp_server_adv_config.adv_data = hogp_adv_data;
return 0;
}
/*************************************************************************************************/
/*!
* \brief rsp包buff
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static int hogp_make_set_rsp_data(u8 adv_reconnect)
{
u8 offset = 0;
u8 *buf = hogp_scan_rsp_data;
#if RCSP_BTMATE_EN
u8 tag_len = sizeof(user_tag_string);
offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)user_tag_string, tag_len);
#endif
if (!adv_reconnect) {/*回连广播默认不填入名字*/
if (!adv_name_ok) {
char *gap_name = ble_comm_get_gap_name();
u8 name_len = strlen(gap_name);
u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2);
if (name_len > vaild_len) {
name_len = vaild_len;
}
offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)gap_name, name_len);
}
}
if (offset > ADV_RSP_PACKET_MAX) {
puts("***rsp_data overflow!!!!!!\n");
return -1;
}
log_info("rsp_data(%d):", offset);
log_info_hexdump(buf, offset);
hogp_server_adv_config.rsp_data_len = offset;
hogp_server_adv_config.rsp_data = hogp_scan_rsp_data;
return 0;
}
/*************************************************************************************************/
/*!
* \brief gatt name
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void modify_ble_name(const char *name)
{
log_info(">>>modify_ble_name:%s\n", name);
ble_comm_set_config_name(bt_get_local_name(), 1);
}
static void wait_to_open_adv(void)
{
if (!hogp_con_handle) {
log_info("allow open adv");
ble_gatt_server_adv_enable(1);
} else {
log_info("no allow open adv");
}
}
static void __hogp_reconnect_low_timeout_handle(void)
{
if (0 == hogp_con_handle && ble_gatt_server_get_work_state() == BLE_ST_ADV) {
log_info("ADV_RECONNECT timeout!!!\n");
ble_gatt_server_adv_enable(0);
hogp_pair_info.direct_adv_cnt = 0;
hogp_adv_config_set();
#if RCSP_BTMATE_EN
sys_timeout_add(NULL, wait_to_open_adv, 20);
#else
ble_gatt_server_adv_enable(1);
#endif
} else {
/*其他情况,要取消定向广播*/
log_info("Set Switch to ADV_IND Config\n");
hogp_pair_info.direct_adv_cnt = 0;
hogp_adv_config_set();
}
}
/*************************************************************************************************/
/*!
* \brief 广
*
* \param [in]
*
* \return
*
* \note 广广
*/
/*************************************************************************************************/
static void hogp_adv_config_set(void)
{
int ret = 0;
int adv_reconnect_flag = 0;
hogp_server_adv_config.adv_interval = ADV_INTERVAL_MIN;
hogp_server_adv_config.adv_auto_do = 1;
hogp_server_adv_config.adv_channel = le_adv_channel_sel;
if (PAIR_RECONNECT_ADV_EN && hogp_pair_info.pair_flag && hogp_pair_info.direct_adv_cnt) {
hogp_server_adv_config.adv_type = pair_reconnect_adv_type;
memcpy(hogp_server_adv_config.direct_address_info, hogp_pair_info.peer_address_info, 7);
if (pair_reconnect_adv_type != ADV_DIRECT_IND) {
hogp_server_adv_config.adv_interval = PAIR_RECONNECT_ADV_INTERVAL;
if (pair_reconnect_adv_timeout) {
if (hogp_adv_timeout_number) {
sys_timeout_del(hogp_adv_timeout_number);
hogp_adv_timeout_number = 0;
}
hogp_adv_timeout_number = sys_timeout_add(0, __hogp_reconnect_low_timeout_handle, pair_reconnect_adv_timeout);
}
}
log_info("RECONNECT_ADV1= %02x, address:", pair_reconnect_adv_type);
put_buf(hogp_server_adv_config.direct_address_info, 7);
adv_reconnect_flag = 1;
} else {
hogp_server_adv_config.adv_type = ADV_IND;
memset(hogp_server_adv_config.direct_address_info, 0, 7);
}
log_info("adv_type:%d,channel=%02x\n", hogp_server_adv_config.adv_type, hogp_server_adv_config.adv_channel);
ret |= hogp_make_set_adv_data(adv_reconnect_flag);
ret |= hogp_make_set_rsp_data(adv_reconnect_flag);
if (ret) {
log_info("adv_setup_init fail!!!\n");
return;
}
ble_gatt_server_set_adv_config(&hogp_server_adv_config);
}
/*************************************************************************************************/
/*!
* \brief 广
*
* \param [in]
*
* \return
*
* \note 广广
*/
/*************************************************************************************************/
void hogp_reconnect_adv_config_set(u8 adv_type, u32 adv_timeout)
{
int ret = 0;
int adv_reconnect_flag = 0;
hogp_server_adv_config.adv_interval = PAIR_RECONNECT_ADV_INTERVAL;
hogp_server_adv_config.adv_auto_do = 1;
hogp_server_adv_config.adv_channel = ADV_CHANNEL_ALL;
__hogp_conn_pair_vm_do(&hogp_pair_info, 0);
if (hogp_pair_info.pair_flag) {
adv_reconnect_flag = 1; /*已配对*/
hogp_server_adv_config.adv_type = adv_type;
} else {
hogp_server_adv_config.adv_type = ADV_IND;/*强制切换可发现广播*/
}
if (PAIR_RECONNECT_ADV_EN && hogp_pair_info.pair_flag) {
memcpy(hogp_server_adv_config.direct_address_info, &hogp_pair_info.peer_address_info, 7);
log_info("RECONNECT_ADV2= %02x, address:", adv_type);
put_buf(hogp_server_adv_config.direct_address_info, 7);
if (adv_type == ADV_DIRECT_IND) {
hogp_pair_info.direct_adv_cnt = (adv_timeout + 1279) / 1280; /*定向次数*/
} else {
if (adv_timeout) {
/*设置超时切换到无定向广播*/
if (hogp_adv_timeout_number) {
sys_timeout_del(hogp_adv_timeout_number);
hogp_adv_timeout_number = 0;
}
hogp_adv_timeout_number = sys_timeout_add(0, __hogp_reconnect_low_timeout_handle, adv_timeout);
}
}
} else {
memset(hogp_server_adv_config.direct_address_info, 0, 7);
hogp_server_adv_config.adv_interval = ADV_INTERVAL_MIN;
}
log_info("adv_type:%d,channel=%02x\n", hogp_server_adv_config.adv_type, hogp_server_adv_config.adv_channel);
ret |= hogp_make_set_adv_data(adv_reconnect_flag);
ret |= hogp_make_set_rsp_data(adv_reconnect_flag);
if (ret) {
log_info("adv_setup_init fail!!!\n");
return;
}
ble_gatt_server_set_adv_config(&hogp_server_adv_config);
}
/*************************************************************************************************/
/*!
* \brief init
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void hogp_server_init(void)
{
log_info("%s", __FUNCTION__);
ble_gatt_server_set_profile(hogp_profile_data, sizeof(hogp_profile_data));
hogp_adv_config_set();
}
/*************************************************************************************************/
/*!
* \brief bt_ble_before_start_init
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void bt_ble_before_start_init(void)
{
log_info("%s", __FUNCTION__);
ble_comm_init(&hogp_gatt_control_block);
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return vbat percent
*
* \note
*/
/*************************************************************************************************/
static u8 hid_get_vbat_handle(void)
{
if (!get_vbat_percent_call) {
return 0;
}
u8 cur_val, avg_val, val;
if (hid_battery_level_add_cnt > 10) {
/*超过10次取平均值*/
hid_battery_level_add_sum = hid_battery_level_add_sum / hid_battery_level_add_cnt;
hid_battery_level_add_cnt = 1;
}
cur_val = get_vbat_percent_call();
if (hid_battery_level_add_cnt) {
avg_val = hid_battery_level_add_sum / hid_battery_level_add_cnt;
if (cur_val > (avg_val + 2) || (cur_val + 2) < avg_val) {
/*变化较大*/
hid_battery_level_add_sum = 0;
hid_battery_level_add_cnt = 0;
}
}
hid_battery_level_add_sum += cur_val;
hid_battery_level_add_cnt++;
/*简单的累加求平均值计算*/
val = (u8)(hid_battery_level_add_sum / hid_battery_level_add_cnt);
log_info("vbat: avg=%d,cur=%d,val=%d\n", avg_val, cur_val, val);
return val;
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static void hid_battery_timer_handler(void *priev)
{
#if TCFG_SYS_LVD_EN
if (hogp_con_handle && get_vbat_percent_call) {
u8 tmp_val = hid_get_vbat_handle();
/* tmp_val = (tmp_val +10)%101; */
if (hid_battery_level != tmp_val) {
hid_battery_level = tmp_val;
if (ble_gatt_server_characteristic_ccc_get(hogp_con_handle, ATT_CHARACTERISTIC_2a19_01_CLIENT_CONFIGURATION_HANDLE)) {
log_info("notify battery: %d\n", hid_battery_level);
ble_comm_att_send_data(hogp_con_handle, ATT_CHARACTERISTIC_2a19_01_VALUE_HANDLE, &hid_battery_level, 1, ATT_OP_AUTO_READ_CCC);
}
}
}
#endif // TCFG_SYS_LVD_EN
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void bt_ble_init(void)
{
log_info("%s\n", __FUNCTION__);
log_info("ble_file: %s", __FILE__);
hogp_con_handle = 0;
__hogp_conn_pair_vm_do(&hogp_pair_info, 0);
if (hogp_pair_info.pair_flag) {
hogp_pair_info.direct_adv_cnt = REPEAT_DIRECT_ADV_COUNT;
}
#if TCFG_SYS_LVD_EN
if (!hid_battery_notify_timer_id && HID_BATTERY_TIMER_SET) {
log_info("add hid_battery_notify_timer_id\n");
hid_battery_notify_timer_id = sys_timer_add((void *)0, hid_battery_timer_handler, HID_BATTERY_TIMER_SET);
}
#endif // TCFG_SYS_LVD_EN
#if DOUBLE_BT_SAME_NAME
ble_comm_set_config_name(bt_get_local_name(), 0);
#else
ble_comm_set_config_name(bt_get_local_name(), 1);
#endif
hogp_server_init();
#if CONFIG_APP_STANDARD_KEYBOARD
ble_module_enable(0);
#else
ble_module_enable(1);
#endif
}
/*************************************************************************************************/
/*!
* \brief 退
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void bt_ble_exit(void)
{
log_info("***** ble_exit******\n");
if (ble_hid_timer_handle) {
sys_s_hi_timer_del(ble_hid_timer_handle);
ble_hid_timer_handle = 0;
}
#if TCFG_SYS_LVD_EN
if (hid_battery_notify_timer_id) {
sys_timer_del(hid_battery_notify_timer_id);
hid_battery_notify_timer_id = 0;
}
#endif // TCFG_SYS_LVD_EN
log_info("%s\n", __FUNCTION__);
ble_module_enable(0);
ble_comm_exit();
}
/*************************************************************************************************/
/*!
* \brief 使
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void ble_module_enable(u8 en)
{
log_info("mode_en:%d\n", en);
ble_comm_module_enable(en);
}
/*************************************************************************************************/
/*!
* \brief sleep
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
static u8 hogp_idle_query(void)
{
return !is_hogp_active;
}
REGISTER_LP_TARGET(le_hogp_target) = {
.name = "ble_hogp",
.is_idle = hogp_idle_query,
};
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_icon(u16 class_type)
{
memcpy(Appearance, &class_type, 2);
}
/*************************************************************************************************/
/*!
* \brief hid描述符
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_ReportMap(u8 *map, u16 size)
{
report_map = map;
report_map_size = size;
hid_report_change = 1;
}
/*************************************************************************************************/
/*!
* \brief set callback
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_output_callback(void *cb)
{
le_hogp_output_callback = cb;
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_pair_config(u8 pair_max, u8 is_allow_cover)
{
ble_list_config_reset(pair_max, is_allow_cover); //开1对1配对绑定
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_pair_allow(void)
{
hogp_pair_info.pair_flag = 0;
__hogp_conn_pair_vm_do(&hogp_pair_info, 1);
ble_list_clear_all();
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_regiest_get_battery(u8(*get_battery_cbk)(void))
{
get_vbat_percent_call = get_battery_cbk;
}
/*************************************************************************************************/
/*!
* \brief 广使
*
* \param type [in] ADV_DIRECT_IND, ADV_DIRECT_IND_LOW,ADV_IND
*
* ADV_DIRECT_IND (广:1.28s超时,interval 2ms)
* ADV_DIRECT_IND_LOW (广:interval channel 广)
* ADV_IND (广:interval channel 广)
* \param adv_timeout [in]
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_reconnect_adv_cfg(u8 adv_type, u32 adv_timeout)
{
pair_reconnect_adv_type = adv_type;
pair_reconnect_adv_timeout = adv_timeout;
}
/*************************************************************************************************/
/*!
* \brief 广
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_adv_channel(int channel)
{
le_adv_channel_sel = channel;
}
/*************************************************************************************************/
/*!
* \brief set PNP_PID
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_set_PNP_info(const u8 *info)
{
memcpy(PnP_ID, info, sizeof(PnP_ID));
}
/*************************************************************************************************/
/*!
* \brief is connect
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
int ble_hid_is_connected(void)
{
return hogp_con_handle;
}
/*************************************************************************************************/
/*!
* \brief disconnect
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void le_hogp_disconnect(void)
{
if (hogp_con_handle) {
ble_comm_disconnect(hogp_con_handle);
}
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return addr_type + address
*
* \note
*/
/*************************************************************************************************/
u8 *ble_cur_connect_addrinfo(void)
{
return cur_peer_addr_info;
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void ble_set_pair_addrinfo(u8 *addr_info)
{
log_info("ble_set_pair_addrinfo\n");
if (addr_info) {
put_buf(addr_info, 7);
memcpy(hogp_pair_info.peer_address_info, addr_info, 7);
hogp_pair_info.head_tag = BLE_VM_HEAD_TAG;
hogp_pair_info.tail_tag = BLE_VM_TAIL_TAG;
hogp_pair_info.pair_flag = 1;
hogp_pair_info.direct_adv_flag = 1;
hogp_pair_info.direct_adv_cnt = REPEAT_DIRECT_ADV_COUNT;
__hogp_conn_pair_vm_do(&hogp_pair_info, 1);
} else {
memset(&hogp_pair_info, 0, sizeof(struct pair_info_t));
}
}
//profile 支持的report id
static const u16 report_id_handle_table[] = {
0,
HID_REPORT_ID_01_SEND_HANDLE,
HID_REPORT_ID_02_SEND_HANDLE,
HID_REPORT_ID_03_SEND_HANDLE,
HID_REPORT_ID_04_SEND_HANDLE,
HID_REPORT_ID_05_SEND_HANDLE,
HID_REPORT_ID_06_SEND_HANDLE,
};
/*************************************************************************************************/
/*!
* \brief hid
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
int ble_hid_data_send(u8 report_id, u8 *data, u16 len)
{
if (report_id == 0 || report_id > 6) {
log_info("report_id %d,err!!!\n", report_id);
return -1;
}
putchar('@');
return ble_comm_att_send_data(hogp_con_handle, report_id_handle_table[report_id], data, len, ATT_OP_AUTO_READ_CCC);
}
/*************************************************************************************************/
/*!
* \brief hid
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void ble_hid_key_deal_test(u16 key_msg)
{
if (key_msg) {
ble_hid_data_send(1, &key_msg, 2);
key_msg = 0;//key release
ble_hid_data_send(1, &key_msg, 2);
}
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
int ble_hid_transfer_channel_send(u8 *packet, u16 size)
{
/* log_info("transfer_tx(%d):", size); */
/* log_info_hexdump(packet, size); */
return ble_comm_att_send_data(hogp_con_handle, ATT_CHARACTERISTIC_ae42_01_VALUE_HANDLE, packet, size, ATT_OP_AUTO_READ_CCC);
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
int ble_hid_transfer_channel_send1(u8 *packet, u16 size)
{
/* log_info("transfer_tx(%d):", size); */
/* log_info_hexdump(packet, size); */
return ble_comm_att_send_data(hogp_con_handle, ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE, packet, size, ATT_OP_AUTO_READ_CCC);
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void __attribute__((weak)) ble_hid_transfer_channel_recieve(u8 *packet, u16 size)
{
log_info("transfer_rx(%d):", size);
log_info_hexdump(packet, size);
//ble_hid_transfer_channel_send(packet,size);//for test
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void __attribute__((weak)) ble_hid_transfer_channel_recieve1(u8 *packet, u16 size)
{
log_info("transfer_rx1(%d):", size);
log_info_hexdump(packet, size);
}
/*************************************************************************************************/
/*!
* \brief
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void ble_set_pair_list_control(u8 mode)
{
bool ret = 0;
u8 connect_address[6];
switch (mode) {
case 0:
//close pair,关配对
ret = ble_list_pair_accept(0);
break;
case 1:
//open pair,开配对
ret = ble_list_pair_accept(1);
break;
case 2:
//绑定已配对设备,不再接受新的配对
swapX(&cur_peer_addr_info[1], connect_address, 6);
//bond current's device
ret = ble_list_bonding_remote(connect_address, cur_peer_addr_info[0]);
//close pair
ble_list_pair_accept(0);
break;
default:
break;
}
log_info("%s: %02x,ret=%02x\n", __FUNCTION__, mode, ret);
}
/*************************************************************************************************/
/*!
* \brief testbox,key test
*
* \param [in]
*
* \return
*
* \note
*/
/*************************************************************************************************/
void ble_server_send_test_key_num(u8 key_num)
{
if (hogp_con_handle) {
if (get_remote_test_flag()) {
ble_op_test_key_num(hogp_con_handle, key_num);
} else {
log_info("-not conn testbox\n");
}
}
}
void call_hogp_adv_config_set()
{
return hogp_adv_config_set();
}
#endif