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_FAKE:
127 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
129 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
131 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
133 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
135 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
137 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
144 static void append_entry(DBusMessageIter *dict,
145 const char *key, int type, void *val)
147 DBusMessageIter entry, value;
148 const char *signature;
150 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
153 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
156 case DBUS_TYPE_BOOLEAN:
157 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
159 case DBUS_TYPE_STRING:
160 signature = DBUS_TYPE_STRING_AS_STRING;
162 case DBUS_TYPE_UINT16:
163 signature = DBUS_TYPE_UINT16_AS_STRING;
165 case DBUS_TYPE_UINT32:
166 signature = DBUS_TYPE_UINT32_AS_STRING;
168 case DBUS_TYPE_OBJECT_PATH:
169 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
172 signature = DBUS_TYPE_VARIANT_AS_STRING;
176 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
178 dbus_message_iter_append_basic(&value, type, val);
179 dbus_message_iter_close_container(&entry, &value);
181 dbus_message_iter_close_container(dict, &entry);
184 static void append_property(DBusMessageIter *dict,
185 struct connman_property *property)
187 if (property->value == NULL)
190 append_entry(dict, property->name, property->type, &property->value);
193 static DBusMessage *get_properties(DBusConnection *conn,
194 DBusMessage *msg, void *data)
196 struct connman_element *element = data;
199 DBusMessageIter array, dict;
202 DBG("conn %p", conn);
204 reply = dbus_message_new_method_return(msg);
208 dbus_message_iter_init_append(reply, &array);
210 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
211 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
212 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
213 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
215 if (element->parent != NULL &&
216 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
217 append_entry(&dict, "Parent",
218 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
221 str = type2string(element->type);
223 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
224 str = subtype2string(element->subtype);
226 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
228 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
230 if (element->priority > 0)
231 append_entry(&dict, "Priority",
232 DBUS_TYPE_UINT16, &element->priority);
235 if (element->network.identifier != NULL)
236 append_entry(&dict, "Identifier",
237 DBUS_TYPE_STRING, &element->network.identifier);
240 if (element->ipv4.address != NULL)
241 append_entry(&dict, "IPv4.Address",
242 DBUS_TYPE_STRING, &element->ipv4.address);
243 if (element->ipv4.netmask != NULL)
244 append_entry(&dict, "IPv4.Netmask",
245 DBUS_TYPE_STRING, &element->ipv4.netmask);
246 if (element->ipv4.gateway != NULL)
247 append_entry(&dict, "IPv4.Gateway",
248 DBUS_TYPE_STRING, &element->ipv4.gateway);
250 connman_element_lock(element);
252 for (list = element->properties; list; list = list->next) {
253 struct connman_property *property = list->data;
255 append_property(&dict, property);
258 connman_element_unlock(element);
260 dbus_message_iter_close_container(&array, &dict);
265 static DBusMessage *set_property(DBusConnection *conn,
266 DBusMessage *msg, void *data)
268 struct connman_element *element = data;
269 DBusMessageIter iter;
270 DBusMessageIter value;
274 DBG("conn %p", conn);
276 if (dbus_message_iter_init(msg, &iter) == FALSE)
277 return __connman_error_invalid_arguments(msg);
279 dbus_message_iter_get_basic(&iter, &name);
280 dbus_message_iter_next(&iter);
281 dbus_message_iter_recurse(&iter, &value);
283 if (__connman_security_check_privileges(msg) < 0)
284 return __connman_error_permission_denied(msg);
286 connman_element_lock(element);
288 for (list = element->properties; list; list = list->next) {
289 struct connman_property *property = list->data;
292 if (g_str_equal(property->name, name) == FALSE)
295 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
298 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
300 if (property->type == DBUS_TYPE_STRING) {
301 dbus_message_iter_get_basic(&value, &str);
302 g_free(property->value);
303 property->value = g_strdup(str);
305 property->value = NULL;
308 connman_element_unlock(element);
310 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
313 static DBusMessage *clear_property(DBusConnection *conn,
314 DBusMessage *msg, void *data)
316 struct connman_element *element = data;
320 DBG("conn %p", conn);
322 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
323 DBUS_TYPE_INVALID) == FALSE)
324 return __connman_error_invalid_arguments(msg);
326 if (__connman_security_check_privileges(msg) < 0)
327 return __connman_error_permission_denied(msg);
329 connman_element_lock(element);
331 for (list = element->properties; list; list = list->next) {
332 struct connman_property *property = list->data;
334 if (g_str_equal(property->name, name) == FALSE)
337 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
340 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
343 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
345 if (property->type == DBUS_TYPE_STRING)
346 g_free(property->value);
348 property->value = NULL;
351 connman_element_unlock(element);
353 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
356 static DBusMessage *do_update(DBusConnection *conn,
357 DBusMessage *msg, void *data)
359 struct connman_element *element = data;
361 DBG("conn %p", conn);
363 if (element->enabled == FALSE)
364 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
366 if (element->driver && element->driver->update) {
367 DBG("Calling update callback");
368 element->driver->update(element);
371 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
374 static DBusMessage *do_enable(DBusConnection *conn,
375 DBusMessage *msg, void *data)
377 struct connman_element *element = data;
379 DBG("conn %p", conn);
381 if (element->enabled == TRUE)
382 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
384 if (element->driver && element->driver->enable) {
385 DBG("Calling enable callback");
386 element->driver->enable(element);
389 element->enabled = TRUE;
391 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
392 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
393 DBUS_TYPE_OBJECT_PATH, &element->path,
396 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
399 static DBusMessage *do_disable(DBusConnection *conn,
400 DBusMessage *msg, void *data)
402 struct connman_element *element = data;
404 DBG("conn %p", conn);
406 if (element->enabled == FALSE)
407 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
409 if (element->driver && element->driver->disable) {
410 DBG("Calling disable callback");
411 element->driver->disable(element);
414 element->enabled = FALSE;
416 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
417 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
418 DBUS_TYPE_OBJECT_PATH, &element->path,
421 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
424 static GDBusMethodTable element_methods[] = {
425 { "GetProperties", "", "a{sv}", get_properties },
426 { "SetProperty", "sv", "", set_property },
427 { "ClearProperty", "s", "", clear_property },
428 { "Update", "", "", do_update },
429 { "Enable", "", "", do_enable },
430 { "Disable", "", "", do_disable },
434 static GDBusSignalTable element_signals[] = {
435 { "PropertyChanged", "sv" },
439 struct append_filter {
440 enum connman_element_type type;
441 DBusMessageIter *iter;
444 static gboolean append_path(GNode *node, gpointer data)
446 struct connman_element *element = node->data;
447 struct append_filter *filter = data;
449 DBG("element %p name %s", element, element->name);
451 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
454 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
455 filter->type != element->type)
458 dbus_message_iter_append_basic(filter->iter,
459 DBUS_TYPE_OBJECT_PATH, &element->path);
464 void __connman_element_list(enum connman_element_type type,
465 DBusMessageIter *iter)
467 struct append_filter filter = { type, iter };
471 g_static_rw_lock_reader_lock(&element_lock);
472 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
473 append_path, &filter);
474 g_static_rw_lock_reader_unlock(&element_lock);
477 static gint compare_priority(gconstpointer a, gconstpointer b)
479 const struct connman_driver *driver1 = a;
480 const struct connman_driver *driver2 = b;
482 return driver2->priority - driver1->priority;
485 static gboolean match_driver(struct connman_element *element,
486 struct connman_driver *driver)
488 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
491 if (element->type != driver->type &&
492 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
495 if (element->subtype == driver->subtype ||
496 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
502 static gboolean probe_driver(GNode *node, gpointer data)
504 struct connman_element *element = node->data;
505 struct connman_driver *driver = data;
507 DBG("element %p name %s", element, element->name);
509 if (!element->driver && match_driver(element, driver) == TRUE) {
510 if (driver->probe(element) < 0)
513 connman_element_lock(element);
514 element->driver = driver;
515 connman_element_unlock(element);
522 * connman_driver_register:
523 * @driver: driver definition
525 * Register a new driver
527 * Returns: %0 on success
529 int connman_driver_register(struct connman_driver *driver)
531 DBG("driver %p name %s", driver, driver->name);
533 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
539 g_static_rw_lock_writer_lock(&element_lock);
541 driver_list = g_slist_insert_sorted(driver_list, driver,
544 if (element_root != NULL)
545 g_node_traverse(element_root, G_PRE_ORDER,
546 G_TRAVERSE_ALL, -1, probe_driver, driver);
548 g_static_rw_lock_writer_unlock(&element_lock);
553 static gboolean remove_driver(GNode *node, gpointer data)
555 struct connman_element *element = node->data;
556 struct connman_driver *driver = data;
558 DBG("element %p name %s", element, element->name);
560 if (element->driver == driver) {
562 driver->remove(element);
564 connman_element_lock(element);
565 element->driver = NULL;
566 connman_element_unlock(element);
573 * connman_driver_unregister:
574 * @driver: driver definition
576 * Remove a previously registered driver
578 void connman_driver_unregister(struct connman_driver *driver)
580 DBG("driver %p name %s", driver, driver->name);
582 g_static_rw_lock_writer_lock(&element_lock);
584 driver_list = g_slist_remove(driver_list, driver);
586 if (element_root != NULL)
587 g_node_traverse(element_root, G_POST_ORDER,
588 G_TRAVERSE_ALL, -1, remove_driver, driver);
590 g_static_rw_lock_writer_unlock(&element_lock);
594 * connman_element_create:
595 * @name: element name
597 * Allocate a new element and assign the given #name to it. If the name
598 * is #NULL, it will be later on created based on the element type.
600 * Returns: a newly-allocated #connman_element structure
602 struct connman_element *connman_element_create(const char *name)
604 struct connman_element *element;
606 element = g_try_new0(struct connman_element, 1);
610 DBG("element %p", element);
612 element->refcount = 1;
614 g_static_mutex_init(&element->mutex);
616 element->name = g_strdup(name);
617 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
618 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
619 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
621 element->enabled = FALSE;
626 struct connman_element *connman_element_ref(struct connman_element *element)
628 DBG("element %p name %s refcount %d", element, element->name,
629 g_atomic_int_get(&element->refcount) + 1);
631 g_atomic_int_inc(&element->refcount);
636 static void free_properties(struct connman_element *element)
640 DBG("element %p name %s", element, element->name);
642 connman_element_lock(element);
644 for (list = element->properties; list; list = list->next) {
645 struct connman_property *property = list->data;
647 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
648 if (property->type == DBUS_TYPE_STRING)
649 g_free(property->value);
655 g_slist_free(element->properties);
657 element->properties = NULL;
659 connman_element_unlock(element);
662 void connman_element_unref(struct connman_element *element)
664 DBG("element %p name %s refcount %d", element, element->name,
665 g_atomic_int_get(&element->refcount) - 1);
667 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
668 free_properties(element);
669 g_free(element->ipv4.address);
670 g_free(element->ipv4.netmask);
671 g_free(element->ipv4.gateway);
672 g_free(element->ipv4.network);
673 g_free(element->ipv4.broadcast);
674 g_free(element->ipv4.nameserver);
675 g_free(element->network.identifier);
676 g_free(element->path);
677 g_free(element->name);
682 int connman_element_add_static_property(struct connman_element *element,
683 const char *name, int type, const void *value)
685 struct connman_property *property;
687 DBG("element %p name %s", element, element->name);
689 if (type != DBUS_TYPE_STRING)
692 property = g_try_new0(struct connman_property, 1);
693 if (property == NULL)
696 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
697 property->id = CONNMAN_PROPERTY_ID_INVALID;
698 property->name = g_strdup(name);
699 property->type = type;
701 DBG("name %s type %d value %p", name, type, value);
704 case DBUS_TYPE_STRING:
705 property->value = g_strdup(*((const char **) value));
709 connman_element_lock(element);
710 element->properties = g_slist_append(element->properties, property);
711 connman_element_unlock(element);
716 static void *get_reference_value(struct connman_element *element,
717 enum connman_property_id id)
721 DBG("element %p name %s", element, element->name);
723 for (list = element->properties; list; list = list->next) {
724 struct connman_property *property = list->data;
726 if (property->id != id)
729 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
730 return property->value;
733 if (element->parent == NULL)
736 return get_reference_value(element->parent, id);
739 static void set_reference_properties(struct connman_element *element)
743 DBG("element %p name %s", element, element->name);
745 for (list = element->properties; list; list = list->next) {
746 struct connman_property *property = list->data;
748 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
751 property->value = get_reference_value(element->parent,
756 static struct connman_property *create_property(struct connman_element *element,
757 enum connman_property_id id)
759 struct connman_property *property;
762 DBG("element %p name %s", element, element->name);
764 connman_element_lock(element);
766 for (list = element->properties; list; list = list->next) {
767 property = list->data;
769 if (property->id == id)
773 property = g_try_new0(struct connman_property, 1);
774 if (property == NULL)
777 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
779 property->name = g_strdup(propid2name(id));
780 property->type = propid2type(id);
782 if (property->name == NULL) {
788 element->properties = g_slist_append(element->properties, property);
791 connman_element_unlock(element);
796 static void create_default_properties(struct connman_element *element)
798 struct connman_property *property;
801 DBG("element %p name %s", element, element->name);
803 for (i = 0; propid_table[i].name; i++) {
804 DBG("property %s", propid_table[i].name);
806 property = create_property(element, propid_table[i].id);
808 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
810 if (propid_table[i].type != DBUS_TYPE_STRING)
813 if (propid_table[i].value)
814 property->value = g_strdup(propid_table[i].value);
816 property->value = g_strdup("");
820 static int define_properties_valist(struct connman_element *element,
823 enum connman_property_id id;
825 DBG("element %p name %s", element, element->name);
827 id = va_arg(args, enum connman_property_id);
829 while (id != CONNMAN_PROPERTY_ID_INVALID) {
831 DBG("property %d", id);
833 create_property(element, id);
835 id = va_arg(args, enum connman_property_id);
842 * connman_element_define_properties:
843 * @element: an element
844 * @varargs: list of property identifiers
846 * Define the valid properties for an element.
848 * Returns: %0 on success
850 int connman_element_define_properties(struct connman_element *element, ...)
855 DBG("element %p name %s", element, element->name);
857 va_start(args, element);
859 err = define_properties_valist(element, args);
866 int connman_element_create_property(struct connman_element *element,
867 const char *name, int type)
872 int connman_element_set_property(struct connman_element *element,
873 enum connman_property_id id, const void *value)
876 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
877 connman_element_lock(element);
878 g_free(element->ipv4.address);
879 element->ipv4.address = g_strdup(*((const char **) value));
880 connman_element_unlock(element);
882 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
883 connman_element_lock(element);
884 g_free(element->ipv4.netmask);
885 element->ipv4.netmask = g_strdup(*((const char **) value));
886 connman_element_unlock(element);
888 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
889 connman_element_lock(element);
890 g_free(element->ipv4.gateway);
891 element->ipv4.gateway = g_strdup(*((const char **) value));
892 connman_element_unlock(element);
894 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
895 connman_element_lock(element);
896 g_free(element->ipv4.nameserver);
897 element->ipv4.nameserver = g_strdup(*((const char **) value));
898 connman_element_unlock(element);
904 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
905 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
906 DBUS_TYPE_OBJECT_PATH, &element->path,
912 int connman_element_get_value(struct connman_element *element,
913 enum connman_property_id id, void *value)
915 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
919 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
920 if (element->ipv4.address == NULL)
921 return connman_element_get_value(element->parent,
923 connman_element_lock(element);
924 *((char **) value) = element->ipv4.address;
925 connman_element_unlock(element);
927 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
928 if (element->ipv4.netmask == NULL)
929 return connman_element_get_value(element->parent,
931 connman_element_lock(element);
932 *((char **) value) = element->ipv4.netmask;
933 connman_element_unlock(element);
935 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
936 if (element->ipv4.gateway == NULL)
937 return connman_element_get_value(element->parent,
939 connman_element_lock(element);
940 *((char **) value) = element->ipv4.gateway;
941 connman_element_unlock(element);
943 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
944 if (element->ipv4.nameserver == NULL)
945 return connman_element_get_value(element->parent,
947 connman_element_lock(element);
948 *((char **) value) = element->ipv4.nameserver;
949 connman_element_unlock(element);
959 * connman_element_register:
960 * @element: the element to register
961 * @parent: the parent to register the element with
963 * Register an element with the core. It will be register under the given
964 * parent of if %NULL is provided under the root element.
966 * Returns: %0 on success
968 int connman_element_register(struct connman_element *element,
969 struct connman_element *parent)
971 DBG("element %p name %s parent %p", element, element->name, parent);
973 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
974 if (g_pattern_match_simple(device_filter,
975 element->name) == FALSE) {
976 DBG("ignoring %s device", element->name);
981 if (connman_element_ref(element) == NULL)
984 connman_element_lock(element);
986 __connman_element_load(element);
988 if (element->name == NULL) {
989 element->name = g_strdup(type2string(element->type));
990 if (element->name == NULL) {
991 connman_element_unlock(element);
996 element->parent = parent;
998 connman_element_unlock(element);
1000 if (thread_register != NULL)
1001 g_thread_pool_push(thread_register, element, NULL);
1006 void connman_element_unregister(struct connman_element *element)
1008 DBG("element %p name %s", element, element->name);
1010 if (thread_unregister != NULL)
1011 g_thread_pool_push(thread_unregister, element, NULL);
1014 void connman_element_unregister_children(struct connman_element *element)
1016 DBG("element %p name %s", element, element->name);
1018 if (thread_unregister_children != NULL)
1019 g_thread_pool_push(thread_unregister_children, element, NULL);
1022 static gboolean update_element(GNode *node, gpointer user_data)
1024 struct connman_element *element = node->data;
1026 DBG("element %p name %s", element, element->name);
1028 if (element->driver && element->driver->update)
1029 element->driver->update(element);
1031 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1032 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1033 DBUS_TYPE_OBJECT_PATH, &element->path,
1039 void connman_element_update(struct connman_element *element)
1043 DBG("element %p name %s", element, element->name);
1045 g_static_rw_lock_reader_lock(&element_lock);
1047 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1050 g_node_traverse(node, G_PRE_ORDER,
1051 G_TRAVERSE_ALL, -1, update_element, NULL);
1053 g_static_rw_lock_reader_unlock(&element_lock);
1056 static void register_element(gpointer data, gpointer user_data)
1058 struct connman_element *element = data;
1059 const gchar *basepath;
1063 g_static_rw_lock_writer_lock(&element_lock);
1065 connman_element_lock(element);
1067 if (element->parent) {
1068 node = g_node_find(element_root, G_PRE_ORDER,
1069 G_TRAVERSE_ALL, element->parent);
1070 basepath = element->parent->path;
1072 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1073 element->subtype = element->parent->subtype;
1075 element->parent = element_root->data;
1077 node = element_root;
1081 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1083 set_reference_properties(element);
1085 connman_element_unlock(element);
1087 DBG("element %p path %s", element, element->path);
1089 g_node_append_data(node, element);
1091 if (g_dbus_register_interface(connection, element->path,
1092 CONNMAN_ELEMENT_INTERFACE,
1093 element_methods, element_signals,
1094 NULL, element, NULL) == FALSE)
1095 connman_error("Failed to register %s", element->path);
1097 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1098 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1099 DBUS_TYPE_OBJECT_PATH, &element->path,
1102 g_static_rw_lock_writer_unlock(&element_lock);
1104 __connman_element_store(element);
1106 g_static_rw_lock_writer_lock(&element_lock);
1108 for (list = driver_list; list; list = list->next) {
1109 struct connman_driver *driver = list->data;
1111 if (match_driver(element, driver) == FALSE)
1114 DBG("driver %p name %s", driver, driver->name);
1116 if (driver->probe(element) == 0) {
1117 connman_element_lock(element);
1118 element->driver = driver;
1119 connman_element_unlock(element);
1124 g_static_rw_lock_writer_unlock(&element_lock);
1127 static gboolean remove_element(GNode *node, gpointer user_data)
1129 struct connman_element *element = node->data;
1130 struct connman_element *root = user_data;
1132 DBG("element %p name %s", element, element->name);
1134 if (element == root)
1137 if (element->driver) {
1138 if (element->driver->remove)
1139 element->driver->remove(element);
1141 connman_element_lock(element);
1142 element->driver = NULL;
1143 connman_element_unlock(element);
1147 g_node_unlink(node);
1148 g_node_destroy(node);
1151 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1152 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1153 DBUS_TYPE_OBJECT_PATH, &element->path,
1156 g_dbus_unregister_interface(connection, element->path,
1157 CONNMAN_ELEMENT_INTERFACE);
1159 connman_element_unref(element);
1164 static void unregister_element(gpointer data, gpointer user_data)
1166 struct connman_element *element = data;
1169 DBG("element %p name %s", element, element->name);
1171 g_static_rw_lock_writer_lock(&element_lock);
1173 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1176 g_node_traverse(node, G_POST_ORDER,
1177 G_TRAVERSE_ALL, -1, remove_element, NULL);
1179 g_static_rw_lock_writer_unlock(&element_lock);
1182 static void unregister_children(gpointer data, gpointer user_data)
1184 struct connman_element *element = data;
1187 DBG("element %p name %s", element, element->name);
1189 g_static_rw_lock_writer_lock(&element_lock);
1191 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1194 g_node_traverse(node, G_POST_ORDER,
1195 G_TRAVERSE_ALL, -1, remove_element, element);
1197 g_static_rw_lock_writer_unlock(&element_lock);
1200 int __connman_element_init(DBusConnection *conn, const char *device)
1202 struct connman_element *element;
1204 DBG("conn %p", conn);
1206 connection = dbus_connection_ref(conn);
1207 if (connection == NULL)
1210 device_filter = g_strdup(device);
1212 g_static_rw_lock_writer_lock(&element_lock);
1214 element = connman_element_create("root");
1216 element->path = g_strdup("/");
1217 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1219 create_default_properties(element);
1221 element_root = g_node_new(element);
1223 g_static_rw_lock_writer_unlock(&element_lock);
1225 thread_register = g_thread_pool_new(register_element,
1226 NULL, 1, FALSE, NULL);
1227 thread_unregister = g_thread_pool_new(unregister_element,
1228 NULL, 1, FALSE, NULL);
1229 thread_unregister_children = g_thread_pool_new(unregister_children,
1230 NULL, 1, FALSE, NULL);
1232 __connman_device_init();
1237 static gboolean free_driver(GNode *node, gpointer data)
1239 struct connman_element *element = node->data;
1241 DBG("element %p name %s", element, element->name);
1243 if (element->driver) {
1244 if (element->driver->remove)
1245 element->driver->remove(element);
1247 connman_element_lock(element);
1248 element->driver = NULL;
1249 connman_element_unlock(element);
1255 static gboolean free_node(GNode *node, gpointer data)
1257 struct connman_element *element = node->data;
1259 DBG("element %p name %s", element, element->name);
1261 if (g_node_depth(node) > 1)
1262 g_thread_pool_push(thread_unregister, element, NULL);
1267 void __connman_element_cleanup(void)
1271 __connman_device_cleanup();
1273 g_thread_pool_free(thread_register, TRUE, TRUE);
1274 thread_register = NULL;
1276 g_static_rw_lock_writer_lock(&element_lock);
1277 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1279 g_static_rw_lock_writer_unlock(&element_lock);
1281 g_static_rw_lock_writer_lock(&element_lock);
1282 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1284 g_static_rw_lock_writer_unlock(&element_lock);
1286 g_thread_pool_free(thread_unregister, FALSE, TRUE);
1287 thread_unregister = NULL;
1289 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
1290 thread_unregister_children = NULL;
1292 g_static_rw_lock_writer_lock(&element_lock);
1293 g_node_destroy(element_root);
1294 element_root = NULL;
1295 g_static_rw_lock_writer_unlock(&element_lock);
1297 g_free(device_filter);
1299 dbus_connection_unref(connection);