diff --git a/src/device.c b/src/device.c
index ce96ab5..3ef0340 100644
--- a/src/device.c
+++ b/src/device.c
bt_gatt_client_set_ready_handler(device->client, NULL, NULL, NULL);
bt_gatt_client_unref(device->client);
device->client = NULL;
-
- /*
- * TODO: Once GATT over BR/EDR is properly supported, we should check
- * the bonding state for the correct bearer based on the transport over
- * which GATT is being done.
- */
- if (device->le_state.bonded)
- return;
-
- gatt_db_clear(device->db);
- device->gatt_cache_used = false;
}
static void gatt_server_cleanup(struct btd_device *device)
return;
}
+ /* Mark service as active to skip discovering it again */
+ gatt_db_service_set_active(data->cur_attr, true);
+
/* Mark service as claimed */
gatt_db_service_set_claimed(data->cur_attr, true);
/* Don't probe the profiles if a matching service already exists. */
if (find_service_with_uuid(data->dev->services, data->cur_uuid)) {
+ /* Mark service as active to skip discovering it again */
+ gatt_db_service_set_active(data->cur_attr, true);
/* Mark the service as claimed by the existing profile. */
gatt_db_service_set_claimed(data->cur_attr, true);
return;
device_svc_resolved(device, device->bdaddr_type, 0);
}
+static void gatt_client_init(struct btd_device *device);
+
static void gatt_client_ready_cb(bool success, uint8_t att_ecode,
void *user_data)
{
diff --git a/src/gatt-client.c b/src/gatt-client.c
index 162bcac..3356ee4 100644
--- a/src/gatt-client.c
+++ b/src/gatt-client.c
DBG("Exported GATT service: %s", service->path);
+ /* Set service active so we can skip discovering next time */
+ gatt_db_service_set_active(attr, true);
+
return service;
}
DBG("Device disconnected. Cleaning up.");
/*
- * Remove all services. We'll recreate them when a new bt_gatt_client
- * becomes ready. Leave the services around if the device is bonded.
* TODO: Once GATT over BR/EDR is properly supported, we should pass the
* correct bdaddr_type based on the transport over which GATT is being
* done.
*/
- if (!device_is_bonded(client->device, BDADDR_LE_PUBLIC)) {
- DBG("Device not bonded. Removing exported services.");
- queue_remove_all(client->services, NULL, NULL,
- unregister_service);
- } else {
- DBG("Device is bonded. Keeping exported services up.");
- queue_foreach(client->all_notify_clients, clear_notify_id,
- NULL);
- queue_foreach(client->services, cancel_ops, client->gatt);
- }
+ queue_foreach(client->all_notify_clients, clear_notify_id, NULL);
+ queue_foreach(client->services, cancel_ops, client->gatt);
bt_gatt_client_unref(client->gatt);
client->gatt = NULL;
diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 7bc3b71..feb30f6 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
attr = gatt_db_insert_service(client->db, start, &uuid, false,
end - start + 1);
if (!attr) {
- util_debug(client->debug_callback, client->debug_data,
- "Failed to create service");
- success = false;
- goto done;
+ gatt_db_clear_range(client->db, start, end);
+ attr = gatt_db_insert_service(client->db, start, &uuid,
+ false, end - start + 1);
+ if (!attr) {
+ util_debug(client->debug_callback,
+ client->debug_data,
+ "Failed to store service");
+ success = false;
+ goto done;
+ }
}
- queue_push_tail(op->pending_svcs, attr);
+ /* Skip if service already active */
+ if (!gatt_db_service_get_active(attr))
+ queue_push_tail(op->pending_svcs, attr);
}
next:
attr = queue_pop_head(op->pending_svcs);
/* Complete with success if queue is empty */
- if (!attr)
+ if (!attr) {
+ success = true;
goto done;
+ }
/*
* Store the service in the tmp queue to be reused during
attr = gatt_db_insert_service(client->db, start, &uuid, true,
end - start + 1);
if (!attr) {
- util_debug(client->debug_callback, client->debug_data,
+ gatt_db_clear_range(client->db, start, end);
+ attr = gatt_db_insert_service(client->db, start, &uuid,
+ true, end - start + 1);
+ if (!attr) {
+ util_debug(client->debug_callback,
+ client->debug_data,
"Failed to store service");
- success = false;
- goto done;
+ success = false;
+ goto done;
+ }
}
- queue_push_tail(op->pending_svcs, attr);
+ /* Skip if service already active */
+ if (!gatt_db_service_get_active(attr))
+ queue_push_tail(op->pending_svcs, attr);
}
secondary:
"MTU exchange complete, with MTU: %u",
bt_att_get_mtu(client->att));
- /* Don't do discovery if the database was pre-populated */
- if (!gatt_db_isempty(client->db)) {
- op->complete_func(op, true, 0);
- return;
- }
-
client->discovery_req = bt_gatt_discover_all_primary_services(
client->att, NULL,
discover_primary_cb,
diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 2b2090c..5e1537e 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
return true;
}
-static bool find_insert_loc(struct gatt_db *db, uint16_t start, uint16_t end,
+static struct gatt_db_service *find_insert_loc(struct gatt_db *db,
+ uint16_t start, uint16_t end,
struct gatt_db_service **after)
{
const struct queue_entry *services_entry;
gatt_db_service_get_handles(service, &cur_start, &cur_end);
if (start >= cur_start && start <= cur_end)
- return false;
+ return service;
if (end >= cur_start && end <= cur_end)
- return false;
+ return service;
if (end < cur_start)
- return true;
+ return NULL;
*after = service;
services_entry = services_entry->next;
}
- return true;
+ return NULL;
}
struct gatt_db_attribute *gatt_db_insert_service(struct gatt_db *db,
if (num_handles < 1 || (handle + num_handles - 1) > UINT16_MAX)
return NULL;
- if (!find_insert_loc(db, handle, handle + num_handles - 1, &after))
+ service = find_insert_loc(db, handle, handle + num_handles - 1, &after);
+ if (service) {
+ const bt_uuid_t *type;
+ bt_uuid_t value;
+
+ if (primary)
+ type = &primary_service_uuid;
+ else
+ type = &secondary_service_uuid;
+
+ gatt_db_attribute_get_service_uuid(service->attributes[0],
+ &value);
+
+ /* Check if service match */
+ if (!bt_uuid_cmp(&service->attributes[0]->uuid, type) &&
+ !bt_uuid_cmp(&value, uuid) &&
+ service->num_handles == num_handles &&
+ service->attributes[0]->handle == handle)
+ return service->attributes[0];
+
return NULL;
+ }
service = gatt_db_service_create(uuid, handle, primary, num_handles);