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?

  • Sorry, Simon, I didn't mean to accept the answer, I'm still facing this issue.

    When I say "reset sensor" I simply mean toggling the reset pin or cycling power to the device. NOT programming or erasing. 

    It seems as if the bonding information is not being stored by the sensor. Here is what the nRF Connect logs show after the following steps:

    1. Connect and read encrypted service using nRF Connect app.

    2. Accept iOS prompt to "pair".

    3. Press reset button on my sensor.

    4. Attempt to reconnect to the sensor using my same phone and nRF Connect app.

    5. Connection fails. Here is what nRF connect log shows:

    nRF Connect Connection Logs

    It pretty clearly implies that the sensor is not storing the bonding information.

    I feel like I'm missing an additional step in allowing the device to store the bonding information. I should note again that I do store my own user information using the NVS module API.

    Do I need to configure any special memory offset or something for bonding information? Is it trying to overwrite my user data or bootloader or something?

  • Hi again Eric

    Indeed this seems to be the case. I've done some digging and haven't really gotten to a good conclusion, as it doesn't seem from the snippets you've already shared that the bond information is taking place at all. It could be that the peripheral device changes the GAP address as well, which will make the peripheral device appear as a new device to the iOS device. You can find an example on how this is done here: https://devzone.nordicsemi.com/f/nordic-q-a/37369/switching-keyboard-mouse-between-3-paired-devices/143932#143932 

    Would it be possible for you to upload the full project in a state that builds on my end so we can try to debug this from our end and find what happens with the bonding information. Since it works as intended until you reset it, my guess is that there is something happening upon a pin reset that deletes bond information. If you don't want to share your full project publicly, we can set this case to private mode so that only yourself and Nordic engineers will be able to view its contents.

    Best regards, 

    Simon

  • Thanks Simon, I would prefer to set the case to private in order to share my code. I would happily update the public ticket with the solution once resolved (or create a new ticket with the solution without any sensitive information). 

    I assume setting this ticket to private has to be done on your end? Once set to private, I will upload my source code.

  • Hi Eric

    I've set the ticket to private mode now. You can safely upload your code/project here now.

    Best regards,

    Simon

Related