Channel Sounding Reflector not able to connect again after disconnection

Hi,

I am working on the channel sounding feature on the 54l15 and I want to perform it sequentially between 3 reflectors and one initiator. I realized that after I make a disconnection with a reflector, unless it reboots, it's not able to connect back. I am really puzzled by this as this looks like a simple solution but I have not a clue. This is my code for it. I'm thinking that maybe it's because when I disconnect it I didn't clean up the resources properly? It would return E: Advertising failed to start (err -12). Maybe this is also something I need to address on the initiator code?

#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/sys/reboot.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/cs.h>
#include <bluetooth/services/ras.h>

#include <dk_buttons_and_leds.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(app_main, LOG_LEVEL_INF);

#define CON_STATUS_LED DK_LED1

static K_SEM_DEFINE(sem_connected, 0, 1);

static struct bt_conn *connection;

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_RANGING_SERVICE_VAL)),
	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

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

	(void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("Connected to %s (err 0x%02X)", addr, err);

	if (err) {
		bt_conn_unref(conn);
		connection = NULL;
	}

	connection = bt_conn_ref(conn);

	k_sem_give(&sem_connected);

	dk_set_led_on(CON_STATUS_LED);
}

static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
{
	LOG_INF("Disconnected (reason 0x%02X)", reason);

	bt_conn_unref(conn);
	connection = NULL;

	dk_set_led_off(CON_STATUS_LED);
	// sys_reboot(SYS_REBOOT_COLD);

	int err;

	err = bt_enable(NULL);
	if (err) {
		LOG_ERR("Bluetooth init failed (err %d)", err);
		return 0;
	}

	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_2, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		LOG_ERR("Advertising failed to start (err %d)", err);
		return 0;
	}
}

static void remote_capabilities_cb(struct bt_conn *conn,
				   uint8_t status,
				   struct bt_conn_le_cs_capabilities *params)
{
	ARG_UNUSED(conn);
	ARG_UNUSED(params);

	if (status == BT_HCI_ERR_SUCCESS) {
		LOG_INF("CS capability exchange completed.");
	} else {
		LOG_WRN("CS capability exchange failed. (HCI status 0x%02x)", status);
	}
}

static void config_create_cb(struct bt_conn *conn,
			      uint8_t status,
			      struct bt_conn_le_cs_config *config)
{
	ARG_UNUSED(conn);

	if (status == BT_HCI_ERR_SUCCESS) {
		LOG_INF("CS config creation complete. ID: %d", config->id);
	} else {
		LOG_WRN("CS config creation failed. (HCI status 0x%02x)", status);
	}
}

static void security_enable_cb(struct bt_conn *conn, uint8_t status)
{
	ARG_UNUSED(conn);

	if (status == BT_HCI_ERR_SUCCESS) {
		LOG_INF("CS security enabled.");
	} else {
		LOG_WRN("CS security enable failed. (HCI status 0x%02x)", status);
	}
}

static void procedure_enable_cb(struct bt_conn *conn,
				uint8_t status,
				struct bt_conn_le_cs_procedure_enable_complete *params)
{
	ARG_UNUSED(conn);

	if (status == BT_HCI_ERR_SUCCESS) {
		if (params->state == 1) {
			LOG_INF("CS procedures enabled.");
		} else {
			LOG_INF("CS procedures disabled.");
		}
	} else {
		LOG_WRN("CS procedures enable failed. (HCI status 0x%02x)", status);
	}
}

BT_CONN_CB_DEFINE(conn_cb) = {
	.connected = connected_cb,
	.disconnected = disconnected_cb,
	.le_cs_read_remote_capabilities_complete = remote_capabilities_cb,
	.le_cs_config_complete = config_create_cb,
	.le_cs_security_enable_complete = security_enable_cb,
	.le_cs_procedure_enable_complete = procedure_enable_cb,
};

int main(void)
{
	int err;

	LOG_INF("Starting Channel Sounding Reflector Sample");

	dk_leds_init();

	err = bt_enable(NULL);
	if (err) {
		LOG_ERR("Bluetooth init failed (err %d)", err);
		return 0;
	}

	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_2, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		LOG_ERR("Advertising failed to start (err %d)", err);
		return 0;
	}

	while (true) {
		k_sem_take(&sem_connected, K_FOREVER);

		const struct bt_le_cs_set_default_settings_param default_settings = {
			.enable_initiator_role = false,
			.enable_reflector_role = true,
			.cs_sync_antenna_selection = BT_LE_CS_ANTENNA_SELECTION_OPT_REPETITIVE,
			.max_tx_power = BT_HCI_OP_LE_CS_MAX_MAX_TX_POWER,
		};

		err = bt_le_cs_set_default_settings(connection, &default_settings);
		if (err) {
			LOG_ERR("Failed to configure default CS settings (err %d)", err);
		}
	}

	return 0;
}

I also tried a sequential model where I enable and disable channel sounding on each device instead of disconnecting, but I realized that the results are similar to those from concurrent models. They are all able to maintain connections but one one device actually receives data. Would this also be because the firmware was not optimized for this use case? Thank you in advance.

Sincerely,

Triston Tsui

Parents
  • Hi Triston,

    -12 is -ENOMEM and that is returned because when at this poin in the disconnected callback, all resources have not been freed yet, so it is too early to re-start advertising. You should be able to handle this using the recycled callback (this is demonstrated here).

    Best regards,

    Einar

  • Hi Einar, I tried the recycled callback function, but it still did not work. I just put another advertising function inside of the recycled callback, since that was shown in the sample, was I supposed to add anything additional? It was advertising, but it kept disconnecting right after.

    Another question, when I tried to run sequential procedures by enabling and disabling bluetooth, it would only work for the first device that requested the data, would the problem be similar to concurrent procedures? Where the schedule was not optimized to hold the connections of all devices and perform the cs procedure at the same time? In this case would I have to do a full sequential by connecting and disconnecting?

    Thank you for the help.

  • Hi,

    I would have expected usign the recycled event to be enought. You could add a futherr delay using a delayable work item (you can see many exampls of this in the SDK if you sarch for k_work_init_delayable()).

    Which SDK version are you using? I ask beacause channel sounding is a new feature with onging work, so I recommend using the latest release.

    Regardign the last questions, we are planning to support multiple connections, but for 3.0.1 it has not been tested. Note that there is no need to disable and re-enable the Bluetooth stack when re-starting advertising. I did not see this before, but I see you have a call to bt_enable() when restarting advertising, and this shoudl be removed (the Bluetooth stack has not been disabled before this point).

Reply
  • Hi,

    I would have expected usign the recycled event to be enought. You could add a futherr delay using a delayable work item (you can see many exampls of this in the SDK if you sarch for k_work_init_delayable()).

    Which SDK version are you using? I ask beacause channel sounding is a new feature with onging work, so I recommend using the latest release.

    Regardign the last questions, we are planning to support multiple connections, but for 3.0.1 it has not been tested. Note that there is no need to disable and re-enable the Bluetooth stack when re-starting advertising. I did not see this before, but I see you have a call to bt_enable() when restarting advertising, and this shoudl be removed (the Bluetooth stack has not been disabled before this point).

Children
No Data
Related