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

fatal error in the BLE observers

Hello, new-to-this platform dev here!

I am implementing BLE bonding on my nRF52840 DK, which uses the S140 Softdevice. The DK is a peripheral and I'm using version 17.1 of the SDK. I adapted most of the peer_manager/whitelist code from the ble_peripheral hci keyboard sample. However, I'd like to implement some special logic to allow only the first device to be bonded with my nRF52840 to talk to it, and to reject pairing/bonding attempts from other devices. 

I implemented this logic in the ble_evt_handler, where I intercept LE_GAP_EVT_CONNECTED events and apply my go/no go logic. If the connection request falls into the "no go" category, I call sd_ble_gap_disconnect function. This returns an err_code of 0x0. But the next thing that happens is nrf_sdh_ble_evts_poll tries to forward  the event to BLE observers (line 300 of nrf_sdh_ble.c), and that's where I hit the fatal error. In the debugger, it looks like the sdh_ble_observer items point to valid addresses, but that's about as far as I can get on this.

Can anyone see where I am going wrong? Or know a better way to accomplish my goal?

Code from my BLE event handler:

    case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("ble_evt_handler: connected event ");

            pm_peer_id_t peer_id;
            err_code = pm_peer_id_get(p_ble_evt->evt.gattc_evt.conn_handle,&peer_id);
            APP_ERROR_CHECK(err_code);
            NRF_LOG_INFO("ble_evt_handler: conn handle 0x%x peer lookup returns %d", p_ble_evt->evt.gattc_evt.conn_handle,peer_id);
            NRF_LOG_INFO("current peer_cnt %d", pm_peer_count());

            // if this connection isn't already a peer and we already have a peer, reject it
            if ( peer_id == PM_PEER_ID_INVALID && pm_peer_count() > 0 )
            {
              NRF_LOG_INFO("ble_evt_handler: going to reject this");
              // according to message sequence charts at https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v7.3.0/group___b_l_e___g_a_p___m_s_c.html,
               // I should send an sd_ble_gap_disconnect message here.
              // according to function docs at https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s140.api.v6.0.0%2Fgroup___b_l_e___g_a_p___f_u_n_c_t_i_o_n_s.html,
              // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION and BLE_HCI_CONN_INTERVAL_UNACCEPTABLE are the only valid reason codes to use.
              // both return 0x0 in the err_code, but lead to a fatal error on line 300 of nrf_sdh_ble.c.
              //err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
              err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
              NRF_LOG_INFO("ble_evt_handler: disc error code %d",err_code)
              APP_ERROR_CHECK(err_code);
            }
            else
            {
              NRF_LOG_INFO("ble_evt_handler: going to set up connection");
              err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
              APP_ERROR_CHECK(err_code);
              m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
              err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
              APP_ERROR_CHECK(err_code);
              err_code = pm_conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false);
              if (err_code != NRF_ERROR_BUSY)
              {
                APP_ERROR_CHECK(err_code);
              }
            }
            break;

    case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected, reason %d.", p_ble_evt->evt.gap_evt.params.disconnected.reason);
            m_conn_handle = BLE_CONN_HANDLE_INVALID;
            break;

Related