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
33 static DBusConnection *connection;
35 static GStaticRWLock element_lock = G_STATIC_RW_LOCK_INIT;
36 static GNode *element_root = NULL;
38 static GSList *driver_list = NULL;
40 static GThreadPool *thread_register = NULL;
41 static GThreadPool *thread_unregister = NULL;
42 static GThreadPool *thread_unregister_children = NULL;
44 static gchar *device_filter = NULL;
46 static const char *type2string(enum connman_element_type type)
49 case CONNMAN_ELEMENT_TYPE_UNKNOWN:
51 case CONNMAN_ELEMENT_TYPE_ROOT:
53 case CONNMAN_ELEMENT_TYPE_DEVICE:
55 case CONNMAN_ELEMENT_TYPE_NETWORK:
57 case CONNMAN_ELEMENT_TYPE_IPV4:
59 case CONNMAN_ELEMENT_TYPE_IPV6:
61 case CONNMAN_ELEMENT_TYPE_DHCP:
63 case CONNMAN_ELEMENT_TYPE_BOOTP:
65 case CONNMAN_ELEMENT_TYPE_ZEROCONF:
67 case CONNMAN_ELEMENT_TYPE_RESOLVER:
69 case CONNMAN_ELEMENT_TYPE_INTERNET:
76 static const char *subtype2string(enum connman_element_subtype type)
79 case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN:
81 case CONNMAN_ELEMENT_SUBTYPE_ETHERNET:
83 case CONNMAN_ELEMENT_SUBTYPE_WIFI:
85 case CONNMAN_ELEMENT_SUBTYPE_WIMAX:
87 case CONNMAN_ELEMENT_SUBTYPE_MODEM:
89 case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH:
96 static void append_entry(DBusMessageIter *dict,
97 const char *key, int type, void *val)
99 DBusMessageIter entry, value;
100 const char *signature;
102 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
105 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
108 case DBUS_TYPE_BOOLEAN:
109 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
111 case DBUS_TYPE_STRING:
112 signature = DBUS_TYPE_STRING_AS_STRING;
114 case DBUS_TYPE_UINT16:
115 signature = DBUS_TYPE_UINT16_AS_STRING;
117 case DBUS_TYPE_UINT32:
118 signature = DBUS_TYPE_UINT32_AS_STRING;
120 case DBUS_TYPE_OBJECT_PATH:
121 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
124 signature = DBUS_TYPE_VARIANT_AS_STRING;
128 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
130 dbus_message_iter_append_basic(&value, type, val);
131 dbus_message_iter_close_container(&entry, &value);
133 dbus_message_iter_close_container(dict, &entry);
136 static void append_property(DBusMessageIter *dict,
137 struct connman_property *property)
139 if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC) {
140 append_entry(dict, property->name, property->type,
146 static DBusMessage *get_properties(DBusConnection *conn,
147 DBusMessage *msg, void *data)
149 struct connman_element *element = data;
152 DBusMessageIter array, dict;
155 DBG("conn %p", conn);
157 reply = dbus_message_new_method_return(msg);
161 dbus_message_iter_init_append(reply, &array);
163 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
164 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
165 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
166 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
168 if (element->parent != NULL)
169 append_entry(&dict, "Parent",
170 DBUS_TYPE_OBJECT_PATH, &element->parent->path);
172 str = type2string(element->type);
174 append_entry(&dict, "Type", DBUS_TYPE_STRING, &str);
175 str = subtype2string(element->subtype);
177 append_entry(&dict, "Subtype", DBUS_TYPE_STRING, &str);
179 append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &element->enabled);
181 if (element->priority > 0)
182 append_entry(&dict, "Priority",
183 DBUS_TYPE_UINT16, &element->priority);
185 if (element->network.identifier != NULL)
186 append_entry(&dict, "Identifier",
187 DBUS_TYPE_STRING, &element->network.identifier);
189 if (element->ipv4.address != NULL)
190 append_entry(&dict, "IPv4.Address",
191 DBUS_TYPE_STRING, &element->ipv4.address);
192 if (element->ipv4.netmask != NULL)
193 append_entry(&dict, "IPv4.Netmask",
194 DBUS_TYPE_STRING, &element->ipv4.netmask);
195 if (element->ipv4.gateway != NULL)
196 append_entry(&dict, "IPv4.Gateway",
197 DBUS_TYPE_STRING, &element->ipv4.gateway);
199 for (list = element->properties; list; list = list->next) {
200 struct connman_property *property = list->data;
202 append_property(&dict, property);
205 dbus_message_iter_close_container(&array, &dict);
210 static DBusMessage *set_property(DBusConnection *conn,
211 DBusMessage *msg, void *data)
213 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
216 static DBusMessage *do_update(DBusConnection *conn,
217 DBusMessage *msg, void *data)
219 struct connman_element *element = data;
221 DBG("conn %p", conn);
223 if (element->driver == NULL)
224 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
226 if (element->driver->update) {
227 DBG("Calling update callback");
228 element->driver->update(element);
231 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
234 static DBusMessage *do_enable(DBusConnection *conn,
235 DBusMessage *msg, void *data)
237 struct connman_element *element = data;
239 DBG("conn %p", conn);
241 if (element->driver == NULL)
242 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
244 if (element->driver->enable) {
245 DBG("Calling enable callback");
246 element->driver->enable(element);
249 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
252 static DBusMessage *do_disable(DBusConnection *conn,
253 DBusMessage *msg, void *data)
255 struct connman_element *element = data;
257 DBG("conn %p", conn);
259 if (element->driver == NULL)
260 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
262 if (element->driver->disable) {
263 DBG("Calling disable callback");
264 element->driver->disable(element);
267 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
270 static GDBusMethodTable element_methods[] = {
271 { "GetProperties", "", "a{sv}", get_properties },
272 { "SetProperty", "sv", "", set_property },
273 { "Update", "", "", do_update },
274 { "Enable", "", "", do_enable },
275 { "Disable", "", "", do_disable },
279 static GDBusSignalTable element_signals[] = {
280 { "PropertyChanged", "sv" },
284 struct append_filter {
285 enum connman_element_type type;
286 DBusMessageIter *iter;
289 static gboolean append_path(GNode *node, gpointer data)
291 struct connman_element *element = node->data;
292 struct append_filter *filter = data;
294 DBG("element %p name %s", element, element->name);
296 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
299 if (filter->type != CONNMAN_ELEMENT_TYPE_UNKNOWN &&
300 filter->type != element->type)
303 dbus_message_iter_append_basic(filter->iter,
304 DBUS_TYPE_OBJECT_PATH, &element->path);
309 void __connman_element_list(enum connman_element_type type,
310 DBusMessageIter *iter)
312 struct append_filter filter = { type, iter };
316 g_static_rw_lock_reader_lock(&element_lock);
317 g_node_traverse(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
318 append_path, &filter);
319 g_static_rw_lock_reader_unlock(&element_lock);
322 static gint compare_priority(gconstpointer a, gconstpointer b)
324 const struct connman_driver *driver1 = a;
325 const struct connman_driver *driver2 = b;
327 return driver2->priority - driver1->priority;
330 static gboolean match_driver(struct connman_element *element,
331 struct connman_driver *driver)
333 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
336 if (element->type != driver->type &&
337 driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN)
340 if (element->subtype == driver->subtype ||
341 driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
347 static gboolean probe_driver(GNode *node, gpointer data)
349 struct connman_element *element = node->data;
350 struct connman_driver *driver = data;
352 DBG("element %p name %s", element, element->name);
354 if (!element->driver && match_driver(element, driver) == TRUE) {
355 if (driver->probe(element) < 0)
358 connman_element_lock(element);
359 element->driver = driver;
360 connman_element_unlock(element);
367 * connman_driver_register:
368 * @driver: driver definition
370 * Register a new driver
372 * Returns: %0 on success
374 int connman_driver_register(struct connman_driver *driver)
376 DBG("driver %p name %s", driver, driver->name);
378 if (driver->type == CONNMAN_ELEMENT_TYPE_ROOT)
384 g_static_rw_lock_writer_lock(&element_lock);
386 driver_list = g_slist_insert_sorted(driver_list, driver,
389 if (element_root != NULL)
390 g_node_traverse(element_root, G_PRE_ORDER,
391 G_TRAVERSE_ALL, -1, probe_driver, driver);
393 g_static_rw_lock_writer_unlock(&element_lock);
398 static gboolean remove_driver(GNode *node, gpointer data)
400 struct connman_element *element = node->data;
401 struct connman_driver *driver = data;
403 DBG("element %p name %s", element, element->name);
405 if (element->driver == driver) {
407 driver->remove(element);
409 connman_element_lock(element);
410 element->driver = NULL;
411 connman_element_unlock(element);
418 * connman_driver_unregister:
419 * @driver: driver definition
421 * Remove a previously registered driver
423 void connman_driver_unregister(struct connman_driver *driver)
425 DBG("driver %p name %s", driver, driver->name);
427 g_static_rw_lock_writer_lock(&element_lock);
429 driver_list = g_slist_remove(driver_list, driver);
431 if (element_root != NULL)
432 g_node_traverse(element_root, G_POST_ORDER,
433 G_TRAVERSE_ALL, -1, remove_driver, driver);
435 g_static_rw_lock_writer_unlock(&element_lock);
438 struct connman_element *connman_element_create(void)
440 struct connman_element *element;
442 element = g_new0(struct connman_element, 1);
444 DBG("element %p", element);
446 element->refcount = 1;
448 g_static_mutex_init(&element->mutex);
450 element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
451 element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN;
452 element->state = CONNMAN_ELEMENT_STATE_CLOSED;
454 element->enabled = FALSE;
456 element->netdev.index = -1;
461 struct connman_element *connman_element_ref(struct connman_element *element)
463 DBG("element %p name %s refcount %d", element, element->name,
464 g_atomic_int_get(&element->refcount) + 1);
466 g_atomic_int_inc(&element->refcount);
471 void connman_element_unref(struct connman_element *element)
473 DBG("element %p name %s refcount %d", element, element->name,
474 g_atomic_int_get(&element->refcount) - 1);
476 if (g_atomic_int_dec_and_test(&element->refcount) == TRUE) {
479 for (list = element->properties; list; list = list->next) {
480 struct connman_property *property = list->data;
481 if ((property->flags & CONNMAN_PROPERTY_FLAG_STATIC) &&
482 property->type == DBUS_TYPE_STRING)
483 g_free(property->value);
487 g_slist_free(element->properties);
489 g_free(element->ipv4.address);
490 g_free(element->ipv4.netmask);
491 g_free(element->ipv4.gateway);
492 g_free(element->ipv4.network);
493 g_free(element->ipv4.broadcast);
494 g_free(element->ipv4.nameserver);
495 g_free(element->network.identifier);
496 g_free(element->netdev.name);
497 g_free(element->path);
498 g_free(element->name);
503 int connman_element_add_static_property(struct connman_element *element,
504 const char *name, int type, const void *value)
506 struct connman_property *property;
508 DBG("element %p name %s", element, element->name);
510 if (type != DBUS_TYPE_STRING)
513 property = g_try_new0(struct connman_property, 1);
514 if (property == NULL)
517 property->flags = CONNMAN_PROPERTY_FLAG_STATIC;
519 property->name = g_strdup(name);
520 property->type = type;
522 DBG("name %s type %d value %p", name, type, value);
525 case DBUS_TYPE_STRING:
526 property->value = g_strdup(*((const char **) value));
530 connman_element_lock(element);
531 element->properties = g_slist_append(element->properties, property);
532 connman_element_unlock(element);
537 int connman_element_set_property(struct connman_element *element,
538 enum connman_property_type type, const void *value)
541 case CONNMAN_PROPERTY_TYPE_INVALID:
543 case CONNMAN_PROPERTY_TYPE_IPV4_ADDRESS:
544 connman_element_lock(element);
545 g_free(element->ipv4.address);
546 element->ipv4.address = g_strdup(*((const char **) value));
547 connman_element_unlock(element);
549 case CONNMAN_PROPERTY_TYPE_IPV4_NETMASK:
550 connman_element_lock(element);
551 g_free(element->ipv4.netmask);
552 element->ipv4.netmask = g_strdup(*((const char **) value));
553 connman_element_unlock(element);
555 case CONNMAN_PROPERTY_TYPE_IPV4_GATEWAY:
556 connman_element_lock(element);
557 g_free(element->ipv4.gateway);
558 element->ipv4.gateway = g_strdup(*((const char **) value));
559 connman_element_unlock(element);
561 case CONNMAN_PROPERTY_TYPE_IPV4_NAMESERVER:
562 connman_element_lock(element);
563 g_free(element->ipv4.nameserver);
564 element->ipv4.nameserver = g_strdup(*((const char **) value));
565 connman_element_unlock(element);
569 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
570 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
571 DBUS_TYPE_OBJECT_PATH, &element->path,
577 int connman_element_get_value(struct connman_element *element,
578 enum connman_property_type type, void *value)
580 if (element->type == CONNMAN_ELEMENT_TYPE_ROOT)
584 case CONNMAN_PROPERTY_TYPE_INVALID:
586 case CONNMAN_PROPERTY_TYPE_IPV4_ADDRESS:
587 if (element->ipv4.address == NULL)
588 return connman_element_get_value(element->parent,
590 connman_element_lock(element);
591 *((char **) value) = element->ipv4.address;
592 connman_element_unlock(element);
594 case CONNMAN_PROPERTY_TYPE_IPV4_NETMASK:
595 if (element->ipv4.netmask == NULL)
596 return connman_element_get_value(element->parent,
598 connman_element_lock(element);
599 *((char **) value) = element->ipv4.netmask;
600 connman_element_unlock(element);
602 case CONNMAN_PROPERTY_TYPE_IPV4_GATEWAY:
603 if (element->ipv4.gateway == NULL)
604 return connman_element_get_value(element->parent,
606 connman_element_lock(element);
607 *((char **) value) = element->ipv4.gateway;
608 connman_element_unlock(element);
610 case CONNMAN_PROPERTY_TYPE_IPV4_NAMESERVER:
611 if (element->ipv4.nameserver == NULL)
612 return connman_element_get_value(element->parent,
614 connman_element_lock(element);
615 *((char **) value) = element->ipv4.nameserver;
616 connman_element_unlock(element);
623 int connman_element_register(struct connman_element *element,
624 struct connman_element *parent)
626 DBG("element %p name %s parent %p", element, element->name, parent);
628 if (device_filter && element->type == CONNMAN_ELEMENT_TYPE_DEVICE) {
629 if (g_str_equal(device_filter, element->netdev.name) == FALSE)
633 if (connman_element_ref(element) == NULL)
636 connman_element_lock(element);
638 __connman_element_load(element);
640 if (element->name == NULL) {
641 element->name = g_strdup(type2string(element->type));
642 if (element->name == NULL)
646 element->parent = parent;
648 connman_element_unlock(element);
650 if (thread_register != NULL)
651 g_thread_pool_push(thread_register, element, NULL);
656 void connman_element_unregister(struct connman_element *element)
658 DBG("element %p name %s", element, element->name);
660 if (thread_unregister != NULL)
661 g_thread_pool_push(thread_unregister, element, NULL);
664 void connman_element_unregister_children(struct connman_element *element)
666 DBG("element %p name %s", element, element->name);
668 if (thread_unregister_children != NULL)
669 g_thread_pool_push(thread_unregister_children, element, NULL);
672 static gboolean update_element(GNode *node, gpointer user_data)
674 struct connman_element *element = node->data;
676 DBG("element %p name %s", element, element->name);
678 if (element->driver && element->driver->update)
679 element->driver->update(element);
681 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
682 CONNMAN_MANAGER_INTERFACE, "ElementUpdated",
683 DBUS_TYPE_OBJECT_PATH, &element->path,
689 void connman_element_update(struct connman_element *element)
693 DBG("element %p name %s", element, element->name);
695 g_static_rw_lock_reader_lock(&element_lock);
697 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
700 g_node_traverse(node, G_PRE_ORDER,
701 G_TRAVERSE_ALL, -1, update_element, NULL);
703 g_static_rw_lock_reader_unlock(&element_lock);
706 static void register_element(gpointer data, gpointer user_data)
708 struct connman_element *element = data;
709 const gchar *basepath;
713 g_static_rw_lock_writer_lock(&element_lock);
715 connman_element_lock(element);
717 if (element->parent) {
718 node = g_node_find(element_root, G_PRE_ORDER,
719 G_TRAVERSE_ALL, element->parent);
720 basepath = element->parent->path;
722 if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN)
723 element->subtype = element->parent->subtype;
729 element->path = g_strdup_printf("%s/%s", basepath, element->name);
731 connman_element_unlock(element);
733 DBG("element %p path %s", element, element->path);
735 g_node_append_data(node, element);
737 if (g_dbus_register_interface(connection, element->path,
738 CONNMAN_ELEMENT_INTERFACE,
739 element_methods, element_signals,
740 NULL, element, NULL) == FALSE)
741 connman_error("Failed to register %s", element->path);
743 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
744 CONNMAN_MANAGER_INTERFACE, "ElementAdded",
745 DBUS_TYPE_OBJECT_PATH, &element->path,
748 g_static_rw_lock_writer_unlock(&element_lock);
750 __connman_element_store(element);
752 g_static_rw_lock_writer_lock(&element_lock);
754 for (list = driver_list; list; list = list->next) {
755 struct connman_driver *driver = list->data;
757 if (match_driver(element, driver) == FALSE)
760 DBG("driver %p name %s", driver, driver->name);
762 if (driver->probe(element) == 0) {
763 connman_element_lock(element);
764 element->driver = driver;
765 connman_element_unlock(element);
770 g_static_rw_lock_writer_unlock(&element_lock);
773 static gboolean remove_element(GNode *node, gpointer user_data)
775 struct connman_element *element = node->data;
776 struct connman_element *root = user_data;
778 DBG("element %p name %s", element, element->name);
783 if (element->driver) {
784 if (element->driver->remove)
785 element->driver->remove(element);
787 connman_element_lock(element);
788 element->driver = NULL;
789 connman_element_unlock(element);
794 g_node_destroy(node);
797 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
798 CONNMAN_MANAGER_INTERFACE, "ElementRemoved",
799 DBUS_TYPE_OBJECT_PATH, &element->path,
802 g_dbus_unregister_interface(connection, element->path,
803 CONNMAN_ELEMENT_INTERFACE);
805 connman_element_unref(element);
810 static void unregister_element(gpointer data, gpointer user_data)
812 struct connman_element *element = data;
815 DBG("element %p name %s", element, element->name);
817 g_static_rw_lock_writer_lock(&element_lock);
819 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
822 g_node_traverse(node, G_POST_ORDER,
823 G_TRAVERSE_ALL, -1, remove_element, NULL);
825 g_static_rw_lock_writer_unlock(&element_lock);
828 static void unregister_children(gpointer data, gpointer user_data)
830 struct connman_element *element = data;
833 DBG("element %p name %s", element, element->name);
835 g_static_rw_lock_writer_lock(&element_lock);
837 node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element);
840 g_node_traverse(node, G_POST_ORDER,
841 G_TRAVERSE_ALL, -1, remove_element, element);
843 g_static_rw_lock_writer_unlock(&element_lock);
846 int __connman_element_init(DBusConnection *conn, const char *device)
848 struct connman_element *element;
850 DBG("conn %p", conn);
852 connection = dbus_connection_ref(conn);
853 if (connection == NULL)
856 device_filter = g_strdup(device);
858 g_static_rw_lock_writer_lock(&element_lock);
860 element = connman_element_create();
862 element->name = g_strdup("root");
863 element->path = g_strdup("/");
864 element->type = CONNMAN_ELEMENT_TYPE_ROOT;
866 element_root = g_node_new(element);
868 g_static_rw_lock_writer_unlock(&element_lock);
870 thread_register = g_thread_pool_new(register_element,
871 NULL, 1, FALSE, NULL);
872 thread_unregister = g_thread_pool_new(unregister_element,
873 NULL, 1, FALSE, NULL);
874 thread_unregister_children = g_thread_pool_new(unregister_children,
875 NULL, 1, FALSE, NULL);
880 static gboolean free_driver(GNode *node, gpointer data)
882 struct connman_element *element = node->data;
884 DBG("element %p name %s", element, element->name);
886 if (element->driver) {
887 if (element->driver->remove)
888 element->driver->remove(element);
890 connman_element_lock(element);
891 element->driver = NULL;
892 connman_element_unlock(element);
898 static gboolean free_node(GNode *node, gpointer data)
900 struct connman_element *element = node->data;
902 DBG("element %p name %s", element, element->name);
904 if (g_node_depth(node) > 1)
905 g_thread_pool_push(thread_unregister, element, NULL);
910 void __connman_element_cleanup(void)
914 g_thread_pool_free(thread_register, TRUE, TRUE);
915 thread_register = NULL;
917 g_static_rw_lock_writer_lock(&element_lock);
918 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
920 g_static_rw_lock_writer_unlock(&element_lock);
922 g_static_rw_lock_writer_lock(&element_lock);
923 g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
925 g_static_rw_lock_writer_unlock(&element_lock);
927 g_thread_pool_free(thread_unregister, FALSE, TRUE);
928 thread_unregister = NULL;
930 g_thread_pool_free(thread_unregister_children, FALSE, TRUE);
931 thread_unregister_children = NULL;
933 g_static_rw_lock_writer_lock(&element_lock);
934 g_node_destroy(element_root);
936 g_static_rw_lock_writer_unlock(&element_lock);
938 g_free(device_filter);
940 dbus_connection_unref(connection);