Skip to content

Commit 4b68043

Browse files
Thalleycarlescufi
authored andcommitted
Bluetooth: MPL: Replace busy bool with atomic
Replace the busy boolean flag with an atomic value. This prevents any race conditions with the MPL implementation. Modifies where the new atomic value is set and cleared so that initialization gets to finish before allowing any reads. Due to how the MPL is structured, and how a select cannot be rejected from OTS, this does not give a perfect solution. Ideally we need a separate object per OTS object, rather than a shared one, and/or the OTS implemenation would allow us to reject a select if the object is not currently available or ready. This commit does not fix the above issues, as that is a larger undertaking. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 0aec059 commit 4b68043

File tree

1 file changed

+45
-57
lines changed
  • subsys/bluetooth/audio

1 file changed

+45
-57
lines changed

subsys/bluetooth/audio/mpl.c

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <zephyr/logging/log.h>
2525
#include <zephyr/net_buf.h>
2626
#include <zephyr/sys/__assert.h>
27+
#include <zephyr/sys/atomic.h>
2728
#include <zephyr/sys/util.h>
2829
#include <zephyr/sys/time_units.h>
2930
#include <zephyr/sys/util_macro.h>
@@ -279,6 +280,12 @@ enum mpl_objects {
279280
MPL_OBJ_SEARCH_RESULTS,
280281
};
281282

283+
enum mpl_obj_flag {
284+
MPL_OBJ_FLAG_BUSY,
285+
286+
MPL_OBJ_FLAG_NUM_FLAGS, /* keep as last */
287+
};
288+
282289
/* The active object */
283290
/* Only a single object is selected or being added (active) at a time. */
284291
/* And, except for the icon object, all objects can be created dynamically. */
@@ -287,8 +294,6 @@ struct obj_t {
287294
/* ID of the currently selected object*/
288295
uint64_t selected_id;
289296

290-
bool busy;
291-
292297
/* Type of object being added, e.g. MPL_OBJ_ICON */
293298
uint8_t add_type;
294299

@@ -302,15 +307,16 @@ struct obj_t {
302307
struct mpl_group *add_group;
303308
};
304309
struct net_buf_simple *content;
310+
311+
ATOMIC_DEFINE(flags, MPL_OBJ_FLAG_NUM_FLAGS);
305312
};
306313

307314
static struct obj_t obj = {
308315
.selected_id = 0,
309316
.add_type = MPL_OBJ_NONE,
310-
.busy = false,
311317
.add_track = NULL,
312318
.add_group = NULL,
313-
.content = NET_BUF_SIMPLE(CONFIG_BT_MPL_MAX_OBJ_SIZE)
319+
.content = NET_BUF_SIMPLE(CONFIG_BT_MPL_MAX_OBJ_SIZE),
314320
};
315321

316322
/* Set up content buffer for the icon object */
@@ -475,13 +481,6 @@ static int add_icon_object(struct mpl_mediaplayer *pl)
475481
const struct bt_uuid *icon_type = BT_UUID_OTS_TYPE_MPL_ICON;
476482
static char *icon_name = "Icon";
477483

478-
if (obj.busy) {
479-
/* TODO: Can there be a collision between select and internal */
480-
/* activities, like adding new objects? */
481-
LOG_ERR("Object busy");
482-
return 0;
483-
}
484-
obj.busy = true;
485484
obj.add_type = MPL_OBJ_ICON;
486485
obj.desc = &created_desc;
487486

@@ -496,7 +495,6 @@ static int add_icon_object(struct mpl_mediaplayer *pl)
496495
ret = bt_ots_obj_add(bt_mcs_get_ots(), &add_param);
497496
if (ret < 0) {
498497
LOG_WRN("Unable to add icon object, error %d", ret);
499-
obj.busy = false;
500498

501499
return ret;
502500
}
@@ -512,11 +510,6 @@ static int add_current_track_segments_object(struct mpl_mediaplayer *pl)
512510
struct bt_ots_obj_created_desc created_desc = {};
513511
const struct bt_uuid *segs_type = BT_UUID_OTS_TYPE_TRACK_SEGMENT;
514512

515-
if (obj.busy) {
516-
LOG_ERR("Object busy");
517-
return 0;
518-
}
519-
obj.busy = true;
520513
obj.add_type = MPL_OBJ_TRACK_SEGMENTS;
521514
obj.desc = &created_desc;
522515

@@ -531,7 +524,6 @@ static int add_current_track_segments_object(struct mpl_mediaplayer *pl)
531524
ret = bt_ots_obj_add(bt_mcs_get_ots(), &add_param);
532525
if (ret < 0) {
533526
LOG_WRN("Unable to add track segments object: %d", ret);
534-
obj.busy = false;
535527

536528
return ret;
537529
}
@@ -547,17 +539,11 @@ static int add_track_object(struct mpl_track *track)
547539
const struct bt_uuid *track_type = BT_UUID_OTS_TYPE_TRACK;
548540
int ret;
549541

550-
if (obj.busy) {
551-
LOG_ERR("Object busy");
552-
return 0;
553-
}
554542
if (!track) {
555543
LOG_ERR("No track");
556544
return -EINVAL;
557545
}
558546

559-
obj.busy = true;
560-
561547
obj.add_type = MPL_OBJ_TRACK;
562548
obj.add_track = track;
563549
obj.desc = &created_desc;
@@ -573,7 +559,6 @@ static int add_track_object(struct mpl_track *track)
573559
ret = bt_ots_obj_add(bt_mcs_get_ots(), &add_param);
574560
if (ret < 0) {
575561
LOG_WRN("Unable to add track object: %d", ret);
576-
obj.busy = false;
577562

578563
return ret;
579564
}
@@ -589,11 +574,6 @@ static int add_parent_group_object(struct mpl_mediaplayer *pl)
589574
struct bt_ots_obj_created_desc created_desc = {};
590575
const struct bt_uuid *group_type = BT_UUID_OTS_TYPE_GROUP;
591576

592-
if (obj.busy) {
593-
LOG_ERR("Object busy");
594-
return 0;
595-
}
596-
obj.busy = true;
597577
obj.add_type = MPL_OBJ_PARENT_GROUP;
598578
obj.desc = &created_desc;
599579

@@ -608,7 +588,6 @@ static int add_parent_group_object(struct mpl_mediaplayer *pl)
608588
ret = bt_ots_obj_add(bt_mcs_get_ots(), &add_param);
609589
if (ret < 0) {
610590
LOG_WRN("Unable to add parent group object");
611-
obj.busy = false;
612591

613592
return ret;
614593
}
@@ -624,18 +603,11 @@ static int add_group_object(struct mpl_group *group)
624603
const struct bt_uuid *group_type = BT_UUID_OTS_TYPE_GROUP;
625604
int ret;
626605

627-
if (obj.busy) {
628-
LOG_ERR("Object busy");
629-
return 0;
630-
}
631-
632606
if (!group) {
633607
LOG_ERR("No group");
634608
return -EINVAL;
635609
}
636610

637-
obj.busy = true;
638-
639611
obj.add_type = MPL_OBJ_GROUP;
640612
obj.add_group = group;
641613
obj.desc = &created_desc;
@@ -651,7 +623,6 @@ static int add_group_object(struct mpl_group *group)
651623
ret = bt_ots_obj_add(bt_mcs_get_ots(), &add_param);
652624
if (ret < 0) {
653625
LOG_WRN("Unable to add group object: %d", ret);
654-
obj.busy = false;
655626

656627
return ret;
657628
}
@@ -729,13 +700,12 @@ static int on_obj_deleted(struct bt_ots *ots, struct bt_conn *conn,
729700
static void on_obj_selected(struct bt_ots *ots, struct bt_conn *conn,
730701
uint64_t id)
731702
{
732-
if (obj.busy) {
703+
if (atomic_test_and_set_bit(obj.flags, MPL_OBJ_FLAG_BUSY)) {
733704
/* TODO: Can there be a collision between select and internal */
734705
/* activities, like adding new objects? */
735706
LOG_ERR("Object busy - select not performed");
736707
return;
737708
}
738-
obj.busy = true;
739709

740710
LOG_DBG_OBJ_ID("Object Id selected: ", id);
741711

@@ -764,18 +734,20 @@ static void on_obj_selected(struct bt_ots *ots, struct bt_conn *conn,
764734
(void)setup_group_object(media_player.group);
765735
} else {
766736
LOG_ERR("Unknown Object ID");
767-
obj.busy = false;
737+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
768738
return;
769739
}
770740

771741
obj.selected_id = id;
772-
obj.busy = false;
742+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
773743
}
774744

775745
static int on_obj_created(struct bt_ots *ots, struct bt_conn *conn, uint64_t id,
776746
const struct bt_ots_obj_add_param *add_param,
777747
struct bt_ots_obj_created_desc *created_desc)
778748
{
749+
/* Objects are always created locally so we do not need to check for MPL_OBJ_FLAG_BUSY */
750+
779751
LOG_DBG_OBJ_ID("Object Id created: ", id);
780752

781753
*created_desc = *obj.desc;
@@ -830,24 +802,19 @@ static int on_obj_created(struct bt_ots *ots, struct bt_conn *conn, uint64_t id,
830802
LOG_DBG("Unknown Object ID");
831803
}
832804

833-
if (obj.add_type == MPL_OBJ_NONE) {
834-
obj.busy = false;
835-
}
836805
return 0;
837806
}
838807

839-
840808
static ssize_t on_object_send(struct bt_ots *ots, struct bt_conn *conn,
841809
uint64_t id, void **data, size_t len,
842810
off_t offset)
843811
{
844-
if (obj.busy) {
812+
if (atomic_test_and_set_bit(obj.flags, MPL_OBJ_FLAG_BUSY)) {
845813
/* TODO: Can there be a collision between select and internal */
846814
/* activities, like adding new objects? */
847815
LOG_ERR("Object busy");
848-
return 0;
816+
return -EBUSY;
849817
}
850-
obj.busy = true;
851818

852819
if (IS_ENABLED(CONFIG_BT_MPL_LOG_LEVEL_DBG)) {
853820
char t[BT_OTS_OBJ_ID_STR_LEN];
@@ -857,20 +824,20 @@ static ssize_t on_object_send(struct bt_ots *ots, struct bt_conn *conn,
857824

858825
if (id != obj.selected_id) {
859826
LOG_ERR("Read from unselected object");
860-
obj.busy = false;
861-
return 0;
827+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
828+
return -EINVAL;
862829
}
863830

864831
if (!data) {
865832
LOG_DBG("Read complete");
866-
obj.busy = false;
833+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
867834
return 0;
868835
}
869836

870837
if (offset >= obj.content->len) {
871838
LOG_DBG("Offset too large");
872-
obj.busy = false;
873-
return 0;
839+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
840+
return -EINVAL;
874841
}
875842

876843
if (IS_ENABLED(CONFIG_BT_MPL_LOG_LEVEL_DBG)) {
@@ -880,7 +847,8 @@ static ssize_t on_object_send(struct bt_ots *ots, struct bt_conn *conn,
880847
}
881848

882849
*data = &obj.content->data[offset];
883-
obj.busy = false;
850+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
851+
884852
return MIN(len, obj.content->len - offset);
885853
}
886854

@@ -2357,14 +2325,29 @@ int media_proxy_pl_init(void)
23572325
*/
23582326
#ifdef CONFIG_BT_MCS
23592327
#ifdef CONFIG_BT_MPL_OBJECTS
2328+
/* The test here is arguably needed as the objects cannot be accessed before bt_mcs_init is
2329+
* called, but the set is to avoid the objects being accessed before properly initialized
2330+
*/
2331+
if (atomic_test_and_set_bit(obj.flags, MPL_OBJ_FLAG_BUSY)) {
2332+
LOG_ERR("Object busy");
2333+
return -EBUSY;
2334+
}
2335+
23602336
ret = bt_mcs_init(&ots_cbs);
2337+
if (ret < 0) {
2338+
LOG_ERR("Could not init MCS: %d", ret);
2339+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
2340+
2341+
return ret;
2342+
}
23612343
#else
23622344
ret = bt_mcs_init(NULL);
2363-
#endif /* CONFIG_BT_MPL_OBJECTS */
23642345
if (ret < 0) {
23652346
LOG_ERR("Could not init MCS: %d", ret);
23662347
return ret;
23672348
}
2349+
#endif /* CONFIG_BT_MPL_OBJECTS */
2350+
/* TODO: If anything below fails we should unregister MCS */
23682351
#else
23692352
LOG_WRN("MCS not configured");
23702353
#endif /* CONFIG_BT_MCS */
@@ -2380,13 +2363,15 @@ int media_proxy_pl_init(void)
23802363
ret = add_icon_object(&media_player);
23812364
if (ret < 0) {
23822365
LOG_ERR("Unable to add icon object, error %d", ret);
2366+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
23832367
return ret;
23842368
}
23852369

23862370
/* Add all tracks and groups to OTS */
23872371
ret = add_group_and_track_objects(&media_player);
23882372
if (ret < 0) {
23892373
LOG_ERR("Error adding tracks and groups to OTS, error %d", ret);
2374+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
23902375
return ret;
23912376
}
23922377

@@ -2396,8 +2381,11 @@ int media_proxy_pl_init(void)
23962381
ret = add_current_track_segments_object(&media_player);
23972382
if (ret < 0) {
23982383
LOG_ERR("Error adding Track Segments Object to OTS, error %d", ret);
2384+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
23992385
return ret;
24002386
}
2387+
2388+
atomic_clear_bit(obj.flags, MPL_OBJ_FLAG_BUSY);
24012389
#endif /* CONFIG_BT_MPL_OBJECTS */
24022390

24032391
/* Set up the calls structure */

0 commit comments

Comments
 (0)