bluetooth: host: add ability to load CCC settings on demand

This commits adds a BT_SETTINGS_CCC_LAZY_LOADING option to allow for
CCC settings to be loaded on demand when a peer device connects in
order to reduce memory usage.

Signed-off-by: François Delawarde <fnde@oticon.com>
This commit is contained in:
François Delawarde 2019-11-05 08:20:07 +01:00 committed by Johan Hedberg
commit a51986616e
3 changed files with 59 additions and 1 deletions

View file

@ -551,7 +551,11 @@ ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn,
.properties = _props, })), \
BT_GATT_ATTRIBUTE(_uuid, _perm, _read, _write, _value)
#define BT_GATT_CCC_MAX (CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN)
#if IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)
#define BT_GATT_CCC_MAX (CONFIG_BT_MAX_CONN)
#else
#define BT_GATT_CCC_MAX (CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN)
#endif
/** @brief GATT CCC configuration entry.
* @param id Local identity, BT_ID_DEFAULT in most cases.

View file

@ -173,6 +173,15 @@ config BT_SETTINGS
instead of each subsystem doing it independently.
if BT_SETTINGS
config BT_SETTINGS_CCC_LAZY_LOADING
bool "Load CCC values from settings when peer connects"
default y
help
Load Client Configuration Characteristic setting right after a bonded
device connects.
Disabling this option will increase memory usage as CCC values for all
bonded devices will be loaded when calling settings_load.
config BT_SETTINGS_CCC_STORE_ON_WRITE
bool "Store CCC value immediately after it has been written"
help

View file

@ -3585,6 +3585,11 @@ static void add_subscriptions(struct bt_conn *conn)
#endif /* CONFIG_BT_GATT_CLIENT */
#if IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)
static int ccc_set_direct(const char *key, size_t len, settings_read_cb read_cb,
void *cb_arg, void *param);
#endif /* CONFIG_BT_SETTINGS_CCC_LAZY_LOADING */
void bt_gatt_connected(struct bt_conn *conn)
{
struct conn_data data;
@ -3594,6 +3599,26 @@ void bt_gatt_connected(struct bt_conn *conn)
data.conn = conn;
data.sec = BT_SECURITY_L1;
#if IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)
/* Load CCC settings from backend if bonded */
if (bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
char key[BT_SETTINGS_KEY_MAX];
if (conn->id) {
char id_str[4];
u8_to_dec(id_str, sizeof(id_str), conn->id);
bt_settings_encode_key(key, sizeof(key), "ccc",
&conn->le.dst, id_str);
} else {
bt_settings_encode_key(key, sizeof(key), "ccc",
&conn->le.dst, NULL);
}
settings_load_subtree_direct(key, ccc_set_direct, (void *)key);
}
#endif /* CONFIG_BT_SETTINGS_CCC_LAZY_LOADING */
bt_gatt_foreach_attr(0x0001, 0xffff, update_ccc, &data);
/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part C page 2192:
@ -4124,7 +4149,27 @@ static int ccc_set(const char *name, size_t len_rd, settings_read_cb read_cb,
return 0;
}
#if IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)
static int ccc_set_direct(const char *key, size_t len, settings_read_cb read_cb,
void *cb_arg, void *param)
{
const char *name;
BT_DBG("key: %s", log_strdup((const char *)param));
/* Only "bt/ccc" settings should ever come here */
if (!settings_name_steq((const char *)param, "bt/ccc", &name)) {
BT_ERR("Invalid key");
return -EINVAL;
}
return ccc_set(name, len, read_cb, cb_arg);
}
#else
/* Only register the ccc_set settings handler when not loading on-demand */
SETTINGS_STATIC_HANDLER_DEFINE(bt_ccc, "bt/ccc", NULL, ccc_set, NULL, NULL);
#endif /* CONFIG_BT_SETTINGS_CCC_LAZY_LOADING */
#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
static int sc_set(const char *name, size_t len_rd, settings_read_cb read_cb,