@@ -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)
@@ -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);
@@ -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)
@@ -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)
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Most sets should be clone of each other, or at least very similar, so this attempts to clone the existing gatt-db of the first member found when connecting new sets, this substantially speed up the process of bonding sets if their database matches which is something that is currently ranging from 20-30 seconds depending on the manufacturer and with this changes it cuts 5-10 seconds by bypassing discovery all procedure of other members. If the dbs don't really match bt_gatt_client instance will attempt to rediscover the ranges that don't match. --- src/device.c | 21 +++++++++++++++++++++ src/device.h | 1 + src/set.c | 22 ++++++++++++++++++++-- src/shared/gatt-db.c | 4 ++-- 4 files changed, 44 insertions(+), 4 deletions(-)