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 offlinemode;
41 connman_bool_t blocked;
42 connman_bool_t powered;
43 connman_bool_t powered_pending;
44 connman_bool_t powered_persistent;
45 connman_bool_t scanning;
46 connman_bool_t disconnected;
47 connman_bool_t reconnect;
48 connman_uint16_t scan_interval;
56 unsigned int connections;
59 struct connman_device_driver *driver;
62 connman_bool_t registered;
65 struct connman_network *network;
72 static gboolean device_scan_trigger(gpointer user_data)
74 struct connman_device *device = user_data;
76 DBG("device %p", device);
78 if (device->driver == NULL) {
79 device->scan_timeout = 0;
83 if (device->driver->scan)
84 device->driver->scan(device);
89 static void clear_scan_trigger(struct connman_device *device)
91 if (device->scan_timeout > 0) {
92 g_source_remove(device->scan_timeout);
93 device->scan_timeout = 0;
97 static void reset_scan_trigger(struct connman_device *device)
99 clear_scan_trigger(device);
101 if (device->scan_interval > 0) {
102 guint interval = device->scan_interval;
103 device->scan_timeout = g_timeout_add_seconds(interval,
104 device_scan_trigger, device);
108 static void force_scan_trigger(struct connman_device *device)
110 clear_scan_trigger(device);
112 device->scan_timeout = g_timeout_add_seconds(5,
113 device_scan_trigger, device);
116 void connman_device_schedule_scan(struct connman_device *device)
118 reset_scan_trigger(device);
121 static const char *type2description(enum connman_device_type type)
124 case CONNMAN_DEVICE_TYPE_UNKNOWN:
125 case CONNMAN_DEVICE_TYPE_VENDOR:
127 case CONNMAN_DEVICE_TYPE_ETHERNET:
129 case CONNMAN_DEVICE_TYPE_WIFI:
131 case CONNMAN_DEVICE_TYPE_WIMAX:
133 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
135 case CONNMAN_DEVICE_TYPE_GPS:
137 case CONNMAN_DEVICE_TYPE_MBM:
138 case CONNMAN_DEVICE_TYPE_CELLULAR:
139 case CONNMAN_DEVICE_TYPE_HSO:
140 case CONNMAN_DEVICE_TYPE_NOZOMI:
141 case CONNMAN_DEVICE_TYPE_HUAWEI:
142 case CONNMAN_DEVICE_TYPE_NOVATEL:
149 static const char *type2string(enum connman_device_type type)
152 case CONNMAN_DEVICE_TYPE_UNKNOWN:
153 case CONNMAN_DEVICE_TYPE_VENDOR:
155 case CONNMAN_DEVICE_TYPE_ETHERNET:
157 case CONNMAN_DEVICE_TYPE_WIFI:
159 case CONNMAN_DEVICE_TYPE_WIMAX:
161 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
163 case CONNMAN_DEVICE_TYPE_GPS:
165 case CONNMAN_DEVICE_TYPE_MBM:
166 case CONNMAN_DEVICE_TYPE_CELLULAR:
167 case CONNMAN_DEVICE_TYPE_HSO:
168 case CONNMAN_DEVICE_TYPE_HUAWEI:
169 case CONNMAN_DEVICE_TYPE_NOZOMI:
170 case CONNMAN_DEVICE_TYPE_NOVATEL:
177 enum connman_service_type __connman_device_get_service_type(struct connman_device *device)
179 enum connman_device_type type = connman_device_get_type(device);
182 case CONNMAN_DEVICE_TYPE_UNKNOWN:
183 case CONNMAN_DEVICE_TYPE_VENDOR:
184 case CONNMAN_DEVICE_TYPE_GPS:
185 case CONNMAN_DEVICE_TYPE_NOZOMI:
186 case CONNMAN_DEVICE_TYPE_HUAWEI:
187 case CONNMAN_DEVICE_TYPE_NOVATEL:
189 case CONNMAN_DEVICE_TYPE_ETHERNET:
190 return CONNMAN_SERVICE_TYPE_ETHERNET;
191 case CONNMAN_DEVICE_TYPE_WIFI:
192 return CONNMAN_SERVICE_TYPE_WIFI;
193 case CONNMAN_DEVICE_TYPE_WIMAX:
194 return CONNMAN_SERVICE_TYPE_WIMAX;
195 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
196 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
197 case CONNMAN_DEVICE_TYPE_MBM:
198 case CONNMAN_DEVICE_TYPE_CELLULAR:
199 case CONNMAN_DEVICE_TYPE_HSO:
200 return CONNMAN_SERVICE_TYPE_CELLULAR;
203 return CONNMAN_SERVICE_TYPE_UNKNOWN;
206 static int powered_changed(struct connman_device *device)
209 DBusMessageIter entry, value;
210 const char *key = "Powered";
212 signal = dbus_message_new_signal(device->element.path,
213 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
217 dbus_message_iter_init_append(signal, &entry);
219 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
221 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
222 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
223 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
225 dbus_message_iter_close_container(&entry, &value);
227 g_dbus_send_message(connection, signal);
232 static int set_powered(struct connman_device *device, connman_bool_t powered)
234 struct connman_device_driver *driver = device->driver;
235 enum connman_service_type type;
238 DBG("device %p powered %d", device, powered);
240 if (device->powered_pending == powered)
246 type = __connman_device_get_service_type(device);
248 if (powered == TRUE) {
249 if (driver->enable) {
250 device->powered_pending = powered;
252 err = driver->enable(device);
254 __connman_notifier_enable(type);
258 device->powered_pending = powered;
260 device->reconnect = FALSE;
262 clear_scan_trigger(device);
264 g_hash_table_remove_all(device->networks);
266 if (driver->disable) {
267 err = driver->disable(device);
269 __connman_notifier_disable(type);
275 device->powered = powered;
277 if (device->registered == TRUE)
278 powered_changed(device);
284 static void append_path(gpointer key, gpointer value, gpointer user_data)
286 struct connman_element *element = value;
287 DBusMessageIter *iter = user_data;
289 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
293 static void append_networks(struct connman_device *device,
294 DBusMessageIter *entry)
296 DBusMessageIter value, iter;
297 const char *key = "Networks";
299 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
301 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
302 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
305 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
306 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
307 g_hash_table_foreach(device->networks, append_path, &iter);
308 dbus_message_iter_close_container(&value, &iter);
310 dbus_message_iter_close_container(entry, &value);
313 static DBusMessage *get_properties(DBusConnection *conn,
314 DBusMessage *msg, void *data)
316 struct connman_device *device = data;
318 DBusMessageIter array, dict, entry;
321 DBG("conn %p", conn);
323 if (__connman_security_check_privilege(msg,
324 CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
325 return __connman_error_permission_denied(msg);
327 reply = dbus_message_new_method_return(msg);
331 dbus_message_iter_init_append(reply, &array);
333 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
334 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
335 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
336 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
338 if (device->name != NULL)
339 connman_dbus_dict_append_variant(&dict, "Name",
340 DBUS_TYPE_STRING, &device->name);
342 str = type2string(device->type);
344 connman_dbus_dict_append_variant(&dict, "Type",
345 DBUS_TYPE_STRING, &str);
347 if (device->address != NULL)
348 connman_dbus_dict_append_variant(&dict, "Address",
349 DBUS_TYPE_STRING, &device->address);
351 if (device->interface != NULL)
352 connman_dbus_dict_append_variant(&dict, "Interface",
353 DBUS_TYPE_STRING, &device->interface);
355 connman_dbus_dict_append_variant(&dict, "Powered",
356 DBUS_TYPE_BOOLEAN, &device->powered);
358 if (device->driver && device->driver->scan)
359 connman_dbus_dict_append_variant(&dict, "Scanning",
360 DBUS_TYPE_BOOLEAN, &device->scanning);
362 switch (device->mode) {
363 case CONNMAN_DEVICE_MODE_UNKNOWN:
365 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
366 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
367 if (device->scan_interval > 0)
368 connman_dbus_dict_append_variant(&dict, "ScanInterval",
369 DBUS_TYPE_UINT16, &device->scan_interval);
371 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
373 append_networks(device, &entry);
374 dbus_message_iter_close_container(&dict, &entry);
378 dbus_message_iter_close_container(&array, &dict);
383 static gboolean powered_timeout(gpointer user_data)
385 struct connman_device *device = user_data;
387 DBG("device %p", device);
391 if (device->pending != NULL) {
394 reply = __connman_error_operation_timeout(device->pending);
396 g_dbus_send_message(connection, reply);
398 dbus_message_unref(device->pending);
399 device->pending = NULL;
405 static DBusMessage *set_property(DBusConnection *conn,
406 DBusMessage *msg, void *data)
408 struct connman_device *device = data;
409 DBusMessageIter iter, value;
413 DBG("conn %p", conn);
415 if (dbus_message_iter_init(msg, &iter) == FALSE)
416 return __connman_error_invalid_arguments(msg);
418 dbus_message_iter_get_basic(&iter, &name);
419 dbus_message_iter_next(&iter);
420 dbus_message_iter_recurse(&iter, &value);
422 if (__connman_security_check_privilege(msg,
423 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
424 return __connman_error_permission_denied(msg);
426 type = dbus_message_iter_get_arg_type(&value);
428 if (g_str_equal(name, "Powered") == TRUE) {
429 connman_bool_t powered;
432 if (type != DBUS_TYPE_BOOLEAN)
433 return __connman_error_invalid_arguments(msg);
435 dbus_message_iter_get_basic(&value, &powered);
437 device->powered_persistent = powered;
439 __connman_storage_save_device(device);
441 if (device->powered == powered)
442 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
444 if (device->pending != NULL)
445 return __connman_error_in_progress(msg);
447 err = set_powered(device, powered);
449 if (err != -EINPROGRESS)
450 return __connman_error_failed(msg, -err);
452 device->pending = dbus_message_ref(msg);
454 device->timeout = g_timeout_add_seconds(15,
455 powered_timeout, device);
459 } else if (g_str_equal(name, "ScanInterval") == TRUE) {
460 connman_uint16_t interval;
462 switch (device->mode) {
463 case CONNMAN_DEVICE_MODE_UNKNOWN:
464 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
465 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
469 if (type != DBUS_TYPE_UINT16)
470 return __connman_error_invalid_arguments(msg);
472 dbus_message_iter_get_basic(&value, &interval);
474 if (device->scan_interval != interval) {
475 device->scan_interval = interval;
477 __connman_storage_save_device(device);
479 reset_scan_trigger(device);
482 return __connman_error_invalid_property(msg);
484 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
487 static DBusMessage *propose_scan(DBusConnection *conn,
488 DBusMessage *msg, void *data)
490 struct connman_device *device = data;
493 DBG("conn %p", conn);
495 switch (device->mode) {
496 case CONNMAN_DEVICE_MODE_UNKNOWN:
497 return __connman_error_not_supported(msg);
498 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
499 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
503 err = __connman_device_scan(device);
505 return __connman_error_failed(msg, -err);
507 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
510 static GDBusMethodTable device_methods[] = {
511 { "GetProperties", "", "a{sv}", get_properties },
512 { "SetProperty", "sv", "", set_property,
513 G_DBUS_METHOD_FLAG_ASYNC },
514 { "ProposeScan", "", "", propose_scan },
518 static GDBusSignalTable device_signals[] = {
519 { "PropertyChanged", "sv" },
523 static void append_devices(DBusMessageIter *entry)
525 DBusMessageIter value, iter;
526 const char *key = "Devices";
528 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
530 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
531 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
534 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
535 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
536 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
537 dbus_message_iter_close_container(&value, &iter);
539 dbus_message_iter_close_container(entry, &value);
542 static void emit_devices_signal(void)
545 DBusMessageIter entry;
547 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
548 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
552 dbus_message_iter_init_append(signal, &entry);
554 append_devices(&entry);
556 g_dbus_send_message(connection, signal);
559 static int register_interface(struct connman_element *element)
561 struct connman_device *device = element->device;
563 DBG("element %p name %s", element, element->name);
565 if (g_dbus_register_interface(connection, element->path,
566 CONNMAN_DEVICE_INTERFACE,
567 device_methods, device_signals,
568 NULL, device, NULL) == FALSE) {
569 connman_error("Failed to register %s device", element->path);
573 device->registered = TRUE;
575 emit_devices_signal();
580 static void unregister_interface(struct connman_element *element)
582 struct connman_device *device = element->device;
584 DBG("element %p name %s", element, element->name);
586 device->registered = FALSE;
588 emit_devices_signal();
590 g_dbus_unregister_interface(connection, element->path,
591 CONNMAN_DEVICE_INTERFACE);
594 static int setup_device(struct connman_device *device)
596 enum connman_service_type type;
599 DBG("device %p", device);
601 err = register_interface(&device->element);
603 if (device->driver->remove)
604 device->driver->remove(device);
605 device->driver = NULL;
609 type = __connman_device_get_service_type(device);
610 __connman_notifier_register(type);
612 switch (device->mode) {
613 case CONNMAN_DEVICE_MODE_UNKNOWN:
614 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
615 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
619 if (device->offlinemode == FALSE &&
620 device->powered_persistent == TRUE)
621 __connman_device_enable(device);
626 static void probe_driver(struct connman_element *element, gpointer user_data)
628 struct connman_device_driver *driver = user_data;
630 DBG("element %p name %s", element, element->name);
632 if (element->device == NULL)
635 if (element->device->driver != NULL)
638 if (driver->type != element->device->type)
641 if (driver->probe(element->device) < 0)
644 element->device->driver = driver;
646 setup_device(element->device);
649 static void remove_device(struct connman_device *device)
651 enum connman_service_type type;
653 DBG("device %p", device);
655 __connman_device_disable(device);
657 switch (device->mode) {
658 case CONNMAN_DEVICE_MODE_UNKNOWN:
659 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
660 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
664 type = __connman_device_get_service_type(device);
665 __connman_notifier_unregister(type);
667 unregister_interface(&device->element);
669 if (device->driver->remove)
670 device->driver->remove(device);
672 device->driver = NULL;
675 static void remove_driver(struct connman_element *element, gpointer user_data)
677 struct connman_device_driver *driver = user_data;
679 DBG("element %p name %s", element, element->name);
681 if (element->device == NULL)
684 if (element->device->driver == driver)
685 remove_device(element->device);
688 connman_bool_t __connman_device_has_driver(struct connman_device *device)
690 if (device == NULL || device->driver == NULL)
693 return device->registered;
696 static GSList *driver_list = NULL;
698 static gint compare_priority(gconstpointer a, gconstpointer b)
700 const struct connman_device_driver *driver1 = a;
701 const struct connman_device_driver *driver2 = b;
703 return driver2->priority - driver1->priority;
707 * connman_device_driver_register:
708 * @driver: device driver definition
710 * Register a new device driver
712 * Returns: %0 on success
714 int connman_device_driver_register(struct connman_device_driver *driver)
716 DBG("driver %p name %s", driver, driver->name);
718 driver_list = g_slist_insert_sorted(driver_list, driver,
721 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
722 probe_driver, driver);
728 * connman_device_driver_unregister:
729 * @driver: device driver definition
731 * Remove a previously registered device driver
733 void connman_device_driver_unregister(struct connman_device_driver *driver)
735 DBG("driver %p name %s", driver, driver->name);
737 driver_list = g_slist_remove(driver_list, driver);
739 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
740 remove_driver, driver);
743 static void unregister_network(gpointer data)
745 struct connman_network *network = data;
747 DBG("network %p", network);
749 connman_element_unregister((struct connman_element *) network);
751 connman_network_unref(network);
754 static void device_destruct(struct connman_element *element)
756 struct connman_device *device = element->device;
758 DBG("element %p name %s", element, element->name);
760 if (device->timeout > 0) {
761 g_source_remove(device->timeout);
765 clear_scan_trigger(device);
767 if (device->pending != NULL) {
768 dbus_message_unref(device->pending);
769 device->pending = NULL;
772 g_free(device->ident);
773 g_free(device->node);
774 g_free(device->name);
775 g_free(device->address);
776 g_free(device->control);
777 g_free(device->interface);
779 g_free(device->last_network);
781 g_hash_table_destroy(device->networks);
782 device->networks = NULL;
786 * connman_device_create:
787 * @node: device node name (for example an address)
790 * Allocate a new device of given #type and assign the #node name to it.
792 * Returns: a newly-allocated #connman_device structure
794 struct connman_device *connman_device_create(const char *node,
795 enum connman_device_type type)
797 struct connman_device *device;
800 DBG("node %s type %d", node, type);
802 device = g_try_new0(struct connman_device, 1);
806 DBG("device %p", device);
808 __connman_element_initialize(&device->element);
810 device->element.name = g_strdup(node);
811 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
813 device->element.device = device;
814 device->element.destruct = device_destruct;
816 str = type2string(type);
818 connman_element_set_string(&device->element,
819 CONNMAN_PROPERTY_ID_TYPE, str);
821 device->element.ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP;
824 device->name = g_strdup(type2description(device->type));
825 device->mode = CONNMAN_DEVICE_MODE_UNKNOWN;
826 device->secondary = FALSE;
828 device->powered_persistent = TRUE;
830 device->phyindex = -1;
833 case CONNMAN_DEVICE_TYPE_UNKNOWN:
834 case CONNMAN_DEVICE_TYPE_VENDOR:
835 device->scan_interval = 0;
837 case CONNMAN_DEVICE_TYPE_ETHERNET:
838 case CONNMAN_DEVICE_TYPE_WIFI:
839 device->scan_interval = 300;
841 case CONNMAN_DEVICE_TYPE_WIMAX:
842 device->scan_interval = 0;
844 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
845 device->scan_interval = 0;
847 case CONNMAN_DEVICE_TYPE_GPS:
848 device->scan_interval = 0;
850 case CONNMAN_DEVICE_TYPE_MBM:
851 case CONNMAN_DEVICE_TYPE_CELLULAR:
852 case CONNMAN_DEVICE_TYPE_HSO:
853 case CONNMAN_DEVICE_TYPE_NOZOMI:
854 case CONNMAN_DEVICE_TYPE_HUAWEI:
855 case CONNMAN_DEVICE_TYPE_NOVATEL:
856 device->scan_interval = 0;
860 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
861 g_free, unregister_network);
867 * connman_device_ref:
868 * @device: device structure
870 * Increase reference counter of device
872 struct connman_device *connman_device_ref(struct connman_device *device)
874 if (connman_element_ref(&device->element) == NULL)
881 * connman_device_unref:
882 * @device: device structure
884 * Decrease reference counter of device
886 void connman_device_unref(struct connman_device *device)
888 connman_element_unref(&device->element);
891 const char *__connman_device_get_type(struct connman_device *device)
893 return type2string(device->type);
897 * connman_device_get_type:
898 * @device: device structure
902 enum connman_device_type connman_device_get_type(struct connman_device *device)
908 * connman_device_get_name:
909 * @device: device structure
911 * Get unique name of device
913 const char *connman_device_get_name(struct connman_device *device)
915 return device->element.name;
919 * connman_device_get_path:
920 * @device: device structure
922 * Get path name of device
924 const char *connman_device_get_path(struct connman_device *device)
926 return device->element.path;
930 * connman_device_set_index:
931 * @device: device structure
932 * @index: index number
934 * Set index number of device
936 void connman_device_set_index(struct connman_device *device, int index)
938 device->element.index = index;
942 * connman_device_get_index:
943 * @device: device structure
945 * Get index number of device
947 int connman_device_get_index(struct connman_device *device)
949 return device->element.index;
952 int __connman_device_get_phyindex(struct connman_device *device)
954 return device->phyindex;
957 void __connman_device_set_phyindex(struct connman_device *device,
960 device->phyindex = phyindex;
964 * connman_device_set_interface:
965 * @device: device structure
966 * @interface: interface name
967 * @control: control interface
969 * Set interface name of device
971 void connman_device_set_interface(struct connman_device *device,
972 const char *interface, const char *control)
974 g_free(device->element.devname);
975 device->element.devname = g_strdup(interface);
977 g_free(device->interface);
978 device->interface = g_strdup(interface);
980 g_free(device->control);
981 device->control = g_strdup(control);
983 if (device->name == NULL) {
984 const char *str = type2description(device->type);
985 if (str != NULL && device->interface != NULL)
986 device->name = g_strdup_printf("%s (%s)", str,
991 const char *connman_device_get_control(struct connman_device *device)
993 return device->control;
997 * connman_device_set_ident:
998 * @device: device structure
999 * @ident: unique identifier
1001 * Set unique identifier of device
1003 void connman_device_set_ident(struct connman_device *device,
1006 g_free(device->ident);
1007 device->ident = g_strdup(ident);
1010 const char *__connman_device_get_ident(struct connman_device *device)
1012 return device->ident;
1016 * connman_device_set_mode:
1017 * @device: device structure
1018 * @mode: network mode
1020 * Change network mode of device
1022 void connman_device_set_mode(struct connman_device *device,
1023 enum connman_device_mode mode)
1025 device->mode = mode;
1029 * connman_device_get_mode:
1030 * @device: device structure
1032 * Get network mode of device
1034 enum connman_device_mode connman_device_get_mode(struct connman_device *device)
1036 return device->mode;
1040 * connman_device_set_secondary:
1041 * @device: device structure
1042 * @secondary: secondary value
1044 * Change secondary value of device
1046 void connman_device_set_secondary(struct connman_device *device,
1047 connman_bool_t secondary)
1049 device->secondary = secondary;
1053 * connman_device_get_secondary:
1054 * @device: device structure
1056 * Get secondary value of device
1058 connman_bool_t connman_device_get_secondary(struct connman_device *device)
1060 return device->secondary;
1064 * connman_device_set_powered:
1065 * @device: device structure
1066 * @powered: powered state
1068 * Change power state of device
1070 int connman_device_set_powered(struct connman_device *device,
1071 connman_bool_t powered)
1073 enum connman_service_type type;
1075 DBG("driver %p powered %d", device, powered);
1077 if (device->timeout > 0) {
1078 g_source_remove(device->timeout);
1079 device->timeout = 0;
1082 if (device->pending != NULL) {
1083 g_dbus_send_reply(connection, device->pending,
1086 dbus_message_unref(device->pending);
1087 device->pending = NULL;
1090 if (device->powered == powered)
1093 device->powered = powered;
1094 device->powered_pending = powered;
1096 type = __connman_device_get_service_type(device);
1098 if (device->powered == TRUE)
1099 __connman_notifier_enable(type);
1101 __connman_notifier_disable(type);
1103 if (device->registered == FALSE)
1106 powered_changed(device);
1108 if (powered == FALSE)
1111 reset_scan_trigger(device);
1113 if (device->driver->scan)
1114 device->driver->scan(device);
1119 int __connman_device_set_blocked(struct connman_device *device,
1120 connman_bool_t blocked)
1122 connman_bool_t powered;
1124 DBG("device %p blocked %d", device, blocked);
1126 device->blocked = blocked;
1128 if (device->offlinemode == TRUE)
1131 connman_info("%s {rfkill} blocked %d", device->interface, blocked);
1133 if (blocked == FALSE)
1134 powered = device->powered_persistent;
1138 return set_powered(device, powered);
1141 int __connman_device_scan(struct connman_device *device)
1143 if (!device->driver || !device->driver->scan)
1146 if (device->powered == FALSE)
1149 reset_scan_trigger(device);
1151 return device->driver->scan(device);
1154 int __connman_device_enable(struct connman_device *device)
1156 enum connman_service_type type;
1159 DBG("device %p", device);
1161 if (!device->driver || !device->driver->enable)
1164 if (device->powered_pending == TRUE)
1167 device->powered_pending = TRUE;
1169 err = device->driver->enable(device);
1173 device->powered = TRUE;
1175 type = __connman_device_get_service_type(device);
1176 __connman_notifier_enable(type);
1181 int __connman_device_enable_persistent(struct connman_device *device)
1183 DBG("device %p", device);
1185 device->powered_persistent = TRUE;
1187 __connman_storage_save_device(device);
1189 return __connman_device_enable(device);
1192 int __connman_device_disable(struct connman_device *device)
1194 enum connman_service_type type;
1197 DBG("device %p", device);
1199 if (!device->driver || !device->driver->disable)
1202 if (device->powered == FALSE)
1205 if (device->powered_pending == FALSE)
1208 device->powered_pending = FALSE;
1210 device->reconnect = FALSE;
1212 clear_scan_trigger(device);
1214 g_hash_table_remove_all(device->networks);
1216 err = device->driver->disable(device);
1220 device->powered = FALSE;
1222 type = __connman_device_get_service_type(device);
1223 __connman_notifier_disable(type);
1228 int __connman_device_disable_persistent(struct connman_device *device)
1230 DBG("device %p", device);
1232 device->powered_persistent = FALSE;
1234 __connman_storage_save_device(device);
1236 return __connman_device_disable(device);
1239 int __connman_device_disconnect(struct connman_device *device)
1241 GHashTableIter iter;
1242 gpointer key, value;
1244 DBG("device %p", device);
1246 connman_device_set_disconnected(device, TRUE);
1248 g_hash_table_iter_init(&iter, device->networks);
1250 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1251 struct connman_network *network = value;
1253 if (__connman_network_get_connecting(network) == TRUE) {
1255 * Skip network in the process of connecting.
1256 * This is a workaround for WiFi networks serviced
1257 * by the supplicant plugin that hold a reference
1258 * to the network. If we disconnect the network
1259 * here then the referenced object will not be
1260 * registered and usage (like launching DHCP client)
1261 * will fail. There is nothing to be gained by
1262 * removing the network here anyway.
1264 connman_warn("Skipping disconnect of %s",
1265 connman_network_get_identifier(network));
1269 __connman_network_disconnect(network);
1275 static void mark_network_unavailable(gpointer key, gpointer value,
1278 struct connman_network *network = value;
1280 if (connman_network_get_connected(network) == TRUE)
1283 connman_network_set_available(network, FALSE);
1286 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1289 struct connman_network *network = value;
1291 if (connman_network_get_connected(network) == TRUE)
1294 if (connman_network_get_available(network) == TRUE)
1300 void __connman_device_cleanup_networks(struct connman_device *device)
1302 g_hash_table_foreach_remove(device->networks,
1303 remove_unavailable_network, NULL);
1306 static void scanning_changed(struct connman_device *device)
1308 DBusMessage *signal;
1309 DBusMessageIter entry, value;
1310 const char *key = "Scanning";
1312 signal = dbus_message_new_signal(device->element.path,
1313 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1317 dbus_message_iter_init_append(signal, &entry);
1319 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1321 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1322 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
1323 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN,
1325 dbus_message_iter_close_container(&entry, &value);
1327 g_dbus_send_message(connection, signal);
1330 static void mark_network_available(gpointer key, gpointer value,
1333 struct connman_network *network = value;
1335 connman_network_set_available(network, TRUE);
1338 void connman_device_cleanup_scanning(struct connman_device *device)
1340 device->scanning = FALSE;
1342 scanning_changed(device);
1344 g_hash_table_foreach(device->networks,
1345 mark_network_available, NULL);
1349 * connman_device_set_scanning:
1350 * @device: device structure
1351 * @scanning: scanning state
1353 * Change scanning state of device
1355 int connman_device_set_scanning(struct connman_device *device,
1356 connman_bool_t scanning)
1358 DBG("device %p scanning %d", device, scanning);
1360 if (!device->driver || !device->driver->scan)
1363 if (device->scanning == scanning)
1366 device->scanning = scanning;
1368 scanning_changed(device);
1370 if (scanning == TRUE) {
1371 reset_scan_trigger(device);
1373 g_hash_table_foreach(device->networks,
1374 mark_network_unavailable, NULL);
1379 __connman_device_cleanup_networks(device);
1381 if (device->connections > 0)
1384 if (device->disconnected == TRUE)
1387 __connman_service_auto_connect();
1393 * connman_device_set_disconnected:
1394 * @device: device structure
1395 * @disconnected: disconnected state
1397 * Change disconnected state of device (only for device with networks)
1399 int connman_device_set_disconnected(struct connman_device *device,
1400 connman_bool_t disconnected)
1402 DBG("device %p disconnected %d", device, disconnected);
1404 switch (device->mode) {
1405 case CONNMAN_DEVICE_MODE_UNKNOWN:
1407 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1408 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1412 if (device->disconnected == disconnected)
1415 device->disconnected = disconnected;
1417 if (disconnected == TRUE)
1418 force_scan_trigger(device);
1424 * connman_device_get_disconnected:
1425 * @device: device structure
1427 * Get device disconnected state
1429 connman_bool_t connman_device_get_disconnected(struct connman_device *device)
1431 return device->disconnected;
1435 * connman_device_set_string:
1436 * @device: device structure
1437 * @key: unique identifier
1438 * @value: string value
1440 * Set string value for specific key
1442 int connman_device_set_string(struct connman_device *device,
1443 const char *key, const char *value)
1445 DBG("device %p key %s value %s", device, key, value);
1447 if (g_str_equal(key, "Address") == TRUE) {
1448 g_free(device->address);
1449 device->address = g_strdup(value);
1450 } else if (g_str_equal(key, "Name") == TRUE) {
1451 g_free(device->name);
1452 device->name = g_strdup(value);
1453 } else if (g_str_equal(key, "Node") == TRUE) {
1454 g_free(device->node);
1455 device->node = g_strdup(value);
1458 return connman_element_set_string(&device->element, key, value);
1462 * connman_device_get_string:
1463 * @device: device structure
1464 * @key: unique identifier
1466 * Get string value for specific key
1468 const char *connman_device_get_string(struct connman_device *device,
1471 DBG("device %p key %s", device, key);
1473 if (g_str_equal(key, "Address") == TRUE)
1474 return device->address;
1475 else if (g_str_equal(key, "Name") == TRUE)
1476 return device->name;
1477 else if (g_str_equal(key, "Node") == TRUE)
1478 return device->node;
1480 return connman_element_get_string(&device->element, key);
1483 static void set_offlinemode(struct connman_element *element, gpointer user_data)
1485 struct connman_device *device = element->device;
1486 connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data);
1487 connman_bool_t powered;
1489 DBG("element %p name %s", element, element->name);
1494 device->offlinemode = offlinemode;
1496 powered = (offlinemode == TRUE) ? FALSE : TRUE;
1498 if (device->powered == powered)
1501 if (device->powered_persistent == FALSE)
1504 set_powered(device, powered);
1507 int __connman_device_set_offlinemode(connman_bool_t offlinemode)
1509 DBG("offlinmode %d", offlinemode);
1511 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
1512 set_offlinemode, GUINT_TO_POINTER(offlinemode));
1514 __connman_notifier_offlinemode(offlinemode);
1519 void __connman_device_increase_connections(struct connman_device *device)
1521 device->connections++;
1524 void __connman_device_decrease_connections(struct connman_device *device)
1526 device->connections--;
1530 * connman_device_add_network:
1531 * @device: device structure
1532 * @network: network structure
1534 * Add new network to the device
1536 int connman_device_add_network(struct connman_device *device,
1537 struct connman_network *network)
1539 const char *identifier = connman_network_get_identifier(network);
1542 DBG("device %p network %p", device, network);
1544 if (identifier == NULL)
1547 switch (device->mode) {
1548 case CONNMAN_DEVICE_MODE_UNKNOWN:
1550 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1551 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1555 __connman_network_set_device(network, device);
1557 err = connman_element_register((struct connman_element *) network,
1560 __connman_network_set_device(network, NULL);
1564 g_hash_table_insert(device->networks, g_strdup(identifier),
1571 * connman_device_get_network:
1572 * @device: device structure
1573 * @identifier: network identifier
1575 * Get network for given identifier
1577 struct connman_network *connman_device_get_network(struct connman_device *device,
1578 const char *identifier)
1580 DBG("device %p identifier %s", device, identifier);
1582 return g_hash_table_lookup(device->networks, identifier);
1586 * connman_device_remove_network:
1587 * @device: device structure
1588 * @identifier: network identifier
1590 * Remove network for given identifier
1592 int connman_device_remove_network(struct connman_device *device,
1593 const char *identifier)
1595 DBG("device %p identifier %s", device, identifier);
1597 g_hash_table_remove(device->networks, identifier);
1602 void connman_device_remove_all_networks(struct connman_device *device)
1604 g_hash_table_remove_all(device->networks);
1607 void __connman_device_set_network(struct connman_device *device,
1608 struct connman_network *network)
1612 if (device->network == network)
1615 if (device->network != NULL)
1616 connman_network_unref(device->network);
1618 if (network != NULL) {
1619 name = connman_network_get_string(network,
1620 CONNMAN_PROPERTY_ID_NAME);
1621 g_free(device->last_network);
1622 device->last_network = g_strdup(name);
1624 device->network = connman_network_ref(network);
1626 g_free(device->last_network);
1627 device->last_network = NULL;
1629 device->network = NULL;
1633 void __connman_device_set_reconnect(struct connman_device *device,
1634 connman_bool_t reconnect)
1636 device->reconnect = reconnect;
1639 connman_bool_t __connman_device_get_reconnect(
1640 struct connman_device *device)
1642 return device->reconnect;
1646 * connman_device_register:
1647 * @device: device structure
1649 * Register device with the system
1651 int connman_device_register(struct connman_device *device)
1653 __connman_storage_load_device(device);
1655 device->offlinemode = __connman_profile_get_offlinemode();
1657 return connman_element_register(&device->element, NULL);
1661 * connman_device_unregister:
1662 * @device: device structure
1664 * Unregister device with the system
1666 void connman_device_unregister(struct connman_device *device)
1668 __connman_storage_save_device(device);
1670 connman_element_unregister(&device->element);
1674 * connman_device_get_data:
1675 * @device: device structure
1677 * Get private device data pointer
1679 void *connman_device_get_data(struct connman_device *device)
1681 return device->driver_data;
1685 * connman_device_set_data:
1686 * @device: device structure
1687 * @data: data pointer
1689 * Set private device data pointer
1691 void connman_device_set_data(struct connman_device *device, void *data)
1693 device->driver_data = data;
1696 static gboolean match_driver(struct connman_device *device,
1697 struct connman_device_driver *driver)
1699 if (device->type == driver->type ||
1700 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1706 static int device_probe(struct connman_element *element)
1708 struct connman_device *device = element->device;
1711 DBG("element %p name %s", element, element->name);
1716 if (device->driver != NULL)
1719 for (list = driver_list; list; list = list->next) {
1720 struct connman_device_driver *driver = list->data;
1722 if (match_driver(device, driver) == FALSE)
1725 DBG("driver %p name %s", driver, driver->name);
1727 if (driver->probe(device) == 0) {
1728 device->driver = driver;
1733 if (device->driver == NULL)
1736 return setup_device(device);
1739 static void device_remove(struct connman_element *element)
1741 struct connman_device *device = element->device;
1743 DBG("element %p name %s", element, element->name);
1748 if (device->driver == NULL)
1751 remove_device(device);
1754 static struct connman_driver device_driver = {
1756 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
1757 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
1758 .probe = device_probe,
1759 .remove = device_remove,
1762 static int device_load(struct connman_device *device)
1764 const char *ident = __connman_profile_active_ident();
1766 GError *error = NULL;
1768 connman_bool_t powered;
1771 DBG("device %p", device);
1773 keyfile = __connman_storage_open(ident);
1774 if (keyfile == NULL)
1777 identifier = g_strdup_printf("device_%s", device->element.name);
1778 if (identifier == NULL)
1781 powered = g_key_file_get_boolean(keyfile, identifier,
1784 device->powered_persistent = powered;
1785 g_clear_error(&error);
1787 switch (device->mode) {
1788 case CONNMAN_DEVICE_MODE_UNKNOWN:
1790 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1791 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1792 val = g_key_file_get_integer(keyfile, identifier,
1793 "ScanInterval", &error);
1794 if (error == NULL && val > 0)
1795 device->scan_interval = val;
1796 g_clear_error(&error);
1803 __connman_storage_close(ident, keyfile, FALSE);
1808 static int device_save(struct connman_device *device)
1810 const char *ident = __connman_profile_active_ident();
1814 DBG("device %p", device);
1816 keyfile = __connman_storage_open(ident);
1817 if (keyfile == NULL)
1820 identifier = g_strdup_printf("device_%s", device->element.name);
1821 if (identifier == NULL)
1824 g_key_file_set_boolean(keyfile, identifier,
1825 "Powered", device->powered_persistent);
1827 switch (device->mode) {
1828 case CONNMAN_DEVICE_MODE_UNKNOWN:
1830 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1831 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1832 if (device->scan_interval > 0)
1833 g_key_file_set_integer(keyfile, identifier,
1834 "ScanInterval", device->scan_interval);
1841 __connman_storage_close(ident, keyfile, TRUE);
1846 static struct connman_storage device_storage = {
1848 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
1849 .device_load = device_load,
1850 .device_save = device_save,
1853 int __connman_device_init(void)
1857 connection = connman_dbus_get_connection();
1859 if (connman_storage_register(&device_storage) < 0)
1860 connman_error("Failed to register device storage");
1862 return connman_driver_register(&device_driver);
1865 void __connman_device_cleanup(void)
1869 connman_driver_unregister(&device_driver);
1871 connman_storage_unregister(&device_storage);
1873 dbus_connection_unref(connection);