Commit 500a1792 authored by Emil Gydesen's avatar Emil Gydesen Committed by Carles Cufi
Browse files

Bluetooth: Audio: Add TBS shell module



Add a shell module for the TBS.

Signed-off-by: default avatarEmil Gydesen <emil.gydesen@nordicsemi.no>
parent 2a08b9e7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@ zephyr_library_sources_ifdef(
  CONFIG_BT_CSIS_CLIENT
  csis_client.c
  )
zephyr_library_sources_ifdef(
  CONFIG_BT_TBS
  tbs.c
  )
zephyr_library_sources_ifdef(
  CONFIG_BT_MPL
  mpl.c
+602 −0
Original line number Diff line number Diff line
/** @file
 *  @brief Bluetooth Telephone Bearer Service shell
 */

/*
 * Copyright (c) 2020-2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdlib.h>
#include <zephyr.h>
#include <shell/shell.h>

#include <bluetooth/audio/tbs.h>

#include "bt.h"

static struct bt_conn *tbs_authorized_conn;
static bool cbs_registered;

static bool tbs_authorize_cb(struct bt_conn *conn)
{
	return conn == tbs_authorized_conn;
}

static bool tbs_originate_call_cb(struct bt_conn *conn, uint8_t call_index,
				  const char *uri)
{
	/* Always accept calls */
	return true;
}

static struct bt_tbs_cb tbs_cbs = {
	.originate_call = tbs_originate_call_cb,
	.authorize = tbs_authorize_cb
};

static int cmd_tbs_authorize(const struct shell *sh, size_t argc, char *argv[])
{
	char addr[BT_ADDR_LE_STR_LEN];

	tbs_authorized_conn = default_conn;

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

	shell_print(sh, "Connection with addr %s authorized", addr);

	return 0;
}

static int cmd_tbs_init(void)
{
	if (!cbs_registered) {
		bt_tbs_register_cb(&tbs_cbs);
		cbs_registered = true;
	}

	return 0;
}

static int cmd_tbs_accept(const struct shell *sh, size_t argc, char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_accept((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_terminate(const struct shell *sh, size_t argc,
			     char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_terminate((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_hold(const struct shell *sh, size_t argc, char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_hold((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_retrieve(const struct shell *sh, size_t argc,
			    char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_retrieve((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_originate(const struct shell *sh, size_t argc, char *argv[])
{
	long service_index;
	int result;
	uint8_t call_index;

	if (argc > 2) {
		service_index = strtol(argv[1], NULL, 0);
		if (service_index < 0 ||
		    service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
			shell_error(sh, "Invalid service index: %ld",
				    service_index);

			return -ENOEXEC;
		}
	} else {
		service_index = 0;
	}

	result = bt_tbs_originate((uint8_t)service_index, argv[argc - 1],
				  &call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS call_index %u originated", call_index);
	}

	return result;
}

static int cmd_tbs_join(const struct shell *sh, size_t argc, char *argv[])
{
	uint8_t call_indexes[CONFIG_BT_TBS_MAX_CALLS];
	int result;
	long call_index;

	for (int i = 1; i < argc; i++) {
		call_index = strtol(argv[i], NULL, 0);

		if (call_index < 0 || call_index > UINT8_MAX) {
			shell_error(sh, "Invalid call index %ld", call_index);
			return -ENOEXEC;
		}

		call_indexes[i - 1] = (uint8_t)call_index;
	}

	result = bt_tbs_join(argc - 1, call_indexes);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS join succeeded");
	}

	return result;
}

static int cmd_tbs_answer(const struct shell *sh, size_t argc, char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_remote_answer((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_remote_hold(const struct shell *sh, size_t argc,
			       char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_remote_hold((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_remote_retrieve(const struct shell *sh, size_t argc,
				   char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_remote_retrieve((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_remote_terminate(const struct shell *sh, size_t argc,
				    char *argv[])
{
	long call_index;
	int result;

	call_index = strtol(argv[1], NULL, 0);
	if (call_index <= 0 || call_index > UINT8_MAX) {
		shell_error(sh, "Invalid call_index: %ld", call_index);
		return -ENOEXEC;
	}

	result = bt_tbs_remote_terminate((uint8_t)call_index);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded for call_index: %ld",
			    call_index);
	}

	return result;
}

static int cmd_tbs_incoming(const struct shell *sh, size_t argc, char *argv[])
{
	long service_index;
	int result;

	if (argc > 4) {
		service_index = strtol(argv[1], NULL, 0);
		if (service_index < 0 ||
		    service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
			shell_error(sh, "Invalid service index: %ld",
				    service_index);

			return -ENOEXEC;
		}
	} else {
		service_index = 0;
	}

	result = bt_tbs_remote_incoming((uint8_t)service_index,
					argv[argc - 3],
					argv[argc - 2],
					argv[argc - 1]);
	if (result < 0) {
		shell_print(sh, "TBS failed: %d", result);
	} else {
		shell_print(sh, "TBS succeeded");
	}

	return result;
}

static int cmd_tbs_set_bearer_provider_name(const struct shell *sh, size_t argc,
					    char *argv[])
{
	long service_index;
	int result;

	if (argc > 2) {
		if (!strcmp(argv[1], "gtbs")) {
			service_index = BT_TBS_GTBS_INDEX;
		} else {
			service_index = strtol(argv[1], NULL, 0);
			if (service_index < 0 ||
			    service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
				shell_error(sh, "Invalid service index: %ld",
					    service_index);
				return -ENOEXEC;
			}
		}
	} else {
		service_index = 0;
	}

	result = bt_tbs_set_bearer_provider_name((uint8_t)service_index,
						 argv[argc - 1]);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "Could not set provider name: %d", result);
	}

	return result;
}

static int cmd_tbs_set_bearer_technology(const struct shell *sh, size_t argc,
					 char *argv[])
{
	long technology;
	long service_index;
	int result;

	if (argc > 2) {
		if (!strcmp(argv[1], "gtbs")) {
			service_index = BT_TBS_GTBS_INDEX;
		} else {
			service_index = strtol(argv[1], NULL, 0);
			if (service_index < 0 ||
			    service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
				shell_error(sh, "Invalid service index: %ld",
					    service_index);
				return -ENOEXEC;
			}
		}
	} else {
		service_index = 0;
	}

	technology = strtol(argv[argc - 1], NULL, 0);
	if (technology < 0 || technology > UINT8_MAX) {
		shell_error(sh, "Invalid technology value: %ld", technology);

		return -ENOEXEC;
	}

	result = bt_tbs_set_bearer_technology((uint8_t)service_index,
					      (uint8_t)technology);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "Could not set technology: %d", result);
	}

	return result;
}

static int cmd_tbs_set_bearer_signal_strength(const struct shell *sh,
					      size_t argc, char *argv[])
{
	long signal_strength;
	long service_index;
	int result;

	if (argc > 2) {
		if (!strcmp(argv[1], "gtbs")) {
			service_index = BT_TBS_GTBS_INDEX;
		} else {
			service_index = strtol(argv[1], NULL, 0);
			if (service_index < 0 ||
			service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
				shell_error(sh, "Invalid service index: %ld",
					    service_index);

				return -ENOEXEC;
			}
		}
	} else {
		service_index = 0;
	}

	signal_strength = strtol(argv[argc - 1], NULL, 0);
	if (signal_strength < 0 || signal_strength > UINT8_MAX) {
		shell_error(sh, "Invalid signal strength: %ld",
			    signal_strength);

		return -ENOEXEC;
	}

	result = bt_tbs_set_signal_strength((uint8_t)service_index,
					    (uint8_t)signal_strength);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "Could not set signal strength: %d", result);
	}

	return result;
}

static int cmd_tbs_set_status_flags(const struct shell *sh, size_t argc,
				    char *argv[])
{
	long status_flags;
	long service_index;
	int result;

	if (argc > 2) {
		if (!strcmp(argv[1], "gtbs")) {
			service_index = BT_TBS_GTBS_INDEX;
		} else {
			service_index = strtol(argv[1], NULL, 0);
			if (service_index < 0 ||
			    service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
				shell_error(sh, "Invalid service index: %ld",
					    service_index);

				return -ENOEXEC;
			}
		}
	} else {
		service_index = 0;
	}

	status_flags = strtol(argv[argc - 1], NULL, 0);
	if (status_flags < 0 || status_flags > 3) {
		shell_error(sh, "Invalid status flags value: %ld",
			    status_flags);

		return -ENOEXEC;
	}

	result = bt_tbs_set_status_flags((uint8_t)service_index,
					 (uint16_t)status_flags);
	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "Could not set status flags: %d", result);
	}

	return result;
}

static int cmd_tbs_set_uri_scheme_list(const struct shell *sh, size_t argc,
				       char *argv[])
{
	long service_index;
	int result;

	service_index = strtol(argv[1], NULL, 0);
	if (service_index < 0 || service_index >= CONFIG_BT_TBS_BEARER_COUNT) {
		shell_error(sh, "Invalid service index: %ld", service_index);

		return -ENOEXEC;
	}

	result = bt_tbs_set_uri_scheme_list((uint8_t)service_index,
					    (const char **)&argv[2],
					    argc - 2);

	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
		shell_print(sh, "Could not set URI prefix list: %d", result);
	}

	return result;
}

static int cmd_tbs_print_calls(const struct shell *sh, size_t argc,
			       char *argv[])
{
	if (IS_ENABLED(CONFIG_BT_DEBUG_TBS)) {
		bt_tbs_dbg_print_calls();
		return 0;
	}

	return -ENOEXEC;
}

static int cmd_tbs(const struct shell *sh, size_t argc, char **argv)
{
	if (argc > 1) {
		shell_error(sh, "%s unknown parameter: %s", argv[0],
			    argv[1]);
	} else {
		shell_error(sh, "%s Missing subcommand", argv[0]);
	}

	return -ENOEXEC;
}

SHELL_STATIC_SUBCMD_SET_CREATE(tbs_cmds,
	SHELL_CMD_ARG(init, NULL,
		      "Initialize TBS",
		      cmd_tbs_init, 1, 0),
	SHELL_CMD_ARG(authorize, NULL,
		      "Authorize the current connection",
		      cmd_tbs_authorize, 1, 0),
	SHELL_CMD_ARG(accept, NULL,
		      "Accept call <call_index>",
		      cmd_tbs_accept, 2, 0),
	SHELL_CMD_ARG(terminate, NULL,
		      "Terminate call <call_index>",
		      cmd_tbs_terminate, 2, 0),
	SHELL_CMD_ARG(hold, NULL,
		      "Hold call <call_index>",
		      cmd_tbs_hold, 2, 0),
	SHELL_CMD_ARG(retrieve, NULL,
		      "Retrieve call <call_index>",
		      cmd_tbs_retrieve, 2, 0),
	SHELL_CMD_ARG(originate, NULL,
		      "Originate call [<instance_index>] <uri>",
		      cmd_tbs_originate, 2, 1),
#if CONFIG_BT_TBS_MAX_CALLS > 1
	SHELL_CMD_ARG(join, NULL,
		      "Join calls <id> <id> [<id> [<id> [...]]]",
		      cmd_tbs_join, 3, CONFIG_BT_TBS_MAX_CALLS - 2),
#endif /* CONFIG_BT_TBS_MAX_CALLS > 1 */
	SHELL_CMD_ARG(incoming, NULL,
		      "Simulate incoming remote call "
		      "[<{instance_index, gtbs}>] <local_uri> <remote_uri> "
		      "<remote_friendly_name>",
		      cmd_tbs_incoming, 4, 1),
	SHELL_CMD_ARG(remote_answer, NULL,
		      "Simulate remote answer outgoing call <call_index>",
		      cmd_tbs_answer, 2, 0),
	SHELL_CMD_ARG(remote_retrieve, NULL,
		      "Simulate remote retrieve <call_index>",
		      cmd_tbs_remote_retrieve, 2, 0),
	SHELL_CMD_ARG(remote_terminate, NULL,
		      "Simulate remote terminate <call_index>",
		      cmd_tbs_remote_terminate, 2, 0),
	SHELL_CMD_ARG(remote_hold, NULL,
		      "Simulate remote hold <call_index>",
		      cmd_tbs_remote_hold, 2, 0),
	SHELL_CMD_ARG(set_bearer_provider_name, NULL,
		      "Set the bearer provider name [<{instance_index, gtbs}>] "
		      "<name>",
		      cmd_tbs_set_bearer_provider_name, 2, 1),
	SHELL_CMD_ARG(set_bearer_technology, NULL,
		      "Set the bearer technology [<{instance_index, gtbs}>] "
		      "<technology>",
		      cmd_tbs_set_bearer_technology, 2, 1),
	SHELL_CMD_ARG(set_bearer_signal_strength, NULL,
		      "Set the bearer signal strength "
		      "[<{instance_index, gtbs}>] <strength>",
		      cmd_tbs_set_bearer_signal_strength, 2, 1),
	SHELL_CMD_ARG(set_status_flags, NULL,
		      "Set the bearer feature and status value "
		      "[<{instance_index, gtbs}>] <feature_and_status>",
		      cmd_tbs_set_status_flags, 2, 1),
	SHELL_CMD_ARG(set_uri_scheme, NULL,
		      "Set the URI prefix list <bearer_idx> "
		      "<uri1 [uri2 [uri3 [...]]]>",
		      cmd_tbs_set_uri_scheme_list, 3, 30),
	SHELL_CMD_ARG(print_calls, NULL,
		      "Output all calls in the debug log",
		      cmd_tbs_print_calls, 1, 0),
	SHELL_SUBCMD_SET_END
);

SHELL_CMD_ARG_REGISTER(tbs, &tbs_cmds, "Bluetooth TBS shell commands",
		       cmd_tbs, 1, 1);
+4 −2
Original line number Diff line number Diff line
@@ -79,6 +79,9 @@ CONFIG_BT_MPL_MAX_OBJ_SIZE=600
CONFIG_BT_MPL_ICON_BITMAP_SIZE=321
CONFIG_BT_MPL_TRACK_MAX_SIZE=50

# Telephone bearer service
CONFIG_BT_TBS=y

CONFIG_BT_MCS=y
CONFIG_BT_MCC=y
CONFIG_BT_MCC_OTS=y
@@ -105,9 +108,8 @@ CONFIG_BT_DEBUG_MCC=y
CONFIG_BT_OTS_LOG_LEVEL_DBG=y
CONFIG_BT_DEBUG_OTS_CLIENT=y
CONFIG_MCTL_DEBUG=y

CONFIG_BT_DEBUG_ASCS=y
CONFIG_BT_DEBUG_PACS=y
CONFIG_BT_AUDIO_DEBUG_UNICAST_SERVER=y

CONFIG_BT_DEBUG_HAS=y
CONFIG_BT_DEBUG_TBS=y