From: Mikel Astiz <mikel.astiz@xxxxxxxxxxxx> The service state can provide enough information not to maintain such a connected_profiles list. Therefore, avoid duplicated information and remove the list. --- src/device.c | 88 +++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/src/device.c b/src/device.c index fd65cb6..0d73ce2 100644 --- a/src/device.c +++ b/src/device.c @@ -186,7 +186,6 @@ struct btd_device { guint attachid; /* Attrib server attach */ gboolean connected; - GSList *connected_profiles; sdp_list_t *tmp_records; @@ -229,6 +228,21 @@ static gint service_profile_cmp(gconstpointer a, gconstpointer b) return 1; } +static GSList *find_service_with_state(GSList *list, + btd_service_state_t state) +{ + GSList *l; + + for (l = list; l != NULL; l = g_slist_next(l)) { + struct btd_service *service = l->data; + + if (btd_service_get_state(service) == state) + return l; + } + + return NULL; +} + static gboolean store_device_info_cb(gpointer user_data) { struct btd_device *device = user_data; @@ -984,15 +998,26 @@ static void bonding_request_cancel(struct bonding_req *bonding) adapter_cancel_bonding(adapter, &device->bdaddr, device->bdaddr_type); } -static void dev_disconn_profile(gpointer a, gpointer b) +static void dev_disconn_service(gpointer a, gpointer b) { - struct btd_profile *profile = a; - struct btd_device *dev = b; + struct btd_service *service = a; + struct btd_profile *profile = btd_service_get_profile(service); + struct btd_device *dev = btd_service_get_device(service); + btd_service_state_t state = btd_service_get_state(service); + int err; if (!profile->disconnect) return; - profile->disconnect(dev, profile); + if (state != BTD_SERVICE_STATE_CONNECTING && + state != BTD_SERVICE_STATE_CONNECTED) + return; + + btd_service_disconnecting(service); + + err = profile->disconnect(dev, profile); + if (err != 0) + btd_service_disconnecting_complete(service, err); } void device_request_disconnect(struct btd_device *device, DBusMessage *msg) @@ -1018,10 +1043,7 @@ void device_request_disconnect(struct btd_device *device, DBusMessage *msg) if (device->disconn_timer) return; - g_slist_foreach(device->connected_profiles, dev_disconn_profile, - device); - g_slist_free(device->connected_profiles); - device->connected_profiles = NULL; + g_slist_foreach(device->services, dev_disconn_service, NULL); g_slist_free(device->pending); device->pending = NULL; @@ -1073,13 +1095,20 @@ static int connect_next(struct btd_device *dev) while (dev->pending) { int err; + GSList *l; profile = dev->pending->data; + l = g_slist_find_custom(dev->services, profile, + service_profile_cmp); + btd_service_connecting(l->data); + err = profile->connect(dev, profile); if (err == 0) return 0; + btd_service_connecting_complete(l->data, err); + error("Failed to connect %s: %s", profile->name, strerror(-err)); dev->pending = g_slist_remove(dev->pending, profile); @@ -1092,6 +1121,7 @@ void device_profile_connected(struct btd_device *dev, struct btd_profile *profile, int err) { struct btd_profile *pending; + GSList *l; DBG("%s %s (%d)", profile->name, strerror(-err), -err); @@ -1101,10 +1131,9 @@ void device_profile_connected(struct btd_device *dev, pending = dev->pending->data; dev->pending = g_slist_remove(dev->pending, profile); - if (!err) - dev->connected_profiles = - g_slist_append(dev->connected_profiles, - profile); + l = g_slist_find_custom(dev->services, profile, service_profile_cmp); + if (l != NULL) + btd_service_connecting_complete(l->data, err); /* Only continue connecting the next profile if it matches the first * pending, otherwise it will trigger another connect to the same @@ -1125,7 +1154,9 @@ void device_profile_connected(struct btd_device *dev, DBG("returning response to %s", dbus_message_get_sender(dev->connect)); - if (err && dev->connected_profiles == NULL) + l = find_service_with_state(dev->services, BTD_SERVICE_STATE_CONNECTED); + + if (err && l == NULL) g_dbus_send_message(dbus_conn, btd_error_failed(dev->connect, strerror(-err))); else @@ -1236,7 +1267,8 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg, if (g_slist_find(dev->pending, p)) continue; - if (g_slist_find(dev->connected_profiles, p)) + if (btd_service_get_state(service) != + BTD_SERVICE_STATE_DISCONNECTED) continue; dev->pending = g_slist_insert_sorted(dev->pending, p, @@ -1305,8 +1337,11 @@ static DBusMessage *connect_profile(DBusConnection *conn, DBusMessage *msg, void device_profile_disconnected(struct btd_device *dev, struct btd_profile *profile, int err) { - dev->connected_profiles = g_slist_remove(dev->connected_profiles, - profile); + GSList *l; + + l = g_slist_find_custom(dev->services, profile, service_profile_cmp); + if (l != NULL) + btd_service_disconnecting_complete(l->data, err); if (!dev->disconnect) return; @@ -1327,10 +1362,12 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct btd_device *dev = user_data; + struct btd_service *service; struct btd_profile *p; const char *pattern; char *uuid; int err; + GSList *l; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) @@ -1346,12 +1383,19 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg, if (!p) return btd_error_invalid_args(msg); + l = g_slist_find_custom(dev->services, p, service_profile_cmp); + service = l->data; + if (!p->disconnect) return btd_error_not_supported(msg); + btd_service_disconnecting(service); + err = p->disconnect(dev, p); - if (err < 0) + if (err < 0) { + btd_service_disconnecting_complete(service, err); return btd_error_failed(msg, strerror(-err)); + } dev->disconnect = dbus_message_ref(msg); @@ -2242,10 +2286,7 @@ void device_remove(struct btd_device *device, gboolean remove_stored) if (device->browse) browse_request_cancel(device->browse); - g_slist_foreach(device->connected_profiles, dev_disconn_profile, - device); - g_slist_free(device->connected_profiles); - device->connected_profiles = NULL; + g_slist_foreach(device->services, dev_disconn_service, NULL); g_slist_free(device->pending); device->pending = NULL; @@ -2420,9 +2461,6 @@ void device_remove_profile(gpointer a, gpointer b) if (l == NULL) return; - device->connected_profiles = g_slist_remove(device->connected_profiles, - profile); - service = l->data; device->services = g_slist_delete_link(device->services, l); service_remove(service); -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html