1 /*
2 * Copyright (c) 2019 - 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdbool.h>
7 #include <stdint.h>
8 #include <string.h>
9
10 #include <zephyr/autoconf.h>
11 #include <zephyr/bluetooth/addr.h>
12 #include <zephyr/bluetooth/audio/mcc.h>
13 #include <zephyr/bluetooth/audio/mcs.h>
14 #include <zephyr/bluetooth/audio/media_proxy.h>
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/bluetooth/conn.h>
17 #include <zephyr/bluetooth/gap.h>
18 #include <zephyr/bluetooth/hci_types.h>
19 #include <zephyr/bluetooth/services/ots.h>
20 #include <zephyr/kernel.h>
21 #include <zephyr/net_buf.h>
22 #include <zephyr/sys/printk.h>
23
24 #include "bstests.h"
25 #include "common.h"
26
27 #ifdef CONFIG_BT_MCC
28 extern enum bst_result_t bst_result;
29
30 static struct bt_mcc_cb mcc_cb;
31
32 static uint64_t g_icon_object_id;
33 static uint64_t g_track_segments_object_id;
34 static uint64_t g_current_track_object_id;
35 static uint64_t g_next_track_object_id;
36 static uint64_t g_parent_group_object_id;
37 static uint64_t g_current_group_object_id;
38 static uint64_t g_search_results_object_id;
39
40 static int32_t g_pos;
41 static int8_t g_pb_speed;
42 static uint8_t g_playing_order;
43 static uint8_t g_state;
44 static uint8_t g_command_result;
45 static uint8_t g_search_result;
46 static uint32_t g_supported_opcodes;
47
48 CREATE_FLAG(discovery_done);
49 CREATE_FLAG(player_name_read);
50 CREATE_FLAG(icon_object_id_read);
51 CREATE_FLAG(icon_url_read);
52 CREATE_FLAG(track_change_notified);
53 CREATE_FLAG(track_title_read);
54 CREATE_FLAG(track_duration_read);
55 CREATE_FLAG(track_position_read);
56 CREATE_FLAG(track_position_set);
57 CREATE_FLAG(playback_speed_read);
58 CREATE_FLAG(playback_speed_set);
59 CREATE_FLAG(seeking_speed_read);
60 CREATE_FLAG(supported_opcodes_read);
61 CREATE_FLAG(track_segments_object_id_read);
62 CREATE_FLAG(current_track_object_id_read);
63 CREATE_FLAG(current_track_object_id_set);
64 CREATE_FLAG(next_track_object_id_read);
65 CREATE_FLAG(next_track_object_id_set);
66 CREATE_FLAG(parent_group_object_id_read);
67 CREATE_FLAG(current_group_object_id_read);
68 CREATE_FLAG(current_group_object_id_set);
69 CREATE_FLAG(search_results_object_id_read);
70 CREATE_FLAG(playing_order_read);
71 CREATE_FLAG(playing_order_set);
72 CREATE_FLAG(playing_orders_supported_read);
73 CREATE_FLAG(ccid_read);
74 CREATE_FLAG(media_state_read);
75 CREATE_FLAG(command_sent);
76 CREATE_FLAG(command_notified);
77 CREATE_FLAG(search_sent);
78 CREATE_FLAG(search_notified);
79 CREATE_FLAG(object_selected);
80 CREATE_FLAG(metadata_read);
81 CREATE_FLAG(object_read);
82
83
mcc_discover_mcs_cb(struct bt_conn * conn,int err)84 static void mcc_discover_mcs_cb(struct bt_conn *conn, int err)
85 {
86 if (err) {
87 FAIL("Discovery of MCS failed (%d)\n", err);
88 return;
89 }
90
91 SET_FLAG(discovery_done);
92 }
93
mcc_read_player_name_cb(struct bt_conn * conn,int err,const char * name)94 static void mcc_read_player_name_cb(struct bt_conn *conn, int err, const char *name)
95 {
96 if (err) {
97 FAIL("Player Name read failed (%d)\n", err);
98 return;
99 }
100
101 SET_FLAG(player_name_read);
102 }
103
mcc_read_icon_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)104 static void mcc_read_icon_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
105 {
106 if (err) {
107 FAIL("Icon Object ID read failed (%d)", err);
108 return;
109 }
110
111 g_icon_object_id = id;
112 SET_FLAG(icon_object_id_read);
113 }
114
mcc_read_icon_url_cb(struct bt_conn * conn,int err,const char * url)115 static void mcc_read_icon_url_cb(struct bt_conn *conn, int err, const char *url)
116 {
117 if (err) {
118 FAIL("Icon URL read failed (%d)", err);
119 return;
120 }
121
122 SET_FLAG(icon_url_read);
123 }
124
mcc_track_changed_ntf_cb(struct bt_conn * conn,int err)125 static void mcc_track_changed_ntf_cb(struct bt_conn *conn, int err)
126 {
127 if (err) {
128 FAIL("Track change notification failed (%d)", err);
129 return;
130 }
131
132 SET_FLAG(track_change_notified);
133 }
134
mcc_read_track_title_cb(struct bt_conn * conn,int err,const char * title)135 static void mcc_read_track_title_cb(struct bt_conn *conn, int err, const char *title)
136 {
137 if (err) {
138 FAIL("Track title read failed (%d)", err);
139 return;
140 }
141
142 SET_FLAG(track_title_read);
143 }
144
mcc_read_track_duration_cb(struct bt_conn * conn,int err,int32_t dur)145 static void mcc_read_track_duration_cb(struct bt_conn *conn, int err, int32_t dur)
146 {
147 if (err) {
148 FAIL("Track duration read failed (%d)", err);
149 return;
150 }
151
152 SET_FLAG(track_duration_read);
153 }
154
mcc_read_track_position_cb(struct bt_conn * conn,int err,int32_t pos)155 static void mcc_read_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
156 {
157 if (err) {
158 FAIL("Track position read failed (%d)", err);
159 return;
160 }
161
162 g_pos = pos;
163 SET_FLAG(track_position_read);
164 }
165
mcc_set_track_position_cb(struct bt_conn * conn,int err,int32_t pos)166 static void mcc_set_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
167 {
168 if (err) {
169 FAIL("Track Position set failed (%d)", err);
170 return;
171 }
172
173 g_pos = pos;
174 SET_FLAG(track_position_set);
175 }
176
mcc_read_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)177 static void mcc_read_playback_speed_cb(struct bt_conn *conn, int err,
178 int8_t speed)
179 {
180 if (err) {
181 FAIL("Playback speed read failed (%d)", err);
182 return;
183 }
184
185 g_pb_speed = speed;
186 SET_FLAG(playback_speed_read);
187 }
188
mcc_set_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)189 static void mcc_set_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed)
190 {
191 if (err) {
192 FAIL("Playback speed set failed (%d)", err);
193 return;
194 }
195
196 g_pb_speed = speed;
197 SET_FLAG(playback_speed_set);
198 }
199
mcc_read_seeking_speed_cb(struct bt_conn * conn,int err,int8_t speed)200 static void mcc_read_seeking_speed_cb(struct bt_conn *conn, int err,
201 int8_t speed)
202 {
203 if (err) {
204 FAIL("Seeking speed read failed (%d)", err);
205 return;
206 }
207
208 SET_FLAG(seeking_speed_read);
209 }
210
mcc_read_segments_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)211 static void mcc_read_segments_obj_id_cb(struct bt_conn *conn, int err,
212 uint64_t id)
213 {
214 if (err) {
215 FAIL("Track Segments ID read failed (%d)\n", err);
216 return;
217 }
218
219 g_track_segments_object_id = id;
220 SET_FLAG(track_segments_object_id_read);
221 }
222
mcc_read_current_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)223 static void mcc_read_current_track_obj_id_cb(struct bt_conn *conn, int err,
224 uint64_t id)
225 {
226 if (err) {
227 FAIL("Current Track Object ID read failed (%d)\n", err);
228 return;
229 }
230
231 g_current_track_object_id = id;
232 SET_FLAG(current_track_object_id_read);
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 if (err) {
239 FAIL("Current Track Object ID set failed (%d)\n", err);
240 return;
241 }
242
243 g_current_track_object_id = id;
244 SET_FLAG(current_track_object_id_set);
245 }
246
mcc_read_next_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)247 static void mcc_read_next_track_obj_id_cb(struct bt_conn *conn, int err,
248 uint64_t id)
249 {
250 if (err) {
251 FAIL("Next Track Object ID read failed (%d)\n", err);
252 return;
253 }
254
255 g_next_track_object_id = id;
256 SET_FLAG(next_track_object_id_read);
257 }
258
mcc_set_next_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)259 static void mcc_set_next_track_obj_id_cb(struct bt_conn *conn, int err,
260 uint64_t id)
261 {
262 if (err) {
263 FAIL("Next Track Object ID set failed (%d)\n", err);
264 return;
265 }
266
267 g_next_track_object_id = id;
268 SET_FLAG(next_track_object_id_set);
269 }
270
mcc_read_current_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)271 static void mcc_read_current_group_obj_id_cb(struct bt_conn *conn, int err,
272 uint64_t id)
273 {
274 if (err) {
275 FAIL("Current Group Object ID read failed (%d)\n", err);
276 return;
277 }
278
279 g_current_group_object_id = id;
280 SET_FLAG(current_group_object_id_read);
281 }
282
mcc_set_current_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)283 static void mcc_set_current_group_obj_id_cb(struct bt_conn *conn, int err,
284 uint64_t id)
285 {
286 if (err) {
287 FAIL("Current Group Object ID set failed (%d)\n", err);
288 return;
289 }
290
291 g_current_group_object_id = id;
292 SET_FLAG(current_group_object_id_set);
293 }
294
mcc_read_parent_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)295 static void mcc_read_parent_group_obj_id_cb(struct bt_conn *conn, int err,
296 uint64_t id)
297 {
298 if (err) {
299 FAIL("Parent Group Object ID read failed (%d)\n", err);
300 return;
301 }
302
303 g_parent_group_object_id = id;
304 SET_FLAG(parent_group_object_id_read);
305 }
306
mcc_read_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)307 static void mcc_read_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
308 {
309 if (err) {
310 FAIL("Playing order read failed (%d)", err);
311 return;
312 }
313
314 g_playing_order = order;
315 SET_FLAG(playing_order_read);
316 }
317
mcc_set_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)318 static void mcc_set_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
319 {
320 if (err) {
321 FAIL("Playing order set failed (%d)", err);
322 return;
323 }
324
325 g_playing_order = order;
326 SET_FLAG(playing_order_set);
327 }
328
mcc_read_playing_orders_supported_cb(struct bt_conn * conn,int err,uint16_t orders)329 static void mcc_read_playing_orders_supported_cb(struct bt_conn *conn, int err,
330 uint16_t orders)
331 {
332 if (err) {
333 FAIL("Playing orders supported read failed (%d)", err);
334 return;
335 }
336
337 SET_FLAG(playing_orders_supported_read);
338 }
339
mcc_read_media_state_cb(struct bt_conn * conn,int err,uint8_t state)340 static void mcc_read_media_state_cb(struct bt_conn *conn, int err, uint8_t state)
341 {
342 if (err) {
343 FAIL("Media State read failed (%d)", err);
344 return;
345 }
346
347 g_state = state;
348 SET_FLAG(media_state_read);
349 }
350
mcc_send_command_cb(struct bt_conn * conn,int err,const struct mpl_cmd * cmd)351 static void mcc_send_command_cb(struct bt_conn *conn, int err, const struct mpl_cmd *cmd)
352 {
353 if (err) {
354 FAIL("Command send failed (%d) - opcode: %u, param: %d",
355 err, cmd->opcode, cmd->param);
356 return;
357 }
358
359 SET_FLAG(command_sent);
360 }
361
mcc_cmd_ntf_cb(struct bt_conn * conn,int err,const struct mpl_cmd_ntf * ntf)362 static void mcc_cmd_ntf_cb(struct bt_conn *conn, int err, const struct mpl_cmd_ntf *ntf)
363 {
364 if (err) {
365 FAIL("Command notification error (%d) - opcode: %u, result: %u",
366 err, ntf->requested_opcode, ntf->result_code);
367 return;
368 }
369
370 g_command_result = ntf->result_code;
371 SET_FLAG(command_notified);
372 }
373
mcc_read_opcodes_supported_cb(struct bt_conn * conn,int err,uint32_t opcodes)374 static void mcc_read_opcodes_supported_cb(struct bt_conn *conn, int err,
375 uint32_t opcodes)
376 {
377 if (err != 0) {
378 FAIL("Media State read failed (%d)", err);
379 return;
380 }
381
382 g_supported_opcodes = opcodes;
383 SET_FLAG(supported_opcodes_read);
384 }
385
mcc_send_search_cb(struct bt_conn * conn,int err,const struct mpl_search * search)386 static void mcc_send_search_cb(struct bt_conn *conn, int err,
387 const struct mpl_search *search)
388 {
389 if (err) {
390 FAIL("Search send failed (%d)", err);
391 return;
392 }
393
394 SET_FLAG(search_sent);
395 }
396
mcc_search_ntf_cb(struct bt_conn * conn,int err,uint8_t result_code)397 static void mcc_search_ntf_cb(struct bt_conn *conn, int err, uint8_t result_code)
398 {
399 if (err) {
400 FAIL("Search notification error (%d), result code: %u",
401 err, result_code);
402 return;
403 }
404
405 g_search_result = result_code;
406 SET_FLAG(search_notified);
407 }
408
mcc_read_search_results_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)409 static void mcc_read_search_results_obj_id_cb(struct bt_conn *conn, int err,
410 uint64_t id)
411 {
412 if (err) {
413 FAIL("Search Results Object ID read failed (%d)", err);
414 return;
415 }
416
417 g_search_results_object_id = id;
418 SET_FLAG(search_results_object_id_read);
419 }
420
mcc_read_content_control_id_cb(struct bt_conn * conn,int err,uint8_t ccid)421 static void mcc_read_content_control_id_cb(struct bt_conn *conn, int err, uint8_t ccid)
422 {
423 if (err) {
424 FAIL("Content control ID read failed (%d)", err);
425 return;
426 }
427
428 SET_FLAG(ccid_read);
429 }
430
mcc_otc_obj_selected_cb(struct bt_conn * conn,int err)431 static void mcc_otc_obj_selected_cb(struct bt_conn *conn, int err)
432 {
433 if (err) {
434 FAIL("Selecting object failed (%d)\n", err);
435 return;
436 }
437
438 SET_FLAG(object_selected);
439 }
440
mcc_otc_obj_metadata_cb(struct bt_conn * conn,int err)441 static void mcc_otc_obj_metadata_cb(struct bt_conn *conn, int err)
442 {
443 if (err) {
444 FAIL("Reading object metadata failed (%d)\n", err);
445 return;
446 }
447
448 SET_FLAG(metadata_read);
449 }
450
mcc_icon_object_read_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)451 static void mcc_icon_object_read_cb(struct bt_conn *conn, int err,
452 struct net_buf_simple *buf)
453 {
454 if (err) {
455 FAIL("Reading Icon Object failed (%d)", err);
456 return;
457 }
458
459 SET_FLAG(object_read);
460 }
461
mcc_track_segments_object_read_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)462 static void mcc_track_segments_object_read_cb(struct bt_conn *conn, int err,
463 struct net_buf_simple *buf)
464 {
465 if (err) {
466 FAIL("Reading Track Segments Object failed (%d)", err);
467 return;
468 }
469
470 SET_FLAG(object_read);
471 }
472
mcc_otc_read_current_track_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)473 static void mcc_otc_read_current_track_object_cb(struct bt_conn *conn, int err,
474 struct net_buf_simple *buf)
475 {
476 if (err) {
477 FAIL("Current Track Object read failed (%d)", err);
478 return;
479 }
480
481 SET_FLAG(object_read);
482 }
483
mcc_otc_read_next_track_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)484 static void mcc_otc_read_next_track_object_cb(struct bt_conn *conn, int err,
485 struct net_buf_simple *buf)
486 {
487 if (err) {
488 FAIL("Next Track Object read failed (%d)", err);
489 return;
490 }
491
492 SET_FLAG(object_read);
493 }
494
mcc_otc_read_parent_group_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)495 static void mcc_otc_read_parent_group_object_cb(struct bt_conn *conn, int err,
496 struct net_buf_simple *buf)
497 {
498 if (err) {
499 FAIL("Parent Group Object read failed (%d)", err);
500 return;
501 }
502
503 SET_FLAG(object_read);
504 }
505
mcc_otc_read_current_group_object_cb(struct bt_conn * conn,int err,struct net_buf_simple * buf)506 static void mcc_otc_read_current_group_object_cb(struct bt_conn *conn, int err,
507 struct net_buf_simple *buf)
508 {
509 if (err) {
510 FAIL("Current Group Object read failed (%d)", err);
511 return;
512 }
513
514 SET_FLAG(object_read);
515 }
516
do_mcc_init(void)517 int do_mcc_init(void)
518 {
519 /* Set up the callbacks */
520 mcc_cb.discover_mcs = mcc_discover_mcs_cb;
521 mcc_cb.read_player_name = mcc_read_player_name_cb;
522 mcc_cb.read_icon_obj_id = mcc_read_icon_obj_id_cb;
523 mcc_cb.read_icon_url = mcc_read_icon_url_cb;
524 mcc_cb.track_changed_ntf = mcc_track_changed_ntf_cb;
525 mcc_cb.read_track_title = mcc_read_track_title_cb;
526 mcc_cb.read_track_duration = mcc_read_track_duration_cb;
527 mcc_cb.read_track_position = mcc_read_track_position_cb;
528 mcc_cb.set_track_position = mcc_set_track_position_cb;
529 mcc_cb.read_playback_speed = mcc_read_playback_speed_cb;
530 mcc_cb.set_playback_speed = mcc_set_playback_speed_cb;
531 mcc_cb.read_seeking_speed = mcc_read_seeking_speed_cb;
532 mcc_cb.read_segments_obj_id = mcc_read_segments_obj_id_cb;
533 mcc_cb.read_current_track_obj_id = mcc_read_current_track_obj_id_cb;
534 mcc_cb.set_current_track_obj_id = mcc_set_current_track_obj_id_cb;
535 mcc_cb.read_next_track_obj_id = mcc_read_next_track_obj_id_cb;
536 mcc_cb.set_next_track_obj_id = mcc_set_next_track_obj_id_cb;
537 mcc_cb.read_current_group_obj_id = mcc_read_current_group_obj_id_cb;
538 mcc_cb.set_current_group_obj_id = mcc_set_current_group_obj_id_cb;
539 mcc_cb.read_parent_group_obj_id = mcc_read_parent_group_obj_id_cb;
540 mcc_cb.read_playing_order = mcc_read_playing_order_cb;
541 mcc_cb.set_playing_order = mcc_set_playing_order_cb;
542 mcc_cb.read_playing_orders_supported = mcc_read_playing_orders_supported_cb;
543 mcc_cb.read_media_state = mcc_read_media_state_cb;
544 mcc_cb.send_cmd = mcc_send_command_cb;
545 mcc_cb.cmd_ntf = mcc_cmd_ntf_cb;
546 mcc_cb.read_opcodes_supported = mcc_read_opcodes_supported_cb;
547 mcc_cb.send_search = mcc_send_search_cb;
548 mcc_cb.search_ntf = mcc_search_ntf_cb;
549 mcc_cb.read_search_results_obj_id = mcc_read_search_results_obj_id_cb;
550 mcc_cb.read_content_control_id = mcc_read_content_control_id_cb;
551 mcc_cb.otc_obj_selected = mcc_otc_obj_selected_cb;
552 mcc_cb.otc_obj_metadata = mcc_otc_obj_metadata_cb;
553 mcc_cb.otc_icon_object = mcc_icon_object_read_cb;
554 mcc_cb.otc_track_segments_object = mcc_track_segments_object_read_cb;
555 mcc_cb.otc_current_track_object = mcc_otc_read_current_track_object_cb;
556 mcc_cb.otc_next_track_object = mcc_otc_read_next_track_object_cb;
557 mcc_cb.otc_current_group_object = mcc_otc_read_current_group_object_cb;
558 mcc_cb.otc_parent_group_object = mcc_otc_read_parent_group_object_cb;
559
560 /* Initialize the module */
561 return bt_mcc_init(&mcc_cb);
562 }
563
564 /* Helper function - select object and read the object metadata
565 *
566 * Will FAIL the test on errors calling select and read metadata.
567 * Will WAIT (hang) until callbacks are received.
568 * If callbacks are not received, the test fill FAIL due to timeout.
569 *
570 * @param object_id ID of the object to select and read metadata for
571 */
test_select_obj_id(uint64_t id)572 static void test_select_obj_id(uint64_t id)
573 {
574 uint64_t invalid_id;
575 int err;
576
577 /* Invalid behavior */
578 err = bt_ots_client_select_id(NULL, default_conn, id);
579 if (err == 0) {
580 FAIL("bt_ots_client_select_id did not fail with NULL OTS instance");
581 return;
582 }
583
584 err = bt_ots_client_select_id(bt_mcc_otc_inst(default_conn), NULL, id);
585 if (err == 0) {
586 FAIL("bt_ots_client_select_id did not fail with NULL conn");
587 return;
588 }
589
590 invalid_id = BT_OTS_OBJ_ID_MIN - 1;
591
592 err = bt_ots_client_select_id(bt_mcc_otc_inst(default_conn), default_conn, invalid_id);
593 if (err == 0) {
594 FAIL("bt_ots_client_select_id did not fail with invalid ID 0x%016llx",
595 invalid_id);
596 return;
597 }
598
599 invalid_id = BT_OTS_OBJ_ID_MAX + 1;
600
601 err = bt_ots_client_select_id(bt_mcc_otc_inst(default_conn), default_conn, invalid_id);
602 if (err == 0) {
603 FAIL("bt_ots_client_select_id did not fail with invalid ID 0x%016llx",
604 invalid_id);
605 return;
606 }
607
608 /* Valid behavior */
609 UNSET_FLAG(object_selected);
610 err = bt_ots_client_select_id(bt_mcc_otc_inst(default_conn),
611 default_conn, id);
612 if (err) {
613 FAIL("Failed to select object\n");
614 return;
615 }
616
617 WAIT_FOR_FLAG(object_selected);
618 printk("Selecting object succeeded\n");
619 }
620
test_read_object_meta(void)621 static void test_read_object_meta(void)
622 {
623 int err;
624
625 /* Invalid behavior */
626 err = bt_mcc_otc_read_object_metadata(NULL);
627 if (err == 0) {
628 FAIL("bt_mcc_otc_read_object_metadata did not fail with NULL conn");
629 return;
630 }
631
632 /* Valid behavior */
633
634 UNSET_FLAG(metadata_read);
635 err = bt_mcc_otc_read_object_metadata(default_conn);
636 if (err) {
637 FAIL("Failed to read object metadata\n");
638 return;
639 }
640
641 WAIT_FOR_FLAG(metadata_read);
642 printk("Reading object metadata succeeded\n");
643 }
644
645 /* Helper function to read the media state and verify that it is as expected
646 * Will FAIL on error reading the media state
647 * Will FAIL if the state is not as expected
648 *
649 * Returns true if the state is as expected
650 * Returns false in case of errors, or if the state is not as expected
651 */
test_verify_media_state_wait_flags(uint8_t expected_state)652 static bool test_verify_media_state_wait_flags(uint8_t expected_state)
653 {
654 int err;
655
656 UNSET_FLAG(media_state_read);
657 err = bt_mcc_read_media_state(default_conn);
658 if (err) {
659 FAIL("Failed to read media state: %d", err);
660 return false;
661 }
662
663 WAIT_FOR_FLAG(media_state_read);
664 if (g_state != expected_state) {
665 FAIL("Server is not in expected state: %d, expected: %d\n",
666 g_state, expected_state);
667 return false;
668 }
669
670 return true;
671 }
672
test_read_supported_opcodes(void)673 static void test_read_supported_opcodes(void)
674 {
675 int err;
676
677 /* Invalid behavior */
678 err = bt_mcc_read_opcodes_supported(NULL);
679 if (err == 0) {
680 FAIL("bt_mcc_read_opcodes_supported did not fail with NULL conn");
681 return;
682 }
683
684 /* Valid behavior */
685 UNSET_FLAG(supported_opcodes_read);
686 err = bt_mcc_read_opcodes_supported(default_conn);
687 if (err != 0) {
688 FAIL("Failed to read supported opcodes: %d", err);
689 return;
690 }
691
692 WAIT_FOR_FLAG(supported_opcodes_read);
693 printk("Supported opcodes read succeeded\n");
694 }
695
696 /* This will only test invalid behavior for send_cmd as valid behavior is
697 * tested by test_send_cmd_wait_flags
698 */
test_invalid_send_cmd(void)699 static void test_invalid_send_cmd(void)
700 {
701 struct mpl_cmd cmd = { 0 };
702 int err;
703
704 err = bt_mcc_send_cmd(NULL, &cmd);
705 if (err == 0) {
706 FAIL("bt_mcc_send_cmd did not fail with NULL conn");
707 return;
708 }
709
710 err = bt_mcc_send_cmd(default_conn, NULL);
711 if (err == 0) {
712 FAIL("bt_mcc_send_cmd did not fail with NULL cmd");
713 return;
714 }
715
716 cmd.opcode = 0; /* Invalid opcode */
717
718 err = bt_mcc_send_cmd(default_conn, &cmd);
719 if (err == 0) {
720 FAIL("bt_mcc_send_cmd did not fail with invalid opcode %u", cmd.opcode);
721 return;
722 }
723
724 cmd.opcode = 0x80; /* Invalid opcode */
725
726 err = bt_mcc_send_cmd(default_conn, &cmd);
727 if (err == 0) {
728 FAIL("bt_mcc_send_cmd did not fail with invalid opcode %u", cmd.opcode);
729 return;
730 }
731 }
732
733 /* Helper function to write commands to the control point, including the
734 * flag handling.
735 * Will FAIL on error to send the command.
736 * Will WAIT for the required flags before returning.
737 */
test_send_cmd_wait_flags(struct mpl_cmd * cmd)738 static void test_send_cmd_wait_flags(struct mpl_cmd *cmd)
739 {
740 int err;
741
742 /* Need both flags, even if the notification result is what we care
743 * about. The notification may come before the write callback, and if
744 * the write callback has not yet arrived, we will get EBUSY at the
745 * next call.
746 */
747 UNSET_FLAG(command_sent);
748 UNSET_FLAG(command_notified);
749 err = bt_mcc_send_cmd(default_conn, cmd);
750 if (err) {
751 FAIL("Failed to send command: %d, opcode: %u",
752 err, cmd->opcode);
753 return;
754 }
755
756 WAIT_FOR_FLAG(command_sent);
757 WAIT_FOR_FLAG(command_notified);
758 }
759
test_cp_play(void)760 static void test_cp_play(void)
761 {
762 struct mpl_cmd cmd;
763
764 cmd.opcode = BT_MCS_OPC_PLAY;
765 cmd.use_param = false;
766
767 test_send_cmd_wait_flags(&cmd);
768
769 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
770 FAIL("PLAY command failed\n");
771 return;
772 }
773
774 if (test_verify_media_state_wait_flags(BT_MCS_MEDIA_STATE_PLAYING)) {
775 printk("PLAY command succeeded\n");
776 }
777 }
778
test_cp_pause(void)779 static void test_cp_pause(void)
780 {
781 struct mpl_cmd cmd;
782
783 cmd.opcode = BT_MCS_OPC_PAUSE;
784 cmd.use_param = false;
785
786 test_send_cmd_wait_flags(&cmd);
787
788 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
789 FAIL("PAUSE command failed\n");
790 return;
791 }
792
793 if (test_verify_media_state_wait_flags(BT_MCS_MEDIA_STATE_PAUSED)) {
794 printk("PAUSE command succeeded\n");
795 }
796 }
797
test_cp_fast_rewind(void)798 static void test_cp_fast_rewind(void)
799 {
800 const int32_t tmp_pos = g_pos;
801 struct mpl_cmd cmd;
802
803 cmd.opcode = BT_MCS_OPC_FAST_REWIND;
804 cmd.use_param = false;
805
806 UNSET_FLAG(track_position_read);
807
808 test_send_cmd_wait_flags(&cmd);
809
810 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
811 FAIL("FAST REWIND command failed\n");
812 return;
813 }
814
815 if (test_verify_media_state_wait_flags(BT_MCS_MEDIA_STATE_SEEKING)) {
816 printk("FAST REWIND command succeeded\n");
817 }
818
819 /* Wait for the track position to change during rewinding */
820 WAIT_FOR_FLAG(track_position_read);
821 if (tmp_pos <= g_pos) {
822 FAIL("Position did not change during rewinding");
823 return;
824 }
825 }
826
test_cp_fast_forward(void)827 static void test_cp_fast_forward(void)
828 {
829 const int32_t tmp_pos = g_pos;
830 struct mpl_cmd cmd;
831
832 cmd.opcode = BT_MCS_OPC_FAST_FORWARD;
833 cmd.use_param = false;
834
835 UNSET_FLAG(track_position_read);
836
837 test_send_cmd_wait_flags(&cmd);
838
839 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
840 FAIL("FAST FORWARD command failed\n");
841 return;
842 }
843
844 if (test_verify_media_state_wait_flags(BT_MCS_MEDIA_STATE_SEEKING)) {
845 printk("FAST FORWARD command succeeded\n");
846 }
847
848 /* Wait for the track position to change during forwarding */
849 WAIT_FOR_FLAG(track_position_read);
850 if (tmp_pos >= g_pos) {
851 FAIL("Position did not change during forwarding");
852 return;
853 }
854 }
855
test_cp_stop(void)856 static void test_cp_stop(void)
857 {
858 struct mpl_cmd cmd;
859
860 cmd.opcode = BT_MCS_OPC_STOP;
861 cmd.use_param = false;
862
863 test_send_cmd_wait_flags(&cmd);
864
865 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
866 FAIL("STOP command failed\n");
867 return;
868 }
869
870 /* There is no "STOPPED" state in the spec - STOP goes to PAUSED */
871 if (test_verify_media_state_wait_flags(BT_MCS_MEDIA_STATE_PAUSED)) {
872 printk("STOP command succeeded\n");
873 }
874 }
875
test_cp_move_relative(void)876 static void test_cp_move_relative(void)
877 {
878 int err;
879 struct mpl_cmd cmd;
880
881 /* Assumes that the server is in a state where it is able to change
882 * the current track position
883 * Also assumes position will not change by itself, which is wrong if
884 * if the player is playing.
885 */
886 UNSET_FLAG(track_position_read);
887 err = bt_mcc_read_track_position(default_conn);
888 if (err) {
889 FAIL("Failed to read track position: %d\n", err);
890 return;
891 }
892
893 WAIT_FOR_FLAG(track_position_read);
894 uint32_t tmp_pos = g_pos;
895
896 cmd.opcode = BT_MCS_OPC_MOVE_RELATIVE;
897 cmd.use_param = true;
898 cmd.param = 1000; /* Position change, measured in 1/100 of a second */
899
900 test_send_cmd_wait_flags(&cmd);
901
902 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
903 FAIL("MOVE RELATIVE command failed\n");
904 return;
905 }
906
907 UNSET_FLAG(track_position_read);
908 err = bt_mcc_read_track_position(default_conn);
909 if (err) {
910 FAIL("Failed to read track position: %d\n", err);
911 return;
912 }
913
914 WAIT_FOR_FLAG(track_position_read);
915 if (g_pos == tmp_pos) {
916 /* Position did not change */
917 FAIL("Server did not move track position\n");
918 return;
919 }
920
921 printk("MOVE RELATIVE command succeeded\n");
922 }
923
test_cp_prev_segment(void)924 static void test_cp_prev_segment(void)
925 {
926 struct mpl_cmd cmd;
927
928 /* Assumes that the server is in a state where there is a current
929 * track that has segments, and where the server may switch between
930 * these
931 */
932
933 /* To properly verify track segment changes, the track segments
934 * object must be downloaded and parsed. That is somewhat complex,
935 * and is getting close to what the qualification tests do.
936 * Alternatively, the track position may be checked, but the server
937 * implementation does not set that for segment changes yet.
938 * For now, we will settle for seeing that the opcodes are accepted.
939 */
940
941 cmd.opcode = BT_MCS_OPC_PREV_SEGMENT;
942 cmd.use_param = false;
943
944 test_send_cmd_wait_flags(&cmd);
945
946 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
947 FAIL("PREV SEGMENT command failed\n");
948 return;
949 }
950
951 printk("PREV SEGMENT command succeeded\n");
952 }
953
test_cp_next_segment(void)954 static void test_cp_next_segment(void)
955 {
956 struct mpl_cmd cmd;
957
958 cmd.opcode = BT_MCS_OPC_NEXT_SEGMENT;
959 cmd.use_param = false;
960
961 test_send_cmd_wait_flags(&cmd);
962
963 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
964 FAIL("NEXT SEGMENT command failed\n");
965 return;
966 }
967
968 printk("NEXT SEGMENT command succeeded\n");
969 }
970
test_cp_first_segment(void)971 static void test_cp_first_segment(void)
972 {
973 struct mpl_cmd cmd;
974
975 cmd.opcode = BT_MCS_OPC_FIRST_SEGMENT;
976 cmd.use_param = false;
977
978 test_send_cmd_wait_flags(&cmd);
979
980 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
981 FAIL("FIRST SEGMENT command failed\n");
982 return;
983 }
984
985 printk("FIRST SEGMENT command succeeded\n");
986 }
987
test_cp_last_segment(void)988 static void test_cp_last_segment(void)
989 {
990 struct mpl_cmd cmd;
991
992 cmd.opcode = BT_MCS_OPC_LAST_SEGMENT;
993 cmd.use_param = false;
994
995 test_send_cmd_wait_flags(&cmd);
996
997 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
998 FAIL("LAST SEGMENT command failed\n");
999 return;
1000 }
1001
1002 printk("LAST SEGMENT command succeeded\n");
1003 }
1004
test_cp_goto_segment(void)1005 static void test_cp_goto_segment(void)
1006 {
1007 struct mpl_cmd cmd;
1008
1009 cmd.opcode = BT_MCS_OPC_GOTO_SEGMENT;
1010 cmd.use_param = true;
1011 cmd.param = 2; /* Second segment - not the first, maybe not last */
1012
1013 test_send_cmd_wait_flags(&cmd);
1014
1015 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1016 FAIL("GOTO SEGMENT command failed\n");
1017 return;
1018 }
1019
1020 printk("GOTO SEGMENT command succeeded\n");
1021 }
1022
1023 /* Helper function to read the current track object ID, including flag handling
1024 * Will FAIL on error reading object ID
1025 * Will WAIT until the read is completed (object ID flag read flag is set)
1026 */
test_read_current_track_object_id_wait_flags(void)1027 static void test_read_current_track_object_id_wait_flags(void)
1028 {
1029 int err;
1030
1031 UNSET_FLAG(current_track_object_id_read);
1032 err = bt_mcc_read_current_track_obj_id(default_conn);
1033 if (err) {
1034 FAIL("Failed to read current track object ID: %d", err);
1035 return;
1036 }
1037
1038 WAIT_FOR_FLAG(current_track_object_id_read);
1039 }
1040
test_cp_prev_track(void)1041 static void test_cp_prev_track(void)
1042 {
1043 uint64_t object_id;
1044 struct mpl_cmd cmd;
1045
1046 /* Assumes that the server is in a state where it has multiple tracks
1047 * and can change between them.
1048 */
1049
1050 /* To verify that a track change has happened, the test checks that the
1051 * current track object ID has changed.
1052 */
1053
1054 cmd.opcode = BT_MCS_OPC_PREV_TRACK;
1055 cmd.use_param = false;
1056
1057 test_read_current_track_object_id_wait_flags();
1058 object_id = g_current_track_object_id;
1059
1060 test_send_cmd_wait_flags(&cmd);
1061
1062 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1063 FAIL("PREV TRACK command failed\n");
1064 return;
1065 }
1066
1067 test_read_current_track_object_id_wait_flags();
1068
1069 if (g_current_track_object_id == object_id) {
1070 /* Track did not change */
1071 FAIL("Server did not change track\n");
1072 return;
1073 }
1074
1075 printk("PREV TRACK command succeeded\n");
1076 }
1077
test_cp_next_track_and_track_changed(void)1078 static void test_cp_next_track_and_track_changed(void)
1079 {
1080 uint64_t object_id;
1081 struct mpl_cmd cmd;
1082
1083 /* This test is also used to test the track changed notification */
1084 UNSET_FLAG(track_change_notified);
1085
1086 cmd.opcode = BT_MCS_OPC_NEXT_TRACK;
1087 cmd.use_param = false;
1088
1089 test_read_current_track_object_id_wait_flags();
1090 object_id = g_current_track_object_id;
1091
1092 test_send_cmd_wait_flags(&cmd);
1093
1094 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1095 FAIL("NEXT TRACK command failed\n");
1096 return;
1097 }
1098
1099 WAIT_FOR_FLAG(track_change_notified);
1100 printk("Track change notified\n");
1101
1102 test_read_current_track_object_id_wait_flags();
1103
1104 if (g_current_track_object_id == object_id) {
1105 FAIL("Server did not change track\n");
1106 return;
1107 }
1108
1109 printk("NEXT TRACK command succeeded\n");
1110 }
1111
test_cp_first_track(void)1112 static void test_cp_first_track(void)
1113 {
1114 uint64_t object_id;
1115 struct mpl_cmd cmd;
1116
1117 cmd.opcode = BT_MCS_OPC_FIRST_TRACK;
1118 cmd.use_param = false;
1119
1120 test_read_current_track_object_id_wait_flags();
1121 object_id = g_current_track_object_id;
1122
1123 test_send_cmd_wait_flags(&cmd);
1124
1125 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1126 FAIL("FIRST TRACK command failed\n");
1127 return;
1128 }
1129
1130 test_read_current_track_object_id_wait_flags();
1131
1132 if (g_current_track_object_id == object_id) {
1133 FAIL("Server did not change track\n");
1134 return;
1135 }
1136
1137 printk("FIRST TRACK command succeeded\n");
1138 }
1139
test_cp_last_track(void)1140 static void test_cp_last_track(void)
1141 {
1142 uint64_t object_id;
1143 struct mpl_cmd cmd;
1144
1145 cmd.opcode = BT_MCS_OPC_LAST_TRACK;
1146 cmd.use_param = false;
1147
1148 test_read_current_track_object_id_wait_flags();
1149 object_id = g_current_track_object_id;
1150
1151 test_send_cmd_wait_flags(&cmd);
1152
1153 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1154 FAIL("LAST TRACK command failed\n");
1155 return;
1156 }
1157
1158 test_read_current_track_object_id_wait_flags();
1159
1160 if (g_current_track_object_id == object_id) {
1161 FAIL("Server did not change track\n");
1162 return;
1163 }
1164
1165 printk("LAST TRACK command succeeded\n");
1166 }
1167
test_cp_goto_track(void)1168 static void test_cp_goto_track(void)
1169 {
1170 uint64_t object_id;
1171 struct mpl_cmd cmd;
1172
1173 cmd.opcode = BT_MCS_OPC_GOTO_TRACK;
1174 cmd.use_param = true;
1175 cmd.param = 2; /* Second track, not the first, maybe not the last */
1176
1177 test_read_current_track_object_id_wait_flags();
1178 object_id = g_current_track_object_id;
1179
1180 test_send_cmd_wait_flags(&cmd);
1181
1182 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1183 FAIL("GOTO TRACK command failed\n");
1184 return;
1185 }
1186
1187 test_read_current_track_object_id_wait_flags();
1188
1189 if (g_current_track_object_id == object_id) {
1190 FAIL("Server did not change track\n");
1191 return;
1192 }
1193
1194 printk("GOTO TRACK command succeeded\n");
1195 }
1196
1197 /* Helper function to read the current group object ID, including flag handling
1198 * Will FAIL on error reading object ID
1199 * Will WAIT until the read is completed (object ID flag read flag is set)
1200 */
test_read_current_group_object_id_wait_flags(void)1201 static void test_read_current_group_object_id_wait_flags(void)
1202 {
1203 int err;
1204
1205 UNSET_FLAG(current_group_object_id_read);
1206 err = bt_mcc_read_current_group_obj_id(default_conn);
1207 if (err) {
1208 FAIL("Failed to read current group object ID: %d", err);
1209 return;
1210 }
1211
1212 WAIT_FOR_FLAG(current_group_object_id_read);
1213 }
1214
test_cp_prev_group(void)1215 static void test_cp_prev_group(void)
1216 {
1217 uint64_t object_id;
1218 struct mpl_cmd cmd;
1219
1220 /* Assumes that the server is in a state where it has multiple groups
1221 * and can change between them.
1222 */
1223
1224 /* To verify that a group change has happened, the test checks that the
1225 * current group object ID has changed.
1226 */
1227
1228 cmd.opcode = BT_MCS_OPC_PREV_GROUP;
1229 cmd.use_param = false;
1230
1231 test_read_current_group_object_id_wait_flags();
1232 object_id = g_current_group_object_id;
1233
1234 test_send_cmd_wait_flags(&cmd);
1235
1236 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1237 FAIL("PREV GROUP command failed\n");
1238 return;
1239 }
1240
1241 test_read_current_group_object_id_wait_flags();
1242
1243 if (g_current_group_object_id == object_id) {
1244 /* Group did not change */
1245 FAIL("Server did not change group\n");
1246 return;
1247 }
1248
1249 printk("PREV GROUP command succeeded\n");
1250 }
1251
test_cp_next_group(void)1252 static void test_cp_next_group(void)
1253 {
1254 uint64_t object_id;
1255 struct mpl_cmd cmd;
1256
1257 cmd.opcode = BT_MCS_OPC_NEXT_GROUP;
1258 cmd.use_param = false;
1259
1260 test_read_current_group_object_id_wait_flags();
1261 object_id = g_current_group_object_id;
1262
1263 test_send_cmd_wait_flags(&cmd);
1264
1265 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1266 FAIL("NEXT GROUP command failed\n");
1267 return;
1268 }
1269
1270 test_read_current_group_object_id_wait_flags();
1271
1272 if (g_current_group_object_id == object_id) {
1273 FAIL("Server did not change group\n");
1274 return;
1275 }
1276
1277 printk("NEXT GROUP command succeeded\n");
1278 }
1279
test_cp_first_group(void)1280 static void test_cp_first_group(void)
1281 {
1282 uint64_t object_id;
1283 struct mpl_cmd cmd;
1284
1285 cmd.opcode = BT_MCS_OPC_FIRST_GROUP;
1286 cmd.use_param = false;
1287
1288 test_read_current_group_object_id_wait_flags();
1289 object_id = g_current_group_object_id;
1290
1291 test_send_cmd_wait_flags(&cmd);
1292
1293 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1294 FAIL("FIRST GROUP command failed\n");
1295 return;
1296 }
1297
1298 test_read_current_group_object_id_wait_flags();
1299
1300 if (g_current_group_object_id == object_id) {
1301 FAIL("Server did not change group\n");
1302 return;
1303 }
1304
1305 printk("FIRST GROUP command succeeded\n");
1306 }
1307
test_cp_last_group(void)1308 static void test_cp_last_group(void)
1309 {
1310 uint64_t object_id;
1311 struct mpl_cmd cmd;
1312
1313 cmd.opcode = BT_MCS_OPC_LAST_GROUP;
1314 cmd.use_param = false;
1315
1316 test_read_current_group_object_id_wait_flags();
1317 object_id = g_current_group_object_id;
1318
1319 test_send_cmd_wait_flags(&cmd);
1320
1321 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1322 FAIL("LAST GROUP command failed\n");
1323 return;
1324 }
1325
1326 test_read_current_group_object_id_wait_flags();
1327
1328 if (g_current_group_object_id == object_id) {
1329 FAIL("Server did not change group\n");
1330 return;
1331 }
1332
1333 printk("LAST GROUP command succeeded\n");
1334 }
1335
test_cp_goto_group(void)1336 static void test_cp_goto_group(void)
1337 {
1338 uint64_t object_id;
1339 struct mpl_cmd cmd;
1340
1341 cmd.opcode = BT_MCS_OPC_GOTO_GROUP;
1342 cmd.use_param = true;
1343 cmd.param = 2; /* Second group, not the first, maybe not the last */
1344
1345 test_read_current_group_object_id_wait_flags();
1346 object_id = g_current_group_object_id;
1347
1348 test_send_cmd_wait_flags(&cmd);
1349
1350 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
1351 FAIL("GOTO GROUP command failed\n");
1352 return;
1353 }
1354
1355 test_read_current_group_object_id_wait_flags();
1356
1357 if (g_current_group_object_id == object_id) {
1358 FAIL("Server did not change group\n");
1359 return;
1360 }
1361
1362 printk("GOTO GROUP command succeeded\n");
1363 }
1364
test_search(void)1365 static void test_search(void)
1366 {
1367 struct mpl_search search = { 0 };
1368 struct mpl_sci sci = {0};
1369 int err;
1370
1371 /* Invalid behavior */
1372 err = bt_mcc_read_search_results_obj_id(NULL);
1373 if (err == 0) {
1374 FAIL("bt_mcc_read_search_results_obj_id did not fail with NULL conn");
1375 return;
1376 }
1377
1378 err = bt_mcc_send_search(NULL, &search);
1379 if (err == 0) {
1380 FAIL("bt_mcc_send_search did not fail with NULL conn");
1381 return;
1382 }
1383
1384 err = bt_mcc_send_search(default_conn, NULL);
1385 if (err == 0) {
1386 FAIL("bt_mcc_send_search did not fail with NULL search");
1387 return;
1388 }
1389
1390 search.len = SEARCH_LEN_MAX + 1;
1391
1392 err = bt_mcc_send_search(default_conn, &search);
1393 if (err == 0) {
1394 FAIL("bt_mcc_send_search did not fail with search len above max");
1395 return;
1396 }
1397
1398 search.len = SEARCH_LEN_MIN - 1;
1399
1400 err = bt_mcc_send_search(default_conn, &search);
1401 if (err == 0) {
1402 FAIL("bt_mcc_send_search did not fail with search len below min");
1403 return;
1404 }
1405
1406 /* Valid behavior */
1407 /* Test outline:
1408 * - verify that the search results object ID is zero before search
1409 * - write a search (one search control item) to the search control point,
1410 * get write callback and notification
1411 * - verify that the search results object ID is non-zero
1412 */
1413
1414 UNSET_FLAG(search_results_object_id_read);
1415 err = bt_mcc_read_search_results_obj_id(default_conn);
1416
1417 if (err) {
1418 FAIL("Failed to read search results object ID: %d", err);
1419 return;
1420 }
1421
1422 WAIT_FOR_FLAG(search_results_object_id_read);
1423
1424 /* Set up the search control item, then the search
1425 * Note: As of now, the server implementation only fakes the search,
1426 * so it makes no difference what we search for. The result is the
1427 * same anyway.
1428 */
1429 sci.type = BT_MCS_SEARCH_TYPE_TRACK_NAME;
1430 strcpy(sci.param, "Some track name");
1431 /* Length is length of type, plus length of param w/o termination */
1432 sci.len = sizeof(sci.type) + strlen(sci.param);
1433
1434 search.len = 0;
1435 memcpy(&search.search[search.len], &sci.len, sizeof(sci.len));
1436 search.len += sizeof(sci.len);
1437
1438 memcpy(&search.search[search.len], &sci.type, sizeof(sci.type));
1439 search.len += sizeof(sci.type);
1440
1441 memcpy(&search.search[search.len], &sci.param, strlen(sci.param));
1442 search.len += strlen(sci.param);
1443
1444 UNSET_FLAG(search_sent);
1445 UNSET_FLAG(search_notified);
1446 UNSET_FLAG(search_results_object_id_read);
1447
1448 err = bt_mcc_send_search(default_conn, &search);
1449 if (err) {
1450 FAIL("Failed to write to search control point\n");
1451 return;
1452 }
1453
1454 WAIT_FOR_FLAG(search_sent);
1455 WAIT_FOR_FLAG(search_notified);
1456
1457 if (g_search_result != BT_MCS_SCP_NTF_SUCCESS) {
1458 FAIL("SEARCH operation failed\n");
1459 return;
1460 }
1461
1462 /* A search results object will have been created and the search
1463 * results object ID will have been notified if the search gave results
1464 */
1465 WAIT_FOR_FLAG(search_results_object_id_read);
1466 if (g_search_results_object_id == 0) {
1467 FAIL("No search results\n");
1468 return;
1469 }
1470
1471 printk("SEARCH operation succeeded\n");
1472 }
1473
test_discover(void)1474 static void test_discover(void)
1475 {
1476 int err;
1477
1478 /* Invalid behavior */
1479 err = bt_mcc_discover_mcs(NULL, true);
1480 if (err == 0) {
1481 FAIL("bt_mcc_discover_mcs did not fail with NULL conn");
1482 return;
1483 }
1484
1485 /* Valid behavior */
1486 UNSET_FLAG(discovery_done);
1487
1488 err = bt_mcc_discover_mcs(default_conn, true);
1489 if (err != 0) {
1490 FAIL("Failed to start discovery of MCS: %d\n", err);
1491 }
1492
1493 WAIT_FOR_FLAG(discovery_done);
1494 printk("Discovery of MCS succeeded\n");
1495 }
1496
test_read_player_name(void)1497 static void test_read_player_name(void)
1498 {
1499 int err;
1500
1501 /* Invalid behavior */
1502 err = bt_mcc_read_player_name(NULL);
1503 if (err == 0) {
1504 FAIL("bt_mcc_read_player_name did not fail with NULL conn");
1505 return;
1506 }
1507
1508 /* Valid behavior */
1509 UNSET_FLAG(player_name_read);
1510
1511 err = bt_mcc_read_player_name(default_conn);
1512 if (err != 0) {
1513 FAIL("Failed to read media player name ID: %d", err);
1514 return;
1515 }
1516
1517 WAIT_FOR_FLAG(player_name_read);
1518 printk("Player Name read succeeded\n");
1519 }
1520
test_read_icon_obj_id(void)1521 static void test_read_icon_obj_id(void)
1522 {
1523 int err;
1524
1525 /* Invalid behavior */
1526 err = bt_mcc_read_icon_obj_id(NULL);
1527 if (err == 0) {
1528 FAIL("bt_mcc_read_icon_obj_id did not fail with NULL conn");
1529 return;
1530 }
1531
1532 /* Valid behavior */
1533 UNSET_FLAG(icon_object_id_read);
1534
1535 err = bt_mcc_read_icon_obj_id(default_conn);
1536 if (err != 0) {
1537 FAIL("Failed to read icon object ID: %d", err);
1538 return;
1539 }
1540
1541 WAIT_FOR_FLAG(icon_object_id_read);
1542 printk("Icon Object ID read succeeded\n");
1543 }
1544
test_read_icon_obj(void)1545 static void test_read_icon_obj(void)
1546 {
1547 int err;
1548
1549 /* Invalid behavior */
1550 err = bt_mcc_otc_read_icon_object(NULL);
1551 if (err == 0) {
1552 FAIL("bt_mcc_otc_read_icon_object did not fail with NULL conn");
1553 return;
1554 }
1555
1556 /* Valid behavior */
1557 UNSET_FLAG(object_read);
1558
1559 err = bt_mcc_otc_read_icon_object(default_conn);
1560
1561 if (err != 0) {
1562 FAIL("Failed to read icon object\n");
1563 return;
1564 }
1565
1566 WAIT_FOR_FLAG(object_read);
1567 printk("Reading Icon Object succeeded\n");
1568 }
1569
test_read_icon_url(void)1570 static void test_read_icon_url(void)
1571 {
1572 int err;
1573
1574 /* Invalid behavior */
1575 err = bt_mcc_read_icon_url(NULL);
1576 if (err == 0) {
1577 FAIL("bt_mcc_read_icon_url did not fail with NULL conn");
1578 return;
1579 }
1580
1581 /* Valid behavior */
1582 UNSET_FLAG(icon_url_read);
1583
1584 err = bt_mcc_read_icon_url(default_conn);
1585 if (err != 0) {
1586 FAIL("Failed to read icon url: %d", err);
1587 return;
1588 }
1589
1590 WAIT_FOR_FLAG(icon_url_read);
1591 printk("Icon URL read succeeded\n");
1592 }
1593
test_read_track_title(void)1594 static void test_read_track_title(void)
1595 {
1596 int err;
1597
1598 /* Invalid behavior */
1599 err = bt_mcc_read_track_title(NULL);
1600 if (err == 0) {
1601 FAIL("bt_mcc_read_track_title did not fail with NULL conn");
1602 return;
1603 }
1604
1605 /* Valid behavior */
1606 UNSET_FLAG(track_title_read);
1607
1608 err = bt_mcc_read_track_title(default_conn);
1609 if (err != 0) {
1610 FAIL("Failed to read track_title: %d", err);
1611 return;
1612 }
1613
1614 WAIT_FOR_FLAG(track_title_read);
1615 printk("Track title read succeeded\n");
1616 }
1617
test_read_track_duration(void)1618 static void test_read_track_duration(void)
1619 {
1620 int err;
1621
1622 /* Invalid behavior */
1623 err = bt_mcc_read_track_duration(NULL);
1624 if (err == 0) {
1625 FAIL("bt_mcc_read_track_duration did not fail with NULL conn");
1626 return;
1627 }
1628
1629 /* Valid behavior */
1630 UNSET_FLAG(track_duration_read);
1631
1632 err = bt_mcc_read_track_duration(default_conn);
1633 if (err != 0) {
1634 FAIL("Failed to read track_duration: %d", err);
1635 return;
1636 }
1637
1638 WAIT_FOR_FLAG(track_duration_read);
1639 printk("Track duration read succeeded\n");
1640 }
1641
test_read_track_position(void)1642 static void test_read_track_position(void)
1643 {
1644 int err;
1645
1646 /* Invalid behavior */
1647 err = bt_mcc_read_track_position(NULL);
1648 if (err == 0) {
1649 FAIL("bt_mcc_read_track_position did not fail with NULL conn");
1650 return;
1651 }
1652
1653 /* Valid behavior */
1654 UNSET_FLAG(track_position_read);
1655
1656 err = bt_mcc_read_track_position(default_conn);
1657 if (err != 0) {
1658 FAIL("Failed to read track position: %d", err);
1659 return;
1660 }
1661
1662 WAIT_FOR_FLAG(track_position_read);
1663 printk("Track position read succeeded\n");
1664 }
1665
test_write_track_position(int32_t pos)1666 static void test_write_track_position(int32_t pos)
1667 {
1668 int err;
1669
1670 /* Invalid behavior - There are no invalid positions to test so only test conn */
1671 err = bt_mcc_set_track_position(NULL, pos);
1672 if (err == 0) {
1673 FAIL("bt_mcc_set_track_position did not fail with NULL conn");
1674 return;
1675 }
1676
1677 /* Valid behavior */
1678 UNSET_FLAG(track_position_set);
1679
1680 err = bt_mcc_set_track_position(default_conn, pos);
1681 if (err != 0) {
1682 FAIL("Failed to set track position: %d", err);
1683 return;
1684 }
1685
1686 WAIT_FOR_FLAG(track_position_set);
1687 if (g_pos != pos) {
1688 /* In this controlled case, we expect that the resulting */
1689 /* position is the position given in the set command */
1690 FAIL("Track position set failed: Incorrect position\n");
1691 }
1692
1693 printk("Track position set succeeded\n");
1694 }
1695
test_read_playback_speed(void)1696 static void test_read_playback_speed(void)
1697 {
1698 int err;
1699
1700 /* Invalid behavior */
1701 err = bt_mcc_read_playback_speed(NULL);
1702 if (err == 0) {
1703 FAIL("bt_mcc_read_playback_speed did not fail with NULL conn");
1704 return;
1705 }
1706
1707 /* Valid behavior */
1708 UNSET_FLAG(playback_speed_read);
1709
1710 err = bt_mcc_read_playback_speed(default_conn);
1711 if (err != 0) {
1712 FAIL("Failed to read playback speed: %d", err);
1713 return;
1714 }
1715
1716 WAIT_FOR_FLAG(playback_speed_read);
1717 printk("Playback speed read succeeded\n");
1718 }
1719
test_set_playback_speed(int8_t pb_speed)1720 static void test_set_playback_speed(int8_t pb_speed)
1721 {
1722 int err;
1723
1724 /* Invalid behavior - There are no invalid speeds to test so only test conn */
1725 err = bt_mcc_set_playback_speed(NULL, pb_speed);
1726 if (err == 0) {
1727 FAIL("bt_mcc_set_playback_speed did not fail with NULL conn");
1728 return;
1729 }
1730
1731 /* Valid behavior */
1732 UNSET_FLAG(playback_speed_set);
1733
1734 err = bt_mcc_set_playback_speed(default_conn, pb_speed);
1735 if (err != 0) {
1736 FAIL("Failed to set playback speed: %d", err);
1737 return;
1738 }
1739
1740 WAIT_FOR_FLAG(playback_speed_set);
1741 if (g_pb_speed != pb_speed) {
1742 FAIL("Playback speed failed: Incorrect playback speed\n");
1743 }
1744
1745 printk("Playback speed set succeeded\n");
1746 }
1747
test_read_seeking_speed(void)1748 static void test_read_seeking_speed(void)
1749 {
1750 int err;
1751
1752 /* Invalid behavior */
1753 err = bt_mcc_read_seeking_speed(NULL);
1754 if (err == 0) {
1755 FAIL("bt_mcc_read_seeking_speed did not fail with NULL conn");
1756 return;
1757 }
1758
1759 /* Valid behavior */
1760 UNSET_FLAG(seeking_speed_read);
1761
1762 err = bt_mcc_read_seeking_speed(default_conn);
1763 if (err != 0) {
1764 FAIL("Failed to read seeking speed: %d", err);
1765 return;
1766 }
1767
1768 WAIT_FOR_FLAG(seeking_speed_read);
1769 printk("Seeking speed read succeeded\n");
1770 }
1771
test_read_track_segments_obj_id(void)1772 static void test_read_track_segments_obj_id(void)
1773 {
1774 int err;
1775
1776 /* Invalid behavior */
1777 err = bt_mcc_read_segments_obj_id(NULL);
1778 if (err == 0) {
1779 FAIL("bt_mcc_read_segments_obj_id did not fail with NULL conn");
1780 return;
1781 }
1782
1783 /* Valid behavior */
1784 UNSET_FLAG(track_segments_object_id_read);
1785
1786 err = bt_mcc_read_segments_obj_id(default_conn);
1787 if (err != 0) {
1788 FAIL("Failed to read track segments object ID: %d", err);
1789 return;
1790 }
1791
1792 WAIT_FOR_FLAG(track_segments_object_id_read);
1793 printk("Track Segments Object ID read succeeded\n");
1794 }
1795
test_read_track_segments_object(void)1796 static void test_read_track_segments_object(void)
1797 {
1798 int err;
1799
1800 /* Invalid behavior */
1801 err = bt_mcc_otc_read_track_segments_object(NULL);
1802 if (err == 0) {
1803 FAIL("bt_mcc_otc_read_track_segments_object did not fail with NULL conn");
1804 return;
1805 }
1806
1807 /* Valid behavior */
1808 UNSET_FLAG(object_read);
1809
1810 err = bt_mcc_otc_read_track_segments_object(default_conn);
1811 if (err != 0) {
1812 FAIL("Failed to read track segments object\n");
1813 return;
1814 }
1815
1816 WAIT_FOR_FLAG(object_read);
1817 printk("Reading Track Segments Object succeeded\n");
1818 }
1819
test_set_current_track_obj_id(uint64_t id)1820 static void test_set_current_track_obj_id(uint64_t id)
1821 {
1822 uint64_t invalid_id;
1823 int err;
1824
1825 /* Invalid behavior */
1826 err = bt_mcc_set_current_track_obj_id(NULL, id);
1827 if (err == 0) {
1828 FAIL("bt_mcc_set_current_track_obj_id did not fail with NULL conn");
1829 return;
1830 }
1831
1832 invalid_id = BT_OTS_OBJ_ID_MIN - 1;
1833 err = bt_mcc_set_current_track_obj_id(default_conn, invalid_id);
1834 if (err == 0) {
1835 FAIL("bt_mcc_set_current_track_obj_id did not fail with invalid ID 0x%016llx",
1836 invalid_id);
1837 return;
1838 }
1839
1840 invalid_id = BT_OTS_OBJ_ID_MAX + 1;
1841 err = bt_mcc_set_current_track_obj_id(default_conn, invalid_id);
1842 if (err == 0) {
1843 FAIL("bt_mcc_set_current_track_obj_id did not fail with invalid ID 0x%016llx",
1844 invalid_id);
1845 return;
1846 }
1847
1848 invalid_id = OTS_OBJ_ID_DIR_LIST;
1849 err = bt_mcc_set_current_track_obj_id(default_conn, invalid_id);
1850 if (err == 0) {
1851 FAIL("bt_mcc_set_current_track_obj_id did not fail with invalid ID 0x%016llx",
1852 invalid_id);
1853 return;
1854 }
1855
1856 /* Valid behavior */
1857 UNSET_FLAG(current_track_object_id_set);
1858
1859 err = bt_mcc_set_current_track_obj_id(default_conn, id);
1860 if (err != 0) {
1861 FAIL("Failed to set current track object ID: %d", err);
1862 return;
1863 }
1864
1865 WAIT_FOR_FLAG(current_track_object_id_set);
1866
1867 if (g_current_track_object_id != id) {
1868 FAIL("Current track object ID not the one that was set");
1869 return;
1870 }
1871
1872 printk("Current Track Object ID set succeeded\n");
1873 }
1874
test_read_current_track_obj_id(void)1875 static void test_read_current_track_obj_id(void)
1876 {
1877 int err;
1878
1879 /* Invalid behavior */
1880 err = bt_mcc_read_current_track_obj_id(NULL);
1881 if (err == 0) {
1882 FAIL("bt_mcc_read_current_track_obj_id did not fail with NULL conn");
1883 return;
1884 }
1885
1886 /* Valid behavior */
1887 UNSET_FLAG(current_track_object_id_read);
1888
1889 err = bt_mcc_read_current_track_obj_id(default_conn);
1890 if (err != 0) {
1891 FAIL("Failed to read current track object ID: %d", err);
1892 return;
1893 }
1894
1895 WAIT_FOR_FLAG(current_track_object_id_read);
1896
1897 printk("Current Track Object ID read succeeded\n");
1898 }
1899
test_read_current_track_obj_id_with_expect(uint64_t expected_id)1900 static void test_read_current_track_obj_id_with_expect(uint64_t expected_id)
1901 {
1902 test_read_current_track_obj_id();
1903
1904 if (g_current_track_object_id != expected_id) {
1905 FAIL("Current track object ID not the one that was set");
1906 return;
1907 }
1908
1909 printk("Current Track Object ID read succeeded\n");
1910 }
1911
test_read_current_track_object(void)1912 static void test_read_current_track_object(void)
1913 {
1914 int err;
1915
1916 /* Invalid behavior */
1917 err = bt_mcc_otc_read_current_track_object(NULL);
1918 if (err == 0) {
1919 FAIL("bt_mcc_otc_read_current_track_object did not fail with NULL conn");
1920 return;
1921 }
1922
1923 /* Valid behavior */
1924 UNSET_FLAG(object_read);
1925
1926 err = bt_mcc_otc_read_current_track_object(default_conn);
1927
1928 if (err != 0) {
1929 FAIL("Failed to current track object\n");
1930 return;
1931 }
1932
1933 WAIT_FOR_FLAG(object_read);
1934 printk("Current Track Object read succeeded\n");
1935 }
1936
test_set_next_track_obj_id(uint64_t id)1937 static void test_set_next_track_obj_id(uint64_t id)
1938 {
1939 uint64_t invalid_id;
1940 int err;
1941
1942 /* Invalid behavior */
1943 err = bt_mcc_set_next_track_obj_id(NULL, id);
1944 if (err == 0) {
1945 FAIL("bt_mcc_set_next_track_obj_id did not fail with NULL conn");
1946 return;
1947 }
1948
1949 invalid_id = BT_OTS_OBJ_ID_MIN - 1;
1950 err = bt_mcc_set_next_track_obj_id(default_conn, invalid_id);
1951 if (err == 0) {
1952 FAIL("bt_mcc_set_next_track_obj_id did not fail with invalid ID 0x%016llx",
1953 invalid_id);
1954 return;
1955 }
1956
1957 invalid_id = BT_OTS_OBJ_ID_MAX + 1;
1958 err = bt_mcc_set_next_track_obj_id(default_conn, invalid_id);
1959 if (err == 0) {
1960 FAIL("bt_mcc_set_next_track_obj_id did not fail with invalid ID 0x%016llx",
1961 invalid_id);
1962 return;
1963 }
1964
1965 invalid_id = OTS_OBJ_ID_DIR_LIST;
1966 err = bt_mcc_set_next_track_obj_id(default_conn, invalid_id);
1967 if (err == 0) {
1968 FAIL("bt_mcc_set_next_track_obj_id did not fail with invalid ID 0x%016llx",
1969 invalid_id);
1970 return;
1971 }
1972
1973 /* Valid behavior */
1974 UNSET_FLAG(next_track_object_id_set);
1975
1976 err = bt_mcc_set_next_track_obj_id(default_conn, id);
1977 if (err != 0) {
1978 FAIL("Failed to set next track object ID: %d", err);
1979 return;
1980 }
1981
1982 WAIT_FOR_FLAG(next_track_object_id_set);
1983 if (g_next_track_object_id != id) {
1984 FAIL("Next track object ID not the one that was set");
1985 return;
1986 }
1987
1988 printk("Next Track Object ID set succeeded\n");
1989 }
1990
test_read_next_track_obj_id(void)1991 static void test_read_next_track_obj_id(void)
1992 {
1993 int err;
1994
1995 /* Invalid behavior */
1996 err = bt_mcc_read_next_track_obj_id(NULL);
1997 if (err == 0) {
1998 FAIL("bt_mcc_read_next_track_obj_id did not fail with NULL conn");
1999 return;
2000 }
2001
2002 /* Valid behavior */
2003 UNSET_FLAG(next_track_object_id_read);
2004
2005 err = bt_mcc_read_next_track_obj_id(default_conn);
2006 if (err != 0) {
2007 FAIL("Failed to read next track object ID: %d", err);
2008 return;
2009 }
2010
2011 WAIT_FOR_FLAG(next_track_object_id_read);
2012
2013 printk("Next Track Object ID read succeeded\n");
2014 }
2015
test_read_next_track_obj_id_with_expect(uint64_t expected_id)2016 static void test_read_next_track_obj_id_with_expect(uint64_t expected_id)
2017 {
2018 test_read_next_track_obj_id();
2019
2020 if (g_next_track_object_id != expected_id) {
2021 FAIL("Next track object ID not the one that was set");
2022 return;
2023 }
2024
2025 printk("Next Track Object ID read succeeded\n");
2026 }
2027
test_read_next_track_object(void)2028 static void test_read_next_track_object(void)
2029 {
2030 int err;
2031
2032 /* Invalid behavior */
2033 err = bt_mcc_otc_read_next_track_object(NULL);
2034 if (err == 0) {
2035 FAIL("bt_mcc_otc_read_next_track_object did not fail with NULL conn");
2036 return;
2037 }
2038
2039 /* Valid behavior */
2040 UNSET_FLAG(object_read);
2041
2042 err = bt_mcc_otc_read_next_track_object(default_conn);
2043 if (err != 0) {
2044 FAIL("Failed to read next track object\n");
2045 return;
2046 }
2047
2048 WAIT_FOR_FLAG(object_read);
2049 printk("Next Track Object read succeeded\n");
2050 }
2051
test_read_parent_group_obj_id(void)2052 static void test_read_parent_group_obj_id(void)
2053 {
2054 int err;
2055
2056 /* Invalid behavior */
2057 err = bt_mcc_read_parent_group_obj_id(NULL);
2058 if (err == 0) {
2059 FAIL("bt_mcc_read_parent_group_obj_id did not fail with NULL conn");
2060 return;
2061 }
2062
2063 /* Valid behavior */
2064 UNSET_FLAG(parent_group_object_id_read);
2065
2066 err = bt_mcc_read_parent_group_obj_id(default_conn);
2067 if (err != 0) {
2068 FAIL("Failed to read parent group object ID: %d", err);
2069 return;
2070 }
2071
2072 WAIT_FOR_FLAG(parent_group_object_id_read);
2073 printk("Parent Group Object ID read succeeded\n");
2074 }
2075
test_read_parent_group_object(void)2076 static void test_read_parent_group_object(void)
2077 {
2078 int err;
2079
2080 /* Invalid behavior */
2081 err = bt_mcc_otc_read_parent_group_object(NULL);
2082 if (err == 0) {
2083 FAIL("bt_mcc_otc_read_parent_group_object did not fail with NULL conn");
2084 return;
2085 }
2086
2087 /* Valid behavior */
2088 UNSET_FLAG(object_read);
2089
2090 err = bt_mcc_otc_read_parent_group_object(default_conn);
2091 if (err != 0) {
2092 FAIL("Failed to read parent group object\n");
2093 return;
2094 }
2095
2096 WAIT_FOR_FLAG(object_read);
2097 printk("Parent Group Object read succeeded\n");
2098 }
2099
test_set_current_group_obj_id(uint64_t id)2100 static void test_set_current_group_obj_id(uint64_t id)
2101 {
2102 uint64_t invalid_id;
2103 int err;
2104
2105 /* Invalid behavior */
2106 err = bt_mcc_set_current_group_obj_id(NULL, id);
2107 if (err == 0) {
2108 FAIL("bt_mcc_set_current_group_obj_id did not fail with NULL conn");
2109 return;
2110 }
2111
2112 invalid_id = BT_OTS_OBJ_ID_MIN - 1;
2113 err = bt_mcc_set_current_group_obj_id(default_conn, invalid_id);
2114 if (err == 0) {
2115 FAIL("bt_mcc_set_current_group_obj_id did not fail with invalid ID 0x%016llx",
2116 invalid_id);
2117 return;
2118 }
2119
2120 invalid_id = BT_OTS_OBJ_ID_MAX + 1;
2121 err = bt_mcc_set_current_group_obj_id(default_conn, invalid_id);
2122 if (err == 0) {
2123 FAIL("bt_mcc_set_current_group_obj_id did not fail with invalid ID 0x%016llx",
2124 invalid_id);
2125 return;
2126 }
2127
2128 invalid_id = OTS_OBJ_ID_DIR_LIST;
2129 err = bt_mcc_set_current_group_obj_id(default_conn, invalid_id);
2130 if (err == 0) {
2131 FAIL("bt_mcc_set_current_group_obj_id did not fail with invalid ID 0x%016llx",
2132 invalid_id);
2133 return;
2134 }
2135
2136 /* Valid behavior */
2137 UNSET_FLAG(current_group_object_id_set);
2138 err = bt_mcc_set_current_group_obj_id(default_conn, id);
2139 if (err != 0) {
2140 FAIL("Failed to set current group object ID: %d", err);
2141 return;
2142 }
2143
2144 WAIT_FOR_FLAG(current_group_object_id_set);
2145 if (g_current_group_object_id != id) {
2146 FAIL("Current group object ID not the one that was set");
2147 return;
2148 }
2149
2150 printk("Current Group Object ID set succeeded\n");
2151 }
2152
test_read_current_group_obj_id(void)2153 static void test_read_current_group_obj_id(void)
2154 {
2155 int err;
2156
2157 /* Invalid behavior */
2158 err = bt_mcc_read_current_group_obj_id(NULL);
2159 if (err == 0) {
2160 FAIL("bt_mcc_read_current_group_obj_id did not fail with NULL conn");
2161 return;
2162 }
2163
2164 /* Valid behavior */
2165 UNSET_FLAG(current_group_object_id_read);
2166
2167 err = bt_mcc_read_current_group_obj_id(default_conn);
2168 if (err != 0) {
2169 FAIL("Failed to read current group object ID: %d", err);
2170 return;
2171 }
2172
2173 WAIT_FOR_FLAG(current_group_object_id_read);
2174
2175 printk("Current Group Object ID read succeeded\n");
2176 }
2177
test_read_current_group_obj_id_with_expect(uint64_t expected_id)2178 static void test_read_current_group_obj_id_with_expect(uint64_t expected_id)
2179 {
2180 test_read_current_group_obj_id();
2181
2182 if (g_current_group_object_id != expected_id) {
2183 FAIL("Current group object ID not the one that was set");
2184 return;
2185 }
2186
2187 printk("Current Group Object ID read succeeded\n");
2188 }
2189
test_read_current_group_object(void)2190 static void test_read_current_group_object(void)
2191 {
2192 int err;
2193
2194 /* Invalid behavior */
2195 err = bt_mcc_otc_read_current_group_object(NULL);
2196 if (err == 0) {
2197 FAIL("bt_mcc_otc_read_current_group_object did not fail with NULL conn");
2198 return;
2199 }
2200
2201 /* Valid behavior */
2202 UNSET_FLAG(object_read);
2203
2204 err = bt_mcc_otc_read_current_group_object(default_conn);
2205 if (err != 0) {
2206 FAIL("Failed to read current group object\n");
2207 return;
2208 }
2209
2210 WAIT_FOR_FLAG(object_read);
2211 printk("Current Group Object read succeeded\n");
2212 }
2213
test_read_playing_order(void)2214 static void test_read_playing_order(void)
2215 {
2216 int err;
2217
2218 /* Invalid behavior */
2219 err = bt_mcc_read_playing_order(NULL);
2220 if (err == 0) {
2221 FAIL("bt_mcc_read_playing_order did not fail with NULL conn");
2222 return;
2223 }
2224
2225 /* Valid behavior */
2226 UNSET_FLAG(playing_order_read);
2227
2228 err = bt_mcc_read_playing_order(default_conn);
2229 if (err != 0) {
2230 FAIL("Failed to read playing order: %d", err);
2231 return;
2232 }
2233
2234 WAIT_FOR_FLAG(playing_order_read);
2235 printk("Playing order read succeeded\n");
2236 }
2237
test_set_playing_order(void)2238 static void test_set_playing_order(void)
2239 {
2240 uint8_t new_playing_order;
2241 int err;
2242
2243 /* Invalid behavior */
2244 err = bt_mcc_set_playing_order(NULL, BT_MCS_PLAYING_ORDER_SINGLE_ONCE);
2245 if (err == 0) {
2246 FAIL("bt_mcc_read_playing_order did not fail with NULL conn");
2247 return;
2248 }
2249
2250 new_playing_order = 0x00;
2251
2252 err = bt_mcc_set_playing_order(default_conn, new_playing_order);
2253 if (err == 0) {
2254 FAIL("bt_mcc_set_playing_order did not fail with invalid playing order: 0x%02X",
2255 new_playing_order);
2256 return;
2257 }
2258
2259 new_playing_order = 0x0b;
2260
2261 err = bt_mcc_set_playing_order(default_conn, new_playing_order);
2262 if (err == 0) {
2263 FAIL("bt_mcc_set_playing_order did not fail with invalid playing order: 0x%02X",
2264 new_playing_order);
2265 return;
2266 }
2267
2268 /* Valid behavior */
2269 if (g_playing_order == BT_MCS_PLAYING_ORDER_SHUFFLE_ONCE) {
2270 new_playing_order = BT_MCS_PLAYING_ORDER_SINGLE_ONCE;
2271 } else {
2272 new_playing_order = BT_MCS_PLAYING_ORDER_SHUFFLE_ONCE;
2273 }
2274
2275 UNSET_FLAG(playing_order_set);
2276
2277 err = bt_mcc_set_playing_order(default_conn, new_playing_order);
2278 if (err != 0) {
2279 FAIL("Failed to set playing_order: %d", err);
2280 return;
2281 }
2282
2283 WAIT_FOR_FLAG(playing_order_set);
2284 if (g_playing_order != new_playing_order) {
2285 FAIL("Playing order set failed: Incorrect playing_order\n");
2286 }
2287 printk("Playing order set succeeded\n");
2288 }
2289
test_read_playing_orders_supported(void)2290 static void test_read_playing_orders_supported(void)
2291 {
2292 int err;
2293
2294 /* Invalid behavior */
2295 err = bt_mcc_read_playing_orders_supported(NULL);
2296 if (err == 0) {
2297 FAIL("bt_mcc_read_playing_orders_supported did not fail with NULL conn");
2298 return;
2299 }
2300
2301 /* Valid behavior */
2302 UNSET_FLAG(playing_orders_supported_read);
2303
2304 err = bt_mcc_read_playing_orders_supported(default_conn);
2305 if (err != 0) {
2306 FAIL("Failed to read playing orders supported: %d", err);
2307 return;
2308 }
2309
2310 WAIT_FOR_FLAG(playing_orders_supported_read);
2311 printk("Playing orders supported read succeeded\n");
2312 }
2313
test_read_media_state(void)2314 static void test_read_media_state(void)
2315 {
2316 int err;
2317
2318 /* Invalid behavior */
2319 err = bt_mcc_read_media_state(NULL);
2320 if (err == 0) {
2321 FAIL("bt_mcc_read_media_state did not fail with NULL conn");
2322 return;
2323 }
2324
2325 /* Valid behavior */
2326 UNSET_FLAG(media_state_read);
2327
2328 err = bt_mcc_read_media_state(default_conn);
2329 if (err != 0) {
2330 FAIL("Failed to read media state: %d", err);
2331 return;
2332 }
2333
2334 WAIT_FOR_FLAG(media_state_read);
2335 printk("Media state read succeeded\n");
2336 }
2337
test_read_content_control_id(void)2338 static void test_read_content_control_id(void)
2339 {
2340 int err;
2341
2342 /* Invalid behavior */
2343 err = bt_mcc_read_content_control_id(NULL);
2344 if (err == 0) {
2345 FAIL("bt_mcc_read_content_control_id did not fail with NULL conn");
2346 return;
2347 }
2348
2349 /* Valid behavior */
2350 UNSET_FLAG(ccid_read);
2351
2352 err = bt_mcc_read_content_control_id(default_conn);
2353 if (err != 0) {
2354 FAIL("Failed to read content control ID: %d", err);
2355 return;
2356 }
2357
2358 WAIT_FOR_FLAG(ccid_read);
2359 printk("Content control ID read succeeded\n");
2360 }
2361
reset_test_iteration(unsigned int i)2362 static void reset_test_iteration(unsigned int i)
2363 {
2364 struct mpl_cmd cmd;
2365
2366 printk("Resetting test iteration\n");
2367
2368 g_icon_object_id = 0U;
2369 g_track_segments_object_id = 0U;
2370 g_current_track_object_id = 0U;
2371 g_next_track_object_id = 0U;
2372 g_parent_group_object_id = 0U;
2373 g_current_group_object_id = 0U;
2374 g_search_results_object_id = 0U;
2375
2376 g_pos = 0;
2377 g_pb_speed = 0;
2378 g_playing_order = 0U;
2379 g_state = 0U;
2380 g_command_result = 0U;
2381 g_search_result = 0U;
2382 g_supported_opcodes = 0U;
2383
2384 test_cp_pause();
2385
2386 cmd.opcode = BT_MCS_OPC_FIRST_GROUP;
2387 cmd.use_param = false;
2388 test_send_cmd_wait_flags(&cmd);
2389 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
2390 FAIL("First group command failed\n");
2391 return;
2392 }
2393
2394 cmd.opcode = BT_MCS_OPC_FIRST_TRACK;
2395 cmd.use_param = false;
2396 test_send_cmd_wait_flags(&cmd);
2397 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
2398 FAIL("First track command failed\n");
2399 return;
2400 }
2401
2402 cmd.opcode = BT_MCS_OPC_FIRST_SEGMENT;
2403 cmd.use_param = false;
2404 test_send_cmd_wait_flags(&cmd);
2405 if (g_command_result != BT_MCS_OPC_NTF_SUCCESS) {
2406 FAIL("First segment command failed\n");
2407 return;
2408 }
2409
2410 printk("Test iteration reset\n");
2411 }
2412
2413 /* This function tests all commands in the API in sequence
2414 * The order of the sequence follows the order of the characterstics in the
2415 * Media Control Service specification
2416 */
test_main(void)2417 void test_main(void)
2418 {
2419 const unsigned int iterations = 3;
2420 int err;
2421
2422 printk("Media Control Client test application. Board: %s\n", CONFIG_BOARD);
2423
2424 err = bt_enable(NULL);
2425 if (err != 0) {
2426 FAIL("Bluetooth init failed (err %d)\n", err);
2427 return;
2428 }
2429
2430 printk("Bluetooth initialized\n");
2431
2432 bt_le_scan_cb_register(&common_scan_cb);
2433
2434 /* Initialize MCC ********************************************/
2435 err = do_mcc_init();
2436 if (err != 0) {
2437 FAIL("Could not initialize MCC (err %d\n)", err);
2438 } else {
2439 printk("MCC init succeeded\n");
2440 }
2441
2442 /* Connect ******************************************/
2443 for (unsigned int i = 0U; i < iterations; i++) {
2444 const uint64_t new_current_group_object_id_1 = 0x10e;
2445 const uint64_t new_current_group_object_id_2 = 0x106; /* ID of first group */
2446 const uint64_t new_current_track_object_id = 0x103;
2447 const uint64_t new_next_track_object = 0x102;
2448
2449 printk("\n########### Running iteration #%u\n\n", i);
2450
2451 UNSET_FLAG(flag_connected);
2452 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
2453 if (err != 0) {
2454 FAIL("Failed to start scanning (err %d\n)", err);
2455 } else {
2456 printk("Scanning started successfully\n");
2457 }
2458
2459 WAIT_FOR_FLAG(flag_connected);
2460
2461 char addr[BT_ADDR_LE_STR_LEN];
2462
2463 bt_addr_le_to_str(bt_conn_get_dst(default_conn), addr, sizeof(addr));
2464 printk("Connected: %s\n", addr);
2465
2466 bt_conn_le_param_update(default_conn,
2467 BT_LE_CONN_PARAM(BT_GAP_US_TO_CONN_INTERVAL(7500),
2468 BT_GAP_US_TO_CONN_INTERVAL(20000), 0U,
2469 BT_GAP_MS_TO_CONN_TIMEOUT(4000U)));
2470 WAIT_FOR_FLAG(flag_conn_updated);
2471
2472 test_discover();
2473 test_discover(); /* test that we can discover twice */
2474
2475 reset_test_iteration(i);
2476
2477 test_read_media_state();
2478 test_read_content_control_id();
2479 test_read_player_name();
2480 test_read_seeking_speed();
2481 test_read_playing_orders_supported();
2482 test_read_supported_opcodes();
2483 test_read_playing_order();
2484 test_set_playing_order();
2485 test_invalid_send_cmd();
2486
2487 test_read_icon_obj_id();
2488 test_select_obj_id(g_icon_object_id);
2489 test_read_object_meta();
2490 test_read_icon_obj();
2491 test_read_icon_url();
2492
2493 /* Track changed ************************************************
2494 *
2495 * The track changed characteristic is tested as part of the control
2496 * point next track test
2497 */
2498
2499 test_read_track_title();
2500 test_read_track_duration();
2501 test_read_track_position();
2502
2503 int32_t pos = g_pos + 1200; /*12 seconds further into the track */
2504
2505 test_write_track_position(pos);
2506
2507 test_read_playback_speed();
2508
2509 int8_t pb_speed = g_pb_speed + 8; /* 2^(8/64) faster than current speed */
2510
2511 test_set_playback_speed(pb_speed);
2512
2513 /* Track segments */
2514 test_read_track_segments_obj_id();
2515 test_select_obj_id(g_track_segments_object_id);
2516 test_read_object_meta();
2517 test_read_track_segments_object();
2518
2519 /* Current track */
2520 test_set_current_track_obj_id(new_current_track_object_id);
2521 test_read_current_track_obj_id_with_expect(new_current_track_object_id);
2522 test_select_obj_id(g_current_track_object_id);
2523 test_read_object_meta();
2524 test_read_current_track_object();
2525
2526 /* Next track */
2527 test_set_next_track_obj_id(new_next_track_object);
2528 test_read_next_track_obj_id_with_expect(new_next_track_object);
2529 test_select_obj_id(g_next_track_object_id);
2530 test_read_object_meta();
2531 test_read_next_track_object();
2532
2533 /* Parent group */
2534 test_read_parent_group_obj_id();
2535 test_select_obj_id(g_parent_group_object_id);
2536 test_read_object_meta();
2537 test_read_parent_group_object();
2538
2539 /* Current group object ******************************************/
2540 test_set_current_group_obj_id(new_current_group_object_id_1);
2541 test_read_current_group_obj_id_with_expect(new_current_group_object_id_1);
2542 test_select_obj_id(g_current_group_object_id);
2543 test_read_object_meta();
2544 test_read_current_group_object();
2545
2546 /* Set current group back to first group, so that later tests (segments) will work.
2547 * (Only the tracks of the first group has segments in the MPL.)
2548 */
2549 test_set_current_group_obj_id(new_current_group_object_id_2);
2550
2551 /* This part of the test not only checks that the opcodes are accepted
2552 * by the server, but also that they actually do lead to the expected
2553 * state changes. This may lean too much upon knowledge or assumptions,
2554 * and therefore be too fragile.
2555 * It may be more robust to just give commands and check for the success
2556 * code in the control point notifications
2557 */
2558
2559 /* It is assumed that the server starts the test in the paused state */
2560 test_verify_media_state_wait_flags(BT_MCS_MEDIA_STATE_PAUSED);
2561
2562 /* The tests are ordered to ensure that each command changes state */
2563 test_cp_play();
2564 test_cp_fast_forward();
2565 test_cp_pause();
2566 test_cp_fast_rewind();
2567 test_cp_stop();
2568
2569 /* Control point - move relative opcode */
2570 test_cp_move_relative();
2571
2572 /* Control point - segment change opcodes */
2573 test_cp_prev_segment();
2574 test_cp_next_segment();
2575 test_cp_first_segment();
2576 test_cp_last_segment();
2577 test_cp_goto_segment();
2578
2579 /* Control point - track change opcodes */
2580 /* The tests are ordered to ensure that each command changes track */
2581 /* Assumes we are not starting on the last track */
2582 test_cp_next_track_and_track_changed();
2583 test_cp_prev_track();
2584 test_cp_last_track();
2585 test_cp_first_track();
2586 test_cp_goto_track();
2587
2588 /* Control point - group change opcodes *******************************/
2589 /* The tests are ordered to ensure that each command changes group */
2590 /* Assumes we are not starting on the last group */
2591 test_cp_next_group();
2592 test_cp_prev_group();
2593 test_cp_last_group();
2594 test_cp_first_group();
2595 test_cp_goto_group();
2596
2597 /* Search control point */
2598 test_search();
2599
2600 printk("Disconnecting\n");
2601 err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
2602 if (err != 0) {
2603 FAIL("Failed to disconnect: %d", err);
2604 return;
2605 }
2606 WAIT_FOR_COND(default_conn == NULL);
2607 k_sleep(K_SECONDS(1));
2608 printk("Disconnected\n");
2609 }
2610
2611 /* TEST IS COMPLETE */
2612 PASS("MCC passed\n");
2613 }
2614
2615 static const struct bst_test_instance test_mcs[] = {
2616 {
2617 .test_id = "mcc",
2618 .test_pre_init_f = test_init,
2619 .test_tick_f = test_tick,
2620 .test_main_f = test_main
2621 },
2622 BSTEST_END_MARKER
2623 };
2624
test_mcc_install(struct bst_test_list * tests)2625 struct bst_test_list *test_mcc_install(struct bst_test_list *tests)
2626 {
2627 return bst_add_tests(tests, test_mcs);
2628 }
2629
2630 #else
2631
test_mcc_install(struct bst_test_list * tests)2632 struct bst_test_list *test_mcc_install(struct bst_test_list *tests)
2633 {
2634 return tests;
2635 }
2636
2637 #endif /* CONFIG_BT_MCC */
2638