diff --git a/monitor/att.c b/monitor/att.c
index 3e5d7f1..b3fb3ba 100644
--- a/monitor/att.c
+++ b/monitor/att.c
static struct gatt_db_attribute *insert_chrc(const struct l2cap_frame *frame,
uint16_t handle,
+ uint16_t value_handle,
bt_uuid_t *uuid, uint8_t prop,
bool rsp)
{
if (!db)
return NULL;
- return gatt_db_insert_characteristic(db, handle, uuid, 0, prop, NULL,
- NULL, NULL);
+ return gatt_db_insert_characteristic(db, handle, value_handle, uuid, 0,
+ prop, NULL, NULL, NULL);
}
static int bt_uuid_from_data(bt_uuid_t *uuid, const void *data, uint16_t size)
print_uuid(" Value UUID", frame->data, frame->size);
bt_uuid_from_data(&uuid, frame->data, frame->size);
- insert_chrc(frame, handle, &uuid, prop, true);
+ insert_chrc(frame, handle - 1, handle, &uuid, prop, true);
}
static void chrc_read(const struct l2cap_frame *frame)
diff --git a/src/gatt-database.c b/src/gatt-database.c
index 7221ffc..6c11027 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
}
chrc->attrib = gatt_db_service_insert_characteristic(service->attrib,
- handle, &uuid, chrc->perm,
- chrc->props, chrc_read_cb,
- chrc_write_cb, chrc);
+ handle - 1, handle, &uuid,
+ chrc->perm, chrc->props,
+ chrc_read_cb, chrc_write_cb,
+ chrc);
if (!chrc->attrib) {
error("Failed to create characteristic entry in database");
return false;
diff --git a/src/settings.c b/src/settings.c
index 85534f2..033e967 100644
--- a/src/settings.c
+++ b/src/settings.c
handle_int, value_handle,
properties, val_len ? val_str : "", uuid_str);
- att = gatt_db_service_insert_characteristic(service, value_handle,
+ att = gatt_db_service_insert_characteristic(service, handle_int,
+ value_handle,
&uuid, 0, properties,
NULL, NULL, NULL);
if (!att || gatt_db_attribute_get_handle(att) != value_handle)
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 6340bcd..dcf6f02 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
}
attr = gatt_db_insert_characteristic(client->db,
+ chrc_data->start_handle,
chrc_data->value_handle,
&chrc_data->uuid, 0,
chrc_data->properties,
return true;
failed:
+ DBG(client, "Failed to discover descriptors");
+
free(chrc_data);
return false;
}
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 9559583..2c8e7d3 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
return true;
}
-static uint16_t get_attribute_index(struct gatt_db_service *service,
+static uint16_t service_get_attribute_index(struct gatt_db_service *service,
+ uint16_t *handle,
int end_offset)
{
int i = 0;
- /* Here we look for first free attribute index with given offset */
- while (i < (service->num_handles - end_offset) &&
+ if (!service || !service->attributes[0] || !handle)
+ return 0;
+
+ if (*handle) {
+ /* Check if handle is in within service range */
+ if (*handle < service->attributes[0]->handle)
+ return 0;
+
+ /* Return index based on given handle */
+ i = *handle - service->attributes[0]->handle;
+ } else {
+ /* Here we look for first free attribute index with given
+ * offset.
+ */
+ while (i < (service->num_handles - end_offset) &&
service->attributes[i])
- i++;
+ i++;
+ }
- return i == (service->num_handles - end_offset) ? 0 : i;
-}
+ if (i >= (service->num_handles - end_offset))
+ return 0;
-static uint16_t get_handle_at_index(struct gatt_db_service *service,
- int index)
-{
- return service->attributes[index]->handle;
+ /* Set handle based on the index */
+ if (!(*handle))
+ *handle = service->attributes[0]->handle + i;
+
+ return i;
}
static struct gatt_db_attribute *
service_insert_characteristic(struct gatt_db_service *service,
uint16_t handle,
+ uint16_t value_handle,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
gatt_db_write_t write_func,
void *user_data)
{
+ struct gatt_db_attribute **chrc;
uint8_t value[MAX_CHAR_DECL_VALUE_LEN];
uint16_t len = 0;
int i;
if (handle == UINT16_MAX)
return NULL;
- i = get_attribute_index(service, 1);
+ i = service_get_attribute_index(service, &handle, 1);
if (!i)
return NULL;
- if (!handle)
- handle = get_handle_at_index(service, i - 1) + 2;
-
value[0] = properties;
len += sizeof(properties);
/* We set handle of characteristic value, which will be added next */
- put_le16(handle, &value[1]);
+ put_le16(value_handle, &value[1]);
len += sizeof(uint16_t);
len += uuid_to_le(uuid, &value[3]);
- service->attributes[i] = new_attribute(service, handle - 1,
+ service->attributes[i] = new_attribute(service, handle,
&characteristic_uuid,
value, len);
if (!service->attributes[i])
return NULL;
- set_attribute_data(service->attributes[i], NULL, NULL, BT_ATT_PERM_READ, NULL);
+ chrc = &service->attributes[i];
+ set_attribute_data(service->attributes[i], NULL, NULL, BT_ATT_PERM_READ,
+ NULL);
- i++;
+ i = service_get_attribute_index(service, &value_handle, 0);
+ if (!i) {
+ free(*chrc);
+ *chrc = NULL;
+ return NULL;
+ }
- service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
+ service->attributes[i] = new_attribute(service, value_handle, uuid,
+ NULL, 0);
if (!service->attributes[i]) {
- free(service->attributes[i - 1]);
+ free(*chrc);
+ *chrc = NULL;
return NULL;
}
+ /* Update handle of characteristic value_handle if it has changed */
+ put_le16(value_handle, &value[1]);
+ if (memcmp((*chrc)->value, value, len))
+ memcpy((*chrc)->value, value, len);
+
set_attribute_data(service->attributes[i], read_func, write_func,
permissions, user_data);
struct gatt_db_attribute *
gatt_db_insert_characteristic(struct gatt_db *db,
uint16_t handle,
+ uint16_t value_handle,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
if (!attrib)
return NULL;
- return service_insert_characteristic(attrib->service, handle, uuid,
+ return service_insert_characteristic(attrib->service, handle,
+ value_handle, uuid,
permissions, properties,
read_func, write_func,
user_data);
struct gatt_db_attribute *
gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
uint16_t handle,
+ uint16_t value_handle,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
if (!attrib)
return NULL;
- return service_insert_characteristic(attrib->service, handle, uuid,
+ return service_insert_characteristic(attrib->service, handle,
+ value_handle, uuid,
permissions, properties,
read_func, write_func,
user_data);
if (!attrib)
return NULL;
- return service_insert_characteristic(attrib->service, 0, uuid,
+ return service_insert_characteristic(attrib->service, 0, 0, uuid,
permissions, properties,
read_func, write_func,
user_data);
{
int i;
- i = get_attribute_index(service, 0);
+ i = service_get_attribute_index(service, &handle, 0);
if (!i)
return NULL;
- /* Check if handle is in within service range */
- if (handle && handle <= service->attributes[0]->handle)
- return NULL;
-
- if (!handle)
- handle = get_handle_at_index(service, i - 1) + 1;
-
service->attributes[i] = new_attribute(service, handle, uuid, NULL, 0);
if (!service->attributes[i])
return NULL;
len += include->value_len;
}
- index = get_attribute_index(service, 0);
+ index = service_get_attribute_index(service, &handle, 0);
if (!index)
return NULL;
- /* Check if handle is in within service range */
- if (handle && handle <= service->attributes[0]->handle)
- return NULL;
-
- if (!handle)
- handle = get_handle_at_index(service, index - 1) + 1;
-
service->attributes[index] = new_attribute(service, handle,
&included_service_uuid,
value, len);
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index fb939e4..f7596e3 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
struct gatt_db_attribute *
gatt_db_service_insert_characteristic(struct gatt_db_attribute *attrib,
uint16_t handle,
+ uint16_t value_handle,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
struct gatt_db_attribute *
gatt_db_insert_characteristic(struct gatt_db *db,
uint16_t handle,
+ uint16_t value_handle,
const bt_uuid_t *uuid,
uint32_t permissions,
uint8_t properties,
diff --git a/unit/test-gatt.c b/unit/test-gatt.c
index 5e06d4e..1613fbc 100644
--- a/unit/test-gatt.c
+++ b/unit/test-gatt.c
if (handle)
attrib = gatt_db_service_insert_characteristic(service_att,
+ handle - 1,
handle, uuid,
att_permissions,
char_properties,