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 struct connman_device {
34 struct connman_element element;
35 enum connman_device_type type;
36 enum connman_device_mode mode;
37 enum connman_device_policy policy;
38 connman_bool_t powered;
39 connman_bool_t carrier;
40 connman_bool_t scanning;
41 connman_bool_t disconnected;
42 connman_uint8_t priority;
43 connman_uint16_t scan_interval;
47 unsigned int connections;
50 struct connman_device_driver *driver;
53 connman_bool_t registered;
56 struct connman_network *network;
60 static gboolean device_scan_trigger(gpointer user_data)
62 struct connman_device *device = user_data;
64 DBG("device %p", device);
66 if (device->driver == NULL) {
67 device->scan_timeout = 0;
71 if (device->driver->scan)
72 device->driver->scan(device);
77 static const char *type2description(enum connman_device_type type)
80 case CONNMAN_DEVICE_TYPE_UNKNOWN:
81 case CONNMAN_DEVICE_TYPE_VENDOR:
83 case CONNMAN_DEVICE_TYPE_ETHERNET:
85 case CONNMAN_DEVICE_TYPE_WIFI:
87 case CONNMAN_DEVICE_TYPE_WIMAX:
89 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
91 case CONNMAN_DEVICE_TYPE_GPS:
93 case CONNMAN_DEVICE_TYPE_HSO:
94 case CONNMAN_DEVICE_TYPE_NOZOMI:
95 case CONNMAN_DEVICE_TYPE_HUAWEI:
96 case CONNMAN_DEVICE_TYPE_NOVATEL:
103 static const char *type2string(enum connman_device_type type)
106 case CONNMAN_DEVICE_TYPE_UNKNOWN:
107 case CONNMAN_DEVICE_TYPE_VENDOR:
109 case CONNMAN_DEVICE_TYPE_ETHERNET:
111 case CONNMAN_DEVICE_TYPE_WIFI:
113 case CONNMAN_DEVICE_TYPE_WIMAX:
115 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
117 case CONNMAN_DEVICE_TYPE_GPS:
119 case CONNMAN_DEVICE_TYPE_HSO:
120 case CONNMAN_DEVICE_TYPE_HUAWEI:
121 case CONNMAN_DEVICE_TYPE_NOZOMI:
122 case CONNMAN_DEVICE_TYPE_NOVATEL:
129 static const char *policy2string(enum connman_device_policy policy)
132 case CONNMAN_DEVICE_POLICY_UNKNOWN:
134 case CONNMAN_DEVICE_POLICY_IGNORE:
136 case CONNMAN_DEVICE_POLICY_OFF:
138 case CONNMAN_DEVICE_POLICY_AUTO:
140 case CONNMAN_DEVICE_POLICY_MANUAL:
147 static enum connman_device_policy string2policy(const char *policy)
149 if (g_str_equal(policy, "ignore") == TRUE)
150 return CONNMAN_DEVICE_POLICY_IGNORE;
151 else if (g_str_equal(policy, "off") == TRUE)
152 return CONNMAN_DEVICE_POLICY_OFF;
153 else if (g_str_equal(policy, "auto") == TRUE)
154 return CONNMAN_DEVICE_POLICY_AUTO;
155 else if (g_str_equal(policy, "manual") == TRUE)
156 return CONNMAN_DEVICE_POLICY_MANUAL;
158 return CONNMAN_DEVICE_POLICY_UNKNOWN;
161 static int set_powered(struct connman_device *device, connman_bool_t powered)
163 struct connman_device_driver *driver = device->driver;
166 DBG("device %p powered %d", device, powered);
171 if (powered == TRUE) {
173 err = driver->enable(device);
177 g_hash_table_remove_all(device->networks);
180 err = driver->disable(device);
188 static int set_policy(DBusConnection *connection,
189 struct connman_device *device,
190 enum connman_device_policy policy)
193 DBusMessageIter entry, value;
194 const char *str, *key = "Policy";
197 DBG("device %p policy %d", device, policy);
199 if (device->policy == policy)
203 case CONNMAN_DEVICE_POLICY_UNKNOWN:
205 case CONNMAN_DEVICE_POLICY_IGNORE:
207 case CONNMAN_DEVICE_POLICY_OFF:
208 if (device->powered == TRUE)
209 err = set_powered(device, FALSE);
211 case CONNMAN_DEVICE_POLICY_AUTO:
212 case CONNMAN_DEVICE_POLICY_MANUAL:
213 if (device->powered == FALSE)
214 err = set_powered(device, TRUE);
221 device->policy = policy;
223 signal = dbus_message_new_signal(device->element.path,
224 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
228 dbus_message_iter_init_append(signal, &entry);
230 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
232 str = policy2string(policy);
234 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
235 DBUS_TYPE_STRING_AS_STRING, &value);
236 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
237 dbus_message_iter_close_container(&entry, &value);
239 g_dbus_send_message(connection, signal);
244 static void append_path(gpointer key, gpointer value, gpointer user_data)
246 struct connman_element *element = value;
247 DBusMessageIter *iter = user_data;
249 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
253 static void append_networks(struct connman_device *device,
254 DBusMessageIter *entry)
256 DBusMessageIter value, iter;
257 const char *key = "Networks";
259 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
261 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
262 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
265 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
266 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
267 g_hash_table_foreach(device->networks, append_path, &iter);
268 dbus_message_iter_close_container(&value, &iter);
270 dbus_message_iter_close_container(entry, &value);
273 static DBusMessage *get_properties(DBusConnection *conn,
274 DBusMessage *msg, void *data)
276 struct connman_device *device = data;
278 DBusMessageIter array, dict, entry;
281 DBG("conn %p", conn);
283 if (__connman_security_check_privilege(msg,
284 CONNMAN_SECURITY_PRIVILEGE_PUBLIC) < 0)
285 return __connman_error_permission_denied(msg);
287 reply = dbus_message_new_method_return(msg);
291 dbus_message_iter_init_append(reply, &array);
293 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
294 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
295 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
296 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
298 str = type2description(device->type);
299 if (str != NULL && device->interface != NULL) {
300 char *name = g_strdup_printf("%s (%s)", str, device->interface);
302 connman_dbus_dict_append_variant(&dict, "Name",
303 DBUS_TYPE_STRING, &name);
307 str = type2string(device->type);
309 connman_dbus_dict_append_variant(&dict, "Type",
310 DBUS_TYPE_STRING, &str);
312 if (device->interface != NULL)
313 connman_dbus_dict_append_variant(&dict, "Interface",
314 DBUS_TYPE_STRING, &device->interface);
316 str = policy2string(device->policy);
318 connman_dbus_dict_append_variant(&dict, "Policy",
319 DBUS_TYPE_STRING, &str);
321 if (device->priority > 0)
322 connman_dbus_dict_append_variant(&dict, "Priority",
323 DBUS_TYPE_BYTE, &device->priority);
325 connman_dbus_dict_append_variant(&dict, "Powered",
326 DBUS_TYPE_BOOLEAN, &device->powered);
328 if (device->driver && device->driver->scan)
329 connman_dbus_dict_append_variant(&dict, "Scanning",
330 DBUS_TYPE_BOOLEAN, &device->scanning);
332 switch (device->mode) {
333 case CONNMAN_DEVICE_MODE_UNKNOWN:
335 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
336 __connman_element_append_ipv4(&device->element, &dict);
338 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
339 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
340 if (device->scan_interval > 0)
341 connman_dbus_dict_append_variant(&dict, "ScanInterval",
342 DBUS_TYPE_UINT16, &device->scan_interval);
344 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
346 append_networks(device, &entry);
347 dbus_message_iter_close_container(&dict, &entry);
351 dbus_message_iter_close_container(&array, &dict);
356 static DBusMessage *set_property(DBusConnection *conn,
357 DBusMessage *msg, void *data)
359 struct connman_device *device = data;
360 DBusMessageIter iter, value;
364 DBG("conn %p", conn);
366 if (dbus_message_iter_init(msg, &iter) == FALSE)
367 return __connman_error_invalid_arguments(msg);
369 dbus_message_iter_get_basic(&iter, &name);
370 dbus_message_iter_next(&iter);
371 dbus_message_iter_recurse(&iter, &value);
373 if (__connman_security_check_privilege(msg,
374 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
375 return __connman_error_permission_denied(msg);
377 type = dbus_message_iter_get_arg_type(&value);
379 if (g_str_equal(name, "Powered") == TRUE) {
380 connman_bool_t powered;
383 if (type != DBUS_TYPE_BOOLEAN)
384 return __connman_error_invalid_arguments(msg);
386 dbus_message_iter_get_basic(&value, &powered);
388 if (device->powered == powered)
389 return __connman_error_invalid_arguments(msg);
391 err = set_powered(device, powered);
392 if (err < 0 && err != -EINPROGRESS)
393 return __connman_error_failed(msg);
394 } else if (g_str_equal(name, "Policy") == TRUE) {
395 enum connman_device_policy policy;
399 if (type != DBUS_TYPE_STRING)
400 return __connman_error_invalid_arguments(msg);
402 dbus_message_iter_get_basic(&value, &str);
403 policy = string2policy(str);
404 if (policy == CONNMAN_DEVICE_POLICY_UNKNOWN)
405 return __connman_error_invalid_arguments(msg);
407 err = set_policy(conn, device, policy);
409 return __connman_error_failed(msg);
410 } else if (g_str_equal(name, "Priority") == TRUE) {
411 connman_uint8_t priority;
413 if (type != DBUS_TYPE_BYTE)
414 return __connman_error_invalid_arguments(msg);
416 dbus_message_iter_get_basic(&value, &priority);
418 device->priority = priority;
419 } else if (g_str_equal(name, "ScanInterval") == TRUE) {
420 connman_uint16_t interval;
422 switch (device->mode) {
423 case CONNMAN_DEVICE_MODE_UNKNOWN:
424 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
425 return __connman_error_invalid_arguments(msg);
426 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
427 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
431 if (type != DBUS_TYPE_UINT16)
432 return __connman_error_invalid_arguments(msg);
434 dbus_message_iter_get_basic(&value, &interval);
436 device->scan_interval = interval;
438 if (device->scan_timeout > 0) {
439 g_source_remove(device->scan_timeout);
440 device->scan_timeout = 0;
443 if (device->scan_interval > 0) {
444 guint interval = device->scan_interval;
445 device->scan_timeout = g_timeout_add_seconds(interval,
446 device_scan_trigger, device);
448 } else if (g_str_has_prefix(name, "IPv4") == TRUE) {
449 switch (device->mode) {
450 case CONNMAN_DEVICE_MODE_UNKNOWN:
451 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
452 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
453 return __connman_error_invalid_arguments(msg);
454 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
455 __connman_element_set_ipv4(&device->element,
461 __connman_storage_save_device(device);
463 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
466 static DBusMessage *create_network(DBusConnection *conn,
467 DBusMessage *msg, void *data)
469 DBG("conn %p", conn);
471 if (__connman_security_check_privilege(msg,
472 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
473 return __connman_error_permission_denied(msg);
475 return __connman_error_invalid_arguments(msg);
478 static DBusMessage *remove_network(DBusConnection *conn,
479 DBusMessage *msg, void *data)
481 DBG("conn %p", conn);
483 if (__connman_security_check_privilege(msg,
484 CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
485 return __connman_error_permission_denied(msg);
487 return __connman_error_invalid_arguments(msg);
490 static DBusMessage *propose_scan(DBusConnection *conn,
491 DBusMessage *msg, void *data)
493 struct connman_device *device = data;
496 DBG("conn %p", conn);
498 switch (device->mode) {
499 case CONNMAN_DEVICE_MODE_UNKNOWN:
500 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
501 return __connman_error_not_supported(msg);
502 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
503 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
507 if (!device->driver || !device->driver->scan)
508 return __connman_error_not_supported(msg);
510 if (device->powered == FALSE)
511 return __connman_error_failed(msg);
513 err = device->driver->scan(device);
515 return __connman_error_failed(msg);
517 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
520 static GDBusMethodTable device_methods[] = {
521 { "GetProperties", "", "a{sv}", get_properties },
522 { "SetProperty", "sv", "", set_property },
523 { "CreateNetwork", "a{sv}", "o", create_network },
524 { "RemoveNetwork", "o", "", remove_network },
525 { "ProposeScan", "", "", propose_scan },
529 static GDBusSignalTable device_signals[] = {
530 { "PropertyChanged", "sv" },
534 static DBusConnection *connection;
536 static void append_devices(DBusMessageIter *entry)
538 DBusMessageIter value, iter;
539 const char *key = "Devices";
541 dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key);
543 dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT,
544 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
547 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
548 DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter);
549 __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, &iter);
550 dbus_message_iter_close_container(&value, &iter);
552 dbus_message_iter_close_container(entry, &value);
555 static void emit_devices_signal(void)
558 DBusMessageIter entry;
560 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
561 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
565 dbus_message_iter_init_append(signal, &entry);
567 append_devices(&entry);
569 g_dbus_send_message(connection, signal);
572 static int register_interface(struct connman_element *element)
574 struct connman_device *device = element->device;
576 DBG("element %p name %s", element, element->name);
578 if (g_dbus_register_interface(connection, element->path,
579 CONNMAN_DEVICE_INTERFACE,
580 device_methods, device_signals,
581 NULL, device, NULL) == FALSE) {
582 connman_error("Failed to register %s device", element->path);
586 device->registered = TRUE;
588 emit_devices_signal();
593 static void unregister_interface(struct connman_element *element)
595 struct connman_device *device = element->device;
597 DBG("element %p name %s", element, element->name);
599 device->registered = FALSE;
601 emit_devices_signal();
603 g_dbus_unregister_interface(connection, element->path,
604 CONNMAN_DEVICE_INTERFACE);
607 static void device_enable(struct connman_device *device)
609 DBG("device %p", device);
611 if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE ||
612 device->policy == CONNMAN_DEVICE_POLICY_OFF)
615 if (device->powered == TRUE)
618 if (device->driver->enable)
619 device->driver->enable(device);
622 static void device_disable(struct connman_device *device)
624 DBG("device %p", device);
626 if (device->policy == CONNMAN_DEVICE_POLICY_IGNORE)
629 if (device->powered == FALSE)
632 g_hash_table_remove_all(device->networks);
634 if (device->driver->disable)
635 device->driver->disable(device);
638 static int setup_device(struct connman_device *device)
642 DBG("device %p", device);
644 err = register_interface(&device->element);
646 if (device->driver->remove)
647 device->driver->remove(device);
648 device->driver = NULL;
652 switch (device->mode) {
653 case CONNMAN_DEVICE_MODE_UNKNOWN:
654 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
655 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
657 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
658 __connman_profile_add_device(device);
662 device_enable(device);
667 static void probe_driver(struct connman_element *element, gpointer user_data)
669 struct connman_device_driver *driver = user_data;
671 DBG("element %p name %s", element, element->name);
673 if (element->device == NULL)
676 if (element->device->driver != NULL)
679 if (driver->type != element->device->type)
682 if (driver->probe(element->device) < 0)
685 element->device->driver = driver;
687 setup_device(element->device);
690 static void remove_device(struct connman_device *device)
692 DBG("device %p", device);
694 device_disable(device);
696 switch (device->mode) {
697 case CONNMAN_DEVICE_MODE_UNKNOWN:
698 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
699 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
701 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
702 __connman_profile_remove_device(device);
706 unregister_interface(&device->element);
708 if (device->driver->remove)
709 device->driver->remove(device);
711 device->driver = NULL;
714 static void remove_driver(struct connman_element *element, gpointer user_data)
716 struct connman_device_driver *driver = user_data;
718 DBG("element %p name %s", element, element->name);
720 if (element->device == NULL)
723 if (element->device->driver == driver)
724 remove_device(element->device);
727 connman_bool_t __connman_device_has_driver(struct connman_device *device)
729 if (device == NULL || device->driver == NULL)
732 return device->registered;
735 static GSList *driver_list = NULL;
737 static gint compare_priority(gconstpointer a, gconstpointer b)
739 const struct connman_device_driver *driver1 = a;
740 const struct connman_device_driver *driver2 = b;
742 return driver2->priority - driver1->priority;
746 * connman_device_driver_register:
747 * @driver: device driver definition
749 * Register a new device driver
751 * Returns: %0 on success
753 int connman_device_driver_register(struct connman_device_driver *driver)
755 DBG("driver %p name %s", driver, driver->name);
757 driver_list = g_slist_insert_sorted(driver_list, driver,
760 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
761 probe_driver, driver);
767 * connman_device_driver_unregister:
768 * @driver: device driver definition
770 * Remove a previously registered device driver
772 void connman_device_driver_unregister(struct connman_device_driver *driver)
774 DBG("driver %p name %s", driver, driver->name);
776 driver_list = g_slist_remove(driver_list, driver);
778 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
779 remove_driver, driver);
782 static void unregister_network(gpointer data)
784 struct connman_network *network = data;
786 DBG("network %p", network);
788 connman_element_unregister((struct connman_element *) network);
790 connman_network_unref(network);
793 static void device_destruct(struct connman_element *element)
795 struct connman_device *device = element->device;
797 DBG("element %p name %s", element, element->name);
799 g_free(device->node);
800 g_free(device->name);
801 g_free(device->interface);
803 g_free(device->last_network);
805 g_hash_table_destroy(device->networks);
806 device->networks = NULL;
810 * connman_device_create:
811 * @node: device node name (for example an address)
814 * Allocate a new device of given #type and assign the #node name to it.
816 * Returns: a newly-allocated #connman_device structure
818 struct connman_device *connman_device_create(const char *node,
819 enum connman_device_type type)
821 struct connman_device *device;
824 DBG("node %s type %d", node, type);
826 device = g_try_new0(struct connman_device, 1);
830 DBG("device %p", device);
832 __connman_element_initialize(&device->element);
834 device->element.name = g_strdup(node);
835 device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE;
837 device->element.device = device;
838 device->element.destruct = device_destruct;
840 str = type2string(type);
842 connman_element_set_static_property(&device->element,
843 "Type", DBUS_TYPE_STRING, &str);
845 device->element.ipv4.method = CONNMAN_IPV4_METHOD_DHCP;
848 device->mode = CONNMAN_DEVICE_MODE_UNKNOWN;
849 device->policy = CONNMAN_DEVICE_POLICY_AUTO;
852 case CONNMAN_DEVICE_TYPE_UNKNOWN:
853 case CONNMAN_DEVICE_TYPE_VENDOR:
854 device->priority = 0;
855 device->scan_interval = 0;
857 case CONNMAN_DEVICE_TYPE_ETHERNET:
858 case CONNMAN_DEVICE_TYPE_WIFI:
859 device->priority = 100;
860 device->scan_interval = 300;
862 case CONNMAN_DEVICE_TYPE_WIMAX:
863 device->priority = 20;
864 device->scan_interval = 0;
866 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
867 device->priority = 50;
868 device->scan_interval = 0;
870 case CONNMAN_DEVICE_TYPE_GPS:
871 device->priority = 0;
872 device->scan_interval = 0;
874 case CONNMAN_DEVICE_TYPE_HSO:
875 case CONNMAN_DEVICE_TYPE_NOZOMI:
876 case CONNMAN_DEVICE_TYPE_HUAWEI:
877 case CONNMAN_DEVICE_TYPE_NOVATEL:
878 device->priority = 60;
879 device->scan_interval = 0;
883 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
884 g_free, unregister_network);
890 * connman_device_ref:
891 * @device: device structure
893 * Increase reference counter of device
895 struct connman_device *connman_device_ref(struct connman_device *device)
897 if (connman_element_ref(&device->element) == NULL)
904 * connman_device_unref:
905 * @device: device structure
907 * Decrease reference counter of device
909 void connman_device_unref(struct connman_device *device)
911 connman_element_unref(&device->element);
915 * connman_device_get_name:
916 * @device: device structure
918 * Get unique name of device
920 const char *connman_device_get_name(struct connman_device *device)
922 return device->element.name;
926 * connman_device_get_path:
927 * @device: device structure
929 * Get path name of device
931 const char *connman_device_get_path(struct connman_device *device)
933 return device->element.path;
937 * connman_device_set_index:
938 * @device: device structure
939 * @index: index number
941 * Set index number of device
943 void connman_device_set_index(struct connman_device *device, int index)
945 device->element.index = index;
949 * connman_device_get_index:
950 * @device: device structure
952 * Get index number of device
954 int connman_device_get_index(struct connman_device *device)
956 return device->element.index;
960 * connman_device_set_interface:
961 * @device: device structure
962 * @interface: interface name
964 * Set interface name of device
966 void connman_device_set_interface(struct connman_device *device,
967 const char *interface)
969 g_free(device->element.devname);
970 device->element.devname = g_strdup(interface);
972 g_free(device->interface);
973 device->interface = g_strdup(interface);
977 * connman_device_get_interface:
978 * @device: device structure
980 * Get interface name of device
982 const char *connman_device_get_interface(struct connman_device *device)
984 return device->interface;
988 * connman_device_set_policy:
989 * @device: device structure
990 * @policy: power and connection policy
992 * Change power and connection policy of device
994 void connman_device_set_policy(struct connman_device *device,
995 enum connman_device_policy policy)
997 device->policy = policy;
1001 * connman_device_set_mode:
1002 * @device: device structure
1003 * @mode: network mode
1005 * Change network mode of device
1007 void connman_device_set_mode(struct connman_device *device,
1008 enum connman_device_mode mode)
1010 device->mode = mode;
1014 * connman_device_get_mode:
1015 * @device: device structure
1017 * Get network mode of device
1019 enum connman_device_mode connman_device_get_mode(struct connman_device *device)
1021 return device->mode;
1025 * connman_device_set_powered:
1026 * @device: device structure
1027 * @powered: powered state
1029 * Change power state of device
1031 int connman_device_set_powered(struct connman_device *device,
1032 connman_bool_t powered)
1034 DBusMessage *signal;
1035 DBusMessageIter entry, value;
1036 const char *key = "Powered";
1038 DBG("driver %p powered %d", device, powered);
1040 if (device->powered == powered)
1043 device->powered = powered;
1045 if (device->registered == FALSE)
1048 signal = dbus_message_new_signal(device->element.path,
1049 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1053 dbus_message_iter_init_append(signal, &entry);
1055 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1057 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1058 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
1059 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &powered);
1060 dbus_message_iter_close_container(&entry, &value);
1062 g_dbus_send_message(connection, signal);
1064 if (powered == FALSE)
1067 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
1070 if (device->scan_timeout > 0) {
1071 g_source_remove(device->scan_timeout);
1072 device->scan_timeout = 0;
1075 if (device->scan_interval > 0) {
1076 guint interval = device->scan_interval;
1077 device->scan_timeout = g_timeout_add_seconds(interval,
1078 device_scan_trigger, device);
1081 if (device->driver->scan)
1082 device->driver->scan(device);
1088 * connman_device_set_carrier:
1089 * @device: device structure
1090 * @carrier: carrier state
1092 * Change carrier state of device (only for device without scanning)
1094 int connman_device_set_carrier(struct connman_device *device,
1095 connman_bool_t carrier)
1097 DBG("driver %p carrier %d", device, carrier);
1099 switch (device->mode) {
1100 case CONNMAN_DEVICE_MODE_UNKNOWN:
1101 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1102 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1104 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1108 if (device->carrier == carrier)
1111 device->carrier = carrier;
1113 if (carrier == TRUE) {
1114 enum connman_element_type type = CONNMAN_ELEMENT_TYPE_UNKNOWN;
1115 struct connman_element *element;
1117 switch (device->element.ipv4.method) {
1118 case CONNMAN_IPV4_METHOD_UNKNOWN:
1119 case CONNMAN_IPV4_METHOD_OFF:
1121 case CONNMAN_IPV4_METHOD_STATIC:
1122 type = CONNMAN_ELEMENT_TYPE_IPV4;
1124 case CONNMAN_IPV4_METHOD_DHCP:
1125 type = CONNMAN_ELEMENT_TYPE_DHCP;
1129 element = connman_element_create(NULL);
1130 if (element != NULL) {
1131 element->type = type;
1132 element->index = device->element.index;
1134 if (connman_element_register(element,
1135 &device->element) < 0)
1136 connman_element_unref(element);
1139 connman_element_unregister_children(&device->element);
1144 void __connman_device_disconnect(struct connman_device *device)
1146 GHashTableIter iter;
1147 gpointer key, value;
1149 DBG("device %p", device);
1151 connman_device_set_disconnected(device, TRUE);
1153 g_hash_table_iter_init(&iter, device->networks);
1155 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1156 struct connman_network *network = value;
1158 if (connman_network_get_connected(network) == TRUE)
1159 __connman_network_disconnect(network);
1163 static void connect_known_network(struct connman_device *device)
1165 struct connman_network *network = NULL;
1166 GHashTableIter iter;
1167 gpointer key, value;
1168 unsigned int count = 0;
1170 DBG("device %p", device);
1172 g_hash_table_iter_init(&iter, device->networks);
1174 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
1175 connman_uint8_t old_priority, new_priority;
1176 connman_uint8_t old_strength, new_strength;
1181 if (connman_network_get_available(value) == FALSE)
1184 name = connman_network_get_string(value, "Name");
1185 if (name != NULL && device->last_network != NULL) {
1186 if (g_str_equal(name, device->last_network) == TRUE) {
1192 if (connman_network_get_remember(value) == FALSE)
1195 if (network == NULL) {
1200 old_priority = connman_network_get_uint8(network, "Priority");
1201 new_priority = connman_network_get_uint8(value, "Priority");
1203 if (new_priority != old_priority) {
1204 if (new_priority > old_priority)
1209 old_strength = connman_network_get_uint8(network, "Strength");
1210 new_strength = connman_network_get_uint8(value, "Strength");
1212 if (new_strength > old_strength)
1216 if (network != NULL) {
1219 err = connman_network_connect(network);
1220 if (err == 0 || err == -EINPROGRESS)
1227 if (device->driver && device->driver->scan)
1228 device->driver->scan(device);
1231 static void mark_network_unavailable(gpointer key, gpointer value,
1234 struct connman_network *network = value;
1236 if (connman_network_get_connected(network) == TRUE)
1239 connman_network_set_available(network, FALSE);
1242 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1245 struct connman_network *network = value;
1247 if (connman_network_get_connected(network) == TRUE)
1250 if (connman_network_get_remember(network) == TRUE)
1253 if (connman_network_get_available(network) == TRUE)
1260 * connman_device_set_scanning:
1261 * @device: device structure
1262 * @scanning: scanning state
1264 * Change scanning state of device
1266 int connman_device_set_scanning(struct connman_device *device,
1267 connman_bool_t scanning)
1269 DBusMessage *signal;
1270 DBusMessageIter entry, value;
1271 const char *key = "Scanning";
1273 DBG("driver %p scanning %d", device, scanning);
1275 if (!device->driver || !device->driver->scan)
1278 if (device->scanning == scanning)
1281 device->scanning = scanning;
1283 signal = dbus_message_new_signal(device->element.path,
1284 CONNMAN_DEVICE_INTERFACE, "PropertyChanged");
1288 dbus_message_iter_init_append(signal, &entry);
1290 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1292 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
1293 DBUS_TYPE_BOOLEAN_AS_STRING, &value);
1294 dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &scanning);
1295 dbus_message_iter_close_container(&entry, &value);
1297 g_dbus_send_message(connection, signal);
1299 if (scanning == TRUE) {
1300 if (device->scan_timeout > 0) {
1301 g_source_remove(device->scan_timeout);
1302 device->scan_timeout = 0;
1305 if (device->scan_interval > 0) {
1306 guint interval = device->scan_interval;
1307 device->scan_timeout = g_timeout_add_seconds(interval,
1308 device_scan_trigger, device);
1311 g_hash_table_foreach(device->networks,
1312 mark_network_unavailable, NULL);
1316 g_hash_table_foreach_remove(device->networks,
1317 remove_unavailable_network, NULL);
1319 if (device->connections > 0)
1322 if (device->disconnected == TRUE)
1325 if (device->policy != CONNMAN_DEVICE_POLICY_AUTO)
1328 connect_known_network(device);
1334 * connman_device_set_disconnected:
1335 * @device: device structure
1336 * @disconnected: disconnected state
1338 * Change disconnected state of device (only for device with networks)
1340 int connman_device_set_disconnected(struct connman_device *device,
1341 connman_bool_t disconnected)
1343 DBG("driver %p disconnected %d", device, disconnected);
1345 switch (device->mode) {
1346 case CONNMAN_DEVICE_MODE_UNKNOWN:
1347 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1349 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1350 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1354 if (device->disconnected == disconnected)
1357 device->disconnected = disconnected;
1363 * connman_device_set_string:
1364 * @device: device structure
1365 * @key: unique identifier
1366 * @value: string value
1368 * Set string value for specific key
1370 int connman_device_set_string(struct connman_device *device,
1371 const char *key, const char *value)
1373 DBG("device %p key %s value %s", device, key, value);
1375 if (g_str_equal(key, "Name") == TRUE) {
1376 g_free(device->name);
1377 device->name = g_strdup(value);
1378 } else if (g_str_equal(key, "Node") == TRUE) {
1379 g_free(device->node);
1380 device->node = g_strdup(value);
1387 * connman_device_get_string:
1388 * @device: device structure
1389 * @key: unique identifier
1391 * Get string value for specific key
1393 const char *connman_device_get_string(struct connman_device *device,
1396 DBG("device %p key %s", device, key);
1398 if (g_str_equal(key, "Name") == TRUE)
1399 return device->name;
1400 else if (g_str_equal(key, "Node") == TRUE)
1401 return device->node;
1406 static void set_offlinemode(struct connman_element *element, gpointer user_data)
1408 struct connman_device *device = element->device;
1409 connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data);
1410 connman_bool_t powered;
1412 DBG("element %p name %s", element, element->name);
1417 powered = (offlinemode == TRUE) ? FALSE : TRUE;
1419 if (device->powered == powered)
1422 set_powered(device, powered);
1425 int __connman_device_set_offlinemode(connman_bool_t offlinemode)
1427 DBG("offlinmode %d", offlinemode);
1429 __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE,
1430 set_offlinemode, GUINT_TO_POINTER(offlinemode));
1435 void __connman_device_increase_connections(struct connman_device *device)
1437 device->connections++;
1440 void __connman_device_decrease_connections(struct connman_device *device)
1442 device->connections--;
1446 * connman_device_add_network:
1447 * @device: device structure
1448 * @network: network structure
1450 * Add new network to the device
1452 int connman_device_add_network(struct connman_device *device,
1453 struct connman_network *network)
1455 const char *identifier = connman_network_get_identifier(network);
1458 DBG("device %p network %p", device, network);
1460 switch (device->mode) {
1461 case CONNMAN_DEVICE_MODE_UNKNOWN:
1462 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1464 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1465 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1469 __connman_network_set_device(network, device);
1471 __connman_storage_load_network(network);
1473 err = connman_element_register((struct connman_element *) network,
1476 __connman_network_set_device(network, NULL);
1480 g_hash_table_insert(device->networks, g_strdup(identifier),
1487 * connman_device_get_network:
1488 * @device: device structure
1489 * @identifier: network identifier
1491 * Get network for given identifier
1493 struct connman_network *connman_device_get_network(struct connman_device *device,
1494 const char *identifier)
1496 DBG("device %p identifier %s", device, identifier);
1498 return g_hash_table_lookup(device->networks, identifier);
1502 * connman_device_remove_network:
1503 * @device: device structure
1504 * @identifier: network identifier
1506 * Remove network for given identifier
1508 int connman_device_remove_network(struct connman_device *device,
1509 const char *identifier)
1511 DBG("device %p identifier %s", device, identifier);
1513 g_hash_table_remove(device->networks, identifier);
1518 void __connman_device_set_network(struct connman_device *device,
1519 struct connman_network *network)
1523 if (network != NULL) {
1524 name = connman_network_get_string(network, "Name");
1525 device->last_network = g_strdup(name);
1528 device->network = network;
1532 * connman_device_register:
1533 * @device: device structure
1535 * Register device with the system
1537 int connman_device_register(struct connman_device *device)
1539 __connman_storage_load_device(device);
1541 switch (device->mode) {
1542 case CONNMAN_DEVICE_MODE_UNKNOWN:
1543 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1545 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1546 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1547 __connman_storage_init_network(device);
1551 return connman_element_register(&device->element, NULL);
1555 * connman_device_unregister:
1556 * @device: device structure
1558 * Unregister device with the system
1560 void connman_device_unregister(struct connman_device *device)
1562 __connman_storage_save_device(device);
1564 connman_element_unregister(&device->element);
1568 * connman_device_get_data:
1569 * @device: device structure
1571 * Get private device data pointer
1573 void *connman_device_get_data(struct connman_device *device)
1575 return device->driver_data;
1579 * connman_device_set_data:
1580 * @device: device structure
1581 * @data: data pointer
1583 * Set private device data pointer
1585 void connman_device_set_data(struct connman_device *device, void *data)
1587 device->driver_data = data;
1590 static gboolean match_driver(struct connman_device *device,
1591 struct connman_device_driver *driver)
1593 if (device->type == driver->type ||
1594 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1600 static int device_probe(struct connman_element *element)
1602 struct connman_device *device = element->device;
1605 DBG("element %p name %s", element, element->name);
1610 if (device->driver != NULL)
1613 for (list = driver_list; list; list = list->next) {
1614 struct connman_device_driver *driver = list->data;
1616 if (match_driver(device, driver) == FALSE)
1619 DBG("driver %p name %s", driver, driver->name);
1621 if (driver->probe(device) == 0) {
1622 device->driver = driver;
1627 if (device->driver == NULL)
1630 return setup_device(device);
1633 static void device_remove(struct connman_element *element)
1635 struct connman_device *device = element->device;
1637 DBG("element %p name %s", element, element->name);
1642 if (device->driver == NULL)
1645 remove_device(device);
1648 static struct connman_driver device_driver = {
1650 .type = CONNMAN_ELEMENT_TYPE_DEVICE,
1651 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
1652 .probe = device_probe,
1653 .remove = device_remove,
1656 static int device_load(struct connman_device *device)
1659 gchar *pathname, *data = NULL;
1664 DBG("device %p", device);
1666 pathname = g_strdup_printf("%s/%s.conf", STORAGEDIR,
1667 device->element.name);
1668 if (pathname == NULL)
1671 keyfile = g_key_file_new();
1673 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE) {
1680 if (g_key_file_load_from_data(keyfile, data, length,
1681 0, NULL) == FALSE) {
1688 str = g_key_file_get_string(keyfile, "Configuration", "Policy", NULL);
1690 device->policy = string2policy(str);
1694 val = g_key_file_get_integer(keyfile, "Configuration",
1697 device->priority = val;
1699 switch (device->mode) {
1700 case CONNMAN_DEVICE_MODE_UNKNOWN:
1701 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1703 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1704 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1705 val = g_key_file_get_integer(keyfile, "Configuration",
1706 "ScanInterval", NULL);
1708 device->scan_interval = val;
1712 str = g_key_file_get_string(keyfile, "Configuration",
1713 "LastNetwork", NULL);
1715 device->last_network = str;
1717 g_key_file_free(keyfile);
1722 static int device_save(struct connman_device *device)
1725 gchar *pathname, *data = NULL;
1729 DBG("device %p", device);
1731 pathname = g_strdup_printf("%s/%s.conf", STORAGEDIR,
1732 device->element.name);
1733 if (pathname == NULL)
1736 keyfile = g_key_file_new();
1738 if (g_file_get_contents(pathname, &data, &length, NULL) == FALSE)
1742 if (g_key_file_load_from_data(keyfile, data, length,
1750 str = policy2string(device->policy);
1752 g_key_file_set_string(keyfile, "Configuration", "Policy", str);
1754 if (device->priority > 0)
1755 g_key_file_set_integer(keyfile, "Configuration",
1756 "Priority", device->priority);
1758 switch (device->mode) {
1759 case CONNMAN_DEVICE_MODE_UNKNOWN:
1760 case CONNMAN_DEVICE_MODE_TRANSPORT_IP:
1762 case CONNMAN_DEVICE_MODE_NETWORK_SINGLE:
1763 case CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE:
1764 if (device->scan_interval > 0)
1765 g_key_file_set_integer(keyfile, "Configuration",
1766 "ScanInterval", device->scan_interval);
1770 if (device->last_network != NULL)
1771 g_key_file_set_string(keyfile, "Configuration",
1772 "LastNetwork", device->last_network);
1774 data = g_key_file_to_data(keyfile, &length, NULL);
1776 g_file_set_contents(pathname, data, length, NULL);
1781 g_key_file_free(keyfile);
1785 if (device->network != NULL)
1786 __connman_storage_save_network(device->network);
1791 static struct connman_storage device_storage = {
1793 .priority = CONNMAN_STORAGE_PRIORITY_LOW,
1794 .device_load = device_load,
1795 .device_save = device_save,
1798 int __connman_device_init(void)
1802 connection = connman_dbus_get_connection();
1804 if (connman_storage_register(&device_storage) < 0)
1805 connman_error("Failed to register device storage");
1807 return connman_driver_register(&device_driver);
1810 void __connman_device_cleanup(void)
1814 connman_driver_unregister(&device_driver);
1816 connman_storage_unregister(&device_storage);
1818 dbus_connection_unref(connection);