diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index a211cda..2289a63 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
#include "src/shared/queue.h"
#include "src/shared/gatt-db.h"
+#define MAX_CHAR_DECL_VALUE_LEN 19
+
static const bt_uuid_t primary_service_uuid = { .type = BT_UUID16,
.value.u16 = GATT_PRIM_SVC_UUID };
static const bt_uuid_t secondary_service_uuid = { .type = BT_UUID16,
.value.u16 = GATT_SND_SVC_UUID };
+static const bt_uuid_t characteristic_uuid = { .type = BT_UUID16,
+ .value.u16 = GATT_CHARAC_UUID };
struct gatt_db {
uint16_t next_handle;
struct gatt_db_attribute {
uint16_t handle;
bt_uuid_t uuid;
+ uint8_t permissions;
+ gatt_db_read_t read_func;
+ gatt_db_write_t write_func;
+ void *user_data;
uint16_t val_len;
uint8_t value[0];
};
return true;
}
+
+static uint16_t get_attribute_index(struct gatt_db_service *service,
+ int end_offset)
+{
+ int i = 0;
+
+ /* Here we look for first free attribute index with given offset */
+ while (i < (service->num_handles - end_offset) &&
+ service->attributes[i])
+ i++;
+
+ return i == (service->num_handles - end_offset) ? 0 : i;
+}
+
+static uint16_t get_handle_at_index(struct gatt_db_service *service,
+ int index)
+{
+ return service->attributes[index]->handle;
+}
+
+static uint16_t update_attribute_handle(struct gatt_db_service *service,
+ int index)
+{
+ uint16_t previous_handle;
+
+ /* We call this function with index > 0, because index 0 is reserved
+ * for service declaration, and is set in add_service()
+ */
+ previous_handle = service->attributes[index - 1]->handle;
+ service->attributes[index]->handle = previous_handle + 1;
+
+ return service->attributes[index]->handle;
+}
+
+static void set_attribute_data(struct gatt_db_attribute *attribute,
+ gatt_db_read_t read_func,
+ gatt_db_write_t write_func,
+ uint8_t permissions,
+ void *user_data)
+{
+ attribute->permissions = permissions;
+ attribute->read_func = read_func;
+ attribute->write_func = write_func;
+ attribute->user_data = user_data;
+}
+
+uint16_t gatt_db_add_characteristic(struct gatt_db *db, uint16_t handle,
+ const bt_uuid_t *uuid,
+ uint8_t permissions,
+ uint8_t properties,
+ gatt_db_read_t read_func,
+ gatt_db_write_t write_func,
+ void *user_data)
+{
+ uint8_t value[MAX_CHAR_DECL_VALUE_LEN];
+ struct gatt_db_service *service;
+ uint16_t len = 0;
+ int i;
+
+ service = queue_find(db->services, match_service_by_handle,
+ INT_TO_PTR(handle));
+ if (!service)
+ return 0;
+
+ i = get_attribute_index(service, 1);
+ if (!i)
+ return 0;
+
+ value[0] = properties;
+ len += sizeof(properties);
+ /* We set handle of characteristic value, which will be added next */
+ put_le16(get_handle_at_index(service, i - 1) + 2, &value[1]);
+ len += sizeof(uint16_t);
+ len += uuid_to_le(uuid, &value[3]);
+
+ service->attributes[i] = new_attribute(&characteristic_uuid, value,
+ len);
+ if (!service->attributes[i])
+ return 0;
+
+ update_attribute_handle(service, i++);
+
+ service->attributes[i] = new_attribute(uuid, NULL, 0);
+ if (!service->attributes[i]) {
+ free(service->attributes[i - 1]);
+ return 0;
+ }
+
+ set_attribute_data(service->attributes[i], read_func, write_func,
+ permissions, user_data);
+
+ return update_attribute_handle(service, i);
+}
diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h
index b014b17..ccbafdb 100644
--- a/src/shared/gatt-db.h
+++ b/src/shared/gatt-db.h
uint16_t gatt_db_add_service(struct gatt_db *db, const bt_uuid_t *uuid,
bool primary, uint16_t num_handles);
bool gatt_db_remove_service(struct gatt_db *db, uint16_t handle);
+
+typedef void (*gatt_db_read_t) (uint16_t handle, uint16_t request_id,
+ void *user_data);
+
+typedef void (*gatt_db_write_t) (uint16_t handle, uint16_t request_id,
+ const uint8_t *value, size_t len,
+ void *user_data);
+
+uint16_t gatt_db_add_characteristic(struct gatt_db *db, uint16_t handle,
+ const bt_uuid_t *uuid,
+ uint8_t permissions,
+ uint8_t properties,
+ gatt_db_read_t read_func,
+ gatt_db_write_t write_func,
+ void *user_data);