Bluetooth: audio: Add configurable PACS supported contexts

Add the ability to change supported contexts in PACS.
Enhance the context command in the shell module to make it configurable.

Signed-off-by: Szymon Czapracki <szymon.czapracki@codecoup.pl>
This commit is contained in:
Szymon Czapracki 2022-11-24 09:33:09 +01:00 committed by Carles Cufí
commit 35bd427927
4 changed files with 143 additions and 17 deletions

View file

@ -55,20 +55,20 @@ struct pacs {
sys_slist_t list;
};
#if defined(CONFIG_BT_PAC_SNK)
#if defined(CONTIG_BT_PAC_SNK)
static uint16_t snk_available_contexts;
static const uint16_t snk_supported_contexts = CONFIG_BT_PACS_SNK_CONTEXT;
static uint16_t snk_supported_contexts;
#else
static const uint16_t snk_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static const uint16_t snk_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static uint16_t snk_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static uint16_t snk_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
#endif /* CONFIG_BT_PAC_SNK */
#if defined(CONFIG_BT_PAC_SRC)
static uint16_t src_available_contexts;
static const uint16_t src_supported_contexts = CONFIG_BT_PACS_SRC_CONTEXT;
static uint16_t src_supported_contexts;
#else
static const uint16_t src_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static const uint16_t src_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static uint16_t src_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static uint16_t src_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
#endif /* CONFIG_BT_PAC_SRC */
NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, CONFIG_BT_L2CAP_TX_MTU);
@ -231,10 +231,12 @@ static ssize_t supported_context_read(struct bt_conn *conn,
}
static void available_contexts_notify(struct k_work *work);
static void supported_contexts_notify(struct k_work *work);
static K_WORK_DELAYABLE_DEFINE(available_contexts_work, available_contexts_notify);
static K_WORK_DELAYABLE_DEFINE(supported_contexts_work, supported_contexts_notify);
static int set_available_contexts(uint16_t contexts, uint16_t *available,
const uint16_t supported)
uint16_t supported)
{
int err;
@ -246,13 +248,45 @@ static int set_available_contexts(uint16_t contexts, uint16_t *available,
return 0;
}
*available = contexts;
err = k_work_reschedule(&available_contexts_work, PAC_NOTIFY_TIMEOUT);
if (err < 0) {
return err;
}
*available = contexts;
return 0;
}
static int set_supported_contexts(uint16_t contexts, uint16_t *supported,
uint16_t *available)
{
int err;
/* Ensure unspecified is always supported */
contexts |= BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED;
if (*supported == contexts) {
return 0;
}
err = k_work_reschedule(&supported_contexts_work, PAC_NOTIFY_TIMEOUT);
if (err < 0) {
return err;
}
*supported = contexts;
/* Update available contexts if needed*/
if ((contexts & *available) != *available) {
*available = *available & contexts;
err = k_work_reschedule(&available_contexts_work,
PAC_NOTIFY_TIMEOUT);
if (err < 0) {
LOG_WRN("Update available contexts notify failed: %d", err);
}
}
return 0;
}
@ -281,11 +315,22 @@ static inline int set_snk_available_contexts(uint16_t contexts)
return set_available_contexts(contexts, &snk_available_contexts,
snk_supported_contexts);
}
static inline int set_snk_supported_contexts(uint16_t contexts)
{
return set_supported_contexts(contexts, &snk_supported_contexts,
&snk_available_contexts);
}
#else
static inline int set_snk_available_contexts(uint16_t contexts)
{
return -ENOTSUP;
}
static inline int set_snk_supported_contexts(uint16_t contexts)
{
return -ENOTSUP;
}
#endif /* CONFIG_BT_PAC_SNK */
#if defined(CONFIG_BT_PAC_SNK_LOC)
@ -385,11 +430,22 @@ static inline int set_src_available_contexts(uint16_t contexts)
return set_available_contexts(contexts, &src_available_contexts,
src_supported_contexts);
}
static inline int set_src_supported_contexts(uint16_t contexts)
{
return set_supported_contexts(contexts, &src_supported_contexts,
&snk_supported_contexts);
}
#else
static inline int set_src_available_contexts(uint16_t contexts)
{
return -ENOTSUP;
}
static inline int set_src_supported_contexts(uint16_t contexts)
{
return -ENOTSUP;
}
#endif /* CONFIG_BT_PAC_SRC */
#if defined(CONFIG_BT_PAC_SRC_LOC)
@ -602,6 +658,21 @@ static void available_contexts_notify(struct k_work *work)
}
}
static void supported_contexts_notify(struct k_work *work)
{
struct bt_pacs_context context = {
.snk = sys_cpu_to_le16(snk_supported_contexts),
.src = sys_cpu_to_le16(src_supported_contexts),
};
int err;
err = bt_gatt_notify_uuid(NULL, BT_UUID_PACS_SUPPORTED_CONTEXT, pacs_svc.attrs,
&context, sizeof(context));
if (err != 0 && err != -ENOTCONN) {
LOG_WRN("Supported Audio Contexts notify failed: %d", err);
}
}
bool bt_pacs_context_available(enum bt_audio_dir dir, uint16_t context)
{
if (dir == BT_AUDIO_DIR_SOURCE) {
@ -722,6 +793,18 @@ int bt_pacs_set_available_contexts(enum bt_audio_dir dir, enum bt_audio_context
return -EINVAL;
}
int bt_pacs_set_supported_contexts(enum bt_audio_dir dir, enum bt_audio_context contexts)
{
switch (dir) {
case BT_AUDIO_DIR_SINK:
return set_snk_supported_contexts(contexts);
case BT_AUDIO_DIR_SOURCE:
return set_src_supported_contexts(contexts);
}
return -EINVAL;
}
enum bt_audio_context bt_pacs_get_available_contexts(enum bt_audio_dir dir)
{
switch (dir) {

View file

@ -1887,10 +1887,21 @@ static int cmd_context(const struct shell *sh, size_t argc, char *argv[])
return err;
}
err = bt_pacs_set_available_contexts(dir, ctx);
if (err) {
shell_error(ctx_shell, "Set available contexts err %d", err);
return err;
if (!strcmp(argv[3], "supported")) {
err = bt_pacs_set_supported_contexts(dir, ctx);
if (err) {
shell_error(ctx_shell, "Set supported contexts err %d", err);
return err;
}
} else if (!strcmp(argv[3], "available")) {
err = bt_pacs_set_available_contexts(dir, ctx);
if (err) {
shell_error(ctx_shell, "Set available contexts err %d", err);
return err;
}
} else {
shell_error(sh, "Unsupported context type: %s", argv[3]);
return -ENOEXEC;
}
return 0;
@ -1924,6 +1935,10 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, LOCATION);
__ASSERT(err == 0, "Failed to set sink location");
err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
CONTEXT);
__ASSERT(err == 0, "Failed to set sink supported contexts");
err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
CONTEXT);
__ASSERT(err == 0, "Failed to set sink available contexts");
@ -1933,6 +1948,10 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, LOCATION);
__ASSERT(err == 0, "Failed to set source location");
err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
CONTEXT);
__ASSERT(err == 0, "Failed to set sink supported contexts");
err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
CONTEXT);
__ASSERT(err == 0, "Failed to set source available contexts");
@ -2084,9 +2103,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(audio_cmds,
SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_location, NULL,
"<direction: sink, source> <location bitmask>",
cmd_set_loc, 3, 0),
SHELL_COND_CMD_ARG(CONFIG_BT_PACS, add_context, NULL,
"<direction: sink, source> <context bitmask>",
cmd_context, 3, 0),
SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_context, NULL,
"<direction: sink, source>"
"<context bitmask> <type: supported, available>",
cmd_context, 4, 0),
SHELL_SUBCMD_SET_END
);