Bluetooth: GATT: Add function to check if attribute has been subscribed

Add public API function in GATT to check if a specific connection has
subscribed to the given attribute.
Without this function the application has to keep track of which
connections has subscribed using the callbacks from BT_GATT_CCC_MANAGED
since the cfg_changed callback of the CCC doesn't carry connection
context.
The other alternative is for the application to parse the information
in the struct _bt_gatt_ccc object. Although this object has structure
information available to the application the structure is marked as
internal, so the application shouldn't rely on this definition.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2019-10-14 10:44:30 +02:00 committed by Johan Hedberg
commit 5229276817
2 changed files with 70 additions and 0 deletions

View file

@ -917,6 +917,27 @@ struct bt_gatt_indicate_params {
int bt_gatt_indicate(struct bt_conn *conn,
struct bt_gatt_indicate_params *params);
/** @brief Check if connection have subscribed to attribute
*
* Check if connection has subscribed to attribute value change.
*
* The attribute object can be the so called Characteristic Declaration,
* which is usually declared with BT_GATT_CHARACTERISTIC followed
* by BT_GATT_CCC, or the Characteristic Value Declaration which is
* automatically created after the Characteristic Declaration when using
* BT_GATT_CHARACTERISTIC, or the Client Characteristic Configuration
* Descriptor (CCCD) which is created by BT_GATT_CCC.
*
* @param conn Connection object.
* @param attr Attribute object.
* @param ccc_value The subscription type, either notifications or indications.
*
* @return true if the attribute object has been subscribed.
*/
bool bt_gatt_is_subscribed(struct bt_conn *conn,
const struct bt_gatt_attr *attr, u16_t ccc_value);
/** @brief Get ATT MTU for a connection
*
* Get negotiated ATT connection MTU, note that this does not equal the largest

View file

@ -2082,6 +2082,55 @@ static u8_t disconnected_cb(const struct bt_gatt_attr *attr, void *user_data)
return BT_GATT_ITER_CONTINUE;
}
bool bt_gatt_is_subscribed(struct bt_conn *conn,
const struct bt_gatt_attr *attr, u16_t ccc_value)
{
const struct _bt_gatt_ccc *ccc;
__ASSERT(conn, "invalid parameter\n");
__ASSERT(attr, "invalid parameter\n");
if (conn->state != BT_CONN_CONNECTED) {
return false;
}
/* Check if attribute is a characteristic declaration */
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
struct bt_gatt_chrc *chrc = attr->user_data;
if (!(chrc->properties &
(BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE))) {
/* Characteristic doesn't support subscription */
return false;
}
attr = bt_gatt_attr_next(attr);
}
/* Check if attribute is a characteristic value */
if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) != 0) {
attr = bt_gatt_attr_next(attr);
}
/* Check if the attribute is the CCC Descriptor */
if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) != 0) {
return false;
}
ccc = attr->user_data;
/* Check if the connection is subscribed */
for (size_t i = 0; i < BT_GATT_CCC_MAX; i++) {
if (conn->id == ccc->cfg[i].id &&
!bt_conn_addr_le_cmp(conn, &ccc->cfg[i].peer) &&
(ccc_value & ccc->cfg[i].value)) {
return true;
}
}
return false;
}
#if defined(CONFIG_BT_GATT_CLIENT)
void bt_gatt_notification(struct bt_conn *conn, u16_t handle,
const void *data, u16_t length)