X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Felement.c;h=11450539872aff529d4f9e5149926eacbc73a9ba;hb=76fc6c0e0c2ad9890a5cfde7b503b11276f64a95;hp=0aef003b3417d8463a0116879dada0015ac75bd0;hpb=193dcee5019657796339e4c4132e6d5425318871;p=connman diff --git a/src/element.c b/src/element.c index 0aef003..1145053 100644 --- a/src/element.c +++ b/src/element.c @@ -34,11 +34,8 @@ static DBusConnection *connection; -static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT; static GNode *element_root = NULL; - static GSList *driver_list = NULL; - static gchar *device_filter = NULL; static struct { @@ -55,6 +52,8 @@ static struct { DBUS_TYPE_STRING, "IPv4.Netmask" }, { CONNMAN_PROPERTY_ID_IPV4_GATEWAY, DBUS_TYPE_STRING, "IPv4.Gateway" }, + { CONNMAN_PROPERTY_ID_IPV4_BROADCAST, + DBUS_TYPE_STRING, "IPv4.Broadcast" }, { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, DBUS_TYPE_STRING, "IPv4.Nameserver" }, @@ -115,8 +114,6 @@ static const char *type2string(enum connman_element_type type) return "bootp"; case CONNMAN_ELEMENT_TYPE_ZEROCONF: return "zeroconf"; - case CONNMAN_ELEMENT_TYPE_RESOLVER: - return "resolver"; case CONNMAN_ELEMENT_TYPE_CONNECTION: return "connection"; } @@ -148,17 +145,37 @@ static const char *subtype2string(enum connman_element_subtype type) return NULL; } +static const char *subtype2description(enum connman_element_subtype type) +{ + switch (type) { + case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN: + case CONNMAN_ELEMENT_SUBTYPE_FAKE: + case CONNMAN_ELEMENT_SUBTYPE_NETWORK: + return NULL; + case CONNMAN_ELEMENT_SUBTYPE_ETHERNET: + return "Ethernet"; + case CONNMAN_ELEMENT_SUBTYPE_WIFI: + return "Wireless"; + case CONNMAN_ELEMENT_SUBTYPE_WIMAX: + return "WiMAX"; + case CONNMAN_ELEMENT_SUBTYPE_MODEM: + return "Modem"; + case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH: + return "Bluetooth"; + } + + return NULL; +} + const char *__connman_element_policy2string(enum connman_element_policy policy) { switch (policy) { case CONNMAN_ELEMENT_POLICY_UNKNOWN: return "unknown"; - case CONNMAN_ELEMENT_POLICY_OFF: - return "off"; - case CONNMAN_ELEMENT_POLICY_AUTO: - return "auto"; case CONNMAN_ELEMENT_POLICY_IGNORE: return "ignore"; + case CONNMAN_ELEMENT_POLICY_AUTO: + return "auto"; case CONNMAN_ELEMENT_POLICY_ASK: return "ask"; } @@ -168,9 +185,7 @@ const char *__connman_element_policy2string(enum connman_element_policy policy) enum connman_element_policy __connman_element_string2policy(const char *policy) { - if (strcasecmp(policy, "off") == 0) - return CONNMAN_ELEMENT_POLICY_OFF; - else if (strcasecmp(policy, "ignore") == 0) + if (strcasecmp(policy, "ignore") == 0) return CONNMAN_ELEMENT_POLICY_IGNORE; else if (strcasecmp(policy, "auto") == 0) return CONNMAN_ELEMENT_POLICY_AUTO; @@ -180,18 +195,54 @@ enum connman_element_policy __connman_element_string2policy(const char *policy) return CONNMAN_ELEMENT_POLICY_UNKNOWN; } +const char *__connman_ipv4_method2string(enum connman_ipv4_method method) +{ + switch (method) { + case CONNMAN_IPV4_METHOD_UNKNOWN: + return "unknown"; + case CONNMAN_IPV4_METHOD_OFF: + return "off"; + case CONNMAN_IPV4_METHOD_STATIC: + return "static"; + case CONNMAN_IPV4_METHOD_DHCP: + return "dhcp"; + } + + return "unknown"; +} + +enum connman_ipv4_method __connman_ipv4_string2method(const char *method) +{ + if (strcasecmp(method, "off") == 0) + return CONNMAN_IPV4_METHOD_OFF; + else if (strcasecmp(method, "static") == 0) + return CONNMAN_IPV4_METHOD_STATIC; + else if (strcasecmp(method, "dhcp") == 0) + return CONNMAN_IPV4_METHOD_DHCP; + else + return CONNMAN_IPV4_METHOD_UNKNOWN; +} + static void append_property(DBusMessageIter *dict, struct connman_property *property) { if (property->value == NULL) return; - if (property->type == DBUS_TYPE_ARRAY) + switch (property->type) { + case DBUS_TYPE_ARRAY: connman_dbus_dict_append_array(dict, property->name, property->subtype, &property->value, property->size); - else + break; + case DBUS_TYPE_STRING: connman_dbus_dict_append_variant(dict, property->name, property->type, &property->value); + break; + default: + connman_dbus_dict_append_variant(dict, property->name, + property->type, property->value); + break; + } } static void add_common_properties(struct connman_element *element, @@ -280,6 +331,86 @@ static void set_common_property(struct connman_element *element, __connman_element_unlock(element); } +static void emit_enabled_signal(DBusConnection *conn, + struct connman_element *element) +{ + DBusMessage *signal; + DBusMessageIter entry, value; + const char *iface, *key; + + DBG("conn %p", conn); + + if (element == NULL) + return; + + switch (element->type) { + case CONNMAN_ELEMENT_TYPE_DEVICE: + iface = CONNMAN_DEVICE_INTERFACE; + key = "Powered"; + break; + case CONNMAN_ELEMENT_TYPE_NETWORK: + iface = CONNMAN_NETWORK_INTERFACE; + key = "Connected"; + break; + case CONNMAN_ELEMENT_TYPE_CONNECTION: + iface = CONNMAN_CONNECTION_INTERFACE; + key = "Default"; + break; + default: + return; + } + + signal = dbus_message_new_signal(element->path, + iface, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_BOOLEAN_AS_STRING, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, + &element->enabled); + dbus_message_iter_close_container(&entry, &value); + + g_dbus_send_message(conn, signal); +} + +static void emit_scanning_signal(DBusConnection *conn, + struct connman_element *element) +{ + DBusMessage *signal; + DBusMessageIter entry, value; + const char *key = "Scanning"; + + DBG("conn %p", conn); + + if (element == NULL) + return; + + if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE) + return; + + signal = dbus_message_new_signal(element->path, + CONNMAN_DEVICE_INTERFACE, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_BOOLEAN_AS_STRING, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, + &element->scanning); + dbus_message_iter_close_container(&entry, &value); + + g_dbus_send_message(conn, signal); +} + static DBusMessage *do_update(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -318,12 +449,7 @@ static DBusMessage *do_enable(DBusConnection *conn, element->enabled = TRUE; -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif + emit_enabled_signal(connection, element); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } @@ -346,28 +472,20 @@ static DBusMessage *do_disable(DBusConnection *conn, element->enabled = FALSE; -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif + emit_enabled_signal(connection, element); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } static void append_networks(struct connman_element *element, - DBusMessageIter *dict) + DBusMessageIter *entry) { - DBusMessageIter entry, value, iter; + DBusMessageIter value, iter; const char *key = "Networks"; - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING, &value); @@ -378,17 +496,15 @@ static void append_networks(struct connman_element *element, dbus_message_iter_close_container(&value, &iter); - dbus_message_iter_close_container(&entry, &value); - - dbus_message_iter_close_container(dict, &entry); + dbus_message_iter_close_container(entry, &value); } -static DBusMessage *get_device_properties(DBusConnection *conn, +static DBusMessage *device_get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; DBusMessage *reply; - DBusMessageIter array, dict; + DBusMessageIter array, dict, entry; const char *str; DBG("conn %p", conn); @@ -404,6 +520,15 @@ static DBusMessage *get_device_properties(DBusConnection *conn, DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + str = subtype2description(element->subtype); + if (str != NULL && element->devname != NULL) { + char *name = g_strdup_printf("%s (%s)", str, element->devname); + if (name != NULL) + connman_dbus_dict_append_variant(&dict, "Name", + DBUS_TYPE_STRING, &name); + g_free(name); + } + str = subtype2string(element->subtype); if (str != NULL) connman_dbus_dict_append_variant(&dict, "Type", @@ -417,7 +542,17 @@ static DBusMessage *get_device_properties(DBusConnection *conn, connman_dbus_dict_append_variant(&dict, "Powered", DBUS_TYPE_BOOLEAN, &element->enabled); - append_networks(element, &dict); + if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI || + element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIMAX || + element->subtype == CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH) { + connman_dbus_dict_append_variant(&dict, "Scanning", + DBUS_TYPE_BOOLEAN, &element->scanning); + + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + append_networks(element, &entry); + dbus_message_iter_close_container(&dict, &entry); + } add_common_properties(element, &dict); @@ -426,12 +561,11 @@ static DBusMessage *get_device_properties(DBusConnection *conn, return reply; } -static DBusMessage *set_device_property(DBusConnection *conn, +static DBusMessage *device_set_property(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; - DBusMessageIter iter; - DBusMessageIter value; + DBusMessageIter iter, value; const char *name; DBG("conn %p", conn); @@ -452,9 +586,9 @@ static DBusMessage *set_device_property(DBusConnection *conn, dbus_message_iter_get_basic(&value, &powered); if (powered == TRUE) - do_enable(conn, msg, data); + do_enable(conn, msg, element); else - do_disable(conn, msg, data); + do_disable(conn, msg, element); } else set_common_property(element, name, &value); @@ -463,7 +597,88 @@ static DBusMessage *set_device_property(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static DBusMessage *get_network_properties(DBusConnection *conn, +static int parse_network_dict(DBusMessageIter *iter, const char **ssid, + const char **security, const char **passphrase) +{ + while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value; + const char *key; + + dbus_message_iter_recurse(iter, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + switch (dbus_message_iter_get_arg_type(&value)) { + case DBUS_TYPE_STRING: + if (g_str_equal(key, "WiFi.SSID") == TRUE) + dbus_message_iter_get_basic(&value, ssid); + else if (g_str_equal(key, "WiFi.Security") == TRUE) + dbus_message_iter_get_basic(&value, security); + else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) + dbus_message_iter_get_basic(&value, passphrase); + break; + } + + dbus_message_iter_next(iter); + } + + return 0; +} + +static DBusMessage *device_create_network(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct connman_element *element = data; + struct connman_element *network; + DBusMessageIter iter, array; + const char *ssid = NULL, *security = NULL, *passphrase = NULL; + + DBG("conn %p", conn); + + if (element->subtype != CONNMAN_ELEMENT_SUBTYPE_WIFI) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_init(msg, &iter) == FALSE) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&iter, &array); + parse_network_dict(&array, &ssid, &security, &passphrase); + if (ssid == NULL) + return __connman_error_invalid_arguments(msg); + + DBG("ssid %s security %s passphrase %s", ssid, security, passphrase); + + network = connman_element_create(ssid); + + network->type = CONNMAN_ELEMENT_TYPE_NETWORK; + network->index = element->index; + + network->remember = TRUE; + + connman_element_add_static_property(network, "Name", + DBUS_TYPE_STRING, &ssid); + + connman_element_add_static_array_property(element, "WiFi.SSID", + DBUS_TYPE_BYTE, &ssid, strlen(ssid)); + + network->wifi.security = g_strdup(security); + network->wifi.passphrase = g_strdup(passphrase); + + connman_element_register(network, element); + + return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &network->path, + DBUS_TYPE_INVALID); +} + +static DBusMessage *device_remove_network(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); +} + +static DBusMessage *network_get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; @@ -484,14 +699,24 @@ static DBusMessage *get_network_properties(DBusConnection *conn, DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + if (element->parent) + connman_dbus_dict_append_variant(&dict, "Device", + DBUS_TYPE_OBJECT_PATH, &element->parent->path); + str = __connman_element_policy2string(element->policy); if (str != NULL) connman_dbus_dict_append_variant(&dict, "Policy", DBUS_TYPE_STRING, &str); + connman_dbus_dict_append_variant(&dict, "Available", + DBUS_TYPE_BOOLEAN, &element->available); + connman_dbus_dict_append_variant(&dict, "Connected", DBUS_TYPE_BOOLEAN, &element->enabled); + connman_dbus_dict_append_variant(&dict, "Remember", + DBUS_TYPE_BOOLEAN, &element->remember); + add_common_properties(element, &dict); dbus_message_iter_close_container(&array, &dict); @@ -499,7 +724,7 @@ static DBusMessage *get_network_properties(DBusConnection *conn, return reply; } -static DBusMessage *set_network_property(DBusConnection *conn, +static DBusMessage *network_set_property(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; @@ -519,7 +744,9 @@ static DBusMessage *set_network_property(DBusConnection *conn, if (__connman_security_check_privileges(msg) < 0) return __connman_error_permission_denied(msg); - if (g_str_equal(name, "WiFi.Passphrase") == TRUE) { + if (g_str_equal(name, "Remember") == TRUE) { + dbus_message_iter_get_basic(&value, &element->remember); + } else if (g_str_equal(name, "WiFi.Passphrase") == TRUE) { const char *str; dbus_message_iter_get_basic(&value, &str); @@ -533,35 +760,7 @@ static DBusMessage *set_network_property(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static DBusMessage *get_connection_properties(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessage *reply; - DBusMessageIter array, dict; - - DBG("conn %p", conn); - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &array); - - dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - add_common_properties(element, &dict); - - dbus_message_iter_close_container(&array, &dict); - - return reply; -} - -#if 0 -static DBusMessage *get_properties(DBusConnection *conn, +static DBusMessage *connection_get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; @@ -582,22 +781,17 @@ static DBusMessage *get_properties(DBusConnection *conn, DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - if (element->parent != NULL && - element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) { - connman_dbus_dict_append_variant(&dict, "Parent", - DBUS_TYPE_OBJECT_PATH, &element->parent->path); - } - - str = type2string(element->type); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Type", - DBUS_TYPE_STRING, &str); str = subtype2string(element->subtype); if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Subtype", + connman_dbus_dict_append_variant(&dict, "Type", DBUS_TYPE_STRING, &str); - connman_dbus_dict_append_variant(&dict, "Enabled", + if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI || + element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIMAX) + connman_dbus_dict_append_variant(&dict, "Strength", + DBUS_TYPE_BYTE, &element->strength); + + connman_dbus_dict_append_variant(&dict, "Default", DBUS_TYPE_BOOLEAN, &element->enabled); add_common_properties(element, &dict); @@ -607,12 +801,11 @@ static DBusMessage *get_properties(DBusConnection *conn, return reply; } -static DBusMessage *set_property(DBusConnection *conn, +static DBusMessage *connection_set_property(DBusConnection *conn, DBusMessage *msg, void *data) { struct connman_element *element = data; - DBusMessageIter iter; - DBusMessageIter value; + DBusMessageIter iter, value; const char *name; DBG("conn %p", conn); @@ -627,87 +820,45 @@ static DBusMessage *set_property(DBusConnection *conn, if (__connman_security_check_privileges(msg) < 0) return __connman_error_permission_denied(msg); - set_common_property(element, name, &value); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static DBusMessage *clear_property(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - const char *name; - GSList *list; - - DBG("conn %p", conn); - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID) == FALSE) - return __connman_error_invalid_arguments(msg); - - if (__connman_security_check_privileges(msg) < 0) - return __connman_error_permission_denied(msg); - - __connman_element_lock(element); + if (g_str_equal(name, "Default") == TRUE) { + dbus_bool_t enabled; - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (g_str_equal(property->name, name) == FALSE) - continue; + dbus_message_iter_get_basic(&value, &enabled); - if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC) - continue; - - if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE) - continue; - - property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE; - - if (property->type == DBUS_TYPE_STRING) - g_free(property->value); - - property->value = NULL; + if (enabled == TRUE) + return do_enable(conn, msg, element); + else + return do_disable(conn, msg, element); } - __connman_element_unlock(element); - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } -static GDBusMethodTable element_methods[] = { - { "GetProperties", "", "a{sv}", get_properties }, - { "SetProperty", "sv", "", set_property }, - { "ClearProperty", "s", "", clear_property }, - { "Update", "", "", do_update }, - { "Enable", "", "", do_enable }, - { "Disable", "", "", do_disable }, - { }, -}; -#endif - -static GDBusSignalTable element_signals[] = { - { "PropertyChanged", "sv" }, - { }, -}; - static GDBusMethodTable device_methods[] = { - { "GetProperties", "", "a{sv}", get_device_properties }, - { "SetProperty", "sv", "", set_device_property }, - { "Scan", "", "", do_update }, + { "GetProperties", "", "a{sv}", device_get_properties }, + { "SetProperty", "sv", "", device_set_property }, + { "CreateNetwork", "a{sv}", "o", device_create_network }, + { "RemoveNetwork", "o", "", device_remove_network }, + { "ProposeScan", "", "", do_update }, { }, }; static GDBusMethodTable network_methods[] = { - { "GetProperties", "", "a{sv}", get_network_properties }, - { "SetProperty", "sv", "", set_network_property }, + { "GetProperties", "", "a{sv}", network_get_properties }, + { "SetProperty", "sv", "", network_set_property }, { "Connect", "", "", do_enable }, { "Disconnect", "", "", do_disable }, { }, }; static GDBusMethodTable connection_methods[] = { - { "GetProperties", "", "a{sv}", get_connection_properties }, + { "GetProperties", "", "a{sv}", connection_get_properties }, + { "SetProperty", "sv", "", connection_set_property }, + { }, +}; + +static GDBusSignalTable element_signals[] = { + { "PropertyChanged", "sv" }, { }, }; @@ -730,6 +881,10 @@ static gboolean append_path(GNode *node, gpointer user_data) filter->type != element->type) return FALSE; + if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE && + element->subtype == CONNMAN_ELEMENT_SUBTYPE_NETWORK) + return FALSE; + dbus_message_iter_append_basic(filter->iter, DBUS_TYPE_OBJECT_PATH, &element->path); @@ -753,10 +908,8 @@ void __connman_element_list(struct connman_element *element, } else node = element_root; - g_static_rw_lock_reader_lock(&element_lock); g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, append_path, &filter); - g_static_rw_lock_reader_unlock(&element_lock); } struct count_data { @@ -799,10 +952,8 @@ int __connman_element_count(struct connman_element *element, } else node = element_root; - g_static_rw_lock_reader_lock(&element_lock); g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, count_element, &data); - g_static_rw_lock_reader_unlock(&element_lock); return data.count; } @@ -841,8 +992,10 @@ static void enable_element(struct connman_element *element) return; if (element->driver && element->driver->enable) { - if (element->driver->enable(element) == 0) + if (element->driver->enable(element) == 0) { element->enabled = TRUE; + emit_enabled_signal(connection, element); + } } } @@ -874,13 +1027,9 @@ void __connman_driver_rescan(struct connman_driver *driver) if (!driver->probe) return; - g_static_rw_lock_writer_lock(&element_lock); - if (element_root != NULL) g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, probe_driver, driver); - - g_static_rw_lock_writer_unlock(&element_lock); } /** @@ -901,8 +1050,6 @@ int connman_driver_register(struct connman_driver *driver) if (!driver->probe) return -EINVAL; - g_static_rw_lock_writer_lock(&element_lock); - driver_list = g_slist_insert_sorted(driver_list, driver, compare_priority); @@ -910,8 +1057,6 @@ int connman_driver_register(struct connman_driver *driver) g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, probe_driver, driver); - g_static_rw_lock_writer_unlock(&element_lock); - return 0; } @@ -924,8 +1069,10 @@ static void disable_element(struct connman_element *element) return; if (element->driver && element->driver->disable) { - if (element->driver->disable(element) == 0) + if (element->driver->disable(element) == 0) { element->enabled = FALSE; + emit_enabled_signal(connection, element); + } } } @@ -960,15 +1107,11 @@ void connman_driver_unregister(struct connman_driver *driver) { DBG("driver %p name %s", driver, driver->name); - g_static_rw_lock_writer_lock(&element_lock); - driver_list = g_slist_remove(driver_list, driver); if (element_root != NULL) g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, remove_driver, driver); - - g_static_rw_lock_writer_unlock(&element_lock); } /** @@ -1051,6 +1194,7 @@ void connman_element_unref(struct connman_element *element) g_free(element->ipv4.network); g_free(element->ipv4.broadcast); g_free(element->ipv4.nameserver); + g_free(element->devname); g_free(element->path); g_free(element->name); g_free(element); @@ -1064,8 +1208,7 @@ int connman_element_add_static_property(struct connman_element *element, DBG("element %p name %s", element, element->name); - if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE && - type != DBUS_TYPE_INT32) + if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE) return -EINVAL; property = g_try_new0(struct connman_property, 1); @@ -1088,11 +1231,6 @@ int connman_element_add_static_property(struct connman_element *element, if (property->value != NULL) memcpy(property->value, value, 1); break; - case DBUS_TYPE_INT32: - property->value = g_try_malloc(sizeof(gint32)); - if (property->value != NULL) - memcpy(property->value, value, sizeof(gint32)); - break; } __connman_element_lock(element); @@ -1102,6 +1240,102 @@ int connman_element_add_static_property(struct connman_element *element, return 0; } +static void emit_property_changed(DBusConnection *conn, + struct connman_element *element, + const char *name, int type, const void *data) +{ + DBusMessage *signal; + DBusMessageIter entry, value; + const char *iface, *sig; + + DBG("conn %p", conn); + + switch (element->type) { + case CONNMAN_ELEMENT_TYPE_DEVICE: + iface = CONNMAN_DEVICE_INTERFACE; + break; + case CONNMAN_ELEMENT_TYPE_NETWORK: + iface = CONNMAN_NETWORK_INTERFACE; + break; + case CONNMAN_ELEMENT_TYPE_CONNECTION: + iface = CONNMAN_CONNECTION_INTERFACE; + break; + default: + return; + } + + signal = dbus_message_new_signal(element->path, + iface, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name); + + switch (type) { + case DBUS_TYPE_STRING: + sig = DBUS_TYPE_STRING_AS_STRING; + break; + case DBUS_TYPE_BYTE: + sig = DBUS_TYPE_BYTE_AS_STRING; + break; + default: + sig = DBUS_TYPE_VARIANT_AS_STRING; + break; + } + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + sig, &value); + dbus_message_iter_append_basic(&value, type, data); + dbus_message_iter_close_container(&entry, &value); + + g_dbus_send_message(conn, signal); +} + +int connman_element_set_static_property(struct connman_element *element, + const char *name, int type, const void *value) +{ + GSList *list; + + DBG("element %p name %s", element, element->name); + + if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE) + return -EINVAL; + + __connman_element_lock(element); + + for (list = element->properties; list; list = list->next) { + struct connman_property *property = list->data; + + if (g_str_equal(property->name, name) == FALSE) + continue; + + if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC)) + continue; + + property->type = type; + g_free(property->value); + + switch (type) { + case DBUS_TYPE_STRING: + property->value = g_strdup(*((const char **) value)); + break; + case DBUS_TYPE_BYTE: + property->value = g_try_malloc(1); + if (property->value != NULL) + memcpy(property->value, value, 1); + break; + } + } + + __connman_element_unlock(element); + + emit_property_changed(connection, element, name, type, value); + + return 0; +} + int connman_element_add_static_array_property(struct connman_element *element, const char *name, int type, const void *value, int len) { @@ -1320,6 +1554,12 @@ int connman_element_set_property(struct connman_element *element, element->ipv4.gateway = g_strdup(*((const char **) value)); __connman_element_unlock(element); break; + case CONNMAN_PROPERTY_ID_IPV4_BROADCAST: + __connman_element_lock(element); + g_free(element->ipv4.broadcast); + element->ipv4.broadcast = g_strdup(*((const char **) value)); + __connman_element_unlock(element); + break; case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER: __connman_element_lock(element); g_free(element->ipv4.nameserver); @@ -1342,13 +1582,6 @@ int connman_element_set_property(struct connman_element *element, return -EINVAL; } -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif - return 0; } @@ -1383,6 +1616,14 @@ int connman_element_get_value(struct connman_element *element, *((char **) value) = element->ipv4.gateway; __connman_element_unlock(element); break; + case CONNMAN_PROPERTY_ID_IPV4_BROADCAST: + if (element->ipv4.broadcast == NULL) + return connman_element_get_value(element->parent, + id, value); + __connman_element_lock(element); + *((char **) value) = element->ipv4.broadcast; + __connman_element_unlock(element); + break; case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER: if (element->ipv4.nameserver == NULL) return connman_element_get_value(element->parent, @@ -1434,15 +1675,9 @@ gboolean connman_element_get_static_property(struct connman_element *element, switch (property->type) { case DBUS_TYPE_STRING: *((char **) value) = property->value; - break; - case DBUS_TYPE_BYTE: - *((guint8 *) value) = *((guint8 *) property->value); - break; - case DBUS_TYPE_INT32: - *((gint32 *) value) = *((gint32 *) property->value); + found = TRUE; break; } - found = TRUE; break; } } @@ -1526,9 +1761,7 @@ static void append_devices(DBusMessageIter *entry) dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter); - dbus_message_iter_close_container(&value, &iter); dbus_message_iter_close_container(entry, &value); @@ -1553,6 +1786,29 @@ static void emit_devices_signal(DBusConnection *conn) g_dbus_send_message(conn, signal); } +static void emit_networks_signal(DBusConnection *conn, + struct connman_element *device) +{ + DBusMessage *signal; + DBusMessageIter entry; + + DBG("conn %p", conn); + + if (device == NULL) + return; + + signal = dbus_message_new_signal(device->path, + CONNMAN_DEVICE_INTERFACE, "PropertyChanged"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &entry); + + append_networks(device, &entry); + + g_dbus_send_message(conn, signal); +} + static void append_connections(DBusMessageIter *entry) { DBusMessageIter value, iter; @@ -1566,9 +1822,7 @@ static void append_connections(DBusMessageIter *entry) dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter); - dbus_message_iter_close_container(&value, &iter); dbus_message_iter_close_container(entry, &value); @@ -1602,9 +1856,7 @@ static void append_state(DBusMessageIter *entry, const char *state) dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &value); - dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state); - dbus_message_iter_close_container(entry, &value); } @@ -1627,6 +1879,20 @@ static void emit_state_change(DBusConnection *conn, const char *state) g_dbus_send_message(conn, signal); } +static void set_signal_strength(struct connman_element *connection) +{ + struct connman_element *element = connection; + + while (element != NULL) { + if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) { + connection->strength = element->strength; + break; + } + + element = element->parent; + } +} + static void register_element(gpointer data, gpointer user_data) { struct connman_element *element = data; @@ -1634,8 +1900,6 @@ static void register_element(gpointer data, gpointer user_data) GSList *list; GNode *node; - g_static_rw_lock_writer_lock(&element_lock); - __connman_element_lock(element); if (element->parent) { @@ -1664,14 +1928,6 @@ static void register_element(gpointer data, gpointer user_data) g_node_append_data(node, element); -#if 0 - if (g_dbus_register_interface(connection, element->path, - CONNMAN_ELEMENT_INTERFACE, - element_methods, element_signals, - NULL, element, NULL) == FALSE) - connman_error("Failed to register %s element", element->path); -#endif - if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE && element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) { if (g_dbus_register_interface(connection, element->path, @@ -1691,6 +1947,8 @@ static void register_element(gpointer data, gpointer user_data) NULL, element, NULL) == FALSE) connman_error("Failed to register %s network", element->path); + else + emit_networks_signal(connection, element->parent); } if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) { @@ -1701,24 +1959,14 @@ static void register_element(gpointer data, gpointer user_data) connman_error("Failed to register %s connection", element->path); else { + set_signal_strength(element); emit_connections_signal(connection); emit_state_change(connection, "online"); } } -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementAdded", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif - - g_static_rw_lock_writer_unlock(&element_lock); - __connman_element_store(element); - g_static_rw_lock_writer_lock(&element_lock); - for (list = driver_list; list; list = list->next) { struct connman_driver *driver = list->data; @@ -1736,8 +1984,6 @@ static void register_element(gpointer data, gpointer user_data) break; } } - - g_static_rw_lock_writer_unlock(&element_lock); } /** @@ -1755,10 +2001,15 @@ int connman_element_register(struct connman_element *element, { DBG("element %p name %s parent %p", element, element->name, parent); - if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) { + if (element->devname == NULL) + element->devname = g_strdup(element->name); + + if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE && + element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) { if (g_pattern_match_simple(device_filter, - element->name) == FALSE) { - DBG("ignoring %s device", element->name); + element->devname) == FALSE) { + DBG("ignoring %s [%s] device", element->name, + element->devname); return -EPERM; } } @@ -1796,6 +2047,8 @@ static gboolean remove_element(GNode *node, gpointer user_data) return FALSE; if (element->driver) { + disable_element(element); + if (element->driver->remove) element->driver->remove(element); @@ -1809,24 +2062,22 @@ static gboolean remove_element(GNode *node, gpointer user_data) g_node_destroy(node); } -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementRemoved", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif - if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) { - emit_state_change(connection, "offline"); + if (__connman_element_count(NULL, + CONNMAN_ELEMENT_TYPE_CONNECTION) == 0) + emit_state_change(connection, "offline"); emit_connections_signal(connection); g_dbus_unregister_interface(connection, element->path, CONNMAN_CONNECTION_INTERFACE); } - if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) + if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) { + emit_networks_signal(connection, element->parent); + g_dbus_unregister_interface(connection, element->path, CONNMAN_NETWORK_INTERFACE); + } if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE && element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) { @@ -1836,11 +2087,6 @@ static gboolean remove_element(GNode *node, gpointer user_data) CONNMAN_DEVICE_INTERFACE); } -#if 0 - g_dbus_unregister_interface(connection, element->path, - CONNMAN_ELEMENT_INTERFACE); -#endif - connman_element_unref(element); return FALSE; @@ -1852,15 +2098,11 @@ void connman_element_unregister(struct connman_element *element) DBG("element %p name %s", element, element->name); - g_static_rw_lock_writer_lock(&element_lock); - node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element); if (node != NULL) g_node_traverse(node, G_POST_ORDER, G_TRAVERSE_ALL, -1, remove_element, NULL); - - g_static_rw_lock_writer_unlock(&element_lock); } void connman_element_unregister_children(struct connman_element *element) @@ -1869,32 +2111,31 @@ void connman_element_unregister_children(struct connman_element *element) DBG("element %p name %s", element, element->name); - g_static_rw_lock_writer_lock(&element_lock); - node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element); if (node != NULL) g_node_traverse(node, G_POST_ORDER, G_TRAVERSE_ALL, -1, remove_element, element); - - g_static_rw_lock_writer_unlock(&element_lock); } static gboolean update_element(GNode *node, gpointer user_data) { struct connman_element *element = node->data; + struct connman_element *root = user_data; DBG("element %p name %s", element, element->name); if (element->driver && element->driver->update) element->driver->update(element); -#if 0 - g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "ElementUpdated", - DBUS_TYPE_OBJECT_PATH, &element->path, - DBUS_TYPE_INVALID); -#endif + if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION && + root->type == CONNMAN_ELEMENT_TYPE_NETWORK) { + if (element->strength != root->strength) { + element->strength = root->strength; + emit_property_changed(connection, element, "Strength", + DBUS_TYPE_BYTE, &element->strength); + } + } return FALSE; } @@ -1905,15 +2146,11 @@ void connman_element_update(struct connman_element *element) DBG("element %p name %s", element, element->name); - g_static_rw_lock_reader_lock(&element_lock); - node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element); if (node != NULL) g_node_traverse(node, G_PRE_ORDER, - G_TRAVERSE_ALL, -1, update_element, NULL); - - g_static_rw_lock_reader_unlock(&element_lock); + G_TRAVERSE_ALL, -1, update_element, element); } int connman_element_set_enabled(struct connman_element *element, @@ -1924,7 +2161,20 @@ int connman_element_set_enabled(struct connman_element *element, element->enabled = enabled; - connman_element_update(element); + emit_enabled_signal(connection, element); + + return 0; +} + +int connman_element_set_scanning(struct connman_element *element, + gboolean scanning) +{ + if (element->scanning == scanning) + return 0; + + element->scanning = scanning; + + emit_scanning_signal(connection, element); return 0; } @@ -1941,8 +2191,6 @@ int __connman_element_init(DBusConnection *conn, const char *device) device_filter = g_strdup(device); - g_static_rw_lock_writer_lock(&element_lock); - element = connman_element_create("root"); element->path = g_strdup("/"); @@ -1952,8 +2200,6 @@ int __connman_element_init(DBusConnection *conn, const char *device) element_root = g_node_new(element); - g_static_rw_lock_writer_unlock(&element_lock); - __connman_device_init(); return 0; @@ -1966,6 +2212,8 @@ static gboolean free_driver(GNode *node, gpointer data) DBG("element %p name %s", element, element->name); if (element->driver) { + disable_element(element); + if (element->driver->remove) element->driver->remove(element); @@ -1995,20 +2243,14 @@ void __connman_element_cleanup(void) __connman_device_cleanup(); - g_static_rw_lock_writer_lock(&element_lock); g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, free_driver, NULL); - g_static_rw_lock_writer_unlock(&element_lock); - g_static_rw_lock_writer_lock(&element_lock); g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, free_node, NULL); - g_static_rw_lock_writer_unlock(&element_lock); - g_static_rw_lock_writer_lock(&element_lock); g_node_destroy(element_root); element_root = NULL; - g_static_rw_lock_writer_unlock(&element_lock); g_free(device_filter);