Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Crash when LESC pairing failed

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.

Related