Skip to content

Commit 49bd808

Browse files
Thalleymmahadevan108
authored andcommitted
Bluetooth: VOCS: Replace bools with atomic
Replace the booleans used by the VOCS client to use an atomic value instead. The flags are modified to be used in a way that prevents race conditions. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
1 parent aa3dd67 commit 49bd808

File tree

2 files changed

+65
-50
lines changed

2 files changed

+65
-50
lines changed

subsys/bluetooth/audio/vocs_client.c

+53-45
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ static struct bt_vocs_client *lookup_vocs_by_handle(struct bt_conn *conn, uint16
4444

4545
for (int i = 0; i < ARRAY_SIZE(insts); i++) {
4646
if (insts[i].conn == conn &&
47-
insts[i].active &&
48-
insts[i].start_handle <= handle &&
49-
insts[i].end_handle >= handle) {
47+
atomic_test_bit(insts[i].flags, BT_VOCS_CLIENT_FLAG_ACTIVE) &&
48+
insts[i].start_handle <= handle && insts[i].end_handle >= handle) {
5049
return &insts[i];
5150
}
5251
}
@@ -134,7 +133,7 @@ static uint8_t vocs_client_read_offset_state_cb(struct bt_conn *conn, uint8_t er
134133
}
135134

136135
LOG_DBG("Inst %p: err: 0x%02X", inst, err);
137-
inst->busy = false;
136+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
138137

139138
if (cb_err) {
140139
LOG_DBG("Offset state read failed: %d", err);
@@ -175,7 +174,7 @@ static uint8_t vocs_client_read_location_cb(struct bt_conn *conn, uint8_t err,
175174
}
176175

177176
LOG_DBG("Inst %p: err: 0x%02X", inst, err);
178-
inst->busy = false;
177+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
179178

180179
if (cb_err) {
181180
LOG_DBG("Offset state read failed: %d", err);
@@ -226,7 +225,7 @@ static uint8_t internal_read_volume_offset_state_cb(struct bt_conn *conn, uint8_
226225
inst->state.change_counter);
227226

228227
/* clear busy flag to reuse function */
229-
inst->busy = false;
228+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
230229
write_err = bt_vocs_client_state_set(inst, inst->cp.offset);
231230
if (write_err) {
232231
cb_err = BT_ATT_ERR_UNLIKELY;
@@ -242,7 +241,7 @@ static uint8_t internal_read_volume_offset_state_cb(struct bt_conn *conn, uint8_
242241
}
243242

244243
if (cb_err) {
245-
inst->busy = false;
244+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
246245

247246
if (inst->cb && inst->cb->set_offset) {
248247
inst->cb->set_offset(&inst->vocs, err);
@@ -272,7 +271,8 @@ static void vocs_client_write_vocs_cp_cb(struct bt_conn *conn, uint8_t err,
272271
* change counter has been read, we restart the applications write request. If it fails
273272
* the second time, we return an error to the application.
274273
*/
275-
if (cb_err == BT_VOCS_ERR_INVALID_COUNTER && inst->cp_retried) {
274+
if (cb_err == BT_VOCS_ERR_INVALID_COUNTER &&
275+
atomic_test_bit(inst->flags, BT_VOCS_CLIENT_FLAG_CP_RETRIED)) {
276276
cb_err = BT_ATT_ERR_UNLIKELY;
277277
} else if (cb_err == BT_VOCS_ERR_INVALID_COUNTER && inst->state_handle) {
278278
LOG_DBG("Invalid change counter. Reading volume offset state from server.");
@@ -281,18 +281,19 @@ static void vocs_client_write_vocs_cp_cb(struct bt_conn *conn, uint8_t err,
281281
inst->read_params.handle_count = 1;
282282
inst->read_params.single.handle = inst->state_handle;
283283

284+
atomic_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_CP_RETRIED);
285+
284286
cb_err = bt_gatt_read(conn, &inst->read_params);
285287
if (cb_err) {
286288
LOG_WRN("Could not read Volume offset state: %d", cb_err);
287289
} else {
288-
inst->cp_retried = true;
289290
/* Wait for read callback */
290291
return;
291292
}
292293
}
293294

294-
inst->busy = false;
295-
inst->cp_retried = false;
295+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_CP_RETRIED);
296+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
296297

297298
if (inst->cb && inst->cb->set_offset) {
298299
inst->cb->set_offset(&inst->vocs, cb_err);
@@ -315,7 +316,7 @@ static uint8_t vocs_client_read_output_desc_cb(struct bt_conn *conn, uint8_t err
315316
}
316317

317318
LOG_DBG("Inst %p: err: 0x%02X", inst, err);
318-
inst->busy = false;
319+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
319320

320321
if (cb_err) {
321322
LOG_DBG("Description read failed: %d", err);
@@ -358,7 +359,7 @@ static uint8_t vocs_discover_func(struct bt_conn *conn, const struct bt_gatt_att
358359

359360
if (!attr) {
360361
LOG_DBG("Discovery complete for VOCS %p", inst);
361-
inst->busy = false;
362+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
362363
(void)memset(params, 0, sizeof(*params));
363364

364365
if (inst->cb && inst->cb->discover) {
@@ -393,7 +394,7 @@ static uint8_t vocs_discover_func(struct bt_conn *conn, const struct bt_gatt_att
393394
sub_params = &inst->location_sub_params;
394395
}
395396
if (chrc->properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
396-
inst->location_writable = true;
397+
atomic_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_LOC_WRITABLE);
397398
}
398399
} else if (!bt_uuid_cmp(chrc->uuid, BT_UUID_VOCS_CONTROL)) {
399400
LOG_DBG("Control point");
@@ -405,7 +406,7 @@ static uint8_t vocs_discover_func(struct bt_conn *conn, const struct bt_gatt_att
405406
sub_params = &inst->desc_sub_params;
406407
}
407408
if (chrc->properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
408-
inst->desc_writable = true;
409+
atomic_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_DESC_WRITABLE);
409410
}
410411
}
411412

@@ -455,8 +456,8 @@ int bt_vocs_client_state_get(struct bt_vocs_client *inst)
455456
return -EINVAL;
456457
}
457458

458-
if (inst->busy) {
459-
LOG_DBG("Handle not set");
459+
if (atomic_test_and_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
460+
LOG_DBG("Instance is busy");
460461
return -EBUSY;
461462
}
462463

@@ -466,8 +467,8 @@ int bt_vocs_client_state_get(struct bt_vocs_client *inst)
466467
inst->read_params.single.offset = 0U;
467468

468469
err = bt_gatt_read(inst->conn, &inst->read_params);
469-
if (!err) {
470-
inst->busy = true;
470+
if (err != 0) {
471+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
471472
}
472473

473474
return err;
@@ -493,13 +494,16 @@ int bt_vocs_client_location_set(struct bt_vocs_client *inst, uint32_t location)
493494
if (!inst->location_handle) {
494495
LOG_DBG("Handle not set");
495496
return -EINVAL;
496-
} else if (inst->busy) {
497-
return -EBUSY;
498-
} else if (!inst->location_writable) {
497+
} else if (!atomic_test_bit(inst->flags, BT_VOCS_CLIENT_FLAG_LOC_WRITABLE)) {
499498
LOG_DBG("Location is not writable on peer service instance");
500499
return -EPERM;
500+
} else if (atomic_test_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
501+
LOG_DBG("Instance is busy");
502+
return -EBUSY;
501503
}
502504

505+
/* When using write without response we do not set the busy flag */
506+
503507
return bt_gatt_write_without_response(inst->conn,
504508
inst->location_handle,
505509
&location, sizeof(location),
@@ -523,7 +527,8 @@ int bt_vocs_client_location_get(struct bt_vocs_client *inst)
523527
if (!inst->location_handle) {
524528
LOG_DBG("Handle not set");
525529
return -EINVAL;
526-
} else if (inst->busy) {
530+
} else if (atomic_test_and_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
531+
LOG_DBG("Instance is busy");
527532
return -EBUSY;
528533
}
529534

@@ -533,8 +538,8 @@ int bt_vocs_client_location_get(struct bt_vocs_client *inst)
533538
inst->read_params.single.offset = 0U;
534539

535540
err = bt_gatt_read(inst->conn, &inst->read_params);
536-
if (!err) {
537-
inst->busy = true;
541+
if (err != 0) {
542+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
538543
}
539544

540545
return err;
@@ -562,7 +567,8 @@ int bt_vocs_client_state_set(struct bt_vocs_client *inst, int16_t offset)
562567
if (!inst->control_handle) {
563568
LOG_DBG("Handle not set");
564569
return -EINVAL;
565-
} else if (inst->busy) {
570+
} else if (atomic_test_and_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
571+
LOG_DBG("Instance is busy");
566572
return -EBUSY;
567573
}
568574

@@ -577,8 +583,8 @@ int bt_vocs_client_state_set(struct bt_vocs_client *inst, int16_t offset)
577583
inst->write_params.func = vocs_client_write_vocs_cp_cb;
578584

579585
err = bt_gatt_write(inst->conn, &inst->write_params);
580-
if (!err) {
581-
inst->busy = true;
586+
if (err != 0) {
587+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
582588
}
583589

584590
return err;
@@ -601,7 +607,8 @@ int bt_vocs_client_description_get(struct bt_vocs_client *inst)
601607
if (!inst->desc_handle) {
602608
LOG_DBG("Handle not set");
603609
return -EINVAL;
604-
} else if (inst->busy) {
610+
} else if (atomic_test_and_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
611+
LOG_DBG("Instance is busy");
605612
return -EBUSY;
606613
}
607614

@@ -611,8 +618,8 @@ int bt_vocs_client_description_get(struct bt_vocs_client *inst)
611618
inst->read_params.single.offset = 0U;
612619

613620
err = bt_gatt_read(inst->conn, &inst->read_params);
614-
if (!err) {
615-
inst->busy = true;
621+
if (err != 0) {
622+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
616623
}
617624

618625
return err;
@@ -634,13 +641,16 @@ int bt_vocs_client_description_set(struct bt_vocs_client *inst,
634641
if (!inst->desc_handle) {
635642
LOG_DBG("Handle not set");
636643
return -EINVAL;
637-
} else if (inst->busy) {
638-
return -EBUSY;
639-
} else if (!inst->desc_writable) {
644+
} else if (!atomic_test_bit(inst->flags, BT_VOCS_CLIENT_FLAG_DESC_WRITABLE)) {
640645
LOG_DBG("Description is not writable on peer service instance");
641646
return -EPERM;
647+
} else if (atomic_test_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
648+
LOG_DBG("Instance is busy");
649+
return -EBUSY;
642650
}
643651

652+
/* When using write without response we do not set the busy flag */
653+
644654
return bt_gatt_write_without_response(inst->conn,
645655
inst->desc_handle,
646656
description,
@@ -650,9 +660,8 @@ int bt_vocs_client_description_set(struct bt_vocs_client *inst,
650660
struct bt_vocs *bt_vocs_client_free_instance_get(void)
651661
{
652662
for (int i = 0; i < ARRAY_SIZE(insts); i++) {
653-
if (!insts[i].active) {
663+
if (!atomic_test_and_set_bit(insts[i].flags, BT_VOCS_CLIENT_FLAG_ACTIVE)) {
654664
insts[i].vocs.client_instance = true;
655-
insts[i].active = true;
656665
return &insts[i].vocs;
657666
}
658667
}
@@ -689,9 +698,11 @@ int bt_vocs_client_conn_get(const struct bt_vocs *vocs, struct bt_conn **conn)
689698
static void vocs_client_reset(struct bt_vocs_client *inst)
690699
{
691700
memset(&inst->state, 0, sizeof(inst->state));
692-
inst->location_writable = 0;
701+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_LOC_WRITABLE);
702+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_DESC_WRITABLE);
703+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_CP_RETRIED);
704+
693705
inst->location = 0;
694-
inst->desc_writable = 0;
695706
inst->start_handle = 0;
696707
inst->end_handle = 0;
697708
inst->state_handle = 0;
@@ -733,12 +744,10 @@ int bt_vocs_discover(struct bt_conn *conn, struct bt_vocs *vocs,
733744

734745
inst = CONTAINER_OF(vocs, struct bt_vocs_client, vocs);
735746

736-
CHECKIF(!inst->active) {
747+
if (!atomic_test_bit(inst->flags, BT_VOCS_CLIENT_FLAG_ACTIVE)) {
737748
LOG_DBG("Inactive instance");
738749
return -EINVAL;
739-
}
740-
741-
if (inst->busy) {
750+
} else if (atomic_test_and_set_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY)) {
742751
LOG_DBG("Instance is busy");
743752
return -EBUSY;
744753
}
@@ -752,10 +761,9 @@ int bt_vocs_discover(struct bt_conn *conn, struct bt_vocs *vocs,
752761
inst->discover_params.func = vocs_discover_func;
753762

754763
err = bt_gatt_discover(conn, &inst->discover_params);
755-
if (err) {
764+
if (err != 0) {
756765
LOG_DBG("Discover failed (err %d)", err);
757-
} else {
758-
inst->busy = true;
766+
atomic_clear_bit(inst->flags, BT_VOCS_CLIENT_FLAG_BUSY);
759767
}
760768

761769
return err;

subsys/bluetooth/audio/vocs_internal.h

+12-5
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,20 @@ struct bt_vocs {
4242
bool client_instance;
4343
};
4444

45+
enum bt_vocs_client_flag {
46+
BT_VOCS_CLIENT_FLAG_BUSY,
47+
BT_VOCS_CLIENT_FLAG_CP_RETRIED,
48+
BT_VOCS_CLIENT_FLAG_DESC_WRITABLE,
49+
BT_VOCS_CLIENT_FLAG_LOC_WRITABLE,
50+
BT_VOCS_CLIENT_FLAG_ACTIVE,
51+
52+
BT_VOCS_CLIENT_FLAG_NUM_FLAGS, /* keep as last */
53+
};
54+
4555
struct bt_vocs_client {
4656
struct bt_vocs vocs;
4757
struct bt_vocs_state state;
48-
bool location_writable;
4958
uint32_t location;
50-
bool desc_writable;
51-
bool active;
5259

5360
uint16_t start_handle;
5461
uint16_t end_handle;
@@ -59,15 +66,15 @@ struct bt_vocs_client {
5966
struct bt_gatt_subscribe_params state_sub_params;
6067
struct bt_gatt_subscribe_params location_sub_params;
6168
struct bt_gatt_subscribe_params desc_sub_params;
62-
bool cp_retried;
6369

64-
bool busy;
6570
struct bt_vocs_control cp;
6671
struct bt_gatt_write_params write_params;
6772
struct bt_gatt_read_params read_params;
6873
struct bt_vocs_cb *cb;
6974
struct bt_gatt_discover_params discover_params;
7075
struct bt_conn *conn;
76+
77+
ATOMIC_DEFINE(flags, BT_VOCS_CLIENT_FLAG_NUM_FLAGS);
7178
};
7279

7380
enum bt_vocs_notify {

0 commit comments

Comments
 (0)