I have an existing production application and I am trying to enable "just works" bonded pairing. I am using nRF Connect version 2.3.0.
The steps I have taken so far:
1. I have updated my main service (the one also in the advertising packet) to have encrypted characteristics like so:
BT_GATT_SERVICE_DEFINE(history_service, BT_GATT_PRIMARY_SERVICE(BT_UUID_HISTORY_SERVICE), BT_GATT_CHARACTERISTIC(BT_UUID_HISTORY_SERVICE_DATAPOINT, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, read_history_cb_fn, on_receive_datapoint, history_datapoint_buf), BT_GATT_CCC(on_cccd_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
2. I added CONFIG_BT_SMP=y to my prj.conf file
3. I included the security_changed parameter to my bt_conn_cb struct:
static void security_changed(struct bt_conn *conn, bt_security_t level,
enum bt_security_err err)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (!err)
{
printk("Security changed: level %u\n", level);
}
else
{
printk("Security failed: level %u err %d\n", level, err);
}
}
static struct bt_conn_cb conn_callbacks = {
.connected = connected,
.disconnected = disconnected,
.security_changed = security_changed,
.le_param_req = le_param_req,
.le_param_updated = le_param_updated,
};
4. I configured the following additional callbacks (I am going for "just works" bonding and do not have any interface on the sensor itself so I cannot verify a passkey or press a button):
static void auth_cancel(struct bt_conn *conn)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Pairing cancelled\n");
}
static struct bt_conn_auth_cb conn_auth_callbacks = {
.passkey_display = NULL,
.passkey_confirm = NULL,
.cancel = auth_cancel,
.pairing_confirm = NULL,
};
static void pairing_complete(struct bt_conn *conn, bool bonded)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
}
static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Pairing failed conn: %s, reason %d\n", addr, reason);
}
static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
.pairing_complete = pairing_complete,
.pairing_failed = pairing_failed};
My bluetooth setup function is as follows:
bt_conn_cb_register(&conn_callbacks);
err = bt_conn_auth_cb_register(&conn_auth_callbacks);
err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
if (err)
{
printk("Failed to register authorization callbacks.\n");
return;
}
After all of these steps, when I first connect to the sensor, my phone (iOS) asks me if I would like to pair. I choose "pair". But then if I reset my sensor and try to connect to the sensor again with my phone, it disconnects right away with reason 19:
Connection established!
Connected to: 74:8F:43:4A:8B:D3 (random)
Role: 1
Connection interval: 24
Slave latency: 0
Connection supervisory timeout: 72
Disconnected: 19
What am I missing? What does disconnect reason 19 mean?