From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> Wait the bt_gatt_client becomes ready (has performed service discovery) before attempting to connect EATT when acting as peripheral/acceptor since the central/initiator might actually attempt to connect EATT channels in the same way which can potentially cause a collisions. --- src/device.c | 7 +++++ src/gatt-client.c | 74 +++++++++++++++++++++++------------------------ src/gatt-client.h | 1 + 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/device.c b/src/device.c index 998485be7..6253edc77 100644 --- a/src/device.c +++ b/src/device.c @@ -5304,6 +5304,13 @@ static void gatt_client_init(struct btd_device *device) } btd_gatt_client_connected(device->client_dbus); + + /* Only initiate EATT connection when acting as initiator, as acceptor + * it shall be triggered only when ready to avoid possible clashes where + * both sides attempt to connection at same time. + */ + if (device->connect) + bt_gatt_client_eatt_connect(device->client_dbus); } static void gatt_server_init(struct btd_device *device, diff --git a/src/gatt-client.c b/src/gatt-client.c index bec6e1ec0..6cf96365d 100644 --- a/src/gatt-client.c +++ b/src/gatt-client.c @@ -2156,6 +2156,38 @@ static void register_notify(void *data, void *user_data) notify_client_free(notify_client); } +void btd_gatt_client_ready(struct btd_gatt_client *client) +{ + if (!client) + return; + + if (!client->gatt) { + struct bt_gatt_client *gatt; + + gatt = btd_device_get_gatt_client(client->device); + client->gatt = bt_gatt_client_clone(gatt); + if (!client->gatt) { + error("GATT client not initialized"); + return; + } + } + + client->ready = true; + + DBG("GATT client ready"); + + create_services(client); + + DBG("Features 0x%02x", client->features); + + if (!client->features) { + client->features = bt_gatt_client_get_features(client->gatt); + DBG("Update Features 0x%02x", client->features); + if (client->features & BT_GATT_CHRC_CLI_FEAT_EATT) + bt_gatt_client_eatt_connect(client); + } +} + static void eatt_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data) { struct btd_gatt_client *client = user_data; @@ -2166,7 +2198,7 @@ static void eatt_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data) device_attach_att(client->device, io); } -static void eatt_connect(struct btd_gatt_client *client) +void bt_gatt_client_eatt_connect(struct btd_gatt_client *client) { struct bt_att *att = bt_gatt_client_get_att(client->gatt); struct btd_device *dev = client->device; @@ -2176,6 +2208,9 @@ static void eatt_connect(struct btd_gatt_client *client) char addr[18]; int i; + if (!(client->features & BT_GATT_CHRC_CLI_FEAT_EATT)) + return; + if (bt_att_get_channels(att) == btd_opts.gatt_channels) return; @@ -2232,38 +2267,6 @@ static void eatt_connect(struct btd_gatt_client *client) } } -void btd_gatt_client_ready(struct btd_gatt_client *client) -{ - if (!client) - return; - - if (!client->gatt) { - struct bt_gatt_client *gatt; - - gatt = btd_device_get_gatt_client(client->device); - client->gatt = bt_gatt_client_clone(gatt); - if (!client->gatt) { - error("GATT client not initialized"); - return; - } - } - - client->ready = true; - - DBG("GATT client ready"); - - create_services(client); - - DBG("Features 0x%02x", client->features); - - if (!client->features) { - client->features = bt_gatt_client_get_features(client->gatt); - DBG("Update Features 0x%02x", client->features); - if (client->features & BT_GATT_CHRC_CLI_FEAT_EATT) - eatt_connect(client); - } -} - void btd_gatt_client_connected(struct btd_gatt_client *client) { struct bt_gatt_client *gatt; @@ -2284,11 +2287,6 @@ void btd_gatt_client_connected(struct btd_gatt_client *client) * for any pre-registered notification sessions. */ queue_foreach(client->all_notify_clients, register_notify, client); - - if (!(client->features & BT_GATT_CHRC_CLI_FEAT_EATT)) - return; - - eatt_connect(client); } void btd_gatt_client_service_added(struct btd_gatt_client *client, diff --git a/src/gatt-client.h b/src/gatt-client.h index b6539207e..672c5e72f 100644 --- a/src/gatt-client.h +++ b/src/gatt-client.h @@ -20,6 +20,7 @@ void btd_gatt_client_service_added(struct btd_gatt_client *client, void btd_gatt_client_service_removed(struct btd_gatt_client *client, struct gatt_db_attribute *attrib); void btd_gatt_client_disconnected(struct btd_gatt_client *client); +void bt_gatt_client_eatt_connect(struct btd_gatt_client *client); typedef void (*btd_gatt_client_service_path_t)(const char *service_path, void *user_data); -- 2.31.1