Skip to content

Commit aecf7c7

Browse files
Vudentzjhedberg
authored andcommitted
Bluetooth: GATT: Store Client features
Client features shall be persisted across connections. Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 3cccf27 commit aecf7c7

File tree

1 file changed

+115
-2
lines changed

1 file changed

+115
-2
lines changed

subsys/bluetooth/host/gatt.c

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ static ssize_t db_hash_read(struct bt_conn *conn,
426426
sizeof(db_hash));
427427
}
428428

429+
static void clear_cf_cfg(struct gatt_cf_cfg *cfg)
430+
{
431+
bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY);
432+
memset(cfg->data, 0, sizeof(cfg->data));
433+
atomic_set(cfg->flags, 0);
434+
}
435+
429436
static void remove_cf_cfg(struct bt_conn *conn)
430437
{
431438
struct gatt_cf_cfg *cfg;
@@ -442,8 +449,7 @@ static void remove_cf_cfg(struct bt_conn *conn)
442449
* default value at each connection.
443450
*/
444451
if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
445-
bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY);
446-
memset(cfg->data, 0, sizeof(cfg->data));
452+
clear_cf_cfg(cfg);
447453
} else {
448454
/* Update address in case it has changed */
449455
bt_addr_le_copy(&cfg->peer, &conn->le.dst);
@@ -2815,6 +2821,50 @@ bool bt_gatt_change_aware(struct bt_conn *conn, bool req)
28152821
#endif
28162822
}
28172823

2824+
static int bt_gatt_store_cf(struct bt_conn *conn)
2825+
{
2826+
#if defined(CONFIG_BT_GATT_CACHING)
2827+
struct gatt_cf_cfg *cfg;
2828+
char key[BT_SETTINGS_KEY_MAX];
2829+
char *str;
2830+
size_t len;
2831+
int err;
2832+
2833+
cfg = find_cf_cfg(conn);
2834+
if (!cfg) {
2835+
/* No cfg found just cleare it */
2836+
str = NULL;
2837+
len = 0;
2838+
goto save;
2839+
}
2840+
2841+
if (conn->id) {
2842+
char id_str[4];
2843+
2844+
snprintk(id_str, sizeof(id_str), "%u", conn->id);
2845+
bt_settings_encode_key(key, sizeof(key), "cf",
2846+
&conn->le.dst, id_str);
2847+
} else {
2848+
bt_settings_encode_key(key, sizeof(key), "cf",
2849+
&conn->le.dst, NULL);
2850+
}
2851+
2852+
str = (char *)cfg->data;
2853+
len = sizeof(cfg->data);
2854+
2855+
save:
2856+
err = settings_save_one(key, str, len);
2857+
if (err) {
2858+
BT_ERR("Failed to store Client Features (err %d)", err);
2859+
return err;
2860+
}
2861+
2862+
BT_DBG("Stored CF for %s (%s)", bt_addr_le_str(&conn->le.dst), key);
2863+
#endif /* CONFIG_BT_GATT_CACHING */
2864+
return 0;
2865+
2866+
}
2867+
28182868
void bt_gatt_disconnected(struct bt_conn *conn)
28192869
{
28202870
BT_DBG("conn %p", conn);
@@ -2831,6 +2881,7 @@ void bt_gatt_disconnected(struct bt_conn *conn)
28312881
if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
28322882
bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
28332883
bt_gatt_store_ccc(conn->id, &conn->le.dst);
2884+
bt_gatt_store_cf(conn);
28342885
}
28352886

28362887
#if defined(CONFIG_BT_GATT_CLIENT)
@@ -3121,4 +3172,66 @@ static int ccc_set(int argc, char **argv, void *val_ctx)
31213172
}
31223173

31233174
BT_SETTINGS_DEFINE(ccc, ccc_set, NULL, NULL);
3175+
3176+
#if defined(CONFIG_BT_GATT_CACHING)
3177+
static struct gatt_cf_cfg *find_cf_cfg_by_addr(const bt_addr_le_t *addr)
3178+
{
3179+
int i;
3180+
3181+
for (i = 0; i < ARRAY_SIZE(cf_cfg); i++) {
3182+
if (!bt_addr_le_cmp(addr, &cf_cfg[i].peer)) {
3183+
return &cf_cfg[i];
3184+
}
3185+
}
3186+
3187+
return NULL;
3188+
}
3189+
3190+
static int cf_set(int argc, char **argv, void *val_ctx)
3191+
{
3192+
struct gatt_cf_cfg *cfg;
3193+
bt_addr_le_t addr;
3194+
int len, err;
3195+
3196+
if (argc < 1) {
3197+
BT_ERR("Insufficient number of arguments");
3198+
return -EINVAL;
3199+
}
3200+
3201+
err = bt_settings_decode_key(argv[0], &addr);
3202+
if (err) {
3203+
BT_ERR("Unable to decode address %s", argv[0]);
3204+
return -EINVAL;
3205+
}
3206+
3207+
cfg = find_cf_cfg_by_addr(&addr);
3208+
if (!cfg) {
3209+
cfg = find_cf_cfg(NULL);
3210+
if (!cfg) {
3211+
BT_ERR("Unable to restore CF: no cfg left");
3212+
return 0;
3213+
}
3214+
}
3215+
3216+
if (settings_val_get_len_cb(val_ctx)) {
3217+
len = settings_val_read_cb(val_ctx, cfg->data,
3218+
sizeof(cfg->data));
3219+
if (len < 0) {
3220+
BT_ERR("Failed to decode value (err %d)", len);
3221+
return len;
3222+
}
3223+
3224+
BT_DBG("Read CF: len %d", len);
3225+
} else {
3226+
bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY);
3227+
memset(cfg->data, 0, sizeof(cfg->data));
3228+
}
3229+
3230+
BT_DBG("Restored CF for %s", bt_addr_le_str(&addr));
3231+
3232+
return 0;
3233+
}
3234+
3235+
BT_SETTINGS_DEFINE(cf, cf_set, NULL, NULL);
3236+
#endif /*CONFIG_BT_GATT_CACHING */
31243237
#endif /* CONFIG_BT_SETTINGS */

0 commit comments

Comments
 (0)