Hello,
I have the following scenario:
The device boots and starts to advertise.
When the central (android phone or iPhone) connects, peripheral requests bonding and stores the bond (if bonding succeds), bonding uses static passkey method.
When the central disconnects, the device starts to advertise again, but this time advertising with whitelist is required to allow only the bonded device to connect.
Other central devices are not allowed to connect if the device has a stored bond, except the central device that the stored bond corresponds to.
If the device is power cycled, it should read the stored bond and advertise with whitelist.
I have modified the nordic BMS example. For static passkey I've changed SEC_PARAM_MITM to 1, changed SEC_PARAM_IO_CAPABILITIES to BLE_GAP_IO_CAPS_DISPLAY_ONLY and added the following code to the gap_params_init().
uint8_t passkey[] = PASSKEY;
m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
err_code = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);
APP_ERROR_CHECK(err_code);
advertising_init is modified
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
ret_code_t err_code;
uint8_t adv_flags;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
if(pm_peer_count()==0)
{
adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
init.config.ble_adv_whitelist_enabled = false;
init.config.ble_adv_fast_enabled = true;
}
else if(pm_peer_count() == 1)
{
// Advertising with whitelist
adv_flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
init.config.ble_adv_whitelist_enabled = true;
init.config.ble_adv_fast_enabled = false;
ble_opts |= BLE_OPTS_BONDED;
}
else{
// We should not get here, since we only support 1 bond
}
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = true;
init.advdata.flags = adv_flags;
init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.advdata.uuids_complete.p_uuids = m_adv_uuids;
init.config.ble_adv_fast_interval = APP_ADV_FAST_INTERVAL;
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;
init.config.ble_adv_slow_enabled = false;
init.evt_handler = on_adv_evt;
init.error_handler = ble_advertising_error_handler;
err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
following is added to the BLE_GAP_EVT_DISCONNECTED event.
if(ble_flags & BLE_FLAGS_BONDED){
// Change advertising mode to whitelist advertising
sd_ble_gap_adv_stop(m_advertising.adv_handle);
advertising_init();
ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
}
PM_EVT_CONN_SEC_SUCCEEDED is added to the pm_evt_handler.
case PM_EVT_CONN_SEC_SUCCEEDED:
// Sent after the connection has been secured,
ble_flags |= BLE_FLAGS_BONDED;
pm_whitelist_set(&(p_evt->peer_id), 1);
pm_sec_params_set(NULL); // Disallow new bonds
NRF_LOG_INFO("PM_EVT_CONN_SEC_SUCCEEDED Event");
break;
and BLE_ADV_EVT_WHITELIST_REQUEST is added to the on_adv_evt.
case BLE_ADV_EVT_WHITELIST_REQUEST:
err_code = pm_whitelist_get(&dev_addr, &addr_cnt, &dev_irk, &irk_cnt);
err_code = sd_ble_gap_whitelist_set(p_dev_addr, 1);
APP_ERROR_CHECK(err_code);
err_code = ble_advertising_whitelist_reply(&m_advertising, p_dev_addr_im, 1, p_dev_irk, 1);
APP_ERROR_CHECK(err_code);
break;
Advertising is restarted on BLE_GAP_EVT_DISCONNECTED if cetral was previously succesfuly bonded.
case BLE_GAP_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected");
delete_disconnected_bonds();
m_conn_handle = BLE_CONN_HANDLE_INVALID;
if(ble_flags & BLE_OPTS_DISCONNECT){
// Disconnection was due to call to factory_reset function.
// Delete all stored bonds
delete_bonds();
}
if(ble_flags & BLE_FLAGS_BONDED){
// Change advertising mode to whitelist advertising
sd_ble_gap_adv_stop(m_advertising.adv_handle);
advertising_init();
ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
}
The device can bond to the central and reconnect after power cycle.
I still have the following issues:
When the device is disconnected from the central, advertisment is not resumed. I have not managed to resume the advertismend with whitelist after disconnection.
After the the device is bonded and power cycled the pm_peer_count() returns 0. I assume the bond must be loaded somehow from the flash in order this to work or different function must be used to get the number of stored bonds.
I'm using SDK_15.2.0_9412b96 and S132 softddevice.
BR