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
34 static DBusConnection *connection;
36 static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
37 static GNode *element_root = NULL;
39 static GSList *driver_list = NULL;
41 static GThreadPool *thread_register = NULL;
42 static GThreadPool *thread_unregister = NULL;
43 static GThreadPool *thread_unregister_children = NULL;
45 static gchar *device_filter = NULL;
48 enum connman_property_id id;
53 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
54 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
55 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
56 DBUS_TYPE_STRING, "IPv4.Address" },
57 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
58 DBUS_TYPE_STRING, "IPv4.Netmask" },
59 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
60 DBUS_TYPE_STRING, "IPv4.Gateway" },
61 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
62 DBUS_TYPE_STRING, "IPv4.Nameserver" },
66 static int propid2type(enum connman_property_id id)
70 for (i = 0; propid_table[i].name; i++) {
71 if (propid_table[i].id == id)
72 return propid_table[i].type;
75 return DBUS_TYPE_INVALID;
78 static const char *propid2name(enum connman_property_id id)
82 for (i = 0; propid_table[i].name; i++) {
83 if (propid_table[i].id == id)
84 return propid_table[i].name;
90 static const char *type2string(enum connman_element_type type)
93 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
95 case CONNMAN_ELEMENT_TYPE_ROOT:
97 case CONNMAN_ELEMENT_TYPE_DEVICE:
99 case CONNMAN_ELEMENT_TYPE_NETWORK:
101 case CONNMAN_ELEMENT_TYPE_IPV4:
103 case CONNMAN_ELEMENT_TYPE_IPV6:
105 case CONNMAN_ELEMENT_TYPE_DHCP:
107 case CONNMAN_ELEMENT_TYPE_BOOTP:
109 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
111 case CONNMAN_ELEMENT_TYPE_RESOLVER:
113 case CONNMAN_ELEMENT_TYPE_INTERNET:
120 static const char *subtype2string(enum connman_element_subtype type)
123 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
125 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
127 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
129 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
131 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
133 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
135 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
142 static void append_entry(DBusMessageIter *dict,
143 const char *key, int type, void *val)
145 DBusMessageIter entry, value;
146 const char *signature;
148 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
151 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
154 case DBUS_TYPE_BOOLEAN:
155 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
157 case DBUS_TYPE_STRING:
158 signature = DBUS_TYPE_STRING_AS_STRING;
160 case DBUS_TYPE_UINT16:
161 signature = DBUS_TYPE_UINT16_AS_STRING;
163 case DBUS_TYPE_UINT32:
164 signature = DBUS_TYPE_UINT32_AS_STRING;
166 case DBUS_TYPE_OBJECT_PATH:
167 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
170 signature = DBUS_TYPE_VARIANT_AS_STRING;
174 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
176 dbus_message_iter_append_basic(&value, type, val);
177 dbus_message_iter_close_container(&entry, &value);
179 dbus_message_iter_close_container(dict, &entry);
182 static void append_property(DBusMessageIter *dict,
183 struct connman_property *property)
185 if (property->value == NULL)
188 append_entry(dict, property->name, property->type, &property->value);
191 static DBusMessage *get_properties(DBusConnection *conn,
192 DBusMessage *msg, void *data)
194 struct connman_element *element = data;
197 DBusMessageIter array, dict;
200 DBG("conn %p", conn);
202 reply = dbus_message_new_method_return(msg);
206 dbus_message_iter_init_append(reply, &array);
208 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
209 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
210 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
211 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
213 if (element->parent != NULL &&
214 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
215 append_entry(&dict, "Parent",
216 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
219 str = type2string(element->type);
221 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
222 str = subtype2string(element->subtype);
224 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
226 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
228 if (element->priority > 0)
229 append_entry(&dict, "Priority",
230 DBUS_TYPE_UINT16, &element->priority);
232 if (element->network.identifier != NULL)
233 append_entry(&dict, "Identifier",
234 DBUS_TYPE_STRING, &element->network.identifier);
236 if (element->ipv4.address != NULL)
237 append_entry(&dict, "IPv4.Address",
238 DBUS_TYPE_STRING, &element->ipv4.address);
239 if (element->ipv4.netmask != NULL)
240 append_entry(&dict, "IPv4.Netmask",
241 DBUS_TYPE_STRING, &element->ipv4.netmask);
242 if (element->ipv4.gateway != NULL)
243 append_entry(&dict, "IPv4.Gateway",
244 DBUS_TYPE_STRING, &element->ipv4.gateway);
246 connman_element_lock(element);
248 for (list = element->properties; list; list = list->next) {
249 struct connman_property *property = list->data;
251 append_property(&dict, property);
254 connman_element_unlock(element);
256 dbus_message_iter_close_container(&array, &dict);
261 static DBusMessage *set_property(DBusConnection *conn,
262 DBusMessage *msg, void *data)
264 struct connman_element *element = data;
265 DBusMessageIter iter;
266 DBusMessageIter value;
270 DBG("conn %p", conn);
272 if (dbus_message_iter_init(msg, &iter) == FALSE)
273 return __connman_error_invalid_arguments(msg);
275 dbus_message_iter_get_basic(&iter, &name);
276 dbus_message_iter_next(&iter);
277 dbus_message_iter_recurse(&iter, &value);
279 if (__connman_security_check_privileges(msg) < 0)
280 return __connman_error_permission_denied(msg);
282 connman_element_lock(element);
284 for (list = element->properties; list; list = list->next) {
285 struct connman_property *property = list->data;
288 if (g_str_equal(property->name, name) == FALSE)
291 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
294 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
296 if (property->type == DBUS_TYPE_STRING) {
297 dbus_message_iter_get_basic(&value, &str);
298 g_free(property->value);
299 property->value = g_strdup(str);
301 property->value = NULL;
304 connman_element_unlock(element);
306 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
309 static DBusMessage *clear_property(DBusConnection *conn,
310 DBusMessage *msg, void *data)
312 struct connman_element *element = data;
316 DBG("conn %p", conn);
318 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
319 DBUS_TYPE_INVALID) == FALSE)
320 return __connman_error_invalid_arguments(msg);
322 if (__connman_security_check_privileges(msg) < 0)
323 return __connman_error_permission_denied(msg);
325 connman_element_lock(element);
327 for (list = element->properties; list; list = list->next) {
328 struct connman_property *property = list->data;
330 if (g_str_equal(property->name, name) == FALSE)
333 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
336 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
339 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
341 if (property->type == DBUS_TYPE_STRING)
342 g_free(property->value);
344 property->value = NULL;
347 connman_element_unlock(element);
349 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
352 static DBusMessage *do_update(DBusConnection *conn,
353 DBusMessage *msg, void *data)
355 struct connman_element *element = data;
357 DBG("conn %p", conn);
359 if (element->enabled == FALSE)
360 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
362 if (element->driver && element->driver->update) {
363 DBG("Calling update callback");
364 element->driver->update(element);
367 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
370 static DBusMessage *do_enable(DBusConnection *conn,
371 DBusMessage *msg, void *data)
373 struct connman_element *element = data;
375 DBG("conn %p", conn);
377 if (element->enabled == TRUE)
378 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
380 if (element->driver && element->driver->enable) {
381 DBG("Calling enable callback");
382 element->driver->enable(element);
385 element->enabled = TRUE;
387 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
388 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
389 DBUS_TYPE_OBJECT_PATH, &element->path,
392 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
395 static DBusMessage *do_disable(DBusConnection *conn,
396 DBusMessage *msg, void *data)
398 struct connman_element *element = data;
400 DBG("conn %p", conn);
402 if (element->enabled == FALSE)
403 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
405 if (element->driver && element->driver->disable) {
406 DBG("Calling disable callback");
407 element->driver->disable(element);
410 element->enabled = FALSE;
412 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
413 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
414 DBUS_TYPE_OBJECT_PATH, &element->path,
417 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
420 static GDBusMethodTable element_methods[] = {
421 { "GetProperties", "", "a{sv}", get_properties },
422 { "SetProperty", "sv", "", set_property },
423 { "ClearProperty", "s", "", clear_property },
424 { "Update", "", "", do_update },
425 { "Enable", "", "", do_enable },
426 { "Disable", "", "", do_disable },
430 static GDBusSignalTable element_signals[] = {
431 { "PropertyChanged", "sv" },
435 struct append_filter {
436 enum connman_element_type type;
437 DBusMessageIter *iter;
440 static gboolean append_path(GNode *node, gpointer data)
442 struct connman_element *element = node->data;
443 struct append_filter *filter = data;
445 DBG("element %p name %s", element, element->name);
447 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
450 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
451 filter->type != element->type)
454 dbus_message_iter_append_basic(filter->iter,
455 DBUS_TYPE_OBJECT_PATH, &element->path);
460 void __connman_element_list(enum connman_element_type type,
461 DBusMessageIter *iter)
463 struct append_filter filter = { type, iter };
467 g_static_rw_lock_reader_lock(&element_lock);
468 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
469 append_path, &filter);
470 g_static_rw_lock_reader_unlock(&element_lock);
473 static gint compare_priority(gconstpointer a, gconstpointer b)
475 const struct connman_driver *driver1 = a;
476 const struct connman_driver *driver2 = b;
478 return driver2->priority - driver1->priority;
481 static gboolean match_driver(struct connman_element *element,
482 struct connman_driver *driver)
484 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
487 if (element->type != driver->type &&
488 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
491 if (element->subtype == driver->subtype ||
492 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
498 static gboolean probe_driver(GNode *node, gpointer data)
500 struct connman_element *element = node->data;
501 struct connman_driver *driver = data;
503 DBG("element %p name %s", element, element->name);
505 if (!element->driver && match_driver(element, driver) == TRUE) {
506 if (driver->probe(element) < 0)
509 connman_element_lock(element);
510 element->driver = driver;
511 connman_element_unlock(element);
518 * connman_driver_register:
519 * @driver: driver definition
521 * Register a new driver
523 * Returns: %0 on success
525 int connman_driver_register(struct connman_driver *driver)
527 DBG("driver %p name %s", driver, driver->name);
529 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
535 g_static_rw_lock_writer_lock(&element_lock);
537 driver_list = g_slist_insert_sorted(driver_list, driver,
540 if (element_root != NULL)
541 g_node_traverse(element_root, G_PRE_ORDER,
542 G_TRAVERSE_ALL, -1, probe_driver, driver);
544 g_static_rw_lock_writer_unlock(&element_lock);
549 static gboolean remove_driver(GNode *node, gpointer data)
551 struct connman_element *element = node->data;
552 struct connman_driver *driver = data;
554 DBG("element %p name %s", element, element->name);
556 if (element->driver == driver) {
558 driver->remove(element);
560 connman_element_lock(element);
561 element->driver = NULL;
562 connman_element_unlock(element);
569 * connman_driver_unregister:
570 * @driver: driver definition
572 * Remove a previously registered driver
574 void connman_driver_unregister(struct connman_driver *driver)
576 DBG("driver %p name %s", driver, driver->name);
578 g_static_rw_lock_writer_lock(&element_lock);
580 driver_list = g_slist_remove(driver_list, driver);
582 if (element_root != NULL)
583 g_node_traverse(element_root, G_POST_ORDER,
584 G_TRAVERSE_ALL, -1, remove_driver, driver);
586 g_static_rw_lock_writer_unlock(&element_lock);
590 * connman_element_create:
591 * @name: element name
593 * Allocate a new element and assign the given #name to it. If the name
594 * is #NULL, it will be later on created based on the element type.
596 * Returns: a newly-allocated #connman_element structure
598 struct connman_element *connman_element_create(const char *name)
600 struct connman_element *element;
602 element = g_try_new0(struct connman_element, 1);
606 DBG("element %p", element);
608 element->refcount = 1;
610 g_static_mutex_init(&element->mutex);
612 element->name = g_strdup(name);
613 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
614 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
615 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
617 element->enabled = FALSE;
622 struct connman_element *connman_element_ref(struct connman_element *element)
624 DBG("element %p name %s refcount %d", element, element->name,
625 g_atomic_int_get(&element->refcount) + 1);
627 g_atomic_int_inc(&element->refcount);
632 static void free_properties(struct connman_element *element)
636 DBG("element %p name %s", element, element->name);
638 connman_element_lock(element);
640 for (list = element->properties; list; list = list->next) {
641 struct connman_property *property = list->data;
643 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
644 if (property->type == DBUS_TYPE_STRING)
645 g_free(property->value);
651 g_slist_free(element->properties);
653 element->properties = NULL;
655 connman_element_unlock(element);
658 void connman_element_unref(struct connman_element *element)
660 DBG("element %p name %s refcount %d", element, element->name,
661 g_atomic_int_get(&element->refcount) - 1);
663 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
664 free_properties(element);
665 g_free(element->ipv4.address);
666 g_free(element->ipv4.netmask);
667 g_free(element->ipv4.gateway);
668 g_free(element->ipv4.network);
669 g_free(element->ipv4.broadcast);
670 g_free(element->ipv4.nameserver);
671 g_free(element->network.identifier);
672 g_free(element->path);
673 g_free(element->name);
678 int connman_element_add_static_property(struct connman_element *element,
679 const char *name, int type, const void *value)
681 struct connman_property *property;
683 DBG("element %p name %s", element, element->name);
685 if (type != DBUS_TYPE_STRING)
688 property = g_try_new0(struct connman_property, 1);
689 if (property == NULL)
692 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
693 property->id = CONNMAN_PROPERTY_ID_INVALID;
694 property->name = g_strdup(name);
695 property->type = type;
697 DBG("name %s type %d value %p", name, type, value);
700 case DBUS_TYPE_STRING:
701 property->value = g_strdup(*((const char **) value));
705 connman_element_lock(element);
706 element->properties = g_slist_append(element->properties, property);
707 connman_element_unlock(element);
712 static void *get_reference_value(struct connman_element *element,
713 enum connman_property_id id)
717 DBG("element %p name %s", element, element->name);
719 for (list = element->properties; list; list = list->next) {
720 struct connman_property *property = list->data;
722 if (property->id != id)
725 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
726 return property->value;
729 if (element->parent == NULL)
732 return get_reference_value(element->parent, id);
735 static void set_reference_properties(struct connman_element *element)
739 DBG("element %p name %s", element, element->name);
741 for (list = element->properties; list; list = list->next) {
742 struct connman_property *property = list->data;
744 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
747 property->value = get_reference_value(element->parent,
752 static struct connman_property *create_property(struct connman_element *element,
753 enum connman_property_id id)
755 struct connman_property *property;
758 DBG("element %p name %s", element, element->name);
760 connman_element_lock(element);
762 for (list = element->properties; list; list = list->next) {
763 property = list->data;
765 if (property->id == id)
769 property = g_try_new0(struct connman_property, 1);
770 if (property == NULL)
773 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
775 property->name = g_strdup(propid2name(id));
776 property->type = propid2type(id);
778 if (property->name == NULL) {
784 element->properties = g_slist_append(element->properties, property);
787 connman_element_unlock(element);
792 static void create_default_properties(struct connman_element *element)
794 struct connman_property *property;
797 DBG("element %p name %s", element, element->name);
799 for (i = 0; propid_table[i].name; i++) {
800 DBG("property %s", propid_table[i].name);
802 property = create_property(element, propid_table[i].id);
804 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
806 if (propid_table[i].type != DBUS_TYPE_STRING)
809 if (propid_table[i].value)
810 property->value = g_strdup(propid_table[i].value);
812 property->value = g_strdup("");
816 static int define_properties_valist(struct connman_element *element,
819 enum connman_property_id id;
821 DBG("element %p name %s", element, element->name);
823 id = va_arg(args, enum connman_property_id);
825 while (id != CONNMAN_PROPERTY_ID_INVALID) {
827 DBG("property %d", id);
829 create_property(element, id);
831 id = va_arg(args, enum connman_property_id);
838 * connman_element_define_properties:
839 * @element: an element
840 * @varargs: list of property identifiers
842 * Define the valid properties for an element.
844 * Returns: %0 on success
846 int connman_element_define_properties(struct connman_element *element, ...)
851 DBG("element %p name %s", element, element->name);
853 va_start(args, element);
855 err = define_properties_valist(element, args);
862 int connman_element_create_property(struct connman_element *element,
863 const char *name, int type)
868 int connman_element_set_property(struct connman_element *element,
869 enum connman_property_id id, const void *value)
872 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
873 connman_element_lock(element);
874 g_free(element->ipv4.address);
875 element->ipv4.address = g_strdup(*((const char **) value));
876 connman_element_unlock(element);
878 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
879 connman_element_lock(element);
880 g_free(element->ipv4.netmask);
881 element->ipv4.netmask = g_strdup(*((const char **) value));
882 connman_element_unlock(element);
884 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
885 connman_element_lock(element);
886 g_free(element->ipv4.gateway);
887 element->ipv4.gateway = g_strdup(*((const char **) value));
888 connman_element_unlock(element);
890 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
891 connman_element_lock(element);
892 g_free(element->ipv4.nameserver);
893 element->ipv4.nameserver = g_strdup(*((const char **) value));
894 connman_element_unlock(element);
900 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
901 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
902 DBUS_TYPE_OBJECT_PATH, &element->path,
908 int connman_element_get_value(struct connman_element *element,
909 enum connman_property_id id, void *value)
911 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
915 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
916 if (element->ipv4.address == NULL)
917 return connman_element_get_value(element->parent,
919 connman_element_lock(element);
920 *((char **) value) = element->ipv4.address;
921 connman_element_unlock(element);
923 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
924 if (element->ipv4.netmask == NULL)
925 return connman_element_get_value(element->parent,
927 connman_element_lock(element);
928 *((char **) value) = element->ipv4.netmask;
929 connman_element_unlock(element);
931 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
932 if (element->ipv4.gateway == NULL)
933 return connman_element_get_value(element->parent,
935 connman_element_lock(element);
936 *((char **) value) = element->ipv4.gateway;
937 connman_element_unlock(element);
939 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
940 if (element->ipv4.nameserver == NULL)
941 return connman_element_get_value(element->parent,
943 connman_element_lock(element);
944 *((char **) value) = element->ipv4.nameserver;
945 connman_element_unlock(element);
955 * connman_element_register:
956 * @element: the element to register
957 * @parent: the parent to register the element with
959 * Register an element with the core. It will be register under the given
960 * parent of if %NULL is provided under the root element.
962 * Returns: %0 on success
964 int connman_element_register(struct connman_element *element,
965 struct connman_element *parent)
967 DBG("element %p name %s parent %p", element, element->name, parent);
969 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
970 if (g_pattern_match_simple(device_filter,
971 element->name) == FALSE) {
972 DBG("ignoring %s device", element->name);
977 if (connman_element_ref(element) == NULL)
980 connman_element_lock(element);
982 __connman_element_load(element);
984 if (element->name == NULL) {
985 element->name = g_strdup(type2string(element->type));
986 if (element->name == NULL) {
987 connman_element_unlock(element);
992 element->parent = parent;
994 connman_element_unlock(element);
996 if (thread_register != NULL)
997 g_thread_pool_push(thread_register, element, NULL);
1002 void connman_element_unregister(struct connman_element *element)
1004 DBG("element %p name %s", element, element->name);
1006 if (thread_unregister != NULL)
1007 g_thread_pool_push(thread_unregister, element, NULL);
1010 void connman_element_unregister_children(struct connman_element *element)
1012 DBG("element %p name %s", element, element->name);
1014 if (thread_unregister_children != NULL)
1015 g_thread_pool_push(thread_unregister_children, element, NULL);
1018 static gboolean update_element(GNode *node, gpointer user_data)
1020 struct connman_element *element = node->data;
1022 DBG("element %p name %s", element, element->name);
1024 if (element->driver && element->driver->update)
1025 element->driver->update(element);
1027 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1028 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1029 DBUS_TYPE_OBJECT_PATH, &element->path,
1035 void connman_element_update(struct connman_element *element)
1039 DBG("element %p name %s", element, element->name);
1041 g_static_rw_lock_reader_lock(&element_lock);
1043 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1046 g_node_traverse(node, G_PRE_ORDER,
1047 G_TRAVERSE_ALL, -1, update_element, NULL);
1049 g_static_rw_lock_reader_unlock(&element_lock);
1052 static void register_element(gpointer data, gpointer user_data)
1054 struct connman_element *element = data;
1055 const gchar *basepath;
1059 g_static_rw_lock_writer_lock(&element_lock);
1061 connman_element_lock(element);
1063 if (element->parent) {
1064 node = g_node_find(element_root, G_PRE_ORDER,
1065 G_TRAVERSE_ALL, element->parent);
1066 basepath = element->parent->path;
1068 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1069 element->subtype = element->parent->subtype;
1071 element->parent = element_root->data;
1073 node = element_root;
1077 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1079 set_reference_properties(element);
1081 connman_element_unlock(element);
1083 DBG("element %p path %s", element, element->path);
1085 g_node_append_data(node, element);
1087 if (g_dbus_register_interface(connection, element->path,
1088 CONNMAN_ELEMENT_INTERFACE,
1089 element_methods, element_signals,
1090 NULL, element, NULL) == FALSE)
1091 connman_error("Failed to register %s", element->path);
1093 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1094 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1095 DBUS_TYPE_OBJECT_PATH, &element->path,
1098 g_static_rw_lock_writer_unlock(&element_lock);
1100 __connman_element_store(element);
1102 g_static_rw_lock_writer_lock(&element_lock);
1104 for (list = driver_list; list; list = list->next) {
1105 struct connman_driver *driver = list->data;
1107 if (match_driver(element, driver) == FALSE)
1110 DBG("driver %p name %s", driver, driver->name);
1112 if (driver->probe(element) == 0) {
1113 connman_element_lock(element);
1114 element->driver = driver;
1115 connman_element_unlock(element);
1120 g_static_rw_lock_writer_unlock(&element_lock);
1123 static gboolean remove_element(GNode *node, gpointer user_data)
1125 struct connman_element *element = node->data;
1126 struct connman_element *root = user_data;
1128 DBG("element %p name %s", element, element->name);
1130 if (element == root)
1133 if (element->driver) {
1134 if (element->driver->remove)
1135 element->driver->remove(element);
1137 connman_element_lock(element);
1138 element->driver = NULL;
1139 connman_element_unlock(element);
1143 g_node_unlink(node);
1144 g_node_destroy(node);
1147 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1148 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1149 DBUS_TYPE_OBJECT_PATH, &element->path,
1152 g_dbus_unregister_interface(connection, element->path,
1153 CONNMAN_ELEMENT_INTERFACE);
1155 connman_element_unref(element);
1160 static void unregister_element(gpointer data, gpointer user_data)
1162 struct connman_element *element = data;
1165 DBG("element %p name %s", element, element->name);
1167 g_static_rw_lock_writer_lock(&element_lock);
1169 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1172 g_node_traverse(node, G_POST_ORDER,
1173 G_TRAVERSE_ALL, -1, remove_element, NULL);
1175 g_static_rw_lock_writer_unlock(&element_lock);
1178 static void unregister_children(gpointer data, gpointer user_data)
1180 struct connman_element *element = data;
1183 DBG("element %p name %s", element, element->name);
1185 g_static_rw_lock_writer_lock(&element_lock);
1187 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1190 g_node_traverse(node, G_POST_ORDER,
1191 G_TRAVERSE_ALL, -1, remove_element, element);
1193 g_static_rw_lock_writer_unlock(&element_lock);
1196 int __connman_element_init(DBusConnection *conn, const char *device)
1198 struct connman_element *element;
1200 DBG("conn %p", conn);
1202 connection = dbus_connection_ref(conn);
1203 if (connection == NULL)
1206 device_filter = g_strdup(device);
1208 g_static_rw_lock_writer_lock(&element_lock);
1210 element = connman_element_create("root");
1212 element->path = g_strdup("/");
1213 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1215 create_default_properties(element);
1217 element_root = g_node_new(element);
1219 g_static_rw_lock_writer_unlock(&element_lock);
1221 thread_register = g_thread_pool_new(register_element,
1222 NULL, 1, FALSE, NULL);
1223 thread_unregister = g_thread_pool_new(unregister_element,
1224 NULL, 1, FALSE, NULL);
1225 thread_unregister_children = g_thread_pool_new(unregister_children,
1226 NULL, 1, FALSE, NULL);
1231 static gboolean free_driver(GNode *node, gpointer data)
1233 struct connman_element *element = node->data;
1235 DBG("element %p name %s", element, element->name);
1237 if (element->driver) {
1238 if (element->driver->remove)
1239 element->driver->remove(element);
1241 connman_element_lock(element);
1242 element->driver = NULL;
1243 connman_element_unlock(element);
1249 static gboolean free_node(GNode *node, gpointer data)
1251 struct connman_element *element = node->data;
1253 DBG("element %p name %s", element, element->name);
1255 if (g_node_depth(node) > 1)
1256 g_thread_pool_push(thread_unregister, element, NULL);
1261 void __connman_element_cleanup(void)
1265 g_thread_pool_free(thread_register, TRUE, TRUE);
1266 thread_register = NULL;
1268 g_static_rw_lock_writer_lock(&element_lock);
1269 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1271 g_static_rw_lock_writer_unlock(&element_lock);
1273 g_static_rw_lock_writer_lock(&element_lock);
1274 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1276 g_static_rw_lock_writer_unlock(&element_lock);
1278 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1279 thread_unregister = NULL;
1281 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1282 thread_unregister_children = NULL;
1284 g_static_rw_lock_writer_lock(&element_lock);
1285 g_node_destroy(element_root);
1286 element_root = NULL;
1287 g_static_rw_lock_writer_unlock(&element_lock);
1289 g_free(device_filter);
1291 dbus_connection_unref(connection);