Skip to content

Commit 35bd427

Browse files
szymon-czaprackicarlescufi
authored andcommitted
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 <[email protected]>
1 parent cc40bc3 commit 35bd427

File tree

4 files changed

+142
-16
lines changed

4 files changed

+142
-16
lines changed

include/zephyr/bluetooth/audio/pacs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ int bt_pacs_set_available_contexts(enum bt_audio_dir dir,
9696
*/
9797
enum bt_audio_context bt_pacs_get_available_contexts(enum bt_audio_dir dir);
9898

99+
/** @brief Set the supported contexts for an endpoint type
100+
*
101+
* @param dir Direction of the endpoints to change available contexts for.
102+
* @param contexts The contexts to be set.
103+
*/
104+
int bt_pacs_set_supported_contexts(enum bt_audio_dir dir,
105+
enum bt_audio_context contexts);
106+
99107
#ifdef __cplusplus
100108
}
101109
#endif

subsys/bluetooth/audio/pacs.c

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,20 @@ struct pacs {
5555
sys_slist_t list;
5656
};
5757

58-
#if defined(CONFIG_BT_PAC_SNK)
58+
#if defined(CONTIG_BT_PAC_SNK)
5959
static uint16_t snk_available_contexts;
60-
static const uint16_t snk_supported_contexts = CONFIG_BT_PACS_SNK_CONTEXT;
60+
static uint16_t snk_supported_contexts;
6161
#else
62-
static const uint16_t snk_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
63-
static const uint16_t snk_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
62+
static uint16_t snk_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
63+
static uint16_t snk_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
6464
#endif /* CONFIG_BT_PAC_SNK */
6565

6666
#if defined(CONFIG_BT_PAC_SRC)
6767
static uint16_t src_available_contexts;
68-
static const uint16_t src_supported_contexts = CONFIG_BT_PACS_SRC_CONTEXT;
68+
static uint16_t src_supported_contexts;
6969
#else
70-
static const uint16_t src_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
71-
static const uint16_t src_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
70+
static uint16_t src_available_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
71+
static uint16_t src_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
7272
#endif /* CONFIG_BT_PAC_SRC */
7373

7474
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,
231231
}
232232

233233
static void available_contexts_notify(struct k_work *work);
234+
static void supported_contexts_notify(struct k_work *work);
234235
static K_WORK_DELAYABLE_DEFINE(available_contexts_work, available_contexts_notify);
236+
static K_WORK_DELAYABLE_DEFINE(supported_contexts_work, supported_contexts_notify);
235237

236238
static int set_available_contexts(uint16_t contexts, uint16_t *available,
237-
const uint16_t supported)
239+
uint16_t supported)
238240
{
239241
int err;
240242

@@ -246,13 +248,45 @@ static int set_available_contexts(uint16_t contexts, uint16_t *available,
246248
return 0;
247249
}
248250

251+
err = k_work_reschedule(&available_contexts_work, PAC_NOTIFY_TIMEOUT);
252+
if (err < 0) {
253+
return err;
254+
}
255+
249256
*available = contexts;
250257

251-
err = k_work_reschedule(&available_contexts_work, PAC_NOTIFY_TIMEOUT);
258+
return 0;
259+
}
260+
261+
static int set_supported_contexts(uint16_t contexts, uint16_t *supported,
262+
uint16_t *available)
263+
{
264+
int err;
265+
266+
/* Ensure unspecified is always supported */
267+
contexts |= BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED;
268+
269+
if (*supported == contexts) {
270+
return 0;
271+
}
272+
273+
err = k_work_reschedule(&supported_contexts_work, PAC_NOTIFY_TIMEOUT);
252274
if (err < 0) {
253275
return err;
254276
}
255277

278+
*supported = contexts;
279+
280+
/* Update available contexts if needed*/
281+
if ((contexts & *available) != *available) {
282+
*available = *available & contexts;
283+
err = k_work_reschedule(&available_contexts_work,
284+
PAC_NOTIFY_TIMEOUT);
285+
if (err < 0) {
286+
LOG_WRN("Update available contexts notify failed: %d", err);
287+
}
288+
}
289+
256290
return 0;
257291
}
258292

@@ -281,11 +315,22 @@ static inline int set_snk_available_contexts(uint16_t contexts)
281315
return set_available_contexts(contexts, &snk_available_contexts,
282316
snk_supported_contexts);
283317
}
318+
319+
static inline int set_snk_supported_contexts(uint16_t contexts)
320+
{
321+
return set_supported_contexts(contexts, &snk_supported_contexts,
322+
&snk_available_contexts);
323+
}
284324
#else
285325
static inline int set_snk_available_contexts(uint16_t contexts)
286326
{
287327
return -ENOTSUP;
288328
}
329+
330+
static inline int set_snk_supported_contexts(uint16_t contexts)
331+
{
332+
return -ENOTSUP;
333+
}
289334
#endif /* CONFIG_BT_PAC_SNK */
290335

291336
#if defined(CONFIG_BT_PAC_SNK_LOC)
@@ -385,11 +430,22 @@ static inline int set_src_available_contexts(uint16_t contexts)
385430
return set_available_contexts(contexts, &src_available_contexts,
386431
src_supported_contexts);
387432
}
433+
434+
static inline int set_src_supported_contexts(uint16_t contexts)
435+
{
436+
return set_supported_contexts(contexts, &src_supported_contexts,
437+
&snk_supported_contexts);
438+
}
388439
#else
389440
static inline int set_src_available_contexts(uint16_t contexts)
390441
{
391442
return -ENOTSUP;
392443
}
444+
445+
static inline int set_src_supported_contexts(uint16_t contexts)
446+
{
447+
return -ENOTSUP;
448+
}
393449
#endif /* CONFIG_BT_PAC_SRC */
394450

395451
#if defined(CONFIG_BT_PAC_SRC_LOC)
@@ -602,6 +658,21 @@ static void available_contexts_notify(struct k_work *work)
602658
}
603659
}
604660

661+
static void supported_contexts_notify(struct k_work *work)
662+
{
663+
struct bt_pacs_context context = {
664+
.snk = sys_cpu_to_le16(snk_supported_contexts),
665+
.src = sys_cpu_to_le16(src_supported_contexts),
666+
};
667+
int err;
668+
669+
err = bt_gatt_notify_uuid(NULL, BT_UUID_PACS_SUPPORTED_CONTEXT, pacs_svc.attrs,
670+
&context, sizeof(context));
671+
if (err != 0 && err != -ENOTCONN) {
672+
LOG_WRN("Supported Audio Contexts notify failed: %d", err);
673+
}
674+
}
675+
605676
bool bt_pacs_context_available(enum bt_audio_dir dir, uint16_t context)
606677
{
607678
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
722793
return -EINVAL;
723794
}
724795

796+
int bt_pacs_set_supported_contexts(enum bt_audio_dir dir, enum bt_audio_context contexts)
797+
{
798+
switch (dir) {
799+
case BT_AUDIO_DIR_SINK:
800+
return set_snk_supported_contexts(contexts);
801+
case BT_AUDIO_DIR_SOURCE:
802+
return set_src_supported_contexts(contexts);
803+
}
804+
805+
return -EINVAL;
806+
}
807+
725808
enum bt_audio_context bt_pacs_get_available_contexts(enum bt_audio_dir dir)
726809
{
727810
switch (dir) {

subsys/bluetooth/shell/audio.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,10 +1887,21 @@ static int cmd_context(const struct shell *sh, size_t argc, char *argv[])
18871887
return err;
18881888
}
18891889

1890-
err = bt_pacs_set_available_contexts(dir, ctx);
1891-
if (err) {
1892-
shell_error(ctx_shell, "Set available contexts err %d", err);
1893-
return err;
1890+
if (!strcmp(argv[3], "supported")) {
1891+
err = bt_pacs_set_supported_contexts(dir, ctx);
1892+
if (err) {
1893+
shell_error(ctx_shell, "Set supported contexts err %d", err);
1894+
return err;
1895+
}
1896+
} else if (!strcmp(argv[3], "available")) {
1897+
err = bt_pacs_set_available_contexts(dir, ctx);
1898+
if (err) {
1899+
shell_error(ctx_shell, "Set available contexts err %d", err);
1900+
return err;
1901+
}
1902+
} else {
1903+
shell_error(sh, "Unsupported context type: %s", argv[3]);
1904+
return -ENOEXEC;
18941905
}
18951906

18961907
return 0;
@@ -1924,6 +1935,10 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
19241935
err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, LOCATION);
19251936
__ASSERT(err == 0, "Failed to set sink location");
19261937

1938+
err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
1939+
CONTEXT);
1940+
__ASSERT(err == 0, "Failed to set sink supported contexts");
1941+
19271942
err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
19281943
CONTEXT);
19291944
__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[])
19331948
err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, LOCATION);
19341949
__ASSERT(err == 0, "Failed to set source location");
19351950

1951+
err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
1952+
CONTEXT);
1953+
__ASSERT(err == 0, "Failed to set sink supported contexts");
1954+
19361955
err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
19371956
CONTEXT);
19381957
__ASSERT(err == 0, "Failed to set source available contexts");
@@ -2084,9 +2103,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(audio_cmds,
20842103
SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_location, NULL,
20852104
"<direction: sink, source> <location bitmask>",
20862105
cmd_set_loc, 3, 0),
2087-
SHELL_COND_CMD_ARG(CONFIG_BT_PACS, add_context, NULL,
2088-
"<direction: sink, source> <context bitmask>",
2089-
cmd_context, 3, 0),
2106+
SHELL_COND_CMD_ARG(CONFIG_BT_PACS, set_context, NULL,
2107+
"<direction: sink, source>"
2108+
"<context bitmask> <type: supported, available>",
2109+
cmd_context, 4, 0),
20902110
SHELL_SUBCMD_SET_END
20912111
);
20922112

tests/bluetooth/bsim_bt/bsim_test_audio/src/unicast_server_test.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,14 @@ static void set_available_contexts(void)
296296
{
297297
int err;
298298

299+
err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK,
300+
BT_AUDIO_CONTEXT_TYPE_MEDIA |
301+
BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL);
302+
if (IS_ENABLED(CONFIG_BT_PAC_SNK) && err != 0) {
303+
FAIL("Failed to set sink supported contexts (err %d)\n", err);
304+
return;
305+
}
306+
299307
err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK,
300308
BT_AUDIO_CONTEXT_TYPE_MEDIA |
301309
BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL);
@@ -304,6 +312,13 @@ static void set_available_contexts(void)
304312
return;
305313
}
306314

315+
err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE,
316+
BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS);
317+
if (IS_ENABLED(CONFIG_BT_PAC_SRC) && err != 0) {
318+
FAIL("Failed to set source supported contexts (err %d)\n", err);
319+
return;
320+
}
321+
307322
err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE,
308323
BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS);
309324
if (IS_ENABLED(CONFIG_BT_PAC_SRC) && err != 0) {

0 commit comments

Comments
 (0)