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_ETHERNET:
127 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
129 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
131 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
133 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
140 static void append_entry(DBusMessageIter *dict,
141 const char *key, int type, void *val)
143 DBusMessageIter entry, value;
144 const char *signature;
146 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
149 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
152 case DBUS_TYPE_BOOLEAN:
153 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
155 case DBUS_TYPE_STRING:
156 signature = DBUS_TYPE_STRING_AS_STRING;
158 case DBUS_TYPE_UINT16:
159 signature = DBUS_TYPE_UINT16_AS_STRING;
161 case DBUS_TYPE_UINT32:
162 signature = DBUS_TYPE_UINT32_AS_STRING;
164 case DBUS_TYPE_OBJECT_PATH:
165 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
168 signature = DBUS_TYPE_VARIANT_AS_STRING;
172 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
174 dbus_message_iter_append_basic(&value, type, val);
175 dbus_message_iter_close_container(&entry, &value);
177 dbus_message_iter_close_container(dict, &entry);
180 static void append_property(DBusMessageIter *dict,
181 struct connman_property *property)
183 if (property->value == NULL)
186 append_entry(dict, property->name, property->type, &property->value);
189 static DBusMessage *get_properties(DBusConnection *conn,
190 DBusMessage *msg, void *data)
192 struct connman_element *element = data;
195 DBusMessageIter array, dict;
198 DBG("conn %p", conn);
200 reply = dbus_message_new_method_return(msg);
204 dbus_message_iter_init_append(reply, &array);
206 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
207 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
208 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
209 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
211 if (element->parent != NULL &&
212 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
213 append_entry(&dict, "Parent",
214 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
217 str = type2string(element->type);
219 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
220 str = subtype2string(element->subtype);
222 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
224 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
226 if (element->priority > 0)
227 append_entry(&dict, "Priority",
228 DBUS_TYPE_UINT16, &element->priority);
230 if (element->network.identifier != NULL)
231 append_entry(&dict, "Identifier",
232 DBUS_TYPE_STRING, &element->network.identifier);
234 if (element->ipv4.address != NULL)
235 append_entry(&dict, "IPv4.Address",
236 DBUS_TYPE_STRING, &element->ipv4.address);
237 if (element->ipv4.netmask != NULL)
238 append_entry(&dict, "IPv4.Netmask",
239 DBUS_TYPE_STRING, &element->ipv4.netmask);
240 if (element->ipv4.gateway != NULL)
241 append_entry(&dict, "IPv4.Gateway",
242 DBUS_TYPE_STRING, &element->ipv4.gateway);
244 connman_element_lock(element);
246 for (list = element->properties; list; list = list->next) {
247 struct connman_property *property = list->data;
249 append_property(&dict, property);
252 connman_element_unlock(element);
254 dbus_message_iter_close_container(&array, &dict);
259 static DBusMessage *set_property(DBusConnection *conn,
260 DBusMessage *msg, void *data)
262 struct connman_element *element = data;
263 DBusMessageIter iter;
264 DBusMessageIter value;
268 DBG("conn %p", conn);
270 if (dbus_message_iter_init(msg, &iter) == FALSE)
271 return __connman_error_invalid_arguments(msg);
273 dbus_message_iter_get_basic(&iter, &name);
274 dbus_message_iter_next(&iter);
275 dbus_message_iter_recurse(&iter, &value);
277 if (__connman_security_check_privileges(msg) < 0)
278 return __connman_error_permission_denied(msg);
280 connman_element_lock(element);
282 for (list = element->properties; list; list = list->next) {
283 struct connman_property *property = list->data;
286 if (g_str_equal(property->name, name) == FALSE)
289 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
292 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
294 if (property->type == DBUS_TYPE_STRING) {
295 dbus_message_iter_get_basic(&value, &str);
296 g_free(property->value);
297 property->value = g_strdup(str);
299 property->value = NULL;
302 connman_element_unlock(element);
304 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
307 static DBusMessage *clear_property(DBusConnection *conn,
308 DBusMessage *msg, void *data)
310 struct connman_element *element = data;
314 DBG("conn %p", conn);
316 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
317 DBUS_TYPE_INVALID) == FALSE)
318 return __connman_error_invalid_arguments(msg);
320 if (__connman_security_check_privileges(msg) < 0)
321 return __connman_error_permission_denied(msg);
323 connman_element_lock(element);
325 for (list = element->properties; list; list = list->next) {
326 struct connman_property *property = list->data;
328 if (g_str_equal(property->name, name) == FALSE)
331 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
334 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
337 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
339 if (property->type == DBUS_TYPE_STRING)
340 g_free(property->value);
342 property->value = NULL;
345 connman_element_unlock(element);
347 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
350 static DBusMessage *do_update(DBusConnection *conn,
351 DBusMessage *msg, void *data)
353 struct connman_element *element = data;
355 DBG("conn %p", conn);
357 if (element->driver == NULL)
358 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
360 if (element->driver->update) {
361 DBG("Calling update callback");
362 element->driver->update(element);
365 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
368 static DBusMessage *do_enable(DBusConnection *conn,
369 DBusMessage *msg, void *data)
371 struct connman_element *element = data;
373 DBG("conn %p", conn);
375 if (element->driver == NULL)
376 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
378 if (element->driver->enable) {
379 DBG("Calling enable callback");
380 element->driver->enable(element);
383 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
386 static DBusMessage *do_disable(DBusConnection *conn,
387 DBusMessage *msg, void *data)
389 struct connman_element *element = data;
391 DBG("conn %p", conn);
393 if (element->driver == NULL)
394 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
396 if (element->driver->disable) {
397 DBG("Calling disable callback");
398 element->driver->disable(element);
401 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
404 static GDBusMethodTable element_methods[] = {
405 { "GetProperties", "", "a{sv}", get_properties },
406 { "SetProperty", "sv", "", set_property },
407 { "ClearProperty", "s", "", clear_property },
408 { "Update", "", "", do_update },
409 { "Enable", "", "", do_enable },
410 { "Disable", "", "", do_disable },
414 static GDBusSignalTable element_signals[] = {
415 { "PropertyChanged", "sv" },
419 struct append_filter {
420 enum connman_element_type type;
421 DBusMessageIter *iter;
424 static gboolean append_path(GNode *node, gpointer data)
426 struct connman_element *element = node->data;
427 struct append_filter *filter = data;
429 DBG("element %p name %s", element, element->name);
431 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
434 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
435 filter->type != element->type)
438 dbus_message_iter_append_basic(filter->iter,
439 DBUS_TYPE_OBJECT_PATH, &element->path);
444 void __connman_element_list(enum connman_element_type type,
445 DBusMessageIter *iter)
447 struct append_filter filter = { type, iter };
451 g_static_rw_lock_reader_lock(&element_lock);
452 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
453 append_path, &filter);
454 g_static_rw_lock_reader_unlock(&element_lock);
457 static gint compare_priority(gconstpointer a, gconstpointer b)
459 const struct connman_driver *driver1 = a;
460 const struct connman_driver *driver2 = b;
462 return driver2->priority - driver1->priority;
465 static gboolean match_driver(struct connman_element *element,
466 struct connman_driver *driver)
468 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
471 if (element->type != driver->type &&
472 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
475 if (element->subtype == driver->subtype ||
476 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
482 static gboolean probe_driver(GNode *node, gpointer data)
484 struct connman_element *element = node->data;
485 struct connman_driver *driver = data;
487 DBG("element %p name %s", element, element->name);
489 if (!element->driver && match_driver(element, driver) == TRUE) {
490 if (driver->probe(element) < 0)
493 connman_element_lock(element);
494 element->driver = driver;
495 connman_element_unlock(element);
502 * connman_driver_register:
503 * @driver: driver definition
505 * Register a new driver
507 * Returns: %0 on success
509 int connman_driver_register(struct connman_driver *driver)
511 DBG("driver %p name %s", driver, driver->name);
513 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
519 g_static_rw_lock_writer_lock(&element_lock);
521 driver_list = g_slist_insert_sorted(driver_list, driver,
524 if (element_root != NULL)
525 g_node_traverse(element_root, G_PRE_ORDER,
526 G_TRAVERSE_ALL, -1, probe_driver, driver);
528 g_static_rw_lock_writer_unlock(&element_lock);
533 static gboolean remove_driver(GNode *node, gpointer data)
535 struct connman_element *element = node->data;
536 struct connman_driver *driver = data;
538 DBG("element %p name %s", element, element->name);
540 if (element->driver == driver) {
542 driver->remove(element);
544 connman_element_lock(element);
545 element->driver = NULL;
546 connman_element_unlock(element);
553 * connman_driver_unregister:
554 * @driver: driver definition
556 * Remove a previously registered driver
558 void connman_driver_unregister(struct connman_driver *driver)
560 DBG("driver %p name %s", driver, driver->name);
562 g_static_rw_lock_writer_lock(&element_lock);
564 driver_list = g_slist_remove(driver_list, driver);
566 if (element_root != NULL)
567 g_node_traverse(element_root, G_POST_ORDER,
568 G_TRAVERSE_ALL, -1, remove_driver, driver);
570 g_static_rw_lock_writer_unlock(&element_lock);
574 * connman_element_create:
575 * @name: element name
577 * Allocate a new element and assign the given #name to it. If the name
578 * is #NULL, it will be later on created based on the element type.
580 * Returns: a newly-allocated #connman_element structure
582 struct connman_element *connman_element_create(const char *name)
584 struct connman_element *element;
586 element = g_try_new0(struct connman_element, 1);
590 DBG("element %p", element);
592 element->refcount = 1;
594 g_static_mutex_init(&element->mutex);
596 element->name = g_strdup(name);
597 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
598 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
599 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
601 element->enabled = FALSE;
606 struct connman_element *connman_element_ref(struct connman_element *element)
608 DBG("element %p name %s refcount %d", element, element->name,
609 g_atomic_int_get(&element->refcount) + 1);
611 g_atomic_int_inc(&element->refcount);
616 static void free_properties(struct connman_element *element)
620 DBG("element %p name %s", element, element->name);
622 connman_element_lock(element);
624 for (list = element->properties; list; list = list->next) {
625 struct connman_property *property = list->data;
627 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
628 if (property->type == DBUS_TYPE_STRING)
629 g_free(property->value);
635 g_slist_free(element->properties);
637 element->properties = NULL;
639 connman_element_unlock(element);
642 void connman_element_unref(struct connman_element *element)
644 DBG("element %p name %s refcount %d", element, element->name,
645 g_atomic_int_get(&element->refcount) - 1);
647 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
648 free_properties(element);
649 g_free(element->ipv4.address);
650 g_free(element->ipv4.netmask);
651 g_free(element->ipv4.gateway);
652 g_free(element->ipv4.network);
653 g_free(element->ipv4.broadcast);
654 g_free(element->ipv4.nameserver);
655 g_free(element->network.identifier);
656 g_free(element->path);
657 g_free(element->name);
662 int connman_element_add_static_property(struct connman_element *element,
663 const char *name, int type, const void *value)
665 struct connman_property *property;
667 DBG("element %p name %s", element, element->name);
669 if (type != DBUS_TYPE_STRING)
672 property = g_try_new0(struct connman_property, 1);
673 if (property == NULL)
676 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
677 property->id = CONNMAN_PROPERTY_ID_INVALID;
678 property->name = g_strdup(name);
679 property->type = type;
681 DBG("name %s type %d value %p", name, type, value);
684 case DBUS_TYPE_STRING:
685 property->value = g_strdup(*((const char **) value));
689 connman_element_lock(element);
690 element->properties = g_slist_append(element->properties, property);
691 connman_element_unlock(element);
696 static void *get_reference_value(struct connman_element *element,
697 enum connman_property_id id)
701 DBG("element %p name %s", element, element->name);
703 for (list = element->properties; list; list = list->next) {
704 struct connman_property *property = list->data;
706 if (property->id != id)
709 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
710 return property->value;
713 if (element->parent == NULL)
716 return get_reference_value(element->parent, id);
719 static void set_reference_properties(struct connman_element *element)
723 DBG("element %p name %s", element, element->name);
725 for (list = element->properties; list; list = list->next) {
726 struct connman_property *property = list->data;
728 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
731 property->value = get_reference_value(element->parent,
736 static struct connman_property *create_property(struct connman_element *element,
737 enum connman_property_id id)
739 struct connman_property *property;
742 DBG("element %p name %s", element, element->name);
744 connman_element_lock(element);
746 for (list = element->properties; list; list = list->next) {
747 property = list->data;
749 if (property->id == id)
753 property = g_try_new0(struct connman_property, 1);
754 if (property == NULL)
757 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
759 property->name = g_strdup(propid2name(id));
760 property->type = propid2type(id);
762 if (property->name == NULL) {
768 element->properties = g_slist_append(element->properties, property);
771 connman_element_unlock(element);
776 static void create_default_properties(struct connman_element *element)
778 struct connman_property *property;
781 DBG("element %p name %s", element, element->name);
783 for (i = 0; propid_table[i].name; i++) {
784 DBG("property %s", propid_table[i].name);
786 property = create_property(element, propid_table[i].id);
788 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
790 if (propid_table[i].type != DBUS_TYPE_STRING)
793 if (propid_table[i].value)
794 property->value = g_strdup(propid_table[i].value);
796 property->value = g_strdup("");
800 static int define_properties_valist(struct connman_element *element,
803 enum connman_property_id id;
805 DBG("element %p name %s", element, element->name);
807 id = va_arg(args, enum connman_property_id);
809 while (id != CONNMAN_PROPERTY_ID_INVALID) {
811 DBG("property %d", id);
813 create_property(element, id);
815 id = va_arg(args, enum connman_property_id);
822 * connman_element_define_properties:
823 * @element: an element
824 * @varargs: list of property identifiers
826 * Define the valid properties for an element.
828 * Returns: %0 on success
830 int connman_element_define_properties(struct connman_element *element, ...)
835 DBG("element %p name %s", element, element->name);
837 va_start(args, element);
839 err = define_properties_valist(element, args);
846 int connman_element_create_property(struct connman_element *element,
847 const char *name, int type)
852 int connman_element_set_property(struct connman_element *element,
853 enum connman_property_id id, const void *value)
857 case CONNMAN_PROPERTY_TYPE_INVALID:
859 case CONNMAN_PROPERTY_TYPE_IPV4_ADDRESS:
860 connman_element_lock(element);
861 g_free(element->ipv4.address);
862 element->ipv4.address = g_strdup(*((const char **) value));
863 connman_element_unlock(element);
865 case CONNMAN_PROPERTY_TYPE_IPV4_NETMASK:
866 connman_element_lock(element);
867 g_free(element->ipv4.netmask);
868 element->ipv4.netmask = g_strdup(*((const char **) value));
869 connman_element_unlock(element);
871 case CONNMAN_PROPERTY_TYPE_IPV4_GATEWAY:
872 connman_element_lock(element);
873 g_free(element->ipv4.gateway);
874 element->ipv4.gateway = g_strdup(*((const char **) value));
875 connman_element_unlock(element);
877 case CONNMAN_PROPERTY_TYPE_IPV4_NAMESERVER:
878 connman_element_lock(element);
879 g_free(element->ipv4.nameserver);
880 element->ipv4.nameserver = g_strdup(*((const char **) value));
881 connman_element_unlock(element);
886 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
887 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
888 DBUS_TYPE_OBJECT_PATH, &element->path,
894 int connman_element_get_value(struct connman_element *element,
895 enum connman_property_id id, void *value)
897 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
902 case CONNMAN_PROPERTY_TYPE_INVALID:
904 case CONNMAN_PROPERTY_TYPE_IPV4_ADDRESS:
905 if (element->ipv4.address == NULL)
906 return connman_element_get_value(element->parent,
908 connman_element_lock(element);
909 *((char **) value) = element->ipv4.address;
910 connman_element_unlock(element);
912 case CONNMAN_PROPERTY_TYPE_IPV4_NETMASK:
913 if (element->ipv4.netmask == NULL)
914 return connman_element_get_value(element->parent,
916 connman_element_lock(element);
917 *((char **) value) = element->ipv4.netmask;
918 connman_element_unlock(element);
920 case CONNMAN_PROPERTY_TYPE_IPV4_GATEWAY:
921 if (element->ipv4.gateway == NULL)
922 return connman_element_get_value(element->parent,
924 connman_element_lock(element);
925 *((char **) value) = element->ipv4.gateway;
926 connman_element_unlock(element);
928 case CONNMAN_PROPERTY_TYPE_IPV4_NAMESERVER:
929 if (element->ipv4.nameserver == NULL)
930 return connman_element_get_value(element->parent,
932 connman_element_lock(element);
933 *((char **) value) = element->ipv4.nameserver;
934 connman_element_unlock(element);
943 * connman_element_register:
944 * @element: the element to register
945 * @parent: the parent to register the element with
947 * Register an element with the core. It will be register under the given
948 * parent of if %NULL is provided under the root element.
950 * Returns: %0 on success
952 int connman_element_register(struct connman_element *element,
953 struct connman_element *parent)
955 DBG("element %p name %s parent %p", element, element->name, parent);
957 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
958 if (g_str_equal(device_filter, element->name) == FALSE)
962 if (connman_element_ref(element) == NULL)
965 connman_element_lock(element);
967 __connman_element_load(element);
969 if (element->name == NULL) {
970 element->name = g_strdup(type2string(element->type));
971 if (element->name == NULL) {
972 connman_element_unlock(element);
977 element->parent = parent;
979 connman_element_unlock(element);
981 if (thread_register != NULL)
982 g_thread_pool_push(thread_register, element, NULL);
987 void connman_element_unregister(struct connman_element *element)
989 DBG("element %p name %s", element, element->name);
991 if (thread_unregister != NULL)
992 g_thread_pool_push(thread_unregister, element, NULL);
995 void connman_element_unregister_children(struct connman_element *element)
997 DBG("element %p name %s", element, element->name);
999 if (thread_unregister_children != NULL)
1000 g_thread_pool_push(thread_unregister_children, element, NULL);
1003 static gboolean update_element(GNode *node, gpointer user_data)
1005 struct connman_element *element = node->data;
1007 DBG("element %p name %s", element, element->name);
1009 if (element->driver && element->driver->update)
1010 element->driver->update(element);
1012 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1013 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1014 DBUS_TYPE_OBJECT_PATH, &element->path,
1020 void connman_element_update(struct connman_element *element)
1024 DBG("element %p name %s", element, element->name);
1026 g_static_rw_lock_reader_lock(&element_lock);
1028 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1031 g_node_traverse(node, G_PRE_ORDER,
1032 G_TRAVERSE_ALL, -1, update_element, NULL);
1034 g_static_rw_lock_reader_unlock(&element_lock);
1037 static void register_element(gpointer data, gpointer user_data)
1039 struct connman_element *element = data;
1040 const gchar *basepath;
1044 g_static_rw_lock_writer_lock(&element_lock);
1046 connman_element_lock(element);
1048 if (element->parent) {
1049 node = g_node_find(element_root, G_PRE_ORDER,
1050 G_TRAVERSE_ALL, element->parent);
1051 basepath = element->parent->path;
1053 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1054 element->subtype = element->parent->subtype;
1056 element->parent = element_root->data;
1058 node = element_root;
1062 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1064 set_reference_properties(element);
1066 connman_element_unlock(element);
1068 DBG("element %p path %s", element, element->path);
1070 g_node_append_data(node, element);
1072 if (g_dbus_register_interface(connection, element->path,
1073 CONNMAN_ELEMENT_INTERFACE,
1074 element_methods, element_signals,
1075 NULL, element, NULL) == FALSE)
1076 connman_error("Failed to register %s", element->path);
1078 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1079 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1080 DBUS_TYPE_OBJECT_PATH, &element->path,
1083 g_static_rw_lock_writer_unlock(&element_lock);
1085 __connman_element_store(element);
1087 g_static_rw_lock_writer_lock(&element_lock);
1089 for (list = driver_list; list; list = list->next) {
1090 struct connman_driver *driver = list->data;
1092 if (match_driver(element, driver) == FALSE)
1095 DBG("driver %p name %s", driver, driver->name);
1097 if (driver->probe(element) == 0) {
1098 connman_element_lock(element);
1099 element->driver = driver;
1100 connman_element_unlock(element);
1105 g_static_rw_lock_writer_unlock(&element_lock);
1108 static gboolean remove_element(GNode *node, gpointer user_data)
1110 struct connman_element *element = node->data;
1111 struct connman_element *root = user_data;
1113 DBG("element %p name %s", element, element->name);
1115 if (element == root)
1118 if (element->driver) {
1119 if (element->driver->remove)
1120 element->driver->remove(element);
1122 connman_element_lock(element);
1123 element->driver = NULL;
1124 connman_element_unlock(element);
1128 g_node_unlink(node);
1129 g_node_destroy(node);
1132 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1133 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1134 DBUS_TYPE_OBJECT_PATH, &element->path,
1137 g_dbus_unregister_interface(connection, element->path,
1138 CONNMAN_ELEMENT_INTERFACE);
1140 connman_element_unref(element);
1145 static void unregister_element(gpointer data, gpointer user_data)
1147 struct connman_element *element = data;
1150 DBG("element %p name %s", element, element->name);
1152 g_static_rw_lock_writer_lock(&element_lock);
1154 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1157 g_node_traverse(node, G_POST_ORDER,
1158 G_TRAVERSE_ALL, -1, remove_element, NULL);
1160 g_static_rw_lock_writer_unlock(&element_lock);
1163 static void unregister_children(gpointer data, gpointer user_data)
1165 struct connman_element *element = data;
1168 DBG("element %p name %s", element, element->name);
1170 g_static_rw_lock_writer_lock(&element_lock);
1172 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1175 g_node_traverse(node, G_POST_ORDER,
1176 G_TRAVERSE_ALL, -1, remove_element, element);
1178 g_static_rw_lock_writer_unlock(&element_lock);
1181 int __connman_element_init(DBusConnection *conn, const char *device)
1183 struct connman_element *element;
1185 DBG("conn %p", conn);
1187 connection = dbus_connection_ref(conn);
1188 if (connection == NULL)
1191 device_filter = g_strdup(device);
1193 g_static_rw_lock_writer_lock(&element_lock);
1195 element = connman_element_create("root");
1197 element->path = g_strdup("/");
1198 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1200 create_default_properties(element);
1202 element_root = g_node_new(element);
1204 g_static_rw_lock_writer_unlock(&element_lock);
1206 thread_register = g_thread_pool_new(register_element,
1207 NULL, 1, FALSE, NULL);
1208 thread_unregister = g_thread_pool_new(unregister_element,
1209 NULL, 1, FALSE, NULL);
1210 thread_unregister_children = g_thread_pool_new(unregister_children,
1211 NULL, 1, FALSE, NULL);
1216 static gboolean free_driver(GNode *node, gpointer data)
1218 struct connman_element *element = node->data;
1220 DBG("element %p name %s", element, element->name);
1222 if (element->driver) {
1223 if (element->driver->remove)
1224 element->driver->remove(element);
1226 connman_element_lock(element);
1227 element->driver = NULL;
1228 connman_element_unlock(element);
1234 static gboolean free_node(GNode *node, gpointer data)
1236 struct connman_element *element = node->data;
1238 DBG("element %p name %s", element, element->name);
1240 if (g_node_depth(node) > 1)
1241 g_thread_pool_push(thread_unregister, element, NULL);
1246 void __connman_element_cleanup(void)
1250 g_thread_pool_free(thread_register, TRUE, TRUE);
1251 thread_register = NULL;
1253 g_static_rw_lock_writer_lock(&element_lock);
1254 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1256 g_static_rw_lock_writer_unlock(&element_lock);
1258 g_static_rw_lock_writer_lock(&element_lock);
1259 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1261 g_static_rw_lock_writer_unlock(&element_lock);
1263 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1264 thread_unregister = NULL;
1266 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1267 thread_unregister_children = NULL;
1269 g_static_rw_lock_writer_lock(&element_lock);
1270 g_node_destroy(element_root);
1271 element_root = NULL;
1272 g_static_rw_lock_writer_unlock(&element_lock);
1274 g_free(device_filter);
1276 dbus_connection_unref(connection);