diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c
index d1f51a0..0c48f00 100644
--- a/profiles/deviceinfo/deviceinfo.c
+++ b/profiles/deviceinfo/deviceinfo.c
bt_string_to_uuid(&pnpid_uuid, PNPID_UUID);
if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
- &uuid)) {
+ NULL, &uuid)) {
error("Failed to obtain characteristic data");
return;
}
diff --git a/profiles/gap/gas.c b/profiles/gap/gas.c
index 877c4fd..35b996c 100644
--- a/profiles/gap/gas.c
+++ b/profiles/gap/gas.c
bt_uuid_t uuid;
if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
- &uuid)) {
+ NULL, &uuid)) {
error("Failed to obtain characteristic data");
return;
}
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index 4015b3f..d3ca762 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
bt_uuid_t uuid, scan_interval_wind_uuid, scan_refresh_uuid;
if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
- &uuid)) {
+ NULL, &uuid)) {
error("Failed to obtain characteristic data");
return;
}
diff --git a/src/device.c b/src/device.c
index 14ddc6b..5269ee8 100644
--- a/src/device.c
+++ b/src/device.c
bt_uuid_t uuid;
if (!gatt_db_attribute_get_char_data(attr, &handle_num, &value_handle,
- &properties, &uuid)) {
+ &properties, NULL, &uuid)) {
warn("Error storing characteristic - can't get data");
return;
}
diff --git a/src/gatt-client.c b/src/gatt-client.c
index 52add1d..ebb7b35 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
gatt_db_attribute_get_char_data(attr, &chrc->handle,
&chrc->value_handle,
- &chrc->props, &uuid);
+ &chrc->props, NULL,
+ &uuid);
chrc->attr = gatt_db_get_attribute(service->client->db,
chrc->value_handle);
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 34b6cc7..ff49be1 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
if (bt_uuid_cmp(&uuid, gatt_db_attribute_get_type(attr)))
return NULL;
- if (!gatt_db_attribute_get_char_data(attr, NULL, NULL,
- &properties, NULL))
- return NULL;
+ if (!gatt_db_attribute_get_char_data(attr, NULL, NULL, &properties,
+ NULL, NULL))
+ return NULL;
chrc = new0(struct notify_chrc, 1);
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index cc49458..513451f 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
.value.u16 = GATT_CHARAC_UUID };
static const bt_uuid_t included_service_uuid = { .type = BT_UUID16,
.value.u16 = GATT_INCLUDE_UUID };
+static const bt_uuid_t ext_desc_uuid = { .type = BT_UUID16,
+ .value.u16 = GATT_CHARAC_EXT_PROPER_UUID };
struct gatt_db {
int ref_count;
return le_to_uuid(decl->value, decl->value_len, uuid);
}
+static void read_ext_prop_value(struct gatt_db_attribute *attrib,
+ int err, const uint8_t *value,
+ size_t length, void *user_data)
+{
+ uint16_t *ext_prop = user_data;
+
+ if (err || (length != sizeof(uint16_t)))
+ return;
+
+ *ext_prop = (uint16_t) value[0];
+}
+
+static void read_ext_prop(struct gatt_db_attribute *attrib,
+ void *user_data)
+{
+ uint16_t *ext_prop = user_data;
+
+ /*
+ * If ext_prop is set that means extended properties descriptor
+ * has been already found
+ */
+ if (*ext_prop != 0)
+ return;
+
+ if (bt_uuid_cmp(&ext_desc_uuid, &attrib->uuid))
+ return;
+
+ gatt_db_attribute_read(attrib, 0, BT_ATT_OP_READ_REQ, NULL,
+ read_ext_prop_value, ext_prop);
+}
+
+static uint8_t get_char_extended_prop(const struct gatt_db_attribute *attrib)
+{
+ uint16_t ext_prop;
+
+ if (!attrib)
+ return 0;
+
+ if (bt_uuid_cmp(&characteristic_uuid, &attrib->uuid))
+ return 0;
+
+ /* Check properties first */
+ if (!(attrib->value[0] & BT_GATT_CHRC_PROP_EXT_PROP))
+ return 0;
+
+ ext_prop = 0;
+
+ /*
+ * Cast needed for foreach function. We do not change attrib during
+ * this call
+ */
+ gatt_db_service_foreach_desc((struct gatt_db_attribute *) attrib,
+ read_ext_prop, &ext_prop);
+
+ return ext_prop;
+}
+
bool gatt_db_attribute_get_char_data(const struct gatt_db_attribute *attrib,
uint16_t *handle,
uint16_t *value_handle,
uint8_t *properties,
+ uint16_t *ext_prop,
bt_uuid_t *uuid)
{
if (!attrib)
if (properties)
*properties = attrib->value[0];
+ if (ext_prop)
+ *ext_prop = get_char_extended_prop(attrib);
+
if (value_handle)
*value_handle = get_le16(attrib->value + 1);
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index 96cceb9..134ec63 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
uint16_t *handle,
uint16_t *value_handle,
uint8_t *properties,
+ uint16_t *ext_prop,
bt_uuid_t *uuid);
bool gatt_db_attribute_get_incl_data(const struct gatt_db_attribute *attrib,
diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index 2153bec..4c8c9dd 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
{
uint16_t handle, value_handle;
uint8_t properties;
+ uint16_t ext_prop;
bt_uuid_t uuid;
if (!gatt_db_attribute_get_char_data(attr, &handle,
&value_handle,
&properties,
+ &ext_prop,
&uuid))
return;
printf("\t " COLOR_YELLOW "charac" COLOR_OFF
- " - start: 0x%04x, value: 0x%04x, "
- "props: 0x%02x, uuid: ",
- handle, value_handle, properties);
+ " - start: 0x%04x, value: 0x%04x, "
+ "props: 0x%02x, ext_props: 0x%04x, uuid: ",
+ handle, value_handle, properties, ext_prop);
print_uuid(&uuid);
gatt_db_service_foreach_desc(attr, print_desc, NULL);
diff --git a/tools/btgatt-server.c b/tools/btgatt-server.c
index 099db8a..fadaff2 100644
--- a/tools/btgatt-server.c
+++ b/tools/btgatt-server.c
{
uint16_t handle, value_handle;
uint8_t properties;
+ uint16_t ext_prop;
bt_uuid_t uuid;
if (!gatt_db_attribute_get_char_data(attr, &handle,
&value_handle,
&properties,
+ &ext_prop,
&uuid))
return;
printf("\t " COLOR_YELLOW "charac" COLOR_OFF
- " - start: 0x%04x, value: 0x%04x, "
- "props: 0x%02x, uuid: ",
- handle, value_handle, properties);
+ " - start: 0x%04x, value: 0x%04x, "
+ "props: 0x%02x, ext_prop: 0x%04x, uuid: ",
+ handle, value_handle, properties, ext_prop);
print_uuid(&uuid);
gatt_db_service_foreach_desc(attr, print_desc, NULL);
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 126a59f..03925e9 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
bt_uuid_t a_uuid, b_uuid;
gatt_db_attribute_get_char_data(a, &a_handle, &a_value_handle,
- &a_properties, &a_uuid);
+ &a_properties, NULL, &a_uuid);
gatt_db_attribute_get_char_data(b, &b_handle, &b_value_handle,
- &b_properties, &b_uuid);
+ &b_properties, NULL, &b_uuid);
return a_handle == b_handle && a_value_handle == b_value_handle &&
a_properties == b_properties &&