[PATCH v2 4/6] technology: Implement Technology Scan and scan start/stop functionality

patrik.flykt at linux.intel.com patrik.flykt at linux.intel.com
Wed Feb 1 06:43:56 PST 2012


From: Patrik Flykt <patrik.flykt at linux.intel.com>

When Technology Scan D-Bus method call is called, add caller to a scan
list and start a scan for the service type. When a device reports scan
completed, check whether it was the last device scanning and reply to
the callers accordingly.

Also check for scanning status when removing devices and technology
objects.
---
v2: move check for scanning devices here from device.c

 src/connman.h    |    2 +
 src/technology.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 102 insertions(+), 11 deletions(-)

diff --git a/src/connman.h b/src/connman.h
index db58316..d6ce040 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -393,6 +393,8 @@ int __connman_technology_update_rfkill(unsigned int index,
 int __connman_technology_remove_rfkill(unsigned int index,
 					enum connman_service_type type);
 
+void __connman_technology_scan_started(struct connman_device *device);
+void __connman_technology_scan_stopped(struct connman_device *device);
 void __connman_technology_add_interface(enum connman_service_type type,
 				int index, const char *name, const char *ident);
 void __connman_technology_remove_interface(enum connman_service_type type,
diff --git a/src/technology.c b/src/technology.c
index c208b95..d244b27 100644
--- a/src/technology.c
+++ b/src/technology.c
@@ -70,6 +70,8 @@ struct connman_technology {
 
 	DBusMessage *pending_reply;
 	guint pending_timeout;
+
+	GSList *scan_pending;
 };
 
 static GSList *driver_list = NULL;
@@ -744,17 +746,6 @@ static DBusMessage *set_property(DBusConnection *conn,
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static GDBusMethodTable technology_methods[] = {
-	{ "GetProperties", "",   "a{sv}", get_properties },
-	{ "SetProperty",   "sv", "",      set_property   },
-	{ },
-};
-
-static GDBusSignalTable technology_signals[] = {
-	{ "PropertyChanged", "sv" },
-	{ },
-};
-
 static struct connman_technology *technology_find(enum connman_service_type type)
 {
 	GSList *list;
@@ -771,6 +762,99 @@ static struct connman_technology *technology_find(enum connman_service_type type
 	return NULL;
 }
 
+static void reply_scan_pending(struct connman_technology *technology, int err)
+{
+	DBusMessage *reply;
+
+	DBG("technology %p err %d", technology, err);
+
+	while (technology->scan_pending != NULL) {
+		DBusMessage *msg = technology->scan_pending->data;
+
+		DBG("reply to %s", dbus_message_get_sender(msg));
+
+		if (err == 0)
+			reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+		else
+			reply = __connman_error_failed(msg, -err);
+		g_dbus_send_message(connection, reply);
+		dbus_message_unref(msg);
+
+		technology->scan_pending =
+			g_slist_delete_link(technology->scan_pending,
+					technology->scan_pending);
+	}
+}
+
+void __connman_technology_scan_started(struct connman_device *device)
+{
+	DBG("device %p", device);
+}
+
+void __connman_technology_scan_stopped(struct connman_device *device)
+{
+	int count = 0;
+	struct connman_technology *technology;
+	enum connman_service_type type;
+	GSList *list;
+	
+	type = __connman_device_get_service_type(device);
+	technology = technology_find(type);
+
+	DBG("technology %p device %p", technology, device);
+
+	if (technology == NULL)
+		return;
+
+	for (list = technology->device_list; list != NULL; list = list->next) {
+		struct connman_device *other_device = list->data;
+
+		if (device == other_device)
+			continue;
+
+		if (__connman_device_get_service_type(other_device) != type)
+			continue;
+
+		if (__connman_device_scanning(other_device))
+			count += 1;
+	}
+
+	if (count == 0)
+		reply_scan_pending(technology, 0);
+}
+
+static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+	struct connman_technology *technology = data;
+	int err;
+
+	DBG ("technology %p request from %s", technology,
+			dbus_message_get_sender(msg));
+
+	dbus_message_ref(msg);
+	technology->scan_pending =
+		g_slist_prepend(technology->scan_pending, msg);
+
+	err = __connman_device_request_scan(technology->type);
+	if (err < 0)
+		reply_scan_pending(technology, err);
+
+	return NULL;
+}
+
+static GDBusMethodTable technology_methods[] = {
+	{ "GetProperties", "",   "a{sv}", get_properties },
+	{ "SetProperty",   "sv", "",      set_property   },
+	{ "Scan",          "",    "",     scan,
+						G_DBUS_METHOD_FLAG_ASYNC },
+	{ },
+};
+
+static GDBusSignalTable technology_signals[] = {
+	{ "PropertyChanged", "sv" },
+	{ },
+};
+
 static struct connman_technology *technology_get(enum connman_service_type type)
 {
 	struct connman_technology *technology;
@@ -853,6 +937,8 @@ static void technology_put(struct connman_technology *technology)
 	if (__sync_fetch_and_sub(&technology->refcount, 1) > 0)
 		return;
 
+	reply_scan_pending(technology, -EINTR);
+
 	if (technology->driver) {
 		technology->driver->remove(technology);
 		technology->driver = NULL;
@@ -986,6 +1072,9 @@ int __connman_technology_remove_device(struct connman_device *device)
 		return -ENXIO;
 	}
 
+	if (__connman_device_scanning(device))
+		__connman_technology_scan_stopped(device);
+
 	technology->device_list = g_slist_remove(technology->device_list,
 								device);
 	technology_put(technology);
-- 
1.7.2.5




More information about the connman mailing list