5 * Copyright (C) 2007-2014 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
31 #include <sys/ioctl.h>
32 #include <net/ethernet.h>
37 static GSList *device_list = NULL;
38 static gchar **device_filter = NULL;
39 static gchar **nodevice_filter = NULL;
41 enum connman_pending_type {
47 struct connman_device {
49 enum connman_device_type type;
50 enum connman_pending_type powered_pending; /* Indicates a pending
55 bool scanning[MAX_CONNMAN_SERVICE_TYPES];
63 guint pending_timeout;
65 struct connman_device_driver *driver;
69 struct connman_network *network;
72 time_t last_user_selection_time;
73 char *last_user_selection_ident;
74 char *last_connected_ident;
78 static void clear_pending_trigger(struct connman_device *device)
80 if (device->pending_timeout > 0) {
81 g_source_remove(device->pending_timeout);
82 device->pending_timeout = 0;
86 static const char *type2description(enum connman_device_type type)
89 case CONNMAN_DEVICE_TYPE_UNKNOWN:
90 case CONNMAN_DEVICE_TYPE_VENDOR:
92 case CONNMAN_DEVICE_TYPE_ETHERNET:
94 case CONNMAN_DEVICE_TYPE_WIFI:
96 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
98 case CONNMAN_DEVICE_TYPE_GPS:
100 case CONNMAN_DEVICE_TYPE_CELLULAR:
102 case CONNMAN_DEVICE_TYPE_GADGET:
110 static const char *type2string(enum connman_device_type type)
113 case CONNMAN_DEVICE_TYPE_UNKNOWN:
114 case CONNMAN_DEVICE_TYPE_VENDOR:
116 case CONNMAN_DEVICE_TYPE_ETHERNET:
118 case CONNMAN_DEVICE_TYPE_WIFI:
120 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
122 case CONNMAN_DEVICE_TYPE_GPS:
124 case CONNMAN_DEVICE_TYPE_CELLULAR:
126 case CONNMAN_DEVICE_TYPE_GADGET:
134 enum connman_service_type __connman_device_get_service_type(
135 struct connman_device *device)
137 enum connman_device_type type = connman_device_get_type(device);
140 case CONNMAN_DEVICE_TYPE_UNKNOWN:
141 case CONNMAN_DEVICE_TYPE_VENDOR:
142 case CONNMAN_DEVICE_TYPE_GPS:
144 case CONNMAN_DEVICE_TYPE_ETHERNET:
145 return CONNMAN_SERVICE_TYPE_ETHERNET;
146 case CONNMAN_DEVICE_TYPE_WIFI:
147 return CONNMAN_SERVICE_TYPE_WIFI;
148 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
149 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
150 case CONNMAN_DEVICE_TYPE_CELLULAR:
151 return CONNMAN_SERVICE_TYPE_CELLULAR;
152 case CONNMAN_DEVICE_TYPE_GADGET:
153 return CONNMAN_SERVICE_TYPE_GADGET;
157 return CONNMAN_SERVICE_TYPE_UNKNOWN;
160 static bool device_has_service_type(struct connman_device *device,
161 enum connman_service_type service_type)
163 enum connman_service_type device_service_type =
164 __connman_device_get_service_type(device);
167 * For devices whose device_service_type is unknown we should
168 * allow to decide whether they support specific service_type
171 if (device_service_type == CONNMAN_SERVICE_TYPE_UNKNOWN)
174 #if defined TIZEN_EXT_WIFI_MESH
175 if (device_service_type == CONNMAN_SERVICE_TYPE_MESH)
176 return service_type != CONNMAN_SERVICE_TYPE_MESH;
179 if (device_service_type == CONNMAN_SERVICE_TYPE_WIFI) {
180 return service_type == CONNMAN_SERVICE_TYPE_WIFI ||
181 service_type == CONNMAN_SERVICE_TYPE_P2P;
184 return service_type == device_service_type;
187 static gboolean device_pending_reset(gpointer user_data)
189 struct connman_device *device = user_data;
191 DBG("device %p", device);
193 /* Power request timedout, reset power pending state. */
194 device->pending_timeout = 0;
195 device->powered_pending = PENDING_NONE;
200 int __connman_device_enable(struct connman_device *device)
204 DBG("device %p", device);
206 if (!device->driver || !device->driver->enable)
209 /* There is an ongoing power disable request. */
210 if (device->powered_pending == PENDING_DISABLE)
213 if (device->powered_pending == PENDING_ENABLE)
216 if (device->powered_pending == PENDING_NONE && device->powered)
219 if (device->index > 0) {
220 err = connman_inet_ifup(device->index);
221 if (err < 0 && err != -EALREADY)
225 device->powered_pending = PENDING_ENABLE;
227 err = device->driver->enable(device);
229 * device gets enabled right away.
230 * Invoke the callback
233 connman_device_set_powered(device, true);
237 if (err == -EALREADY) {
238 /* If device is already powered, but connman is not updated */
239 connman_device_set_powered(device, true);
243 * if err == -EINPROGRESS, then the DBus call to the respective daemon
244 * was successful. We set a 4 sec timeout so if the daemon never
245 * returns a reply, we would reset the pending request.
247 if (err == -EINPROGRESS)
248 device->pending_timeout = g_timeout_add_seconds(4,
249 device_pending_reset, device);
254 int __connman_device_disable(struct connman_device *device)
258 DBG("device %p", device);
260 /* Ongoing power enable request */
261 if (device->powered_pending == PENDING_ENABLE)
264 if (device->powered_pending == PENDING_DISABLE)
267 if (device->powered_pending == PENDING_NONE && !device->powered)
270 device->powered_pending = PENDING_DISABLE;
272 if (device->network) {
273 struct connman_service *service =
274 connman_service_lookup_from_network(device->network);
277 __connman_service_disconnect(service);
279 connman_network_set_connected(device->network, false);
282 if (!device->driver || !device->driver->disable)
285 err = device->driver->disable(device);
286 if (err == 0 || err == -EALREADY) {
287 connman_device_set_powered(device, false);
291 if (err == -EINPROGRESS)
292 device->pending_timeout = g_timeout_add_seconds(4,
293 device_pending_reset, device);
298 static void probe_driver(struct connman_device_driver *driver)
302 DBG("driver %p name %s", driver, driver->name);
304 for (list = device_list; list; list = list->next) {
305 struct connman_device *device = list->data;
310 if (driver->type != device->type)
313 if (driver->probe(device) < 0)
316 device->driver = driver;
318 __connman_technology_add_device(device);
322 static void remove_device(struct connman_device *device)
324 DBG("device %p", device);
326 __connman_device_disable(device);
328 __connman_technology_remove_device(device);
330 if (device->driver->remove)
331 device->driver->remove(device);
333 device->driver = NULL;
336 static void remove_driver(struct connman_device_driver *driver)
340 DBG("driver %p name %s", driver, driver->name);
342 for (list = device_list; list; list = list->next) {
343 struct connman_device *device = list->data;
345 if (device->driver == driver)
346 remove_device(device);
350 bool __connman_device_has_driver(struct connman_device *device)
352 if (!device || !device->driver)
358 static GSList *driver_list = NULL;
360 static gint compare_priority(gconstpointer a, gconstpointer b)
362 const struct connman_device_driver *driver1 = a;
363 const struct connman_device_driver *driver2 = b;
365 return driver2->priority - driver1->priority;
369 * connman_device_driver_register:
370 * @driver: device driver definition
372 * Register a new device driver
374 * Returns: %0 on success
376 int connman_device_driver_register(struct connman_device_driver *driver)
378 DBG("driver %p name %s", driver, driver->name);
380 driver_list = g_slist_insert_sorted(driver_list, driver,
382 probe_driver(driver);
388 * connman_device_driver_unregister:
389 * @driver: device driver definition
391 * Remove a previously registered device driver
393 void connman_device_driver_unregister(struct connman_device_driver *driver)
395 DBG("driver %p name %s", driver, driver->name);
397 driver_list = g_slist_remove(driver_list, driver);
399 remove_driver(driver);
402 static void free_network(gpointer data)
404 struct connman_network *network = data;
406 DBG("network %p", network);
408 __connman_network_set_device(network, NULL);
410 connman_network_unref(network);
413 static void device_destruct(struct connman_device *device)
415 DBG("device %p name %s", device, device->name);
417 clear_pending_trigger(device);
419 g_hash_table_destroy(device->networks);
420 device->networks = NULL;
422 g_free(device->ident);
423 g_free(device->node);
424 g_free(device->name);
425 g_free(device->address);
426 g_free(device->interface);
427 g_free(device->path);
429 g_free(device->last_network);
431 #if defined TIZEN_EXT
432 g_free(device->last_user_selection_ident);
433 g_free(device->last_connected_ident);
440 * connman_device_create:
441 * @node: device node name (for example an address)
444 * Allocate a new device of given #type and assign the #node name to it.
446 * Returns: a newly-allocated #connman_device structure
448 struct connman_device *connman_device_create(const char *node,
449 enum connman_device_type type)
451 struct connman_device *device;
453 DBG("node %s type %d", node, type);
455 device = g_try_new0(struct connman_device, 1);
459 DBG("device %p", device);
461 device->refcount = 1;
464 device->name = g_strdup(type2description(device->type));
466 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
467 g_free, free_network);
469 device_list = g_slist_prepend(device_list, device);
475 * connman_device_ref:
476 * @device: device structure
478 * Increase reference counter of device
480 struct connman_device *connman_device_ref_debug(struct connman_device *device,
481 const char *file, int line, const char *caller)
483 DBG("%p ref %d by %s:%d:%s()", device, device->refcount + 1,
486 __sync_fetch_and_add(&device->refcount, 1);
492 * connman_device_unref:
493 * @device: device structure
495 * Decrease reference counter of device
497 void connman_device_unref_debug(struct connman_device *device,
498 const char *file, int line, const char *caller)
500 DBG("%p ref %d by %s:%d:%s()", device, device->refcount - 1,
503 if (__sync_fetch_and_sub(&device->refcount, 1) != 1)
506 if (device->driver) {
507 device->driver->remove(device);
508 device->driver = NULL;
511 device_list = g_slist_remove(device_list, device);
513 device_destruct(device);
516 const char *__connman_device_get_type(struct connman_device *device)
518 return type2string(device->type);
522 * connman_device_get_type:
523 * @device: device structure
527 enum connman_device_type connman_device_get_type(struct connman_device *device)
533 * connman_device_set_index:
534 * @device: device structure
535 * @index: index number
537 * Set index number of device
539 void connman_device_set_index(struct connman_device *device, int index)
541 device->index = index;
545 * connman_device_get_index:
546 * @device: device structure
548 * Get index number of device
550 int connman_device_get_index(struct connman_device *device)
552 return device->index;
556 * connman_device_set_interface:
557 * @device: device structure
558 * @interface: interface name
560 * Set interface name of device
562 void connman_device_set_interface(struct connman_device *device,
563 const char *interface)
565 g_free(device->interface);
566 device->interface = g_strdup(interface);
569 const char *str = type2description(device->type);
570 if (str && device->interface)
571 device->name = g_strdup_printf("%s (%s)", str,
577 * connman_device_set_ident:
578 * @device: device structure
579 * @ident: unique identifier
581 * Set unique identifier of device
583 void connman_device_set_ident(struct connman_device *device,
586 g_free(device->ident);
587 device->ident = g_strdup(ident);
590 const char *connman_device_get_ident(struct connman_device *device)
592 return device->ident;
596 * connman_device_set_powered:
597 * @device: device structure
598 * @powered: powered state
600 * Change power state of device
602 int connman_device_set_powered(struct connman_device *device,
605 struct connman_device_scan_params params;
606 enum connman_service_type type;
609 DBG("device %p powered %d", device, powered);
611 if (device->powered == powered)
614 clear_pending_trigger(device);
616 device->powered_pending = PENDING_NONE;
618 device->powered = powered;
620 type = __connman_device_get_service_type(device);
622 if (!device->powered) {
623 __connman_technology_disabled(type);
627 __connman_technology_enabled(type);
629 for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++)
630 device->scanning[i] = false;
632 if (device->driver && device->driver->scan) {
633 memset(¶ms, 0, sizeof(params));
634 params.type = CONNMAN_SERVICE_TYPE_UNKNOWN;
636 device->driver->scan(device, ¶ms);
642 bool connman_device_get_powered(struct connman_device *device)
644 return device->powered;
647 static int device_scan(enum connman_service_type type,
648 struct connman_device *device,
649 bool force_full_scan)
651 struct connman_device_scan_params params;
653 if (!device->driver || !device->driver->scan)
656 if (!device->powered)
659 memset(¶ms, 0, sizeof(params));
661 params.force_full_scan = force_full_scan;
663 return device->driver->scan(device, ¶ms);
666 int __connman_device_disconnect(struct connman_device *device)
671 DBG("device %p", device);
673 g_hash_table_iter_init(&iter, device->networks);
675 while (g_hash_table_iter_next(&iter, &key, &value)) {
676 struct connman_network *network = value;
678 if (connman_network_get_connecting(network)) {
680 * Skip network in the process of connecting.
681 * This is a workaround for WiFi networks serviced
682 * by the supplicant plugin that hold a reference
683 * to the network. If we disconnect the network
684 * here then the referenced object will not be
685 * registered and usage (like launching DHCP client)
686 * will fail. There is nothing to be gained by
687 * removing the network here anyway.
689 connman_warn("Skipping disconnect of %s, network is connecting.",
690 connman_network_get_identifier(network));
694 __connman_network_disconnect(network);
700 int connman_device_reconnect_service(struct connman_device *device)
702 DBG("device %p", device);
704 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
709 #if defined TIZEN_EXT
710 bool connman_device_set_last_user_selection_time(struct connman_device *device,
713 if (device->last_user_selection_time != time) {
714 device->last_user_selection_time = time;
721 time_t connman_device_get_last_user_selection_time(struct connman_device *device)
723 return device->last_user_selection_time;
726 bool connman_device_set_last_user_selection_ident(struct connman_device *device,
729 if (g_strcmp0(device->last_user_selection_ident, ident) != 0) {
730 g_free(device->last_user_selection_ident);
731 device->last_user_selection_ident = g_strdup(ident);
739 const char *connman_device_get_last_user_selection_ident(struct connman_device *device)
741 return device->last_user_selection_ident;
744 bool connman_device_set_last_connected_ident(struct connman_device *device,
747 if (g_strcmp0(device->last_connected_ident, ident) != 0) {
748 g_free(device->last_connected_ident);
749 device->last_connected_ident = g_strdup(ident);
757 const char *connman_device_get_last_connected_ident(struct connman_device *device)
759 return device->last_connected_ident;
762 void connman_device_save_last_user_selection(struct connman_device *device)
766 gchar *selection_str;
768 keyfile = __connman_storage_load_ins();
770 selection_str = g_strdup_printf("%s:%ld",
771 device->last_user_selection_ident, device->last_user_selection_time);
774 keyfile = g_key_file_new();
776 g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
777 DBG("%s", selection_str);
778 __connman_storage_save_ins(keyfile);
781 get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
782 if (!get_str || g_strcmp0(get_str, selection_str) != 0) {
783 g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
784 DBG("%s -> %s", get_str, selection_str);
785 __connman_storage_save_ins(keyfile);
791 g_free(selection_str);
792 g_key_file_free(keyfile);
795 void connman_device_load_last_user_selection(struct connman_device *device)
799 char **selection_str;
801 keyfile = __connman_storage_load_ins();
805 get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
807 selection_str = g_strsplit(get_str, ":", 0);
811 time_t last_user_selection_time;
813 /* Only events that occur within 8 hours are counted. */
814 ref_time = time(NULL);
815 timeinfo = localtime(&ref_time);
816 timeinfo->tm_hour -= 8;
817 ref_time = mktime(timeinfo);
819 last_user_selection_time = strtol(selection_str[1], NULL, 10);
821 if (last_user_selection_time > ref_time) {
822 if (g_strcmp0(selection_str[0], device->last_user_selection_ident) != 0) {
823 g_free(device->last_user_selection_ident);
824 device->last_user_selection_ident = g_strdup(selection_str[0]);
827 device->last_user_selection_time = last_user_selection_time;
829 DBG("%s %ld", device->last_user_selection_ident, device->last_user_selection_time);
832 g_strfreev(selection_str);
838 g_key_file_free(keyfile);
841 void connman_device_save_last_connected(struct connman_device *device)
846 if (!device->last_connected_ident)
849 keyfile = __connman_storage_load_ins();
852 keyfile = g_key_file_new();
854 g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
855 DBG("%s", device->last_connected_ident);
856 __connman_storage_save_ins(keyfile);
859 get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
860 if (!get_str || g_strcmp0(get_str, device->last_connected_ident) != 0) {
861 g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
862 DBG("%s -> %s", get_str, device->last_connected_ident);
863 __connman_storage_save_ins(keyfile);
869 g_key_file_free(keyfile);
872 void connman_device_load_last_connected(struct connman_device *device)
877 keyfile = __connman_storage_load_ins();
881 get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
883 if (g_strcmp0(get_str, device->last_connected_ident) != 0) {
884 g_free(device->last_connected_ident);
885 device->last_connected_ident = g_strdup(get_str);
888 DBG("%s", device->last_connected_ident);
893 g_key_file_free(keyfile);
897 static void mark_network_available(gpointer key, gpointer value,
900 struct connman_network *network = value;
902 connman_network_set_available(network, true);
905 static void mark_network_unavailable(gpointer key, gpointer value,
908 struct connman_network *network = value;
910 if (connman_network_get_connected(network) ||
911 connman_network_get_connecting(network))
914 connman_network_set_available(network, false);
917 static gboolean remove_unavailable_network(gpointer key, gpointer value,
920 struct connman_network *network = value;
922 if (connman_network_get_connected(network) ||
923 connman_network_get_connecting(network))
926 if (connman_network_get_available(network))
932 void __connman_device_cleanup_networks(struct connman_device *device)
934 g_hash_table_foreach_remove(device->networks,
935 remove_unavailable_network, NULL);
938 bool connman_device_get_scanning(struct connman_device *device,
939 enum connman_service_type type)
943 if (type != CONNMAN_SERVICE_TYPE_UNKNOWN)
944 return device->scanning[type];
946 for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++)
947 if (device->scanning[i])
953 void connman_device_reset_scanning(struct connman_device *device)
955 g_hash_table_foreach(device->networks,
956 mark_network_available, NULL);
960 * connman_device_set_scanning:
961 * @device: device structure
962 * @scanning: scanning state
964 * Change scanning state of device
966 int connman_device_set_scanning(struct connman_device *device,
967 enum connman_service_type type, bool scanning)
969 DBG("device %p scanning %d", device, scanning);
971 if (!device->driver || !device->driver->scan)
974 if (type == CONNMAN_SERVICE_TYPE_UNKNOWN)
977 if (device->scanning[type] == scanning)
980 device->scanning[type] = scanning;
983 __connman_technology_scan_started(device);
985 g_hash_table_foreach(device->networks,
986 mark_network_unavailable, NULL);
991 __connman_device_cleanup_networks(device);
993 __connman_technology_scan_stopped(device, type);
995 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
997 #if defined TIZEN_EXT_WIFI_MESH
998 if (type == CONNMAN_SERVICE_TYPE_MESH)
999 __connman_mesh_auto_connect();
1006 * connman_device_set_string:
1007 * @device: device structure
1008 * @key: unique identifier
1009 * @value: string value
1011 * Set string value for specific key
1013 int connman_device_set_string(struct connman_device *device,
1014 const char *key, const char *value)
1016 DBG("device %p key %s value %s", device, key, value);
1018 if (g_str_equal(key, "Address")) {
1019 g_free(device->address);
1020 device->address = g_strdup(value);
1021 } else if (g_str_equal(key, "Name")) {
1022 g_free(device->name);
1023 device->name = g_strdup(value);
1024 } else if (g_str_equal(key, "Node")) {
1025 g_free(device->node);
1026 device->node = g_strdup(value);
1027 } else if (g_str_equal(key, "Path")) {
1028 g_free(device->path);
1029 device->path = g_strdup(value);
1038 * connman_device_get_string:
1039 * @device: device structure
1040 * @key: unique identifier
1042 * Get string value for specific key
1044 const char *connman_device_get_string(struct connman_device *device,
1047 DBG("device %p key %s", device, key);
1049 if (g_str_equal(key, "Address"))
1050 return device->address;
1051 else if (g_str_equal(key, "Name"))
1052 return device->name;
1053 else if (g_str_equal(key, "Node"))
1054 return device->node;
1055 else if (g_str_equal(key, "Interface"))
1056 return device->interface;
1057 else if (g_str_equal(key, "Path"))
1058 return device->path;
1064 * connman_device_add_network:
1065 * @device: device structure
1066 * @network: network structure
1068 * Add new network to the device
1070 int connman_device_add_network(struct connman_device *device,
1071 struct connman_network *network)
1073 const char *identifier = connman_network_get_identifier(network);
1075 DBG("device %p network %p", device, network);
1080 connman_network_ref(network);
1082 __connman_network_set_device(network, device);
1084 g_hash_table_replace(device->networks, g_strdup(identifier),
1091 * connman_device_get_network:
1092 * @device: device structure
1093 * @identifier: network identifier
1095 * Get network for given identifier
1097 struct connman_network *connman_device_get_network(struct connman_device *device,
1098 const char *identifier)
1100 DBG("device %p identifier %s", device, identifier);
1102 return g_hash_table_lookup(device->networks, identifier);
1106 * connman_device_remove_network:
1107 * @device: device structure
1108 * @identifier: network identifier
1110 * Remove network for given identifier
1112 int connman_device_remove_network(struct connman_device *device,
1113 struct connman_network *network)
1115 const char *identifier;
1117 DBG("device %p network %p", device, network);
1122 identifier = connman_network_get_identifier(network);
1123 g_hash_table_remove(device->networks, identifier);
1128 void __connman_device_set_network(struct connman_device *device,
1129 struct connman_network *network)
1136 if (device->network == network)
1140 name = connman_network_get_string(network, "Name");
1141 g_free(device->last_network);
1142 device->last_network = g_strdup(name);
1144 device->network = network;
1146 g_free(device->last_network);
1147 device->last_network = NULL;
1149 device->network = NULL;
1153 static bool match_driver(struct connman_device *device,
1154 struct connman_device_driver *driver)
1156 if (device->type == driver->type ||
1157 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1164 * connman_device_register:
1165 * @device: device structure
1167 * Register device with the system
1169 int connman_device_register(struct connman_device *device)
1173 DBG("device %p name %s", device, device->name);
1178 for (list = driver_list; list; list = list->next) {
1179 struct connman_device_driver *driver = list->data;
1181 if (!match_driver(device, driver))
1184 DBG("driver %p name %s", driver, driver->name);
1186 if (driver->probe(device) == 0) {
1187 device->driver = driver;
1192 if (!device->driver)
1195 return __connman_technology_add_device(device);
1199 * connman_device_unregister:
1200 * @device: device structure
1202 * Unregister device with the system
1204 void connman_device_unregister(struct connman_device *device)
1206 DBG("device %p name %s", device, device->name);
1208 if (!device->driver)
1211 remove_device(device);
1215 * connman_device_get_data:
1216 * @device: device structure
1218 * Get private device data pointer
1220 void *connman_device_get_data(struct connman_device *device)
1222 return device->driver_data;
1226 * connman_device_set_data:
1227 * @device: device structure
1228 * @data: data pointer
1230 * Set private device data pointer
1232 void connman_device_set_data(struct connman_device *device, void *data)
1234 device->driver_data = data;
1237 struct connman_device *__connman_device_find_device(
1238 enum connman_service_type type)
1242 for (list = device_list; list; list = list->next) {
1243 struct connman_device *device = list->data;
1244 enum connman_service_type service_type =
1245 __connman_device_get_service_type(device);
1247 if (service_type != type)
1256 struct connman_device *connman_device_find_by_index(int index)
1260 for (list = device_list; list; list = list->next) {
1261 struct connman_device *device = list->data;
1262 if (device->index == index)
1270 * connman_device_set_regdom
1271 * @device: device structure
1272 * @alpha2: string representing regulatory domain
1274 * Set regulatory domain on device basis
1276 int connman_device_set_regdom(struct connman_device *device,
1279 if (!device->driver || !device->driver->set_regdom)
1282 if (!device->powered)
1285 return device->driver->set_regdom(device, alpha2);
1289 * connman_device_regdom_notify
1290 * @device: device structure
1291 * @alpha2: string representing regulatory domain
1293 * Notify on setting regulatory domain on device basis
1295 void connman_device_regdom_notify(struct connman_device *device,
1296 int result, const char *alpha2)
1298 __connman_technology_notify_regdom_by_device(device, result, alpha2);
1301 #if defined TIZEN_EXT
1302 static int device_specific_scan(enum connman_service_type type,
1303 struct connman_device *device,
1304 int scan_type, GSList *specific_scan_list)
1306 if (!device->driver || !device->driver->specific_scan)
1309 if (!device->powered)
1312 return device->driver->specific_scan(type, device, scan_type,
1313 specific_scan_list, NULL);
1316 int __connman_device_request_specific_scan(enum connman_service_type type,
1317 int scan_type, GSList *specific_scan_list)
1319 bool success = false;
1320 int last_err = -ENOSYS;
1325 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1326 case CONNMAN_SERVICE_TYPE_SYSTEM:
1327 case CONNMAN_SERVICE_TYPE_ETHERNET:
1328 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1329 case CONNMAN_SERVICE_TYPE_CELLULAR:
1330 case CONNMAN_SERVICE_TYPE_GPS:
1331 case CONNMAN_SERVICE_TYPE_VPN:
1332 case CONNMAN_SERVICE_TYPE_GADGET:
1334 case CONNMAN_SERVICE_TYPE_WIFI:
1335 case CONNMAN_SERVICE_TYPE_P2P:
1336 #if defined TIZEN_EXT_WIFI_MESH
1337 case CONNMAN_SERVICE_TYPE_MESH:
1342 for (list = device_list; list; list = list->next) {
1343 struct connman_device *device = list->data;
1344 enum connman_service_type service_type =
1345 __connman_device_get_service_type(device);
1347 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1348 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1349 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1351 } else if (service_type != type)
1355 err = device_specific_scan(type, device, scan_type, specific_scan_list);
1356 if (err == 0 || err == -EINPROGRESS) {
1360 DBG("device %p err %d", device, err);
1370 #if defined TIZEN_EXT_WIFI_MESH
1371 static int device_abort_scan(enum connman_service_type type,
1372 struct connman_device *device)
1374 if (!device->driver || !device->driver->scan)
1377 if (!device->powered)
1380 return device->driver->abort_scan(type, device);
1383 int __connman_device_abort_scan(enum connman_service_type type)
1388 if (type != CONNMAN_SERVICE_TYPE_MESH)
1391 for (list = device_list; list; list = list->next) {
1392 struct connman_device *device = list->data;
1393 enum connman_service_type service_type =
1394 __connman_device_get_service_type(device);
1396 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1397 if (type == CONNMAN_SERVICE_TYPE_MESH)
1398 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1401 if (!device->scanning) {
1406 err = device_abort_scan(type, device);
1412 static int device_mesh_specific_scan(enum connman_service_type type,
1413 struct connman_device *device, const char *name,
1416 if (!device->driver || !device->driver->mesh_specific_scan)
1419 if (!device->powered)
1422 return device->driver->mesh_specific_scan(type, device, name, freq, NULL);
1425 int __connman_device_request_mesh_specific_scan(enum connman_service_type type,
1429 bool success = false;
1430 int last_err = -ENOSYS;
1434 if (type != CONNMAN_SERVICE_TYPE_MESH)
1437 for (list = device_list; list; list = list->next) {
1438 struct connman_device *device = list->data;
1439 enum connman_service_type service_type =
1440 __connman_device_get_service_type(device);
1442 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1443 if (type == CONNMAN_SERVICE_TYPE_MESH)
1444 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1448 err = device_mesh_specific_scan(type, device, name, freq);
1449 if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
1453 DBG("device %p err %d", device, err);
1462 #endif /* TIZEN_EXT_WIFI_MESH */
1465 static int connman_device_request_scan(enum connman_service_type type,
1466 bool force_full_scan)
1468 bool success = false;
1469 int last_err = -ENOSYS;
1474 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1475 case CONNMAN_SERVICE_TYPE_SYSTEM:
1476 case CONNMAN_SERVICE_TYPE_ETHERNET:
1477 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1478 case CONNMAN_SERVICE_TYPE_CELLULAR:
1479 case CONNMAN_SERVICE_TYPE_GPS:
1480 case CONNMAN_SERVICE_TYPE_VPN:
1481 case CONNMAN_SERVICE_TYPE_GADGET:
1483 case CONNMAN_SERVICE_TYPE_WIFI:
1484 case CONNMAN_SERVICE_TYPE_P2P:
1485 #if defined TIZEN_EXT_WIFI_MESH
1486 case CONNMAN_SERVICE_TYPE_MESH:
1491 for (list = device_list; list; list = list->next) {
1492 struct connman_device *device = list->data;
1494 if (!device_has_service_type(device, type))
1497 err = device_scan(type, device, force_full_scan);
1498 #if defined TIZEN_EXT
1499 /* When Scan is already in progress then return Error so that
1500 * wifi-manager can block the scan-done signal to be sent to
1501 * application and start requested scan after scan already in progress
1502 * is completed then notify to application about the scan event */
1503 if (err == 0 || err == -EINPROGRESS) {
1505 if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
1510 DBG("device %p err %d", device, err);
1520 int __connman_device_request_scan(enum connman_service_type type)
1522 return connman_device_request_scan(type, false);
1525 int __connman_device_request_scan_full(enum connman_service_type type)
1527 return connman_device_request_scan(type, true);
1530 int __connman_device_request_hidden_scan(struct connman_device *device,
1531 const char *ssid, unsigned int ssid_len,
1532 const char *identity, const char *passphrase,
1533 const char *security, void *user_data)
1535 struct connman_device_scan_params params;
1537 DBG("device %p", device);
1539 if (!device || !device->driver ||
1540 !device->driver->scan)
1543 params.type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1545 params.ssid_len = ssid_len;
1546 params.identity = identity;
1547 params.passphrase = passphrase;
1548 params.security = security;
1549 params.user_data = user_data;
1551 return device->driver->scan(device, ¶ms);
1554 void __connman_device_stop_scan(enum connman_service_type type)
1558 for (list = device_list; list; list = list->next) {
1559 struct connman_device *device = list->data;
1561 if (!device_has_service_type(device, type))
1564 if (device->driver && device->driver->stop_scan)
1565 device->driver->stop_scan(type, device);
1569 #if defined TIZEN_EXT
1570 char *index2ident(int index, const char *prefix)
1572 static char *index2ident(int index, const char *prefix)
1576 struct ether_addr eth;
1583 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1587 memset(&ifr, 0, sizeof(ifr));
1588 ifr.ifr_ifindex = index;
1590 err = ioctl(sk, SIOCGIFNAME, &ifr);
1593 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1600 len = prefix ? strlen(prefix) + 18 : 18;
1602 str = g_malloc(len);
1606 memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1607 snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
1608 prefix ? prefix : "",
1609 eth.ether_addr_octet[0],
1610 eth.ether_addr_octet[1],
1611 eth.ether_addr_octet[2],
1612 eth.ether_addr_octet[3],
1613 eth.ether_addr_octet[4],
1614 eth.ether_addr_octet[5]);
1619 #if defined TIZEN_EXT
1620 char *index2addr(int index)
1622 static char *index2addr(int index)
1626 struct ether_addr eth;
1633 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1637 memset(&ifr, 0, sizeof(ifr));
1638 ifr.ifr_ifindex = index;
1640 err = ioctl(sk, SIOCGIFNAME, &ifr);
1643 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1654 memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1655 snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
1656 eth.ether_addr_octet[0],
1657 eth.ether_addr_octet[1],
1658 eth.ether_addr_octet[2],
1659 eth.ether_addr_octet[3],
1660 eth.ether_addr_octet[4],
1661 eth.ether_addr_octet[5]);
1666 struct connman_device *connman_device_create_from_index(int index)
1668 enum connman_device_type type;
1669 struct connman_device *device;
1670 char *devname, *ident = NULL;
1671 char *addr = NULL, *name = NULL;
1676 devname = connman_inet_ifname(index);
1680 if (__connman_device_isfiltered(devname)) {
1681 connman_info("Ignoring interface %s (filtered)", devname);
1686 type = __connman_rtnl_get_device_type(index);
1689 case CONNMAN_DEVICE_TYPE_UNKNOWN:
1690 connman_info("Ignoring interface %s (type unknown)", devname);
1693 case CONNMAN_DEVICE_TYPE_ETHERNET:
1694 case CONNMAN_DEVICE_TYPE_GADGET:
1695 case CONNMAN_DEVICE_TYPE_WIFI:
1696 name = index2ident(index, "");
1697 addr = index2addr(index);
1699 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1700 case CONNMAN_DEVICE_TYPE_CELLULAR:
1701 case CONNMAN_DEVICE_TYPE_GPS:
1702 case CONNMAN_DEVICE_TYPE_VENDOR:
1703 name = g_strdup(devname);
1707 device = connman_device_create(name, type);
1712 case CONNMAN_DEVICE_TYPE_UNKNOWN:
1713 case CONNMAN_DEVICE_TYPE_VENDOR:
1714 case CONNMAN_DEVICE_TYPE_GPS:
1716 case CONNMAN_DEVICE_TYPE_ETHERNET:
1717 case CONNMAN_DEVICE_TYPE_GADGET:
1718 ident = index2ident(index, NULL);
1720 case CONNMAN_DEVICE_TYPE_WIFI:
1721 ident = index2ident(index, NULL);
1723 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1725 case CONNMAN_DEVICE_TYPE_CELLULAR:
1726 ident = index2ident(index, NULL);
1730 connman_device_set_index(device, index);
1731 connman_device_set_interface(device, devname);
1732 #if defined TIZEN_EXT
1733 connman_device_load_last_connected(device);
1734 connman_device_load_last_user_selection(device);
1738 connman_device_set_ident(device, ident);
1742 connman_device_set_string(device, "Address", addr);
1752 bool __connman_device_isfiltered(const char *devname)
1755 char **blacklisted_interfaces;
1761 for (pattern = device_filter, match = false; *pattern; pattern++) {
1762 if (g_pattern_match_simple(*pattern, devname)) {
1769 DBG("ignoring device %s (match)", devname);
1774 if (g_pattern_match_simple("dummy*", devname)) {
1775 DBG("ignoring dummy networking devices");
1779 if (!nodevice_filter)
1782 for (pattern = nodevice_filter; *pattern; pattern++) {
1783 if (g_pattern_match_simple(*pattern, devname)) {
1784 DBG("ignoring device %s (no match)", devname);
1790 if (__connman_inet_isrootnfs_device(devname)) {
1791 DBG("ignoring device %s (rootnfs)", devname);
1795 blacklisted_interfaces =
1796 connman_setting_get_string_list("NetworkInterfaceBlacklist");
1797 if (!blacklisted_interfaces)
1800 for (pattern = blacklisted_interfaces; *pattern; pattern++) {
1801 if (g_str_has_prefix(devname, *pattern)) {
1802 DBG("ignoring device %s (blacklist)", devname);
1810 static void cleanup_devices(void)
1813 * Check what interfaces are currently up and if connman is
1814 * suppose to handle the interface, then cleanup the mess
1815 * related to that interface. There might be weird routes etc
1816 * that are related to that interface and that might confuse
1817 * connmand. So in this case we just turn the interface down
1818 * so that kernel removes routes/addresses automatically and
1819 * then proceed the startup.
1821 * Note that this cleanup must be done before rtnl/detect code
1822 * has activated interface watches.
1828 interfaces = __connman_inet_get_running_interfaces();
1833 for (i = 0; interfaces[i]; i++) {
1836 struct sockaddr_in sin_addr, sin_mask;
1838 filtered = __connman_device_isfiltered(interfaces[i]);
1842 index = connman_inet_ifindex(interfaces[i]);
1846 if (!__connman_inet_get_address_netmask(index, &sin_addr,
1848 char *address = g_strdup(inet_ntoa(sin_addr.sin_addr));
1849 char *netmask = g_strdup(inet_ntoa(sin_mask.sin_addr));
1851 if (__connman_config_address_provisioned(address,
1853 DBG("Skip %s which is already provisioned "
1854 "with %s/%s", interfaces[i], address,
1865 DBG("cleaning up %s index %d", interfaces[i], index);
1867 #if defined TIZEN_EXT
1868 if (strcmp(interfaces[i], "wlan0") != 0)
1870 connman_inet_ifdown(index);
1873 * ConnMan will turn the interface UP automatically so
1874 * no need to do it here.
1878 g_strfreev(interfaces);
1881 int __connman_device_init(const char *device, const char *nodevice)
1886 device_filter = g_strsplit(device, ",", -1);
1889 nodevice_filter = g_strsplit(nodevice, ",", -1);
1896 void __connman_device_cleanup(void)
1900 g_strfreev(nodevice_filter);
1901 g_strfreev(device_filter);