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 "common/bt_shell_private.h"
33 #include "host/shell/bt.h"
34 #include "audio.h"
35 
36 #define UNICAST_SINK_SUPPORTED (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0)
37 #define UNICAST_SRC_SUPPORTED  (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0)
38 
39 #define GMAP_AC_MAX_CONN   2U
40 #define GMAP_AC_MAX_SRC    (2U * GMAP_AC_MAX_CONN)
41 
42 static enum bt_gmap_role gmap_role;
43 
gmap_ad_data_add(struct bt_data data[],size_t data_size)44 size_t gmap_ad_data_add(struct bt_data data[], size_t data_size)
45 {
46 	static uint8_t ad_gmap[3] = {
47 		BT_UUID_16_ENCODE(BT_UUID_GMAS_VAL),
48 	};
49 
50 	if (gmap_role == 0) {
51 		/* Not initialized*/
52 
53 		return 0U;
54 	}
55 
56 	ad_gmap[2] = (uint8_t)gmap_role;
57 
58 	__ASSERT(data > 0, "No space for ad_gmap");
59 	data[0].type = BT_DATA_SVC_DATA16;
60 	data[0].data_len = ARRAY_SIZE(ad_gmap);
61 	data[0].data = &ad_gmap[0];
62 
63 	return 1U;
64 }
65 
gmap_discover_cb(struct bt_conn * conn,int err,enum bt_gmap_role role,struct bt_gmap_feat features)66 static void gmap_discover_cb(struct bt_conn *conn, int err, enum bt_gmap_role role,
67 			     struct bt_gmap_feat features)
68 {
69 	if (err != 0) {
70 		bt_shell_error("gmap discovery (err %d)", err);
71 		return;
72 	}
73 
74 	bt_shell_print("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_MAX_ASE_SRC_COUNT > 0
100 		features->ugt_feat |= (BT_GMAP_UGT_FEAT_SOURCE | BT_GMAP_UGT_FEAT_80KBPS_SOURCE);
101 #if CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 1
102 		features->ugt_feat |= BT_GMAP_UGT_FEAT_MULTISOURCE;
103 #endif /* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 1 */
104 #endif /* CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0 */
105 #if CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0
106 		features->ugt_feat |= (BT_GMAP_UGT_FEAT_SINK | BT_GMAP_UGT_FEAT_64KBPS_SINK);
107 #if CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 1
108 		features->ugt_feat |= BT_GMAP_UGT_FEAT_MULTISINK;
109 #endif /* CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 1 */
110 #endif /* CONFIG_BT_ASCS_MAX_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 	err = bt_gmap_discover(default_conn);
203 	if (err != 0) {
204 		shell_error(sh, "bt_gmap_discover (err %d)", err);
205 	}
206 
207 	return err;
208 }
209 
210 static struct named_lc3_preset gmap_unicast_snk_presets[] = {
211 	{"32_1_gr", BT_GMAP_LC3_PRESET_32_1_GR(LOCATION, CONTEXT)},
212 	{"32_2_gr", BT_GMAP_LC3_PRESET_32_2_GR(LOCATION, CONTEXT)},
213 	{"48_1_gr", BT_GMAP_LC3_PRESET_48_1_GR(LOCATION, CONTEXT)},
214 	{"48_2_gr", BT_GMAP_LC3_PRESET_48_2_GR(LOCATION, CONTEXT)},
215 	{"48_3_gr", BT_GMAP_LC3_PRESET_48_3_GR(LOCATION, CONTEXT)},
216 	{"48_4_gr", BT_GMAP_LC3_PRESET_48_4_GR(LOCATION, CONTEXT)},
217 };
218 
219 static struct named_lc3_preset gmap_unicast_src_presets[] = {
220 	{"16_1_gs", BT_GMAP_LC3_PRESET_16_1_GS(LOCATION, CONTEXT)},
221 	{"16_2_gs", BT_GMAP_LC3_PRESET_16_2_GS(LOCATION, CONTEXT)},
222 	{"32_1_gs", BT_GMAP_LC3_PRESET_32_1_GS(LOCATION, CONTEXT)},
223 	{"32_2_gs", BT_GMAP_LC3_PRESET_32_2_GS(LOCATION, CONTEXT)},
224 	{"48_1_gs", BT_GMAP_LC3_PRESET_48_1_GS(LOCATION, CONTEXT)},
225 	{"48_2_gs", BT_GMAP_LC3_PRESET_48_2_GS(LOCATION, CONTEXT)},
226 };
227 
228 static struct named_lc3_preset gmap_broadcast_presets[] = {
229 	{"48_1_g", BT_GMAP_LC3_PRESET_48_1_G(LOCATION, CONTEXT)},
230 	{"48_2_g", BT_GMAP_LC3_PRESET_48_2_G(LOCATION, CONTEXT)},
231 	{"48_3_g", BT_GMAP_LC3_PRESET_48_3_G(LOCATION, CONTEXT)},
232 	{"48_4_g", BT_GMAP_LC3_PRESET_48_4_G(LOCATION, CONTEXT)},
233 };
234 
gmap_get_named_preset(bool is_unicast,enum bt_audio_dir dir,const char * preset_arg)235 const struct named_lc3_preset *gmap_get_named_preset(bool is_unicast, enum bt_audio_dir dir,
236 						     const char *preset_arg)
237 {
238 	if (is_unicast) {
239 		if (dir == BT_AUDIO_DIR_SINK) {
240 			for (size_t i = 0U; i < ARRAY_SIZE(gmap_unicast_snk_presets); i++) {
241 				if (!strcmp(preset_arg, gmap_unicast_snk_presets[i].name)) {
242 					return &gmap_unicast_snk_presets[i];
243 				}
244 			}
245 		} else if (dir == BT_AUDIO_DIR_SOURCE) {
246 			for (size_t i = 0U; i < ARRAY_SIZE(gmap_unicast_src_presets); i++) {
247 				if (!strcmp(preset_arg, gmap_unicast_src_presets[i].name)) {
248 					return &gmap_unicast_src_presets[i];
249 				}
250 			}
251 		}
252 	} else {
253 		for (size_t i = 0U; i < ARRAY_SIZE(gmap_broadcast_presets); i++) {
254 			if (!strcmp(preset_arg, gmap_broadcast_presets[i].name)) {
255 				return &gmap_broadcast_presets[i];
256 			}
257 		}
258 	}
259 
260 	return NULL;
261 }
262 
263 #if defined(CONFIG_BT_GMAP_UGG_SUPPORTED)
264 #if UNICAST_SINK_SUPPORTED
cmd_gmap_ac_1(const struct shell * sh,size_t argc,char ** argv)265 static int cmd_gmap_ac_1(const struct shell *sh, size_t argc, char **argv)
266 {
267 	const struct bap_unicast_ac_param param = {
268 		.name = "AC_1",
269 		.conn_cnt = 1,
270 		.snk_cnt = {1U},
271 		.src_cnt = {0U},
272 		.snk_chan_cnt = 1U,
273 		.src_chan_cnt = 0U,
274 	};
275 
276 	return cap_ac_unicast(sh, &param);
277 }
278 #endif /* UNICAST_SINK_SUPPORTED */
279 
280 #if UNICAST_SRC_SUPPORTED
cmd_gmap_ac_2(const struct shell * sh,size_t argc,char ** argv)281 static int cmd_gmap_ac_2(const struct shell *sh, size_t argc, char **argv)
282 {
283 	const struct bap_unicast_ac_param param = {
284 		.name = "AC_2",
285 		.conn_cnt = 1,
286 		.snk_cnt = {0U},
287 		.src_cnt = {1U},
288 		.snk_chan_cnt = 0U,
289 		.src_chan_cnt = 1U,
290 	};
291 
292 	return cap_ac_unicast(sh, &param);
293 }
294 #endif /* UNICAST_SRC_SUPPORTED */
295 
296 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
cmd_gmap_ac_3(const struct shell * sh,size_t argc,char ** argv)297 static int cmd_gmap_ac_3(const struct shell *sh, size_t argc, char **argv)
298 {
299 	const struct bap_unicast_ac_param param = {
300 		.name = "AC_3",
301 		.conn_cnt = 1U,
302 		.snk_cnt = {1U},
303 		.src_cnt = {1U},
304 		.snk_chan_cnt = 1U,
305 		.src_chan_cnt = 1U,
306 	};
307 
308 	return cap_ac_unicast(sh, &param);
309 }
310 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
311 
312 #if UNICAST_SINK_SUPPORTED
cmd_gmap_ac_4(const struct shell * sh,size_t argc,char ** argv)313 static int cmd_gmap_ac_4(const struct shell *sh, size_t argc, char **argv)
314 {
315 	const struct bap_unicast_ac_param param = {
316 		.name = "AC_4",
317 		.conn_cnt = 1U,
318 		.snk_cnt = {1U},
319 		.src_cnt = {0U},
320 		.snk_chan_cnt = 2U,
321 		.src_chan_cnt = 0U,
322 	};
323 
324 	return cap_ac_unicast(sh, &param);
325 }
326 #endif /* UNICAST_SINK_SUPPORTED */
327 
328 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
cmd_gmap_ac_5(const struct shell * sh,size_t argc,char ** argv)329 static int cmd_gmap_ac_5(const struct shell *sh, size_t argc, char **argv)
330 {
331 	const struct bap_unicast_ac_param param = {
332 		.name = "AC_5",
333 		.conn_cnt = 1U,
334 		.snk_cnt = {1U},
335 		.src_cnt = {1U},
336 		.snk_chan_cnt = 2U,
337 		.src_chan_cnt = 1U,
338 	};
339 
340 	return cap_ac_unicast(sh, &param);
341 }
342 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
343 
344 #if UNICAST_SINK_SUPPORTED
345 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
cmd_gmap_ac_6_i(const struct shell * sh,size_t argc,char ** argv)346 static int cmd_gmap_ac_6_i(const struct shell *sh, size_t argc, char **argv)
347 {
348 	const struct bap_unicast_ac_param param = {
349 		.name = "AC_6_I",
350 		.conn_cnt = 1U,
351 		.snk_cnt = {2U},
352 		.src_cnt = {0U},
353 		.snk_chan_cnt = 1U,
354 		.src_chan_cnt = 0U,
355 	};
356 
357 	return cap_ac_unicast(sh, &param);
358 }
359 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
360 
361 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_6_ii(const struct shell * sh,size_t argc,char ** argv)362 static int cmd_gmap_ac_6_ii(const struct shell *sh, size_t argc, char **argv)
363 {
364 	const struct bap_unicast_ac_param param = {
365 		.name = "AC_6_II",
366 		.conn_cnt = 2,
367 		.snk_cnt = {1U, 1U},
368 		.src_cnt = {0U, 0U},
369 		.snk_chan_cnt = 1U,
370 		.src_chan_cnt = 0U,
371 	};
372 
373 	return cap_ac_unicast(sh, &param);
374 }
375 #endif /* CONFIG_BT_MAX_CONN >= 2 */
376 #endif /* UNICAST_SINK_SUPPORTED */
377 
378 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
379 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_7_ii(const struct shell * sh,size_t argc,char ** argv)380 static int cmd_gmap_ac_7_ii(const struct shell *sh, size_t argc, char **argv)
381 {
382 	const struct bap_unicast_ac_param param = {
383 		.name = "AC_7_II",
384 		.conn_cnt = 2,
385 		.snk_cnt = {1U, 0U},
386 		.src_cnt = {0U, 1U},
387 		.snk_chan_cnt = 1U,
388 		.src_chan_cnt = 1U,
389 	};
390 
391 	return cap_ac_unicast(sh, &param);
392 }
393 #endif /* CONFIG_BT_MAX_CONN >= 2 */
394 
395 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
cmd_gmap_ac_8_i(const struct shell * sh,size_t argc,char ** argv)396 static int cmd_gmap_ac_8_i(const struct shell *sh, size_t argc, char **argv)
397 {
398 	const struct bap_unicast_ac_param param = {
399 		.name = "AC_8_I",
400 		.conn_cnt = 1U,
401 		.snk_cnt = {2U},
402 		.src_cnt = {1U},
403 		.snk_chan_cnt = 1U,
404 		.src_chan_cnt = 1U,
405 	};
406 
407 	return cap_ac_unicast(sh, &param);
408 }
409 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
410 
411 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_8_ii(const struct shell * sh,size_t argc,char ** argv)412 static int cmd_gmap_ac_8_ii(const struct shell *sh, size_t argc, char **argv)
413 {
414 	const struct bap_unicast_ac_param param = {
415 		.name = "AC_8_II",
416 		.conn_cnt = 2U,
417 		.snk_cnt = {1U, 1U},
418 		.src_cnt = {1U, 0U},
419 		.snk_chan_cnt = 1U,
420 		.src_chan_cnt = 1U,
421 	};
422 
423 	return cap_ac_unicast(sh, &param);
424 }
425 #endif /* CONFIG_BT_MAX_CONN >= 2 */
426 
427 #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)428 static int cmd_gmap_ac_11_i(const struct shell *sh, size_t argc, char **argv)
429 {
430 	const struct bap_unicast_ac_param param = {
431 		.name = "AC_11_I",
432 		.conn_cnt = 1U,
433 		.snk_cnt = {2U},
434 		.src_cnt = {2U},
435 		.snk_chan_cnt = 1U,
436 		.src_chan_cnt = 1U,
437 	};
438 
439 	return cap_ac_unicast(sh, &param);
440 }
441 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 &&                                        \
442 	* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1                                           \
443 	*/
444 
445 #if CONFIG_BT_MAX_CONN >= 2
cmd_gmap_ac_11_ii(const struct shell * sh,size_t argc,char ** argv)446 static int cmd_gmap_ac_11_ii(const struct shell *sh, size_t argc, char **argv)
447 {
448 	const struct bap_unicast_ac_param param = {
449 		.name = "AC_11_II",
450 		.conn_cnt = 2U,
451 		.snk_cnt = {1U, 1U},
452 		.src_cnt = {1U, 1U},
453 		.snk_chan_cnt = 1U,
454 		.src_chan_cnt = 1U,
455 	};
456 
457 	return cap_ac_unicast(sh, &param);
458 }
459 #endif /* CONFIG_BT_MAX_CONN >= 2 */
460 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
461 #endif /* CONFIG_BT_GMAP_UGG_SUPPORTED */
462 
463 #if defined(CONFIG_BT_GMAP_BGS_SUPPORTED)
cmd_gmap_ac_12(const struct shell * sh,size_t argc,char ** argv)464 static int cmd_gmap_ac_12(const struct shell *sh, size_t argc, char **argv)
465 {
466 	const struct bap_broadcast_ac_param param = {
467 		.name = "AC_12",
468 		.stream_cnt = 1U,
469 		.chan_cnt = 1U,
470 	};
471 
472 	return cap_ac_broadcast(sh, argc, argv, &param);
473 }
474 
475 #if CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1
cmd_gmap_ac_13(const struct shell * sh,size_t argc,char ** argv)476 static int cmd_gmap_ac_13(const struct shell *sh, size_t argc, char **argv)
477 {
478 	const struct bap_broadcast_ac_param param = {
479 		.name = "AC_13",
480 		.stream_cnt = 2U,
481 		.chan_cnt = 1U,
482 	};
483 
484 	return cap_ac_broadcast(sh, argc, argv, &param);
485 }
486 #endif /* CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1 */
487 
cmd_gmap_ac_14(const struct shell * sh,size_t argc,char ** argv)488 static int cmd_gmap_ac_14(const struct shell *sh, size_t argc, char **argv)
489 {
490 	const struct bap_broadcast_ac_param param = {
491 		.name = "AC_14",
492 		.stream_cnt = 1U,
493 		.chan_cnt = 2U,
494 	};
495 
496 	return cap_ac_broadcast(sh, argc, argv, &param);
497 }
498 #endif /* CONFIG_BT_GMAP_BGS_SUPPORTED */
499 
cmd_gmap(const struct shell * sh,size_t argc,char ** argv)500 static int cmd_gmap(const struct shell *sh, size_t argc, char **argv)
501 {
502 	if (argc > 1) {
503 		shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
504 	} else {
505 		shell_error(sh, "%s missing subcomand", argv[0]);
506 	}
507 
508 	return -ENOEXEC;
509 }
510 
511 #define HELP_NONE "[none]"
512 
513 SHELL_STATIC_SUBCMD_SET_CREATE(
514 	gmap_cmds, SHELL_CMD_ARG(init, NULL, HELP_NONE, cmd_gmap_init, 1, 0),
515 	SHELL_CMD_ARG(set_role, NULL, "[ugt | ugg | bgr | bgs]", cmd_gmap_set_role, 2, 3),
516 	SHELL_CMD_ARG(discover, NULL, HELP_NONE, cmd_gmap_discover, 1, 0),
517 #if defined(CONFIG_BT_GMAP_UGG_SUPPORTED)
518 #if UNICAST_SINK_SUPPORTED
519 	SHELL_CMD_ARG(ac_1, NULL, "Unicast audio configuration 1", cmd_gmap_ac_1, 1, 0),
520 #endif /* UNICAST_SINK_SUPPORTED */
521 #if UNICAST_SRC_SUPPORTED
522 	SHELL_CMD_ARG(ac_2, NULL, "Unicast audio configuration 2", cmd_gmap_ac_2, 1, 0),
523 #endif /* UNICAST_SRC_SUPPORTED */
524 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
525 	SHELL_CMD_ARG(ac_3, NULL, "Unicast audio configuration 3", cmd_gmap_ac_3, 1, 0),
526 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
527 #if UNICAST_SINK_SUPPORTED
528 	SHELL_CMD_ARG(ac_4, NULL, "Unicast audio configuration 4", cmd_gmap_ac_4, 1, 0),
529 #endif /* UNICAST_SINK_SUPPORTED */
530 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
531 	SHELL_CMD_ARG(ac_5, NULL, "Unicast audio configuration 5", cmd_gmap_ac_5, 1, 0),
532 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
533 #if UNICAST_SINK_SUPPORTED
534 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
535 	SHELL_CMD_ARG(ac_6_i, NULL, "Unicast audio configuration 6(i)", cmd_gmap_ac_6_i, 1, 0),
536 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
537 #if CONFIG_BT_MAX_CONN >= 2
538 	SHELL_CMD_ARG(ac_6_ii, NULL, "Unicast audio configuration 6(ii)", cmd_gmap_ac_6_ii, 1, 0),
539 #endif /* CONFIG_BT_MAX_CONN >= 2 */
540 #endif /* UNICAST_SINK_SUPPORTED */
541 #if UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED
542 #if CONFIG_BT_MAX_CONN >= 2
543 	SHELL_CMD_ARG(ac_7_ii, NULL, "Unicast audio configuration 7(ii)", cmd_gmap_ac_7_ii, 1, 0),
544 #endif /* CONFIG_BT_MAX_CONN >= 2 */
545 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1
546 	SHELL_CMD_ARG(ac_8_i, NULL, "Unicast audio configuration 8(i)", cmd_gmap_ac_8_i, 1, 0),
547 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 */
548 #if CONFIG_BT_MAX_CONN >= 2
549 	SHELL_CMD_ARG(ac_8_ii, NULL, "Unicast audio configuration 8(ii)", cmd_gmap_ac_8_ii, 1, 0),
550 #endif /* CONFIG_BT_MAX_CONN >= 2 */
551 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 && CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1
552 	SHELL_CMD_ARG(ac_11_i, NULL, "Unicast audio configuration 11(i)", cmd_gmap_ac_11_i, 1, 0),
553 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1 &&                                        \
554 	* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1                                           \
555 	*/
556 #if CONFIG_BT_MAX_CONN >= 2
557 	SHELL_CMD_ARG(ac_11_ii, NULL, "Unicast audio configuration 11(ii)", cmd_gmap_ac_11_ii, 1,
558 		      0),
559 #endif /* CONFIG_BT_MAX_CONN >= 2 */
560 #endif /* UNICAST_SINK_SUPPORTED && UNICAST_SRC_SUPPORTED */
561 #endif /* CONFIG_BT_GMAP_UGG_SUPPORTED */
562 
563 #if defined(CONFIG_BT_GMAP_BGS_SUPPORTED)
564 	SHELL_CMD_ARG(ac_12, NULL, "Broadcast audio configuration 12", cmd_gmap_ac_12, 1, 0),
565 #if CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1
566 	SHELL_CMD_ARG(ac_13, NULL, "Broadcast audio configuration 13", cmd_gmap_ac_13, 1, 0),
567 #endif /* CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT > 1 */
568 	SHELL_CMD_ARG(ac_14, NULL, "Broadcast audio configuration 14", cmd_gmap_ac_14, 1, 0),
569 #endif /* CONFIG_BT_GMAP_BGS_SUPPORTED*/
570 	SHELL_SUBCMD_SET_END);
571 
572 SHELL_CMD_ARG_REGISTER(gmap, &gmap_cmds, "Bluetooth GMAP shell commands", cmd_gmap, 1, 1);
573