1 /** @file
2  *  @brief Bluetooth Telephone Bearer Service shell
3  */
4 
5 /*
6  * Copyright (c) 2020-2021 Nordic Semiconductor ASA
7  *
8  * SPDX-License-Identifier: Apache-2.0
9  */
10 
11 #include <errno.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <zephyr/autoconf.h>
19 #include <zephyr/bluetooth/addr.h>
20 #include <zephyr/bluetooth/audio/tbs.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/kernel.h>
23 #include <zephyr/shell/shell.h>
24 #include <zephyr/shell/shell_string_conv.h>
25 #include <zephyr/sys/util_macro.h>
26 
27 #include "host/shell/bt.h"
28 
29 static struct bt_conn *tbs_authorized_conn;
30 
tbs_authorize_cb(struct bt_conn * conn)31 static bool tbs_authorize_cb(struct bt_conn *conn)
32 {
33 	return conn == tbs_authorized_conn;
34 }
35 
tbs_originate_call_cb(struct bt_conn * conn,uint8_t call_index,const char * uri)36 static bool tbs_originate_call_cb(struct bt_conn *conn, uint8_t call_index,
37 				  const char *uri)
38 {
39 	/* Always accept calls */
40 	return true;
41 }
42 
43 static struct bt_tbs_cb tbs_cbs = {
44 	.originate_call = tbs_originate_call_cb,
45 	.authorize = tbs_authorize_cb
46 };
47 
cmd_tbs_authorize(const struct shell * sh,size_t argc,char * argv[])48 static int cmd_tbs_authorize(const struct shell *sh, size_t argc, char *argv[])
49 {
50 	char addr[BT_ADDR_LE_STR_LEN];
51 
52 	tbs_authorized_conn = default_conn;
53 
54 	(void)bt_addr_le_to_str(bt_conn_get_dst(tbs_authorized_conn),
55 				addr, sizeof(addr));
56 
57 	shell_print(sh, "Connection with addr %s authorized", addr);
58 
59 	return 0;
60 }
61 
cmd_tbs_init(const struct shell * sh,size_t argc,char * argv[])62 static int cmd_tbs_init(const struct shell *sh, size_t argc, char *argv[])
63 {
64 	static bool registered;
65 
66 	if (registered) {
67 		shell_info(sh, "Already initialized");
68 
69 		return -ENOEXEC;
70 	}
71 
72 	const struct bt_tbs_register_param gtbs_param = {
73 		.provider_name = "Generic TBS",
74 		.uci = "un000",
75 		.uri_schemes_supported = "tel,skype",
76 		.gtbs = true,
77 		.authorization_required = false,
78 		.technology = BT_TBS_TECHNOLOGY_3G,
79 		.supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES,
80 	};
81 	int err;
82 
83 	err = bt_tbs_register_bearer(&gtbs_param);
84 	if (err < 0) {
85 		shell_error(sh, "Failed to register GTBS: %d", err);
86 
87 		return -ENOEXEC;
88 	}
89 
90 	shell_info(sh, "Registered GTBS");
91 
92 	for (int i = 0; i < CONFIG_BT_TBS_BEARER_COUNT; i++) {
93 		char prov_name[22]; /* Enough to store "Telephone Bearer #255" */
94 		const struct bt_tbs_register_param tbs_param = {
95 			.provider_name = prov_name,
96 			.uci = "un000",
97 			.uri_schemes_supported = "tel,skype",
98 			.gtbs = false,
99 			.authorization_required = false,
100 			/* Set different technologies per bearer */
101 			.technology = (i % BT_TBS_TECHNOLOGY_WCDMA) + 1,
102 			.supported_features = CONFIG_BT_TBS_SUPPORTED_FEATURES,
103 		};
104 
105 		snprintf(prov_name, sizeof(prov_name), "Telephone Bearer #%d", i);
106 
107 		err = bt_tbs_register_bearer(&tbs_param);
108 		if (err < 0) {
109 			shell_error(sh, "Failed to register TBS[%d]: %d", i, err);
110 
111 			return -ENOEXEC;
112 		}
113 
114 		shell_info(sh, "Registered TBS[%d] with index %u", i, (uint8_t)err);
115 	}
116 
117 	bt_tbs_register_cb(&tbs_cbs);
118 	registered = true;
119 
120 	return 0;
121 }
122 
cmd_tbs_accept(const struct shell * sh,size_t argc,char * argv[])123 static int cmd_tbs_accept(const struct shell *sh, size_t argc, char *argv[])
124 {
125 	unsigned long call_index;
126 	int result = 0;
127 
128 	call_index = shell_strtoul(argv[1], 0, &result);
129 	if (result != 0) {
130 		shell_error(sh, "Could not parse call_index: %d", result);
131 
132 		return -ENOEXEC;
133 	}
134 
135 	if (call_index > UINT8_MAX) {
136 		shell_error(sh, "Invalid call_index: %lu", call_index);
137 
138 		return -ENOEXEC;
139 	}
140 
141 	result = bt_tbs_accept((uint8_t)call_index);
142 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
143 		shell_print(sh, "TBS failed: %d", result);
144 	} else {
145 		shell_print(sh, "TBS succeeded for call_index: %ld",
146 			    call_index);
147 	}
148 
149 	return result;
150 }
151 
cmd_tbs_terminate(const struct shell * sh,size_t argc,char * argv[])152 static int cmd_tbs_terminate(const struct shell *sh, size_t argc,
153 			     char *argv[])
154 {
155 	unsigned long call_index;
156 	int result = 0;
157 
158 	call_index = shell_strtoul(argv[1], 0, &result);
159 	if (result != 0) {
160 		shell_error(sh, "Could not parse call_index: %d", result);
161 
162 		return -ENOEXEC;
163 	}
164 
165 	if (call_index > UINT8_MAX) {
166 		shell_error(sh, "Invalid call_index: %lu", call_index);
167 
168 		return -ENOEXEC;
169 	}
170 
171 	result = bt_tbs_terminate((uint8_t)call_index);
172 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
173 		shell_print(sh, "TBS failed: %d", result);
174 	} else {
175 		shell_print(sh, "TBS succeeded for call_index: %ld",
176 			    call_index);
177 	}
178 
179 	return result;
180 }
181 
cmd_tbs_hold(const struct shell * sh,size_t argc,char * argv[])182 static int cmd_tbs_hold(const struct shell *sh, size_t argc, char *argv[])
183 {
184 	unsigned long call_index;
185 	int result = 0;
186 
187 	call_index = shell_strtoul(argv[1], 0, &result);
188 	if (result != 0) {
189 		shell_error(sh, "Could not parse call_index: %d", result);
190 
191 		return -ENOEXEC;
192 	}
193 
194 	if (call_index > UINT8_MAX) {
195 		shell_error(sh, "Invalid call_index: %lu", call_index);
196 
197 		return -ENOEXEC;
198 	}
199 
200 	result = bt_tbs_hold((uint8_t)call_index);
201 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
202 		shell_print(sh, "TBS failed: %d", result);
203 	} else {
204 		shell_print(sh, "TBS succeeded for call_index: %ld",
205 			    call_index);
206 	}
207 
208 	return result;
209 }
210 
cmd_tbs_retrieve(const struct shell * sh,size_t argc,char * argv[])211 static int cmd_tbs_retrieve(const struct shell *sh, size_t argc,
212 			    char *argv[])
213 {
214 	unsigned long call_index;
215 	int result = 0;
216 
217 	call_index = shell_strtoul(argv[1], 0, &result);
218 	if (result != 0) {
219 		shell_error(sh, "Could not parse call_index: %d", result);
220 
221 		return -ENOEXEC;
222 	}
223 
224 	if (call_index > UINT8_MAX) {
225 		shell_error(sh, "Invalid call_index: %lu", call_index);
226 
227 		return -ENOEXEC;
228 	}
229 
230 	result = bt_tbs_retrieve((uint8_t)call_index);
231 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
232 		shell_print(sh, "TBS failed: %d", result);
233 	} else {
234 		shell_print(sh, "TBS succeeded for call_index: %ld",
235 			    call_index);
236 	}
237 
238 	return result;
239 }
240 
cmd_tbs_originate(const struct shell * sh,size_t argc,char * argv[])241 static int cmd_tbs_originate(const struct shell *sh, size_t argc, char *argv[])
242 {
243 	unsigned long service_index;
244 	uint8_t call_index;
245 	int result = 0;
246 
247 	if (argc > 2) {
248 		service_index = shell_strtoul(argv[1], 0, &result);
249 		if (result != 0) {
250 			shell_error(sh, "Could not parse service_index: %d",
251 				    result);
252 
253 			return -ENOEXEC;
254 		}
255 
256 		if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
257 			shell_error(sh, "Invalid service_index: %lu",
258 				    service_index);
259 
260 			return -ENOEXEC;
261 		}
262 	} else {
263 		service_index = BT_TBS_GTBS_INDEX;
264 	}
265 
266 	result = bt_tbs_originate((uint8_t)service_index, argv[argc - 1],
267 				  &call_index);
268 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
269 		shell_print(sh, "TBS failed: %d", result);
270 	} else {
271 		shell_print(sh, "TBS call_index %u originated", call_index);
272 	}
273 
274 	return result;
275 }
276 
cmd_tbs_join(const struct shell * sh,size_t argc,char * argv[])277 static int cmd_tbs_join(const struct shell *sh, size_t argc, char *argv[])
278 {
279 	uint8_t call_indexes[CONFIG_BT_TBS_MAX_CALLS];
280 	unsigned long call_index;
281 	int result = 0;
282 
283 	for (size_t i = 1; i < argc; i++) {
284 		call_index = shell_strtoul(argv[i], 0, &result);
285 		if (result != 0) {
286 			shell_error(sh, "Could not parse call_index: %d",
287 				    result);
288 
289 			return -ENOEXEC;
290 		}
291 
292 		if (call_index > UINT8_MAX) {
293 			shell_error(sh, "Invalid call_index: %lu", call_index);
294 
295 			return -ENOEXEC;
296 		}
297 
298 		call_indexes[i - 1] = (uint8_t)call_index;
299 	}
300 
301 	result = bt_tbs_join(argc - 1, call_indexes);
302 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
303 		shell_print(sh, "TBS failed: %d", result);
304 	} else {
305 		shell_print(sh, "TBS join succeeded");
306 	}
307 
308 	return result;
309 }
310 
cmd_tbs_answer(const struct shell * sh,size_t argc,char * argv[])311 static int cmd_tbs_answer(const struct shell *sh, size_t argc, char *argv[])
312 {
313 	unsigned long call_index;
314 	int result = 0;
315 
316 	call_index = shell_strtoul(argv[1], 0, &result);
317 	if (result != 0) {
318 		shell_error(sh, "Could not parse call_index: %d", result);
319 
320 		return -ENOEXEC;
321 	}
322 
323 	if (call_index > UINT8_MAX) {
324 		shell_error(sh, "Invalid call_index: %lu", call_index);
325 
326 		return -ENOEXEC;
327 	}
328 
329 	result = bt_tbs_remote_answer((uint8_t)call_index);
330 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
331 		shell_print(sh, "TBS failed: %d", result);
332 	} else {
333 		shell_print(sh, "TBS succeeded for call_index: %ld",
334 			    call_index);
335 	}
336 
337 	return result;
338 }
339 
cmd_tbs_remote_hold(const struct shell * sh,size_t argc,char * argv[])340 static int cmd_tbs_remote_hold(const struct shell *sh, size_t argc,
341 			       char *argv[])
342 {
343 	unsigned long call_index;
344 	int result = 0;
345 
346 	call_index = shell_strtoul(argv[1], 0, &result);
347 	if (result != 0) {
348 		shell_error(sh, "Could not parse call_index: %d", result);
349 
350 		return -ENOEXEC;
351 	}
352 
353 	if (call_index > UINT8_MAX) {
354 		shell_error(sh, "Invalid call_index: %lu", call_index);
355 
356 		return -ENOEXEC;
357 	}
358 
359 	result = bt_tbs_remote_hold((uint8_t)call_index);
360 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
361 		shell_print(sh, "TBS failed: %d", result);
362 	} else {
363 		shell_print(sh, "TBS succeeded for call_index: %ld",
364 			    call_index);
365 	}
366 
367 	return result;
368 }
369 
cmd_tbs_remote_retrieve(const struct shell * sh,size_t argc,char * argv[])370 static int cmd_tbs_remote_retrieve(const struct shell *sh, size_t argc,
371 				   char *argv[])
372 {
373 	unsigned long call_index;
374 	int result = 0;
375 
376 	call_index = shell_strtoul(argv[1], 0, &result);
377 	if (result != 0) {
378 		shell_error(sh, "Could not parse call_index: %d", result);
379 
380 		return -ENOEXEC;
381 	}
382 
383 	if (call_index > UINT8_MAX) {
384 		shell_error(sh, "Invalid call_index: %lu", call_index);
385 
386 		return -ENOEXEC;
387 	}
388 
389 	result = bt_tbs_remote_retrieve((uint8_t)call_index);
390 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
391 		shell_print(sh, "TBS failed: %d", result);
392 	} else {
393 		shell_print(sh, "TBS succeeded for call_index: %ld",
394 			    call_index);
395 	}
396 
397 	return result;
398 }
399 
cmd_tbs_remote_terminate(const struct shell * sh,size_t argc,char * argv[])400 static int cmd_tbs_remote_terminate(const struct shell *sh, size_t argc,
401 				    char *argv[])
402 {
403 	unsigned long call_index;
404 	int result = 0;
405 
406 	call_index = shell_strtoul(argv[1], 0, &result);
407 	if (result != 0) {
408 		shell_error(sh, "Could not parse call_index: %d", result);
409 
410 		return -ENOEXEC;
411 	}
412 
413 	if (call_index > UINT8_MAX) {
414 		shell_error(sh, "Invalid call_index: %lu", call_index);
415 
416 		return -ENOEXEC;
417 	}
418 
419 	result = bt_tbs_remote_terminate((uint8_t)call_index);
420 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
421 		shell_print(sh, "TBS failed: %d", result);
422 	} else {
423 		shell_print(sh, "TBS succeeded for call_index: %ld",
424 			    call_index);
425 	}
426 
427 	return result;
428 }
429 
cmd_tbs_incoming(const struct shell * sh,size_t argc,char * argv[])430 static int cmd_tbs_incoming(const struct shell *sh, size_t argc, char *argv[])
431 {
432 	unsigned long service_index;
433 	int result = 0;
434 
435 	if (argc > 4) {
436 		if (strcmp(argv[1], "gtbs") == 0) {
437 			service_index = BT_TBS_GTBS_INDEX;
438 		} else {
439 			service_index = shell_strtoul(argv[1], 0, &result);
440 			if (result != 0) {
441 				shell_error(sh,
442 					    "Could not parse service_index: %d",
443 					    result);
444 
445 				return -ENOEXEC;
446 			}
447 
448 			if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
449 				shell_error(sh, "Invalid service_index: %lu",
450 					    service_index);
451 
452 				return -ENOEXEC;
453 			}
454 		}
455 	} else {
456 		service_index = BT_TBS_GTBS_INDEX;
457 	}
458 
459 	result = bt_tbs_remote_incoming((uint8_t)service_index,
460 					argv[argc - 3],
461 					argv[argc - 2],
462 					argv[argc - 1]);
463 	if (result < 0) {
464 		shell_print(sh, "TBS failed: %d", result);
465 	} else {
466 		shell_print(sh, "TBS succeeded");
467 	}
468 
469 	return result;
470 }
471 
cmd_tbs_set_bearer_provider_name(const struct shell * sh,size_t argc,char * argv[])472 static int cmd_tbs_set_bearer_provider_name(const struct shell *sh, size_t argc,
473 					    char *argv[])
474 {
475 	unsigned long service_index;
476 	int result = 0;
477 
478 	if (argc > 2) {
479 		if (strcmp(argv[1], "gtbs") == 0) {
480 			service_index = BT_TBS_GTBS_INDEX;
481 		} else {
482 			service_index = shell_strtoul(argv[1], 0, &result);
483 			if (result != 0) {
484 				shell_error(sh,
485 					    "Could not parse service_index: %d",
486 					    result);
487 
488 				return -ENOEXEC;
489 			}
490 
491 			if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
492 				shell_error(sh, "Invalid service_index: %lu",
493 					    service_index);
494 
495 				return -ENOEXEC;
496 			}
497 		}
498 	} else {
499 		service_index = BT_TBS_GTBS_INDEX;
500 	}
501 
502 	result = bt_tbs_set_bearer_provider_name((uint8_t)service_index,
503 						 argv[argc - 1]);
504 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
505 		shell_print(sh, "Could not set provider name: %d", result);
506 	}
507 
508 	return result;
509 }
510 
cmd_tbs_set_bearer_technology(const struct shell * sh,size_t argc,char * argv[])511 static int cmd_tbs_set_bearer_technology(const struct shell *sh, size_t argc,
512 					 char *argv[])
513 {
514 	unsigned long service_index;
515 	unsigned long technology;
516 	int result = 0;
517 
518 	if (argc > 2) {
519 		if (strcmp(argv[1], "gtbs") == 0) {
520 			service_index = BT_TBS_GTBS_INDEX;
521 		} else {
522 			service_index = shell_strtoul(argv[1], 0, &result);
523 			if (result != 0) {
524 				shell_error(sh,
525 					    "Could not parse service_index: %d",
526 					    result);
527 
528 				return -ENOEXEC;
529 			}
530 
531 			if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
532 				shell_error(sh, "Invalid service_index: %lu",
533 					    service_index);
534 
535 				return -ENOEXEC;
536 			}
537 		}
538 	} else {
539 		service_index = BT_TBS_GTBS_INDEX;
540 	}
541 
542 	technology = shell_strtoul(argv[argc - 1], 0, &result);
543 	if (result != 0) {
544 		shell_error(sh, "Could not parse technology: %d", result);
545 
546 		return -ENOEXEC;
547 	}
548 
549 	if (technology > UINT8_MAX) {
550 		shell_error(sh, "Invalid technology: %lu", technology);
551 
552 		return -ENOEXEC;
553 	}
554 
555 	result = bt_tbs_set_bearer_technology((uint8_t)service_index,
556 					      (uint8_t)technology);
557 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
558 		shell_print(sh, "Could not set technology: %d", result);
559 	}
560 
561 	return result;
562 }
563 
cmd_tbs_set_bearer_signal_strength(const struct shell * sh,size_t argc,char * argv[])564 static int cmd_tbs_set_bearer_signal_strength(const struct shell *sh,
565 					      size_t argc, char *argv[])
566 {
567 	unsigned long signal_strength;
568 	unsigned long service_index;
569 	int result = 0;
570 
571 	if (argc > 2) {
572 		if (strcmp(argv[1], "gtbs") == 0) {
573 			service_index = BT_TBS_GTBS_INDEX;
574 		} else {
575 			service_index = shell_strtoul(argv[1], 0, &result);
576 			if (result != 0) {
577 				shell_error(sh,
578 					    "Could not parse service_index: %d",
579 					    result);
580 
581 				return -ENOEXEC;
582 			}
583 
584 			if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
585 				shell_error(sh, "Invalid service_index: %lu",
586 					    service_index);
587 
588 				return -ENOEXEC;
589 			}
590 		}
591 	} else {
592 		service_index = BT_TBS_GTBS_INDEX;
593 	}
594 
595 	signal_strength = shell_strtoul(argv[argc - 1], 0, &result);
596 	if (result != 0) {
597 		shell_error(sh, "Could not parse signal_strength: %d", result);
598 
599 		return -ENOEXEC;
600 	}
601 
602 	if (signal_strength > UINT8_MAX) {
603 		shell_error(sh, "Invalid signal_strength: %lu",
604 			    signal_strength);
605 
606 		return -ENOEXEC;
607 	}
608 
609 	result = bt_tbs_set_signal_strength((uint8_t)service_index,
610 					    (uint8_t)signal_strength);
611 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
612 		shell_print(sh, "Could not set signal strength: %d", result);
613 	}
614 
615 	return result;
616 }
617 
cmd_tbs_set_status_flags(const struct shell * sh,size_t argc,char * argv[])618 static int cmd_tbs_set_status_flags(const struct shell *sh, size_t argc,
619 				    char *argv[])
620 {
621 	unsigned long service_index;
622 	unsigned long status_flags;
623 	int result = 0;
624 
625 	if (argc > 2) {
626 		if (strcmp(argv[1], "gtbs") == 0) {
627 			service_index = BT_TBS_GTBS_INDEX;
628 		} else {
629 			service_index = shell_strtoul(argv[1], 0, &result);
630 			if (result != 0) {
631 				shell_error(sh,
632 					    "Could not parse service_index: %d",
633 					    result);
634 
635 				return -ENOEXEC;
636 			}
637 
638 			if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
639 				shell_error(sh, "Invalid service_index: %lu",
640 					    service_index);
641 
642 				return -ENOEXEC;
643 			}
644 		}
645 	} else {
646 		service_index = BT_TBS_GTBS_INDEX;
647 	}
648 
649 	status_flags = shell_strtoul(argv[argc - 1], 0, &result);
650 	if (result != 0) {
651 		shell_error(sh, "Could not parse status_flags: %d", result);
652 
653 		return -ENOEXEC;
654 	}
655 
656 	if (status_flags > UINT8_MAX) {
657 		shell_error(sh, "Invalid status_flags: %lu", status_flags);
658 
659 		return -ENOEXEC;
660 	}
661 
662 	result = bt_tbs_set_status_flags((uint8_t)service_index,
663 					 (uint16_t)status_flags);
664 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
665 		shell_print(sh, "Could not set status flags: %d", result);
666 	}
667 
668 	return result;
669 }
670 
cmd_tbs_set_uri_scheme_list(const struct shell * sh,size_t argc,char * argv[])671 static int cmd_tbs_set_uri_scheme_list(const struct shell *sh, size_t argc,
672 				       char *argv[])
673 {
674 	unsigned long service_index;
675 	int result = 0;
676 
677 	if (argc > 2) {
678 		if (strcmp(argv[1], "gtbs") == 0) {
679 			service_index = BT_TBS_GTBS_INDEX;
680 		} else {
681 			service_index = shell_strtoul(argv[1], 0, &result);
682 			if (result != 0) {
683 				shell_error(sh,
684 					    "Could not parse service_index: %d",
685 					    result);
686 
687 				return -ENOEXEC;
688 			}
689 
690 			if (service_index > CONFIG_BT_TBS_BEARER_COUNT) {
691 				shell_error(sh, "Invalid service_index: %lu",
692 					    service_index);
693 
694 				return -ENOEXEC;
695 			}
696 		}
697 	} else {
698 		service_index = BT_TBS_GTBS_INDEX;
699 	}
700 
701 	result = bt_tbs_set_uri_scheme_list((uint8_t)service_index,
702 					    (const char **)&argv[2],
703 					    argc - 2);
704 
705 	if (result != BT_TBS_RESULT_CODE_SUCCESS) {
706 		shell_print(sh, "Could not set URI prefix list: %d", result);
707 	}
708 
709 	return result;
710 }
711 
cmd_tbs_print_calls(const struct shell * sh,size_t argc,char * argv[])712 static int cmd_tbs_print_calls(const struct shell *sh, size_t argc,
713 			       char *argv[])
714 {
715 	if (IS_ENABLED(CONFIG_BT_TBS_LOG_LEVEL_DBG)) {
716 		bt_tbs_dbg_print_calls();
717 		return 0;
718 	}
719 
720 	return -ENOEXEC;
721 }
722 
cmd_tbs(const struct shell * sh,size_t argc,char ** argv)723 static int cmd_tbs(const struct shell *sh, size_t argc, char **argv)
724 {
725 	if (argc > 1) {
726 		shell_error(sh, "%s unknown parameter: %s", argv[0],
727 			    argv[1]);
728 	} else {
729 		shell_error(sh, "%s Missing subcommand", argv[0]);
730 	}
731 
732 	return -ENOEXEC;
733 }
734 
735 SHELL_STATIC_SUBCMD_SET_CREATE(tbs_cmds,
736 	SHELL_CMD_ARG(init, NULL,
737 		      "Initialize TBS",
738 		      cmd_tbs_init, 1, 0),
739 	SHELL_CMD_ARG(authorize, NULL,
740 		      "Authorize the current connection",
741 		      cmd_tbs_authorize, 1, 0),
742 	SHELL_CMD_ARG(accept, NULL,
743 		      "Accept call <call_index>",
744 		      cmd_tbs_accept, 2, 0),
745 	SHELL_CMD_ARG(terminate, NULL,
746 		      "Terminate call <call_index>",
747 		      cmd_tbs_terminate, 2, 0),
748 	SHELL_CMD_ARG(hold, NULL,
749 		      "Hold call <call_index>",
750 		      cmd_tbs_hold, 2, 0),
751 	SHELL_CMD_ARG(retrieve, NULL,
752 		      "Retrieve call <call_index>",
753 		      cmd_tbs_retrieve, 2, 0),
754 	SHELL_CMD_ARG(originate, NULL,
755 		      "Originate call [<instance_index>] <uri>",
756 		      cmd_tbs_originate, 2, 1),
757 #if CONFIG_BT_TBS_MAX_CALLS > 1
758 	SHELL_CMD_ARG(join, NULL,
759 		      "Join calls <id> <id> [<id> [<id> [...]]]",
760 		      cmd_tbs_join, 3, CONFIG_BT_TBS_MAX_CALLS - 2),
761 #endif /* CONFIG_BT_TBS_MAX_CALLS > 1 */
762 	SHELL_CMD_ARG(incoming, NULL,
763 		      "Simulate incoming remote call "
764 		      "[<{instance_index, gtbs}>] <local_uri> <remote_uri> "
765 		      "<remote_friendly_name>",
766 		      cmd_tbs_incoming, 4, 1),
767 	SHELL_CMD_ARG(remote_answer, NULL,
768 		      "Simulate remote answer outgoing call <call_index>",
769 		      cmd_tbs_answer, 2, 0),
770 	SHELL_CMD_ARG(remote_retrieve, NULL,
771 		      "Simulate remote retrieve <call_index>",
772 		      cmd_tbs_remote_retrieve, 2, 0),
773 	SHELL_CMD_ARG(remote_terminate, NULL,
774 		      "Simulate remote terminate <call_index>",
775 		      cmd_tbs_remote_terminate, 2, 0),
776 	SHELL_CMD_ARG(remote_hold, NULL,
777 		      "Simulate remote hold <call_index>",
778 		      cmd_tbs_remote_hold, 2, 0),
779 	SHELL_CMD_ARG(set_bearer_provider_name, NULL,
780 		      "Set the bearer provider name [<{instance_index, gtbs}>] "
781 		      "<name>",
782 		      cmd_tbs_set_bearer_provider_name, 2, 1),
783 	SHELL_CMD_ARG(set_bearer_technology, NULL,
784 		      "Set the bearer technology [<{instance_index, gtbs}>] "
785 		      "<technology>",
786 		      cmd_tbs_set_bearer_technology, 2, 1),
787 	SHELL_CMD_ARG(set_bearer_signal_strength, NULL,
788 		      "Set the bearer signal strength "
789 		      "[<{instance_index, gtbs}>] <strength>",
790 		      cmd_tbs_set_bearer_signal_strength, 2, 1),
791 	SHELL_CMD_ARG(set_status_flags, NULL,
792 		      "Set the bearer feature and status value "
793 		      "[<{instance_index, gtbs}>] <feature_and_status>",
794 		      cmd_tbs_set_status_flags, 2, 1),
795 	SHELL_CMD_ARG(set_uri_scheme, NULL,
796 		      "Set the URI prefix list <bearer_idx> "
797 		      "<uri1 [uri2 [uri3 [...]]]>",
798 		      cmd_tbs_set_uri_scheme_list, 3, 30),
799 	SHELL_CMD_ARG(print_calls, NULL,
800 		      "Output all calls in the debug log",
801 		      cmd_tbs_print_calls, 1, 0),
802 	SHELL_SUBCMD_SET_END
803 );
804 
805 SHELL_CMD_ARG_REGISTER(tbs, &tbs_cmds, "Bluetooth TBS shell commands",
806 		       cmd_tbs, 1, 1);
807