Add support for technology interface
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 25 Jan 2010 06:14:11 +0000 (07:14 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 25 Jan 2010 06:14:11 +0000 (07:14 +0100)
12 files changed:
Makefile.am
doc/manager-api.txt
doc/technology-api.txt [new file with mode: 0644]
include/dbus.h
src/connman.h
src/device.c
src/manager.c
src/technology.c
test/list-devices
test/monitor-manager
test/monitor-services
test/test-manager

index ce348ed..15b41a6 100644 (file)
@@ -153,7 +153,7 @@ EXTRA_DIST += doc/overview-api.txt doc/behavior-api.txt \
                                doc/ipconfig-api.txt doc/plugin-api.txt \
                                doc/manager-api.txt doc/agent-api.txt \
                                doc/profile-api.txt doc/service-api.txt \
-                               doc/counter-api.txt \
+                               doc/technology-api.txt doc/counter-api.txt \
                                doc/device-lowlevel-api.txt \
                                doc/network-lowlevel-api.txt \
                                doc/advanced-configuration.txt
index 1ba0480..c898935 100644 (file)
@@ -187,9 +187,9 @@ Properties  string State [readonly]
 
                        List of profile object paths.
 
-               array{object} Devices [readonly]
+               array{object} Technologies [readonly]
 
-                       List of device object paths.
+                       List of technology object paths.
 
                array{object} Services [readonly]
 
diff --git a/doc/technology-api.txt b/doc/technology-api.txt
new file mode 100644 (file)
index 0000000..9b10c58
--- /dev/null
@@ -0,0 +1,34 @@
+Technology hierarchy
+====================
+
+Service                org.moblin.connman
+Interface      org.moblin.connman.Technology
+Object path    [variable prefix]/{technology0,technology1,...}
+
+Methods                dict GetProperties()
+
+                       Returns properties for the technology object. See
+                       the properties section for available properties.
+
+                       Possible Errors: [service].Error.InvalidArguments
+
+Signals                PropertyChanged(string name, variant value)
+
+                       This signal indicates a changed value of the given
+                       property.
+
+Properties     string Name [readonly]
+
+                       Name of this technology.
+
+               string Type [readonly]
+
+                       The technology type (for example "ethernet" etc.)
+
+                       This information should only be used to determine
+                       advanced properties or showing the correct icon
+                       to the user.
+
+               array{object} Devices [readonly]
+
+                       List of device objects.
index 36629df..2ff41b2 100644 (file)
@@ -29,6 +29,7 @@ extern "C" {
 #endif
 
 #define CONNMAN_SERVICE                        "org.moblin.connman"
+#define CONNMAN_PATH                   "/org/moblin/connman"
 
 #define CONNMAN_DEBUG_INTERFACE                CONNMAN_SERVICE ".Debug"
 #define CONNMAN_ERROR_INTERFACE                CONNMAN_SERVICE ".Error"
@@ -44,6 +45,7 @@ extern "C" {
 #define CONNMAN_DEVICE_INTERFACE       CONNMAN_SERVICE ".Device"
 #define CONNMAN_NETWORK_INTERFACE      CONNMAN_SERVICE ".Network"
 #define CONNMAN_PROVIDER_INTERFACE     CONNMAN_SERVICE ".Provider"
+#define CONNMAN_TECHNOLOGY_INTERFACE   CONNMAN_SERVICE ".Technology"
 
 typedef void (* connman_dbus_append_cb_t) (DBusMessageIter *iter,
                                                        void *user_data);
index a704027..d399634 100644 (file)
@@ -269,6 +269,11 @@ connman_bool_t __connman_udev_get_blocked(int phyindex);
 
 #include <connman/device.h>
 
+void __connman_technology_list(DBusMessageIter *iter, void *user_data);
+
+int __connman_technology_add_device(struct connman_device *device);
+int __connman_technology_remove_device(struct connman_device *device);
+
 int __connman_device_init(void);
 void __connman_device_cleanup(void);
 
@@ -282,7 +287,6 @@ void __connman_device_set_phyindex(struct connman_device *device,
 int __connman_device_set_blocked(struct connman_device *device,
                                                connman_bool_t blocked);
 
-
 void __connman_device_increase_connections(struct connman_device *device);
 void __connman_device_decrease_connections(struct connman_device *device);
 
index 875b197..c78e421 100644 (file)
@@ -478,13 +478,6 @@ static GDBusSignalTable device_signals[] = {
        { },
 };
 
-static void emit_devices_signal(void)
-{
-       connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH,
-                       CONNMAN_MANAGER_INTERFACE, "Devices",
-                       DBUS_TYPE_OBJECT_PATH, __connman_device_list, NULL);
-}
-
 static int register_interface(struct connman_element *element)
 {
        struct connman_device *device = element->device;
@@ -501,8 +494,6 @@ static int register_interface(struct connman_element *element)
 
        device->registered = TRUE;
 
-       emit_devices_signal();
-
        return 0;
 }
 
@@ -514,8 +505,6 @@ static void unregister_interface(struct connman_element *element)
 
        device->registered = FALSE;
 
-       emit_devices_signal();
-
        g_dbus_unregister_interface(connection, element->path,
                                                CONNMAN_DEVICE_INTERFACE);
 }
@@ -535,6 +524,8 @@ static int setup_device(struct connman_device *device)
                return err;
        }
 
+       __connman_technology_add_device(device);
+
        type = __connman_device_get_service_type(device);
        __connman_notifier_register(type);
 
@@ -596,6 +587,8 @@ static void remove_device(struct connman_device *device)
        type = __connman_device_get_service_type(device);
        __connman_notifier_unregister(type);
 
+       __connman_technology_remove_device(device);
+
        unregister_interface(&device->element);
 
        if (device->driver->remove)
index 7b2f996..141e959 100644 (file)
@@ -60,9 +60,8 @@ static DBusMessage *get_properties(DBusConnection *conn,
                        DBUS_TYPE_OBJECT_PATH, __connman_service_list, NULL);
        connman_dbus_dict_append_array(&dict, "Providers",
                        DBUS_TYPE_OBJECT_PATH, __connman_provider_list, NULL);
-
-       connman_dbus_dict_append_array(&dict, "Devices",
-                       DBUS_TYPE_OBJECT_PATH, __connman_device_list, NULL);
+       connman_dbus_dict_append_array(&dict, "Technologies",
+                       DBUS_TYPE_OBJECT_PATH, __connman_technology_list, NULL);
 
        str = __connman_notifier_get_state();
        connman_dbus_dict_append_basic(&dict, "State",
index 6c46074..33fbc75 100644 (file)
 #include <config.h>
 #endif
 
+#include <gdbus.h>
+
 #include "connman.h"
 
+static DBusConnection *connection;
+
+static GHashTable *device_table;
+static GSList *technology_list = NULL;
+
+struct connman_technology {
+       gint refcount;
+       enum connman_service_type type;
+       char *path;
+       GSList *device_list;
+};
+
+void __connman_technology_list(DBusMessageIter *iter, void *user_data)
+{
+       GSList *list;
+
+       for (list = technology_list; list; list = list->next) {
+               struct connman_technology *technology = list->data;
+
+               if (technology->path == NULL)
+                       continue;
+
+               dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+                                                       &technology->path);
+       }
+}
+
+static void technologies_changed(void)
+{
+       connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH,
+                       CONNMAN_MANAGER_INTERFACE, "Technologies",
+                       DBUS_TYPE_OBJECT_PATH, __connman_technology_list, NULL);
+}
+
+static void device_list(DBusMessageIter *iter, void *user_data)
+{
+       struct connman_technology *technology = user_data;
+       GSList *list;
+
+       for (list = technology->device_list; list; list = list->next) {
+               struct connman_device *device = list->data;
+               const char *path;
+
+               path = connman_device_get_path(device);
+               if (path == NULL)
+                       continue;
+
+               dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+                                                                       &path);
+       }
+}
+
+static void devices_changed(struct connman_technology *technology)
+{
+       connman_dbus_property_changed_array(technology->path,
+                       CONNMAN_TECHNOLOGY_INTERFACE, "Devices",
+                       DBUS_TYPE_OBJECT_PATH, device_list, technology);
+}
+
+static const char *get_name(enum connman_service_type type)
+{
+       switch (type) {
+       case CONNMAN_SERVICE_TYPE_UNKNOWN:
+       case CONNMAN_SERVICE_TYPE_SYSTEM:
+       case CONNMAN_SERVICE_TYPE_GPS:
+       case CONNMAN_SERVICE_TYPE_VPN:
+               break;
+       case CONNMAN_SERVICE_TYPE_ETHERNET:
+               return "Wired";
+       case CONNMAN_SERVICE_TYPE_WIFI:
+               return "WiFi";
+       case CONNMAN_SERVICE_TYPE_WIMAX:
+               return "WiMAX";
+       case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+               return "Bluetooth";
+       case CONNMAN_SERVICE_TYPE_CELLULAR:
+               return "3G";
+       }
+
+       return NULL;
+}
+
+static DBusMessage *get_properties(DBusConnection *conn,
+                                       DBusMessage *message, void *user_data)
+{
+       struct connman_technology *technology = user_data;
+       DBusMessage *reply;
+       DBusMessageIter array, dict;
+       const char *str;
+
+       reply = dbus_message_new_method_return(message);
+       if (reply == NULL)
+               return NULL;
+
+       dbus_message_iter_init_append(reply, &array);
+
+       connman_dbus_dict_open(&array, &dict);
+
+       str = get_name(technology->type);
+       if (str != NULL)
+               connman_dbus_dict_append_basic(&dict, "Name",
+                                               DBUS_TYPE_STRING, &str);
+
+       str = __connman_service_type2string(technology->type);
+       if (str != NULL)
+               connman_dbus_dict_append_basic(&dict, "Type",
+                                               DBUS_TYPE_STRING, &str);
+
+       connman_dbus_dict_append_array(&dict, "Devices",
+                       DBUS_TYPE_OBJECT_PATH, device_list, technology);
+
+       connman_dbus_dict_close(&array, &dict);
+
+       return reply;
+}
+
+static GDBusMethodTable technology_methods[] = {
+       { "GetProperties", "", "a{sv}", get_properties },
+       { },
+};
+
+static GDBusSignalTable technology_signals[] = {
+       { "PropertyChanged", "sv" },
+       { },
+};
+
+static struct connman_technology *technology_find(enum connman_service_type type)
+{
+       GSList *list;
+
+       DBG("type %d", type);
+
+       for (list = technology_list; list; list = list->next) {
+               struct connman_technology *technology = list->data;
+
+               if (technology->type == type)
+                       return technology;
+       }
+
+       return NULL;
+}
+
+static struct connman_technology *technology_get(enum connman_service_type type)
+{
+       static unsigned int counter = 0;
+       struct connman_technology *technology;
+
+       DBG("type %d", type);
+
+       technology = technology_find(type);
+       if (technology != NULL) {
+               g_atomic_int_inc(&technology->refcount);
+               goto done;
+       }
+
+       technology = g_try_new0(struct connman_technology, 1);
+       if (technology == NULL)
+               return NULL;
+
+       technology->refcount = 1;
+
+       technology->type = type;
+       technology->path = g_strdup_printf("%s/technology%d",
+                                               CONNMAN_PATH, counter++);
+
+       if (g_dbus_register_interface(connection, technology->path,
+                                       CONNMAN_TECHNOLOGY_INTERFACE,
+                                       technology_methods, technology_signals,
+                                       NULL, technology, NULL) == FALSE) {
+               connman_error("Failed to register %s", technology->path);
+               g_free(technology);
+               return NULL;
+       }
+
+       technology_list = g_slist_append(technology_list, technology);
+
+       technologies_changed();
+
+done:
+       DBG("technology %p", technology);
+
+       return technology;
+}
+
+static void technology_put(struct connman_technology *technology)
+{
+       DBG("technology %p", technology);
+
+       if (g_atomic_int_dec_and_test(&technology->refcount) == FALSE)
+               return;
+
+       technology_list = g_slist_remove(technology_list, technology);
+
+       technologies_changed();
+
+       g_dbus_unregister_interface(connection, technology->path,
+                                               CONNMAN_TECHNOLOGY_INTERFACE);
+
+       g_free(technology->path);
+       g_free(technology);
+}
+
+static void unregister_device(gpointer data)
+{
+       struct connman_technology *technology = data;
+
+       DBG("technology %p", technology);
+
+       technology_put(technology);
+}
+
+int __connman_technology_add_device(struct connman_device *device)
+{
+       struct connman_technology *technology;
+       enum connman_service_type type;
+
+       DBG("device %p", device);
+
+       type = __connman_device_get_service_type(device);
+
+       technology = technology_get(type);
+       if (technology == NULL)
+               return -ENXIO;
+
+       g_hash_table_insert(device_table, device, technology);
+
+       technology->device_list = g_slist_append(technology->device_list,
+                                                               device);
+
+       devices_changed(technology);
+
+       return 0;
+}
+
+int __connman_technology_remove_device(struct connman_device *device)
+{
+       struct connman_technology *technology;
+
+       DBG("device %p", device);
+
+       technology = g_hash_table_lookup(device_table, device);
+       if (technology == NULL)
+               return -ENXIO;
+
+       technology->device_list = g_slist_remove(technology->device_list,
+                                                               device);
+
+       devices_changed(technology);
+
+       g_hash_table_remove(device_table, device);
+
+       return 0;
+}
+
 int __connman_technology_init(void)
 {
        DBG("");
 
+       connection = connman_dbus_get_connection();
+
+       device_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+                                               NULL, unregister_device);
+
        return 0;
 }
 
 void __connman_technology_cleanup(void)
 {
        DBG("");
+
+       g_hash_table_destroy(device_table);
+
+       dbus_connection_unref(connection);
 }
index 61d8bbc..78c319b 100755 (executable)
@@ -9,21 +9,27 @@ manager = dbus.Interface(bus.get_object("org.moblin.connman", "/"),
 
 properties = manager.GetProperties()
 
-for path in properties["Devices"]:
-       device = dbus.Interface(bus.get_object("org.moblin.connman", path),
-                                               "org.moblin.connman.Device")
+for path in properties["Technologies"]:
+       technology = dbus.Interface(bus.get_object("org.moblin.connman", path),
+                                               "org.moblin.connman.Technology")
 
-       properties = device.GetProperties()
+       properties = technology.GetProperties()
 
-       print "[ %s ]" % (path)
+       for path in properties["Devices"]:
+               device = dbus.Interface(bus.get_object("org.moblin.connman", path),
+                                                       "org.moblin.connman.Device")
 
-       for key in properties.keys():
-               if key in ["Networks"]:
-                       val = ""
-                       for i in properties[key]:
-                               val += i + " "
-               else:
-                       val = str(properties[key])
-               print "    %s = %s" % (key, val)
+               properties = device.GetProperties()
 
-       print
+               print "[ %s ]" % (path)
+
+               for key in properties.keys():
+                       if key in ["Networks"]:
+                               val = ""
+                               for i in properties[key]:
+                                       val += i + " "
+                       else:
+                               val = str(properties[key])
+                       print "    %s = %s" % (key, val)
+
+               print
index a619242..82ca805 100755 (executable)
@@ -6,7 +6,7 @@ import dbus
 import dbus.mainloop.glib
 
 def property_changed(name, value):
-       if name in ["Profiles", "Services", "Providers",
+       if name in ["Profiles", "Services", "Providers", "Technologies",
                                                "Devices", "Networks"]:
                val = "["
                for i in value:
index c435a34..7d65447 100755 (executable)
@@ -10,7 +10,7 @@ def property_changed(name, value, path, interface):
        ipath = path[path.rfind("/") + 1:]
        if iface not in ["Service"]:
                return
-       if name in ["Profiles", "Services", "Providers",
+       if name in ["Profiles", "Services", "Providers", "Technologies",
                                                "Devices", "Networks"]:
                val = "["
                for i in value:
index a41d657..6f9c200 100755 (executable)
@@ -18,6 +18,8 @@ def print_properties(key, value):
                interface = "org.moblin.connman.Service"
        elif key == "Providers":
                interface = "org.moblin.connman.Provider"
+       elif key == "Technologies":
+               interface = "org.moblin.connman.Technology"
        else:
                return
 
@@ -30,7 +32,8 @@ def print_properties(key, value):
                properties = obj.GetProperties()
 
                for key in properties.keys():
-                       if key in ["Networks", "Services", "Providers"]:
+                       if key in ["Devices", "Networks", "Services",
+                                               "Providers", "Technologies"]:
                                continue
 
                        if key in ["Powered", "Scanning", "Connected",
@@ -46,6 +49,12 @@ def print_properties(key, value):
 
                        print "        %s = %s" % (key, val)
 
+               if "Devices" in properties.keys():
+                       list = ""
+                       for path in properties["Devices"]:
+                               val = str(path)
+                               list = list + val[val.rfind("/") + 1:] + " "
+                       print "        Devices = [ %s]" % (list)
                if "Networks" in properties.keys():
                        list = ""
                        for path in properties["Networks"]:
@@ -67,7 +76,8 @@ def print_properties(key, value):
 
 
 for key in properties.keys():
-       if key in ["Profiles", "Devices", "Services", "Providers"]:
+       if key in ["Profiles", "Devices", "Services", "Providers",
+                                                       "Technologies"]:
                print_properties(key, properties[key])
        elif key in ["AvailableTechnologies", "EnabledTechnologies",
                                        "ConnectedTechnologies",