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