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