diff --git a/subsys/bluetooth/audio/has.c b/subsys/bluetooth/audio/has.c index fc1aba7aec2..6013cadd014 100644 --- a/subsys/bluetooth/audio/has.c +++ b/subsys/bluetooth/audio/has.c @@ -15,6 +15,7 @@ #include #include "../bluetooth/host/hci_core.h" +#include "../bluetooth/host/settings.h" #include "audio_internal.h" #include "has_internal.h" @@ -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; @@ -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) @@ -868,10 +856,86 @@ 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; +} __packed; + +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; + ssize_t len; + int err; + + 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; + } + + context = context_find(&addr); + if (context == NULL) { + /* 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; + } + } + + 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; + } else { + context->last_preset_index_known = 0x00; + } + + /* Notify all the characteristics values after reboot */ + atomic_set(context->flags, BONDED_CLIENT_INIT_FLAGS); + + 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; } @@ -879,8 +943,10 @@ static void update_last_preset_index_known(struct has_client *client, uint8_t in 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); } } } @@ -933,6 +999,8 @@ static int bt_has_cp_preset_record_deleted(struct has_client *client, uint8_t in NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) + sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t)); + LOG_DBG("client %p index 0x%02x", client, index); + preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_PRESET_DELETED, BT_HAS_IS_LAST); net_buf_simple_add_u8(&buf, index); @@ -1709,8 +1777,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;