summaryrefslogtreecommitdiff
path: root/src/technology.c
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2012-02-01 16:43:56 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2012-02-04 01:15:35 +0100
commit204217ff836c16c8056ff540f137f6470a768258 (patch)
treecb3a191f40f330b30c0471fe7b4298b5a5f3c0d7 /src/technology.c
parent1c5a44950001604b346480d3dfc2a6c0596a5146 (diff)
downloadconnman-204217ff836c16c8056ff540f137f6470a768258.tar.gz
connman-204217ff836c16c8056ff540f137f6470a768258.tar.bz2
connman-204217ff836c16c8056ff540f137f6470a768258.zip
technology: Implement Technology Scan and scan start/stop functionality
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.
Diffstat (limited to 'src/technology.c')
-rw-r--r--src/technology.c111
1 files changed, 100 insertions, 11 deletions
diff --git a/src/technology.c b/src/technology.c
index c208b954..12ed5af5 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);