Skip to content

Commit

Permalink
Bluetooth: audio: has: Add non-volatile settings
Browse files Browse the repository at this point in the history
This adds non-volatile settings for the HAS Server. Those are needed to
restore the client awareness of preset list entries exposed by the
server. Based on the settings, the implementation determines how to
notify the client about the HAS related characteristic value changes.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
  • Loading branch information
MariuszSkamra committed Oct 23, 2023
1 parent b1c2075 commit f7ed5b5
Showing 1 changed file with 90 additions and 21 deletions.
111 changes: 90 additions & 21 deletions subsys/bluetooth/audio/has.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <zephyr/sys/slist.h>

#include "../bluetooth/host/hci_core.h"
#include "../bluetooth/host/settings.h"
#include "audio_internal.h"
#include "has_internal.h"

Expand Down Expand Up @@ -298,8 +299,6 @@ static struct has_client *client_alloc(struct bt_conn *conn)
}

LOG_DBG("New client_context for %s", bt_addr_le_str(info.le.dst));
} else {
LOG_DBG("Restored client_context for %s", bt_addr_le_str(info.le.dst));
}

return client;
Expand Down Expand Up @@ -508,26 +507,15 @@ static void bond_deleted_cb(uint8_t id, const bt_addr_le_t *addr)
if (context != NULL) {
context_free(context);
}

if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_settings_delete("has", 0, addr);
}
}

static struct bt_conn_auth_info_cb auth_info_cb = {
.bond_deleted = bond_deleted_cb,
};

static void restore_client_context(const struct bt_bond_info *info, void *user_data)
{
struct client_context *context;

context = context_alloc(&info->addr);
if (context == NULL) {
LOG_ERR("Failed to allocate client_context for %s", bt_addr_le_str(&info->addr));
return;
}

/* Notify all the characteristics values after reboot */
atomic_set(context->flags, BONDED_CLIENT_INIT_FLAGS);
}

#endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */

#if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
Expand Down Expand Up @@ -868,19 +856,102 @@ static int bt_has_cp_generic_update(struct has_client *client, uint8_t prev_inde
}
}

#if defined(CONFIG_BT_SETTINGS)
struct client_context_store {
/* Last notified preset index */
uint8_t last_preset_index_known;
};

static int settings_set_cb(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
{
struct client_context_store store;
struct client_context *context;
bt_addr_le_t addr;
const char *next;
ssize_t len;
int err;

LOG_DBG("%s", name);

if (!name) {
LOG_ERR("Insufficient number of arguments");
return -EINVAL;
}

err = bt_settings_decode_key(name, &addr);
if (err) {
LOG_ERR("Unable to decode address %s", name);
return -EINVAL;
}

settings_name_next(name, &next);

context = context_find(&addr);
if (context == NULL && len_rd) {
/* Find and initialize a free entry */
context = context_alloc(&addr);
if (context == NULL) {
LOG_ERR("Failed to allocate client_context for %s", bt_addr_le_str(&addr));
return -ENOMEM;
}

/* Notify all the characteristics values after reboot */
atomic_set(context->flags, BONDED_CLIENT_INIT_FLAGS);
}

if (len_rd) {
len = read_cb(cb_arg, &store, sizeof(store));
if (len < 0) {
LOG_ERR("Failed to decode value (err %zd)", len);
return len;
}

context->last_preset_index_known = store.last_preset_index_known;

LOG_DBG("Restored client_context for %s len %zd", bt_addr_le_str(&addr), len);
}

return 0;
}

BT_SETTINGS_DEFINE(has, "has", settings_set_cb, NULL);

static void store_client_context(struct client_context *context)
{
struct client_context_store store = {
.last_preset_index_known = context->last_preset_index_known,
};
int err;

LOG_DBG("%s last_preset_index_known 0x%02x",
bt_addr_le_str(&context->addr), store.last_preset_index_known);

err = bt_settings_store("has", 0, &context->addr, &store, sizeof(store));
if (err != 0) {
LOG_ERR("Failed to store err %d", err);
}
}
#else
#define store_client_context(...)
#endif /* CONFIG_BT_SETTINGS */

static void update_last_preset_index_known(struct has_client *client, uint8_t index)
{
if (client != NULL) {
if (client != NULL && client->context != NULL &&
client->context->last_preset_index_known != index) {
client->context->last_preset_index_known = index;
store_client_context(client->context);
return;
}

for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) {
client = &has_client_list[i];

/* For each connected client */
if (client->conn != NULL && client->context != NULL) {
if (client->conn != NULL && client->context != NULL &&
client->context->last_preset_index_known != index) {
client->context->last_preset_index_known = index;
store_client_context(client->context);
}
}
}
Expand Down Expand Up @@ -1709,8 +1780,6 @@ int bt_has_register(const struct bt_has_features_param *features)

#if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
bt_conn_auth_info_cb_register(&auth_info_cb);

bt_foreach_bond(BT_ID_DEFAULT, restore_client_context, NULL);
#endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */

has.registered = true;
Expand Down

0 comments on commit f7ed5b5

Please sign in to comment.