From 204217ff836c16c8056ff540f137f6470a768258 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 1 Feb 2012 16:43:56 +0200 Subject: [PATCH] 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. --- 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..12ed5af 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); -- 2.7.4