1 /** @file
2  *  @brief Media Control Client shell implementation
3  *
4  */
5 
6 /*
7  * Copyright (c) 2020 - 2021 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/mcc.h>
20 #include <zephyr/bluetooth/audio/mcs.h>
21 #include <zephyr/bluetooth/audio/media_proxy.h>
22 #include <zephyr/bluetooth/bluetooth.h>
23 #include <zephyr/bluetooth/conn.h>
24 #include <zephyr/bluetooth/services/ots.h>
25 #include <zephyr/logging/log.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/shell/shell.h>
28 #include <zephyr/shell/shell_string_conv.h>
29 #include <zephyr/sys/util.h>
30 
31 #include "host/shell/bt.h"
32 #include "common/bt_shell_private.h"
33 
34 #include "../media_proxy_internal.h"
35 
36 LOG_MODULE_REGISTER(bt_mcc_shell, CONFIG_BT_MCC_LOG_LEVEL);
37 
38 static struct bt_mcc_cb cb;
39 
40 #ifdef CONFIG_BT_MCC_OTS
41 struct object_ids_t {
42 	uint64_t icon_obj_id;
43 	uint64_t track_segments_obj_id;
44 	uint64_t current_track_obj_id;
45 	uint64_t next_track_obj_id;
46 	uint64_t parent_group_obj_id;
47 	uint64_t current_group_obj_id;
48 	uint64_t search_results_obj_id;
49 };
50 static struct object_ids_t obj_ids;
51 #endif /* CONFIG_BT_MCC_OTS */
52 
53 
mcc_discover_mcs_cb(struct bt_conn * conn,int err)54 static void mcc_discover_mcs_cb(struct bt_conn *conn, int err)
55 {
56 	if (err) {
57 		bt_shell_error("Discovery failed (%d)", err);
58 		return;
59 	}
60 
61 	bt_shell_print("Discovery complete");
62 }
63 
mcc_read_player_name_cb(struct bt_conn * conn,int err,const char * name)64 static void mcc_read_player_name_cb(struct bt_conn *conn, int err, const char *name)
65 {
66 	if (err) {
67 		bt_shell_error("Player Name read failed (%d)", err);
68 		return;
69 	}
70 
71 	bt_shell_print("Player name: %s", name);
72 }
73 
74 #ifdef CONFIG_BT_MCC_OTS
mcc_read_icon_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)75 static void mcc_read_icon_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
76 {
77 	char str[BT_OTS_OBJ_ID_STR_LEN];
78 
79 	if (err) {
80 		bt_shell_error("Icon Object ID read failed (%d)", err);
81 		return;
82 	}
83 
84 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
85 	bt_shell_print("Icon object ID: %s", str);
86 
87 	obj_ids.icon_obj_id = id;
88 }
89 #endif /* CONFIG_BT_MCC_OTS */
90 
91 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
mcc_read_icon_url_cb(struct bt_conn * conn,int err,const char * url)92 static void mcc_read_icon_url_cb(struct bt_conn *conn, int err, const char *url)
93 {
94 	if (err) {
95 		bt_shell_error("Icon URL read failed (%d)", err);
96 		return;
97 	}
98 
99 	bt_shell_print("Icon URL: 0x%s", url);
100 }
101 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
102 
103 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
mcc_read_track_title_cb(struct bt_conn * conn,int err,const char * title)104 static void mcc_read_track_title_cb(struct bt_conn *conn, int err, const char *title)
105 {
106 	if (err) {
107 		bt_shell_error("Track title read failed (%d)", err);
108 		return;
109 	}
110 
111 	bt_shell_print("Track title: %s", title);
112 }
113 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
114 
mcc_track_changed_ntf_cb(struct bt_conn * conn,int err)115 static void mcc_track_changed_ntf_cb(struct bt_conn *conn, int err)
116 {
117 	if (err) {
118 		bt_shell_error("Track changed notification failed (%d)", err);
119 		return;
120 	}
121 
122 	bt_shell_print("Track changed");
123 }
124 
125 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
mcc_read_track_duration_cb(struct bt_conn * conn,int err,int32_t dur)126 static void mcc_read_track_duration_cb(struct bt_conn *conn, int err, int32_t dur)
127 {
128 	if (err) {
129 		bt_shell_error("Track duration read failed (%d)", err);
130 		return;
131 	}
132 
133 	bt_shell_print("Track duration: %d", dur);
134 }
135 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
136 
137 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
mcc_read_track_position_cb(struct bt_conn * conn,int err,int32_t pos)138 static void mcc_read_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
139 {
140 	if (err) {
141 		bt_shell_error("Track position read failed (%d)", err);
142 		return;
143 	}
144 
145 	bt_shell_print("Track Position: %d", pos);
146 }
147 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
148 
149 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
mcc_set_track_position_cb(struct bt_conn * conn,int err,int32_t pos)150 static void mcc_set_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
151 {
152 	if (err) {
153 		bt_shell_error("Track Position set failed (%d)", err);
154 		return;
155 	}
156 
157 	bt_shell_print("Track Position: %d", pos);
158 }
159 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
160 
161 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
mcc_read_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)162 static void mcc_read_playback_speed_cb(struct bt_conn *conn, int err,
163 				       int8_t speed)
164 {
165 	if (err) {
166 		bt_shell_error("Playback speed read failed (%d)", err);
167 		return;
168 	}
169 
170 	bt_shell_print("Playback speed: %d", speed);
171 }
172 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
173 
174 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
mcc_set_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)175 static void mcc_set_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed)
176 {
177 	if (err) {
178 		bt_shell_error("Playback speed set failed (%d)", err);
179 		return;
180 	}
181 
182 	bt_shell_print("Playback speed: %d", speed);
183 }
184 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
185 
186 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
mcc_read_seeking_speed_cb(struct bt_conn * conn,int err,int8_t speed)187 static void mcc_read_seeking_speed_cb(struct bt_conn *conn, int err,
188 				      int8_t speed)
189 {
190 	if (err) {
191 		bt_shell_error("Seeking speed read failed (%d)", err);
192 		return;
193 	}
194 
195 	bt_shell_print("Seeking speed: %d", speed);
196 }
197 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
198 
199 
200 #ifdef CONFIG_BT_MCC_OTS
mcc_read_segments_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)201 static void mcc_read_segments_obj_id_cb(struct bt_conn *conn, int err,
202 					uint64_t id)
203 {
204 	char str[BT_OTS_OBJ_ID_STR_LEN];
205 
206 	if (err) {
207 		bt_shell_error("Track Segments Object ID read failed (%d)", err);
208 		return;
209 	}
210 
211 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
212 	bt_shell_print("Track Segments Object ID: %s", str);
213 
214 	obj_ids.track_segments_obj_id = id;
215 }
216 
217 
mcc_read_current_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)218 static void mcc_read_current_track_obj_id_cb(struct bt_conn *conn, int err,
219 					     uint64_t id)
220 {
221 	char str[BT_OTS_OBJ_ID_STR_LEN];
222 
223 	if (err) {
224 		bt_shell_error("Current Track Object ID read failed (%d)", err);
225 		return;
226 	}
227 
228 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
229 	bt_shell_print("Current Track Object ID: %s", str);
230 
231 	obj_ids.current_track_obj_id = id;
232 }
233 
234 
mcc_set_current_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)235 static void mcc_set_current_track_obj_id_cb(struct bt_conn *conn, int err,
236 					    uint64_t id)
237 {
238 	char str[BT_OTS_OBJ_ID_STR_LEN];
239 
240 	if (err) {
241 		bt_shell_error("Current Track Object ID set failed (%d)", err);
242 		return;
243 	}
244 
245 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
246 	bt_shell_print("Current Track Object ID written: %s", str);
247 }
248 
249 
mcc_read_next_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)250 static void mcc_read_next_track_obj_id_cb(struct bt_conn *conn, int err,
251 					  uint64_t id)
252 {
253 	char str[BT_OTS_OBJ_ID_STR_LEN];
254 
255 	if (err) {
256 		bt_shell_error("Next Track Object ID read failed (%d)", err);
257 		return;
258 	}
259 
260 	if (id == MPL_NO_TRACK_ID) {
261 		bt_shell_print("Next Track Object ID is empty");
262 	} else {
263 		(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
264 		bt_shell_print("Next Track Object ID: %s", str);
265 	}
266 
267 	obj_ids.next_track_obj_id = id;
268 }
269 
270 
mcc_set_next_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)271 static void mcc_set_next_track_obj_id_cb(struct bt_conn *conn, int err,
272 					    uint64_t id)
273 {
274 	char str[BT_OTS_OBJ_ID_STR_LEN];
275 
276 	if (err) {
277 		bt_shell_error("Next Track Object ID set failed (%d)", err);
278 		return;
279 	}
280 
281 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
282 	bt_shell_print("Next Track Object ID written: %s", str);
283 }
284 
285 
mcc_read_parent_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)286 static void mcc_read_parent_group_obj_id_cb(struct bt_conn *conn, int err,
287 					    uint64_t id)
288 {
289 	char str[BT_OTS_OBJ_ID_STR_LEN];
290 
291 	if (err) {
292 		bt_shell_error("Parent Group Object ID read failed (%d)", err);
293 		return;
294 	}
295 
296 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
297 	bt_shell_print("Parent Group Object ID: %s", str);
298 
299 	obj_ids.parent_group_obj_id = id;
300 }
301 
302 
mcc_read_current_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)303 static void mcc_read_current_group_obj_id_cb(struct bt_conn *conn, int err,
304 					     uint64_t id)
305 {
306 	char str[BT_OTS_OBJ_ID_STR_LEN];
307 
308 	if (err) {
309 		bt_shell_error("Current Group Object ID read failed (%d)", err);
310 		return;
311 	}
312 
313 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
314 	bt_shell_print("Current Group Object ID: %s", str);
315 
316 	obj_ids.current_group_obj_id = id;
317 }
318 
mcc_set_current_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)319 static void mcc_set_current_group_obj_id_cb(struct bt_conn *conn, int err,
320 					    uint64_t id)
321 {
322 	char str[BT_OTS_OBJ_ID_STR_LEN];
323 
324 	if (err) {
325 		bt_shell_error("Current Group Object ID set failed (%d)", err);
326 		return;
327 	}
328 
329 	(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
330 	bt_shell_print("Current Group Object ID written: %s", str);
331 }
332 #endif /* CONFIG_BT_MCC_OTS */
333 
334 
335 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
mcc_read_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)336 static void mcc_read_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
337 {
338 	if (err) {
339 		bt_shell_error("Playing order read failed (%d)", err);
340 		return;
341 	}
342 
343 	bt_shell_print("Playing order: %d", order);
344 }
345 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
346 
347 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
mcc_set_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)348 static void mcc_set_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
349 {
350 	if (err) {
351 		bt_shell_error("Playing order set failed (%d)", err);
352 		return;
353 	}
354 
355 	bt_shell_print("Playing order: %d", order);
356 }
357 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
358 
359 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
mcc_read_playing_orders_supported_cb(struct bt_conn * conn,int err,uint16_t orders)360 static void mcc_read_playing_orders_supported_cb(struct bt_conn *conn, int err,
361 						 uint16_t orders)
362 {
363 	if (err) {
364 		bt_shell_error("Playing orders supported read failed (%d)", err);
365 		return;
366 	}
367 
368 	bt_shell_print("Playing orders supported: %d", orders);
369 }
370 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
371 
372 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
mcc_read_media_state_cb(struct bt_conn * conn,int err,uint8_t state)373 static void mcc_read_media_state_cb(struct bt_conn *conn, int err, uint8_t state)
374 {
375 	if (err) {
376 		bt_shell_error("Media State read failed (%d)", err);
377 		return;
378 	}
379 
380 	bt_shell_print("Media State: %d", state);
381 }
382 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
383 
384 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
mcc_send_cmd_cb(struct bt_conn * conn,int err,const struct mpl_cmd * cmd)385 static void mcc_send_cmd_cb(struct bt_conn *conn, int err, const struct mpl_cmd *cmd)
386 {
387 	if (err) {
388 		bt_shell_error("Command send failed (%d) - opcode: %d, param: %d",
389 			       err, cmd->opcode, cmd->param);
390 		return;
391 	}
392 
393 	bt_shell_print("Command opcode: %d, param: %d", cmd->opcode, cmd->param);
394 }
395 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
396 
mcc_cmd_ntf_cb(struct bt_conn * conn,int err,const struct mpl_cmd_ntf * ntf)397 static void mcc_cmd_ntf_cb(struct bt_conn *conn, int err,
398 			   const struct mpl_cmd_ntf *ntf)
399 {
400 	if (err) {
401 		bt_shell_error("Command notification error (%d) - opcode: %d, result: %d",
402 			       err, ntf->requested_opcode, ntf->result_code);
403 		return;
404 	}
405 
406 	bt_shell_print("Command opcode: %d, result: %d",
407 		       ntf->requested_opcode, ntf->result_code);
408 }
409 
410 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
mcc_read_opcodes_supported_cb(struct bt_conn * conn,int err,uint32_t opcodes)411 static void mcc_read_opcodes_supported_cb(struct bt_conn *conn, int err,
412 					    uint32_t opcodes)
413 {
414 	if (err) {
415 		bt_shell_error("Opcodes supported read failed (%d)", err);
416 		return;
417 	}
418 
419 	bt_shell_print("Opcodes supported: %d", opcodes);
420 }
421 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
422 
423 #ifdef CONFIG_BT_MCC_OTS
mcc_send_search_cb(struct bt_conn * conn,int err,const struct mpl_search * search)424 static void mcc_send_search_cb(struct bt_conn *conn, int err,
425 			       const struct mpl_search *search)
426 {
427 	if (err) {
428 		bt_shell_error("Search send failed (%d)", err);
429 		return;
430 	}
431 
432 	bt_shell_print("Search sent");
433 }
434 
mcc_search_ntf_cb(struct bt_conn * conn,int err,uint8_t result_code)435 static void mcc_search_ntf_cb(struct bt_conn *conn, int err, uint8_t result_code)
436 {
437 	if (err) {
438 		bt_shell_error("Search notification error (%d), result code: %d",
439 			       err, result_code);
440 		return;
441 	}
442 
443 	bt_shell_print("Search notification result code: %d", result_code);
444 }
445 
mcc_read_search_results_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)446 static void mcc_read_search_results_obj_id_cb(struct bt_conn *conn, int err,
447 					      uint64_t id)
448 {
449 	char str[BT_OTS_OBJ_ID_STR_LEN];
450 
451 	if (err) {
452 		bt_shell_error("Search Results Object ID read failed (%d)", err);
453 		return;
454 	}
455 
456 	if (id == 0) {
457 		bt_shell_print("Search Results Object ID: 0x000000000000");
458 	} else {
459 		(void)bt_ots_obj_id_to_str(id, str, sizeof(str));
460 		bt_shell_print("Search Results Object ID: %s", str);
461 	}
462 
463 	obj_ids.search_results_obj_id = id;
464 }
465 #endif /* CONFIG_BT_MCC_OTS */
466 
467 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
mcc_read_content_control_id_cb(struct bt_conn * conn,int err,uint8_t ccid)468 static void mcc_read_content_control_id_cb(struct bt_conn *conn, int err, uint8_t ccid)
469 {
470 	if (err) {
471 		bt_shell_error("Content Control ID read failed (%d)", err);
472 		return;
473 	}
474 
475 	bt_shell_print("Content Control ID: %d", ccid);
476 }
477 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
478 
479 #ifdef CONFIG_BT_MCC_OTS
480 /**** Callback functions for the included Object Transfer service *************/
mcc_otc_obj_selected_cb(struct bt_conn * conn,int err)481 static void mcc_otc_obj_selected_cb(struct bt_conn *conn, int err)
482 {
483 	if (err) {
484 		bt_shell_error("Error in selecting object (err %d)", err);
485 		return;
486 	}
487 
488 	bt_shell_print("Selecting object succeeded");
489 }
490 
mcc_otc_obj_metadata_cb(struct bt_conn * conn,int err)491 static void mcc_otc_obj_metadata_cb(struct bt_conn *conn, int err)
492 {
493 	if (err) {
494 		bt_shell_error("Error in reading object metadata (err %d)", err);
495 		return;
496 	}
497 
498 	bt_shell_print("Reading object metadata succeeded\n");
499 }
500 
mcc_icon_object_read_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)501 static void mcc_icon_object_read_cb(struct bt_conn *conn, int err,
502 				    struct net_buf_simple *buf)
503 {
504 	if (err) {
505 		bt_shell_error("Icon Object read failed (%d)", err);
506 		return;
507 	}
508 
509 	bt_shell_print("Icon content (%d octets)", buf->len);
510 	bt_shell_hexdump(buf->data, buf->len);
511 }
512 
513 /* TODO: May want to use a parsed type, instead of the raw buf, here */
mcc_track_segments_object_read_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)514 static void mcc_track_segments_object_read_cb(struct bt_conn *conn, int err,
515 					      struct net_buf_simple *buf)
516 {
517 	if (err) {
518 		bt_shell_error("Track Segments Object read failed (%d)", err);
519 		return;
520 	}
521 
522 	bt_shell_print("Track Segments content (%d octets)", buf->len);
523 	bt_shell_hexdump(buf->data, buf->len);
524 }
525 
mcc_otc_read_current_track_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)526 static void mcc_otc_read_current_track_object_cb(struct bt_conn *conn, int err,
527 						 struct net_buf_simple *buf)
528 {
529 	if (err) {
530 		bt_shell_error("Current Track Object read failed (%d)", err);
531 		return;
532 	}
533 
534 	bt_shell_print("Current Track content (%d octets)", buf->len);
535 	bt_shell_hexdump(buf->data, buf->len);
536 }
537 
mcc_otc_read_next_track_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)538 static void mcc_otc_read_next_track_object_cb(struct bt_conn *conn, int err,
539 					      struct net_buf_simple *buf)
540 {
541 	if (err) {
542 		bt_shell_error("Next Track Object read failed (%d)", err);
543 		return;
544 	}
545 
546 	bt_shell_print("Next Track content (%d octets)", buf->len);
547 	bt_shell_hexdump(buf->data, buf->len);
548 }
549 
mcc_otc_read_parent_group_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)550 static void mcc_otc_read_parent_group_object_cb(struct bt_conn *conn, int err,
551 						struct net_buf_simple *buf)
552 {
553 	if (err) {
554 		bt_shell_error("Parent Group Object read failed (%d)", err);
555 		return;
556 	}
557 
558 	bt_shell_print("Parent Group content (%d octets)", buf->len);
559 	bt_shell_hexdump(buf->data, buf->len);
560 }
561 
mcc_otc_read_current_group_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)562 static void mcc_otc_read_current_group_object_cb(struct bt_conn *conn, int err,
563 						 struct net_buf_simple *buf)
564 {
565 	if (err) {
566 		bt_shell_error("Current Group Object read failed (%d)", err);
567 		return;
568 	}
569 
570 	bt_shell_print("Current Group content (%d octets)", buf->len);
571 	bt_shell_hexdump(buf->data, buf->len);
572 }
573 
574 #endif /* CONFIG_BT_MCC_OTS */
575 
576 
cmd_mcc_init(const struct shell * sh,size_t argc,char ** argv)577 static int cmd_mcc_init(const struct shell *sh, size_t argc, char **argv)
578 {
579 	int result;
580 
581 	/* Set up the callbacks */
582 	cb.discover_mcs                  = mcc_discover_mcs_cb;
583 	cb.read_player_name              = mcc_read_player_name_cb;
584 #ifdef CONFIG_BT_MCC_OTS
585 	cb.read_icon_obj_id              = mcc_read_icon_obj_id_cb;
586 #endif /* CONFIG_BT_MCC_OTS */
587 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
588 	cb.read_icon_url                 = mcc_read_icon_url_cb;
589 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
590 	cb.track_changed_ntf             = mcc_track_changed_ntf_cb;
591 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
592 	cb.read_track_title              = mcc_read_track_title_cb;
593 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
594 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
595 	cb.read_track_duration           = mcc_read_track_duration_cb;
596 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
597 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
598 	cb.read_track_position           = mcc_read_track_position_cb;
599 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
600 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
601 	cb.set_track_position            = mcc_set_track_position_cb;
602 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
603 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
604 	cb.read_playback_speed           = mcc_read_playback_speed_cb;
605 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
606 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
607 	cb.set_playback_speed            = mcc_set_playback_speed_cb;
608 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
609 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
610 	cb.read_seeking_speed            = mcc_read_seeking_speed_cb;
611 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
612 #ifdef CONFIG_BT_MCC_OTS
613 	cb.read_segments_obj_id          = mcc_read_segments_obj_id_cb;
614 	cb.read_current_track_obj_id     = mcc_read_current_track_obj_id_cb;
615 	cb.set_current_track_obj_id      = mcc_set_current_track_obj_id_cb;
616 	cb.read_next_track_obj_id        = mcc_read_next_track_obj_id_cb;
617 	cb.set_next_track_obj_id         = mcc_set_next_track_obj_id_cb;
618 	cb.read_parent_group_obj_id      = mcc_read_parent_group_obj_id_cb;
619 	cb.read_current_group_obj_id     = mcc_read_current_group_obj_id_cb;
620 	cb.set_current_group_obj_id      = mcc_set_current_group_obj_id_cb;
621 #endif /* CONFIG_BT_MCC_OTS */
622 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
623 	cb.read_playing_order            = mcc_read_playing_order_cb;
624 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
625 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
626 	cb.set_playing_order             = mcc_set_playing_order_cb;
627 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
628 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
629 	cb.read_playing_orders_supported = mcc_read_playing_orders_supported_cb;
630 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
631 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
632 	cb.read_media_state              = mcc_read_media_state_cb;
633 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
634 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
635 	cb.send_cmd                      = mcc_send_cmd_cb;
636 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
637 	cb.cmd_ntf                       = mcc_cmd_ntf_cb;
638 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
639 	cb.read_opcodes_supported        = mcc_read_opcodes_supported_cb;
640 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
641 #ifdef CONFIG_BT_MCC_OTS
642 	cb.send_search                   = mcc_send_search_cb;
643 	cb.search_ntf                    = mcc_search_ntf_cb;
644 	cb.read_search_results_obj_id    = mcc_read_search_results_obj_id_cb;
645 #endif /* CONFIG_BT_MCC_OTS */
646 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
647 	cb.read_content_control_id       = mcc_read_content_control_id_cb;
648 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
649 #ifdef CONFIG_BT_MCC_OTS
650 	cb.otc_obj_selected              = mcc_otc_obj_selected_cb;
651 	cb.otc_obj_metadata              = mcc_otc_obj_metadata_cb;
652 	cb.otc_icon_object               = mcc_icon_object_read_cb;
653 	cb.otc_track_segments_object     = mcc_track_segments_object_read_cb;
654 	cb.otc_current_track_object      = mcc_otc_read_current_track_object_cb;
655 	cb.otc_next_track_object         = mcc_otc_read_next_track_object_cb;
656 	cb.otc_parent_group_object       = mcc_otc_read_parent_group_object_cb;
657 	cb.otc_current_group_object      = mcc_otc_read_current_group_object_cb;
658 #endif /* CONFIG_BT_MCC_OTS */
659 
660 	/* Initialize the module */
661 	result = bt_mcc_init(&cb);
662 
663 	if (result) {
664 		shell_error(sh, "Fail: %d", result);
665 	}
666 	return result;
667 }
668 
cmd_mcc_discover_mcs(const struct shell * sh,size_t argc,char ** argv)669 static int cmd_mcc_discover_mcs(const struct shell *sh, size_t argc,
670 				char **argv)
671 {
672 	bool subscribe = true;
673 	int result = 0;
674 
675 	if (argc > 1) {
676 		subscribe = shell_strtobool(argv[1], 0, &result);
677 		if (result != 0) {
678 			shell_error(sh, "Could not parse subscribe: %d",
679 				    result);
680 
681 			return -ENOEXEC;
682 		}
683 	}
684 
685 	result = bt_mcc_discover_mcs(default_conn, (bool)subscribe);
686 	if (result) {
687 		shell_error(sh, "Fail: %d", result);
688 	}
689 	return result;
690 }
691 
cmd_mcc_read_player_name(const struct shell * sh,size_t argc,char * argv[])692 static int cmd_mcc_read_player_name(const struct shell *sh, size_t argc,
693 				    char *argv[])
694 {
695 	int result;
696 
697 	result = bt_mcc_read_player_name(default_conn);
698 	if (result) {
699 		shell_error(sh, "Fail: %d", result);
700 	}
701 	return result;
702 }
703 
704 #ifdef CONFIG_BT_MCC_OTS
cmd_mcc_read_icon_obj_id(const struct shell * sh,size_t argc,char * argv[])705 static int cmd_mcc_read_icon_obj_id(const struct shell *sh, size_t argc,
706 				    char *argv[])
707 {
708 	int result;
709 
710 	result = bt_mcc_read_icon_obj_id(default_conn);
711 	if (result) {
712 		shell_error(sh, "Fail: %d", result);
713 	}
714 	return result;
715 }
716 #endif /* CONFIG_BT_MCC_OTS */
717 
718 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
cmd_mcc_read_icon_url(const struct shell * sh,size_t argc,char * argv[])719 static int cmd_mcc_read_icon_url(const struct shell *sh, size_t argc,
720 				 char *argv[])
721 {
722 	int result;
723 
724 	result = bt_mcc_read_icon_url(default_conn);
725 	if (result) {
726 		shell_error(sh, "Fail: %d", result);
727 	}
728 	return result;
729 }
730 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
731 
732 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
cmd_mcc_read_track_title(const struct shell * sh,size_t argc,char * argv[])733 static int cmd_mcc_read_track_title(const struct shell *sh, size_t argc,
734 				    char *argv[])
735 {
736 	int result;
737 
738 	result = bt_mcc_read_track_title(default_conn);
739 	if (result) {
740 		shell_error(sh, "Fail: %d", result);
741 	}
742 	return result;
743 }
744 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
745 
746 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
cmd_mcc_read_track_duration(const struct shell * sh,size_t argc,char * argv[])747 static int cmd_mcc_read_track_duration(const struct shell *sh, size_t argc,
748 				       char *argv[])
749 {
750 	int result;
751 
752 	result = bt_mcc_read_track_duration(default_conn);
753 	if (result) {
754 		shell_error(sh, "Fail: %d", result);
755 	}
756 	return result;
757 }
758 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
759 
760 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
cmd_mcc_read_track_position(const struct shell * sh,size_t argc,char * argv[])761 static int cmd_mcc_read_track_position(const struct shell *sh, size_t argc,
762 				       char *argv[])
763 {
764 	int result;
765 
766 	result = bt_mcc_read_track_position(default_conn);
767 	if (result) {
768 		shell_error(sh, "Fail: %d", result);
769 	}
770 	return result;
771 }
772 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
773 
774 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
cmd_mcc_set_track_position(const struct shell * sh,size_t argc,char * argv[])775 static int cmd_mcc_set_track_position(const struct shell *sh, size_t argc,
776 				      char *argv[])
777 {
778 	int result = 0;
779 	long pos;
780 
781 	pos = shell_strtol(argv[1], 0, &result);
782 	if (result != 0) {
783 		shell_error(sh, "Could not parse pos: %d", result);
784 
785 		return -ENOEXEC;
786 	}
787 
788 	if (sizeof(long) != sizeof(int32_t) && !IN_RANGE(pos, INT32_MIN, INT32_MAX)) {
789 		shell_error(sh, "Invalid pos: %ld", pos);
790 
791 		return -ENOEXEC;
792 	}
793 
794 	result = bt_mcc_set_track_position(default_conn, pos);
795 	if (result) {
796 		shell_print(sh, "Fail: %d", result);
797 	}
798 	return result;
799 }
800 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
801 
802 
803 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
cmd_mcc_read_playback_speed(const struct shell * sh,size_t argc,char * argv[])804 static int cmd_mcc_read_playback_speed(const struct shell *sh, size_t argc,
805 				       char *argv[])
806 {
807 	int result;
808 
809 	result = bt_mcc_read_playback_speed(default_conn);
810 	if (result) {
811 		shell_error(sh, "Fail: %d", result);
812 	}
813 	return result;
814 }
815 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
816 
817 
818 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
cmd_mcc_set_playback_speed(const struct shell * sh,size_t argc,char * argv[])819 static int cmd_mcc_set_playback_speed(const struct shell *sh, size_t argc,
820 				      char *argv[])
821 {
822 	int result = 0;
823 	long speed;
824 
825 	speed = shell_strtol(argv[1], 0, &result);
826 	if (result != 0) {
827 		shell_error(sh, "Could not parse speed: %d", result);
828 
829 		return -ENOEXEC;
830 	}
831 
832 	if (!IN_RANGE(speed, INT8_MIN, INT8_MAX)) {
833 		shell_error(sh, "Invalid speed: %ld", speed);
834 
835 		return -ENOEXEC;
836 	}
837 
838 	result = bt_mcc_set_playback_speed(default_conn, speed);
839 	if (result) {
840 		shell_print(sh, "Fail: %d", result);
841 	}
842 	return result;
843 }
844 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
845 
846 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
cmd_mcc_read_seeking_speed(const struct shell * sh,size_t argc,char * argv[])847 static int cmd_mcc_read_seeking_speed(const struct shell *sh, size_t argc,
848 				      char *argv[])
849 {
850 	int result;
851 
852 	result = bt_mcc_read_seeking_speed(default_conn);
853 	if (result) {
854 		shell_print(sh, "Fail: %d", result);
855 	}
856 	return result;
857 }
858 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
859 
860 
861 #ifdef CONFIG_BT_MCC_OTS
cmd_mcc_read_track_segments_obj_id(const struct shell * sh,size_t argc,char * argv[])862 static int cmd_mcc_read_track_segments_obj_id(const struct shell *sh,
863 					      size_t argc, char *argv[])
864 {
865 	int result;
866 
867 	result = bt_mcc_read_segments_obj_id(default_conn);
868 	if (result) {
869 		shell_error(sh, "Fail: %d", result);
870 	}
871 	return result;
872 }
873 
874 
cmd_mcc_read_current_track_obj_id(const struct shell * sh,size_t argc,char * argv[])875 static int cmd_mcc_read_current_track_obj_id(const struct shell *sh,
876 					     size_t argc, char *argv[])
877 {
878 	int result;
879 
880 	result = bt_mcc_read_current_track_obj_id(default_conn);
881 	if (result) {
882 		shell_error(sh, "Fail: %d", result);
883 	}
884 	return result;
885 }
886 
cmd_mcc_set_current_track_obj_id(const struct shell * sh,size_t argc,char * argv[])887 static int cmd_mcc_set_current_track_obj_id(const struct shell *sh, size_t argc,
888 					    char *argv[])
889 {
890 	unsigned long long id;
891 	int result = 0;
892 
893 	id = shell_strtoull(argv[1], 0, &result);
894 	if (result != 0) {
895 		shell_error(sh, "Could not parse id: %d", result);
896 
897 		return -ENOEXEC;
898 	}
899 
900 	if (!IN_RANGE(id, BT_OTS_OBJ_ID_MIN, BT_OTS_OBJ_ID_MAX)) {
901 		shell_error(sh, "Invalid id: %llu", id);
902 
903 		return -ENOEXEC;
904 	}
905 
906 	result = bt_mcc_set_current_track_obj_id(default_conn, id);
907 	if (result) {
908 		shell_print(sh, "Fail: %d", result);
909 	}
910 	return result;
911 }
912 
cmd_mcc_read_next_track_obj_id(const struct shell * sh,size_t argc,char * argv[])913 static int cmd_mcc_read_next_track_obj_id(const struct shell *sh, size_t argc,
914 					  char *argv[])
915 {
916 	int result;
917 
918 	result = bt_mcc_read_next_track_obj_id(default_conn);
919 	if (result) {
920 		shell_error(sh, "Fail: %d", result);
921 	}
922 	return result;
923 }
924 
cmd_mcc_set_next_track_obj_id(const struct shell * sh,size_t argc,char * argv[])925 static int cmd_mcc_set_next_track_obj_id(const struct shell *sh, size_t argc,
926 					 char *argv[])
927 {
928 	unsigned long long id;
929 	int result = 0;
930 
931 	id = shell_strtoull(argv[1], 0, &result);
932 	if (result != 0) {
933 		shell_error(sh, "Could not parse id: %d", result);
934 
935 		return -ENOEXEC;
936 	}
937 
938 	if (!IN_RANGE(id, BT_OTS_OBJ_ID_MIN, BT_OTS_OBJ_ID_MAX)) {
939 		shell_error(sh, "Invalid id: %llu", id);
940 
941 		return -ENOEXEC;
942 	}
943 
944 	result = bt_mcc_set_next_track_obj_id(default_conn, id);
945 	if (result) {
946 		shell_print(sh, "Fail: %d", result);
947 	}
948 	return result;
949 }
950 
cmd_mcc_read_parent_group_obj_id(const struct shell * sh,size_t argc,char * argv[])951 static int cmd_mcc_read_parent_group_obj_id(const struct shell *sh, size_t argc,
952 					    char *argv[])
953 {
954 	int result;
955 
956 	result = bt_mcc_read_parent_group_obj_id(default_conn);
957 	if (result) {
958 		shell_error(sh, "Fail: %d", result);
959 	}
960 	return result;
961 }
962 
cmd_mcc_read_current_group_obj_id(const struct shell * sh,size_t argc,char * argv[])963 static int cmd_mcc_read_current_group_obj_id(const struct shell *sh,
964 					     size_t argc, char *argv[])
965 {
966 	int result;
967 
968 	result = bt_mcc_read_current_group_obj_id(default_conn);
969 	if (result) {
970 		shell_error(sh, "Fail: %d", result);
971 	}
972 	return result;
973 }
974 
cmd_mcc_set_current_group_obj_id(const struct shell * sh,size_t argc,char * argv[])975 static int cmd_mcc_set_current_group_obj_id(const struct shell *sh, size_t argc,
976 					    char *argv[])
977 {
978 	unsigned long long id;
979 	int result = 0;
980 
981 	id = shell_strtoull(argv[1], 0, &result);
982 	if (result != 0) {
983 		shell_error(sh, "Could not parse id: %d", result);
984 
985 		return -ENOEXEC;
986 	}
987 
988 	if (!IN_RANGE(id, BT_OTS_OBJ_ID_MIN, BT_OTS_OBJ_ID_MAX)) {
989 		shell_error(sh, "Invalid id: %llu", id);
990 
991 		return -ENOEXEC;
992 	}
993 
994 	result = bt_mcc_set_current_group_obj_id(default_conn, id);
995 	if (result) {
996 		shell_print(sh, "Fail: %d", result);
997 	}
998 	return result;
999 }
1000 #endif /* CONFIG_BT_MCC_OTS */
1001 
1002 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
cmd_mcc_read_playing_order(const struct shell * sh,size_t argc,char * argv[])1003 static int cmd_mcc_read_playing_order(const struct shell *sh, size_t argc,
1004 				      char *argv[])
1005 {
1006 	int result;
1007 
1008 	result = bt_mcc_read_playing_order(default_conn);
1009 	if (result) {
1010 		shell_error(sh, "Fail: %d", result);
1011 	}
1012 	return result;
1013 }
1014 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
1015 
1016 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
cmd_mcc_set_playing_order(const struct shell * sh,size_t argc,char * argv[])1017 static int cmd_mcc_set_playing_order(const struct shell *sh, size_t argc,
1018 				     char *argv[])
1019 {
1020 	unsigned long order;
1021 	int result = 0;
1022 
1023 	order = shell_strtoul(argv[1], 0, &result);
1024 	if (result != 0) {
1025 		shell_error(sh, "Could not parse order: %d", result);
1026 
1027 		return -ENOEXEC;
1028 	}
1029 
1030 	if (order > UINT8_MAX) {
1031 		shell_error(sh, "Invalid order: %lu", order);
1032 
1033 		return -ENOEXEC;
1034 	}
1035 
1036 	result = bt_mcc_set_playing_order(default_conn, order);
1037 	if (result) {
1038 		shell_print(sh, "Fail: %d", result);
1039 	}
1040 	return result;
1041 }
1042 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
1043 
1044 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
cmd_mcc_read_playing_orders_supported(const struct shell * sh,size_t argc,char * argv[])1045 static int cmd_mcc_read_playing_orders_supported(const struct shell *sh,
1046 						 size_t argc, char *argv[])
1047 {
1048 	int result;
1049 
1050 	result = bt_mcc_read_playing_orders_supported(default_conn);
1051 	if (result) {
1052 		shell_error(sh, "Fail: %d", result);
1053 	}
1054 	return result;
1055 }
1056 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
1057 
1058 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
cmd_mcc_read_media_state(const struct shell * sh,size_t argc,char * argv[])1059 static int cmd_mcc_read_media_state(const struct shell *sh, size_t argc,
1060 				    char *argv[])
1061 {
1062 	int result;
1063 
1064 	result = bt_mcc_read_media_state(default_conn);
1065 	if (result) {
1066 		shell_error(sh, "Fail: %d", result);
1067 	}
1068 	return result;
1069 }
1070 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
1071 
1072 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
cmd_mcc_play(const struct shell * sh,size_t argc,char * argv[])1073 static int cmd_mcc_play(const struct shell *sh, size_t argc, char *argv[])
1074 {
1075 	const struct mpl_cmd cmd = {
1076 		.opcode = BT_MCS_OPC_PLAY,
1077 		.use_param = false,
1078 		.param = 0,
1079 	};
1080 	int err;
1081 
1082 	err = bt_mcc_send_cmd(default_conn, &cmd);
1083 	if (err != 0) {
1084 		shell_error(sh, "MCC play failed: %d", err);
1085 	}
1086 
1087 	return err;
1088 }
1089 
cmd_mcc_pause(const struct shell * sh,size_t argc,char * argv[])1090 static int cmd_mcc_pause(const struct shell *sh, size_t argc, char *argv[])
1091 {
1092 	const struct mpl_cmd cmd = {
1093 		.opcode = BT_MCS_OPC_PAUSE,
1094 		.use_param = false,
1095 		.param = 0,
1096 	};
1097 	int err;
1098 
1099 	err = bt_mcc_send_cmd(default_conn, &cmd);
1100 	if (err != 0) {
1101 		shell_error(sh, "MCC pause failed: %d", err);
1102 	}
1103 
1104 	return err;
1105 }
1106 
cmd_mcc_fast_rewind(const struct shell * sh,size_t argc,char * argv[])1107 static int cmd_mcc_fast_rewind(const struct shell *sh, size_t argc,
1108 			       char *argv[])
1109 {
1110 	const struct mpl_cmd cmd = {
1111 		.opcode = BT_MCS_OPC_FAST_REWIND,
1112 		.use_param = false,
1113 		.param = 0,
1114 	};
1115 	int err;
1116 
1117 	err = bt_mcc_send_cmd(default_conn, &cmd);
1118 	if (err != 0) {
1119 		shell_error(sh, "MCC fast rewind failed: %d", err);
1120 	}
1121 
1122 	return err;
1123 }
1124 
cmd_mcc_fast_forward(const struct shell * sh,size_t argc,char * argv[])1125 static int cmd_mcc_fast_forward(const struct shell *sh, size_t argc,
1126 				char *argv[])
1127 {
1128 	const struct mpl_cmd cmd = {
1129 		.opcode = BT_MCS_OPC_FAST_FORWARD,
1130 		.use_param = false,
1131 		.param = 0,
1132 	};
1133 	int err;
1134 
1135 	err = bt_mcc_send_cmd(default_conn, &cmd);
1136 	if (err != 0) {
1137 		shell_error(sh, "MCC fast forward failed: %d", err);
1138 	}
1139 
1140 	return err;
1141 }
1142 
cmd_mcc_stop(const struct shell * sh,size_t argc,char * argv[])1143 static int cmd_mcc_stop(const struct shell *sh, size_t argc, char *argv[])
1144 {
1145 	const struct mpl_cmd cmd = {
1146 		.opcode = BT_MCS_OPC_STOP,
1147 		.use_param = false,
1148 		.param = 0,
1149 	};
1150 	int err;
1151 
1152 	err = bt_mcc_send_cmd(default_conn, &cmd);
1153 	if (err != 0) {
1154 		shell_error(sh, "MCC stop failed: %d", err);
1155 	}
1156 
1157 	return err;
1158 }
1159 
cmd_mcc_move_relative(const struct shell * sh,size_t argc,char * argv[])1160 static int cmd_mcc_move_relative(const struct shell *sh, size_t argc,
1161 				 char *argv[])
1162 {
1163 	struct mpl_cmd cmd = {
1164 		.opcode = BT_MCS_OPC_MOVE_RELATIVE,
1165 		.use_param = true,
1166 	};
1167 	long offset;
1168 	int err;
1169 
1170 	err = 0;
1171 	offset = shell_strtol(argv[1], 10, &err);
1172 	if (err != 0) {
1173 		shell_error(sh, "Failed to parse offset: %d", err);
1174 
1175 		return err;
1176 	}
1177 
1178 	if (sizeof(long) != sizeof(int32_t) && !IN_RANGE(offset, INT32_MIN, INT32_MAX)) {
1179 		shell_error(sh, "Invalid offset: %ld", offset);
1180 
1181 		return -ENOEXEC;
1182 	}
1183 
1184 	cmd.param = (int32_t)offset;
1185 
1186 	err = bt_mcc_send_cmd(default_conn, &cmd);
1187 	if (err != 0) {
1188 		shell_error(sh, "MCC move relative failed: %d", err);
1189 	}
1190 
1191 	return err;
1192 }
1193 
cmd_mcc_prev_segment(const struct shell * sh,size_t argc,char * argv[])1194 static int cmd_mcc_prev_segment(const struct shell *sh, size_t argc,
1195 				char *argv[])
1196 {
1197 	const struct mpl_cmd cmd = {
1198 		.opcode = BT_MCS_OPC_PREV_SEGMENT,
1199 		.use_param = false,
1200 		.param = 0,
1201 	};
1202 	int err;
1203 
1204 	err = bt_mcc_send_cmd(default_conn, &cmd);
1205 	if (err != 0) {
1206 		shell_error(sh, "MCC previous segment failed: %d", err);
1207 	}
1208 
1209 	return err;
1210 }
1211 
cmd_mcc_next_segment(const struct shell * sh,size_t argc,char * argv[])1212 static int cmd_mcc_next_segment(const struct shell *sh, size_t argc,
1213 				char *argv[])
1214 {
1215 	const struct mpl_cmd cmd = {
1216 		.opcode = BT_MCS_OPC_NEXT_SEGMENT,
1217 		.use_param = false,
1218 		.param = 0,
1219 	};
1220 	int err;
1221 
1222 	err = bt_mcc_send_cmd(default_conn, &cmd);
1223 	if (err != 0) {
1224 		shell_error(sh, "MCC next segment failed: %d", err);
1225 	}
1226 
1227 	return err;
1228 }
1229 
cmd_mcc_first_segment(const struct shell * sh,size_t argc,char * argv[])1230 static int cmd_mcc_first_segment(const struct shell *sh, size_t argc,
1231 				 char *argv[])
1232 {
1233 	const struct mpl_cmd cmd = {
1234 		.opcode = BT_MCS_OPC_FIRST_SEGMENT,
1235 		.use_param = false,
1236 		.param = 0,
1237 	};
1238 	int err;
1239 
1240 	err = bt_mcc_send_cmd(default_conn, &cmd);
1241 	if (err != 0) {
1242 		shell_error(sh, "MCC first segment failed: %d", err);
1243 	}
1244 
1245 	return err;
1246 }
1247 
cmd_mcc_last_segment(const struct shell * sh,size_t argc,char * argv[])1248 static int cmd_mcc_last_segment(const struct shell *sh, size_t argc,
1249 				char *argv[])
1250 {
1251 	const struct mpl_cmd cmd = {
1252 		.opcode = BT_MCS_OPC_LAST_SEGMENT,
1253 		.use_param = false,
1254 		.param = 0,
1255 	};
1256 	int err;
1257 
1258 	err = bt_mcc_send_cmd(default_conn, &cmd);
1259 	if (err != 0) {
1260 		shell_error(sh, "MCC last segment failed: %d", err);
1261 	}
1262 
1263 	return err;
1264 }
1265 
cmd_mcc_goto_segment(const struct shell * sh,size_t argc,char * argv[])1266 static int cmd_mcc_goto_segment(const struct shell *sh, size_t argc,
1267 				char *argv[])
1268 {
1269 	struct mpl_cmd cmd = {
1270 		.opcode = BT_MCS_OPC_GOTO_SEGMENT,
1271 		.use_param = true,
1272 	};
1273 	long segment;
1274 	int err;
1275 
1276 	err = 0;
1277 	segment = shell_strtol(argv[1], 10, &err);
1278 	if (err != 0) {
1279 		shell_error(sh, "Failed to parse segment: %d", err);
1280 
1281 		return err;
1282 	}
1283 
1284 	if (sizeof(long) != sizeof(int32_t) && !IN_RANGE(segment, INT32_MIN, INT32_MAX)) {
1285 		shell_error(sh, "Invalid segment: %ld", segment);
1286 
1287 		return -ENOEXEC;
1288 	}
1289 
1290 	cmd.param = (int32_t)segment;
1291 
1292 	err = bt_mcc_send_cmd(default_conn, &cmd);
1293 	if (err != 0) {
1294 		shell_error(sh, "MCC goto segment failed: %d", err);
1295 	}
1296 
1297 	return err;
1298 }
1299 
cmd_mcc_prev_track(const struct shell * sh,size_t argc,char * argv[])1300 static int cmd_mcc_prev_track(const struct shell *sh, size_t argc, char *argv[])
1301 {
1302 	const struct mpl_cmd cmd = {
1303 		.opcode = BT_MCS_OPC_PREV_TRACK,
1304 		.use_param = false,
1305 		.param = 0,
1306 	};
1307 	int err;
1308 
1309 	err = bt_mcc_send_cmd(default_conn, &cmd);
1310 	if (err != 0) {
1311 		shell_error(sh, "MCC previous track failed: %d", err);
1312 	}
1313 
1314 	return err;
1315 }
1316 
cmd_mcc_next_track(const struct shell * sh,size_t argc,char * argv[])1317 static int cmd_mcc_next_track(const struct shell *sh, size_t argc, char *argv[])
1318 {
1319 	const struct mpl_cmd cmd = {
1320 		.opcode = BT_MCS_OPC_NEXT_TRACK,
1321 		.use_param = false,
1322 		.param = 0,
1323 	};
1324 	int err;
1325 
1326 	err = bt_mcc_send_cmd(default_conn, &cmd);
1327 	if (err != 0) {
1328 		shell_error(sh, "MCC next track failed: %d", err);
1329 	}
1330 
1331 	return err;
1332 }
1333 
cmd_mcc_first_track(const struct shell * sh,size_t argc,char * argv[])1334 static int cmd_mcc_first_track(const struct shell *sh, size_t argc,
1335 			       char *argv[])
1336 {
1337 	const struct mpl_cmd cmd = {
1338 		.opcode = BT_MCS_OPC_FIRST_TRACK,
1339 		.use_param = false,
1340 		.param = 0,
1341 	};
1342 	int err;
1343 
1344 	err = bt_mcc_send_cmd(default_conn, &cmd);
1345 	if (err != 0) {
1346 		shell_error(sh, "MCC first track failed: %d", err);
1347 	}
1348 
1349 	return err;
1350 }
1351 
cmd_mcc_last_track(const struct shell * sh,size_t argc,char * argv[])1352 static int cmd_mcc_last_track(const struct shell *sh, size_t argc, char *argv[])
1353 {
1354 	const struct mpl_cmd cmd = {
1355 		.opcode = BT_MCS_OPC_LAST_TRACK,
1356 		.use_param = false,
1357 		.param = 0,
1358 	};
1359 	int err;
1360 
1361 	err = bt_mcc_send_cmd(default_conn, &cmd);
1362 	if (err != 0) {
1363 		shell_error(sh, "MCC last track failed: %d", err);
1364 	}
1365 
1366 	return err;
1367 }
1368 
cmd_mcc_goto_track(const struct shell * sh,size_t argc,char * argv[])1369 static int cmd_mcc_goto_track(const struct shell *sh, size_t argc, char *argv[])
1370 {
1371 	struct mpl_cmd cmd = {
1372 		.opcode = BT_MCS_OPC_GOTO_TRACK,
1373 		.use_param = true,
1374 	};
1375 	long track;
1376 	int err;
1377 
1378 	err = 0;
1379 	track = shell_strtol(argv[1], 10, &err);
1380 	if (err != 0) {
1381 		shell_error(sh, "Failed to parse track: %d", err);
1382 
1383 		return err;
1384 	}
1385 
1386 	if (sizeof(long) != sizeof(int32_t) && !IN_RANGE(track, INT32_MIN, INT32_MAX)) {
1387 		shell_error(sh, "Invalid track: %ld", track);
1388 
1389 		return -ENOEXEC;
1390 	}
1391 
1392 	cmd.param = (int32_t)track;
1393 
1394 	err = bt_mcc_send_cmd(default_conn, &cmd);
1395 	if (err != 0) {
1396 		shell_error(sh, "MCC goto track failed: %d", err);
1397 	}
1398 
1399 	return err;
1400 }
1401 
cmd_mcc_prev_group(const struct shell * sh,size_t argc,char * argv[])1402 static int cmd_mcc_prev_group(const struct shell *sh, size_t argc, char *argv[])
1403 {
1404 	const struct mpl_cmd cmd = {
1405 		.opcode = BT_MCS_OPC_PREV_GROUP,
1406 		.use_param = false,
1407 		.param = 0,
1408 	};
1409 	int err;
1410 
1411 	err = bt_mcc_send_cmd(default_conn, &cmd);
1412 	if (err != 0) {
1413 		shell_error(sh, "MCC previous group failed: %d", err);
1414 	}
1415 
1416 	return err;
1417 }
1418 
cmd_mcc_next_group(const struct shell * sh,size_t argc,char * argv[])1419 static int cmd_mcc_next_group(const struct shell *sh, size_t argc, char *argv[])
1420 {
1421 	const struct mpl_cmd cmd = {
1422 		.opcode = BT_MCS_OPC_NEXT_GROUP,
1423 		.use_param = false,
1424 		.param = 0,
1425 	};
1426 	int err;
1427 
1428 	err = bt_mcc_send_cmd(default_conn, &cmd);
1429 	if (err != 0) {
1430 		shell_error(sh, "MCC next group failed: %d", err);
1431 	}
1432 
1433 	return err;
1434 }
1435 
cmd_mcc_first_group(const struct shell * sh,size_t argc,char * argv[])1436 static int cmd_mcc_first_group(const struct shell *sh, size_t argc,
1437 			       char *argv[])
1438 {
1439 	const struct mpl_cmd cmd = {
1440 		.opcode = BT_MCS_OPC_FIRST_GROUP,
1441 		.use_param = false,
1442 		.param = 0,
1443 	};
1444 	int err;
1445 
1446 	err = bt_mcc_send_cmd(default_conn, &cmd);
1447 	if (err != 0) {
1448 		shell_error(sh, "MCC first group failed: %d", err);
1449 	}
1450 
1451 	return err;
1452 }
1453 
cmd_mcc_last_group(const struct shell * sh,size_t argc,char * argv[])1454 static int cmd_mcc_last_group(const struct shell *sh, size_t argc, char *argv[])
1455 {
1456 	const struct mpl_cmd cmd = {
1457 		.opcode = BT_MCS_OPC_LAST_GROUP,
1458 		.use_param = false,
1459 		.param = 0,
1460 	};
1461 	int err;
1462 
1463 	err = bt_mcc_send_cmd(default_conn, &cmd);
1464 	if (err != 0) {
1465 		shell_error(sh, "MCC last group failed: %d", err);
1466 	}
1467 
1468 	return err;
1469 }
1470 
cmd_mcc_goto_group(const struct shell * sh,size_t argc,char * argv[])1471 static int cmd_mcc_goto_group(const struct shell *sh, size_t argc, char *argv[])
1472 {
1473 	struct mpl_cmd cmd = {
1474 		.opcode = BT_MCS_OPC_GOTO_GROUP,
1475 		.use_param = true,
1476 	};
1477 	long group;
1478 	int err;
1479 
1480 	err = 0;
1481 	group = shell_strtol(argv[1], 10, &err);
1482 	if (err != 0) {
1483 		shell_error(sh, "Failed to parse group: %d", err);
1484 
1485 		return err;
1486 	}
1487 
1488 	if (sizeof(long) != sizeof(int32_t) && !IN_RANGE(group, INT32_MIN, INT32_MAX)) {
1489 		shell_error(sh, "Invalid group: %ld", group);
1490 
1491 		return -ENOEXEC;
1492 	}
1493 
1494 	cmd.param = (int32_t)group;
1495 
1496 	err = bt_mcc_send_cmd(default_conn, &cmd);
1497 	if (err != 0) {
1498 		shell_error(sh, "MCC goto group failed: %d", err);
1499 	}
1500 
1501 	return err;
1502 }
1503 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
1504 
1505 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
cmd_mcc_read_opcodes_supported(const struct shell * sh,size_t argc,char * argv[])1506 static int cmd_mcc_read_opcodes_supported(const struct shell *sh, size_t argc,
1507 					  char *argv[])
1508 {
1509 	int result;
1510 
1511 	result = bt_mcc_read_opcodes_supported(default_conn);
1512 	if (result) {
1513 		shell_error(sh, "Fail: %d", result);
1514 	}
1515 	return result;
1516 }
1517 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
1518 
1519 #ifdef CONFIG_BT_MCC_OTS
cmd_mcc_send_search_raw(const struct shell * sh,size_t argc,char * argv[])1520 static int cmd_mcc_send_search_raw(const struct shell *sh, size_t argc,
1521 				   char *argv[])
1522 {
1523 	int result;
1524 	size_t len;
1525 	struct mpl_search search;
1526 
1527 	len = strlen(argv[1]);
1528 	if (len > sizeof(search.search)) {
1529 		shell_print(sh, "Fail: Invalid argument");
1530 		return -EINVAL;
1531 	}
1532 
1533 	search.len = len;
1534 	memcpy(search.search, argv[1], search.len);
1535 	LOG_DBG("Search string: %s", argv[1]);
1536 
1537 	result = bt_mcc_send_search(default_conn, &search);
1538 	if (result) {
1539 		shell_print(sh, "Fail: %d", result);
1540 	}
1541 	return result;
1542 }
1543 
cmd_mcc_send_search_ioptest(const struct shell * sh,size_t argc,char * argv[])1544 static int cmd_mcc_send_search_ioptest(const struct shell *sh, size_t argc,
1545 				       char *argv[])
1546 {
1547 	/* Implementation follows Media control service testspec 0.9.0r13 */
1548 	/* Testcase MCS/SR/SCP/BV-01-C [Search Control Point], rounds 1 - 9 */
1549 	struct mpl_sci sci_1 = {0};
1550 	struct mpl_sci sci_2 = {0};
1551 	struct mpl_search search;
1552 	unsigned long testround;
1553 	int result = 0;
1554 
1555 	testround = shell_strtoul(argv[1], 0, &result);
1556 	if (result != 0) {
1557 		shell_error(sh, "Could not parse testround: %d", result);
1558 
1559 		return -ENOEXEC;
1560 	}
1561 
1562 	switch (testround) {
1563 	case 1:
1564 	case 8:
1565 	case 9:
1566 		/* 1, 8 and 9 have the same first SCI */
1567 		sci_1.type = BT_MCS_SEARCH_TYPE_TRACK_NAME;
1568 		strcpy(sci_1.param, "TSPX_Track_Name");
1569 		break;
1570 	case 2:
1571 		sci_1.type = BT_MCS_SEARCH_TYPE_ARTIST_NAME;
1572 		strcpy(sci_1.param, "TSPX_Artist_Name");
1573 		break;
1574 	case 3:
1575 		sci_1.type = BT_MCS_SEARCH_TYPE_ALBUM_NAME;
1576 		strcpy(sci_1.param, "TSPX_Album_Name");
1577 		break;
1578 	case 4:
1579 		sci_1.type = BT_MCS_SEARCH_TYPE_GROUP_NAME;
1580 		strcpy(sci_1.param, "TSPX_Group_Name");
1581 		break;
1582 	case 5:
1583 		sci_1.type = BT_MCS_SEARCH_TYPE_EARLIEST_YEAR;
1584 		strcpy(sci_1.param, "TSPX_Earliest_Year");
1585 		break;
1586 	case 6:
1587 		sci_1.type = BT_MCS_SEARCH_TYPE_LATEST_YEAR;
1588 		strcpy(sci_1.param, "TSPX_Latest_Year");
1589 		break;
1590 	case 7:
1591 		sci_1.type = BT_MCS_SEARCH_TYPE_GENRE;
1592 		strcpy(sci_1.param, "TSPX_Genre");
1593 		break;
1594 	default:
1595 		shell_error(sh, "Invalid parameter");
1596 		return -ENOEXEC;
1597 	}
1598 
1599 
1600 	switch (testround) {
1601 	case 8:
1602 		sci_2.type = BT_MCS_SEARCH_TYPE_ONLY_TRACKS;
1603 		break;
1604 	case 9:
1605 		sci_2.type = BT_MCS_SEARCH_TYPE_ONLY_GROUPS;
1606 		break;
1607 	}
1608 
1609 	/* Length is length of type, plus length of param w/o termination */
1610 	sci_1.len = sizeof(sci_1.type) + strlen(sci_1.param);
1611 
1612 	search.len = 0;
1613 	memcpy(&search.search[search.len], &sci_1.len, sizeof(sci_1.len));
1614 	search.len += sizeof(sci_1.len);
1615 
1616 	memcpy(&search.search[search.len], &sci_1.type, sizeof(sci_1.type));
1617 	search.len += sizeof(sci_1.type);
1618 
1619 	memcpy(&search.search[search.len], &sci_1.param, strlen(sci_1.param));
1620 	search.len += strlen(sci_1.param);
1621 
1622 	if (testround == 8 || testround == 9) {
1623 
1624 		sci_2.len = sizeof(sci_2.type); /* The type only, no param */
1625 
1626 		memcpy(&search.search[search.len], &sci_2.len,
1627 		       sizeof(sci_2.len));
1628 		search.len += sizeof(sci_2.len);
1629 
1630 		memcpy(&search.search[search.len], &sci_2.type,
1631 		       sizeof(sci_2.type));
1632 		search.len += sizeof(sci_2.type);
1633 	}
1634 
1635 	shell_print(sh, "Search string: ");
1636 	shell_hexdump(sh, (uint8_t *)&search.search, search.len);
1637 
1638 	result = bt_mcc_send_search(default_conn, &search);
1639 	if (result) {
1640 		shell_print(sh, "Fail: %d", result);
1641 	}
1642 
1643 	return result;
1644 }
1645 
1646 #if defined(CONFIG_BT_MCC_LOG_LEVEL_DBG) && defined(CONFIG_BT_TESTING)
cmd_mcc_test_send_search_iop_invalid_type(const struct shell * sh,size_t argc,char * argv[])1647 static int cmd_mcc_test_send_search_iop_invalid_type(const struct shell *sh,
1648 						     size_t argc, char *argv[])
1649 {
1650 	int result;
1651 	struct mpl_search search;
1652 
1653 	search.search[0] = 2;
1654 	search.search[1] = (char)14; /* Invalid type value */
1655 	search.search[2] = 't';  /* Anything */
1656 	search.len = 3;
1657 
1658 	shell_print(sh, "Search string: ");
1659 	shell_hexdump(sh, (uint8_t *)&search.search, search.len);
1660 
1661 	result = bt_mcc_send_search(default_conn, &search);
1662 	if (result) {
1663 		shell_print(sh, "Fail: %d", result);
1664 	}
1665 
1666 	return result;
1667 }
1668 
cmd_mcc_test_send_search_invalid_sci_len(const struct shell * sh,size_t argc,char * argv[])1669 static int cmd_mcc_test_send_search_invalid_sci_len(const struct shell *sh,
1670 						    size_t argc, char *argv[])
1671 {
1672 	/* Reproduce a search that caused hard fault when sent from peer */
1673 	/* in IOP testing */
1674 
1675 	int result;
1676 	struct mpl_search search;
1677 
1678 	char offending_search[9] = {6, 1, 't', 'r', 'a', 'c', 'k', 0, 1 };
1679 
1680 	search.len = 9;
1681 	memcpy(&search.search, offending_search, search.len);
1682 
1683 	shell_print(sh, "Search string: ");
1684 	shell_hexdump(sh, (uint8_t *)&search.search, search.len);
1685 
1686 	result = bt_mcc_send_search(default_conn, &search);
1687 	if (result) {
1688 		shell_print(sh, "Fail: %d", result);
1689 	}
1690 
1691 	return result;
1692 }
1693 #endif /* CONFIG_BT_MCC_LOG_LEVEL_DBG && CONFIG_BT_TESTING */
1694 
cmd_mcc_read_search_results_obj_id(const struct shell * sh,size_t argc,char * argv[])1695 static int cmd_mcc_read_search_results_obj_id(const struct shell *sh,
1696 					      size_t argc, char *argv[])
1697 {
1698 	int result;
1699 
1700 	result = bt_mcc_read_search_results_obj_id(default_conn);
1701 	if (result) {
1702 		shell_error(sh, "Fail: %d", result);
1703 	}
1704 	return result;
1705 }
1706 #endif /* CONFIG_BT_MCC_OTS */
1707 
1708 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
cmd_mcc_read_content_control_id(const struct shell * sh,size_t argc,char * argv[])1709 static int cmd_mcc_read_content_control_id(const struct shell *sh, size_t argc,
1710 					   char *argv[])
1711 {
1712 	int result;
1713 
1714 	result = bt_mcc_read_content_control_id(default_conn);
1715 	if (result) {
1716 		shell_error(sh, "Fail: %d", result);
1717 	}
1718 	return result;
1719 }
1720 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
1721 
1722 
1723 #ifdef CONFIG_BT_MCC_OTS
cmd_mcc_otc_read_features(const struct shell * sh,size_t argc,char * argv[])1724 static int cmd_mcc_otc_read_features(const struct shell *sh, size_t argc,
1725 				     char *argv[])
1726 {
1727 	int result;
1728 
1729 	result = bt_ots_client_read_feature(bt_mcc_otc_inst(default_conn),
1730 					    default_conn);
1731 	if (result) {
1732 		shell_error(sh, "Fail: %d", result);
1733 	}
1734 	return result;
1735 }
1736 
cmd_mcc_otc_read(const struct shell * sh,size_t argc,char * argv[])1737 static int cmd_mcc_otc_read(const struct shell *sh, size_t argc, char *argv[])
1738 {
1739 	int result;
1740 
1741 	result = bt_ots_client_read_object_data(bt_mcc_otc_inst(default_conn),
1742 						default_conn);
1743 	if (result) {
1744 		shell_error(sh, "Fail: %d", result);
1745 	}
1746 	return result;
1747 }
1748 
cmd_mcc_otc_read_metadata(const struct shell * sh,size_t argc,char * argv[])1749 static int cmd_mcc_otc_read_metadata(const struct shell *sh, size_t argc,
1750 				     char *argv[])
1751 {
1752 	int result;
1753 
1754 	result = bt_ots_client_read_object_metadata(bt_mcc_otc_inst(default_conn),
1755 						    default_conn,
1756 						    BT_OTS_METADATA_REQ_ALL);
1757 	if (result) {
1758 		shell_error(sh, "Fail: %d", result);
1759 	}
1760 	return result;
1761 }
1762 
cmd_mcc_otc_select(const struct shell * sh,size_t argc,char * argv[])1763 static int cmd_mcc_otc_select(const struct shell *sh, size_t argc, char *argv[])
1764 {
1765 	unsigned long long id;
1766 	int result = 0;
1767 
1768 	id = shell_strtoull(argv[1], 0, &result);
1769 	if (result != 0) {
1770 		shell_error(sh, "Could not parse id: %d", result);
1771 
1772 		return -ENOEXEC;
1773 	}
1774 
1775 	if (!IN_RANGE(id, BT_OTS_OBJ_ID_MIN, BT_OTS_OBJ_ID_MAX)) {
1776 		shell_error(sh, "Invalid id: %llu", id);
1777 
1778 		return -ENOEXEC;
1779 	}
1780 
1781 	result = bt_ots_client_select_id(bt_mcc_otc_inst(default_conn),
1782 					 default_conn, id);
1783 	if (result) {
1784 		shell_error(sh, "Fail: %d", result);
1785 	}
1786 	return result;
1787 }
1788 
cmd_mcc_otc_select_first(const struct shell * sh,size_t argc,char * argv[])1789 static int cmd_mcc_otc_select_first(const struct shell *sh, size_t argc,
1790 				    char *argv[])
1791 {
1792 	int result;
1793 
1794 	result = bt_ots_client_select_first(bt_mcc_otc_inst(default_conn),
1795 					    default_conn);
1796 	if (result) {
1797 		shell_error(sh, "Fail: %d", result);
1798 	}
1799 	return result;
1800 }
1801 
cmd_mcc_otc_select_last(const struct shell * sh,size_t argc,char * argv[])1802 static int cmd_mcc_otc_select_last(const struct shell *sh, size_t argc,
1803 				   char *argv[])
1804 {
1805 	int result;
1806 
1807 	result = bt_ots_client_select_last(bt_mcc_otc_inst(default_conn),
1808 					   default_conn);
1809 	if (result) {
1810 		shell_error(sh, "Fail: %d", result);
1811 	}
1812 	return result;
1813 }
1814 
cmd_mcc_otc_select_next(const struct shell * sh,size_t argc,char * argv[])1815 static int cmd_mcc_otc_select_next(const struct shell *sh, size_t argc,
1816 				   char *argv[])
1817 {
1818 	int result;
1819 
1820 	result = bt_ots_client_select_next(bt_mcc_otc_inst(default_conn),
1821 					   default_conn);
1822 	if (result) {
1823 		shell_error(sh, "Fail: %d", result);
1824 	}
1825 	return result;
1826 }
1827 
cmd_mcc_otc_select_prev(const struct shell * sh,size_t argc,char * argv[])1828 static int cmd_mcc_otc_select_prev(const struct shell *sh, size_t argc,
1829 				   char *argv[])
1830 {
1831 	int result;
1832 
1833 	result = bt_ots_client_select_prev(bt_mcc_otc_inst(default_conn),
1834 					   default_conn);
1835 	if (result) {
1836 		shell_error(sh, "Fail: %d", result);
1837 	}
1838 	return result;
1839 }
1840 
cmd_mcc_otc_read_icon_object(const struct shell * sh,size_t argc,char * argv[])1841 static int cmd_mcc_otc_read_icon_object(const struct shell *sh, size_t argc,
1842 					char *argv[])
1843 {
1844 	/* Assumes the Icon Object has already been selected by ID */
1845 
1846 	int result;
1847 
1848 	result = bt_mcc_otc_read_icon_object(default_conn);
1849 	if (result) {
1850 		shell_error(sh, "Fail: %d", result);
1851 	}
1852 	return result;
1853 }
1854 
cmd_mcc_otc_read_track_segments_object(const struct shell * sh,size_t argc,char * argv[])1855 static int cmd_mcc_otc_read_track_segments_object(const struct shell *sh,
1856 						  size_t argc, char *argv[])
1857 {
1858 	/* Assumes the Segment Object has already been selected by ID */
1859 
1860 	int result;
1861 
1862 	result = bt_mcc_otc_read_track_segments_object(default_conn);
1863 	if (result) {
1864 		shell_error(sh, "Fail: %d", result);
1865 	}
1866 	return result;
1867 }
1868 
cmd_mcc_otc_read_current_track_object(const struct shell * sh,size_t argc,char * argv[])1869 static int cmd_mcc_otc_read_current_track_object(const struct shell *sh,
1870 						 size_t argc, char *argv[])
1871 {
1872 	/* Assumes the Current Track Object has already been selected by ID */
1873 
1874 	int result;
1875 
1876 	result = bt_mcc_otc_read_current_track_object(default_conn);
1877 	if (result) {
1878 		shell_error(sh, "Fail: %d", result);
1879 	}
1880 	return result;
1881 }
1882 
cmd_mcc_otc_read_next_track_object(const struct shell * sh,size_t argc,char * argv[])1883 static int cmd_mcc_otc_read_next_track_object(const struct shell *sh,
1884 					      size_t argc, char *argv[])
1885 {
1886 	/* Assumes the Next Track Object has already been selected by ID */
1887 
1888 	int result;
1889 
1890 	result = bt_mcc_otc_read_next_track_object(default_conn);
1891 	if (result) {
1892 		shell_error(sh, "Fail: %d", result);
1893 	}
1894 	return result;
1895 }
1896 
cmd_mcc_otc_read_parent_group_object(const struct shell * sh,size_t argc,char * argv[])1897 static int cmd_mcc_otc_read_parent_group_object(const struct shell *sh,
1898 						size_t argc, char *argv[])
1899 {
1900 	/* Assumes the Parent Group Object has already been selected by ID */
1901 
1902 	int result;
1903 
1904 	result = bt_mcc_otc_read_parent_group_object(default_conn);
1905 	if (result) {
1906 		shell_error(sh, "Fail: %d", result);
1907 	}
1908 	return result;
1909 }
1910 
cmd_mcc_otc_read_current_group_object(const struct shell * sh,size_t argc,char * argv[])1911 static int cmd_mcc_otc_read_current_group_object(const struct shell *sh,
1912 						 size_t argc, char *argv[])
1913 {
1914 	/* Assumes the Current Group Object has already been selected by ID */
1915 
1916 	int result;
1917 
1918 	result = bt_mcc_otc_read_current_group_object(default_conn);
1919 	if (result) {
1920 		shell_error(sh, "Fail: %d", result);
1921 	}
1922 	return result;
1923 }
1924 #endif /* CONFIG_BT_MCC_OTS */
1925 
cmd_mcc(const struct shell * sh,size_t argc,char ** argv)1926 static int cmd_mcc(const struct shell *sh, size_t argc, char **argv)
1927 {
1928 	shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
1929 
1930 	return -ENOEXEC;
1931 }
1932 
1933 SHELL_STATIC_SUBCMD_SET_CREATE(mcc_cmds,
1934 	SHELL_CMD_ARG(init, NULL, "Initialize client",
1935 		      cmd_mcc_init, 1, 0),
1936 	SHELL_CMD_ARG(discover_mcs, NULL,
1937 		      "Discover Media Control Service [subscribe]",
1938 		      cmd_mcc_discover_mcs, 1, 1),
1939 	SHELL_CMD_ARG(read_player_name, NULL, "Read Media Player Name",
1940 		      cmd_mcc_read_player_name, 1, 0),
1941 #ifdef CONFIG_BT_MCC_OTS
1942 	SHELL_CMD_ARG(read_icon_obj_id, NULL, "Read Icon Object ID",
1943 		      cmd_mcc_read_icon_obj_id, 1, 0),
1944 #endif /* CONFIG_BT_MCC_OTS */
1945 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
1946 	SHELL_CMD_ARG(read_icon_url, NULL, "Read Icon URL",
1947 		      cmd_mcc_read_icon_url, 1, 0),
1948 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
1949 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
1950 	SHELL_CMD_ARG(read_track_title, NULL, "Read Track Title",
1951 		      cmd_mcc_read_track_title, 1, 0),
1952 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
1953 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
1954 	SHELL_CMD_ARG(read_track_duration, NULL, "Read Track Duration",
1955 		      cmd_mcc_read_track_duration, 1, 0),
1956 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
1957 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
1958 	SHELL_CMD_ARG(read_track_position, NULL, "Read Track Position",
1959 		      cmd_mcc_read_track_position, 1, 0),
1960 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
1961 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
1962 	SHELL_CMD_ARG(set_track_position, NULL, "Set Track position <position>",
1963 		      cmd_mcc_set_track_position, 2, 0),
1964 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
1965 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
1966 	SHELL_CMD_ARG(read_playback_speed, NULL, "Read Playback Speed",
1967 		      cmd_mcc_read_playback_speed, 1, 0),
1968 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED */
1969 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
1970 	SHELL_CMD_ARG(set_playback_speed, NULL, "Set Playback Speed <speed>",
1971 		      cmd_mcc_set_playback_speed, 2, 0),
1972 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
1973 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
1974 	SHELL_CMD_ARG(read_seeking_speed, NULL, "Read Seeking Speed",
1975 		      cmd_mcc_read_seeking_speed, 1, 0),
1976 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
1977 #ifdef CONFIG_BT_MCC_OTS
1978 	SHELL_CMD_ARG(read_track_segments_obj_id, NULL,
1979 		      "Read Track Segments Object ID",
1980 		      cmd_mcc_read_track_segments_obj_id, 1, 0),
1981 	SHELL_CMD_ARG(read_current_track_obj_id, NULL,
1982 		      "Read Current Track Object ID",
1983 		      cmd_mcc_read_current_track_obj_id, 1, 0),
1984 	SHELL_CMD_ARG(set_current_track_obj_id, NULL,
1985 		      "Set Current Track Object ID <id: 48 bits or less>",
1986 		      cmd_mcc_set_current_track_obj_id, 2, 0),
1987 	SHELL_CMD_ARG(read_next_track_obj_id, NULL,
1988 		      "Read Next Track Object ID",
1989 		      cmd_mcc_read_next_track_obj_id, 1, 0),
1990 	SHELL_CMD_ARG(set_next_track_obj_id, NULL,
1991 		      "Set Next Track Object ID <id: 48 bits or less>",
1992 		      cmd_mcc_set_next_track_obj_id, 2, 0),
1993 	SHELL_CMD_ARG(read_current_group_obj_id, NULL,
1994 		      "Read Current Group Object ID",
1995 		      cmd_mcc_read_current_group_obj_id, 1, 0),
1996 	SHELL_CMD_ARG(read_parent_group_obj_id, NULL,
1997 		      "Read Parent Group Object ID",
1998 		      cmd_mcc_read_parent_group_obj_id, 1, 0),
1999 	SHELL_CMD_ARG(set_current_group_obj_id, NULL,
2000 		      "Set Current Group Object ID <id: 48 bits or less>",
2001 		      cmd_mcc_set_current_group_obj_id, 2, 0),
2002 #endif /* CONFIG_BT_MCC_OTS */
2003 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
2004 	SHELL_CMD_ARG(read_playing_order, NULL, "Read Playing Order",
2005 		      cmd_mcc_read_playing_order, 1, 0),
2006 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
2007 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
2008 	SHELL_CMD_ARG(set_playing_order, NULL, "Set Playing Order <order>",
2009 		      cmd_mcc_set_playing_order, 2, 0),
2010 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
2011 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
2012 	SHELL_CMD_ARG(read_playing_orders_supported, NULL,
2013 		     "Read Playing Orders Supported",
2014 		      cmd_mcc_read_playing_orders_supported, 1, 0),
2015 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
2016 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
2017 	SHELL_CMD_ARG(read_media_state, NULL, "Read Media State",
2018 		      cmd_mcc_read_media_state, 1, 0),
2019 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
2020 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
2021 	SHELL_CMD_ARG(play, NULL, "Send the play command", cmd_mcc_play, 1, 0),
2022 	SHELL_CMD_ARG(pause, NULL, "Send the pause command",
2023 		      cmd_mcc_pause, 1, 0),
2024 	SHELL_CMD_ARG(fast_rewind, NULL, "Send the fast rewind command",
2025 		      cmd_mcc_fast_rewind, 1, 0),
2026 	SHELL_CMD_ARG(fast_forward, NULL, "Send the fast forward command",
2027 		      cmd_mcc_fast_forward, 1, 0),
2028 	SHELL_CMD_ARG(stop, NULL, "Send the stop command", cmd_mcc_stop, 1, 0),
2029 	SHELL_CMD_ARG(move_relative, NULL,
2030 		      "Send the move relative command <int32_t: offset>",
2031 		      cmd_mcc_move_relative, 2, 0),
2032 	SHELL_CMD_ARG(prev_segment, NULL, "Send the prev segment command",
2033 		      cmd_mcc_prev_segment, 1, 0),
2034 	SHELL_CMD_ARG(next_segment, NULL, "Send the next segment command",
2035 		      cmd_mcc_next_segment, 1, 0),
2036 	SHELL_CMD_ARG(first_segment, NULL, "Send the first segment command",
2037 		      cmd_mcc_first_segment, 1, 0),
2038 	SHELL_CMD_ARG(last_segment, NULL, "Send the last segment command",
2039 		      cmd_mcc_last_segment, 1, 0),
2040 	SHELL_CMD_ARG(goto_segment, NULL,
2041 		      "Send the goto segment command <int32_t: segment>",
2042 		      cmd_mcc_goto_segment, 2, 0),
2043 	SHELL_CMD_ARG(prev_track, NULL, "Send the prev track command",
2044 		      cmd_mcc_prev_track, 1, 0),
2045 	SHELL_CMD_ARG(next_track, NULL, "Send the next track command",
2046 		      cmd_mcc_next_track, 1, 0),
2047 	SHELL_CMD_ARG(first_track, NULL, "Send the first track command",
2048 		      cmd_mcc_first_track, 1, 0),
2049 	SHELL_CMD_ARG(last_track, NULL, "Send the last track command",
2050 		      cmd_mcc_last_track, 1, 0),
2051 	SHELL_CMD_ARG(goto_track, NULL,
2052 		      "Send the goto track command  <int32_t: track>",
2053 		      cmd_mcc_goto_track, 2, 0),
2054 	SHELL_CMD_ARG(prev_group, NULL, "Send the prev group command",
2055 		      cmd_mcc_prev_group, 1, 0),
2056 	SHELL_CMD_ARG(next_group, NULL, "Send the next group command",
2057 		      cmd_mcc_next_group, 1, 0),
2058 	SHELL_CMD_ARG(first_group, NULL, "Send the first group command",
2059 		      cmd_mcc_first_group, 1, 0),
2060 	SHELL_CMD_ARG(last_group, NULL, "Send the last group command",
2061 		      cmd_mcc_last_group, 1, 0),
2062 	SHELL_CMD_ARG(goto_group, NULL,
2063 		      "Send the goto group command <int32_t: group>",
2064 		      cmd_mcc_goto_group, 2, 0),
2065 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
2066 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
2067 	SHELL_CMD_ARG(read_opcodes_supported, NULL, "Send the Read Opcodes Supported",
2068 		      cmd_mcc_read_opcodes_supported, 1, 0),
2069 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
2070 #ifdef CONFIG_BT_MCC_OTS
2071 	SHELL_CMD_ARG(send_search_raw, NULL, "Send search <search control item sequence>",
2072 		      cmd_mcc_send_search_raw, 2, 0),
2073 	SHELL_CMD_ARG(send_search_scp_ioptest, NULL,
2074 		      "Send search - IOP test round as input <round number>",
2075 		      cmd_mcc_send_search_ioptest, 2, 0),
2076 #if defined(CONFIG_BT_MCC_LOG_LEVEL_DBG) && defined(CONFIG_BT_TESTING)
2077 	SHELL_CMD_ARG(test_send_search_iop_invalid_type, NULL,
2078 		      "Send search - IOP test, invalid type value (test)",
2079 		      cmd_mcc_test_send_search_iop_invalid_type, 1, 0),
2080 	SHELL_CMD_ARG(test_send_Search_invalid_sci_len, NULL,
2081 		      "Send search - invalid sci length (test)",
2082 		      cmd_mcc_test_send_search_invalid_sci_len, 1, 0),
2083 #endif /* CONFIG_BT_MCC_LOG_LEVEL_DBG && CONFIG_BT_TESTING */
2084 	SHELL_CMD_ARG(read_search_results_obj_id, NULL,
2085 		      "Read Search Results Object ID",
2086 		      cmd_mcc_read_search_results_obj_id, 1, 0),
2087 #endif /* CONFIG_BT_MCC_OTS */
2088 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
2089 	SHELL_CMD_ARG(read_content_control_id, NULL, "Read Content Control ID",
2090 		      cmd_mcc_read_content_control_id, 1, 0),
2091 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
2092 #ifdef CONFIG_BT_MCC_OTS
2093 	SHELL_CMD_ARG(ots_read_features, NULL, "Read OTC Features",
2094 		      cmd_mcc_otc_read_features, 1, 0),
2095 	SHELL_CMD_ARG(ots_oacp_read, NULL, "Read current object",
2096 		      cmd_mcc_otc_read, 1, 0),
2097 	SHELL_CMD_ARG(ots_read_metadata, NULL, "Read current object's metadata",
2098 		      cmd_mcc_otc_read_metadata, 1, 0),
2099 	SHELL_CMD_ARG(ots_select, NULL, "Select an object by its ID <ID>",
2100 		      cmd_mcc_otc_select, 2, 0),
2101 	SHELL_CMD_ARG(ots_read_icon_object, NULL, "Read Icon Object",
2102 		      cmd_mcc_otc_read_icon_object, 1, 0),
2103 	SHELL_CMD_ARG(ots_read_track_segments_object, NULL,
2104 		      "Read Track Segments Object",
2105 		      cmd_mcc_otc_read_track_segments_object, 1, 0),
2106 	SHELL_CMD_ARG(ots_read_current_track_object, NULL,
2107 		      "Read Current Track Object",
2108 		      cmd_mcc_otc_read_current_track_object, 1, 0),
2109 	SHELL_CMD_ARG(ots_read_next_track_object, NULL,
2110 		      "Read Next Track Object",
2111 		      cmd_mcc_otc_read_next_track_object, 1, 0),
2112 	SHELL_CMD_ARG(ots_read_parent_group_object, NULL,
2113 		      "Read Parent Group Object",
2114 		      cmd_mcc_otc_read_parent_group_object, 1, 0),
2115 	SHELL_CMD_ARG(ots_read_current_group_object, NULL,
2116 		      "Read Current Group Object",
2117 		      cmd_mcc_otc_read_current_group_object, 1, 0),
2118 	SHELL_CMD_ARG(ots_select_first, NULL, "Select first object",
2119 		      cmd_mcc_otc_select_first, 1, 0),
2120 	SHELL_CMD_ARG(ots_select_last, NULL, "Select last object",
2121 		      cmd_mcc_otc_select_last, 1, 0),
2122 	SHELL_CMD_ARG(ots_select_next, NULL, "Select next object",
2123 		      cmd_mcc_otc_select_next, 1, 0),
2124 	SHELL_CMD_ARG(ots_select_previous, NULL, "Select previous object",
2125 		      cmd_mcc_otc_select_prev, 1, 0),
2126 #endif /* CONFIG_BT_MCC_OTS */
2127 	SHELL_SUBCMD_SET_END
2128 );
2129 
2130 SHELL_CMD_ARG_REGISTER(mcc, &mcc_cmds, "MCC commands",
2131 		       cmd_mcc, 1, 1);
2132