Bonded Pairing disconnect reason 19 (0x13) after reset

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?

  • Hi Eric

    Just wanted to let you know that it builds on my end and I've reproduced the issue. I just assumed it was the bonding information that was deleted, but since the iOS device only allows pairing the default procedure is to erase the pairing info upon a disconnect. I'm currently looking into how to properly store this info between disconnects and power resets and will get back to you when I have a solution. Just thought you wanted an update. Thank you for your patience!

    Best regards,

    Simon

  • Hi

    So I made some progress, and depending on whether you want bonding or pairing in your project I have some suggestions.

    If you're happy with just doing pairing, you can set the CONFIG_BT_BONDABLE=n in your prj.conf. This will make the iOS ask for a pairing request after every disconnect and power reset, but it will be able to connect. As this will do pairing only, and erase pairing information between every connection.

    If you want bonding, there is a bit more needed to be done it seems. You need to set CONFIG_SETTINGS_NVS = y instead of CONFIG_SETTINGS_NONE, and you need to implement the settings_load function after the Bluetooth initialization in your sample, as that seems to be missing. The peripheral_uart sample (and most other BLE samples in the SDK) can be used as a template.

    Best regards,

    Simon

  • Great news! It is working now. I added the two following configuration lines:

    CONFIG_SETTINGS_NVS=y
    CONFIG_BT_SETTINGS=y

    As well as the settings_load call:

    #if (CONFIG_SETTINGS)
    	err = settings_load();
    #endif

    All seems to be working now. Thank you for the help!

    Let me know how I can go about documenting this in a public manner. I am not sure If it is better to open a new ticket or delete my comment with the source code.

  • Very glad to hear that!

    You can remove the comment with the .zip file and I can set the ticket back to public once you've done that. I think it's better for other users to see the full discussion instead of creating a new ticket.

    Best regards,

    Simon

Related