diff --git a/drivers/bluetooth/nble/gatt.c b/drivers/bluetooth/nble/gatt.c index ee8aa1f9cd2..63bc8444441 100644 --- a/drivers/bluetooth/nble/gatt.c +++ b/drivers/bluetooth/nble/gatt.c @@ -1218,8 +1218,10 @@ static void remove_subscriptions(struct bt_conn *conn) continue; } - /* Remove subscription */ - gatt_subscription_remove(conn, prev, params); + if (params->flags & BT_GATT_SUBSCRIBE_FLAG_VOLATILE) { + /* Remove subscription */ + gatt_subscription_remove(conn, prev, params); + } } } diff --git a/include/bluetooth/gatt.h b/include/bluetooth/gatt.h index 8d36363530f..2730344ac01 100644 --- a/include/bluetooth/gatt.h +++ b/include/bluetooth/gatt.h @@ -960,6 +960,20 @@ typedef uint8_t (*bt_gatt_notify_func_t)(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, const void *data, uint16_t length); +/* Subscription flags */ +enum { + /** Persistence flag + * + * If set, indicates that the subscription is not saved + * on the GATT server side. Therefore, upon disconnection, + * the subscription will be automatically removed + * from the client's subscriptions list and + * when the client reconnects, it will have to + * issue a new subscription. + */ + BT_GATT_SUBSCRIBE_FLAG_VOLATILE = BIT(0), +}; + /** @brief GATT Subscribe parameters */ struct bt_gatt_subscribe_params { struct bt_att_req _req; @@ -972,6 +986,8 @@ struct bt_gatt_subscribe_params { uint16_t ccc_handle; /** Subscribe value */ uint16_t value; + /** Subscription flags */ + uint8_t flags; sys_snode_t node; }; diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 12c0c3296a7..c6b75d5fa50 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -722,6 +722,17 @@ void bt_gatt_notification(struct bt_conn *conn, uint16_t handle, } } +static void update_subscription(struct bt_conn *conn, + struct bt_gatt_subscribe_params *params) +{ + if (params->_peer.type == BT_ADDR_LE_PUBLIC) { + return; + } + + /* Update address */ + bt_addr_le_copy(¶ms->_peer, &conn->le.dst); +} + static void gatt_subscription_remove(struct bt_conn *conn, sys_snode_t *prev, struct bt_gatt_subscribe_params *params) { @@ -747,8 +758,13 @@ static void remove_subscriptions(struct bt_conn *conn) continue; } - /* Remove subscription */ - gatt_subscription_remove(conn, prev, params); + if (!bt_addr_le_is_bonded(&conn->le.dst) || + (params->flags & BT_GATT_SUBSCRIBE_FLAG_VOLATILE)) { + /* Remove subscription */ + gatt_subscription_remove(conn, prev, params); + } else { + update_subscription(conn, params); + } } } @@ -1812,30 +1828,6 @@ static void add_subscriptions(struct bt_conn *conn) } } -static void update_subscriptions(struct bt_conn *conn) -{ - sys_snode_t *node; - - /* Update existing subscriptions */ - SYS_SLIST_FOR_EACH_NODE(&subscriptions, node) { - struct bt_gatt_subscribe_params *params; - - params = CONTAINER_OF(node, struct bt_gatt_subscribe_params, - node); - - if (params->_peer.type == BT_ADDR_LE_PUBLIC) { - continue; - } - - if (bt_conn_addr_le_cmp(conn, ¶ms->_peer)) { - continue; - } - - /* Update address */ - bt_addr_le_copy(¶ms->_peer, &conn->le.dst); - } -} - #endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ void bt_gatt_connected(struct bt_conn *conn) @@ -1853,12 +1845,6 @@ void bt_gatt_disconnected(struct bt_conn *conn) bt_gatt_foreach_attr(0x0001, 0xffff, disconnected_cb, conn); #if defined(CONFIG_BLUETOOTH_GATT_CLIENT) - /* If bonded don't remove subscriptions */ - if (bt_addr_le_is_bonded(&conn->le.dst)) { - update_subscriptions(conn); - return; - } - remove_subscriptions(conn); #endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ }