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 offlinemode;
40 connman_bool_t blocked;
41 connman_bool_t powered;
42 connman_bool_t powered_pending;
43 connman_bool_t powered_persistent;
44 connman_bool_t scanning;
45 connman_bool_t disconnected;
46 connman_bool_t reconnect;
47 connman_uint16_t scan_interval;
55 unsigned int connections;
58 struct connman_device_driver *driver;
61 connman_bool_t registered;
64 struct connman_network *network;
71 static gboolean device_scan_trigger(gpointer user_data)
73 struct connman_device *device = user_data;
75 DBG("device %p", device);
77 if (device->driver == NULL) {
78 device->scan_timeout = 0;
82 if (device->driver->scan)
83 device->driver->scan(device);
88 static void clear_scan_trigger(struct connman_device *device)
90 if (device->scan_timeout > 0) {
91 g_source_remove(device->scan_timeout);
92 device->scan_timeout = 0;
96 static void reset_scan_trigger(struct connman_device *device)
98 clear_scan_trigger(device);
100 if (device->scan_interval > 0) {
101 guint interval = device->scan_interval;
102 device->scan_timeout = g_timeout_add_seconds(interval,
103 device_scan_trigger, device);
107 static void force_scan_trigger(struct connman_device *device)
109 clear_scan_trigger(device);
111 device->scan_timeout = g_timeout_add_seconds(5,
112 device_scan_trigger, device);
115 void connman_device_schedule_scan(struct connman_device *device)
117 reset_scan_trigger(device);
120 static const char *type2description(enum connman_device_type type)
123 case CONNMAN_DEVICE_TYPE_UNKNOWN:
124 case CONNMAN_DEVICE_TYPE_VENDOR:
126 case CONNMAN_DEVICE_TYPE_ETHERNET:
128 case CONNMAN_DEVICE_TYPE_WIFI:
130 case CONNMAN_DEVICE_TYPE_WIMAX:
132 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
134 case CONNMAN_DEVICE_TYPE_GPS:
136 case CONNMAN_DEVICE_TYPE_CELLULAR:
137 case CONNMAN_DEVICE_TYPE_MBM:
138 case CONNMAN_DEVICE_TYPE_HSO:
145 static const char *type2string(enum connman_device_type type)
148 case CONNMAN_DEVICE_TYPE_UNKNOWN:
149 case CONNMAN_DEVICE_TYPE_VENDOR:
151 case CONNMAN_DEVICE_TYPE_ETHERNET:
153 case CONNMAN_DEVICE_TYPE_WIFI:
155 case CONNMAN_DEVICE_TYPE_WIMAX:
157 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
159 case CONNMAN_DEVICE_TYPE_GPS:
161 case CONNMAN_DEVICE_TYPE_CELLULAR:
162 case CONNMAN_DEVICE_TYPE_MBM:
163 case CONNMAN_DEVICE_TYPE_HSO:
170 enum connman_service_type __connman_device_get_service_type(struct connman_device *device)
172 enum connman_device_type type = connman_device_get_type(device);
175 case CONNMAN_DEVICE_TYPE_UNKNOWN:
176 case CONNMAN_DEVICE_TYPE_VENDOR:
177 case CONNMAN_DEVICE_TYPE_GPS:
179 case CONNMAN_DEVICE_TYPE_ETHERNET:
180 return CONNMAN_SERVICE_TYPE_ETHERNET;
181 case CONNMAN_DEVICE_TYPE_WIFI:
182 return CONNMAN_SERVICE_TYPE_WIFI;
183 case CONNMAN_DEVICE_TYPE_WIMAX:
184 return CONNMAN_SERVICE_TYPE_WIMAX;
185 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
186 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
187 case CONNMAN_DEVICE_TYPE_CELLULAR:
188 case CONNMAN_DEVICE_TYPE_MBM:
189 case CONNMAN_DEVICE_TYPE_HSO:
190 return CONNMAN_SERVICE_TYPE_CELLULAR;
193 return CONNMAN_SERVICE_TYPE_UNKNOWN;
196 static int powered_changed(struct connman_device *device)
199 DBusMessageIter iter;
201 signal = dbus_message_new_signal(device->element.path,
202 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
206 dbus_message_iter_init_append(signal, &iter);
207 connman_dbus_property_append_variant(&iter, "Powered",
208 DBUS_TYPE_BOOLEAN, &device->powered);
210 g_dbus_send_message(connection, signal);
215 static int set_powered(struct connman_device *device, connman_bool_t powered)
217 struct connman_device_driver *driver = device->driver;
218 enum connman_service_type type;
221 DBG("device %p powered %d", device, powered);
223 if (device->powered_pending == powered)
229 type = __connman_device_get_service_type(device);
231 if (powered == TRUE) {
232 if (driver->enable) {
233 device->powered_pending = powered;
235 err = driver->enable(device);
237 __connman_notifier_enable(type);
241 device->powered_pending = powered;
243 device->reconnect = FALSE;
245 clear_scan_trigger(device);
247 g_hash_table_remove_all(device->networks);
249 if (driver->disable) {
250 err = driver->disable(device);
252 __connman_notifier_disable(type);
258 device->powered = powered;
260 if (device->registered == TRUE)
261 powered_changed(device);
267 void __connman_device_list(DBusMessageIter *iter)
269 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, iter);
272 static void append_path(gpointer key, gpointer value, gpointer user_data)
274 struct connman_element *element = value;
275 DBusMessageIter *iter = user_data;
277 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
281 static void append_networks(struct connman_device *device,
282 DBusMessageIter *entry)
284 DBusMessageIter value, iter;
285 const char *key = "Networks";
287 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
289 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
290 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
293 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
294 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
295 g_hash_table_foreach(device->networks, append_path, &iter);
296 dbus_message_iter_close_container(&value, &iter);
298 dbus_message_iter_close_container(entry, &value);
301 static DBusMessage *get_properties(DBusConnection *conn,
302 DBusMessage *msg, void *data)
304 struct connman_device *device = data;
306 DBusMessageIter array, dict, entry;
309 DBG("conn %p", conn);
311 if (__connman_security_check_privilege(msg,
312 CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
313 return __connman_error_permission_denied(msg);
315 reply = dbus_message_new_method_return(msg);
319 dbus_message_iter_init_append(reply, &array);
321 connman_dbus_dict_open(&array, &dict);
323 if (device->name != NULL)
324 connman_dbus_dict_append_variant(&dict, "Name",
325 DBUS_TYPE_STRING, &device->name);
327 str = type2string(device->type);
329 connman_dbus_dict_append_variant(&dict, "Type",
330 DBUS_TYPE_STRING, &str);
332 if (device->address != NULL)
333 connman_dbus_dict_append_variant(&dict, "Address",
334 DBUS_TYPE_STRING, &device->address);
336 if (device->interface != NULL)
337 connman_dbus_dict_append_variant(&dict, "Interface",
338 DBUS_TYPE_STRING, &device->interface);
340 connman_dbus_dict_append_variant(&dict, "Powered",
341 DBUS_TYPE_BOOLEAN, &device->powered);
343 if (device->driver && device->driver->scan)
344 connman_dbus_dict_append_variant(&dict, "Scanning",
345 DBUS_TYPE_BOOLEAN, &device->scanning);
347 switch (device->mode) {
348 case CONNMAN_DEVICE_MODE_UNKNOWN:
350 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
351 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
352 if (device->scan_interval > 0)
353 connman_dbus_dict_append_variant(&dict, "ScanInterval",
354 DBUS_TYPE_UINT16, &device->scan_interval);
356 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
358 append_networks(device, &entry);
359 dbus_message_iter_close_container(&dict, &entry);
363 connman_dbus_dict_close(&array, &dict);
368 static gboolean powered_timeout(gpointer user_data)
370 struct connman_device *device = user_data;
372 DBG("device %p", device);
376 if (device->pending != NULL) {
379 reply = __connman_error_operation_timeout(device->pending);
381 g_dbus_send_message(connection, reply);
383 dbus_message_unref(device->pending);
384 device->pending = NULL;
390 static DBusMessage *set_property(DBusConnection *conn,
391 DBusMessage *msg, void *data)
393 struct connman_device *device = data;
394 DBusMessageIter iter, value;
398 DBG("conn %p", conn);
400 if (dbus_message_iter_init(msg, &iter) == FALSE)
401 return __connman_error_invalid_arguments(msg);
403 dbus_message_iter_get_basic(&iter, &name);
404 dbus_message_iter_next(&iter);
405 dbus_message_iter_recurse(&iter, &value);
407 if (__connman_security_check_privilege(msg,
408 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
409 return __connman_error_permission_denied(msg);
411 type = dbus_message_iter_get_arg_type(&value);
413 if (g_str_equal(name, "Powered") == TRUE) {
414 connman_bool_t powered;
417 if (type != DBUS_TYPE_BOOLEAN)
418 return __connman_error_invalid_arguments(msg);
420 dbus_message_iter_get_basic(&value, &powered);
422 device->powered_persistent = powered;
424 __connman_storage_save_device(device);
426 if (device->powered == powered)
427 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
429 if (device->pending != NULL)
430 return __connman_error_in_progress(msg);
432 err = set_powered(device, powered);
434 if (err != -EINPROGRESS)
435 return __connman_error_failed(msg, -err);
437 device->pending = dbus_message_ref(msg);
439 device->timeout = g_timeout_add_seconds(15,
440 powered_timeout, device);
444 } else if (g_str_equal(name, "ScanInterval") == TRUE) {
445 connman_uint16_t interval;
447 switch (device->mode) {
448 case CONNMAN_DEVICE_MODE_UNKNOWN:
449 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
450 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
454 if (type != DBUS_TYPE_UINT16)
455 return __connman_error_invalid_arguments(msg);
457 dbus_message_iter_get_basic(&value, &interval);
459 if (device->scan_interval != interval) {
460 device->scan_interval = interval;
462 __connman_storage_save_device(device);
464 reset_scan_trigger(device);
467 return __connman_error_invalid_property(msg);
469 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
472 static DBusMessage *propose_scan(DBusConnection *conn,
473 DBusMessage *msg, void *data)
475 struct connman_device *device = data;
478 DBG("conn %p", conn);
480 switch (device->mode) {
481 case CONNMAN_DEVICE_MODE_UNKNOWN:
482 return __connman_error_not_supported(msg);
483 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
484 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
488 err = __connman_device_scan(device);
490 return __connman_error_failed(msg, -err);
492 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
495 static GDBusMethodTable device_methods[] = {
496 { "GetProperties", "", "a{sv}", get_properties },
497 { "SetProperty", "sv", "", set_property,
498 G_DBUS_METHOD_FLAG_ASYNC },
499 { "ProposeScan", "", "", propose_scan },
503 static GDBusSignalTable device_signals[] = {
504 { "PropertyChanged", "sv" },
508 static void emit_devices_signal(void)
511 DBusMessageIter iter;
513 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
514 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
518 dbus_message_iter_init_append(signal, &iter);
519 connman_dbus_property_append_variable_array(&iter, "Devices",
520 DBUS_TYPE_OBJECT_PATH, __connman_device_list);
522 g_dbus_send_message(connection, signal);
525 static int register_interface(struct connman_element *element)
527 struct connman_device *device = element->device;
529 DBG("element %p name %s", element, element->name);
531 if (g_dbus_register_interface(connection, element->path,
532 CONNMAN_DEVICE_INTERFACE,
533 device_methods, device_signals,
534 NULL, device, NULL) == FALSE) {
535 connman_error("Failed to register %s device", element->path);
539 device->registered = TRUE;
541 emit_devices_signal();
546 static void unregister_interface(struct connman_element *element)
548 struct connman_device *device = element->device;
550 DBG("element %p name %s", element, element->name);
552 device->registered = FALSE;
554 emit_devices_signal();
556 g_dbus_unregister_interface(connection, element->path,
557 CONNMAN_DEVICE_INTERFACE);
560 static int setup_device(struct connman_device *device)
562 enum connman_service_type type;
565 DBG("device %p", device);
567 err = register_interface(&device->element);
569 if (device->driver->remove)
570 device->driver->remove(device);
571 device->driver = NULL;
575 type = __connman_device_get_service_type(device);
576 __connman_notifier_register(type);
578 switch (device->mode) {
579 case CONNMAN_DEVICE_MODE_UNKNOWN:
580 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
581 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
585 if (device->offlinemode == FALSE &&
586 device->powered_persistent == TRUE)
587 __connman_device_enable(device);
592 static void probe_driver(struct connman_element *element, gpointer user_data)
594 struct connman_device_driver *driver = user_data;
596 DBG("element %p name %s", element, element->name);
598 if (element->device == NULL)
601 if (element->device->driver != NULL)
604 if (driver->type != element->device->type)
607 if (driver->probe(element->device) < 0)
610 element->device->driver = driver;
612 setup_device(element->device);
615 static void remove_device(struct connman_device *device)
617 enum connman_service_type type;
619 DBG("device %p", device);
621 __connman_device_disable(device);
623 switch (device->mode) {
624 case CONNMAN_DEVICE_MODE_UNKNOWN:
625 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
626 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
630 type = __connman_device_get_service_type(device);
631 __connman_notifier_unregister(type);
633 unregister_interface(&device->element);
635 if (device->driver->remove)
636 device->driver->remove(device);
638 device->driver = NULL;
641 static void remove_driver(struct connman_element *element, gpointer user_data)
643 struct connman_device_driver *driver = user_data;
645 DBG("element %p name %s", element, element->name);
647 if (element->device == NULL)
650 if (element->device->driver == driver)
651 remove_device(element->device);
654 connman_bool_t __connman_device_has_driver(struct connman_device *device)
656 if (device == NULL || device->driver == NULL)
659 return device->registered;
662 static GSList *driver_list = NULL;
664 static gint compare_priority(gconstpointer a, gconstpointer b)
666 const struct connman_device_driver *driver1 = a;
667 const struct connman_device_driver *driver2 = b;
669 return driver2->priority - driver1->priority;
673 * connman_device_driver_register:
674 * @driver: device driver definition
676 * Register a new device driver
678 * Returns: %0 on success
680 int connman_device_driver_register(struct connman_device_driver *driver)
682 DBG("driver %p name %s", driver, driver->name);
684 driver_list = g_slist_insert_sorted(driver_list, driver,
687 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
688 probe_driver, driver);
694 * connman_device_driver_unregister:
695 * @driver: device driver definition
697 * Remove a previously registered device driver
699 void connman_device_driver_unregister(struct connman_device_driver *driver)
701 DBG("driver %p name %s", driver, driver->name);
703 driver_list = g_slist_remove(driver_list, driver);
705 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
706 remove_driver, driver);
709 static void unregister_network(gpointer data)
711 struct connman_network *network = data;
713 DBG("network %p", network);
715 connman_element_unregister((struct connman_element *) network);
717 connman_network_unref(network);
720 static void device_destruct(struct connman_element *element)
722 struct connman_device *device = element->device;
724 DBG("element %p name %s", element, element->name);
726 if (device->timeout > 0) {
727 g_source_remove(device->timeout);
731 clear_scan_trigger(device);
733 if (device->pending != NULL) {
734 dbus_message_unref(device->pending);
735 device->pending = NULL;
738 g_free(device->ident);
739 g_free(device->node);
740 g_free(device->name);
741 g_free(device->address);
742 g_free(device->control);
743 g_free(device->interface);
745 g_free(device->last_network);
747 g_hash_table_destroy(device->networks);
748 device->networks = NULL;
752 * connman_device_create:
753 * @node: device node name (for example an address)
756 * Allocate a new device of given #type and assign the #node name to it.
758 * Returns: a newly-allocated #connman_device structure
760 struct connman_device *connman_device_create(const char *node,
761 enum connman_device_type type)
763 struct connman_device *device;
766 DBG("node %s type %d", node, type);
768 device = g_try_new0(struct connman_device, 1);
772 DBG("device %p", device);
774 __connman_element_initialize(&device->element);
776 device->element.name = g_strdup(node);
777 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
779 device->element.device = device;
780 device->element.destruct = device_destruct;
782 str = type2string(type);
784 connman_element_set_string(&device->element,
785 CONNMAN_PROPERTY_ID_TYPE, str);
787 device->element.ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP;
790 device->name = g_strdup(type2description(device->type));
791 device->mode = CONNMAN_DEVICE_MODE_UNKNOWN;
793 device->powered_persistent = TRUE;
795 device->phyindex = -1;
798 case CONNMAN_DEVICE_TYPE_UNKNOWN:
799 case CONNMAN_DEVICE_TYPE_VENDOR:
800 device->scan_interval = 0;
802 case CONNMAN_DEVICE_TYPE_ETHERNET:
803 case CONNMAN_DEVICE_TYPE_WIFI:
804 device->scan_interval = 300;
806 case CONNMAN_DEVICE_TYPE_WIMAX:
807 device->scan_interval = 0;
809 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
810 device->scan_interval = 0;
812 case CONNMAN_DEVICE_TYPE_GPS:
813 device->scan_interval = 0;
815 case CONNMAN_DEVICE_TYPE_CELLULAR:
816 case CONNMAN_DEVICE_TYPE_MBM:
817 case CONNMAN_DEVICE_TYPE_HSO:
818 device->scan_interval = 0;
822 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
823 g_free, unregister_network);
829 * connman_device_ref:
830 * @device: device structure
832 * Increase reference counter of device
834 struct connman_device *connman_device_ref(struct connman_device *device)
836 if (connman_element_ref(&device->element) == NULL)
843 * connman_device_unref:
844 * @device: device structure
846 * Decrease reference counter of device
848 void connman_device_unref(struct connman_device *device)
850 connman_element_unref(&device->element);
853 const char *__connman_device_get_type(struct connman_device *device)
855 return type2string(device->type);
859 * connman_device_get_type:
860 * @device: device structure
864 enum connman_device_type connman_device_get_type(struct connman_device *device)
870 * connman_device_get_name:
871 * @device: device structure
873 * Get unique name of device
875 const char *connman_device_get_name(struct connman_device *device)
877 return device->element.name;
881 * connman_device_get_path:
882 * @device: device structure
884 * Get path name of device
886 const char *connman_device_get_path(struct connman_device *device)
888 return device->element.path;
892 * connman_device_set_index:
893 * @device: device structure
894 * @index: index number
896 * Set index number of device
898 void connman_device_set_index(struct connman_device *device, int index)
900 device->element.index = index;
904 * connman_device_get_index:
905 * @device: device structure
907 * Get index number of device
909 int connman_device_get_index(struct connman_device *device)
911 return device->element.index;
914 int __connman_device_get_phyindex(struct connman_device *device)
916 return device->phyindex;
919 void __connman_device_set_phyindex(struct connman_device *device,
922 device->phyindex = phyindex;
926 * connman_device_set_interface:
927 * @device: device structure
928 * @interface: interface name
929 * @control: control interface
931 * Set interface name of device
933 void connman_device_set_interface(struct connman_device *device,
934 const char *interface, const char *control)
936 g_free(device->element.devname);
937 device->element.devname = g_strdup(interface);
939 g_free(device->interface);
940 device->interface = g_strdup(interface);
942 g_free(device->control);
943 device->control = g_strdup(control);
945 if (device->name == NULL) {
946 const char *str = type2description(device->type);
947 if (str != NULL && device->interface != NULL)
948 device->name = g_strdup_printf("%s (%s)", str,
953 const char *connman_device_get_control(struct connman_device *device)
955 return device->control;
959 * connman_device_set_ident:
960 * @device: device structure
961 * @ident: unique identifier
963 * Set unique identifier of device
965 void connman_device_set_ident(struct connman_device *device,
968 g_free(device->ident);
969 device->ident = g_strdup(ident);
972 const char *__connman_device_get_ident(struct connman_device *device)
974 return device->ident;
978 * connman_device_set_mode:
979 * @device: device structure
980 * @mode: network mode
982 * Change network mode of device
984 void connman_device_set_mode(struct connman_device *device,
985 enum connman_device_mode mode)
991 * connman_device_get_mode:
992 * @device: device structure
994 * Get network mode of device
996 enum connman_device_mode connman_device_get_mode(struct connman_device *device)
1002 * connman_device_set_powered:
1003 * @device: device structure
1004 * @powered: powered state
1006 * Change power state of device
1008 int connman_device_set_powered(struct connman_device *device,
1009 connman_bool_t powered)
1011 enum connman_service_type type;
1013 DBG("driver %p powered %d", device, powered);
1015 if (device->timeout > 0) {
1016 g_source_remove(device->timeout);
1017 device->timeout = 0;
1020 if (device->pending != NULL) {
1021 g_dbus_send_reply(connection, device->pending,
1024 dbus_message_unref(device->pending);
1025 device->pending = NULL;
1028 if (device->powered == powered)
1031 device->powered = powered;
1032 device->powered_pending = powered;
1034 type = __connman_device_get_service_type(device);
1036 if (device->powered == TRUE)
1037 __connman_notifier_enable(type);
1039 __connman_notifier_disable(type);
1041 if (device->registered == FALSE)
1044 powered_changed(device);
1046 if (powered == FALSE)
1049 reset_scan_trigger(device);
1051 if (device->driver->scan)
1052 device->driver->scan(device);
1057 int __connman_device_set_blocked(struct connman_device *device,
1058 connman_bool_t blocked)
1060 connman_bool_t powered;
1062 DBG("device %p blocked %d", device, blocked);
1064 device->blocked = blocked;
1066 if (device->offlinemode == TRUE)
1069 connman_info("%s {rfkill} blocked %d", device->interface, blocked);
1071 if (blocked == FALSE)
1072 powered = device->powered_persistent;
1076 return set_powered(device, powered);
1079 int __connman_device_scan(struct connman_device *device)
1081 if (!device->driver || !device->driver->scan)
1084 if (device->powered == FALSE)
1087 reset_scan_trigger(device);
1089 return device->driver->scan(device);
1092 int __connman_device_enable(struct connman_device *device)
1094 enum connman_service_type type;
1097 DBG("device %p", device);
1099 if (!device->driver || !device->driver->enable)
1102 if (device->powered_pending == TRUE)
1105 device->powered_pending = TRUE;
1107 err = device->driver->enable(device);
1111 device->powered = TRUE;
1113 type = __connman_device_get_service_type(device);
1114 __connman_notifier_enable(type);
1119 int __connman_device_enable_persistent(struct connman_device *device)
1121 DBG("device %p", device);
1123 device->powered_persistent = TRUE;
1125 __connman_storage_save_device(device);
1127 return __connman_device_enable(device);
1130 int __connman_device_disable(struct connman_device *device)
1132 enum connman_service_type type;
1135 DBG("device %p", device);
1137 if (!device->driver || !device->driver->disable)
1140 if (device->powered == FALSE)
1143 if (device->powered_pending == FALSE)
1146 device->powered_pending = FALSE;
1148 device->reconnect = FALSE;
1150 clear_scan_trigger(device);
1152 g_hash_table_remove_all(device->networks);
1154 err = device->driver->disable(device);
1158 device->powered = FALSE;
1160 type = __connman_device_get_service_type(device);
1161 __connman_notifier_disable(type);
1166 int __connman_device_disable_persistent(struct connman_device *device)
1168 DBG("device %p", device);
1170 device->powered_persistent = FALSE;
1172 __connman_storage_save_device(device);
1174 return __connman_device_disable(device);
1177 int __connman_device_disconnect(struct connman_device *device)
1179 GHashTableIter iter;
1180 gpointer key, value;
1182 DBG("device %p", device);
1184 connman_device_set_disconnected(device, TRUE);
1186 g_hash_table_iter_init(&iter, device->networks);
1188 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1189 struct connman_network *network = value;
1191 if (__connman_network_get_connecting(network) == TRUE) {
1193 * Skip network in the process of connecting.
1194 * This is a workaround for WiFi networks serviced
1195 * by the supplicant plugin that hold a reference
1196 * to the network. If we disconnect the network
1197 * here then the referenced object will not be
1198 * registered and usage (like launching DHCP client)
1199 * will fail. There is nothing to be gained by
1200 * removing the network here anyway.
1202 connman_warn("Skipping disconnect of %s",
1203 connman_network_get_identifier(network));
1207 __connman_network_disconnect(network);
1213 static void mark_network_unavailable(gpointer key, gpointer value,
1216 struct connman_network *network = value;
1218 if (connman_network_get_connected(network) == TRUE)
1221 connman_network_set_available(network, FALSE);
1224 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1227 struct connman_network *network = value;
1229 if (connman_network_get_connected(network) == TRUE)
1232 if (connman_network_get_available(network) == TRUE)
1238 void __connman_device_cleanup_networks(struct connman_device *device)
1240 g_hash_table_foreach_remove(device->networks,
1241 remove_unavailable_network, NULL);
1244 static void scanning_changed(struct connman_device *device)
1246 DBusMessage *signal;
1247 DBusMessageIter iter;
1249 signal = dbus_message_new_signal(device->element.path,
1250 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1254 dbus_message_iter_init_append(signal, &iter);
1255 connman_dbus_property_append_variant(&iter, "Scanning",
1256 DBUS_TYPE_BOOLEAN, &device->scanning);
1258 g_dbus_send_message(connection, signal);
1261 static void mark_network_available(gpointer key, gpointer value,
1264 struct connman_network *network = value;
1266 connman_network_set_available(network, TRUE);
1269 void connman_device_cleanup_scanning(struct connman_device *device)
1271 device->scanning = FALSE;
1273 scanning_changed(device);
1275 g_hash_table_foreach(device->networks,
1276 mark_network_available, NULL);
1280 * connman_device_set_scanning:
1281 * @device: device structure
1282 * @scanning: scanning state
1284 * Change scanning state of device
1286 int connman_device_set_scanning(struct connman_device *device,
1287 connman_bool_t scanning)
1289 DBG("device %p scanning %d", device, scanning);
1291 if (!device->driver || !device->driver->scan)
1294 if (device->scanning == scanning)
1297 device->scanning = scanning;
1299 scanning_changed(device);
1301 if (scanning == TRUE) {
1302 reset_scan_trigger(device);
1304 g_hash_table_foreach(device->networks,
1305 mark_network_unavailable, NULL);
1310 __connman_device_cleanup_networks(device);
1312 if (device->connections > 0)
1315 if (device->disconnected == TRUE)
1318 __connman_service_auto_connect();
1324 * connman_device_set_disconnected:
1325 * @device: device structure
1326 * @disconnected: disconnected state
1328 * Change disconnected state of device (only for device with networks)
1330 int connman_device_set_disconnected(struct connman_device *device,
1331 connman_bool_t disconnected)
1333 DBG("device %p disconnected %d", device, disconnected);
1335 switch (device->mode) {
1336 case CONNMAN_DEVICE_MODE_UNKNOWN:
1338 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1339 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1343 if (device->disconnected == disconnected)
1346 device->disconnected = disconnected;
1348 if (disconnected == TRUE)
1349 force_scan_trigger(device);
1355 * connman_device_get_disconnected:
1356 * @device: device structure
1358 * Get device disconnected state
1360 connman_bool_t connman_device_get_disconnected(struct connman_device *device)
1362 return device->disconnected;
1366 * connman_device_set_string:
1367 * @device: device structure
1368 * @key: unique identifier
1369 * @value: string value
1371 * Set string value for specific key
1373 int connman_device_set_string(struct connman_device *device,
1374 const char *key, const char *value)
1376 DBG("device %p key %s value %s", device, key, value);
1378 if (g_str_equal(key, "Address") == TRUE) {
1379 g_free(device->address);
1380 device->address = g_strdup(value);
1381 } else if (g_str_equal(key, "Name") == TRUE) {
1382 g_free(device->name);
1383 device->name = g_strdup(value);
1384 } else if (g_str_equal(key, "Node") == TRUE) {
1385 g_free(device->node);
1386 device->node = g_strdup(value);
1389 return connman_element_set_string(&device->element, key, value);
1393 * connman_device_get_string:
1394 * @device: device structure
1395 * @key: unique identifier
1397 * Get string value for specific key
1399 const char *connman_device_get_string(struct connman_device *device,
1402 DBG("device %p key %s", device, key);
1404 if (g_str_equal(key, "Address") == TRUE)
1405 return device->address;
1406 else if (g_str_equal(key, "Name") == TRUE)
1407 return device->name;
1408 else if (g_str_equal(key, "Node") == TRUE)
1409 return device->node;
1411 return connman_element_get_string(&device->element, key);
1414 static void set_offlinemode(struct connman_element *element, gpointer user_data)
1416 struct connman_device *device = element->device;
1417 connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data);
1418 connman_bool_t powered;
1420 DBG("element %p name %s", element, element->name);
1425 device->offlinemode = offlinemode;
1427 powered = (offlinemode == TRUE) ? FALSE : TRUE;
1429 if (device->powered == powered)
1432 if (device->powered_persistent == FALSE)
1435 set_powered(device, powered);
1438 int __connman_device_set_offlinemode(connman_bool_t offlinemode)
1440 DBG("offlinmode %d", offlinemode);
1442 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
1443 set_offlinemode, GUINT_TO_POINTER(offlinemode));
1445 __connman_notifier_offlinemode(offlinemode);
1450 void __connman_device_increase_connections(struct connman_device *device)
1452 device->connections++;
1455 void __connman_device_decrease_connections(struct connman_device *device)
1457 device->connections--;
1461 * connman_device_add_network:
1462 * @device: device structure
1463 * @network: network structure
1465 * Add new network to the device
1467 int connman_device_add_network(struct connman_device *device,
1468 struct connman_network *network)
1470 const char *identifier = connman_network_get_identifier(network);
1473 DBG("device %p network %p", device, network);
1475 if (identifier == NULL)
1478 switch (device->mode) {
1479 case CONNMAN_DEVICE_MODE_UNKNOWN:
1481 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1482 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1486 __connman_network_set_device(network, device);
1488 err = connman_element_register((struct connman_element *) network,
1491 __connman_network_set_device(network, NULL);
1495 g_hash_table_insert(device->networks, g_strdup(identifier),
1502 * connman_device_get_network:
1503 * @device: device structure
1504 * @identifier: network identifier
1506 * Get network for given identifier
1508 struct connman_network *connman_device_get_network(struct connman_device *device,
1509 const char *identifier)
1511 DBG("device %p identifier %s", device, identifier);
1513 return g_hash_table_lookup(device->networks, identifier);
1517 * connman_device_remove_network:
1518 * @device: device structure
1519 * @identifier: network identifier
1521 * Remove network for given identifier
1523 int connman_device_remove_network(struct connman_device *device,
1524 const char *identifier)
1526 DBG("device %p identifier %s", device, identifier);
1528 g_hash_table_remove(device->networks, identifier);
1533 void connman_device_remove_all_networks(struct connman_device *device)
1535 g_hash_table_remove_all(device->networks);
1538 void __connman_device_set_network(struct connman_device *device,
1539 struct connman_network *network)
1543 if (device->network == network)
1546 if (device->network != NULL)
1547 connman_network_unref(device->network);
1549 if (network != NULL) {
1550 name = connman_network_get_string(network,
1551 CONNMAN_PROPERTY_ID_NAME);
1552 g_free(device->last_network);
1553 device->last_network = g_strdup(name);
1555 device->network = connman_network_ref(network);
1557 g_free(device->last_network);
1558 device->last_network = NULL;
1560 device->network = NULL;
1564 void __connman_device_set_reconnect(struct connman_device *device,
1565 connman_bool_t reconnect)
1567 device->reconnect = reconnect;
1570 connman_bool_t __connman_device_get_reconnect(
1571 struct connman_device *device)
1573 return device->reconnect;
1577 * connman_device_register:
1578 * @device: device structure
1580 * Register device with the system
1582 int connman_device_register(struct connman_device *device)
1584 __connman_storage_load_device(device);
1586 device->offlinemode = __connman_profile_get_offlinemode();
1588 return connman_element_register(&device->element, NULL);
1592 * connman_device_unregister:
1593 * @device: device structure
1595 * Unregister device with the system
1597 void connman_device_unregister(struct connman_device *device)
1599 __connman_storage_save_device(device);
1601 connman_element_unregister(&device->element);
1605 * connman_device_get_data:
1606 * @device: device structure
1608 * Get private device data pointer
1610 void *connman_device_get_data(struct connman_device *device)
1612 return device->driver_data;
1616 * connman_device_set_data:
1617 * @device: device structure
1618 * @data: data pointer
1620 * Set private device data pointer
1622 void connman_device_set_data(struct connman_device *device, void *data)
1624 device->driver_data = data;
1627 static gboolean match_driver(struct connman_device *device,
1628 struct connman_device_driver *driver)
1630 if (device->type == driver->type ||
1631 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1637 static int device_probe(struct connman_element *element)
1639 struct connman_device *device = element->device;
1642 DBG("element %p name %s", element, element->name);
1647 if (device->driver != NULL)
1650 for (list = driver_list; list; list = list->next) {
1651 struct connman_device_driver *driver = list->data;
1653 if (match_driver(device, driver) == FALSE)
1656 DBG("driver %p name %s", driver, driver->name);
1658 if (driver->probe(device) == 0) {
1659 device->driver = driver;
1664 if (device->driver == NULL)
1667 return setup_device(device);
1670 static void device_remove(struct connman_element *element)
1672 struct connman_device *device = element->device;
1674 DBG("element %p name %s", element, element->name);
1679 if (device->driver == NULL)
1682 remove_device(device);
1685 static struct connman_driver device_driver = {
1687 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
1688 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
1689 .probe = device_probe,
1690 .remove = device_remove,
1693 static int device_load(struct connman_device *device)
1695 const char *ident = __connman_profile_active_ident();
1697 GError *error = NULL;
1699 connman_bool_t powered;
1702 DBG("device %p", device);
1704 keyfile = __connman_storage_open_profile(ident);
1705 if (keyfile == NULL)
1708 identifier = g_strdup_printf("device_%s", device->element.name);
1709 if (identifier == NULL)
1712 powered = g_key_file_get_boolean(keyfile, identifier,
1715 device->powered_persistent = powered;
1716 g_clear_error(&error);
1718 switch (device->mode) {
1719 case CONNMAN_DEVICE_MODE_UNKNOWN:
1721 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1722 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1723 val = g_key_file_get_integer(keyfile, identifier,
1724 "ScanInterval", &error);
1725 if (error == NULL && val > 0)
1726 device->scan_interval = val;
1727 g_clear_error(&error);
1734 __connman_storage_close_profile(ident, keyfile, FALSE);
1739 static int device_save(struct connman_device *device)
1741 const char *ident = __connman_profile_active_ident();
1745 DBG("device %p", device);
1747 keyfile = __connman_storage_open_profile(ident);
1748 if (keyfile == NULL)
1751 identifier = g_strdup_printf("device_%s", device->element.name);
1752 if (identifier == NULL)
1755 g_key_file_set_boolean(keyfile, identifier,
1756 "Powered", device->powered_persistent);
1758 switch (device->mode) {
1759 case CONNMAN_DEVICE_MODE_UNKNOWN:
1761 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1762 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1763 if (device->scan_interval > 0)
1764 g_key_file_set_integer(keyfile, identifier,
1765 "ScanInterval", device->scan_interval);
1772 __connman_storage_close_profile(ident, keyfile, TRUE);
1777 static struct connman_storage device_storage = {
1779 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
1780 .device_load = device_load,
1781 .device_save = device_save,
1784 int __connman_device_init(void)
1788 connection = connman_dbus_get_connection();
1790 if (connman_storage_register(&device_storage) < 0)
1791 connman_error("Failed to register device storage");
1793 return connman_driver_register(&device_driver);
1796 void __connman_device_cleanup(void)
1800 connman_driver_unregister(&device_driver);
1802 connman_storage_unregister(&device_storage);
1804 dbus_connection_unref(connection);