5 * Copyright (C) 2007-2009 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 = NULL;
35 struct connman_device {
36 struct connman_element element;
37 enum connman_device_type type;
38 enum connman_device_mode mode;
39 connman_bool_t secondary;
40 connman_bool_t powered;
41 connman_bool_t carrier;
42 connman_bool_t scanning;
43 connman_bool_t disconnected;
44 connman_uint16_t scan_interval;
51 unsigned int connections;
53 struct connman_ipconfig *ipconfig;
55 struct connman_device_driver *driver;
58 connman_bool_t registered;
61 struct connman_network *network;
68 static gboolean device_scan_trigger(gpointer user_data)
70 struct connman_device *device = user_data;
72 DBG("device %p", device);
74 connman_device_set_scanning(device, FALSE);
76 if (device->driver == NULL) {
77 device->scan_timeout = 0;
81 if (device->driver->scan)
82 device->driver->scan(device);
87 static void reset_scan_trigger(struct connman_device *device)
89 if (device->scan_timeout > 0) {
90 g_source_remove(device->scan_timeout);
91 device->scan_timeout = 0;
94 if (device->scan_interval > 0) {
95 guint interval = device->scan_interval;
96 device->scan_timeout = g_timeout_add_seconds(interval,
97 device_scan_trigger, device);
101 static const char *type2description(enum connman_device_type type)
104 case CONNMAN_DEVICE_TYPE_UNKNOWN:
105 case CONNMAN_DEVICE_TYPE_VENDOR:
107 case CONNMAN_DEVICE_TYPE_ETHERNET:
109 case CONNMAN_DEVICE_TYPE_WIFI:
111 case CONNMAN_DEVICE_TYPE_WIMAX:
113 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
115 case CONNMAN_DEVICE_TYPE_GPS:
117 case CONNMAN_DEVICE_TYPE_MBM:
118 case CONNMAN_DEVICE_TYPE_HSO:
119 case CONNMAN_DEVICE_TYPE_NOZOMI:
120 case CONNMAN_DEVICE_TYPE_HUAWEI:
121 case CONNMAN_DEVICE_TYPE_NOVATEL:
128 static const char *type2string(enum connman_device_type type)
131 case CONNMAN_DEVICE_TYPE_UNKNOWN:
132 case CONNMAN_DEVICE_TYPE_VENDOR:
134 case CONNMAN_DEVICE_TYPE_ETHERNET:
136 case CONNMAN_DEVICE_TYPE_WIFI:
138 case CONNMAN_DEVICE_TYPE_WIMAX:
140 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
142 case CONNMAN_DEVICE_TYPE_GPS:
144 case CONNMAN_DEVICE_TYPE_MBM:
145 case CONNMAN_DEVICE_TYPE_HSO:
146 case CONNMAN_DEVICE_TYPE_HUAWEI:
147 case CONNMAN_DEVICE_TYPE_NOZOMI:
148 case CONNMAN_DEVICE_TYPE_NOVATEL:
155 static int set_connected(struct connman_device *device,
156 connman_bool_t connected)
158 if (connected == TRUE) {
159 enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
160 struct connman_element *element;
162 device->disconnected = TRUE;
164 switch (device->element.ipv4.method) {
165 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
166 case CONNMAN_IPCONFIG_METHOD_OFF:
168 case CONNMAN_IPCONFIG_METHOD_STATIC:
169 type = CONNMAN_ELEMENT_TYPE_IPV4;
171 case CONNMAN_IPCONFIG_METHOD_DHCP:
172 type = CONNMAN_ELEMENT_TYPE_DHCP;
176 element = connman_element_create(NULL);
177 if (element != NULL) {
178 struct connman_service *service;
180 element->type = type;
181 element->index = device->element.index;
183 if (connman_element_register(element,
184 &device->element) < 0)
185 connman_element_unref(element);
187 device->disconnected = FALSE;
189 service = __connman_service_lookup_from_device(device);
190 __connman_service_indicate_state(service,
191 CONNMAN_SERVICE_STATE_CONFIGURATION);
194 struct connman_service *service;
196 connman_element_unregister_children(&device->element);
198 device->disconnected = TRUE;
200 service = __connman_service_lookup_from_device(device);
201 __connman_service_indicate_state(service,
202 CONNMAN_SERVICE_STATE_IDLE);
208 static int set_carrier(struct connman_device *device, connman_bool_t carrier)
210 struct connman_service *service;
213 __connman_profile_add_device(device);
215 __connman_profile_remove_device(device);
217 service = __connman_service_lookup_from_device(device);
218 __connman_service_set_carrier(service, carrier);
220 return set_connected(device, carrier);
223 static int powered_changed(struct connman_device *device)
226 DBusMessageIter entry, value;
227 const char *key = "Powered";
229 signal = dbus_message_new_signal(device->element.path,
230 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
234 dbus_message_iter_init_append(signal, &entry);
236 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
238 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
239 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
240 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
242 dbus_message_iter_close_container(&entry, &value);
244 g_dbus_send_message(connection, signal);
249 static int set_powered(struct connman_device *device, connman_bool_t powered)
251 struct connman_device_driver *driver = device->driver;
254 DBG("device %p powered %d", device, powered);
256 if (device->powered == powered)
262 if (powered == TRUE) {
263 if (driver->enable) {
264 err = driver->enable(device);
265 __connman_notifier_device_type_increase(device->type);
269 g_hash_table_remove_all(device->networks);
271 set_carrier(device, FALSE);
273 if (driver->disable) {
274 err = driver->disable(device);
275 __connman_notifier_device_type_decrease(device->type);
281 device->powered = powered;
282 powered_changed(device);
288 static void append_path(gpointer key, gpointer value, gpointer user_data)
290 struct connman_element *element = value;
291 DBusMessageIter *iter = user_data;
293 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
297 static void append_networks(struct connman_device *device,
298 DBusMessageIter *entry)
300 DBusMessageIter value, iter;
301 const char *key = "Networks";
303 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
305 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
306 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
309 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
310 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
311 g_hash_table_foreach(device->networks, append_path, &iter);
312 dbus_message_iter_close_container(&value, &iter);
314 dbus_message_iter_close_container(entry, &value);
317 static DBusMessage *get_properties(DBusConnection *conn,
318 DBusMessage *msg, void *data)
320 struct connman_device *device = data;
322 DBusMessageIter array, dict, entry;
325 DBG("conn %p", conn);
327 if (__connman_security_check_privilege(msg,
328 CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
329 return __connman_error_permission_denied(msg);
331 reply = dbus_message_new_method_return(msg);
335 dbus_message_iter_init_append(reply, &array);
337 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
338 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
339 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
340 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
342 if (device->name != NULL)
343 connman_dbus_dict_append_variant(&dict, "Name",
344 DBUS_TYPE_STRING, &device->name);
346 str = type2string(device->type);
348 connman_dbus_dict_append_variant(&dict, "Type",
349 DBUS_TYPE_STRING, &str);
351 if (device->address != NULL)
352 connman_dbus_dict_append_variant(&dict, "Address",
353 DBUS_TYPE_STRING, &device->address);
355 if (device->interface != NULL)
356 connman_dbus_dict_append_variant(&dict, "Interface",
357 DBUS_TYPE_STRING, &device->interface);
359 connman_dbus_dict_append_variant(&dict, "Powered",
360 DBUS_TYPE_BOOLEAN, &device->powered);
362 if (device->driver && device->driver->scan)
363 connman_dbus_dict_append_variant(&dict, "Scanning",
364 DBUS_TYPE_BOOLEAN, &device->scanning);
366 switch (device->mode) {
367 case CONNMAN_DEVICE_MODE_UNKNOWN:
369 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
370 __connman_element_append_ipv4(&device->element, &dict);
372 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
373 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
374 if (device->scan_interval > 0)
375 connman_dbus_dict_append_variant(&dict, "ScanInterval",
376 DBUS_TYPE_UINT16, &device->scan_interval);
378 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
380 append_networks(device, &entry);
381 dbus_message_iter_close_container(&dict, &entry);
385 dbus_message_iter_close_container(&array, &dict);
390 static gboolean powered_timeout(gpointer user_data)
392 struct connman_device *device = user_data;
394 DBG("device %p", device);
398 if (device->pending != NULL) {
401 reply = __connman_error_operation_timeout(device->pending);
403 g_dbus_send_message(connection, reply);
405 dbus_message_unref(device->pending);
406 device->pending = NULL;
412 static DBusMessage *set_property(DBusConnection *conn,
413 DBusMessage *msg, void *data)
415 struct connman_device *device = data;
416 DBusMessageIter iter, 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_privilege(msg,
430 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
431 return __connman_error_permission_denied(msg);
433 type = dbus_message_iter_get_arg_type(&value);
435 if (g_str_equal(name, "Powered") == TRUE) {
436 connman_bool_t powered;
439 if (type != DBUS_TYPE_BOOLEAN)
440 return __connman_error_invalid_arguments(msg);
442 dbus_message_iter_get_basic(&value, &powered);
444 if (device->powered == powered)
445 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
447 if (device->pending != NULL)
448 return __connman_error_in_progress(msg);
450 err = set_powered(device, powered);
452 if (err != -EINPROGRESS)
453 return __connman_error_failed(msg, -err);
455 device->pending = dbus_message_ref(msg);
457 device->timeout = g_timeout_add_seconds(15,
458 powered_timeout, device);
462 } else if (g_str_equal(name, "ScanInterval") == TRUE) {
463 connman_uint16_t interval;
465 switch (device->mode) {
466 case CONNMAN_DEVICE_MODE_UNKNOWN:
467 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
468 return __connman_error_invalid_arguments(msg);
469 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
470 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
474 if (type != DBUS_TYPE_UINT16)
475 return __connman_error_invalid_arguments(msg);
477 dbus_message_iter_get_basic(&value, &interval);
479 if (device->scan_interval != interval) {
480 device->scan_interval = interval;
482 reset_scan_trigger(device);
484 } else if (g_str_has_prefix(name, "IPv4.") == TRUE) {
487 switch (device->mode) {
488 case CONNMAN_DEVICE_MODE_UNKNOWN:
489 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
490 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
491 return __connman_error_invalid_arguments(msg);
492 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
496 err = __connman_ipconfig_set_ipv4(device->ipconfig,
499 return __connman_error_failed(msg, -err);
501 return __connman_error_invalid_property(msg);
503 __connman_storage_save_device(device);
505 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
508 static void convert_name(const char *ssid, char *name,
509 unsigned int ssid_len)
513 for (i = 0; i < ssid_len; i++) {
514 if (g_ascii_isprint(ssid[i]))
521 static struct connman_network *find_network(struct connman_device *device,
522 const void *ssid, const char *address,
523 const char *security, const char *mode)
525 GHashTableIter network_iter;
531 g_hash_table_iter_init(&network_iter, device->networks);
532 while (g_hash_table_iter_next(&network_iter, &key, &value) == TRUE) {
533 const void *tmp_ssid;
534 const char *tmp_security, *tmp_mode, *tmp_address;
535 unsigned int tmp_ssid_size;
537 tmp_ssid = connman_network_get_blob(value, "WiFi.SSID",
539 tmp_security = connman_network_get_string(value,
541 tmp_mode = connman_network_get_string(value, "WiFi.Mode");
542 tmp_address = connman_network_get_string(value, "Address");
544 if (tmp_ssid_size < 1)
547 if (tmp_ssid && memcmp(ssid, tmp_ssid, tmp_ssid_size))
550 if (security && tmp_security &&
551 g_strcmp0(security, tmp_security) != 0)
554 if (mode && tmp_mode && g_strcmp0(mode, tmp_mode) != 0)
557 if (address && tmp_address &&
558 g_strcmp0(address, tmp_address) != 0)
561 return connman_network_ref(value);
567 static DBusMessage *join_network(DBusConnection *conn,
568 DBusMessage *msg, void *data)
570 struct connman_device *device = data;
571 struct connman_network *network, *found_network;
572 enum connman_network_type type;
573 unsigned int ssid_size;
574 const char *group, *mode, *security, *address;
576 DBusMessageIter iter, array;
579 DBG("conn %p", conn);
581 if (__connman_security_check_privilege(msg,
582 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
583 return __connman_error_permission_denied(msg);
585 if (!device->driver || !device->driver->join)
586 return __connman_error_not_supported(msg);
588 dbus_message_iter_init(msg, &iter);
589 dbus_message_iter_recurse(&iter, &array);
591 switch (device->type) {
592 case CONNMAN_DEVICE_TYPE_WIFI:
593 type = CONNMAN_NETWORK_TYPE_WIFI;
596 return __connman_error_not_supported(msg);
599 network = connman_network_create("00_00_00_00_00_00", type);
601 return __connman_error_failed(msg, ENOMEM);
603 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
604 DBusMessageIter entry, value;
605 const char *key, *str;
607 dbus_message_iter_recurse(&array, &entry);
608 dbus_message_iter_get_basic(&entry, &key);
610 dbus_message_iter_next(&entry);
611 dbus_message_iter_recurse(&entry, &value);
613 switch (dbus_message_iter_get_arg_type(&value)) {
614 case DBUS_TYPE_STRING:
615 dbus_message_iter_get_basic(&value, &str);
616 if (g_str_equal(key, "WiFi.SSID") == TRUE) {
619 connman_network_set_blob(network, key,
621 name = g_try_malloc0(strlen(str) + 1);
623 return __connman_error_failed(msg,
626 convert_name((char *) str, name, strlen(str));
627 connman_network_set_name(network, name);
631 connman_network_set_string(network, key, str);
635 dbus_message_iter_next(&array);
638 ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_size);
639 security = connman_network_get_string(network, "WiFi.Security");
640 mode = connman_network_get_string(network, "WiFi.Mode");
641 address = connman_network_get_string(network, "Address");
643 found_network = find_network(device, ssid, address, security, mode);
644 if (found_network != NULL) {
645 const char* passphrase;
647 passphrase = connman_network_get_string(network,
649 if (passphrase != NULL)
650 connman_network_set_string(found_network,
653 connman_network_unref(network);
654 network = found_network;
656 err = __connman_network_connect(found_network);
658 connman_network_unref(found_network);
661 return __connman_error_failed(msg, -err);
663 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
666 group = connman_wifi_build_group_name(ssid, ssid_size, mode, security);
668 index = connman_device_get_index(device);
669 connman_network_set_index(network, index);
671 connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP);
673 if (connman_device_get_disconnected(device) == FALSE)
674 __connman_device_disconnect(device);
676 err = device->driver->join(device, network);
678 connman_network_unref(network);
681 return __connman_error_failed(msg, -err);
683 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
686 static DBusMessage *create_network(DBusConnection *conn,
687 DBusMessage *msg, void *data)
689 DBG("conn %p", conn);
691 if (__connman_security_check_privilege(msg,
692 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
693 return __connman_error_permission_denied(msg);
695 return __connman_error_invalid_arguments(msg);
698 static DBusMessage *remove_network(DBusConnection *conn,
699 DBusMessage *msg, void *data)
701 DBG("conn %p", conn);
703 if (__connman_security_check_privilege(msg,
704 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
705 return __connman_error_permission_denied(msg);
707 return __connman_error_invalid_arguments(msg);
710 static DBusMessage *propose_scan(DBusConnection *conn,
711 DBusMessage *msg, void *data)
713 struct connman_device *device = data;
716 DBG("conn %p", conn);
718 switch (device->mode) {
719 case CONNMAN_DEVICE_MODE_UNKNOWN:
720 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
721 return __connman_error_not_supported(msg);
722 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
723 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
727 err = __connman_device_scan(device);
729 return __connman_error_failed(msg, -err);
731 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
734 static GDBusMethodTable device_methods[] = {
735 { "GetProperties", "", "a{sv}", get_properties },
736 { "SetProperty", "sv", "", set_property,
737 G_DBUS_METHOD_FLAG_ASYNC },
738 { "JoinNetwork", "a{sv}", "", join_network },
739 { "CreateNetwork", "a{sv}", "o", create_network },
740 { "RemoveNetwork", "o", "", remove_network },
741 { "ProposeScan", "", "", propose_scan },
745 static GDBusSignalTable device_signals[] = {
746 { "PropertyChanged", "sv" },
750 static void append_devices(DBusMessageIter *entry)
752 DBusMessageIter value, iter;
753 const char *key = "Devices";
755 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
757 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
758 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
761 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
762 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
763 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
764 dbus_message_iter_close_container(&value, &iter);
766 dbus_message_iter_close_container(entry, &value);
769 static void emit_devices_signal(void)
772 DBusMessageIter entry;
774 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
775 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
779 dbus_message_iter_init_append(signal, &entry);
781 append_devices(&entry);
783 g_dbus_send_message(connection, signal);
786 static int register_interface(struct connman_element *element)
788 struct connman_device *device = element->device;
790 DBG("element %p name %s", element, element->name);
792 if (g_dbus_register_interface(connection, element->path,
793 CONNMAN_DEVICE_INTERFACE,
794 device_methods, device_signals,
795 NULL, device, NULL) == FALSE) {
796 connman_error("Failed to register %s device", element->path);
800 device->registered = TRUE;
802 emit_devices_signal();
807 static void unregister_interface(struct connman_element *element)
809 struct connman_device *device = element->device;
811 DBG("element %p name %s", element, element->name);
813 device->registered = FALSE;
815 emit_devices_signal();
817 g_dbus_unregister_interface(connection, element->path,
818 CONNMAN_DEVICE_INTERFACE);
821 static void device_enable(struct connman_device *device)
823 DBG("device %p", device);
825 if (device->powered == TRUE)
828 if (device->driver->enable) {
829 if (device->driver->enable(device) == 0)
830 device->powered = TRUE;
831 __connman_notifier_device_type_increase(device->type);
835 static void device_disable(struct connman_device *device)
837 DBG("device %p", device);
839 if (device->powered == FALSE)
842 g_hash_table_remove_all(device->networks);
844 if (device->driver->disable) {
845 if (device->driver->disable(device) == 0)
846 device->powered = FALSE;
847 __connman_notifier_device_type_decrease(device->type);
851 static int setup_device(struct connman_device *device)
855 DBG("device %p", device);
857 err = register_interface(&device->element);
859 if (device->driver->remove)
860 device->driver->remove(device);
861 device->driver = NULL;
865 switch (device->mode) {
866 case CONNMAN_DEVICE_MODE_UNKNOWN:
867 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
868 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
870 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
871 if (device->carrier == TRUE && device->secondary == FALSE)
872 __connman_profile_add_device(device);
876 device_enable(device);
881 static void probe_driver(struct connman_element *element, gpointer user_data)
883 struct connman_device_driver *driver = user_data;
885 DBG("element %p name %s", element, element->name);
887 if (element->device == NULL)
890 if (element->device->driver != NULL)
893 if (driver->type != element->device->type)
896 if (driver->probe(element->device) < 0)
899 element->device->driver = driver;
901 setup_device(element->device);
904 static void remove_device(struct connman_device *device)
906 DBG("device %p", device);
908 device_disable(device);
910 switch (device->mode) {
911 case CONNMAN_DEVICE_MODE_UNKNOWN:
912 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
913 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
915 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
916 if (device->secondary == FALSE)
917 __connman_profile_remove_device(device);
921 unregister_interface(&device->element);
923 if (device->driver->remove)
924 device->driver->remove(device);
926 device->driver = NULL;
929 static void remove_driver(struct connman_element *element, gpointer user_data)
931 struct connman_device_driver *driver = user_data;
933 DBG("element %p name %s", element, element->name);
935 if (element->device == NULL)
938 if (element->device->driver == driver)
939 remove_device(element->device);
942 connman_bool_t __connman_device_has_driver(struct connman_device *device)
944 if (device == NULL || device->driver == NULL)
947 return device->registered;
950 static GSList *driver_list = NULL;
952 static gint compare_priority(gconstpointer a, gconstpointer b)
954 const struct connman_device_driver *driver1 = a;
955 const struct connman_device_driver *driver2 = b;
957 return driver2->priority - driver1->priority;
961 * connman_device_driver_register:
962 * @driver: device driver definition
964 * Register a new device driver
966 * Returns: %0 on success
968 int connman_device_driver_register(struct connman_device_driver *driver)
970 DBG("driver %p name %s", driver, driver->name);
972 driver_list = g_slist_insert_sorted(driver_list, driver,
975 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
976 probe_driver, driver);
982 * connman_device_driver_unregister:
983 * @driver: device driver definition
985 * Remove a previously registered device driver
987 void connman_device_driver_unregister(struct connman_device_driver *driver)
989 DBG("driver %p name %s", driver, driver->name);
991 driver_list = g_slist_remove(driver_list, driver);
993 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
994 remove_driver, driver);
997 static void unregister_network(gpointer data)
999 struct connman_network *network = data;
1001 DBG("network %p", network);
1003 connman_element_unregister((struct connman_element *) network);
1005 connman_network_unref(network);
1008 static void device_destruct(struct connman_element *element)
1010 struct connman_device *device = element->device;
1012 DBG("element %p name %s", element, element->name);
1014 if (device->timeout > 0) {
1015 g_source_remove(device->timeout);
1016 device->timeout = 0;
1019 if (device->pending != NULL) {
1020 dbus_message_unref(device->pending);
1021 device->pending = NULL;
1024 g_free(device->ident);
1025 g_free(device->node);
1026 g_free(device->name);
1027 g_free(device->address);
1028 g_free(device->control);
1029 g_free(device->interface);
1031 connman_ipconfig_unref(device->ipconfig);
1033 g_free(device->last_network);
1035 g_hash_table_destroy(device->networks);
1036 device->networks = NULL;
1040 * connman_device_create:
1041 * @node: device node name (for example an address)
1042 * @type: device type
1044 * Allocate a new device of given #type and assign the #node name to it.
1046 * Returns: a newly-allocated #connman_device structure
1048 struct connman_device *connman_device_create(const char *node,
1049 enum connman_device_type type)
1051 struct connman_device *device;
1054 DBG("node %s type %d", node, type);
1056 device = g_try_new0(struct connman_device, 1);
1060 DBG("device %p", device);
1062 __connman_element_initialize(&device->element);
1064 device->element.name = g_strdup(node);
1065 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
1067 device->element.device = device;
1068 device->element.destruct = device_destruct;
1070 str = type2string(type);
1072 connman_element_set_string(&device->element,
1073 CONNMAN_PROPERTY_ID_TYPE, str);
1075 device->element.ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP;
1077 device->type = type;
1078 device->name = g_strdup(type2description(device->type));
1079 device->mode = CONNMAN_DEVICE_MODE_UNKNOWN;
1080 device->secondary = FALSE;
1083 case CONNMAN_DEVICE_TYPE_UNKNOWN:
1084 case CONNMAN_DEVICE_TYPE_VENDOR:
1085 device->scan_interval = 0;
1087 case CONNMAN_DEVICE_TYPE_ETHERNET:
1088 case CONNMAN_DEVICE_TYPE_WIFI:
1089 device->scan_interval = 300;
1091 case CONNMAN_DEVICE_TYPE_WIMAX:
1092 device->scan_interval = 0;
1094 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1095 device->scan_interval = 0;
1097 case CONNMAN_DEVICE_TYPE_GPS:
1098 device->scan_interval = 0;
1100 case CONNMAN_DEVICE_TYPE_MBM:
1101 case CONNMAN_DEVICE_TYPE_HSO:
1102 case CONNMAN_DEVICE_TYPE_NOZOMI:
1103 case CONNMAN_DEVICE_TYPE_HUAWEI:
1104 case CONNMAN_DEVICE_TYPE_NOVATEL:
1105 device->scan_interval = 0;
1109 device->ipconfig = connman_ipconfig_create();
1110 if (device->ipconfig == NULL) {
1111 connman_device_unref(device);
1115 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
1116 g_free, unregister_network);
1122 * connman_device_ref:
1123 * @device: device structure
1125 * Increase reference counter of device
1127 struct connman_device *connman_device_ref(struct connman_device *device)
1129 if (connman_element_ref(&device->element) == NULL)
1136 * connman_device_unref:
1137 * @device: device structure
1139 * Decrease reference counter of device
1141 void connman_device_unref(struct connman_device *device)
1143 connman_element_unref(&device->element);
1146 const char *__connman_device_get_type(struct connman_device *device)
1148 return type2string(device->type);
1152 * connman_device_get_type:
1153 * @device: device structure
1155 * Get type of device
1157 enum connman_device_type connman_device_get_type(struct connman_device *device)
1159 return device->type;
1163 * connman_device_get_name:
1164 * @device: device structure
1166 * Get unique name of device
1168 const char *connman_device_get_name(struct connman_device *device)
1170 return device->element.name;
1174 * connman_device_get_path:
1175 * @device: device structure
1177 * Get path name of device
1179 const char *connman_device_get_path(struct connman_device *device)
1181 return device->element.path;
1185 * connman_device_set_index:
1186 * @device: device structure
1187 * @index: index number
1189 * Set index number of device
1191 void connman_device_set_index(struct connman_device *device, int index)
1193 device->element.index = index;
1197 * connman_device_get_index:
1198 * @device: device structure
1200 * Get index number of device
1202 int connman_device_get_index(struct connman_device *device)
1204 return device->element.index;
1208 * connman_device_set_interface:
1209 * @device: device structure
1210 * @interface: interface name
1211 * @control: control interface
1213 * Set interface name of device
1215 void connman_device_set_interface(struct connman_device *device,
1216 const char *interface, const char *control)
1218 g_free(device->element.devname);
1219 device->element.devname = g_strdup(interface);
1221 g_free(device->interface);
1222 device->interface = g_strdup(interface);
1224 g_free(device->control);
1225 device->control = g_strdup(control);
1227 if (device->name == NULL) {
1228 const char *str = type2description(device->type);
1229 if (str != NULL && device->interface != NULL)
1230 device->name = g_strdup_printf("%s (%s)", str,
1235 const char *connman_device_get_control(struct connman_device *device)
1237 return device->control;
1241 * connman_device_set_ident:
1242 * @device: device structure
1243 * @ident: unique identifier
1245 * Set unique identifier of device
1247 void connman_device_set_ident(struct connman_device *device,
1250 g_free(device->ident);
1251 device->ident = g_strdup(ident);
1254 const char *__connman_device_get_ident(struct connman_device *device)
1256 return device->ident;
1260 * connman_device_set_mode:
1261 * @device: device structure
1262 * @mode: network mode
1264 * Change network mode of device
1266 void connman_device_set_mode(struct connman_device *device,
1267 enum connman_device_mode mode)
1269 device->mode = mode;
1273 * connman_device_get_mode:
1274 * @device: device structure
1276 * Get network mode of device
1278 enum connman_device_mode connman_device_get_mode(struct connman_device *device)
1280 return device->mode;
1284 * connman_device_set_secondary:
1285 * @device: device structure
1286 * @secondary: secondary value
1288 * Change secondary value of device
1290 void connman_device_set_secondary(struct connman_device *device,
1291 connman_bool_t secondary)
1293 device->secondary = secondary;
1297 * connman_device_get_secondary:
1298 * @device: device structure
1300 * Get secondary value of device
1302 connman_bool_t connman_device_get_secondary(struct connman_device *device)
1304 return device->secondary;
1308 * connman_device_set_powered:
1309 * @device: device structure
1310 * @powered: powered state
1312 * Change power state of device
1314 int connman_device_set_powered(struct connman_device *device,
1315 connman_bool_t powered)
1317 DBG("driver %p powered %d", device, powered);
1319 if (device->timeout > 0) {
1320 g_source_remove(device->timeout);
1321 device->timeout = 0;
1324 if (device->pending != NULL) {
1325 g_dbus_send_reply(connection, device->pending,
1328 dbus_message_unref(device->pending);
1329 device->pending = NULL;
1332 if (device->powered == powered)
1335 device->powered = powered;
1337 if (device->registered == FALSE)
1340 powered_changed(device);
1342 if (powered == FALSE)
1345 reset_scan_trigger(device);
1347 if (device->driver->scan)
1348 device->driver->scan(device);
1354 * connman_device_set_carrier:
1355 * @device: device structure
1356 * @carrier: carrier state
1358 * Change carrier state of device (only for device without scanning)
1360 int connman_device_set_carrier(struct connman_device *device,
1361 connman_bool_t carrier)
1363 DBG("device %p carrier %d", device, carrier);
1365 switch (device->mode) {
1366 case CONNMAN_DEVICE_MODE_UNKNOWN:
1367 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1368 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1370 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1374 if (device->carrier == carrier)
1377 device->carrier = carrier;
1379 return set_carrier(device, device->carrier);
1382 int __connman_device_scan(struct connman_device *device)
1384 if (!device->driver || !device->driver->scan)
1387 if (device->powered == FALSE)
1390 return device->driver->scan(device);
1393 int __connman_device_enable(struct connman_device *device)
1395 if (!device->driver || !device->driver->enable)
1398 if (device->powered == TRUE)
1401 device_enable(device);
1406 int __connman_device_disable(struct connman_device *device)
1408 if (!device->driver || !device->driver->disable)
1411 if (device->powered == FALSE)
1414 device_disable(device);
1419 int __connman_device_connect(struct connman_device *device)
1421 DBG("device %p", device);
1423 if (device->disconnected == FALSE)
1426 if (device->driver && device->driver->connect)
1427 device->driver->connect(device);
1432 int __connman_device_disconnect(struct connman_device *device)
1434 GHashTableIter iter;
1435 gpointer key, value;
1437 DBG("device %p", device);
1439 connman_device_set_disconnected(device, TRUE);
1441 g_hash_table_iter_init(&iter, device->networks);
1443 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1444 struct connman_network *network = value;
1446 __connman_network_disconnect(network);
1449 if (device->driver && device->driver->disconnect)
1450 device->driver->disconnect(device);
1455 static void mark_network_unavailable(gpointer key, gpointer value,
1458 struct connman_network *network = value;
1460 if (connman_network_get_connected(network) == TRUE)
1463 connman_network_set_available(network, FALSE);
1466 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1469 struct connman_network *network = value;
1471 if (connman_network_get_connected(network) == TRUE)
1474 if (connman_network_get_available(network) == TRUE)
1480 void __connman_device_cleanup_networks(struct connman_device *device)
1482 g_hash_table_foreach_remove(device->networks,
1483 remove_unavailable_network, NULL);
1487 * connman_device_set_scanning:
1488 * @device: device structure
1489 * @scanning: scanning state
1491 * Change scanning state of device
1493 int connman_device_set_scanning(struct connman_device *device,
1494 connman_bool_t scanning)
1496 DBusMessage *signal;
1497 DBusMessageIter entry, value;
1498 const char *key = "Scanning";
1500 DBG("device %p scanning %d", device, scanning);
1502 if (!device->driver || !device->driver->scan)
1505 if (device->scanning == scanning)
1508 device->scanning = scanning;
1510 signal = dbus_message_new_signal(device->element.path,
1511 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1515 dbus_message_iter_init_append(signal, &entry);
1517 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1519 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1520 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
1521 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
1522 dbus_message_iter_close_container(&entry, &value);
1524 g_dbus_send_message(connection, signal);
1526 if (scanning == TRUE) {
1527 reset_scan_trigger(device);
1529 g_hash_table_foreach(device->networks,
1530 mark_network_unavailable, NULL);
1535 __connman_device_cleanup_networks(device);
1537 if (device->connections > 0)
1540 if (device->disconnected == TRUE)
1543 __connman_service_auto_connect();
1549 * connman_device_set_disconnected:
1550 * @device: device structure
1551 * @disconnected: disconnected state
1553 * Change disconnected state of device (only for device with networks)
1555 int connman_device_set_disconnected(struct connman_device *device,
1556 connman_bool_t disconnected)
1558 DBG("device %p disconnected %d", device, disconnected);
1560 switch (device->mode) {
1561 case CONNMAN_DEVICE_MODE_UNKNOWN:
1562 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1564 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1565 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1569 if (device->disconnected == disconnected)
1572 device->disconnected = disconnected;
1578 * connman_device_get_disconnected:
1579 * @device: device structure
1581 * Get device disconnected state
1583 connman_bool_t connman_device_get_disconnected(struct connman_device *device)
1585 return device->disconnected;
1589 * connman_device_set_connected:
1590 * @device: device structure
1591 * @connected: connected state
1593 * Change connected state of device (for Ethernet like devices)
1595 int connman_device_set_connected(struct connman_device *device,
1596 connman_bool_t connected)
1598 DBG("device %p connected %d", device, connected);
1600 switch (device->mode) {
1601 case CONNMAN_DEVICE_MODE_UNKNOWN:
1602 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1603 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1605 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1609 if (device->carrier == FALSE)
1612 return set_connected(device, connected);
1616 * connman_device_set_string:
1617 * @device: device structure
1618 * @key: unique identifier
1619 * @value: string value
1621 * Set string value for specific key
1623 int connman_device_set_string(struct connman_device *device,
1624 const char *key, const char *value)
1626 DBG("device %p key %s value %s", device, key, value);
1628 if (g_str_equal(key, "Address") == TRUE) {
1629 g_free(device->address);
1630 device->address = g_strdup(value);
1631 } else if (g_str_equal(key, "Name") == TRUE) {
1632 g_free(device->name);
1633 device->name = g_strdup(value);
1634 } else if (g_str_equal(key, "Node") == TRUE) {
1635 g_free(device->node);
1636 device->node = g_strdup(value);
1639 return connman_element_set_string(&device->element, key, value);
1643 * connman_device_get_string:
1644 * @device: device structure
1645 * @key: unique identifier
1647 * Get string value for specific key
1649 const char *connman_device_get_string(struct connman_device *device,
1652 DBG("device %p key %s", device, key);
1654 if (g_str_equal(key, "Address") == TRUE)
1655 return device->address;
1656 else if (g_str_equal(key, "Name") == TRUE)
1657 return device->name;
1658 else if (g_str_equal(key, "Node") == TRUE)
1659 return device->node;
1661 return connman_element_get_string(&device->element, key);
1664 static void set_offlinemode(struct connman_element *element, gpointer user_data)
1666 struct connman_device *device = element->device;
1667 connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data);
1668 connman_bool_t powered;
1670 DBG("element %p name %s", element, element->name);
1675 powered = (offlinemode == TRUE) ? FALSE : TRUE;
1677 if (device->powered == powered)
1680 set_powered(device, powered);
1683 int __connman_device_set_offlinemode(connman_bool_t offlinemode)
1685 DBG("offlinmode %d", offlinemode);
1687 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
1688 set_offlinemode, GUINT_TO_POINTER(offlinemode));
1690 __connman_notifier_offline_mode(offlinemode);
1695 void __connman_device_increase_connections(struct connman_device *device)
1697 device->connections++;
1700 void __connman_device_decrease_connections(struct connman_device *device)
1702 device->connections--;
1706 * connman_device_add_network:
1707 * @device: device structure
1708 * @network: network structure
1710 * Add new network to the device
1712 int connman_device_add_network(struct connman_device *device,
1713 struct connman_network *network)
1715 const char *identifier = connman_network_get_identifier(network);
1718 DBG("device %p network %p", device, network);
1720 switch (device->mode) {
1721 case CONNMAN_DEVICE_MODE_UNKNOWN:
1722 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1724 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1725 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1729 __connman_network_set_device(network, device);
1731 __connman_storage_load_network(network);
1733 err = connman_element_register((struct connman_element *) network,
1736 __connman_network_set_device(network, NULL);
1740 g_hash_table_insert(device->networks, g_strdup(identifier),
1747 * connman_device_get_network:
1748 * @device: device structure
1749 * @identifier: network identifier
1751 * Get network for given identifier
1753 struct connman_network *connman_device_get_network(struct connman_device *device,
1754 const char *identifier)
1756 DBG("device %p identifier %s", device, identifier);
1758 return g_hash_table_lookup(device->networks, identifier);
1762 * connman_device_remove_network:
1763 * @device: device structure
1764 * @identifier: network identifier
1766 * Remove network for given identifier
1768 int connman_device_remove_network(struct connman_device *device,
1769 const char *identifier)
1771 DBG("device %p identifier %s", device, identifier);
1773 g_hash_table_remove(device->networks, identifier);
1778 void __connman_device_set_network(struct connman_device *device,
1779 struct connman_network *network)
1783 if (device->network == network)
1786 if (device->network != NULL)
1787 connman_network_unref(device->network);
1789 if (network != NULL) {
1790 name = connman_network_get_string(network,
1791 CONNMAN_PROPERTY_ID_NAME);
1792 g_free(device->last_network);
1793 device->last_network = g_strdup(name);
1795 device->network = connman_network_ref(network);
1797 g_free(device->last_network);
1798 device->last_network = NULL;
1800 device->network = NULL;
1805 * connman_device_register:
1806 * @device: device structure
1808 * Register device with the system
1810 int connman_device_register(struct connman_device *device)
1812 __connman_storage_load_device(device);
1814 switch (device->mode) {
1815 case CONNMAN_DEVICE_MODE_UNKNOWN:
1816 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1818 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1819 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1820 __connman_storage_init_network(device);
1824 __connman_notifier_device_type_register(device->type);
1826 return connman_element_register(&device->element, NULL);
1830 * connman_device_unregister:
1831 * @device: device structure
1833 * Unregister device with the system
1835 void connman_device_unregister(struct connman_device *device)
1837 __connman_storage_save_device(device);
1839 __connman_notifier_device_type_unregister(device->type);
1841 connman_element_unregister(&device->element);
1845 * connman_device_get_data:
1846 * @device: device structure
1848 * Get private device data pointer
1850 void *connman_device_get_data(struct connman_device *device)
1852 return device->driver_data;
1856 * connman_device_set_data:
1857 * @device: device structure
1858 * @data: data pointer
1860 * Set private device data pointer
1862 void connman_device_set_data(struct connman_device *device, void *data)
1864 device->driver_data = data;
1867 static gboolean match_driver(struct connman_device *device,
1868 struct connman_device_driver *driver)
1870 if (device->type == driver->type ||
1871 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1877 static int device_probe(struct connman_element *element)
1879 struct connman_device *device = element->device;
1882 DBG("element %p name %s", element, element->name);
1887 if (device->driver != NULL)
1890 for (list = driver_list; list; list = list->next) {
1891 struct connman_device_driver *driver = list->data;
1893 if (match_driver(device, driver) == FALSE)
1896 DBG("driver %p name %s", driver, driver->name);
1898 if (driver->probe(device) == 0) {
1899 device->driver = driver;
1904 if (device->driver == NULL)
1907 return setup_device(device);
1910 static void device_remove(struct connman_element *element)
1912 struct connman_device *device = element->device;
1914 DBG("element %p name %s", element, element->name);
1919 if (device->driver == NULL)
1922 remove_device(device);
1925 static struct connman_driver device_driver = {
1927 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
1928 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
1929 .probe = device_probe,
1930 .remove = device_remove,
1933 static int device_load(struct connman_device *device)
1936 gchar *pathname, *identifier, *data = NULL;
1940 DBG("device %p", device);
1942 pathname = g_strdup_printf("%s/%s.conf", STORAGEDIR,
1943 __connman_profile_active_ident());
1944 if (pathname == NULL)
1947 keyfile = g_key_file_new();
1949 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
1956 if (g_key_file_load_from_data(keyfile, data, length,
1957 0, NULL) == FALSE) {
1964 identifier = g_strdup_printf("device_%s", device->element.name);
1965 if (identifier == NULL)
1968 switch (device->mode) {
1969 case CONNMAN_DEVICE_MODE_UNKNOWN:
1970 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1972 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1973 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1974 val = g_key_file_get_integer(keyfile, identifier,
1975 "ScanInterval", NULL);
1977 device->scan_interval = val;
1982 g_key_file_free(keyfile);
1989 static int device_save(struct connman_device *device)
1992 gchar *pathname, *identifier = NULL, *data = NULL;
1995 DBG("device %p", device);
1997 pathname = g_strdup_printf("%s/%s.conf", STORAGEDIR,
1998 __connman_profile_active_ident());
1999 if (pathname == NULL)
2002 keyfile = g_key_file_new();
2004 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
2008 if (g_key_file_load_from_data(keyfile, data, length,
2016 identifier = g_strdup_printf("device_%s", device->element.name);
2017 if (identifier == NULL)
2020 switch (device->mode) {
2021 case CONNMAN_DEVICE_MODE_UNKNOWN:
2022 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
2024 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
2025 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
2026 if (device->scan_interval > 0)
2027 g_key_file_set_integer(keyfile, identifier,
2028 "ScanInterval", device->scan_interval);
2032 data = g_key_file_to_data(keyfile, &length, NULL);
2034 if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
2035 connman_error("Failed to store device information");
2040 g_key_file_free(keyfile);
2048 static struct connman_storage device_storage = {
2050 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
2051 .device_load = device_load,
2052 .device_save = device_save,
2055 int __connman_device_init(void)
2059 connection = connman_dbus_get_connection();
2061 if (connman_storage_register(&device_storage) < 0)
2062 connman_error("Failed to register device storage");
2064 return connman_driver_register(&device_driver);
2067 void __connman_device_cleanup(void)
2071 connman_driver_unregister(&device_driver);
2073 connman_storage_unregister(&device_storage);
2075 dbus_connection_unref(connection);