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