5 * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 static DBusConnection *connection;
37 static GNode *element_root = NULL;
38 static GSList *driver_list = NULL;
39 static gchar *device_filter = NULL;
41 static gboolean started = FALSE;
44 enum connman_property_id id;
49 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
50 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
51 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
52 DBUS_TYPE_STRING, "IPv4.Address" },
53 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
54 DBUS_TYPE_STRING, "IPv4.Netmask" },
55 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
56 DBUS_TYPE_STRING, "IPv4.Gateway" },
57 { CONNMAN_PROPERTY_ID_IPV4_BROADCAST,
58 DBUS_TYPE_STRING, "IPv4.Broadcast" },
59 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
60 DBUS_TYPE_STRING, "IPv4.Nameserver" },
62 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
63 DBUS_TYPE_STRING, "WiFi.Security" },
64 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
65 DBUS_TYPE_STRING, "WiFi.Passphrase" },
70 static int propid2type(enum connman_property_id id)
74 for (i = 0; propid_table[i].name; i++) {
75 if (propid_table[i].id == id)
76 return propid_table[i].type;
79 return DBUS_TYPE_INVALID;
82 static const char *propid2name(enum connman_property_id id)
86 for (i = 0; propid_table[i].name; i++) {
87 if (propid_table[i].id == id)
88 return propid_table[i].name;
94 static const char *type2string(enum connman_element_type type)
97 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
99 case CONNMAN_ELEMENT_TYPE_ROOT:
101 case CONNMAN_ELEMENT_TYPE_PROFILE:
103 case CONNMAN_ELEMENT_TYPE_DEVICE:
105 case CONNMAN_ELEMENT_TYPE_NETWORK:
107 case CONNMAN_ELEMENT_TYPE_SERVICE:
109 case CONNMAN_ELEMENT_TYPE_IPV4:
111 case CONNMAN_ELEMENT_TYPE_IPV6:
113 case CONNMAN_ELEMENT_TYPE_DHCP:
115 case CONNMAN_ELEMENT_TYPE_BOOTP:
117 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
119 case CONNMAN_ELEMENT_TYPE_CONNECTION:
126 static const char *subtype2string(enum connman_element_subtype type)
129 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
131 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
133 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
135 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
137 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
139 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
141 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
143 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
150 static const char *subtype2description(enum connman_element_subtype type)
153 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
154 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
155 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
157 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
159 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
161 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
163 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
165 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
172 const char *__connman_element_policy2string(enum connman_element_policy policy)
175 case CONNMAN_ELEMENT_POLICY_UNKNOWN:
177 case CONNMAN_ELEMENT_POLICY_IGNORE:
179 case CONNMAN_ELEMENT_POLICY_AUTO:
181 case CONNMAN_ELEMENT_POLICY_ASK:
188 enum connman_element_policy __connman_element_string2policy(const char *policy)
190 if (strcasecmp(policy, "ignore") == 0)
191 return CONNMAN_ELEMENT_POLICY_IGNORE;
192 else if (strcasecmp(policy, "auto") == 0)
193 return CONNMAN_ELEMENT_POLICY_AUTO;
194 else if (strcasecmp(policy, "ask") == 0)
195 return CONNMAN_ELEMENT_POLICY_ASK;
197 return CONNMAN_ELEMENT_POLICY_UNKNOWN;
200 const char *__connman_ipv4_method2string(enum connman_ipv4_method method)
203 case CONNMAN_IPV4_METHOD_UNKNOWN:
205 case CONNMAN_IPV4_METHOD_OFF:
207 case CONNMAN_IPV4_METHOD_STATIC:
209 case CONNMAN_IPV4_METHOD_DHCP:
216 enum connman_ipv4_method __connman_ipv4_string2method(const char *method)
218 if (strcasecmp(method, "off") == 0)
219 return CONNMAN_IPV4_METHOD_OFF;
220 else if (strcasecmp(method, "static") == 0)
221 return CONNMAN_IPV4_METHOD_STATIC;
222 else if (strcasecmp(method, "dhcp") == 0)
223 return CONNMAN_IPV4_METHOD_DHCP;
225 return CONNMAN_IPV4_METHOD_UNKNOWN;
228 static void append_property(DBusMessageIter *dict,
229 struct connman_property *property)
231 if (property->value == NULL)
234 switch (property->type) {
235 case DBUS_TYPE_ARRAY:
236 connman_dbus_dict_append_array(dict, property->name,
237 property->subtype, &property->value, property->size);
239 case DBUS_TYPE_STRING:
240 connman_dbus_dict_append_variant(dict, property->name,
241 property->type, &property->value);
244 connman_dbus_dict_append_variant(dict, property->name,
245 property->type, property->value);
250 static void add_common_properties(struct connman_element *element,
251 DBusMessageIter *dict)
253 const char *address = NULL, *netmask = NULL, *gateway = NULL;
256 connman_element_get_value(element,
257 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
258 connman_element_get_value(element,
259 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
260 connman_element_get_value(element,
261 CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
263 if (element->priority > 0)
264 connman_dbus_dict_append_variant(dict, "Priority",
265 DBUS_TYPE_UINT16, &element->priority);
268 connman_dbus_dict_append_variant(dict, "IPv4.Address",
269 DBUS_TYPE_STRING, &address);
271 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
272 DBUS_TYPE_STRING, &netmask);
274 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
275 DBUS_TYPE_STRING, &gateway);
277 if (element->wifi.security != NULL) {
278 const char *passphrase = "";
280 connman_dbus_dict_append_variant(dict, "WiFi.Security",
281 DBUS_TYPE_STRING, &element->wifi.security);
283 if (element->wifi.passphrase != NULL)
284 passphrase = element->wifi.passphrase;
286 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
287 DBUS_TYPE_STRING, &passphrase);
290 __connman_element_lock(element);
292 for (list = element->properties; list; list = list->next) {
293 struct connman_property *property = list->data;
295 append_property(dict, property);
298 __connman_element_unlock(element);
301 static void set_common_property(struct connman_element *element,
302 const char *name, DBusMessageIter *value)
306 if (g_str_equal(name, "Priority") == TRUE) {
307 dbus_message_iter_get_basic(value, &element->priority);
311 __connman_element_lock(element);
313 for (list = element->properties; list; list = list->next) {
314 struct connman_property *property = list->data;
317 if (g_str_equal(property->name, name) == FALSE)
320 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
323 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
325 if (property->type == DBUS_TYPE_STRING) {
326 dbus_message_iter_get_basic(value, &str);
327 g_free(property->value);
328 property->value = g_strdup(str);
330 property->value = NULL;
333 __connman_element_unlock(element);
336 static void emit_enabled_signal(DBusConnection *conn,
337 struct connman_element *element)
340 DBusMessageIter entry, value;
341 const char *iface, *key;
343 DBG("conn %p", conn);
348 switch (element->type) {
349 case CONNMAN_ELEMENT_TYPE_DEVICE:
350 iface = CONNMAN_DEVICE_INTERFACE;
353 case CONNMAN_ELEMENT_TYPE_NETWORK:
354 iface = CONNMAN_NETWORK_INTERFACE;
357 case CONNMAN_ELEMENT_TYPE_CONNECTION:
358 iface = CONNMAN_CONNECTION_INTERFACE;
365 signal = dbus_message_new_signal(element->path,
366 iface, "PropertyChanged");
370 dbus_message_iter_init_append(signal, &entry);
372 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
374 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
375 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
376 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
378 dbus_message_iter_close_container(&entry, &value);
380 g_dbus_send_message(conn, signal);
383 static void emit_scanning_signal(DBusConnection *conn,
384 struct connman_element *element)
387 DBusMessageIter entry, value;
388 const char *key = "Scanning";
390 DBG("conn %p", conn);
395 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
398 signal = dbus_message_new_signal(element->path,
399 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
403 dbus_message_iter_init_append(signal, &entry);
405 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
407 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
408 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
409 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
411 dbus_message_iter_close_container(&entry, &value);
413 g_dbus_send_message(conn, signal);
416 static DBusMessage *do_update(DBusConnection *conn,
417 DBusMessage *msg, void *data)
419 struct connman_element *element = data;
421 DBG("conn %p", conn);
423 if (element->enabled == FALSE)
424 return __connman_error_failed(msg);
426 if (element->driver && element->driver->update) {
427 DBG("Calling update callback");
428 if (element->driver->update(element) < 0)
429 return __connman_error_failed(msg);
433 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
436 static DBusMessage *do_enable(DBusConnection *conn,
437 DBusMessage *msg, void *data)
439 struct connman_element *element = data;
441 DBG("conn %p", conn);
443 if (element->enabled == TRUE)
444 return __connman_error_failed(msg);
446 if (element->driver && element->driver->enable) {
447 DBG("Calling enable callback");
448 if (element->driver->enable(element) < 0)
449 return __connman_error_failed(msg);
452 element->enabled = TRUE;
454 emit_enabled_signal(connection, element);
456 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
459 static DBusMessage *do_disable(DBusConnection *conn,
460 DBusMessage *msg, void *data)
462 struct connman_element *element = data;
464 DBG("conn %p", conn);
466 if (element->enabled == FALSE)
467 return __connman_error_failed(msg);
469 if (element->driver && element->driver->disable) {
470 DBG("Calling disable callback");
471 if (element->driver->disable(element) < 0)
472 return __connman_error_failed(msg);
475 element->enabled = FALSE;
477 emit_enabled_signal(connection, element);
479 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
482 static void append_networks(struct connman_element *element,
483 DBusMessageIter *entry)
485 DBusMessageIter value, iter;
486 const char *key = "Networks";
488 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
490 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
491 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
494 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
495 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
497 __connman_element_list(element, CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
499 dbus_message_iter_close_container(&value, &iter);
501 dbus_message_iter_close_container(entry, &value);
504 static DBusMessage *device_get_properties(DBusConnection *conn,
505 DBusMessage *msg, void *data)
507 struct connman_element *element = data;
509 DBusMessageIter array, dict, entry;
512 DBG("conn %p", conn);
514 reply = dbus_message_new_method_return(msg);
518 dbus_message_iter_init_append(reply, &array);
520 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
521 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
522 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
523 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
525 str = subtype2description(element->subtype);
526 if (str != NULL && element->devname != NULL) {
527 char *name = g_strdup_printf("%s (%s)", str, element->devname);
529 connman_dbus_dict_append_variant(&dict, "Name",
530 DBUS_TYPE_STRING, &name);
534 str = subtype2string(element->subtype);
536 connman_dbus_dict_append_variant(&dict, "Type",
537 DBUS_TYPE_STRING, &str);
539 str = __connman_element_policy2string(element->policy);
541 connman_dbus_dict_append_variant(&dict, "Policy",
542 DBUS_TYPE_STRING, &str);
544 connman_dbus_dict_append_variant(&dict, "Powered",
545 DBUS_TYPE_BOOLEAN, &element->enabled);
547 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI ||
548 element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIMAX ||
549 element->subtype == CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH) {
550 connman_dbus_dict_append_variant(&dict, "Scanning",
551 DBUS_TYPE_BOOLEAN, &element->scanning);
553 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
555 append_networks(element, &entry);
556 dbus_message_iter_close_container(&dict, &entry);
559 add_common_properties(element, &dict);
561 dbus_message_iter_close_container(&array, &dict);
566 static DBusMessage *device_set_property(DBusConnection *conn,
567 DBusMessage *msg, void *data)
569 struct connman_element *element = data;
570 DBusMessageIter iter, value;
573 DBG("conn %p", conn);
575 if (dbus_message_iter_init(msg, &iter) == FALSE)
576 return __connman_error_invalid_arguments(msg);
578 dbus_message_iter_get_basic(&iter, &name);
579 dbus_message_iter_next(&iter);
580 dbus_message_iter_recurse(&iter, &value);
582 if (__connman_security_check_privileges(msg) < 0)
583 return __connman_error_permission_denied(msg);
585 if (g_str_equal(name, "Powered") == TRUE) {
588 dbus_message_iter_get_basic(&value, &powered);
591 do_enable(conn, msg, element);
593 do_disable(conn, msg, element);
595 set_common_property(element, name, &value);
597 __connman_element_store(element);
599 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
602 static int parse_network_dict(DBusMessageIter *iter, const char **ssid,
603 const char **security, const char **passphrase)
605 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) {
606 DBusMessageIter entry, value;
609 dbus_message_iter_recurse(iter, &entry);
610 dbus_message_iter_get_basic(&entry, &key);
612 dbus_message_iter_next(&entry);
613 dbus_message_iter_recurse(&entry, &value);
615 switch (dbus_message_iter_get_arg_type(&value)) {
616 case DBUS_TYPE_STRING:
617 if (g_str_equal(key, "WiFi.SSID") == TRUE)
618 dbus_message_iter_get_basic(&value, ssid);
619 else if (g_str_equal(key, "WiFi.Security") == TRUE)
620 dbus_message_iter_get_basic(&value, security);
621 else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
622 dbus_message_iter_get_basic(&value, passphrase);
626 dbus_message_iter_next(iter);
632 static DBusMessage *device_create_network(DBusConnection *conn,
633 DBusMessage *msg, void *data)
635 struct connman_element *element = data;
636 struct connman_element *network;
637 DBusMessageIter iter, array;
638 const char *ssid = NULL, *security = NULL, *passphrase = NULL;
640 DBG("conn %p", conn);
642 if (element->subtype != CONNMAN_ELEMENT_SUBTYPE_WIFI)
643 return __connman_error_invalid_arguments(msg);
645 if (dbus_message_iter_init(msg, &iter) == FALSE)
646 return __connman_error_invalid_arguments(msg);
648 dbus_message_iter_recurse(&iter, &array);
649 parse_network_dict(&array, &ssid, &security, &passphrase);
651 return __connman_error_invalid_arguments(msg);
653 DBG("ssid %s security %s passphrase %s", ssid, security, passphrase);
655 network = connman_element_create(ssid);
657 network->type = CONNMAN_ELEMENT_TYPE_NETWORK;
658 network->index = element->index;
660 network->remember = TRUE;
662 connman_element_add_static_property(network, "Name",
663 DBUS_TYPE_STRING, &ssid);
665 connman_element_add_static_array_property(element, "WiFi.SSID",
666 DBUS_TYPE_BYTE, &ssid, strlen(ssid));
668 network->wifi.security = g_strdup(security);
669 network->wifi.passphrase = g_strdup(passphrase);
671 connman_element_register(network, element);
673 return g_dbus_create_reply(msg, DBUS_TYPE_OBJECT_PATH, &network->path,
677 static DBusMessage *device_remove_network(DBusConnection *conn,
678 DBusMessage *msg, void *data)
680 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
683 static DBusMessage *network_get_properties(DBusConnection *conn,
684 DBusMessage *msg, void *data)
686 struct connman_element *element = data;
688 DBusMessageIter array, dict;
691 DBG("conn %p", conn);
693 reply = dbus_message_new_method_return(msg);
697 dbus_message_iter_init_append(reply, &array);
699 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
700 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
701 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
702 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
705 connman_dbus_dict_append_variant(&dict, "Device",
706 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
708 str = __connman_element_policy2string(element->policy);
710 connman_dbus_dict_append_variant(&dict, "Policy",
711 DBUS_TYPE_STRING, &str);
713 connman_dbus_dict_append_variant(&dict, "Available",
714 DBUS_TYPE_BOOLEAN, &element->available);
716 connman_dbus_dict_append_variant(&dict, "Connected",
717 DBUS_TYPE_BOOLEAN, &element->enabled);
719 connman_dbus_dict_append_variant(&dict, "Remember",
720 DBUS_TYPE_BOOLEAN, &element->remember);
722 add_common_properties(element, &dict);
724 dbus_message_iter_close_container(&array, &dict);
729 static DBusMessage *network_set_property(DBusConnection *conn,
730 DBusMessage *msg, void *data)
732 struct connman_element *element = data;
733 DBusMessageIter iter;
734 DBusMessageIter value;
737 DBG("conn %p", conn);
739 if (dbus_message_iter_init(msg, &iter) == FALSE)
740 return __connman_error_invalid_arguments(msg);
742 dbus_message_iter_get_basic(&iter, &name);
743 dbus_message_iter_next(&iter);
744 dbus_message_iter_recurse(&iter, &value);
746 if (__connman_security_check_privileges(msg) < 0)
747 return __connman_error_permission_denied(msg);
749 if (g_str_equal(name, "Remember") == TRUE) {
750 dbus_message_iter_get_basic(&value, &element->remember);
751 } else if (g_str_equal(name, "WiFi.Passphrase") == TRUE) {
754 dbus_message_iter_get_basic(&value, &str);
755 g_free(element->wifi.passphrase);
756 element->wifi.passphrase = g_strdup(str);
758 set_common_property(element, name, &value);
760 __connman_element_store(element);
762 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
765 static DBusMessage *connection_get_properties(DBusConnection *conn,
766 DBusMessage *msg, void *data)
768 struct connman_element *element = data;
770 DBusMessageIter array, dict;
773 DBG("conn %p", conn);
775 reply = dbus_message_new_method_return(msg);
779 dbus_message_iter_init_append(reply, &array);
781 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
782 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
783 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
784 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
786 str = subtype2string(element->subtype);
788 connman_dbus_dict_append_variant(&dict, "Type",
789 DBUS_TYPE_STRING, &str);
791 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI ||
792 element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIMAX)
793 connman_dbus_dict_append_variant(&dict, "Strength",
794 DBUS_TYPE_BYTE, &element->strength);
796 connman_dbus_dict_append_variant(&dict, "Default",
797 DBUS_TYPE_BOOLEAN, &element->enabled);
799 add_common_properties(element, &dict);
801 dbus_message_iter_close_container(&array, &dict);
806 static DBusMessage *connection_set_property(DBusConnection *conn,
807 DBusMessage *msg, void *data)
809 struct connman_element *element = data;
810 DBusMessageIter iter, value;
813 DBG("conn %p", conn);
815 if (dbus_message_iter_init(msg, &iter) == FALSE)
816 return __connman_error_invalid_arguments(msg);
818 dbus_message_iter_get_basic(&iter, &name);
819 dbus_message_iter_next(&iter);
820 dbus_message_iter_recurse(&iter, &value);
822 if (__connman_security_check_privileges(msg) < 0)
823 return __connman_error_permission_denied(msg);
825 if (g_str_equal(name, "Default") == TRUE) {
828 dbus_message_iter_get_basic(&value, &enabled);
831 return do_enable(conn, msg, element);
833 return do_disable(conn, msg, element);
836 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
839 static GDBusMethodTable device_methods[] = {
840 { "GetProperties", "", "a{sv}", device_get_properties },
841 { "SetProperty", "sv", "", device_set_property },
842 { "CreateNetwork", "a{sv}", "o", device_create_network },
843 { "RemoveNetwork", "o", "", device_remove_network },
844 { "ProposeScan", "", "", do_update },
848 static GDBusMethodTable network_methods[] = {
849 { "GetProperties", "", "a{sv}", network_get_properties },
850 { "SetProperty", "sv", "", network_set_property },
851 { "Connect", "", "", do_enable },
852 { "Disconnect", "", "", do_disable },
856 static GDBusMethodTable connection_methods[] = {
857 { "GetProperties", "", "a{sv}", connection_get_properties },
858 { "SetProperty", "sv", "", connection_set_property },
862 static GDBusSignalTable element_signals[] = {
863 { "PropertyChanged", "sv" },
867 struct append_filter {
868 enum connman_element_type type;
869 DBusMessageIter *iter;
872 static gboolean append_path(GNode *node, gpointer user_data)
874 struct connman_element *element = node->data;
875 struct append_filter *filter = user_data;
877 DBG("element %p name %s", element, element->name);
879 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
882 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
883 filter->type != element->type)
886 if (filter->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
887 element->subtype == CONNMAN_ELEMENT_SUBTYPE_NETWORK)
890 dbus_message_iter_append_basic(filter->iter,
891 DBUS_TYPE_OBJECT_PATH, &element->path);
896 void __connman_element_list(struct connman_element *element,
897 enum connman_element_type type,
898 DBusMessageIter *iter)
900 struct append_filter filter = { type, iter };
905 if (element != NULL) {
906 node = g_node_find(element_root, G_PRE_ORDER,
907 G_TRAVERSE_ALL, element);
913 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
914 append_path, &filter);
918 enum connman_element_type type;
922 static gboolean count_element(GNode *node, gpointer user_data)
924 struct connman_element *element = node->data;
925 struct count_data *data = user_data;
927 DBG("element %p name %s", element, element->name);
929 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
932 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
933 data->type != element->type)
941 int __connman_element_count(struct connman_element *element,
942 enum connman_element_type type)
944 struct count_data data = { type, 0 };
949 if (element != NULL) {
950 node = g_node_find(element_root, G_PRE_ORDER,
951 G_TRAVERSE_ALL, element);
957 g_node_traverse(node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
958 count_element, &data);
963 static gint compare_priority(gconstpointer a, gconstpointer b)
965 const struct connman_driver *driver1 = a;
966 const struct connman_driver *driver2 = b;
968 return driver2->priority - driver1->priority;
971 static gboolean match_driver(struct connman_element *element,
972 struct connman_driver *driver)
974 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
977 if (element->type != driver->type &&
978 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
981 if (element->subtype == driver->subtype ||
982 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
988 static void enable_element(struct connman_element *element)
990 if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE)
993 if (element->policy != CONNMAN_ELEMENT_POLICY_AUTO)
996 if (element->driver && element->driver->enable) {
997 if (element->driver->enable(element) == 0) {
998 element->enabled = TRUE;
999 emit_enabled_signal(connection, element);
1004 static gboolean probe_driver(GNode *node, gpointer data)
1006 struct connman_element *element = node->data;
1007 struct connman_driver *driver = data;
1009 DBG("element %p name %s", element, element->name);
1011 if (!element->driver && match_driver(element, driver) == TRUE) {
1012 if (driver->probe(element) < 0)
1015 __connman_element_lock(element);
1016 element->driver = driver;
1017 __connman_element_unlock(element);
1019 enable_element(element);
1025 void __connman_driver_rescan(struct connman_driver *driver)
1027 DBG("driver %p name %s", driver, driver->name);
1032 if (element_root != NULL)
1033 g_node_traverse(element_root, G_PRE_ORDER,
1034 G_TRAVERSE_ALL, -1, probe_driver, driver);
1038 * connman_driver_register:
1039 * @driver: driver definition
1041 * Register a new driver
1043 * Returns: %0 on success
1045 int connman_driver_register(struct connman_driver *driver)
1047 DBG("driver %p name %s", driver, driver->name);
1049 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
1055 driver_list = g_slist_insert_sorted(driver_list, driver,
1058 if (started == FALSE)
1061 if (element_root != NULL)
1062 g_node_traverse(element_root, G_PRE_ORDER,
1063 G_TRAVERSE_ALL, -1, probe_driver, driver);
1068 static void disable_element(struct connman_element *element)
1070 if (element->policy != CONNMAN_ELEMENT_POLICY_AUTO)
1073 if (element->enabled == FALSE)
1076 if (element->driver && element->driver->disable) {
1077 if (element->driver->disable(element) == 0) {
1078 element->enabled = FALSE;
1079 emit_enabled_signal(connection, element);
1084 static gboolean remove_driver(GNode *node, gpointer data)
1086 struct connman_element *element = node->data;
1087 struct connman_driver *driver = data;
1089 DBG("element %p name %s", element, element->name);
1091 if (element->driver == driver) {
1092 disable_element(element);
1095 driver->remove(element);
1097 __connman_element_lock(element);
1098 element->driver = NULL;
1099 __connman_element_unlock(element);
1106 * connman_driver_unregister:
1107 * @driver: driver definition
1109 * Remove a previously registered driver
1111 void connman_driver_unregister(struct connman_driver *driver)
1113 DBG("driver %p name %s", driver, driver->name);
1115 driver_list = g_slist_remove(driver_list, driver);
1117 if (element_root != NULL)
1118 g_node_traverse(element_root, G_POST_ORDER,
1119 G_TRAVERSE_ALL, -1, remove_driver, driver);
1123 * connman_element_create:
1124 * @name: element name
1126 * Allocate a new element and assign the given #name to it. If the name
1127 * is #NULL, it will be later on created based on the element type.
1129 * Returns: a newly-allocated #connman_element structure
1131 struct connman_element *connman_element_create(const char *name)
1133 struct connman_element *element;
1135 element = g_try_new0(struct connman_element, 1);
1136 if (element == NULL)
1139 DBG("element %p", element);
1141 element->refcount = 1;
1143 element->name = g_strdup(name);
1144 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
1145 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
1146 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
1147 element->policy = CONNMAN_ELEMENT_POLICY_AUTO;
1148 element->index = -1;
1149 element->enabled = FALSE;
1154 struct connman_element *connman_element_ref(struct connman_element *element)
1156 DBG("element %p name %s refcount %d", element, element->name,
1157 g_atomic_int_get(&element->refcount) + 1);
1159 g_atomic_int_inc(&element->refcount);
1164 static void free_properties(struct connman_element *element)
1168 DBG("element %p name %s", element, element->name);
1170 __connman_element_lock(element);
1172 for (list = element->properties; list; list = list->next) {
1173 struct connman_property *property = list->data;
1175 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
1176 g_free(property->value);
1178 g_free(property->name);
1182 g_slist_free(element->properties);
1184 element->properties = NULL;
1186 __connman_element_unlock(element);
1189 void connman_element_unref(struct connman_element *element)
1191 DBG("element %p name %s refcount %d", element, element->name,
1192 g_atomic_int_get(&element->refcount) - 1);
1194 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
1195 free_properties(element);
1196 g_free(element->ipv4.address);
1197 g_free(element->ipv4.netmask);
1198 g_free(element->ipv4.gateway);
1199 g_free(element->ipv4.network);
1200 g_free(element->ipv4.broadcast);
1201 g_free(element->ipv4.nameserver);
1202 g_free(element->devname);
1203 g_free(element->devpath);
1204 g_free(element->path);
1205 g_free(element->name);
1210 int connman_element_add_static_property(struct connman_element *element,
1211 const char *name, int type, const void *value)
1213 struct connman_property *property;
1215 DBG("element %p name %s", element, element->name);
1217 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
1220 property = g_try_new0(struct connman_property, 1);
1221 if (property == NULL)
1224 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
1225 property->id = CONNMAN_PROPERTY_ID_INVALID;
1226 property->name = g_strdup(name);
1227 property->type = type;
1229 DBG("name %s type %d value %p", name, type, value);
1232 case DBUS_TYPE_STRING:
1233 property->value = g_strdup(*((const char **) value));
1235 case DBUS_TYPE_BYTE:
1236 property->value = g_try_malloc(1);
1237 if (property->value != NULL)
1238 memcpy(property->value, value, 1);
1242 __connman_element_lock(element);
1243 element->properties = g_slist_append(element->properties, property);
1244 __connman_element_unlock(element);
1249 static void emit_property_changed(DBusConnection *conn,
1250 struct connman_element *element,
1251 const char *name, int type, const void *data)
1253 DBusMessage *signal;
1254 DBusMessageIter entry, value;
1255 const char *iface, *sig;
1257 DBG("conn %p", conn);
1259 switch (element->type) {
1260 case CONNMAN_ELEMENT_TYPE_DEVICE:
1261 iface = CONNMAN_DEVICE_INTERFACE;
1263 case CONNMAN_ELEMENT_TYPE_NETWORK:
1264 iface = CONNMAN_NETWORK_INTERFACE;
1266 case CONNMAN_ELEMENT_TYPE_CONNECTION:
1267 iface = CONNMAN_CONNECTION_INTERFACE;
1273 signal = dbus_message_new_signal(element->path,
1274 iface, "PropertyChanged");
1278 dbus_message_iter_init_append(signal, &entry);
1280 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name);
1283 case DBUS_TYPE_STRING:
1284 sig = DBUS_TYPE_STRING_AS_STRING;
1286 case DBUS_TYPE_BYTE:
1287 sig = DBUS_TYPE_BYTE_AS_STRING;
1290 sig = DBUS_TYPE_VARIANT_AS_STRING;
1294 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1296 dbus_message_iter_append_basic(&value, type, data);
1297 dbus_message_iter_close_container(&entry, &value);
1299 g_dbus_send_message(conn, signal);
1302 int connman_element_set_static_property(struct connman_element *element,
1303 const char *name, int type, const void *value)
1307 DBG("element %p name %s", element, element->name);
1309 if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE)
1312 __connman_element_lock(element);
1314 for (list = element->properties; list; list = list->next) {
1315 struct connman_property *property = list->data;
1317 if (g_str_equal(property->name, name) == FALSE)
1320 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1323 property->type = type;
1324 g_free(property->value);
1327 case DBUS_TYPE_STRING:
1328 property->value = g_strdup(*((const char **) value));
1330 case DBUS_TYPE_BYTE:
1331 property->value = g_try_malloc(1);
1332 if (property->value != NULL)
1333 memcpy(property->value, value, 1);
1338 __connman_element_unlock(element);
1340 emit_property_changed(connection, element, name, type, value);
1345 int connman_element_add_static_array_property(struct connman_element *element,
1346 const char *name, int type, const void *value, int len)
1348 struct connman_property *property;
1350 DBG("element %p name %s", element, element->name);
1352 if (type != DBUS_TYPE_BYTE)
1355 property = g_try_new0(struct connman_property, 1);
1356 if (property == NULL)
1359 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
1360 property->id = CONNMAN_PROPERTY_ID_INVALID;
1361 property->name = g_strdup(name);
1362 property->type = DBUS_TYPE_ARRAY;
1363 property->subtype = type;
1365 DBG("name %s type %d value %p", name, type, value);
1368 case DBUS_TYPE_BYTE:
1369 property->value = g_try_malloc(len);
1370 if (property->value != NULL) {
1371 memcpy(property->value,
1372 *((const unsigned char **) value), len);
1373 property->size = len;
1378 __connman_element_lock(element);
1379 element->properties = g_slist_append(element->properties, property);
1380 __connman_element_unlock(element);
1385 static void *get_reference_value(struct connman_element *element,
1386 enum connman_property_id id)
1390 DBG("element %p name %s", element, element->name);
1392 for (list = element->properties; list; list = list->next) {
1393 struct connman_property *property = list->data;
1395 if (property->id != id)
1398 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
1399 return property->value;
1402 if (element->parent == NULL)
1405 return get_reference_value(element->parent, id);
1408 static void set_reference_properties(struct connman_element *element)
1412 DBG("element %p name %s", element, element->name);
1414 for (list = element->properties; list; list = list->next) {
1415 struct connman_property *property = list->data;
1417 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
1420 property->value = get_reference_value(element->parent,
1425 static struct connman_property *create_property(struct connman_element *element,
1426 enum connman_property_id id)
1428 struct connman_property *property;
1431 DBG("element %p name %s", element, element->name);
1433 __connman_element_lock(element);
1435 for (list = element->properties; list; list = list->next) {
1436 property = list->data;
1438 if (property->id == id)
1442 property = g_try_new0(struct connman_property, 1);
1443 if (property == NULL)
1446 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
1448 property->name = g_strdup(propid2name(id));
1449 property->type = propid2type(id);
1451 if (property->name == NULL) {
1457 element->properties = g_slist_append(element->properties, property);
1460 __connman_element_unlock(element);
1465 static void create_default_properties(struct connman_element *element)
1467 struct connman_property *property;
1470 DBG("element %p name %s", element, element->name);
1472 for (i = 0; propid_table[i].name; i++) {
1473 DBG("property %s", propid_table[i].name);
1475 property = create_property(element, propid_table[i].id);
1477 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
1479 if (propid_table[i].type != DBUS_TYPE_STRING)
1482 if (propid_table[i].value)
1483 property->value = g_strdup(propid_table[i].value);
1485 property->value = g_strdup("");
1489 static int define_properties_valist(struct connman_element *element,
1492 enum connman_property_id id;
1494 DBG("element %p name %s", element, element->name);
1496 id = va_arg(args, enum connman_property_id);
1498 while (id != CONNMAN_PROPERTY_ID_INVALID) {
1500 DBG("property %d", id);
1502 create_property(element, id);
1504 id = va_arg(args, enum connman_property_id);
1511 * connman_element_define_properties:
1512 * @element: an element
1513 * @varargs: list of property identifiers
1515 * Define the valid properties for an element.
1517 * Returns: %0 on success
1519 int connman_element_define_properties(struct connman_element *element, ...)
1524 DBG("element %p name %s", element, element->name);
1526 va_start(args, element);
1528 err = define_properties_valist(element, args);
1535 int connman_element_create_property(struct connman_element *element,
1536 const char *name, int type)
1541 int connman_element_set_property(struct connman_element *element,
1542 enum connman_property_id id, const void *value)
1545 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1546 __connman_element_lock(element);
1547 g_free(element->ipv4.address);
1548 element->ipv4.address = g_strdup(*((const char **) value));
1549 __connman_element_unlock(element);
1551 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1552 __connman_element_lock(element);
1553 g_free(element->ipv4.netmask);
1554 element->ipv4.netmask = g_strdup(*((const char **) value));
1555 __connman_element_unlock(element);
1557 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1558 __connman_element_lock(element);
1559 g_free(element->ipv4.gateway);
1560 element->ipv4.gateway = g_strdup(*((const char **) value));
1561 __connman_element_unlock(element);
1563 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1564 __connman_element_lock(element);
1565 g_free(element->ipv4.broadcast);
1566 element->ipv4.broadcast = g_strdup(*((const char **) value));
1567 __connman_element_unlock(element);
1569 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1570 __connman_element_lock(element);
1571 g_free(element->ipv4.nameserver);
1572 element->ipv4.nameserver = g_strdup(*((const char **) value));
1573 __connman_element_unlock(element);
1575 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1576 __connman_element_lock(element);
1577 g_free(element->wifi.security);
1578 element->wifi.security = g_strdup(*((const char **) value));
1579 __connman_element_unlock(element);
1581 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1582 __connman_element_lock(element);
1583 g_free(element->wifi.passphrase);
1584 element->wifi.passphrase = g_strdup(*((const char **) value));
1585 __connman_element_unlock(element);
1594 int connman_element_get_value(struct connman_element *element,
1595 enum connman_property_id id, void *value)
1597 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1601 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1602 if (element->ipv4.address == NULL)
1603 return connman_element_get_value(element->parent,
1605 __connman_element_lock(element);
1606 *((char **) value) = element->ipv4.address;
1607 __connman_element_unlock(element);
1609 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1610 if (element->ipv4.netmask == NULL)
1611 return connman_element_get_value(element->parent,
1613 __connman_element_lock(element);
1614 *((char **) value) = element->ipv4.netmask;
1615 __connman_element_unlock(element);
1617 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1618 if (element->ipv4.gateway == NULL)
1619 return connman_element_get_value(element->parent,
1621 __connman_element_lock(element);
1622 *((char **) value) = element->ipv4.gateway;
1623 __connman_element_unlock(element);
1625 case CONNMAN_PROPERTY_ID_IPV4_BROADCAST:
1626 if (element->ipv4.broadcast == NULL)
1627 return connman_element_get_value(element->parent,
1629 __connman_element_lock(element);
1630 *((char **) value) = element->ipv4.broadcast;
1631 __connman_element_unlock(element);
1633 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1634 if (element->ipv4.nameserver == NULL)
1635 return connman_element_get_value(element->parent,
1637 __connman_element_lock(element);
1638 *((char **) value) = element->ipv4.nameserver;
1639 __connman_element_unlock(element);
1641 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1642 if (element->wifi.security == NULL)
1643 return connman_element_get_value(element->parent,
1645 __connman_element_lock(element);
1646 *((char **) value) = element->wifi.security;
1647 __connman_element_unlock(element);
1649 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1650 if (element->wifi.passphrase == NULL)
1651 return connman_element_get_value(element->parent,
1653 __connman_element_lock(element);
1654 *((char **) value) = element->wifi.passphrase;
1655 __connman_element_unlock(element);
1664 gboolean connman_element_get_static_property(struct connman_element *element,
1665 const char *name, void *value)
1668 gboolean found = FALSE;
1670 DBG("element %p name %s", element, element->name);
1672 __connman_element_lock(element);
1674 for (list = element->properties; list; list = list->next) {
1675 struct connman_property *property = list->data;
1677 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1680 if (g_str_equal(property->name, name) == TRUE) {
1681 switch (property->type) {
1682 case DBUS_TYPE_STRING:
1683 *((char **) value) = property->value;
1691 __connman_element_unlock(element);
1696 gboolean connman_element_get_static_array_property(struct connman_element *element,
1697 const char *name, void *value, int *len)
1700 gboolean found = FALSE;
1702 DBG("element %p name %s", element, element->name);
1704 __connman_element_lock(element);
1706 for (list = element->properties; list; list = list->next) {
1707 struct connman_property *property = list->data;
1709 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1712 if (g_str_equal(property->name, name) == TRUE) {
1713 *((char **) value) = property->value;
1714 *len = property->size;
1720 __connman_element_unlock(element);
1725 gboolean connman_element_match_static_property(struct connman_element *element,
1726 const char *name, const void *value)
1729 gboolean result = FALSE;
1731 DBG("element %p name %s", element, element->name);
1733 __connman_element_lock(element);
1735 for (list = element->properties; list; list = list->next) {
1736 struct connman_property *property = list->data;
1738 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1741 if (g_str_equal(property->name, name) == FALSE)
1744 if (property->type == DBUS_TYPE_STRING)
1745 result = g_str_equal(property->value,
1746 *((const char **) value));
1752 __connman_element_unlock(element);
1757 static void append_devices(DBusMessageIter *entry)
1759 DBusMessageIter value, iter;
1760 const char *key = "Devices";
1762 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1764 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1765 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1768 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1769 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1770 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
1771 dbus_message_iter_close_container(&value, &iter);
1773 dbus_message_iter_close_container(entry, &value);
1776 static void emit_devices_signal(DBusConnection *conn)
1778 DBusMessage *signal;
1779 DBusMessageIter entry;
1781 DBG("conn %p", conn);
1783 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1784 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1788 dbus_message_iter_init_append(signal, &entry);
1790 append_devices(&entry);
1792 g_dbus_send_message(conn, signal);
1795 static void emit_networks_signal(DBusConnection *conn,
1796 struct connman_element *device)
1798 DBusMessage *signal;
1799 DBusMessageIter entry;
1801 DBG("conn %p", conn);
1806 signal = dbus_message_new_signal(device->path,
1807 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1811 dbus_message_iter_init_append(signal, &entry);
1813 append_networks(device, &entry);
1815 g_dbus_send_message(conn, signal);
1818 static void append_connections(DBusMessageIter *entry)
1820 DBusMessageIter value, iter;
1821 const char *key = "Connections";
1823 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1825 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1826 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1829 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1830 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1831 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1832 dbus_message_iter_close_container(&value, &iter);
1834 dbus_message_iter_close_container(entry, &value);
1837 static void emit_connections_signal(DBusConnection *conn)
1839 DBusMessage *signal;
1840 DBusMessageIter entry;
1842 DBG("conn %p", conn);
1844 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1845 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1849 dbus_message_iter_init_append(signal, &entry);
1851 append_connections(&entry);
1853 g_dbus_send_message(conn, signal);
1856 static void append_state(DBusMessageIter *entry, const char *state)
1858 DBusMessageIter value;
1859 const char *key = "State";
1861 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1863 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1864 DBUS_TYPE_STRING_AS_STRING, &value);
1865 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1866 dbus_message_iter_close_container(entry, &value);
1869 static void emit_state_change(DBusConnection *conn, const char *state)
1871 DBusMessage *signal;
1872 DBusMessageIter entry;
1874 DBG("conn %p", conn);
1876 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1877 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1881 dbus_message_iter_init_append(signal, &entry);
1883 append_state(&entry, state);
1885 g_dbus_send_message(conn, signal);
1888 static void set_signal_strength(struct connman_element *connection)
1890 struct connman_element *element = connection;
1892 while (element != NULL) {
1893 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1894 connection->strength = element->strength;
1898 element = element->parent;
1902 static void probe_element(struct connman_element *element)
1906 DBG("element %p name %s", element, element->name);
1908 for (list = driver_list; list; list = list->next) {
1909 struct connman_driver *driver = list->data;
1911 if (match_driver(element, driver) == FALSE)
1914 DBG("driver %p name %s", driver, driver->name);
1916 if (driver->probe(element) == 0) {
1917 __connman_element_lock(element);
1918 element->driver = driver;
1919 __connman_element_unlock(element);
1921 enable_element(element);
1927 static void register_element(gpointer data, gpointer user_data)
1929 struct connman_element *element = data;
1930 const gchar *basepath;
1933 __connman_element_lock(element);
1935 if (element->parent) {
1936 node = g_node_find(element_root, G_PRE_ORDER,
1937 G_TRAVERSE_ALL, element->parent);
1938 basepath = element->parent->path;
1940 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1941 element->subtype = element->parent->subtype;
1943 element->parent = element_root->data;
1945 node = element_root;
1949 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1951 set_reference_properties(element);
1953 __connman_element_unlock(element);
1955 DBG("element %p path %s", element, element->path);
1957 __connman_element_load(element);
1959 g_node_append_data(node, element);
1961 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
1962 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
1963 if (g_dbus_register_interface(connection, element->path,
1964 CONNMAN_DEVICE_INTERFACE,
1965 device_methods, element_signals,
1966 NULL, element, NULL) == FALSE)
1967 connman_error("Failed to register %s device",
1970 emit_devices_signal(connection);
1973 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1974 if (g_dbus_register_interface(connection, element->path,
1975 CONNMAN_NETWORK_INTERFACE,
1976 network_methods, element_signals,
1977 NULL, element, NULL) == FALSE)
1978 connman_error("Failed to register %s network",
1981 emit_networks_signal(connection, element->parent);
1984 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1985 if (g_dbus_register_interface(connection, element->path,
1986 CONNMAN_CONNECTION_INTERFACE,
1987 connection_methods, element_signals,
1988 NULL, element, NULL) == FALSE)
1989 connman_error("Failed to register %s connection",
1992 set_signal_strength(element);
1993 emit_connections_signal(connection);
1994 emit_state_change(connection, "online");
1998 __connman_element_store(element);
2000 if (started == FALSE)
2003 probe_element(element);
2007 * connman_element_register:
2008 * @element: the element to register
2009 * @parent: the parent to register the element with
2011 * Register an element with the core. It will be register under the given
2012 * parent of if %NULL is provided under the root element.
2014 * Returns: %0 on success
2016 int connman_element_register(struct connman_element *element,
2017 struct connman_element *parent)
2019 DBG("element %p name %s parent %p", element, element->name, parent);
2021 if (element->devname == NULL)
2022 element->devname = g_strdup(element->name);
2024 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
2025 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
2026 if (g_pattern_match_simple(device_filter,
2027 element->devname) == FALSE) {
2028 DBG("ignoring %s [%s] device", element->name,
2034 if (connman_element_ref(element) == NULL)
2037 __connman_element_lock(element);
2039 if (element->name == NULL) {
2040 element->name = g_strdup(type2string(element->type));
2041 if (element->name == NULL) {
2042 __connman_element_unlock(element);
2047 element->parent = parent;
2049 __connman_element_unlock(element);
2051 register_element(element, NULL);
2056 static gboolean remove_element(GNode *node, gpointer user_data)
2058 struct connman_element *element = node->data;
2059 struct connman_element *root = user_data;
2061 DBG("element %p name %s", element, element->name);
2063 if (element == root)
2066 if (element->driver) {
2067 disable_element(element);
2069 if (element->driver->remove)
2070 element->driver->remove(element);
2072 __connman_element_lock(element);
2073 element->driver = NULL;
2074 __connman_element_unlock(element);
2078 g_node_unlink(node);
2079 g_node_destroy(node);
2082 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
2083 if (__connman_element_count(NULL,
2084 CONNMAN_ELEMENT_TYPE_CONNECTION) == 0)
2085 emit_state_change(connection, "offline");
2086 emit_connections_signal(connection);
2088 g_dbus_unregister_interface(connection, element->path,
2089 CONNMAN_CONNECTION_INTERFACE);
2092 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
2093 emit_networks_signal(connection, element->parent);
2095 g_dbus_unregister_interface(connection, element->path,
2096 CONNMAN_NETWORK_INTERFACE);
2099 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
2100 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
2101 emit_devices_signal(connection);
2103 g_dbus_unregister_interface(connection, element->path,
2104 CONNMAN_DEVICE_INTERFACE);
2107 connman_element_unref(element);
2112 void connman_element_unregister(struct connman_element *element)
2116 DBG("element %p name %s", element, element->name);
2118 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
2121 g_node_traverse(node, G_POST_ORDER,
2122 G_TRAVERSE_ALL, -1, remove_element, NULL);
2125 void connman_element_unregister_children(struct connman_element *element)
2129 DBG("element %p name %s", element, element->name);
2131 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
2134 g_node_traverse(node, G_POST_ORDER,
2135 G_TRAVERSE_ALL, -1, remove_element, element);
2138 static gboolean update_element(GNode *node, gpointer user_data)
2140 struct connman_element *element = node->data;
2141 struct connman_element *root = user_data;
2143 DBG("element %p name %s", element, element->name);
2145 if (element->driver && element->driver->update)
2146 element->driver->update(element);
2148 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION &&
2149 root->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
2150 if (element->strength != root->strength) {
2151 element->strength = root->strength;
2152 emit_property_changed(connection, element, "Strength",
2153 DBUS_TYPE_BYTE, &element->strength);
2160 void connman_element_update(struct connman_element *element)
2164 DBG("element %p name %s", element, element->name);
2166 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
2169 g_node_traverse(node, G_PRE_ORDER,
2170 G_TRAVERSE_ALL, -1, update_element, element);
2173 int connman_element_set_enabled(struct connman_element *element,
2176 if (element->enabled == enabled)
2179 element->enabled = enabled;
2181 emit_enabled_signal(connection, element);
2186 int connman_element_set_scanning(struct connman_element *element,
2189 if (element->scanning == scanning)
2192 element->scanning = scanning;
2194 emit_scanning_signal(connection, element);
2199 int __connman_element_init(DBusConnection *conn, const char *device)
2201 struct connman_element *element;
2203 DBG("conn %p", conn);
2205 connection = dbus_connection_ref(conn);
2206 if (connection == NULL)
2209 device_filter = g_strdup(device);
2211 element = connman_element_create("root");
2213 element->path = g_strdup("/");
2214 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
2216 create_default_properties(element);
2218 element_root = g_node_new(element);
2220 __connman_device_init();
2221 __connman_network_init();
2226 static gboolean probe_node(GNode *node, gpointer data)
2228 struct connman_element *element = node->data;
2230 DBG("element %p name %s", element, element->name);
2232 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
2235 if (element->driver)
2238 probe_element(element);
2243 void __connman_element_start(void)
2247 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
2253 static gboolean free_driver(GNode *node, gpointer data)
2255 struct connman_element *element = node->data;
2257 DBG("element %p name %s", element, element->name);
2259 if (element->driver) {
2260 disable_element(element);
2262 if (element->driver->remove)
2263 element->driver->remove(element);
2265 __connman_element_lock(element);
2266 element->driver = NULL;
2267 __connman_element_unlock(element);
2273 static gboolean free_node(GNode *node, gpointer data)
2275 struct connman_element *element = node->data;
2277 DBG("element %p name %s", element, element->name);
2279 if (g_node_depth(node) > 1)
2280 connman_element_unregister(element);
2285 void __connman_element_cleanup(void)
2289 __connman_network_cleanup();
2290 __connman_device_cleanup();
2292 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2295 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
2298 g_node_destroy(element_root);
2299 element_root = NULL;
2301 g_free(device_filter);
2303 dbus_connection_unref(connection);