1 /** @file
2  *  @brief Bluetooth Telephone Bearer Service client shell
3  *
4  */
5 
6 /*
7  * Copyright (c) 2020 Nordic Semiconductor ASA
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <errno.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <string.h>
16 
17 #include <zephyr/autoconf.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/gatt.h>
20 #include <zephyr/bluetooth/audio/tbs.h>
21 #include <zephyr/kernel.h>
22 #include <zephyr/shell/shell_string_conv.h>
23 #include <zephyr/shell/shell.h>
24 #include <zephyr/sys/printk.h>
25 #include <zephyr/sys/byteorder.h>
26 #include <zephyr/sys/util.h>
27 #include <zephyr/types.h>
28 
29 #include "host/shell/bt.h"
30 
cmd_tbs_client_discover(const struct shell * sh,size_t argc,char * argv[])31 static int cmd_tbs_client_discover(const struct shell *sh, size_t argc,
32 				   char *argv[])
33 {
34 	int result = 0;
35 
36 	result = bt_tbs_client_discover(default_conn);
37 	if (result != 0) {
38 		shell_print(sh, "Fail: %d", result);
39 	}
40 
41 	return result;
42 }
43 
44 #if defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL)
cmd_tbs_client_set_signal_strength_interval(const struct shell * sh,size_t argc,char * argv[])45 static int cmd_tbs_client_set_signal_strength_interval(const struct shell *sh,
46 						       size_t argc,
47 						       char *argv[])
48 {
49 	unsigned long inst_index;
50 	unsigned long interval;
51 	int result = 0;
52 
53 	/* TODO: The handling of index/GTBS index is done in almost every
54 	 * function - Should add a helper function to reduce duplicated code
55 	 */
56 	if (argc > 2) {
57 		if (strcmp(argv[1], "gtbs") == 0) {
58 			inst_index = BT_TBS_GTBS_INDEX;
59 		} else {
60 			inst_index = shell_strtoul(argv[1], 0, &result);
61 			if (result != 0) {
62 				shell_error(sh,
63 					    "Failed to parse inst_index: %d",
64 					    result);
65 
66 				return -ENOEXEC;
67 			}
68 
69 			if (inst_index > UINT8_MAX) {
70 				shell_error(sh, "Invalid index: %lu",
71 					    inst_index);
72 
73 				return -ENOEXEC;
74 			}
75 		}
76 	} else {
77 		inst_index = 0;
78 	}
79 
80 	interval = shell_strtoul(argv[argc - 1], 0, &result);
81 	if (result != 0) {
82 		shell_error(sh, "Failed to parse interval: %d", result);
83 
84 		return -ENOEXEC;
85 	}
86 
87 	if (interval > UINT8_MAX) {
88 		shell_error(sh, "Invalid interval: %lu", interval);
89 
90 		return -ENOEXEC;
91 	}
92 
93 	result = bt_tbs_client_set_signal_strength_interval(default_conn,
94 							    inst_index,
95 							    interval);
96 	if (result != 0) {
97 		shell_print(sh, "Fail: %d", result);
98 	}
99 
100 	return result;
101 }
102 #endif /* defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */
103 
104 #if defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL)
cmd_tbs_client_hold(const struct shell * sh,size_t argc,char * argv[])105 static int cmd_tbs_client_hold(const struct shell *sh, size_t argc,
106 			       char *argv[])
107 {
108 	unsigned long inst_index;
109 	unsigned long call_index;
110 	int result = 0;
111 
112 	if (argc > 2) {
113 		if (strcmp(argv[1], "gtbs") == 0) {
114 			inst_index = BT_TBS_GTBS_INDEX;
115 		} else {
116 			inst_index = shell_strtoul(argv[1], 0, &result);
117 			if (result != 0) {
118 				shell_error(sh,
119 					    "Failed to parse inst_index: %d",
120 					    result);
121 
122 				return -ENOEXEC;
123 			}
124 
125 			if (inst_index > UINT8_MAX) {
126 				shell_error(sh, "Invalid index: %lu",
127 					    inst_index);
128 
129 				return -ENOEXEC;
130 			}
131 		}
132 	} else {
133 		inst_index = 0;
134 	}
135 
136 	call_index = shell_strtoul(argv[argc - 1], 0, &result);
137 	if (result != 0) {
138 		shell_error(sh, "Failed to parse call_index: %d", result);
139 
140 		return -ENOEXEC;
141 	}
142 
143 	if (call_index > UINT8_MAX) {
144 		shell_error(sh, "Invalid call_index: %lu", call_index);
145 
146 		return -ENOEXEC;
147 	}
148 
149 	result = bt_tbs_client_hold_call(default_conn, inst_index, call_index);
150 	if (result != 0) {
151 		shell_print(sh, "Fail: %d", result);
152 	}
153 
154 	return result;
155 }
156 #endif /* defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL) */
157 
158 #if defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL)
cmd_tbs_client_retrieve(const struct shell * sh,size_t argc,char * argv[])159 static int cmd_tbs_client_retrieve(const struct shell *sh, size_t argc,
160 				   char *argv[])
161 {
162 	unsigned long inst_index;
163 	unsigned long call_index;
164 	int result = 0;
165 
166 	if (argc > 2) {
167 		if (strcmp(argv[1], "gtbs") == 0) {
168 			inst_index = BT_TBS_GTBS_INDEX;
169 		} else {
170 			inst_index = shell_strtoul(argv[1], 0, &result);
171 			if (result != 0) {
172 				shell_error(sh,
173 					    "Failed to parse inst_index: %d",
174 					    result);
175 
176 				return -ENOEXEC;
177 			}
178 
179 			if (inst_index > UINT8_MAX) {
180 				shell_error(sh, "Invalid index: %lu",
181 					    inst_index);
182 
183 				return -ENOEXEC;
184 			}
185 		}
186 	} else {
187 		inst_index = 0;
188 	}
189 
190 	call_index = shell_strtoul(argv[argc - 1], 0, &result);
191 	if (result != 0) {
192 		shell_error(sh, "Failed to parse call_index: %d", result);
193 
194 		return -ENOEXEC;
195 	}
196 
197 	if (call_index > UINT8_MAX) {
198 		shell_error(sh, "Invalid call_index: %lu", call_index);
199 
200 		return -ENOEXEC;
201 	}
202 
203 	result = bt_tbs_client_retrieve_call(default_conn, inst_index,
204 					     call_index);
205 	if (result != 0) {
206 		shell_print(sh, "Fail: %d", result);
207 	}
208 
209 	return result;
210 }
211 #endif /* defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL) */
212 
213 #if defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL)
cmd_tbs_client_accept(const struct shell * sh,size_t argc,char * argv[])214 static int cmd_tbs_client_accept(const struct shell *sh, size_t argc,
215 				 char *argv[])
216 {
217 	unsigned long inst_index;
218 	unsigned long call_index;
219 	int result = 0;
220 
221 	if (argc > 2) {
222 		if (strcmp(argv[1], "gtbs") == 0) {
223 			inst_index = BT_TBS_GTBS_INDEX;
224 		} else {
225 			inst_index = shell_strtoul(argv[1], 0, &result);
226 			if (result != 0) {
227 				shell_error(sh,
228 					    "Failed to parse inst_index: %d",
229 					    result);
230 
231 				return -ENOEXEC;
232 			}
233 
234 			if (inst_index > UINT8_MAX) {
235 				shell_error(sh, "Invalid index: %lu",
236 					    inst_index);
237 
238 				return -ENOEXEC;
239 			}
240 		}
241 	} else {
242 		inst_index = 0;
243 	}
244 
245 	call_index = shell_strtoul(argv[argc - 1], 0, &result);
246 	if (result != 0) {
247 		shell_error(sh, "Failed to parse call_index: %d", result);
248 
249 		return -ENOEXEC;
250 	}
251 
252 	if (call_index > UINT8_MAX) {
253 		shell_error(sh, "Invalid call_index: %lu", call_index);
254 
255 		return -ENOEXEC;
256 	}
257 
258 	result = bt_tbs_client_accept_call(default_conn, inst_index,
259 					   call_index);
260 
261 	if (result != 0) {
262 		shell_print(sh, "Fail: %d", result);
263 	}
264 
265 	return result;
266 }
267 #endif /* defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL) */
268 
269 #if defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS)
cmd_tbs_client_join(const struct shell * sh,size_t argc,char * argv[])270 static int cmd_tbs_client_join(const struct shell *sh, size_t argc,
271 			       char *argv[])
272 {
273 
274 	uint8_t call_indexes[CONFIG_BT_TBS_CLIENT_MAX_CALLS];
275 	unsigned long inst_index;
276 	int result = 0;
277 
278 	if (strcmp(argv[1], "gtbs") == 0) {
279 		inst_index = BT_TBS_GTBS_INDEX;
280 	} else {
281 		inst_index = shell_strtoul(argv[1], 0, &result);
282 		if (result != 0) {
283 			shell_error(sh,
284 					"Failed to parse inst_index: %d",
285 					result);
286 
287 			return -ENOEXEC;
288 		}
289 
290 		if (inst_index > UINT8_MAX) {
291 			shell_error(sh, "Invalid index: %lu",
292 					inst_index);
293 
294 			return -ENOEXEC;
295 		}
296 	}
297 
298 	for (size_t i = 2U; i < argc; i++) {
299 		unsigned long call_index;
300 
301 		call_index = shell_strtoul(argv[i], 0, &result);
302 		if (result != 0) {
303 			shell_error(sh, "Failed to parse call_index: %d",
304 				    result);
305 
306 			return -ENOEXEC;
307 		}
308 
309 		if (call_index > UINT8_MAX) {
310 			shell_error(sh, "Invalid call_index: %lu", call_index);
311 
312 			return -ENOEXEC;
313 		}
314 
315 		call_indexes[i - 2] = (uint8_t)call_index;
316 	}
317 
318 	result = bt_tbs_client_join_calls(default_conn, inst_index,
319 					  call_indexes, argc - 2);
320 	if (result != 0) {
321 		shell_print(sh, "Fail: %d", result);
322 	}
323 
324 	return result;
325 }
326 #endif /* defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS) */
327 
328 #if defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL)
cmd_tbs_client_terminate(const struct shell * sh,size_t argc,char * argv[])329 static int cmd_tbs_client_terminate(const struct shell *sh, size_t argc,
330 				    char *argv[])
331 {
332 	unsigned long inst_index;
333 	unsigned long call_index;
334 	int result = 0;
335 
336 	if (argc > 2) {
337 		if (strcmp(argv[1], "gtbs") == 0) {
338 			inst_index = BT_TBS_GTBS_INDEX;
339 		} else {
340 			inst_index = shell_strtoul(argv[1], 0, &result);
341 			if (result != 0) {
342 				shell_error(sh,
343 					    "Failed to parse inst_index: %d",
344 					    result);
345 
346 				return -ENOEXEC;
347 			}
348 
349 			if (inst_index > UINT8_MAX) {
350 				shell_error(sh, "Invalid index: %lu",
351 					    inst_index);
352 
353 				return -ENOEXEC;
354 			}
355 		}
356 	} else {
357 		inst_index = 0;
358 	}
359 
360 	call_index = shell_strtoul(argv[argc - 1], 0, &result);
361 	if (result != 0) {
362 		shell_error(sh, "Failed to parse call_index: %d", result);
363 
364 		return -ENOEXEC;
365 	}
366 
367 	if (call_index > UINT8_MAX) {
368 		shell_error(sh, "Invalid call_index: %lu", call_index);
369 
370 		return -ENOEXEC;
371 	}
372 
373 	result = bt_tbs_client_terminate_call(default_conn, inst_index,
374 					      call_index);
375 	if (result != 0) {
376 		shell_print(sh, "Fail: %d", result);
377 	}
378 
379 	return result;
380 }
381 #endif /* defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL) */
382 
383 #if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
cmd_tbs_client_originate(const struct shell * sh,size_t argc,char * argv[])384 static int cmd_tbs_client_originate(const struct shell *sh, size_t argc,
385 				    char *argv[])
386 {
387 	unsigned long inst_index;
388 	int result = 0;
389 
390 	if (argc > 2) {
391 		if (strcmp(argv[1], "gtbs") == 0) {
392 			inst_index = BT_TBS_GTBS_INDEX;
393 		} else {
394 			inst_index = shell_strtoul(argv[1], 0, &result);
395 			if (result != 0) {
396 				shell_error(sh,
397 					    "Failed to parse inst_index: %d",
398 					    result);
399 
400 				return -ENOEXEC;
401 			}
402 
403 			if (inst_index > UINT8_MAX) {
404 				shell_error(sh, "Invalid index: %lu",
405 					    inst_index);
406 
407 				return -ENOEXEC;
408 			}
409 		}
410 	} else {
411 		inst_index = 0;
412 	}
413 
414 	result = bt_tbs_client_originate_call(default_conn, inst_index,
415 					      argv[argc - 1]);
416 	if (result != 0) {
417 		shell_print(sh, "Fail: %d", result);
418 	}
419 
420 	return result;
421 }
422 #endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
423 
424 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
cmd_tbs_client_read_bearer_provider_name(const struct shell * sh,size_t argc,char * argv[])425 static int cmd_tbs_client_read_bearer_provider_name(const struct shell *sh,
426 						    size_t argc, char *argv[])
427 {
428 	unsigned long inst_index;
429 	int result = 0;
430 
431 	if (argc > 1) {
432 		if (strcmp(argv[1], "gtbs") == 0) {
433 			inst_index = BT_TBS_GTBS_INDEX;
434 		} else {
435 			inst_index = shell_strtoul(argv[1], 0, &result);
436 			if (result != 0) {
437 				shell_error(sh,
438 					    "Failed to parse inst_index: %d",
439 					    result);
440 
441 				return -ENOEXEC;
442 			}
443 
444 			if (inst_index > UINT8_MAX) {
445 				shell_error(sh, "Invalid index: %lu",
446 					    inst_index);
447 
448 				return -ENOEXEC;
449 			}
450 		}
451 	} else {
452 		inst_index = 0;
453 	}
454 
455 	result = bt_tbs_client_read_bearer_provider_name(default_conn,
456 							 inst_index);
457 	if (result != 0) {
458 		shell_print(sh, "Fail: %d", result);
459 	}
460 
461 	return result;
462 }
463 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
464 
465 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
cmd_tbs_client_read_bearer_uci(const struct shell * sh,size_t argc,char * argv[])466 static int cmd_tbs_client_read_bearer_uci(const struct shell *sh, size_t argc,
467 					  char *argv[])
468 {
469 	unsigned long inst_index;
470 	int result = 0;
471 
472 	if (argc > 1) {
473 		if (strcmp(argv[1], "gtbs") == 0) {
474 			inst_index = BT_TBS_GTBS_INDEX;
475 		} else {
476 			inst_index = shell_strtoul(argv[1], 0, &result);
477 			if (result != 0) {
478 				shell_error(sh,
479 					    "Failed to parse inst_index: %d",
480 					    result);
481 
482 				return -ENOEXEC;
483 			}
484 
485 			if (inst_index > UINT8_MAX) {
486 				shell_error(sh, "Invalid index: %lu",
487 					    inst_index);
488 
489 				return -ENOEXEC;
490 			}
491 		}
492 	} else {
493 		inst_index = 0;
494 	}
495 
496 	result = bt_tbs_client_read_bearer_uci(default_conn, inst_index);
497 	if (result != 0) {
498 		shell_print(sh, "Fail: %d", result);
499 	}
500 
501 	return result;
502 }
503 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
504 
505 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
cmd_tbs_client_read_technology(const struct shell * sh,size_t argc,char * argv[])506 static int cmd_tbs_client_read_technology(const struct shell *sh, size_t argc,
507 					  char *argv[])
508 {
509 	unsigned long inst_index;
510 	int result = 0;
511 
512 	if (argc > 1) {
513 		if (strcmp(argv[1], "gtbs") == 0) {
514 			inst_index = BT_TBS_GTBS_INDEX;
515 		} else {
516 			inst_index = shell_strtoul(argv[1], 0, &result);
517 			if (result != 0) {
518 				shell_error(sh,
519 					    "Failed to parse inst_index: %d",
520 					    result);
521 
522 				return -ENOEXEC;
523 			}
524 
525 			if (inst_index > UINT8_MAX) {
526 				shell_error(sh, "Invalid index: %lu",
527 					    inst_index);
528 
529 				return -ENOEXEC;
530 			}
531 		}
532 	} else {
533 		inst_index = 0;
534 	}
535 
536 	result = bt_tbs_client_read_technology(default_conn, inst_index);
537 	if (result != 0) {
538 		shell_print(sh, "Fail: %d", result);
539 	}
540 
541 	return result;
542 }
543 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
544 
545 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST)
cmd_tbs_client_read_uri_list(const struct shell * sh,size_t argc,char * argv[])546 static int cmd_tbs_client_read_uri_list(const struct shell *sh, size_t argc,
547 					char *argv[])
548 {
549 	unsigned long inst_index;
550 	int result = 0;
551 
552 	if (argc > 1) {
553 		if (strcmp(argv[1], "gtbs") == 0) {
554 			inst_index = BT_TBS_GTBS_INDEX;
555 		} else {
556 			inst_index = shell_strtoul(argv[1], 0, &result);
557 			if (result != 0) {
558 				shell_error(sh,
559 					    "Failed to parse inst_index: %d",
560 					    result);
561 
562 				return -ENOEXEC;
563 			}
564 
565 			if (inst_index > UINT8_MAX) {
566 				shell_error(sh, "Invalid index: %lu",
567 					    inst_index);
568 
569 				return -ENOEXEC;
570 			}
571 		}
572 	} else {
573 		inst_index = 0;
574 	}
575 
576 	result = bt_tbs_client_read_uri_list(default_conn, inst_index);
577 	if (result != 0) {
578 		shell_print(sh, "Fail: %d", result);
579 	}
580 
581 	return result;
582 }
583 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
584 
585 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
cmd_tbs_client_read_signal_strength(const struct shell * sh,size_t argc,char * argv[])586 static int cmd_tbs_client_read_signal_strength(const struct shell *sh,
587 					       size_t argc, char *argv[])
588 {
589 	unsigned long inst_index;
590 	int result = 0;
591 
592 	if (argc > 1) {
593 		if (strcmp(argv[1], "gtbs") == 0) {
594 			inst_index = BT_TBS_GTBS_INDEX;
595 		} else {
596 			inst_index = shell_strtoul(argv[1], 0, &result);
597 			if (result != 0) {
598 				shell_error(sh,
599 					    "Failed to parse inst_index: %d",
600 					    result);
601 
602 				return -ENOEXEC;
603 			}
604 
605 			if (inst_index > UINT8_MAX) {
606 				shell_error(sh, "Invalid index: %lu",
607 					    inst_index);
608 
609 				return -ENOEXEC;
610 			}
611 		}
612 	} else {
613 		inst_index = 0;
614 	}
615 
616 	result = bt_tbs_client_read_signal_strength(default_conn, inst_index);
617 	if (result != 0) {
618 		shell_print(sh, "Fail: %d", result);
619 	}
620 
621 	return result;
622 }
623 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
624 
625 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL)
cmd_tbs_client_read_signal_interval(const struct shell * sh,size_t argc,char * argv[])626 static int cmd_tbs_client_read_signal_interval(const struct shell *sh,
627 					       size_t argc, char *argv[])
628 {
629 	unsigned long inst_index;
630 	int result = 0;
631 
632 	if (argc > 1) {
633 		if (strcmp(argv[1], "gtbs") == 0) {
634 			inst_index = BT_TBS_GTBS_INDEX;
635 		} else {
636 			inst_index = shell_strtoul(argv[1], 0, &result);
637 			if (result != 0) {
638 				shell_error(sh,
639 					    "Failed to parse inst_index: %d",
640 					    result);
641 
642 				return -ENOEXEC;
643 			}
644 
645 			if (inst_index > UINT8_MAX) {
646 				shell_error(sh, "Invalid index: %lu",
647 					    inst_index);
648 
649 				return -ENOEXEC;
650 			}
651 		}
652 	} else {
653 		inst_index = 0;
654 	}
655 
656 	result = bt_tbs_client_read_signal_interval(default_conn, inst_index);
657 	if (result != 0) {
658 		shell_print(sh, "Fail: %d", result);
659 	}
660 
661 	return result;
662 }
663 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */
664 
665 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
cmd_tbs_client_read_current_calls(const struct shell * sh,size_t argc,char * argv[])666 static int cmd_tbs_client_read_current_calls(const struct shell *sh,
667 					     size_t argc, char *argv[])
668 {
669 	unsigned long inst_index;
670 	int result = 0;
671 
672 	if (argc > 1) {
673 		if (strcmp(argv[1], "gtbs") == 0) {
674 			inst_index = BT_TBS_GTBS_INDEX;
675 		} else {
676 			inst_index = shell_strtoul(argv[1], 0, &result);
677 			if (result != 0) {
678 				shell_error(sh,
679 					    "Failed to parse inst_index: %d",
680 					    result);
681 
682 				return -ENOEXEC;
683 			}
684 
685 			if (inst_index > UINT8_MAX) {
686 				shell_error(sh, "Invalid index: %lu",
687 					    inst_index);
688 
689 				return -ENOEXEC;
690 			}
691 		}
692 	} else {
693 		inst_index = 0;
694 	}
695 
696 	result = bt_tbs_client_read_current_calls(default_conn, inst_index);
697 	if (result != 0) {
698 		shell_print(sh, "Fail: %d", result);
699 	}
700 
701 	return result;
702 }
703 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
704 
705 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
cmd_tbs_client_read_ccid(const struct shell * sh,size_t argc,char * argv[])706 static int cmd_tbs_client_read_ccid(const struct shell *sh, size_t argc,
707 				    char *argv[])
708 {
709 	unsigned long inst_index;
710 	int result = 0;
711 
712 	if (argc > 1) {
713 		if (strcmp(argv[1], "gtbs") == 0) {
714 			inst_index = BT_TBS_GTBS_INDEX;
715 		} else {
716 			inst_index = shell_strtoul(argv[1], 0, &result);
717 			if (result != 0) {
718 				shell_error(sh,
719 					    "Failed to parse inst_index: %d",
720 					    result);
721 
722 				return -ENOEXEC;
723 			}
724 
725 			if (inst_index > UINT8_MAX) {
726 				shell_error(sh, "Invalid index: %lu",
727 					    inst_index);
728 
729 				return -ENOEXEC;
730 			}
731 		}
732 	} else {
733 		inst_index = 0;
734 	}
735 
736 	result = bt_tbs_client_read_ccid(default_conn, inst_index);
737 	if (result != 0) {
738 		shell_print(sh, "Fail: %d", result);
739 	}
740 
741 	return result;
742 }
743 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
744 
745 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
cmd_tbs_client_read_uri(const struct shell * sh,size_t argc,char * argv[])746 static int cmd_tbs_client_read_uri(const struct shell *sh, size_t argc,
747 				   char *argv[])
748 {
749 	unsigned long inst_index;
750 	int result = 0;
751 
752 	if (argc > 1) {
753 		if (strcmp(argv[1], "gtbs") == 0) {
754 			inst_index = BT_TBS_GTBS_INDEX;
755 		} else {
756 			inst_index = shell_strtoul(argv[1], 0, &result);
757 			if (result != 0) {
758 				shell_error(sh,
759 					    "Failed to parse inst_index: %d",
760 					    result);
761 
762 				return -ENOEXEC;
763 			}
764 
765 			if (inst_index > UINT8_MAX) {
766 				shell_error(sh, "Invalid index: %lu",
767 					    inst_index);
768 
769 				return -ENOEXEC;
770 			}
771 		}
772 	} else {
773 		inst_index = 0;
774 	}
775 
776 	result = bt_tbs_client_read_call_uri(default_conn, inst_index);
777 	if (result != 0) {
778 		shell_print(sh, "Fail: %d", result);
779 	}
780 
781 	return result;
782 }
783 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
784 
785 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
cmd_tbs_client_read_status_flags(const struct shell * sh,size_t argc,char * argv[])786 static int cmd_tbs_client_read_status_flags(const struct shell *sh, size_t argc,
787 					    char *argv[])
788 {
789 	unsigned long inst_index;
790 	int result = 0;
791 
792 	if (argc > 1) {
793 		if (strcmp(argv[1], "gtbs") == 0) {
794 			inst_index = BT_TBS_GTBS_INDEX;
795 		} else {
796 			inst_index = shell_strtoul(argv[1], 0, &result);
797 			if (result != 0) {
798 				shell_error(sh,
799 					    "Failed to parse inst_index: %d",
800 					    result);
801 
802 				return -ENOEXEC;
803 			}
804 
805 			if (inst_index > UINT8_MAX) {
806 				shell_error(sh, "Invalid index: %lu",
807 					    inst_index);
808 
809 				return -ENOEXEC;
810 			}
811 		}
812 	} else {
813 		inst_index = 0;
814 	}
815 
816 	result = bt_tbs_client_read_status_flags(default_conn, inst_index);
817 	if (result != 0) {
818 		shell_print(sh, "Fail: %d", result);
819 	}
820 
821 	return result;
822 }
823 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
824 
cmd_tbs_client_read_call_state(const struct shell * sh,size_t argc,char * argv[])825 static int cmd_tbs_client_read_call_state(const struct shell *sh, size_t argc,
826 					  char *argv[])
827 {
828 	unsigned long inst_index;
829 	int result = 0;
830 
831 	if (argc > 1) {
832 		if (strcmp(argv[1], "gtbs") == 0) {
833 			inst_index = BT_TBS_GTBS_INDEX;
834 		} else {
835 			inst_index = shell_strtoul(argv[1], 0, &result);
836 			if (result != 0) {
837 				shell_error(sh,
838 					    "Failed to parse inst_index: %d",
839 					    result);
840 
841 				return -ENOEXEC;
842 			}
843 
844 			if (inst_index > UINT8_MAX) {
845 				shell_error(sh, "Invalid index: %lu",
846 					    inst_index);
847 
848 				return -ENOEXEC;
849 			}
850 		}
851 	} else {
852 		inst_index = 0;
853 	}
854 
855 	result = bt_tbs_client_read_call_state(default_conn, inst_index);
856 	if (result != 0) {
857 		shell_print(sh, "Fail: %d", result);
858 	}
859 
860 	return result;
861 }
862 
863 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
cmd_tbs_client_read_remote_uri(const struct shell * sh,size_t argc,char * argv[])864 static int cmd_tbs_client_read_remote_uri(const struct shell *sh, size_t argc,
865 					  char *argv[])
866 {
867 	unsigned long inst_index;
868 	int result = 0;
869 
870 	if (argc > 1) {
871 		if (strcmp(argv[1], "gtbs") == 0) {
872 			inst_index = BT_TBS_GTBS_INDEX;
873 		} else {
874 			inst_index = shell_strtoul(argv[1], 0, &result);
875 			if (result != 0) {
876 				shell_error(sh,
877 					    "Failed to parse inst_index: %d",
878 					    result);
879 
880 				return -ENOEXEC;
881 			}
882 
883 			if (inst_index > UINT8_MAX) {
884 				shell_error(sh, "Invalid index: %lu",
885 					    inst_index);
886 
887 				return -ENOEXEC;
888 			}
889 		}
890 	} else {
891 		inst_index = 0;
892 	}
893 
894 	result = bt_tbs_client_read_remote_uri(default_conn, inst_index);
895 	if (result != 0) {
896 		shell_print(sh, "Fail: %d", result);
897 	}
898 
899 	return result;
900 }
901 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
902 
903 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
cmd_tbs_client_read_friendly_name(const struct shell * sh,size_t argc,char * argv[])904 static int cmd_tbs_client_read_friendly_name(const struct shell *sh,
905 					     size_t argc, char *argv[])
906 {
907 	unsigned long inst_index;
908 	int result = 0;
909 
910 	if (argc > 1) {
911 		if (strcmp(argv[1], "gtbs") == 0) {
912 			inst_index = BT_TBS_GTBS_INDEX;
913 		} else {
914 			inst_index = shell_strtoul(argv[1], 0, &result);
915 			if (result != 0) {
916 				shell_error(sh,
917 					    "Failed to parse inst_index: %d",
918 					    result);
919 
920 				return -ENOEXEC;
921 			}
922 
923 			if (inst_index > UINT8_MAX) {
924 				shell_error(sh, "Invalid index: %lu",
925 					    inst_index);
926 
927 				return -ENOEXEC;
928 			}
929 		}
930 	} else {
931 		inst_index = 0;
932 	}
933 
934 	result = bt_tbs_client_read_friendly_name(default_conn, inst_index);
935 	if (result != 0) {
936 		shell_print(sh, "Fail: %d", result);
937 	}
938 
939 	return result;
940 }
941 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
942 
943 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
cmd_tbs_client_read_optional_opcodes(const struct shell * sh,size_t argc,char * argv[])944 static int cmd_tbs_client_read_optional_opcodes(const struct shell *sh,
945 						size_t argc, char *argv[])
946 {
947 	unsigned long inst_index;
948 	int result = 0;
949 
950 	if (argc > 1) {
951 		if (strcmp(argv[1], "gtbs") == 0) {
952 			inst_index = BT_TBS_GTBS_INDEX;
953 		} else {
954 			inst_index = shell_strtoul(argv[1], 0, &result);
955 			if (result != 0) {
956 				shell_error(sh,
957 					    "Failed to parse inst_index: %d",
958 					    result);
959 
960 				return -ENOEXEC;
961 			}
962 
963 			if (inst_index > UINT8_MAX) {
964 				shell_error(sh, "Invalid index: %lu",
965 					    inst_index);
966 
967 				return -ENOEXEC;
968 			}
969 		}
970 	} else {
971 		inst_index = 0;
972 	}
973 
974 	result = bt_tbs_client_read_optional_opcodes(default_conn, inst_index);
975 	if (result != 0) {
976 		shell_print(sh, "Fail: %d", result);
977 	}
978 
979 	return result;
980 }
981 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
982 
cmd_tbs_client(const struct shell * sh,size_t argc,char ** argv)983 static int cmd_tbs_client(const struct shell *sh, size_t argc, char **argv)
984 {
985 	if (argc > 1) {
986 		shell_error(sh, "%s unknown parameter: %s",
987 			    argv[0], argv[1]);
988 	} else {
989 		shell_error(sh, "%s Missing subcommand", argv[0]);
990 	}
991 
992 	return -ENOEXEC;
993 }
994 
995 SHELL_STATIC_SUBCMD_SET_CREATE(tbs_client_cmds,
996 	SHELL_CMD_ARG(discover, NULL,
997 		      "Discover TBS",
998 		      cmd_tbs_client_discover, 1, 0),
999 
1000 #if defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL)
1001 	SHELL_CMD_ARG(set_signal_reporting_interval, NULL,
1002 		      "Set the signal reporting interval "
1003 		      "[<{instance_index, gtbs}>] <interval>",
1004 		      cmd_tbs_client_set_signal_strength_interval, 2, 1),
1005 #endif /* defined(CONFIG_BT_TBS_CLIENT_SET_BEARER_SIGNAL_INTERVAL) */
1006 #if defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL)
1007 	SHELL_CMD_ARG(originate, NULL,
1008 		      "Originate a call [<{instance_index, gtbs}>] <uri>",
1009 		      cmd_tbs_client_originate, 2, 1),
1010 #endif /* defined(CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL) */
1011 #if defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL)
1012 	SHELL_CMD_ARG(terminate, NULL,
1013 		      "terminate a call [<{instance_index, gtbs}>] <id>",
1014 		      cmd_tbs_client_terminate, 2, 1),
1015 #endif /* defined(CONFIG_BT_TBS_CLIENT_TERMINATE_CALL) */
1016 #if defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL)
1017 	SHELL_CMD_ARG(accept, NULL,
1018 		      "Accept a call [<{instance_index, gtbs}>] <id>",
1019 		      cmd_tbs_client_accept, 2, 1),
1020 #endif /* defined(CONFIG_BT_TBS_CLIENT_ACCEPT_CALL) */
1021 #if defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL)
1022 	SHELL_CMD_ARG(hold, NULL,
1023 		      "Place a call on hold [<{instance_index, gtbs}>] <id>",
1024 		      cmd_tbs_client_hold, 2, 1),
1025 #endif /* defined(CONFIG_BT_TBS_CLIENT_HOLD_CALL) */
1026 
1027 #if defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL)
1028 	SHELL_CMD_ARG(retrieve, NULL,
1029 		      "Retrieve a held call [<{instance_index, gtbs}>] <id>",
1030 		      cmd_tbs_client_retrieve, 2, 1),
1031 #endif /* defined(CONFIG_BT_TBS_CLIENT_RETRIEVE_CALL) */
1032 #if defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS)
1033 	SHELL_CMD_ARG(join, NULL,
1034 		      "Join calls <{instance_index, gtbs}> "
1035 		      "<id> <id> [<id> [<id> [...]]]",
1036 		      cmd_tbs_client_join, 4,
1037 		      CONFIG_BT_TBS_CLIENT_MAX_CALLS - 2),
1038 #endif /* defined(CONFIG_BT_TBS_CLIENT_JOIN_CALLS) */
1039 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME)
1040 	SHELL_CMD_ARG(read_provider_name, NULL,
1041 		      "Read the bearer name [<{instance_index, gtbs}>]",
1042 		      cmd_tbs_client_read_bearer_provider_name, 1, 1),
1043 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_PROVIDER_NAME) */
1044 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI)
1045 	SHELL_CMD_ARG(read_bearer_uci, NULL,
1046 		      "Read the bearer UCI [<{instance_index, gtbs}>]",
1047 		      cmd_tbs_client_read_bearer_uci, 1, 1),
1048 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_UCI) */
1049 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY)
1050 	SHELL_CMD_ARG(read_technology, NULL,
1051 		      "Read the bearer technology [<{instance_index, gtbs}>]",
1052 		      cmd_tbs_client_read_technology, 1, 1),
1053 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_TECHNOLOGY) */
1054 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST)
1055 	SHELL_CMD_ARG(read_uri_list, NULL,
1056 		      "Read the bearer's supported URI list "
1057 		      "[<{instance_index, gtbs}>]",
1058 		      cmd_tbs_client_read_uri_list, 1, 1),
1059 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST) */
1060 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH)
1061 	SHELL_CMD_ARG(read_signal_strength, NULL,
1062 		      "Read the bearer signal strength "
1063 		      "[<{instance_index, gtbs}>]",
1064 		      cmd_tbs_client_read_signal_strength, 1, 1),
1065 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_SIGNAL_STRENGTH) */
1066 #if defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL)
1067 	SHELL_CMD_ARG(read_signal_interval, NULL,
1068 		      "Read the bearer signal strength reporting interval "
1069 		      "[<{instance_index, gtbs}>]",
1070 		      cmd_tbs_client_read_signal_interval, 1, 1),
1071 #endif /* defined(CONFIG_BT_TBS_CLIENT_READ_BEARER_SIGNAL_INTERVAL) */
1072 #if defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS)
1073 	SHELL_CMD_ARG(read_current_calls, NULL,
1074 		      "Read the current calls [<{instance_index, gtbs}>]",
1075 		      cmd_tbs_client_read_current_calls, 1, 1),
1076 #endif /* defined(CONFIG_BT_TBS_CLIENT_BEARER_LIST_CURRENT_CALLS) */
1077 #if defined(CONFIG_BT_TBS_CLIENT_CCID)
1078 	SHELL_CMD_ARG(read_ccid, NULL,
1079 		      "Read the CCID [<{instance_index, gtbs}>]",
1080 		      cmd_tbs_client_read_ccid, 1, 1),
1081 #endif /* defined(CONFIG_BT_TBS_CLIENT_CCID) */
1082 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI)
1083 	SHELL_CMD_ARG(read_uri, NULL,
1084 		      "Read the incoming call target URI "
1085 		      "[<{instance_index, gtbs}>]",
1086 		      cmd_tbs_client_read_uri, 1, 1),
1087 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_URI) */
1088 #if defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS)
1089 	SHELL_CMD_ARG(read_status_flags, NULL,
1090 		      "Read the in feature and status value "
1091 		      "[<{instance_index, gtbs}>]",
1092 		      cmd_tbs_client_read_status_flags, 1, 1),
1093 #endif /* defined(CONFIG_BT_TBS_CLIENT_STATUS_FLAGS) */
1094 	SHELL_CMD_ARG(read_call_state, NULL,
1095 		      "Read the call state [<{instance_index, gtbs}>]",
1096 		      cmd_tbs_client_read_call_state, 1, 1),
1097 #if defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL)
1098 	SHELL_CMD_ARG(read_remote_uri, NULL,
1099 		      "Read the incoming remote URI [<{instance_index, gtbs}>]",
1100 		      cmd_tbs_client_read_remote_uri, 1, 1),
1101 #endif /* defined(CONFIG_BT_TBS_CLIENT_INCOMING_CALL) */
1102 #if defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME)
1103 	SHELL_CMD_ARG(read_friendly_name, NULL,
1104 		      "Read the friendly name of an incoming call "
1105 		      "[<{instance_index, gtbs}>]",
1106 		      cmd_tbs_client_read_friendly_name, 1, 1),
1107 #endif /* defined(CONFIG_BT_TBS_CLIENT_CALL_FRIENDLY_NAME) */
1108 #if defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES)
1109 	SHELL_CMD_ARG(read_optional_opcodes, NULL,
1110 		      "Read the optional opcodes [<{instance_index, gtbs}>]",
1111 		      cmd_tbs_client_read_optional_opcodes, 1, 1),
1112 #endif /* defined(CONFIG_BT_TBS_CLIENT_OPTIONAL_OPCODES) */
1113 	SHELL_SUBCMD_SET_END
1114 );
1115 
1116 SHELL_CMD_ARG_REGISTER(tbs_client, &tbs_client_cmds,
1117 		       "Bluetooth TBS_CLIENT shell commands",
1118 		       cmd_tbs_client, 1, 1);
1119