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