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.

Parents
  • Hi Nick,

    Thanks for letting us know. Regarding the suggested solution I am not sure using a critical section here is a good idea, as compute_and_give_dhkey() takes a bit of time to complete, and generally spending a long time in critical sections is not recommended (as it blocks any other time critical operations, even with higher interrupt priorities). It could be that it would be better to simply ignore NRF_ERROR_INVALID_STATE in this case, for instance like this:

        err_code = nrf_ble_lesc_request_handler();
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }

Reply
  • Hi Nick,

    Thanks for letting us know. Regarding the suggested solution I am not sure using a critical section here is a good idea, as compute_and_give_dhkey() takes a bit of time to complete, and generally spending a long time in critical sections is not recommended (as it blocks any other time critical operations, even with higher interrupt priorities). It could be that it would be better to simply ignore NRF_ERROR_INVALID_STATE in this case, for instance like this:

        err_code = nrf_ble_lesc_request_handler();
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }

Children
Related