We are using nRF5 SDK 17.1.0, and have LESC pairing enabled. In our main loop we do this:
ret_code_t err_code = nrf_ble_lesc_request_handler(); APP_ERROR_CHECK(err_code);
When LESC pairing failed, this would cause a crash as err_code was NRF_ERROR_INVALID_STATE. This is because the disconnected event occurred during the call to nrf_ble_lesc_request_handler, so m_peer_keys[i].is_requested == true but when sd_ble_gap_lesc_dhkey_reply is called it has disconnected.
To resolve this, I modified nrf_ble_lesc_request_handler:
for (uint16_t i = 0; i < NRF_BLE_LESC_LINK_COUNT; i++)
{
CRITICAL_REGION_ENTER();
if (m_peer_keys[i].is_requested)
{
err_code = compute_and_give_dhkey(&m_peer_keys[i], i);
m_peer_keys[i].is_requested = false;
m_peer_keys[i].is_valid = false;
m_peer_keys[i].passkey_requested = false;
m_peer_keys[i].passkey_displayed = false;
}
CRITICAL_REGION_EXIT();
VERIFY_SUCCESS(err_code);
Perhaps this is not required, but BLE_GAP_EVT_AUTH_STATUS occurs before BLE_GAP_EVT_DISCONNECTED, so I also modified nrf_ble_lesc_on_ble_evt:
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_AUTH_STATUS:
if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {
break;
}
// fallthrough to disconnected on error
case BLE_GAP_EVT_DISCONNECTED:
m_peer_keys[conn_handle].is_valid = false;
m_peer_keys[conn_handle].is_requested = false;
m_peer_keys[conn_handle].passkey_requested = false;
m_peer_keys[conn_handle].passkey_displayed = false;
break;
Now the error doesn't occur.