1 /** @file
2  *  @brief Bluetooth Gaming Audio Profile shell
3  *
4  */
5 
6 /*
7  * Copyright (c) 2023 Nordic Semiconductor ASA
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <errno.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <string.h>
17 
18 #include <zephyr/autoconf.h>
19 #include <zephyr/bluetooth/audio/audio.h>
20 #include <zephyr/bluetooth/audio/gmap_lc3_preset.h>
21 #include <zephyr/bluetooth/audio/gmap.h>
22 #include <zephyr/bluetooth/bluetooth.h>
23 #include <zephyr/bluetooth/gap.h>
24 #include <zephyr/bluetooth/uuid.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/shell/shell.h>
27 #include <zephyr/sys/__assert.h>
28 #include <zephyr/sys/byteorder.h>
29 #include <zephyr/sys/util.h>
30 #include <zephyr/sys/util_macro.h>
31 
32 #include "shell/bt.h"
33 #include "audio.h"
34 
35 #define UNICAST_SINK_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0)
36 #define UNICAST_SRC_SUPPORTED  (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0)
37 
38 #define GMAP_AC_MAX_CONN   2U
39 #define GMAP_AC_MAX_SRC    (2U * GMAP_AC_MAX_CONN)
40 
41 static enum bt_gmap_role gmap_role;
42 
gmap_ad_data_add(struct bt_data data[],size_t data_size)43 size_t gmap_ad_data_add(struct bt_data data[], size_t data_size)
44 {
45 	static uint8_t ad_gmap[3] = {
46 		BT_UUID_16_ENCODE(BT_UUID_GMAS_VAL),
47 	};
48 
49 	if (gmap_role == 0) {
50 		/* Not initialized*/
51 
52 		return 0U;
53 	}
54 
55 	ad_gmap[2] = (uint8_t)gmap_role;
56 
57 	__ASSERT(data > 0, "No space for ad_gmap");
58 	data[0].type = BT_DATA_SVC_DATA16;
59 	data[0].data_len = ARRAY_SIZE(ad_gmap);
60 	data[0].data = &ad_gmap[0];
61 
62 	return 1U;
63 }
64 
gmap_discover_cb(struct bt_conn * conn,int err,enum bt_gmap_role role,struct bt_gmap_feat features)65 static void gmap_discover_cb(struct bt_conn *conn, int err, enum bt_gmap_role role,
66 			     struct bt_gmap_feat features)
67 {
68 	if (err != 0) {
69 		shell_error(ctx_shell, "gmap discovery (err %d)", err);
70 		return;
71 	}
72 
73 	shell_print(ctx_shell,
74 		    "gmap discovered for conn %p:\n\trole 0x%02x\n\tugg_feat 0x%02x\n\tugt_feat "
75 		    "0x%02x\n\tbgs_feat 0x%02x\n\tbgr_feat 0x%02x",
76 		    conn, role, features.ugg_feat, features.ugt_feat, features.bgs_feat,
77 		    features.bgr_feat);
78 }
79 
80 static const struct bt_gmap_cb gmap_cb = {
81 	.discover = gmap_discover_cb,
82 };
83 
set_gmap_features(struct bt_gmap_feat * features)84 static void set_gmap_features(struct bt_gmap_feat *features)
85 {
86 	memset(features, 0, sizeof(*features));
87 
88 	if (IS_ENABLED(CONFIG_BT_GMAP_UGG_SUPPORTED)) {
89 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
90 		features->ugg_feat |= (BT_GMAP_UGG_FEAT_MULTIPLEX | BT_GMAP_UGG_FEAT_96KBPS_SOURCE);
91 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1 &&                                              \
92 	CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT > 1
93 		features->ugg_feat |= BT_GMAP_UGG_FEAT_MULTISINK;
94 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1 && > 1 */
95 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
96 	}
97 
98 	if (IS_ENABLED(CONFIG_BT_GMAP_UGT_SUPPORTED)) {
99 #if CONFIG_BT_ASCS_ASE_SRC_COUNT > 0
100 		features->ugt_feat |= (BT_GMAP_UGT_FEAT_SOURCE | BT_GMAP_UGT_FEAT_80KBPS_SOURCE);
101 #if CONFIG_BT_ASCS_ASE_SRC_COUNT > 1
102 		features->ugt_feat |= BT_GMAP_UGT_FEAT_MULTISOURCE;
103 #endif /* CONFIG_BT_ASCS_ASE_SRC_COUNT > 1 */
104 #endif /* CONFIG_BT_ASCS_ASE_SRC_COUNT > 0 */
105 #if CONFIG_BT_ASCS_ASE_SNK_COUNT > 0
106 		features->ugt_feat |= (BT_GMAP_UGT_FEAT_SINK | BT_GMAP_UGT_FEAT_64KBPS_SINK);
107 #if CONFIG_BT_ASCS_ASE_SNK_COUNT > 1
108 		features->ugt_feat |= BT_GMAP_UGT_FEAT_MULTISINK;
109 #endif /* CONFIG_BT_ASCS_ASE_SNK_COUNT > 1 */
110 #endif /* CONFIG_BT_ASCS_ASE_SNK_COUNT > 0 */
111 	}
112 
113 	if (IS_ENABLED(CONFIG_BT_GMAP_BGS_SUPPORTED)) {
114 		features->bgs_feat |= BT_GMAP_BGS_FEAT_96KBPS;
115 	}
116 
117 	if (IS_ENABLED(CONFIG_BT_GMAP_BGR_SUPPORTED)) {
118 		features->bgr_feat |= BT_GMAP_BGR_FEAT_MULTISINK;
119 #if CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT > 1
120 		features->bgr_feat |= BT_GMAP_BGR_FEAT_MULTIPLEX;
121 #endif /* CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT > 1 */
122 	}
123 }
124 
cmd_gmap_init(const struct shell * sh,size_t argc,char ** argv)125 static int cmd_gmap_init(const struct shell *sh, size_t argc, char **argv)
126 {
127 	struct bt_gmap_feat features;
128 	int err;
129 
130 	gmap_role = (IS_ENABLED(CONFIG_BT_GMAP_UGG_SUPPORTED) ? BT_GMAP_ROLE_UGG : 0U) |
131 		    (IS_ENABLED(CONFIG_BT_GMAP_UGT_SUPPORTED) ? BT_GMAP_ROLE_UGT : 0U) |
132 		    (IS_ENABLED(CONFIG_BT_GMAP_BGS_SUPPORTED) ? BT_GMAP_ROLE_BGS : 0U) |
133 		    (IS_ENABLED(CONFIG_BT_GMAP_BGR_SUPPORTED) ? BT_GMAP_ROLE_BGR : 0U);
134 
135 	set_gmap_features(&features);
136 
137 	err = bt_gmap_register(gmap_role, features);
138 	if (err != 0) {
139 		shell_error(sh, "Failed to register GMAS (err %d)", err);
140 
141 		return -ENOEXEC;
142 	}
143 
144 	err = bt_gmap_cb_register(&gmap_cb);
145 	if (err != 0) {
146 		shell_error(sh, "Failed to register callbacks (err %d)", err);
147 
148 		return -ENOEXEC;
149 	}
150 
151 	return 0;
152 }
153 
cmd_gmap_set_role(const struct shell * sh,size_t argc,char ** argv)154 static int cmd_gmap_set_role(const struct shell *sh, size_t argc, char **argv)
155 {
156 	enum bt_gmap_role role = 0;
157 	struct bt_gmap_feat features;
158 	int err;
159 
160 	for (size_t i = 1U; i < argc; i++) {
161 		const char *arg = argv[i];
162 
163 		if (strcmp(arg, "ugg") == 0) {
164 			role |= BT_GMAP_ROLE_UGG;
165 		} else if (strcmp(arg, "ugt") == 0) {
166 			role |= BT_GMAP_ROLE_UGT;
167 		} else if (strcmp(arg, "bgs") == 0) {
168 			role |= BT_GMAP_ROLE_BGS;
169 		} else if (strcmp(arg, "bgr") == 0) {
170 			role |= BT_GMAP_ROLE_BGR;
171 		} else {
172 			shell_error(sh, "Invalid arg: %s", arg);
173 			shell_help(sh);
174 
175 			return SHELL_CMD_HELP_PRINTED;
176 		}
177 	}
178 
179 	set_gmap_features(&features);
180 
181 	err = bt_gmap_set_role(role, features);
182 	if (err != 0) {
183 		shell_error(sh, "Failed to set new role (err %d)", err);
184 
185 		return -ENOEXEC;
186 	}
187 
188 	gmap_role = role;
189 
190 	return 0;
191 }
192 
cmd_gmap_discover(const struct shell * sh,size_t argc,char ** argv)193 static int cmd_gmap_discover(const struct shell *sh, size_t argc, char **argv)
194 {
195 	int err;
196 
197 	if (default_conn == NULL) {
198 		shell_error(sh, "Not connected");
199 		return -ENOEXEC;
200 	}
201 
202 	if (!ctx_shell) {
203 		ctx_shell = sh;
204 	}
205 
206 	err = bt_gmap_discover(default_conn);
207 	if (err != 0) {
208 		shell_error(sh, "bt_gmap_discover (err %d)", err);
209 	}
210 
211 	return err;
212 }
213 
214 static struct named_lc3_preset gmap_unicast_snk_presets[] = {
215 	{"32_1_gr", BT_GMAP_LC3_PRESET_32_1_GR(LOCATION, CONTEXT)},
216 	{"32_2_gr", BT_GMAP_LC3_PRESET_32_2_GR(LOCATION, CONTEXT)},
217 	{"48_1_gr", BT_GMAP_LC3_PRESET_48_1_GR(LOCATION, CONTEXT)},
218 	{"48_2_gr", BT_GMAP_LC3_PRESET_48_2_GR(LOCATION, CONTEXT)},
219 	{"48_3_gr", BT_GMAP_LC3_PRESET_48_3_GR(LOCATION, CONTEXT)},
220 	{"48_4_gr", BT_GMAP_LC3_PRESET_48_4_GR(LOCATION, CONTEXT)},
221 };
222 
223 static struct named_lc3_preset gmap_unicast_src_presets[] = {
224 	{"16_1_gs", BT_GMAP_LC3_PRESET_16_1_GS(LOCATION, CONTEXT)},
225 	{"16_2_gs", BT_GMAP_LC3_PRESET_16_2_GS(LOCATION, CONTEXT)},
226 	{"32_1_gs", BT_GMAP_LC3_PRESET_32_1_GS(LOCATION, CONTEXT)},
227 	{"32_2_gs", BT_GMAP_LC3_PRESET_32_2_GS(LOCATION, CONTEXT)},
228 	{"48_1_gs", BT_GMAP_LC3_PRESET_48_1_GS(LOCATION, CONTEXT)},
229 	{"48_2_gs", BT_GMAP_LC3_PRESET_48_2_GS(LOCATION, CONTEXT)},
230 };
231 
232 static struct named_lc3_preset gmap_broadcast_presets[] = {
233 	{"48_1_g", BT_GMAP_LC3_PRESET_48_1_G(LOCATION, CONTEXT)},
234 	{"48_2_g", BT_GMAP_LC3_PRESET_48_2_G(LOCATION, CONTEXT)},
235 	{"48_3_g", BT_GMAP_LC3_PRESET_48_3_G(LOCATION, CONTEXT)},
236 	{"48_4_g", BT_GMAP_LC3_PRESET_48_4_G(LOCATION, CONTEXT)},
237 };
238 
gmap_get_named_preset(bool is_unicast,enum bt_audio_dir dir,const char * preset_arg)239 const struct named_lc3_preset *gmap_get_named_preset(bool is_unicast, enum bt_audio_dir dir,
240 						     const char *preset_arg)
241 {
242 	if (is_unicast) {
243 		if (dir == BT_AUDIO_DIR_SINK) {
244 			for (size_t i = 0U; i < ARRAY_SIZE(gmap_unicast_snk_presets); i++) {
245 				if (!strcmp(preset_arg, gmap_unicast_snk_presets[i].name)) {
246 					return &gmap_unicast_snk_presets[i];
247 				}
248 			}
249 		} else if (dir == BT_AUDIO_DIR_SOURCE) {
250 			for (size_t i = 0U; i < ARRAY_SIZE(gmap_unicast_src_presets); i++) {
251 				if (!strcmp(preset_arg, gmap_unicast_src_presets[i].name)) {
252 					return &gmap_unicast_src_presets[i];
253 				}
254 			}
255 		}
256 	} else {
257 		for (size_t i = 0U; i < ARRAY_SIZE(gmap_broadcast_presets); i++) {
258 			if (!strcmp(preset_arg, gmap_broadcast_presets[i].name)) {
259 				return &gmap_broadcast_presets[i];
260 			}
261 		}
262 	}
263 
264 	return NULL;
265 }
266 
267 #if defined(CONFIG_BT_GMAP_UGG_SUPPORTED)
268 #if UNICAST_SINK_SUPPORTED
cmd_gmap_ac_1(const struct shell * sh,size_t argc,char ** argv)269 static int cmd_gmap_ac_1(const struct shell *sh, size_t argc, char **argv)
270 {
271 	const struct bap_unicast_ac_param param = {
272 		.name = "AC_1",
273 		.conn_cnt = 1,
274 		.snk_cnt = {1U},
275 		.src_cnt = {0U},
276 		.snk_chan_cnt = 1U,
277 		.src_chan_cnt = 0U,
278 	};
279 
280 	return cap_ac_unicast(sh, &param);
281 }
282 #endif /* UNICAST_SINK_SUPPORTED */
283 
284 #if UNICAST_SRC_SUPPORTED
cmd_gmap_ac_2(const struct shell * sh,size_t argc,char ** argv)285 static int cmd_gmap_ac_2(const struct shell *sh, size_t argc, char **argv)
286 {
287 	const struct bap_unicast_ac_param param = {
288 		.name = "AC_2",
289 		.conn_cnt = 1,
290 		.snk_cnt = {0U},
291 		.src_cnt = {1U},
292 		.snk_chan_cnt = 0U,
293 		.src_chan_cnt = 1U,
294 	};
295 
296 	return cap_ac_unicast(sh, &param);
297 }
298 #endif /* UNICAST_SRC_SUPPORTED */
299 
300 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
cmd_gmap_ac_3(const struct shell * sh,size_t argc,char ** argv)301 static int cmd_gmap_ac_3(const struct shell *sh, size_t argc, char **argv)
302 {
303 	const struct bap_unicast_ac_param param = {
304 		.name = "AC_3",
305 		.conn_cnt = 1U,
306 		.snk_cnt = {1U},
307 		.src_cnt = {1U},
308 		.snk_chan_cnt = 1U,
309 		.src_chan_cnt = 1U,
310 	};
311 
312 	return cap_ac_unicast(sh, &param);
313 }
314 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
315 
316 #if UNICAST_SINK_SUPPORTED
cmd_gmap_ac_4(const struct shell * sh,size_t argc,char ** argv)317 static int cmd_gmap_ac_4(const struct shell *sh, size_t argc, char **argv)
318 {
319 	const struct bap_unicast_ac_param param = {
320 		.name = "AC_4",
321 		.conn_cnt = 1U,
322 		.snk_cnt = {1U},
323 		.src_cnt = {0U},
324 		.snk_chan_cnt = 2U,
325 		.src_chan_cnt = 0U,
326 	};
327 
328 	return cap_ac_unicast(sh, &param);
329 }
330 #endif /* UNICAST_SINK_SUPPORTED */
331 
332 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
cmd_gmap_ac_5(const struct shell * sh,size_t argc,char ** argv)333 static int cmd_gmap_ac_5(const struct shell *sh, size_t argc, char **argv)
334 {
335 	const struct bap_unicast_ac_param param = {
336 		.name = "AC_5",
337 		.conn_cnt = 1U,
338 		.snk_cnt = {1U},
339 		.src_cnt = {1U},
340 		.snk_chan_cnt = 2U,
341 		.src_chan_cnt = 1U,
342 	};
343 
344 	return cap_ac_unicast(sh, &param);
345 }
346 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
347 
348 #if UNICAST_SINK_SUPPORTED
349 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
cmd_gmap_ac_6_i(const struct shell * sh,size_t argc,char ** argv)350 static int cmd_gmap_ac_6_i(const struct shell *sh, size_t argc, char **argv)
351 {
352 	const struct bap_unicast_ac_param param = {
353 		.name = "AC_6_I",
354 		.conn_cnt = 1U,
355 		.snk_cnt = {2U},
356 		.src_cnt = {0U},
357 		.snk_chan_cnt = 1U,
358 		.src_chan_cnt = 0U,
359 	};
360 
361 	return cap_ac_unicast(sh, &param);
362 }
363 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
364 
365 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_6_ii(const struct shell * sh,size_t argc,char ** argv)366 static int cmd_gmap_ac_6_ii(const struct shell *sh, size_t argc, char **argv)
367 {
368 	const struct bap_unicast_ac_param param = {
369 		.name = "AC_6_II",
370 		.conn_cnt = 2,
371 		.snk_cnt = {1U, 1U},
372 		.src_cnt = {0U, 0U},
373 		.snk_chan_cnt = 1U,
374 		.src_chan_cnt = 0U,
375 	};
376 
377 	return cap_ac_unicast(sh, &param);
378 }
379 #endif /* CONFIG_BT_MAX_CONN >= 2 */
380 #endif /* UNICAST_SINK_SUPPORTED */
381 
382 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
383 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_7_ii(const struct shell * sh,size_t argc,char ** argv)384 static int cmd_gmap_ac_7_ii(const struct shell *sh, size_t argc, char **argv)
385 {
386 	const struct bap_unicast_ac_param param = {
387 		.name = "AC_7_II",
388 		.conn_cnt = 2,
389 		.snk_cnt = {1U, 0U},
390 		.src_cnt = {0U, 1U},
391 		.snk_chan_cnt = 1U,
392 		.src_chan_cnt = 1U,
393 	};
394 
395 	return cap_ac_unicast(sh, &param);
396 }
397 #endif /* CONFIG_BT_MAX_CONN >= 2 */
398 
399 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
cmd_gmap_ac_8_i(const struct shell * sh,size_t argc,char ** argv)400 static int cmd_gmap_ac_8_i(const struct shell *sh, size_t argc, char **argv)
401 {
402 	const struct bap_unicast_ac_param param = {
403 		.name = "AC_8_I",
404 		.conn_cnt = 1U,
405 		.snk_cnt = {2U},
406 		.src_cnt = {1U},
407 		.snk_chan_cnt = 1U,
408 		.src_chan_cnt = 1U,
409 	};
410 
411 	return cap_ac_unicast(sh, &param);
412 }
413 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
414 
415 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_8_ii(const struct shell * sh,size_t argc,char ** argv)416 static int cmd_gmap_ac_8_ii(const struct shell *sh, size_t argc, char **argv)
417 {
418 	const struct bap_unicast_ac_param param = {
419 		.name = "AC_8_II",
420 		.conn_cnt = 2U,
421 		.snk_cnt = {1U, 1U},
422 		.src_cnt = {1U, 0U},
423 		.snk_chan_cnt = 1U,
424 		.src_chan_cnt = 1U,
425 	};
426 
427 	return cap_ac_unicast(sh, &param);
428 }
429 #endif /* CONFIG_BT_MAX_CONN >= 2 */
430 
431 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 && CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1
cmd_gmap_ac_11_i(const struct shell * sh,size_t argc,char ** argv)432 static int cmd_gmap_ac_11_i(const struct shell *sh, size_t argc, char **argv)
433 {
434 	const struct bap_unicast_ac_param param = {
435 		.name = "AC_11_I",
436 		.conn_cnt = 1U,
437 		.snk_cnt = {2U},
438 		.src_cnt = {2U},
439 		.snk_chan_cnt = 1U,
440 		.src_chan_cnt = 1U,
441 	};
442 
443 	return cap_ac_unicast(sh, &param);
444 }
445 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 &&                                        \
446 	* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1                                           \
447 	*/
448 
449 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_11_ii(const struct shell * sh,size_t argc,char ** argv)450 static int cmd_gmap_ac_11_ii(const struct shell *sh, size_t argc, char **argv)
451 {
452 	const struct bap_unicast_ac_param param = {
453 		.name = "AC_11_II",
454 		.conn_cnt = 2U,
455 		.snk_cnt = {1U, 1U},
456 		.src_cnt = {1U, 1U},
457 		.snk_chan_cnt = 1U,
458 		.src_chan_cnt = 1U,
459 	};
460 
461 	return cap_ac_unicast(sh, &param);
462 }
463 #endif /* CONFIG_BT_MAX_CONN >= 2 */
464 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
465 #endif /* CONFIG_BT_GMAP_UGG_SUPPORTED */
466 
467 #if defined(CONFIG_BT_GMAP_BGS_SUPPORTED)
cmd_gmap_ac_12(const struct shell * sh,size_t argc,char ** argv)468 static int cmd_gmap_ac_12(const struct shell *sh, size_t argc, char **argv)
469 {
470 	const struct bap_broadcast_ac_param param = {
471 		.name = "AC_12",
472 		.stream_cnt = 1U,
473 		.chan_cnt = 1U,
474 	};
475 
476 	return cap_ac_broadcast(sh, argc, argv, &param);
477 }
478 
479 #if CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1
cmd_gmap_ac_13(const struct shell * sh,size_t argc,char ** argv)480 static int cmd_gmap_ac_13(const struct shell *sh, size_t argc, char **argv)
481 {
482 	const struct bap_broadcast_ac_param param = {
483 		.name = "AC_13",
484 		.stream_cnt = 2U,
485 		.chan_cnt = 1U,
486 	};
487 
488 	return cap_ac_broadcast(sh, argc, argv, &param);
489 }
490 #endif /* CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1 */
491 
cmd_gmap_ac_14(const struct shell * sh,size_t argc,char ** argv)492 static int cmd_gmap_ac_14(const struct shell *sh, size_t argc, char **argv)
493 {
494 	const struct bap_broadcast_ac_param param = {
495 		.name = "AC_14",
496 		.stream_cnt = 1U,
497 		.chan_cnt = 2U,
498 	};
499 
500 	return cap_ac_broadcast(sh, argc, argv, &param);
501 }
502 #endif /* CONFIG_BT_GMAP_BGS_SUPPORTED */
503 
cmd_gmap(const struct shell * sh,size_t argc,char ** argv)504 static int cmd_gmap(const struct shell *sh, size_t argc, char **argv)
505 {
506 	if (argc > 1) {
507 		shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
508 	} else {
509 		shell_error(sh, "%s missing subcomand", argv[0]);
510 	}
511 
512 	return -ENOEXEC;
513 }
514 
515 #define HELP_NONE "[none]"
516 
517 SHELL_STATIC_SUBCMD_SET_CREATE(
518 	gmap_cmds, SHELL_CMD_ARG(init, NULL, HELP_NONE, cmd_gmap_init, 1, 0),
519 	SHELL_CMD_ARG(set_role, NULL, "[ugt | ugg | bgr | bgs]", cmd_gmap_set_role, 2, 3),
520 	SHELL_CMD_ARG(discover, NULL, HELP_NONE, cmd_gmap_discover, 1, 0),
521 #if defined(CONFIG_BT_GMAP_UGG_SUPPORTED)
522 #if UNICAST_SINK_SUPPORTED
523 	SHELL_CMD_ARG(ac_1, NULL, "Unicast audio configuration 1", cmd_gmap_ac_1, 1, 0),
524 #endif /* UNICAST_SINK_SUPPORTED */
525 #if UNICAST_SRC_SUPPORTED
526 	SHELL_CMD_ARG(ac_2, NULL, "Unicast audio configuration 2", cmd_gmap_ac_2, 1, 0),
527 #endif /* UNICAST_SRC_SUPPORTED */
528 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
529 	SHELL_CMD_ARG(ac_3, NULL, "Unicast audio configuration 3", cmd_gmap_ac_3, 1, 0),
530 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
531 #if UNICAST_SINK_SUPPORTED
532 	SHELL_CMD_ARG(ac_4, NULL, "Unicast audio configuration 4", cmd_gmap_ac_4, 1, 0),
533 #endif /* UNICAST_SINK_SUPPORTED */
534 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
535 	SHELL_CMD_ARG(ac_5, NULL, "Unicast audio configuration 5", cmd_gmap_ac_5, 1, 0),
536 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
537 #if UNICAST_SINK_SUPPORTED
538 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
539 	SHELL_CMD_ARG(ac_6_i, NULL, "Unicast audio configuration 6(i)", cmd_gmap_ac_6_i, 1, 0),
540 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
541 #if CONFIG_BT_MAX_CONN >= 2
542 	SHELL_CMD_ARG(ac_6_ii, NULL, "Unicast audio configuration 6(ii)", cmd_gmap_ac_6_ii, 1, 0),
543 #endif /* CONFIG_BT_MAX_CONN >= 2 */
544 #endif /* UNICAST_SINK_SUPPORTED */
545 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
546 #if CONFIG_BT_MAX_CONN >= 2
547 	SHELL_CMD_ARG(ac_7_ii, NULL, "Unicast audio configuration 7(ii)", cmd_gmap_ac_7_ii, 1, 0),
548 #endif /* CONFIG_BT_MAX_CONN >= 2 */
549 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
550 	SHELL_CMD_ARG(ac_8_i, NULL, "Unicast audio configuration 8(i)", cmd_gmap_ac_8_i, 1, 0),
551 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
552 #if CONFIG_BT_MAX_CONN >= 2
553 	SHELL_CMD_ARG(ac_8_ii, NULL, "Unicast audio configuration 8(ii)", cmd_gmap_ac_8_ii, 1, 0),
554 #endif /* CONFIG_BT_MAX_CONN >= 2 */
555 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 && CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1
556 	SHELL_CMD_ARG(ac_11_i, NULL, "Unicast audio configuration 11(i)", cmd_gmap_ac_11_i, 1, 0),
557 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 &&                                        \
558 	* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1                                           \
559 	*/
560 #if CONFIG_BT_MAX_CONN >= 2
561 	SHELL_CMD_ARG(ac_11_ii, NULL, "Unicast audio configuration 11(ii)", cmd_gmap_ac_11_ii, 1,
562 		      0),
563 #endif /* CONFIG_BT_MAX_CONN >= 2 */
564 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
565 #endif /* CONFIG_BT_GMAP_UGG_SUPPORTED */
566 
567 #if defined(CONFIG_BT_GMAP_BGS_SUPPORTED)
568 	SHELL_CMD_ARG(ac_12, NULL, "Broadcast audio configuration 12", cmd_gmap_ac_12, 1, 0),
569 #if CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1
570 	SHELL_CMD_ARG(ac_13, NULL, "Broadcast audio configuration 13", cmd_gmap_ac_13, 1, 0),
571 #endif /* CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1 */
572 	SHELL_CMD_ARG(ac_14, NULL, "Broadcast audio configuration 14", cmd_gmap_ac_14, 1, 0),
573 #endif /* CONFIG_BT_GMAP_BGS_SUPPORTED*/
574 	SHELL_SUBCMD_SET_END);
575 
576 SHELL_CMD_ARG_REGISTER(gmap, &gmap_cmds, "Bluetooth GMAP shell commands", cmd_gmap, 1, 1);
577