[PATCH BlueZ 09/15] gatt: Add caching support for server

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

This registers both Client Features and Database Hash Characteristics
which are mandatory for the server.
---
 src/gatt-database.c | 103 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 102 insertions(+), 1 deletion(-)

diff --git a/src/gatt-database.c b/src/gatt-database.c
index 2c2f035b1..d72f2c781 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -86,6 +86,8 @@ struct btd_gatt_database {
 	struct queue *ccc_callbacks;
 	struct gatt_db_attribute *svc_chngd;
 	struct gatt_db_attribute *svc_chngd_ccc;
+	struct gatt_db_attribute *cli_feat;
+	struct gatt_db_attribute *db_hash;
 	struct queue *apps;
 	struct queue *profiles;
 };
@@ -177,6 +179,7 @@ struct device_state {
 	bdaddr_t bdaddr;
 	uint8_t bdaddr_type;
 	unsigned int disc_id;
+	uint8_t cli_feat[1];
 	struct queue *ccc_states;
 	struct notify *pending;
 };
@@ -1055,6 +1058,90 @@ service_add_ccc(struct gatt_db_attribute *service,
 	return ccc;
 }
 
+static void cli_feat_read_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct btd_gatt_database *database = user_data;
+	struct device_state *state;
+	uint8_t ecode = 0;
+	const uint8_t *value = NULL;
+	size_t len = 0;
+
+	DBG("Client Features read");
+
+	state = get_device_state(database, att);
+	if (!state) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	len = sizeof(state->cli_feat) - offset;
+	value = len ? &state->cli_feat[offset] : NULL;
+
+done:
+	gatt_db_attribute_read_result(attrib, id, ecode, value, len);
+}
+
+static void cli_feat_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct btd_gatt_database *database = user_data;
+	struct device_state *state;
+	uint8_t ecode = 0;
+
+	DBG("Client Features write");
+
+	state = get_device_state(database, att);
+	if (!state) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	if (!value || !len) {
+		ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto done;
+	}
+
+	/* A client shall never clear a bit it has set.
+	 * TODO: make it generic to any bits.
+	 */
+	if (state->cli_feat[0] & BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING &&
+			!(value[0] & BT_GATT_CHRC_CLI_FEAT_ROBUST_CACHING)) {
+		ecode = BT_ATT_ERROR_VALUE_NOT_ALLOWED;
+		goto done;
+	}
+
+	/* Shall we reallocate the feat array if bigger? */
+	len = MIN(sizeof(state->cli_feat), len);
+	while (len) {
+		state->cli_feat[len - 1] |= value[len -1];
+		len--;
+	}
+
+done:
+	gatt_db_attribute_write_result(attrib, id, ecode);
+}
+
+static void db_hash_read_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct btd_gatt_database *database = user_data;
+	const uint8_t *hash;
+
+	DBG("Database Hash read");
+
+	hash = gatt_db_get_hash(database->db);
+
+	gatt_db_attribute_read_result(attrib, id, 0, hash, 16);
+}
+
 static void populate_gatt_service(struct btd_gatt_database *database)
 {
 	bt_uuid_t uuid;
@@ -1062,7 +1149,7 @@ static void populate_gatt_service(struct btd_gatt_database *database)
 
 	/* Add the GATT service */
 	bt_uuid16_create(&uuid, UUID_GATT);
-	service = gatt_db_add_service(database->db, &uuid, true, 4);
+	service = gatt_db_add_service(database->db, &uuid, true, 8);
 
 	bt_uuid16_create(&uuid, GATT_CHARAC_SERVICE_CHANGED);
 	database->svc_chngd = gatt_db_service_add_characteristic(service, &uuid,
@@ -1072,11 +1159,25 @@ static void populate_gatt_service(struct btd_gatt_database *database)
 	database->svc_chngd_ccc = service_add_ccc(service, database, NULL, NULL,
 									NULL);
 
+	bt_uuid16_create(&uuid, GATT_CHARAC_CLI_FEAT);
+	database->cli_feat = gatt_db_service_add_characteristic(service,
+				&uuid, BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+				BT_GATT_CHRC_PROP_READ |
+				BT_GATT_CHRC_PROP_WRITE,
+				cli_feat_read_cb, cli_feat_write_cb,
+				database);
+
+	bt_uuid16_create(&uuid, GATT_CHARAC_DB_HASH);
+	database->db_hash = gatt_db_service_add_characteristic(service,
+				&uuid, BT_ATT_PERM_READ, BT_GATT_CHRC_PROP_READ,
+				db_hash_read_cb, NULL, database);
+
 	gatt_db_service_set_active(service, true);
 
 	database_add_record(database, service);
 }
 
+
 static void register_core_services(struct btd_gatt_database *database)
 {
 	populate_gap_service(database);
-- 
2.17.2




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux