CH571,CH573,CH582,CH592低功耗蓝牙定向广播/白名单广播回连
以CH582的Hid_Keyboard例程为例,
1、CH582首次广播面向对象为所有扫描设备,例程默认就是这种广播方式;
2、我们主机设备与CH582建立配对之后,可以利用hidDevPairStateCB回调添加代码找到我们主机设备的地址信息(remote_addr)以及地址类型(addr_type);
/*这里自定义了一个结构体,以便后面赋值使用*/
typedef struct
{
BOOL isbond;
uint8_t remote_addr_type;
uint8_t remote_addr[6];
}Device_ID_t;
/*定义一个结构体变量,便于后面赋值使用*/
Device_ID_t mydevinfo;
/**BLE状态回调函数**/
/*********************************************************************
* @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_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);
conn_params.interval_current = event->connInterval;
PRINT("Connected..\n");
tmos_memcpy(devAddr, event->devAddr, 6);//获取设备地址
devAddrType = event->devAddrType;//获取设备地址类型
}
break;
......
default:
break;
}
}
/*该回调函数在hiddev.c文件中*/
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)
{
/******************************添加代码***************************************/
gapBondRec_t bond_info;
uint8_t addr_type;
tmos_snv_read(mainRecordNvID(0), sizeof(gapBondRec_t), &bond_info);//读取当前SNV存储地址处所存储的绑定信息,该结构体中可以读到此次配对的主机唯一身份地址
PRINT("identity addr (");
for(int i = 0 ; i < 6; i ++)
{
PRINT("%02x ", bond_info.publicAddr[i]);//将配对的主机地址打印出来
}
PRINT(")\n");
tmos_memcpy(mydevinfo.remote_addr,bond_info.publicAddr, 6);//将此次绑定的地址赋值到自己定义的地址数组中去,以便定向广播或者白名单回连使用
//为identity address, 可能为public address,也可能是random static address
if( (bond_info.publicAddr[5] & 0xC0) == 0x80 ) //判断地址类型
{
addr_type = 0;
}
else
{
addr_type = 1;
}
extern uint8_t devAddrType;
(devAddrType)?1:(addr_type = 0);
if(devAddrType == 3)
{
addr_type |= devAddrType<<4;
}
mydevinfo.remote_addr_type = addr_type;//获取主机的地址类型
mydevinfo.isbond = 1;//此次设备绑定生效
/*****************************END*************************************/
}
}
3、将上次绑定的设备地址(remote_addr)和地址类型(addr_type)传入定向广播的参数中;
static inline void bt_adv_direct(uint8_t addr_type, uint8_t *addr)
{
uint8_t adv_event_type;
adv_event_type = GAP_ADTYPE_ADV_HDC_DIRECT_IND;
uint8_t Adv_Direct_Addr[B_ADDR_LEN];
uint8_t Adv_Direct_Type = addr_type;
tmos_memcpy(Adv_Direct_Addr, addr,sizeof(Adv_Direct_Addr));
PRINT("Adv Direct type %#x (", Adv_Direct_Type);
for (int i = 0; i < 6; i++) {
if(i) PRINT(" ");
PRINT("%#x", Adv_Direct_Addr[i]);
}
PRINT(")\n");
GAPRole_SetParameter( GAPROLE_ADV_DIRECT_ADDR, sizeof(Adv_Direct_Addr),Adv_Direct_Addr);
GAPRole_SetParameter( GAPROLE_ADV_DIRECT_TYPE, sizeof(Adv_Direct_Type),&Adv_Direct_Type);
GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof(adv_event_type),&adv_event_type);
}
4、利用结构体中的是否绑定参数(mydevinfo.isbond)做判断,每次上电广播时是否进行定向广播;
void adv_init(void)
{
uint8_t initial_advertising_enable = TRUE;
if (mydevinfo.isbond) {
PRINT("type = %d\n",mydevinfo.remote_addr_type);
uint8_t enable = ENABLE;
if(mydevinfo.remote_addr_type&0x30){
GAPBondMgr_SetParameter( GAPBOND_AUTO_SYNC_RL, sizeof(uint8), &enable);
}
else{
enable = DISABLE;
GAPBondMgr_SetParameter( GAPBOND_AUTO_SYNC_RL, sizeof(uint8), &enable);
}
bt_adv_direct(mydevinfo.remote_addr_type, mydevinfo.remote_addr);
}
else{
GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
scanRspData);
}
// Set the GAP Role Parameters
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
}
5、定向广播为3.75ms进行一次快速广播,并且最多持续1.28s,且部分苹果手机和华为手机无法利用该方式回连,可借助下面的白名单回连的方式;
void adv_init(void)
{
uint8_t initial_advertising_enable = TRUE;
uint16 advInt =32; //0.625us * 32 = 20ms,20ms一包广播包
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
if(mydevinfo.isbond)
{
uint8_t reconAdvertData[1] = {0};
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(reconAdvertData), reconAdvertData);//将广播包数据清空
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(reconAdvertData), reconAdvertData);//扫描应答包数据清空
uint8_t filter_policy = GAP_FILTER_POLICY_WHITE;//设置仅允许白名单设备扫描和连接
GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof(uint8_t), &filter_policy);
}else {
uint8_t policy = GAP_FILTER_POLICY_ALL; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof(policy), &policy); } }