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:
- 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.
- 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?
- 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
