[RFC v0 05/11] device: Replace pending profile list with services

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Mikel Astiz <mikel.astiz@xxxxxxxxxxxx>

Use btd_service pointers to represent the list of services pending for
connection.

This list doesn't reference count the btd_service instances, since the
pending services should be a subset of the available services, and thus
they should already be referenced by device->services. This means
special care must be taken to make sure any removed service is also
removed from the pending list, as addressed in service_remove().
---
 src/device.c | 46 +++++++++++++++++++++++++++-------------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/src/device.c b/src/device.c
index fa498d5..98f37a2 100644
--- a/src/device.c
+++ b/src/device.c
@@ -169,7 +169,7 @@ struct btd_device {
 	GSList		*uuids;
 	GSList		*primaries;		/* List of primary services */
 	GSList		*services;		/* List of btd_service */
-	GSList		*pending;		/* Pending profiles */
+	GSList		*pending;		/* Pending services */
 	GSList		*watches;		/* List of disconnect_data */
 	gboolean	temporary;
 	guint		disconn_timer;
@@ -899,6 +899,7 @@ static void service_remove(struct btd_service *service)
 
 	service_unavailable(service);
 	profile->device_remove(profile, device);
+	device->pending = g_slist_remove(device->pending, service);
 	btd_service_unref(service);
 }
 
@@ -1081,29 +1082,32 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
 
 static int connect_next(struct btd_device *dev)
 {
+	struct btd_service *service;
 	struct btd_profile *profile;
 	int err = -ENOENT;
 
 	while (dev->pending) {
 		int err;
 
-		profile = dev->pending->data;
+		service = dev->pending->data;
+		profile = service_get_profile(service);
+
+		if (service_get_state(service) != SERVICE_STATE_DISCONNECTED) {
+			dev->pending = g_slist_delete_link(dev->pending,
+								dev->pending);
+			continue;
+		}
 
 		err = profile->connect(dev, profile);
 		if (err == 0) {
-			GSList *l;
-
-			l = g_slist_find_custom(dev->services, profile,
-							service_profile_cmp);
-			if (l != NULL)
-				service_connecting(l->data);
-
+			service_connecting(service);
 			return 0;
 		}
 
 		error("Failed to connect %s: %s", profile->name,
 							strerror(-err));
-		dev->pending = g_slist_remove(dev->pending, profile);
+
+		dev->pending = g_slist_delete_link(dev->pending, dev->pending);
 	}
 
 	return err;
@@ -1121,7 +1125,9 @@ void device_profile_connected(struct btd_device *dev,
 		return;
 
 	pending = dev->pending->data;
-	dev->pending = g_slist_remove(dev->pending, profile);
+	l = g_slist_find_custom(dev->pending, profile, service_profile_cmp);
+	if (l != NULL)
+		dev->pending = g_slist_delete_link(dev->pending, l);
 
 	l = g_slist_find_custom(dev->services, profile, service_profile_cmp);
 	if (l != NULL)
@@ -1211,9 +1217,12 @@ static struct btd_service *find_connectable_service(struct btd_device *dev,
 	return NULL;
 }
 
-static gint profile_prio_cmp(gconstpointer a, gconstpointer b)
+static gint service_prio_cmp(gconstpointer a, gconstpointer b)
 {
-	const struct btd_profile *p1 = a, *p2 = b;
+	struct btd_service *s1 = (gpointer) a;
+	struct btd_service *s2 = (gpointer) b;
+	struct btd_profile *p1 = service_get_profile(s1);
+	struct btd_profile *p2 = service_get_profile(s2);
 
 	return p2->priority - p1->priority;
 }
@@ -1246,8 +1255,7 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
 		if (!service)
 			return btd_error_invalid_args(msg);
 
-		p = service_get_profile(service);
-		dev->pending = g_slist_prepend(dev->pending, p);
+		dev->pending = g_slist_prepend(dev->pending, service);
 
 		goto start_connect;
 	}
@@ -1259,14 +1267,14 @@ static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
 		if (!p->auto_connect)
 			continue;
 
-		if (g_slist_find(dev->pending, p))
+		if (g_slist_find(dev->pending, service))
 			continue;
 
 		if (service_get_state(service) != SERVICE_STATE_DISCONNECTED)
 			continue;
 
-		dev->pending = g_slist_insert_sorted(dev->pending, p,
-							profile_prio_cmp);
+		dev->pending = g_slist_insert_sorted(dev->pending, service,
+							service_prio_cmp);
 	}
 
 	if (!dev->pending)
@@ -2434,7 +2442,7 @@ void device_probe_profile(gpointer a, gpointer b)
 	if (!profile->auto_connect || !device->general_connect)
 		return;
 
-	device->pending = g_slist_append(device->pending, profile);
+	device->pending = g_slist_append(device->pending, service);
 
 	if (g_slist_length(device->pending) == 1)
 		connect_next(device);
-- 
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


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux