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 GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
38 static GNode *element_root = NULL;
40 static GSList *driver_list = NULL;
42 static gchar *device_filter = NULL;
45 enum connman_property_id id;
50 { CONNMAN_PROPERTY_ID_IPV4_METHOD,
51 DBUS_TYPE_STRING, "IPv4.Method", "dhcp" },
52 { CONNMAN_PROPERTY_ID_IPV4_ADDRESS,
53 DBUS_TYPE_STRING, "IPv4.Address" },
54 { CONNMAN_PROPERTY_ID_IPV4_NETMASK,
55 DBUS_TYPE_STRING, "IPv4.Netmask" },
56 { CONNMAN_PROPERTY_ID_IPV4_GATEWAY,
57 DBUS_TYPE_STRING, "IPv4.Gateway" },
58 { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER,
59 DBUS_TYPE_STRING, "IPv4.Nameserver" },
61 { CONNMAN_PROPERTY_ID_WIFI_SECURITY,
62 DBUS_TYPE_STRING, "WiFi.Security" },
63 { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE,
64 DBUS_TYPE_STRING, "WiFi.Passphrase" },
69 static int propid2type(enum connman_property_id id)
73 for (i = 0; propid_table[i].name; i++) {
74 if (propid_table[i].id == id)
75 return propid_table[i].type;
78 return DBUS_TYPE_INVALID;
81 static const char *propid2name(enum connman_property_id id)
85 for (i = 0; propid_table[i].name; i++) {
86 if (propid_table[i].id == id)
87 return propid_table[i].name;
93 static const char *type2string(enum connman_element_type type)
96 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
98 case CONNMAN_ELEMENT_TYPE_ROOT:
100 case CONNMAN_ELEMENT_TYPE_PROFILE:
102 case CONNMAN_ELEMENT_TYPE_DEVICE:
104 case CONNMAN_ELEMENT_TYPE_NETWORK:
106 case CONNMAN_ELEMENT_TYPE_SERVICE:
108 case CONNMAN_ELEMENT_TYPE_IPV4:
110 case CONNMAN_ELEMENT_TYPE_IPV6:
112 case CONNMAN_ELEMENT_TYPE_DHCP:
114 case CONNMAN_ELEMENT_TYPE_BOOTP:
116 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
118 case CONNMAN_ELEMENT_TYPE_RESOLVER:
120 case CONNMAN_ELEMENT_TYPE_CONNECTION:
127 static const char *subtype2string(enum connman_element_subtype type)
130 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
132 case CONNMAN_ELEMENT_SUBTYPE_FAKE:
134 case CONNMAN_ELEMENT_SUBTYPE_NETWORK:
136 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
138 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
140 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
142 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
144 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
151 static const char *policy2string(enum connman_element_policy policy)
154 case CONNMAN_ELEMENT_POLICY_UNKNOWN:
156 case CONNMAN_ELEMENT_POLICY_OFF:
158 case CONNMAN_ELEMENT_POLICY_AUTO:
160 case CONNMAN_ELEMENT_POLICY_IGNORE:
162 case CONNMAN_ELEMENT_POLICY_ASK:
169 static void append_property(DBusMessageIter *dict,
170 struct connman_property *property)
172 if (property->value == NULL)
175 if (property->type == DBUS_TYPE_ARRAY)
176 connman_dbus_dict_append_array(dict, property->name,
177 property->subtype, &property->value, property->size);
179 connman_dbus_dict_append_variant(dict, property->name,
180 property->type, &property->value);
183 static void add_common_properties(struct connman_element *element,
184 DBusMessageIter *dict)
188 if (element->priority > 0)
189 connman_dbus_dict_append_variant(dict, "Priority",
190 DBUS_TYPE_UINT16, &element->priority);
192 if (element->ipv4.address != NULL)
193 connman_dbus_dict_append_variant(dict, "IPv4.Address",
194 DBUS_TYPE_STRING, &element->ipv4.address);
195 if (element->ipv4.netmask != NULL)
196 connman_dbus_dict_append_variant(dict, "IPv4.Netmask",
197 DBUS_TYPE_STRING, &element->ipv4.netmask);
198 if (element->ipv4.gateway != NULL)
199 connman_dbus_dict_append_variant(dict, "IPv4.Gateway",
200 DBUS_TYPE_STRING, &element->ipv4.gateway);
202 if (element->wifi.security != NULL) {
203 const char *passphrase = "";
205 connman_dbus_dict_append_variant(dict, "WiFi.Security",
206 DBUS_TYPE_STRING, &element->wifi.security);
208 if (element->wifi.passphrase != NULL)
209 passphrase = element->wifi.passphrase;
211 connman_dbus_dict_append_variant(dict, "WiFi.Passphrase",
212 DBUS_TYPE_STRING, &passphrase);
215 __connman_element_lock(element);
217 for (list = element->properties; list; list = list->next) {
218 struct connman_property *property = list->data;
220 append_property(dict, property);
223 __connman_element_unlock(element);
226 static void set_common_property(struct connman_element *element,
227 const char *name, DBusMessageIter *value)
231 if (g_str_equal(name, "Priority") == TRUE) {
232 dbus_message_iter_get_basic(value, &element->priority);
236 __connman_element_lock(element);
238 for (list = element->properties; list; list = list->next) {
239 struct connman_property *property = list->data;
242 if (g_str_equal(property->name, name) == FALSE)
245 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
248 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
250 if (property->type == DBUS_TYPE_STRING) {
251 dbus_message_iter_get_basic(value, &str);
252 g_free(property->value);
253 property->value = g_strdup(str);
255 property->value = NULL;
258 __connman_element_unlock(element);
261 static DBusMessage *get_properties(DBusConnection *conn,
262 DBusMessage *msg, void *data)
264 struct connman_element *element = data;
266 DBusMessageIter array, dict;
269 DBG("conn %p", conn);
271 reply = dbus_message_new_method_return(msg);
275 dbus_message_iter_init_append(reply, &array);
277 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
278 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
279 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
280 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
282 if (element->parent != NULL &&
283 element->parent->type != CONNMAN_ELEMENT_TYPE_ROOT) {
284 connman_dbus_dict_append_variant(&dict, "Parent",
285 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
288 str = type2string(element->type);
290 connman_dbus_dict_append_variant(&dict, "Type",
291 DBUS_TYPE_STRING, &str);
292 str = subtype2string(element->subtype);
294 connman_dbus_dict_append_variant(&dict, "Subtype",
295 DBUS_TYPE_STRING, &str);
297 connman_dbus_dict_append_variant(&dict, "Enabled",
298 DBUS_TYPE_BOOLEAN, &element->enabled);
300 add_common_properties(element, &dict);
302 dbus_message_iter_close_container(&array, &dict);
307 static void append_networks(DBusMessageIter *dict)
309 DBusMessageIter entry, value, iter;
310 const char *key = "Networks";
312 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
315 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
317 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
318 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
321 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
322 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
324 __connman_element_list(CONNMAN_ELEMENT_TYPE_NETWORK, &iter);
326 dbus_message_iter_close_container(&value, &iter);
328 dbus_message_iter_close_container(&entry, &value);
330 dbus_message_iter_close_container(dict, &entry);
333 static DBusMessage *get_device_properties(DBusConnection *conn,
334 DBusMessage *msg, void *data)
336 struct connman_element *element = data;
338 DBusMessageIter array, dict;
341 DBG("conn %p", conn);
343 reply = dbus_message_new_method_return(msg);
347 dbus_message_iter_init_append(reply, &array);
349 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
350 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
351 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
352 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
354 str = subtype2string(element->subtype);
356 connman_dbus_dict_append_variant(&dict, "Type",
357 DBUS_TYPE_STRING, &str);
359 str = policy2string(element->policy);
361 connman_dbus_dict_append_variant(&dict, "Policy",
362 DBUS_TYPE_STRING, &str);
364 connman_dbus_dict_append_variant(&dict, "Powered",
365 DBUS_TYPE_BOOLEAN, &element->enabled);
367 append_networks(&dict);
369 add_common_properties(element, &dict);
371 dbus_message_iter_close_container(&array, &dict);
376 static DBusMessage *get_network_properties(DBusConnection *conn,
377 DBusMessage *msg, void *data)
379 struct connman_element *element = data;
381 DBusMessageIter array, dict;
384 DBG("conn %p", conn);
386 reply = dbus_message_new_method_return(msg);
390 dbus_message_iter_init_append(reply, &array);
392 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
393 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
394 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
395 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
397 str = policy2string(element->policy);
399 connman_dbus_dict_append_variant(&dict, "Policy",
400 DBUS_TYPE_STRING, &str);
402 connman_dbus_dict_append_variant(&dict, "Connected",
403 DBUS_TYPE_BOOLEAN, &element->enabled);
405 add_common_properties(element, &dict);
407 dbus_message_iter_close_container(&array, &dict);
412 static DBusMessage *set_network_property(DBusConnection *conn,
413 DBusMessage *msg, void *data)
415 struct connman_element *element = data;
416 DBusMessageIter iter;
417 DBusMessageIter value;
420 DBG("conn %p", conn);
422 if (dbus_message_iter_init(msg, &iter) == FALSE)
423 return __connman_error_invalid_arguments(msg);
425 dbus_message_iter_get_basic(&iter, &name);
426 dbus_message_iter_next(&iter);
427 dbus_message_iter_recurse(&iter, &value);
429 if (__connman_security_check_privileges(msg) < 0)
430 return __connman_error_permission_denied(msg);
432 if (g_str_equal(name, "WiFi.Passphrase") == TRUE) {
435 dbus_message_iter_get_basic(&value, &str);
436 g_free(element->wifi.passphrase);
437 element->wifi.passphrase = g_strdup(str);
439 set_common_property(element, name, &value);
441 __connman_element_store(element);
443 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
446 static DBusMessage *get_connection_properties(DBusConnection *conn,
447 DBusMessage *msg, void *data)
449 struct connman_element *element = data;
451 DBusMessageIter array, dict;
453 DBG("conn %p", conn);
455 reply = dbus_message_new_method_return(msg);
459 dbus_message_iter_init_append(reply, &array);
461 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
462 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
463 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
464 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
466 add_common_properties(element, &dict);
468 dbus_message_iter_close_container(&array, &dict);
473 static DBusMessage *set_property(DBusConnection *conn,
474 DBusMessage *msg, void *data)
476 struct connman_element *element = data;
477 DBusMessageIter iter;
478 DBusMessageIter value;
481 DBG("conn %p", conn);
483 if (dbus_message_iter_init(msg, &iter) == FALSE)
484 return __connman_error_invalid_arguments(msg);
486 dbus_message_iter_get_basic(&iter, &name);
487 dbus_message_iter_next(&iter);
488 dbus_message_iter_recurse(&iter, &value);
490 if (__connman_security_check_privileges(msg) < 0)
491 return __connman_error_permission_denied(msg);
493 set_common_property(element, name, &value);
495 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
498 static DBusMessage *clear_property(DBusConnection *conn,
499 DBusMessage *msg, void *data)
501 struct connman_element *element = data;
505 DBG("conn %p", conn);
507 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
508 DBUS_TYPE_INVALID) == FALSE)
509 return __connman_error_invalid_arguments(msg);
511 if (__connman_security_check_privileges(msg) < 0)
512 return __connman_error_permission_denied(msg);
514 __connman_element_lock(element);
516 for (list = element->properties; list; list = list->next) {
517 struct connman_property *property = list->data;
519 if (g_str_equal(property->name, name) == FALSE)
522 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC)
525 if (property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)
528 property->flags |= CONNMAN_PROPERTY_FLAG_REFERENCE;
530 if (property->type == DBUS_TYPE_STRING)
531 g_free(property->value);
533 property->value = NULL;
536 __connman_element_unlock(element);
538 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
541 static DBusMessage *do_update(DBusConnection *conn,
542 DBusMessage *msg, void *data)
544 struct connman_element *element = data;
546 DBG("conn %p", conn);
548 if (element->enabled == FALSE)
549 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
551 if (element->driver && element->driver->update) {
552 DBG("Calling update callback");
553 element->driver->update(element);
556 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
559 static DBusMessage *do_enable(DBusConnection *conn,
560 DBusMessage *msg, void *data)
562 struct connman_element *element = data;
564 DBG("conn %p", conn);
566 if (element->enabled == TRUE)
567 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
569 if (element->driver && element->driver->enable) {
570 DBG("Calling enable callback");
571 if (element->driver->enable(element) < 0)
572 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
575 element->enabled = TRUE;
577 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
578 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
579 DBUS_TYPE_OBJECT_PATH, &element->path,
582 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
585 static DBusMessage *do_disable(DBusConnection *conn,
586 DBusMessage *msg, void *data)
588 struct connman_element *element = data;
590 DBG("conn %p", conn);
592 if (element->enabled == FALSE)
593 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
595 if (element->driver && element->driver->disable) {
596 DBG("Calling disable callback");
597 if (element->driver->disable(element) < 0)
598 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
601 element->enabled = FALSE;
603 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
604 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
605 DBUS_TYPE_OBJECT_PATH, &element->path,
608 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
611 static GDBusMethodTable element_methods[] = {
612 { "GetProperties", "", "a{sv}", get_properties },
613 { "SetProperty", "sv", "", set_property },
614 { "ClearProperty", "s", "", clear_property },
615 { "Update", "", "", do_update },
616 { "Enable", "", "", do_enable },
617 { "Disable", "", "", do_disable },
621 static GDBusSignalTable element_signals[] = {
622 { "PropertyChanged", "sv" },
626 static GDBusMethodTable device_methods[] = {
627 { "GetProperties", "", "a{sv}", get_device_properties },
631 static GDBusMethodTable network_methods[] = {
632 { "GetProperties", "", "a{sv}", get_network_properties },
633 { "SetProperty", "sv", "", set_network_property },
637 static GDBusMethodTable connection_methods[] = {
638 { "GetProperties", "", "a{sv}", get_connection_properties },
642 struct append_filter {
643 enum connman_element_type type;
644 DBusMessageIter *iter;
647 static gboolean append_path(GNode *node, gpointer user_data)
649 struct connman_element *element = node->data;
650 struct append_filter *filter = user_data;
652 DBG("element %p name %s", element, element->name);
654 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
657 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
658 filter->type != element->type)
661 dbus_message_iter_append_basic(filter->iter,
662 DBUS_TYPE_OBJECT_PATH, &element->path);
667 void __connman_element_list(enum connman_element_type type,
668 DBusMessageIter *iter)
670 struct append_filter filter = { type, iter };
674 g_static_rw_lock_reader_lock(&element_lock);
675 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
676 append_path, &filter);
677 g_static_rw_lock_reader_unlock(&element_lock);
681 enum connman_element_type type;
685 static gboolean count_element(GNode *node, gpointer user_data)
687 struct connman_element *element = node->data;
688 struct count_data *data = user_data;
690 DBG("element %p name %s", element, element->name);
692 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
695 if (data->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
696 data->type != element->type)
704 int __connman_element_count(enum connman_element_type type)
706 struct count_data data = { type, 0 };
710 g_static_rw_lock_reader_lock(&element_lock);
711 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
712 count_element, &data);
713 g_static_rw_lock_reader_unlock(&element_lock);
718 static gint compare_priority(gconstpointer a, gconstpointer b)
720 const struct connman_driver *driver1 = a;
721 const struct connman_driver *driver2 = b;
723 return driver2->priority - driver1->priority;
726 static gboolean match_driver(struct connman_element *element,
727 struct connman_driver *driver)
729 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
732 if (element->type != driver->type &&
733 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
736 if (element->subtype == driver->subtype ||
737 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
743 static gboolean probe_driver(GNode *node, gpointer data)
745 struct connman_element *element = node->data;
746 struct connman_driver *driver = data;
748 DBG("element %p name %s", element, element->name);
750 if (!element->driver && match_driver(element, driver) == TRUE) {
751 if (driver->probe(element) < 0)
754 __connman_element_lock(element);
755 element->driver = driver;
756 __connman_element_unlock(element);
762 void __connman_driver_rescan(struct connman_driver *driver)
764 DBG("driver %p name %s", driver, driver->name);
769 g_static_rw_lock_writer_lock(&element_lock);
771 if (element_root != NULL)
772 g_node_traverse(element_root, G_PRE_ORDER,
773 G_TRAVERSE_ALL, -1, probe_driver, driver);
775 g_static_rw_lock_writer_unlock(&element_lock);
779 * connman_driver_register:
780 * @driver: driver definition
782 * Register a new driver
784 * Returns: %0 on success
786 int connman_driver_register(struct connman_driver *driver)
788 DBG("driver %p name %s", driver, driver->name);
790 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
796 g_static_rw_lock_writer_lock(&element_lock);
798 driver_list = g_slist_insert_sorted(driver_list, driver,
801 if (element_root != NULL)
802 g_node_traverse(element_root, G_PRE_ORDER,
803 G_TRAVERSE_ALL, -1, probe_driver, driver);
805 g_static_rw_lock_writer_unlock(&element_lock);
810 static gboolean remove_driver(GNode *node, gpointer data)
812 struct connman_element *element = node->data;
813 struct connman_driver *driver = data;
815 DBG("element %p name %s", element, element->name);
817 if (element->driver == driver) {
819 driver->remove(element);
821 __connman_element_lock(element);
822 element->driver = NULL;
823 __connman_element_unlock(element);
830 * connman_driver_unregister:
831 * @driver: driver definition
833 * Remove a previously registered driver
835 void connman_driver_unregister(struct connman_driver *driver)
837 DBG("driver %p name %s", driver, driver->name);
839 g_static_rw_lock_writer_lock(&element_lock);
841 driver_list = g_slist_remove(driver_list, driver);
843 if (element_root != NULL)
844 g_node_traverse(element_root, G_POST_ORDER,
845 G_TRAVERSE_ALL, -1, remove_driver, driver);
847 g_static_rw_lock_writer_unlock(&element_lock);
851 * connman_element_create:
852 * @name: element name
854 * Allocate a new element and assign the given #name to it. If the name
855 * is #NULL, it will be later on created based on the element type.
857 * Returns: a newly-allocated #connman_element structure
859 struct connman_element *connman_element_create(const char *name)
861 struct connman_element *element;
863 element = g_try_new0(struct connman_element, 1);
867 DBG("element %p", element);
869 element->refcount = 1;
871 element->name = g_strdup(name);
872 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
873 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
874 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
875 element->policy = CONNMAN_ELEMENT_POLICY_AUTO;
877 element->enabled = FALSE;
882 struct connman_element *connman_element_ref(struct connman_element *element)
884 DBG("element %p name %s refcount %d", element, element->name,
885 g_atomic_int_get(&element->refcount) + 1);
887 g_atomic_int_inc(&element->refcount);
892 static void free_properties(struct connman_element *element)
896 DBG("element %p name %s", element, element->name);
898 __connman_element_lock(element);
900 for (list = element->properties; list; list = list->next) {
901 struct connman_property *property = list->data;
903 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) {
904 if (property->type == DBUS_TYPE_STRING)
905 g_free(property->value);
906 if (property->type == DBUS_TYPE_ARRAY &&
907 property->subtype == DBUS_TYPE_BYTE)
908 g_free(property->value);
914 g_slist_free(element->properties);
916 element->properties = NULL;
918 __connman_element_unlock(element);
921 void connman_element_unref(struct connman_element *element)
923 DBG("element %p name %s refcount %d", element, element->name,
924 g_atomic_int_get(&element->refcount) - 1);
926 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
927 free_properties(element);
928 g_free(element->ipv4.address);
929 g_free(element->ipv4.netmask);
930 g_free(element->ipv4.gateway);
931 g_free(element->ipv4.network);
932 g_free(element->ipv4.broadcast);
933 g_free(element->ipv4.nameserver);
934 g_free(element->path);
935 g_free(element->name);
940 int connman_element_add_static_property(struct connman_element *element,
941 const char *name, int type, const void *value)
943 struct connman_property *property;
945 DBG("element %p name %s", element, element->name);
947 if (type != DBUS_TYPE_STRING)
950 property = g_try_new0(struct connman_property, 1);
951 if (property == NULL)
954 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
955 property->id = CONNMAN_PROPERTY_ID_INVALID;
956 property->name = g_strdup(name);
957 property->type = type;
959 DBG("name %s type %d value %p", name, type, value);
962 case DBUS_TYPE_STRING:
963 property->value = g_strdup(*((const char **) value));
967 __connman_element_lock(element);
968 element->properties = g_slist_append(element->properties, property);
969 __connman_element_unlock(element);
974 int connman_element_add_static_array_property(struct connman_element *element,
975 const char *name, int type, const void *value, int len)
977 struct connman_property *property;
979 DBG("element %p name %s", element, element->name);
981 if (type != DBUS_TYPE_BYTE)
984 property = g_try_new0(struct connman_property, 1);
985 if (property == NULL)
988 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
989 property->id = CONNMAN_PROPERTY_ID_INVALID;
990 property->name = g_strdup(name);
991 property->type = DBUS_TYPE_ARRAY;
992 property->subtype = type;
994 DBG("name %s type %d value %p", name, type, value);
998 property->value = g_try_malloc(len);
999 if (property->value != NULL) {
1000 memcpy(property->value,
1001 *((const unsigned char **) value), len);
1002 property->size = len;
1007 __connman_element_lock(element);
1008 element->properties = g_slist_append(element->properties, property);
1009 __connman_element_unlock(element);
1014 static void *get_reference_value(struct connman_element *element,
1015 enum connman_property_id id)
1019 DBG("element %p name %s", element, element->name);
1021 for (list = element->properties; list; list = list->next) {
1022 struct connman_property *property = list->data;
1024 if (property->id != id)
1027 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
1028 return property->value;
1031 if (element->parent == NULL)
1034 return get_reference_value(element->parent, id);
1037 static void set_reference_properties(struct connman_element *element)
1041 DBG("element %p name %s", element, element->name);
1043 for (list = element->properties; list; list = list->next) {
1044 struct connman_property *property = list->data;
1046 if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE))
1049 property->value = get_reference_value(element->parent,
1054 static struct connman_property *create_property(struct connman_element *element,
1055 enum connman_property_id id)
1057 struct connman_property *property;
1060 DBG("element %p name %s", element, element->name);
1062 __connman_element_lock(element);
1064 for (list = element->properties; list; list = list->next) {
1065 property = list->data;
1067 if (property->id == id)
1071 property = g_try_new0(struct connman_property, 1);
1072 if (property == NULL)
1075 property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE;
1077 property->name = g_strdup(propid2name(id));
1078 property->type = propid2type(id);
1080 if (property->name == NULL) {
1086 element->properties = g_slist_append(element->properties, property);
1089 __connman_element_unlock(element);
1094 static void create_default_properties(struct connman_element *element)
1096 struct connman_property *property;
1099 DBG("element %p name %s", element, element->name);
1101 for (i = 0; propid_table[i].name; i++) {
1102 DBG("property %s", propid_table[i].name);
1104 property = create_property(element, propid_table[i].id);
1106 property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE;
1108 if (propid_table[i].type != DBUS_TYPE_STRING)
1111 if (propid_table[i].value)
1112 property->value = g_strdup(propid_table[i].value);
1114 property->value = g_strdup("");
1118 static int define_properties_valist(struct connman_element *element,
1121 enum connman_property_id id;
1123 DBG("element %p name %s", element, element->name);
1125 id = va_arg(args, enum connman_property_id);
1127 while (id != CONNMAN_PROPERTY_ID_INVALID) {
1129 DBG("property %d", id);
1131 create_property(element, id);
1133 id = va_arg(args, enum connman_property_id);
1140 * connman_element_define_properties:
1141 * @element: an element
1142 * @varargs: list of property identifiers
1144 * Define the valid properties for an element.
1146 * Returns: %0 on success
1148 int connman_element_define_properties(struct connman_element *element, ...)
1153 DBG("element %p name %s", element, element->name);
1155 va_start(args, element);
1157 err = define_properties_valist(element, args);
1164 int connman_element_create_property(struct connman_element *element,
1165 const char *name, int type)
1170 int connman_element_set_property(struct connman_element *element,
1171 enum connman_property_id id, const void *value)
1174 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1175 __connman_element_lock(element);
1176 g_free(element->ipv4.address);
1177 element->ipv4.address = g_strdup(*((const char **) value));
1178 __connman_element_unlock(element);
1180 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1181 __connman_element_lock(element);
1182 g_free(element->ipv4.netmask);
1183 element->ipv4.netmask = g_strdup(*((const char **) value));
1184 __connman_element_unlock(element);
1186 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1187 __connman_element_lock(element);
1188 g_free(element->ipv4.gateway);
1189 element->ipv4.gateway = g_strdup(*((const char **) value));
1190 __connman_element_unlock(element);
1192 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1193 __connman_element_lock(element);
1194 g_free(element->ipv4.nameserver);
1195 element->ipv4.nameserver = g_strdup(*((const char **) value));
1196 __connman_element_unlock(element);
1198 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1199 __connman_element_lock(element);
1200 g_free(element->wifi.security);
1201 element->wifi.security = g_strdup(*((const char **) value));
1202 __connman_element_unlock(element);
1204 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1205 __connman_element_lock(element);
1206 g_free(element->wifi.passphrase);
1207 element->wifi.passphrase = g_strdup(*((const char **) value));
1208 __connman_element_unlock(element);
1214 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1215 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1216 DBUS_TYPE_OBJECT_PATH, &element->path,
1222 int connman_element_get_value(struct connman_element *element,
1223 enum connman_property_id id, void *value)
1225 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
1229 case CONNMAN_PROPERTY_ID_IPV4_ADDRESS:
1230 if (element->ipv4.address == NULL)
1231 return connman_element_get_value(element->parent,
1233 __connman_element_lock(element);
1234 *((char **) value) = element->ipv4.address;
1235 __connman_element_unlock(element);
1237 case CONNMAN_PROPERTY_ID_IPV4_NETMASK:
1238 if (element->ipv4.netmask == NULL)
1239 return connman_element_get_value(element->parent,
1241 __connman_element_lock(element);
1242 *((char **) value) = element->ipv4.netmask;
1243 __connman_element_unlock(element);
1245 case CONNMAN_PROPERTY_ID_IPV4_GATEWAY:
1246 if (element->ipv4.gateway == NULL)
1247 return connman_element_get_value(element->parent,
1249 __connman_element_lock(element);
1250 *((char **) value) = element->ipv4.gateway;
1251 __connman_element_unlock(element);
1253 case CONNMAN_PROPERTY_ID_IPV4_NAMESERVER:
1254 if (element->ipv4.nameserver == NULL)
1255 return connman_element_get_value(element->parent,
1257 __connman_element_lock(element);
1258 *((char **) value) = element->ipv4.nameserver;
1259 __connman_element_unlock(element);
1261 case CONNMAN_PROPERTY_ID_WIFI_SECURITY:
1262 if (element->wifi.security == NULL)
1263 return connman_element_get_value(element->parent,
1265 __connman_element_lock(element);
1266 *((char **) value) = element->wifi.security;
1267 __connman_element_unlock(element);
1269 case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE:
1270 if (element->wifi.passphrase == NULL)
1271 return connman_element_get_value(element->parent,
1273 __connman_element_lock(element);
1274 *((char **) value) = element->wifi.passphrase;
1275 __connman_element_unlock(element);
1284 gboolean connman_element_get_static_property(struct connman_element *element,
1285 const char *name, void *value)
1288 gboolean found = FALSE;
1290 DBG("element %p name %s", element, element->name);
1292 __connman_element_lock(element);
1294 for (list = element->properties; list; list = list->next) {
1295 struct connman_property *property = list->data;
1297 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1300 if (g_str_equal(property->name, name) == TRUE) {
1301 *((char **) value) = property->value;
1307 __connman_element_unlock(element);
1312 gboolean connman_element_get_static_array_property(struct connman_element *element,
1313 const char *name, void *value, int *len)
1316 gboolean found = FALSE;
1318 DBG("element %p name %s", element, element->name);
1320 __connman_element_lock(element);
1322 for (list = element->properties; list; list = list->next) {
1323 struct connman_property *property = list->data;
1325 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1328 if (g_str_equal(property->name, name) == TRUE) {
1329 *((char **) value) = property->value;
1330 *len = property->size;
1336 __connman_element_unlock(element);
1341 gboolean connman_element_match_static_property(struct connman_element *element,
1342 const char *name, const void *value)
1345 gboolean result = FALSE;
1347 DBG("element %p name %s", element, element->name);
1349 __connman_element_lock(element);
1351 for (list = element->properties; list; list = list->next) {
1352 struct connman_property *property = list->data;
1354 if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC))
1357 if (g_str_equal(property->name, name) == FALSE)
1360 if (property->type == DBUS_TYPE_STRING)
1361 result = g_str_equal(property->value,
1362 *((const char **) value));
1368 __connman_element_unlock(element);
1373 static void append_devices(DBusMessageIter *entry)
1375 DBusMessageIter value, iter;
1376 const char *key = "Devices";
1378 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1380 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1381 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1384 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1385 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1387 //__connman_element_list(CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
1389 dbus_message_iter_close_container(&value, &iter);
1391 dbus_message_iter_close_container(entry, &value);
1394 static void emit_devices_signal(DBusConnection *conn)
1396 DBusMessage *signal;
1397 DBusMessageIter entry;
1399 DBG("conn %p", conn);
1401 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1402 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1406 dbus_message_iter_init_append(signal, &entry);
1408 append_devices(&entry);
1410 g_dbus_send_message(conn, signal);
1413 static void append_connections(DBusMessageIter *entry)
1415 DBusMessageIter value, iter;
1416 const char *key = "Connections";
1418 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1420 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1421 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
1424 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
1425 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
1427 //__connman_element_list(CONNMAN_ELEMENT_TYPE_CONNECTION, &iter);
1429 dbus_message_iter_close_container(&value, &iter);
1431 dbus_message_iter_close_container(entry, &value);
1434 static void emit_connections_signal(DBusConnection *conn)
1436 DBusMessage *signal;
1437 DBusMessageIter entry;
1439 DBG("conn %p", conn);
1441 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1442 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1446 dbus_message_iter_init_append(signal, &entry);
1448 append_connections(&entry);
1450 g_dbus_send_message(conn, signal);
1453 static void append_state(DBusMessageIter *entry, const char *state)
1455 DBusMessageIter value;
1456 const char *key = "State";
1458 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
1460 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
1461 DBUS_TYPE_STRING_AS_STRING, &value);
1463 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &state);
1465 dbus_message_iter_close_container(entry, &value);
1468 static void emit_state_change(DBusConnection *conn, const char *state)
1470 DBusMessage *signal;
1471 DBusMessageIter entry;
1473 DBG("conn %p", conn);
1475 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1476 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
1480 dbus_message_iter_init_append(signal, &entry);
1482 append_state(&entry, state);
1484 g_dbus_send_message(conn, signal);
1487 static void register_element(gpointer data, gpointer user_data)
1489 struct connman_element *element = data;
1490 const gchar *basepath;
1494 g_static_rw_lock_writer_lock(&element_lock);
1496 __connman_element_lock(element);
1498 if (element->parent) {
1499 node = g_node_find(element_root, G_PRE_ORDER,
1500 G_TRAVERSE_ALL, element->parent);
1501 basepath = element->parent->path;
1503 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
1504 element->subtype = element->parent->subtype;
1506 element->parent = element_root->data;
1508 node = element_root;
1512 element->path = g_strdup_printf("%s/%s", basepath, element->name);
1514 set_reference_properties(element);
1516 __connman_element_unlock(element);
1518 DBG("element %p path %s", element, element->path);
1520 __connman_element_load(element);
1522 g_node_append_data(node, element);
1524 if (g_dbus_register_interface(connection, element->path,
1525 CONNMAN_ELEMENT_INTERFACE,
1526 element_methods, element_signals,
1527 NULL, element, NULL) == FALSE)
1528 connman_error("Failed to register %s element", element->path);
1530 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
1531 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
1532 if (g_dbus_register_interface(connection, element->path,
1533 CONNMAN_DEVICE_INTERFACE,
1534 device_methods, element_signals,
1535 NULL, element, NULL) == FALSE)
1536 connman_error("Failed to register %s device",
1539 emit_devices_signal(connection);
1542 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) {
1543 if (g_dbus_register_interface(connection, element->path,
1544 CONNMAN_NETWORK_INTERFACE,
1545 network_methods, element_signals,
1546 NULL, element, NULL) == FALSE)
1547 connman_error("Failed to register %s network",
1551 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1552 if (g_dbus_register_interface(connection, element->path,
1553 CONNMAN_CONNECTION_INTERFACE,
1554 connection_methods, element_signals,
1555 NULL, element, NULL) == FALSE)
1556 connman_error("Failed to register %s connection",
1559 emit_connections_signal(connection);
1560 emit_state_change(connection, "online");
1564 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1565 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
1566 DBUS_TYPE_OBJECT_PATH, &element->path,
1569 g_static_rw_lock_writer_unlock(&element_lock);
1571 __connman_element_store(element);
1573 g_static_rw_lock_writer_lock(&element_lock);
1575 for (list = driver_list; list; list = list->next) {
1576 struct connman_driver *driver = list->data;
1578 if (match_driver(element, driver) == FALSE)
1581 DBG("driver %p name %s", driver, driver->name);
1583 if (driver->probe(element) == 0) {
1584 __connman_element_lock(element);
1585 element->driver = driver;
1586 __connman_element_unlock(element);
1591 g_static_rw_lock_writer_unlock(&element_lock);
1595 * connman_element_register:
1596 * @element: the element to register
1597 * @parent: the parent to register the element with
1599 * Register an element with the core. It will be register under the given
1600 * parent of if %NULL is provided under the root element.
1602 * Returns: %0 on success
1604 int connman_element_register(struct connman_element *element,
1605 struct connman_element *parent)
1607 DBG("element %p name %s parent %p", element, element->name, parent);
1609 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
1610 if (g_pattern_match_simple(device_filter,
1611 element->name) == FALSE) {
1612 DBG("ignoring %s device", element->name);
1617 if (connman_element_ref(element) == NULL)
1620 __connman_element_lock(element);
1622 if (element->name == NULL) {
1623 element->name = g_strdup(type2string(element->type));
1624 if (element->name == NULL) {
1625 __connman_element_unlock(element);
1630 element->parent = parent;
1632 __connman_element_unlock(element);
1634 register_element(element, NULL);
1639 static gboolean remove_element(GNode *node, gpointer user_data)
1641 struct connman_element *element = node->data;
1642 struct connman_element *root = user_data;
1644 DBG("element %p name %s", element, element->name);
1646 if (element == root)
1649 if (element->driver) {
1650 if (element->driver->remove)
1651 element->driver->remove(element);
1653 __connman_element_lock(element);
1654 element->driver = NULL;
1655 __connman_element_unlock(element);
1659 g_node_unlink(node);
1660 g_node_destroy(node);
1663 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1664 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
1665 DBUS_TYPE_OBJECT_PATH, &element->path,
1668 if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) {
1669 emit_state_change(connection, "offline");
1670 emit_connections_signal(connection);
1672 g_dbus_unregister_interface(connection, element->path,
1673 CONNMAN_CONNECTION_INTERFACE);
1676 if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK)
1677 g_dbus_unregister_interface(connection, element->path,
1678 CONNMAN_NETWORK_INTERFACE);
1680 if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE &&
1681 element->subtype != CONNMAN_ELEMENT_SUBTYPE_NETWORK) {
1682 emit_devices_signal(connection);
1684 g_dbus_unregister_interface(connection, element->path,
1685 CONNMAN_DEVICE_INTERFACE);
1688 g_dbus_unregister_interface(connection, element->path,
1689 CONNMAN_ELEMENT_INTERFACE);
1691 connman_element_unref(element);
1696 static void unregister_element(gpointer data, gpointer user_data)
1698 struct connman_element *element = data;
1701 DBG("element %p name %s", element, element->name);
1703 g_static_rw_lock_writer_lock(&element_lock);
1705 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1708 g_node_traverse(node, G_POST_ORDER,
1709 G_TRAVERSE_ALL, -1, remove_element, NULL);
1711 g_static_rw_lock_writer_unlock(&element_lock);
1714 void connman_element_unregister(struct connman_element *element)
1716 DBG("element %p name %s", element, element->name);
1718 unregister_element(element, NULL);
1721 static void unregister_children(gpointer data, gpointer user_data)
1723 struct connman_element *element = data;
1726 DBG("element %p name %s", element, element->name);
1728 g_static_rw_lock_writer_lock(&element_lock);
1730 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1733 g_node_traverse(node, G_POST_ORDER,
1734 G_TRAVERSE_ALL, -1, remove_element, element);
1736 g_static_rw_lock_writer_unlock(&element_lock);
1739 void connman_element_unregister_children(struct connman_element *element)
1741 DBG("element %p name %s", element, element->name);
1743 unregister_children(element, NULL);
1746 static gboolean update_element(GNode *node, gpointer user_data)
1748 struct connman_element *element = node->data;
1750 DBG("element %p name %s", element, element->name);
1752 if (element->driver && element->driver->update)
1753 element->driver->update(element);
1755 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
1756 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
1757 DBUS_TYPE_OBJECT_PATH, &element->path,
1763 void connman_element_update(struct connman_element *element)
1767 DBG("element %p name %s", element, element->name);
1769 g_static_rw_lock_reader_lock(&element_lock);
1771 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
1774 g_node_traverse(node, G_PRE_ORDER,
1775 G_TRAVERSE_ALL, -1, update_element, NULL);
1777 g_static_rw_lock_reader_unlock(&element_lock);
1780 int connman_element_set_enabled(struct connman_element *element,
1783 if (element->enabled == enabled)
1786 element->enabled = enabled;
1788 connman_element_update(element);
1793 int __connman_element_init(DBusConnection *conn, const char *device)
1795 struct connman_element *element;
1797 DBG("conn %p", conn);
1799 connection = dbus_connection_ref(conn);
1800 if (connection == NULL)
1803 device_filter = g_strdup(device);
1805 g_static_rw_lock_writer_lock(&element_lock);
1807 element = connman_element_create("root");
1809 element->path = g_strdup("/");
1810 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
1812 create_default_properties(element);
1814 element_root = g_node_new(element);
1816 g_static_rw_lock_writer_unlock(&element_lock);
1818 __connman_device_init();
1823 static gboolean free_driver(GNode *node, gpointer data)
1825 struct connman_element *element = node->data;
1827 DBG("element %p name %s", element, element->name);
1829 if (element->driver) {
1830 if (element->driver->remove)
1831 element->driver->remove(element);
1833 __connman_element_lock(element);
1834 element->driver = NULL;
1835 __connman_element_unlock(element);
1841 static gboolean free_node(GNode *node, gpointer data)
1843 struct connman_element *element = node->data;
1845 DBG("element %p name %s", element, element->name);
1847 if (g_node_depth(node) > 1)
1848 unregister_element(element, NULL);
1853 void __connman_element_cleanup(void)
1857 __connman_device_cleanup();
1859 g_static_rw_lock_writer_lock(&element_lock);
1860 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1862 g_static_rw_lock_writer_unlock(&element_lock);
1864 g_static_rw_lock_writer_lock(&element_lock);
1865 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
1867 g_static_rw_lock_writer_unlock(&element_lock);
1869 g_static_rw_lock_writer_lock(&element_lock);
1870 g_node_destroy(element_root);
1871 element_root = NULL;
1872 g_static_rw_lock_writer_unlock(&element_lock);
1874 g_free(device_filter);
1876 dbus_connection_unref(connection);