Connection security level is stuck at level 1 after it had successfully paired (with confirmed connection security level 4) with an iPhone.

Hi,

My development environment:

- VS Code

- nRF Connect SDK: v2.7.0

Description:

- My firmware had successfully paired (with passcode) with an iPhone. Security level reaches level 4 as expected. BLE advertising is setup with accept_list to make sure only the paired Central can connect.

- After paired, it works for a few hours.

- Sometimes only : when reconnecting, security level is only level 1, and stick to level 1 forever.

- When the connection security level is stick to level 1, printing its connection info crashes the app although `bt_conn_get_info()` return success. Please refer to `print_connection_params()` below.

Outline of my code:

int main(void)
{
    ...
    int err = init_ecg_bluetooth();
	if (err)
	{
		LOG_ERR("bt_enable error returned: %d", err);
		return 0;
	}
	...
}

static struct bt_conn *current_conn = NULL;

static void on_connected(struct bt_conn *conn, uint8_t err)
{
    if (err)
    {
        LOG_ERR("Connection failed (err 0x%02x)\n", err);
    }
    else
    {
        LOG_INF("Connected\n");

        current_conn = bt_conn_ref(conn);
        print_connection_params(current_conn);
    }
}

static void on_disconnected(struct bt_conn *conn, uint8_t reason)
{
    // C:\ncs\v2.4.0\zephyr\include\zephyr\bluetooth\hci_err.h
    LOG_INF("Disconnected (reason 0x%02x)\n", reason);

    bt_conn_unref(current_conn);
    current_conn = NULL;
    ...
}

static void on_security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err error)
{
    if (error != BT_SECURITY_ERR_SUCCESS)
    {
        LOG_ERR("failed to upgrade security: %d", error);
        ...
        return;
    }

    ...

    LOG_INF("connection security upgraded: %d -> %d", level, is_conn_secured());

    ...
}

/**
 * @brief This only gets called for the first pairing.
 *        Since then, only @ref on_security_changed() is called.
 *
 * @param conn
 * @param bonded
 */
static void on_pairing_complete(struct bt_conn *conn, bool bonded)
{
    LOG_INF("bonded: %d", bonded);
    if (bonded)
    {
        ...

        bt_foreach_bond(BT_ID_DEFAULT, copy_last_bond_addr, NULL);
        print_addr_le(bond_addr, "bonded addr");

        ...
    }
}

static void on_pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
{
    LOG_ERR("pairing failed: %d", reason);

    ...
}

void print_connection_params(struct bt_conn *conn)
{
    struct bt_conn_info info;
    int err = bt_conn_get_info(conn, &info);
    if (err < 0)
    {
        LOG_ERR("Failed to get connection info: %d", err); // this line never prints!
    }
    else
    {
        LOG_INF("Connection params: interval %d*1.25ms, latency %d, timeout %d*10ms, security: %d",
                info.le.interval, info.le.latency, info.le.timeout,
                info.security.level); // ! crash here! this line never prints
    }
}

// Function below is triggered on a button press
void print_ecg_ble_state()
{
    print_addr_le(bond_addr, "bonded addr"); // this line prints
    ...
    
    if (current_conn)
    {
        LOG_INF("conn available with security level: %d %d %d",
                bt_conn_get_security(current_conn),
                is_streaming, // our app variable
                conn_param); // this line prints: 1 0 2
        print_connection_params(current_conn);
    }
    else
    {
        LOG_INF("conn not available"); // this does not print
    }

    ...
}

My questions:

  1. Why only sometimes, on reconnecting, BLE stack fails to upgrade the security level from 1 to 4? It sticks to level 1 forever until the system crashes (causing reboot). After reboot, the system works as normal. This symptom is confirmed when this app works with both iPhone and ESP32S3 acting as Central.
  2. As you may notice, `print_connection_params()` is called with `current_conn` in `on_connected()`. After the connection is stick with level 1 forever (error state), calling `print_connection_params()` on the referenced `current_conn` crashes the app. Why is this? 
  3. Connection upgrade is done at the nRF BLE stack level, is connection forever stick to security level 1 because something's wrong with this nRF SDK Connect v2.7.0?

Best regards,

Quan

Related