Diff between 7e9816dd8c219f26f52fcb46fa13ecddfcf2d526 and cbe4144dea6fde87e13016c2861c9ba5f75f716f

Changed Files

File Additions Deletions Status
src/device.c +21 -0 modified
src/device.h +1 -0 modified
src/set.c +20 -2 modified
src/shared/gatt-db.c +2 -2 modified

Full Patch

diff --git a/src/device.c b/src/device.c
index 620bbd5..5dc1cd0 100644
--- a/src/device.c
+++ b/src/device.c
@@ -6994,6 +6994,27 @@ struct gatt_db *btd_device_get_gatt_db(struct btd_device *device)
 	return device->db;
 }
 
+bool btd_device_set_gatt_db(struct btd_device *device, struct gatt_db *db)
+{
+	struct gatt_db *clone;
+
+	if (!device)
+		return false;
+
+	clone = gatt_db_clone(db);
+	if (clone)
+		return false;
+
+	gatt_db_unregister(device->db, device->db_id);
+	gatt_db_unref(device->db);
+
+	device->db = clone;
+	device->db_id = gatt_db_register(device->db, gatt_service_added,
+					gatt_service_removed, device, NULL);
+
+	return true;
+}
+
 struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device)
 {
 	if (!device)
diff --git a/src/device.h b/src/device.h
index a2b7bb1..0794f92 100644
--- a/src/device.h
+++ b/src/device.h
@@ -66,6 +66,7 @@ struct gatt_primary *btd_device_get_primary(struct btd_device *device,
 							const char *uuid);
 GSList *btd_device_get_primaries(struct btd_device *device);
 struct gatt_db *btd_device_get_gatt_db(struct btd_device *device);
+bool btd_device_set_gatt_db(struct btd_device *device, struct gatt_db *db);
 struct bt_gatt_client *btd_device_get_gatt_client(struct btd_device *device);
 struct bt_gatt_server *btd_device_get_gatt_server(struct btd_device *device);
 bool btd_device_is_initiator(struct btd_device *device);
diff --git a/src/set.c b/src/set.c
index bf35ee4..4ca2f78 100644
--- a/src/set.c
+++ b/src/set.c
@@ -28,6 +28,8 @@
 #include "src/shared/queue.h"
 #include "src/shared/ad.h"
 #include "src/shared/crypto.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
 
 #include "log.h"
 #include "error.h"
@@ -277,8 +279,24 @@ static void foreach_rsi(void *data, void *user_data)
 
 	bt_crypto_unref(crypto);
 
-	if (!memcmp(ad->data, res, sizeof(res)))
-		device_connect_le(set->device);
+	if (memcmp(ad->data, res, sizeof(res)))
+		return;
+
+	/* Attempt to use existing gatt_db from set if device has never been
+	 * connected before.
+	 *
+	 * If dbs don't really match bt_gatt_client will attempt to rediscover
+	 * the ranges that don't match.
+	 */
+	if (gatt_db_isempty(btd_device_get_gatt_db(set->device))) {
+		struct btd_device *device;
+
+		device = queue_get_entries(set->devices)->data;
+		btd_device_set_gatt_db(set->device,
+					btd_device_get_gatt_db(device));
+	}
+
+	device_connect_le(set->device);
 }
 
 static void foreach_device(struct btd_device *device, void *data)
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index d8d2139..16abcba 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -278,8 +278,8 @@ static void service_clone(void *data, void *user_data)
 	for (i = 0; i < service->num_handles; i++) {
 		struct gatt_db_attribute *attr = service->attributes[i];
 
-		/* Only clone values for characteristics since that is
-		 * cacheable.
+		/* Only clone values for characteristics declaration since that
+		 * is considered when calculating the db hash.
 		 */
 		if (bt_uuid_len(&attr->uuid) == 2 &&
 				attr->uuid.value.u16 == GATT_CHARAC_UUID)