BT_HCI_ERR_CONN_FAIL_TO_ESTAB every time on re-connection

I am working on a peripheral / receiver project based on the nRF5340 audio application for SDK 2.5.1. 

I have added the ability for the receiver to advertise and accept a connection from a central device. 

This all works fine up to a certain point. After some time, the connection gets terminated by the receiver. I believe it's a known issue with controllers when both syncing to a broadcast stream and having an ACL connection at the same time. 

The disconnecting issue aside, my central device cannot re-connect to the peripheral again after the disconnect, unless the receiver gets a reset. Here is what happens in my logs :

HL [00:01:09.882,537] <inf> bt_mgmt: Disconnected in bt_mgmt : 7F:A0:94:3D:DF:2E (random) : (reason 0x08)
HL [00:01:09.882,568] <wrn> streamctrl_broadcast_sink: Unexpected/unhandled bt_mgmt event: 6
HL [00:01:09.883,666] <inf> bt_mgmt_adv: connectable extended advertising set created
HL [00:01:09.883,758] <inf> broadcast_sink: Application disconnected: 7F:A0:94:3D:DF:2E (random) (reason 0x08)
HL [00:01:09.883,758] <inf> broadcast_sink: Restarting advertising..
HL [00:01:09.884,674] <inf> bt_mgmt_adv: Advertising successfully started
HL [00:01:10.136,108] <inf> bt_mgmt: Connected in bt_mgmt
HL [00:01:10.136,199] <inf> bt_mgmt: Connected: 5F:B4:9C:F0:98:9D (random)
HL [00:01:10.136,413] <wrn> streamctrl_broadcast_sink: Unexpected/unhandled bt_mgmt event: 2
HL [00:01:10.136,505] <inf> broadcast_sink: Application connected: 5F:B4:9C:F0:98:9D (random)

HL [00:01:10.332,550] <inf> bt_mgmt: Disconnected in bt_mgmt : 5F:B4:9C:F0:98:9D (random) : (reason 0x3e)

This happens again and again when the central tris to re-connect after the receiver disconnects. It fails with reason 0x3eBT_HCI_ERR_CONN_FAIL_TO_ESTAB

Here are my connected and disconnected callback functions which are implemented in broadcast_sink.c :  

static void connected(struct bt_conn *conn, uint8_t err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (err != 0U)
	{
		LOG_INF("Failed to connect to application %s (%u)", addr, err);
		app_conn = NULL;
		return;
	}

	app_conn = bt_conn_ref(conn);

	if (app_conn == NULL)
	{
		LOG_ERR("connected - app_conn is NULL");
	}

	LOG_INF("Application connected: %s\n", addr);

}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (app_conn)
	{
		bt_conn_unref(app_conn);
		app_conn = NULL;
	}


	LOG_INF("Application disconnected: %s (reason 0x%02x)", addr, reason);

	LOG_INF("Restarting advertising..");

}

Also within the SDK , in bluetooth/bt_management/bt_mgmt.c, there are connected and disconnected callbacks which also get invoked before my own callbacks. 

static void connected_cb(struct bt_conn *conn, uint8_t err)
{
	LOG_INF("Connected in bt_mgmt");

	int ret;
	char addr[BT_ADDR_LE_STR_LEN] = {0};
	uint8_t num_conn = 0;
	uint16_t conn_handle;
	enum ble_hci_vs_tx_power conn_tx_pwr;
	struct bt_mgmt_msg msg;

	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (err) {
		LOG_ERR("ACL connection in bt_mgmt to addr: %s, conn: %p, failed, error %d", addr,
			(void *)conn, err);

		bt_conn_unref(conn);

		if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
			ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL);
			if (ret) {
				LOG_ERR("Failed to restart scanning: %d", ret);
			}
		}

		if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
			//ret = bt_mgmt_adv_start(NULL, 0, NULL, 0, true);
			ret = bt_mgmt_adv_start(ext_adv_buf, ext_adv_buf_cnt, NULL, 0, true);
			if (ret) {
				LOG_ERR("Failed to restart advertising: %d", ret);
			}
		}

		return;
	}

	bt_conn_foreach(BT_CONN_TYPE_LE, conn_state_connected_check, (void *)&num_conn);

	/* ACL connection established */
	/* NOTE: The string below is used by the Nordic CI system */
	LOG_INF("Connected: %s", addr);

	if (IS_ENABLED(CONFIG_BT_CENTRAL) && (num_conn < MAX_CONN_NUM)) {
		/* Room for more connections, start scanning again */
		ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL);
		if (ret) {
			LOG_ERR("Failed to resume scanning: %d", ret);
		}
	}

	ret = bt_hci_get_conn_handle(conn, &conn_handle);
	if (ret) {
		LOG_ERR("Unable to get conn handle");
	} else {
		if (IS_ENABLED(CONFIG_NRF_21540_ACTIVE)) {
			conn_tx_pwr = CONFIG_NRF_21540_MAIN_DBM;
		} else {
			conn_tx_pwr = CONFIG_BLE_CONN_TX_POWER_DBM;
		}

		ret = ble_hci_vsc_conn_tx_pwr_set(conn_handle, conn_tx_pwr);
		if (ret) {
			LOG_ERR("Failed to set TX power for conn");
		} else {
			LOG_DBG("TX power set to %d dBm for connection %p", conn_tx_pwr,
				(void *)conn);
		}
	}

	msg.event = BT_MGMT_CONNECTED;
	msg.conn = conn;

	ret = zbus_chan_pub(&bt_mgmt_chan, &msg, K_NO_WAIT);
	ERR_CHK(ret);

	if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
		ret = bt_conn_set_security(conn, BT_SECURITY_L2);
		if (ret) {
			LOG_ERR("Failed to set security to L2: %d", ret);
		}
	}
}

static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
{
	int ret;
	char addr[BT_ADDR_LE_STR_LEN];
	struct bt_mgmt_msg msg;

	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	/* NOTE: The string below is used by the Nordic CI system */
	LOG_INF("Disconnected in bt_mgmt : %s : (reason 0x%02x)", addr, reason);

	if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
		bt_conn_unref(conn);
	}

	/* Publish disconnected */
	msg.event = BT_MGMT_DISCONNECTED;
	msg.conn = conn;

	ret = zbus_chan_pub(&bt_mgmt_chan, &msg, K_NO_WAIT);
	ERR_CHK(ret);

	if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
		//ret = bt_mgmt_adv_start(NULL, 0, NULL, 0, true);
		ret = bt_mgmt_adv_start(ext_adv_buf, ext_adv_buf_cnt, NULL, 0, true);
		ERR_CHK(ret);
	}

	if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
		ret = bt_mgmt_scan_start(0, 0, BT_MGMT_SCAN_TYPE_CONN, NULL);
		if (ret) {
			LOG_ERR("Failed to restart scanning: %d", ret);
		}
	}
}

Any ideas as to why the central device can't reconnect here with error BT_HCI_ERR_CONN_FAIL_TO_ESTAB , until the receiver gets reset? The receiver and central device are right beside one another.

The receiver is clearly not in a right state to accept a new connection after it disconnects, but I'm not sure how to solve this. Thanks in advance for any help. 

Related