5 * Copyright (C) 2007-2013 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
38 static DBusConnection *connection;
40 static GSList *technology_list = NULL;
43 * List of devices with no technology associated with them either because of
44 * no compiled in support or the driver is not yet loaded.
46 static GSList *techless_device_list = NULL;
47 static GHashTable *rfkill_list;
49 static bool global_offlinemode;
52 struct connman_scan_pending {
54 connman_scan_type_e scan_type;
58 struct connman_bssid_pending {
60 unsigned char bssid[6];
64 struct connman_rfkill {
66 enum connman_service_type type;
71 struct connman_technology {
73 enum connman_service_type type;
81 bool tethering_persistent; /* Tells the save status, needed
82 * as offline mode might set
85 char *tethering_ident;
86 char *tethering_passphrase;
88 bool enable_persistent; /* Save the tech state */
92 DBusMessage *pending_reply;
93 guint pending_timeout;
100 bool dbus_registered;
101 #if defined TIZEN_EXT
102 char **enabled_devices;
104 #if defined TIZEN_EXT_WIFI_MESH
105 DBusMessage *mesh_dbus_msg;
109 static GSList *driver_list = NULL;
111 static int technology_enabled(struct connman_technology *technology);
112 static int technology_disabled(struct connman_technology *technology);
114 static gint compare_priority(gconstpointer a, gconstpointer b)
116 const struct connman_technology_driver *driver1 = a;
117 const struct connman_technology_driver *driver2 = b;
119 return driver2->priority - driver1->priority;
122 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
124 struct connman_rfkill *rfkill = value;
125 enum connman_service_type type = GPOINTER_TO_INT(user_data);
127 /* Calling _technology_add_rfkill will update the tech. */
128 if (rfkill->type == type)
129 __connman_technology_add_rfkill(rfkill->index, type,
130 rfkill->softblock, rfkill->hardblock);
134 connman_technology_is_tethering_allowed(enum connman_service_type type)
136 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
138 const char *type_str = __connman_service_type2string(type);
145 allowed = connman_setting_get_string_list("TetheringTechnologies");
147 allowed = allowed_default;
149 for (i = 0; allowed[i]; i++) {
150 if (g_strcmp0(allowed[i], type_str) == 0)
157 static const char *get_name(enum connman_service_type type)
160 case CONNMAN_SERVICE_TYPE_UNKNOWN:
161 case CONNMAN_SERVICE_TYPE_SYSTEM:
162 case CONNMAN_SERVICE_TYPE_GPS:
163 case CONNMAN_SERVICE_TYPE_VPN:
165 case CONNMAN_SERVICE_TYPE_GADGET:
167 case CONNMAN_SERVICE_TYPE_ETHERNET:
169 case CONNMAN_SERVICE_TYPE_WIFI:
171 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
173 case CONNMAN_SERVICE_TYPE_CELLULAR:
175 case CONNMAN_SERVICE_TYPE_P2P:
177 #if defined TIZEN_EXT_WIFI_MESH
178 case CONNMAN_SERVICE_TYPE_MESH:
186 static void technology_save(struct connman_technology *technology)
190 const char *name = get_name(technology->type);
192 DBG("technology %p type %d name %s", technology, technology->type,
197 keyfile = __connman_storage_load_global();
199 keyfile = g_key_file_new();
201 identifier = g_strdup_printf("%s", name);
205 g_key_file_set_boolean(keyfile, identifier, "Enable",
206 technology->enable_persistent);
208 g_key_file_set_boolean(keyfile, identifier, "Tethering",
209 technology->tethering_persistent);
211 if (technology->tethering_ident)
212 g_key_file_set_string(keyfile, identifier,
213 "Tethering.Identifier",
214 technology->tethering_ident);
216 if (technology->tethering_passphrase)
217 g_key_file_set_string(keyfile, identifier,
218 "Tethering.Passphrase",
219 technology->tethering_passphrase);
224 __connman_storage_save_global(keyfile);
226 g_key_file_free(keyfile);
229 static void tethering_changed(struct connman_technology *technology)
231 dbus_bool_t tethering = technology->tethering;
233 connman_dbus_property_changed_basic(technology->path,
234 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
235 DBUS_TYPE_BOOLEAN, &tethering);
237 technology_save(technology);
240 int connman_technology_tethering_notify(struct connman_technology *technology,
245 DBG("technology %p enabled %u", technology, enabled);
247 if (technology->tethering == enabled)
251 err = __connman_tethering_set_enabled();
255 __connman_tethering_set_disabled();
257 technology->tethering = enabled;
258 tethering_changed(technology);
263 static int set_tethering(struct connman_technology *technology,
266 int result = -EOPNOTSUPP;
268 const char *ident, *passphrase, *bridge;
269 GSList *tech_drivers;
271 ident = technology->tethering_ident;
272 passphrase = technology->tethering_passphrase;
274 __sync_synchronize();
275 if (!technology->enabled)
278 bridge = __connman_tethering_get_bridge();
282 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
283 (!ident || !passphrase))
286 for (tech_drivers = technology->driver_list; tech_drivers;
287 tech_drivers = g_slist_next(tech_drivers)) {
288 struct connman_technology_driver *driver = tech_drivers->data;
290 if (!driver || !driver->set_tethering)
293 err = driver->set_tethering(technology, ident, passphrase,
296 if (result == -EINPROGRESS)
299 if (err == -EINPROGRESS || err == 0)
306 void connman_technology_regdom_notify(struct connman_technology *technology,
312 connman_error("Failed to set regulatory domain");
314 DBG("Regulatory domain set to %s", alpha2);
316 g_free(technology->regdom);
317 technology->regdom = g_strdup(alpha2);
320 static int set_regdom_by_device(struct connman_technology *technology,
325 for (list = technology->device_list; list; list = list->next) {
326 struct connman_device *device = list->data;
328 if (connman_device_set_regdom(device, alpha2) != 0)
335 int connman_technology_set_regdom(const char *alpha2)
337 GSList *list, *tech_drivers;
339 for (list = technology_list; list; list = list->next) {
340 struct connman_technology *technology = list->data;
342 if (set_regdom_by_device(technology, alpha2) != 0) {
344 for (tech_drivers = technology->driver_list;
346 tech_drivers = g_slist_next(tech_drivers)) {
348 struct connman_technology_driver *driver =
351 if (driver->set_regdom)
352 driver->set_regdom(technology, alpha2);
360 static struct connman_technology *technology_find(enum connman_service_type type)
364 DBG("type %d", type);
366 for (list = technology_list; list; list = list->next) {
367 struct connman_technology *technology = list->data;
369 if (technology->type == type)
376 enum connman_service_type connman_technology_get_type
377 (struct connman_technology *technology)
380 return CONNMAN_SERVICE_TYPE_UNKNOWN;
382 return technology->type;
385 bool connman_technology_get_wifi_tethering(const char **ssid,
388 struct connman_technology *technology;
395 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
399 if (!technology->tethering)
402 *ssid = technology->tethering_ident;
403 *psk = technology->tethering_passphrase;
408 #if defined TIZEN_EXT
409 const char *connman_techonology_get_path(enum connman_service_type type)
411 struct connman_technology *technology = technology_find(type);
416 return technology->path;
420 static void free_rfkill(gpointer data)
422 struct connman_rfkill *rfkill = data;
427 static void technology_load(struct connman_technology *technology)
431 GError *error = NULL;
432 bool enable, need_saving = false;
434 DBG("technology %p", technology);
436 keyfile = __connman_storage_load_global();
437 /* Fallback on disabling technology if file not found. */
439 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
440 /* We enable ethernet by default */
441 technology->enable_persistent = true;
443 technology->enable_persistent = false;
447 identifier = g_strdup_printf("%s", get_name(technology->type));
453 technology->enabled_devices = g_key_file_get_string_list(keyfile,
454 identifier, "Enable.Devices", &length, NULL);
455 if (technology->enabled_devices && length == 0) {
456 g_strfreev(technology->enabled_devices);
457 technology->enabled_devices = NULL;
461 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
463 technology->enable_persistent = enable;
465 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
466 technology->enable_persistent = true;
468 technology->enable_persistent = false;
471 g_clear_error(&error);
474 enable = g_key_file_get_boolean(keyfile, identifier,
475 "Tethering", &error);
477 technology->tethering_persistent = enable;
480 g_clear_error(&error);
484 technology_save(technology);
486 technology->tethering_ident = g_key_file_get_string(keyfile,
487 identifier, "Tethering.Identifier", NULL);
489 technology->tethering_passphrase = g_key_file_get_string(keyfile,
490 identifier, "Tethering.Passphrase", NULL);
494 g_key_file_free(keyfile);
497 bool __connman_technology_get_offlinemode(void)
499 return global_offlinemode;
502 static void connman_technology_save_offlinemode(void)
505 GError *error = NULL;
508 keyfile = __connman_storage_load_global();
511 keyfile = g_key_file_new();
512 g_key_file_set_boolean(keyfile, "global",
513 "OfflineMode", global_offlinemode);
515 __connman_storage_save_global(keyfile);
518 offlinemode = g_key_file_get_boolean(keyfile, "global",
519 "OfflineMode", &error);
521 if (error || offlinemode != global_offlinemode) {
522 g_key_file_set_boolean(keyfile, "global",
523 "OfflineMode", global_offlinemode);
525 g_clear_error(&error);
527 __connman_storage_save_global(keyfile);
531 g_key_file_free(keyfile);
534 static bool connman_technology_load_offlinemode(void)
537 GError *error = NULL;
540 /* If there is a error, we enable offlinemode */
541 keyfile = __connman_storage_load_global();
545 offlinemode = g_key_file_get_boolean(keyfile, "global",
546 "OfflineMode", &error);
549 g_clear_error(&error);
552 g_key_file_free(keyfile);
557 #if defined TIZEN_EXT
558 static void append_devices(DBusMessageIter *iter, void *user_data)
562 struct connman_technology *technology = user_data;
564 for (list = technology->device_list; list; list = list->next) {
565 struct connman_device *device = list->data;
567 const char *str = connman_device_get_string(device, "Interface");
568 struct connman_network *network = connman_device_get_default_network(device);
569 struct connman_service *service = connman_service_lookup_from_network(network);
571 connman_dbus_dict_append_basic(iter, "Ifname",
572 DBUS_TYPE_STRING, &str);
574 val = connman_device_get_powered(device);
575 connman_dbus_dict_append_basic(iter, "Powered",
576 DBUS_TYPE_BOOLEAN, &val);
578 if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
579 __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
584 connman_dbus_dict_append_basic(iter, "Connected",
585 DBUS_TYPE_BOOLEAN, &val);
587 str = connman_device_get_string(device, "Address");
588 connman_dbus_dict_append_basic(iter, "MAC.Address",
589 DBUS_TYPE_STRING, &str);
593 void __connman_technology_append_interfaces(DBusMessageIter *array,
594 enum connman_service_type type, const char *ifname)
597 struct connman_technology *technology = NULL;
599 for (list = technology_list; list; list = list->next) {
600 struct connman_technology *local_tech = list->data;
602 if (local_tech->type != type)
605 technology = local_tech;
612 for (list = technology->device_list; list; list = list->next) {
613 struct connman_device *device = list->data;
614 const char *str = connman_device_get_string(device, "Interface");
616 if (g_strcmp0(ifname, str) == 0)
619 dbus_message_iter_append_basic(array,
620 DBUS_TYPE_STRING, &str);
625 static void append_properties(DBusMessageIter *iter,
626 struct connman_technology *technology)
628 DBusMessageIter dict;
632 connman_dbus_dict_open(iter, &dict);
634 str = get_name(technology->type);
636 connman_dbus_dict_append_basic(&dict, "Name",
637 DBUS_TYPE_STRING, &str);
639 str = __connman_service_type2string(technology->type);
641 connman_dbus_dict_append_basic(&dict, "Type",
642 DBUS_TYPE_STRING, &str);
644 __sync_synchronize();
645 val = technology->enabled;
646 connman_dbus_dict_append_basic(&dict, "Powered",
650 val = technology->connected;
651 connman_dbus_dict_append_basic(&dict, "Connected",
655 val = technology->tethering;
656 connman_dbus_dict_append_basic(&dict, "Tethering",
660 if (technology->tethering_ident)
661 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
663 &technology->tethering_ident);
665 if (technology->tethering_passphrase)
666 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
668 &technology->tethering_passphrase);
669 #if defined TIZEN_EXT
670 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
671 connman_dbus_dict_append_dict(&dict, "Device.List",
672 append_devices, technology);
674 connman_dbus_dict_close(iter, &dict);
677 static void technology_added_signal(struct connman_technology *technology)
680 DBusMessageIter iter;
682 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
683 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
687 dbus_message_iter_init_append(signal, &iter);
688 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
690 append_properties(&iter, technology);
692 dbus_connection_send(connection, signal, NULL);
693 dbus_message_unref(signal);
696 static void technology_removed_signal(struct connman_technology *technology)
698 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
699 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
700 DBUS_TYPE_OBJECT_PATH, &technology->path,
704 static DBusMessage *get_properties(DBusConnection *conn,
705 DBusMessage *message, void *user_data)
707 struct connman_technology *technology = user_data;
709 DBusMessageIter iter;
711 reply = dbus_message_new_method_return(message);
715 dbus_message_iter_init_append(reply, &iter);
716 append_properties(&iter, technology);
721 void __connman_technology_list_struct(DBusMessageIter *array)
724 DBusMessageIter entry;
726 for (list = technology_list; list; list = list->next) {
727 struct connman_technology *technology = list->data;
729 if (!technology->path ||
730 (technology->rfkill_driven &&
731 technology->hardblocked))
734 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
736 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
738 append_properties(&entry, technology);
739 dbus_message_iter_close_container(array, &entry);
743 static gboolean technology_pending_reply(gpointer user_data)
745 struct connman_technology *technology = user_data;
748 /* Power request timed out, send ETIMEDOUT. */
749 if (technology->pending_reply) {
750 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
752 g_dbus_send_message(connection, reply);
754 dbus_message_unref(technology->pending_reply);
755 technology->pending_reply = NULL;
756 technology->pending_timeout = 0;
762 static int technology_affect_devices(struct connman_technology *technology,
765 int err = 0, err_dev;
768 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
770 __connman_technology_enabled(technology->type);
772 __connman_technology_disabled(technology->type);
776 #if defined TIZEN_EXT_WIFI_MESH
777 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
781 for (list = technology->device_list; list; list = list->next) {
782 struct connman_device *device = list->data;
785 err_dev = __connman_device_enable(device);
787 err_dev = __connman_device_disable(device);
789 if (err_dev < 0 && err_dev != -EALREADY)
796 static void powered_changed(struct connman_technology *technology)
800 if (!technology->dbus_registered)
803 if (technology->pending_reply) {
804 g_dbus_send_reply(connection,
805 technology->pending_reply, DBUS_TYPE_INVALID);
806 dbus_message_unref(technology->pending_reply);
807 technology->pending_reply = NULL;
809 g_source_remove(technology->pending_timeout);
810 technology->pending_timeout = 0;
813 __sync_synchronize();
814 enabled = technology->enabled;
815 #if defined TIZEN_EXT
816 DBG("ConnMan, Powered : %s, %s",
817 enabled ? "TRUE" : "FALSE",technology->path);
819 connman_dbus_property_changed_basic(technology->path,
820 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
821 DBUS_TYPE_BOOLEAN, &enabled);
824 static void enable_tethering(struct connman_technology *technology)
828 if (!connman_setting_get_bool("PersistentTetheringMode"))
831 ret = set_tethering(technology, true);
832 if (ret < 0 && ret != -EALREADY)
833 DBG("Cannot enable tethering yet for %s (%d/%s)",
834 get_name(technology->type),
835 -ret, strerror(-ret));
838 static int technology_enabled(struct connman_technology *technology)
840 __sync_synchronize();
841 if (technology->enabled)
844 technology->enabled = true;
846 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
847 struct connman_technology *p2p;
849 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
850 if (p2p && !p2p->enabled && p2p->enable_persistent)
851 technology_enabled(p2p);
854 if (technology->tethering_persistent)
855 enable_tethering(technology);
857 powered_changed(technology);
862 static int technology_enable(struct connman_technology *technology)
867 DBG("technology %p enable", technology);
869 __sync_synchronize();
871 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
872 struct connman_technology *wifi;
874 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
875 if (wifi && wifi->enabled)
876 return technology_enabled(technology);
880 if (technology->enabled)
883 if (technology->pending_reply)
886 if (connman_setting_get_bool("PersistentTetheringMode") &&
887 technology->tethering)
888 set_tethering(technology, true);
890 if (technology->rfkill_driven)
891 err = __connman_rfkill_block(technology->type, false);
893 err_dev = technology_affect_devices(technology, true);
895 if (!technology->rfkill_driven)
901 static int technology_disabled(struct connman_technology *technology)
903 __sync_synchronize();
904 if (!technology->enabled)
907 technology->enabled = false;
909 powered_changed(technology);
914 static int technology_disable(struct connman_technology *technology)
918 DBG("technology %p disable", technology);
920 __sync_synchronize();
922 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
923 technology->enable_persistent = false;
924 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
925 __connman_peer_disconnect_all();
926 return technology_disabled(technology);
927 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
928 struct connman_technology *p2p;
930 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
931 if (p2p && p2p->enabled) {
932 p2p->enable_persistent = true;
933 technology_disabled(p2p);
937 if (!technology->enabled)
940 if (technology->pending_reply)
943 if (technology->tethering)
944 set_tethering(technology, false);
946 err = technology_affect_devices(technology, false);
948 if (technology->rfkill_driven)
949 err = __connman_rfkill_block(technology->type, true);
954 static DBusMessage *set_powered(struct connman_technology *technology,
955 DBusMessage *msg, bool powered)
957 DBusMessage *reply = NULL;
960 if (technology->rfkill_driven && technology->hardblocked) {
966 err = technology_enable(technology);
968 err = technology_disable(technology);
971 technology->enable_persistent = powered;
972 technology_save(technology);
976 if (err == -EINPROGRESS) {
977 technology->pending_reply = dbus_message_ref(msg);
978 technology->pending_timeout = g_timeout_add_seconds(10,
979 technology_pending_reply, technology);
980 } else if (err == -EALREADY) {
982 reply = __connman_error_already_enabled(msg);
984 reply = __connman_error_already_disabled(msg);
986 reply = __connman_error_failed(msg, -err);
988 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
993 #if defined TIZEN_EXT
994 int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
996 static int bssid_len;
997 static const char *def_ifname = "default";
998 static GSList *bssid_list = NULL;
1000 const char *local_ifname = ifname;
1002 struct connman_bssid_pending *bssid_info;
1004 DBG("mode: %d, ifname: %s", mode, ifname);
1007 local_ifname = def_ifname;
1009 for (list = bssid_list; list; list = list->next) {
1010 bssid_info = list->data;
1012 if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
1018 if (mode == CHECK_BSSID) {
1025 if (mode == GET_BSSID && bssid) {
1027 memcpy(bssid, bssid_info->bssid, 6);
1033 if (mode == RESET_BSSID) {
1035 bssid_list = g_slist_remove(bssid_list, bssid_info);
1036 g_free(bssid_info->ifname);
1042 if (mode != SET_BSSID || !bssid) {
1043 DBG("Invalid parameter");
1048 bssid_list = g_slist_remove(bssid_list, bssid_info);
1049 g_free(bssid_info->ifname);
1053 bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
1055 DBG("Failed to allocate memory");
1059 unsigned char *bssid_data = bssid_info->bssid;
1061 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1062 &bssid_data[0], &bssid_data[1], &bssid_data[2],
1063 &bssid_data[3], &bssid_data[4], &bssid_data[5]);
1064 if (bssid_len != 6) {
1065 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
1070 DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
1072 bssid_data[0], bssid_data[1], bssid_data[2],
1073 bssid_data[3], bssid_data[4], bssid_data[5],
1076 bssid_info->ifname = g_strdup(ifname);
1077 bssid_list = g_slist_prepend(bssid_list, bssid_info);
1083 static DBusMessage *set_property(DBusConnection *conn,
1084 DBusMessage *msg, void *data)
1086 struct connman_technology *technology = data;
1087 DBusMessageIter iter, value;
1091 DBG("conn %p", conn);
1093 if (!dbus_message_iter_init(msg, &iter))
1094 return __connman_error_invalid_arguments(msg);
1096 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1097 return __connman_error_invalid_arguments(msg);
1099 dbus_message_iter_get_basic(&iter, &name);
1100 dbus_message_iter_next(&iter);
1102 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1103 return __connman_error_invalid_arguments(msg);
1105 dbus_message_iter_recurse(&iter, &value);
1107 type = dbus_message_iter_get_arg_type(&value);
1109 DBG("property %s", name);
1111 if (g_str_equal(name, "Tethering")) {
1112 dbus_bool_t tethering;
1115 if (type != DBUS_TYPE_BOOLEAN)
1116 return __connman_error_invalid_arguments(msg);
1118 if (!connman_technology_is_tethering_allowed(technology->type)) {
1119 DBG("%s tethering not allowed by config file",
1120 __connman_service_type2string(technology->type));
1121 return __connman_error_not_supported(msg);
1124 dbus_message_iter_get_basic(&value, &tethering);
1126 if (technology->tethering == tethering) {
1128 return __connman_error_already_disabled(msg);
1130 return __connman_error_already_enabled(msg);
1133 err = set_tethering(technology, tethering);
1135 return __connman_error_failed(msg, -err);
1137 technology->tethering_persistent = tethering;
1139 technology_save(technology);
1141 } else if (g_str_equal(name, "TetheringIdentifier")) {
1144 dbus_message_iter_get_basic(&value, &str);
1146 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1147 return __connman_error_not_supported(msg);
1149 if (strlen(str) < 1 || strlen(str) > 32)
1150 return __connman_error_invalid_arguments(msg);
1152 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1153 g_free(technology->tethering_ident);
1154 technology->tethering_ident = g_strdup(str);
1155 technology_save(technology);
1157 connman_dbus_property_changed_basic(technology->path,
1158 CONNMAN_TECHNOLOGY_INTERFACE,
1159 "TetheringIdentifier",
1161 &technology->tethering_ident);
1163 } else if (g_str_equal(name, "TetheringPassphrase")) {
1166 dbus_message_iter_get_basic(&value, &str);
1168 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1169 return __connman_error_not_supported(msg);
1171 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1174 return __connman_error_passphrase_required(msg);
1176 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1177 g_free(technology->tethering_passphrase);
1178 technology->tethering_passphrase = g_strdup(str);
1179 technology_save(technology);
1181 connman_dbus_property_changed_basic(technology->path,
1182 CONNMAN_TECHNOLOGY_INTERFACE,
1183 "TetheringPassphrase",
1185 &technology->tethering_passphrase);
1187 } else if (g_str_equal(name, "Powered")) {
1190 if (type != DBUS_TYPE_BOOLEAN)
1191 return __connman_error_invalid_arguments(msg);
1193 dbus_message_iter_get_basic(&value, &enable);
1195 return set_powered(technology, msg, enable);
1196 #if defined TIZEN_EXT
1197 } else if (g_str_equal(name, "SetBSSID")) {
1200 if (type != DBUS_TYPE_STRING)
1201 return __connman_error_invalid_arguments(msg);
1203 dbus_message_iter_get_basic(&value, &key);
1204 DBG("BSSID %s", key);
1205 set_connman_bssid(SET_BSSID, key, NULL);
1208 return __connman_error_invalid_property(msg);
1210 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1213 static void reply_scan_pending(struct connman_technology *technology, int err)
1217 DBG("technology %p err %d", technology, err);
1219 while (technology->scan_pending) {
1220 #if defined TIZEN_EXT
1221 struct connman_scan_pending *pending_data = technology->scan_pending->data;
1222 DBusMessage *msg = pending_data->msg;
1224 DBusMessage *msg = technology->scan_pending->data;
1226 DBG("reply to %s", dbus_message_get_sender(msg));
1229 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1231 reply = __connman_error_failed(msg, -err);
1232 g_dbus_send_message(connection, reply);
1233 dbus_message_unref(msg);
1235 technology->scan_pending =
1236 g_slist_delete_link(technology->scan_pending,
1237 technology->scan_pending);
1238 #if defined TIZEN_EXT
1239 g_free(pending_data->ifname);
1240 g_free(pending_data);
1245 #if defined TIZEN_EXT
1246 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1249 DBusMessage *signal;
1250 DBusMessageIter iter;
1251 dbus_bool_t result = FALSE;
1253 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1254 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1258 dbus_message_iter_init_append(signal, &iter);
1260 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1262 connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
1264 result = dbus_connection_send(connection, signal, NULL);
1265 dbus_message_unref(signal);
1267 DBG("Successfuly sent signal");
1272 void __connman_technology_notify_scan_done(const char *ifname, int val)
1275 DBusMessage *signal;
1276 DBusMessageIter iter;
1278 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1279 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1283 dbus_message_iter_init_append(signal, &iter);
1285 connman_dbus_property_append_basic(&iter, ifname,
1286 DBUS_TYPE_INT32, &val);
1288 connman_dbus_property_append_basic(&iter, "",
1289 DBUS_TYPE_INT32, &val);
1291 dbus_connection_send(connection, signal, NULL);
1292 dbus_message_unref(signal);
1294 DBG("Successfuly sent ScanDone signal");
1297 static void reply_scan_pending_device(
1298 struct connman_technology *technology, const char *ifname, int count)
1302 dbus_bool_t status = 0;
1303 connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
1305 DBG("technology %p ifname %s count %d", technology, ifname, count);
1307 list = technology->scan_pending;
1310 struct connman_scan_pending *pending_data = list->data;
1311 DBusMessage *msg = pending_data->msg;
1314 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1315 scan_type = pending_data->scan_type;
1317 if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
1320 scan_type = pending_data->scan_type;
1322 DBG("reply to %s", dbus_message_get_sender(msg));
1323 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1325 g_dbus_send_message(connection, reply);
1326 dbus_message_unref(msg);
1328 technology->scan_pending =
1329 g_slist_remove(technology->scan_pending, pending_data);
1331 g_free(pending_data->ifname);
1332 g_free(pending_data);
1335 if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
1336 scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1338 __connman_technology_notify_scan_changed(ifname, &status);
1339 __connman_technology_notify_scan_done(ifname, scan_type);
1342 static void __connman_technology_notify_device_detected(
1343 struct connman_technology *technology, const char *ifname, bool val)
1346 DBusMessage *signal;
1347 DBusMessageIter iter;
1348 dbus_bool_t detected = val;
1353 signal = dbus_message_new_signal(technology->path,
1354 CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
1358 dbus_message_iter_init_append(signal, &iter);
1359 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
1360 dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
1362 dbus_connection_send(connection, signal, NULL);
1363 dbus_message_unref(signal);
1365 DBG("Successfuly sent DeviceDetected signal");
1369 void __connman_technology_scan_started(struct connman_device *device)
1371 DBG("device %p", device);
1372 #if defined TIZEN_EXT
1373 dbus_bool_t status = 1;
1374 const char *ifname = connman_device_get_string(device, "Interface");
1376 __connman_technology_notify_scan_changed(ifname, &status);
1380 void __connman_technology_scan_stopped(struct connman_device *device,
1381 enum connman_service_type type)
1384 struct connman_technology *technology;
1387 technology = technology_find(type);
1389 DBG("technology %p device %p", technology, device);
1394 for (list = technology->device_list; list; list = list->next) {
1395 struct connman_device *other_device = list->data;
1397 if (device == other_device)
1400 if (connman_device_get_scanning(other_device, type))
1404 #if defined TIZEN_EXT
1405 const char *ifname = connman_device_get_string(device, "Interface");
1406 reply_scan_pending_device(technology, ifname, count);
1411 reply_scan_pending(technology, 0);
1415 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1416 int result, const char *alpha2)
1418 bool regdom_set = false;
1419 struct connman_technology *technology;
1420 enum connman_service_type type;
1421 GSList *tech_drivers;
1423 type = __connman_device_get_service_type(device);
1424 technology = technology_find(type);
1431 for (tech_drivers = technology->driver_list;
1433 tech_drivers = g_slist_next(tech_drivers)) {
1434 struct connman_technology_driver *driver =
1437 if (driver->set_regdom) {
1438 driver->set_regdom(technology, alpha2);
1448 connman_technology_regdom_notify(technology, alpha2);
1451 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1453 struct connman_technology *technology = data;
1456 DBG("technology %p request from %s", technology,
1457 dbus_message_get_sender(msg));
1459 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1460 !technology->enabled)
1461 return __connman_error_permission_denied(msg);
1463 #if !defined TIZEN_EXT
1464 dbus_message_ref(msg);
1465 technology->scan_pending =
1466 g_slist_prepend(technology->scan_pending, msg);
1469 err = __connman_device_request_scan_full(technology->type);
1471 #if defined TIZEN_EXT
1472 return __connman_error_failed(msg, -err);
1474 reply_scan_pending(technology, err);
1477 #if defined TIZEN_EXT
1478 struct connman_scan_pending *pending_data =
1479 g_try_malloc0(sizeof(struct connman_scan_pending));
1481 return __connman_error_failed(msg, ENOMEM);
1483 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1484 DBG("scan_type %d", pending_data->scan_type);
1486 pending_data->msg = dbus_message_ref(msg);
1488 technology->scan_pending =
1489 g_slist_prepend(technology->scan_pending, pending_data);
1494 #if defined TIZEN_EXT
1495 static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
1497 struct connman_technology *technology = data;
1498 DBusMessageIter iter;
1502 DBG("technology %p request from %s", technology,
1503 dbus_message_get_sender(msg));
1505 if (!dbus_message_iter_init(msg, &iter))
1506 return __connman_error_invalid_arguments(msg);
1508 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1509 return __connman_error_invalid_arguments(msg);
1511 dbus_message_iter_get_basic(&iter, &ifname);
1512 DBG("Interface name %s", ifname);
1514 if (!ifname || strlen(ifname) == 0)
1515 return __connman_error_invalid_arguments(msg);
1517 err = connman_device_request_device_scan(technology->type, ifname, true);
1519 return __connman_error_failed(msg, -err);
1521 struct connman_scan_pending *pending_data =
1522 g_try_malloc0(sizeof(struct connman_scan_pending));
1524 return __connman_error_failed(msg, ENOMEM);
1526 pending_data->ifname = g_strdup(ifname);
1527 if (pending_data->ifname == NULL) {
1528 g_free(pending_data);
1529 return __connman_error_failed(msg, ENOMEM);
1532 pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1533 DBG("scan_type %d", pending_data->scan_type);
1535 pending_data->msg = dbus_message_ref(msg);
1537 technology->scan_pending =
1538 g_slist_prepend(technology->scan_pending, pending_data);
1543 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1545 struct connman_technology *technology = data;
1546 GSList *specific_scan_list = NULL;
1548 const char *name = NULL;
1549 const char *freq = NULL;
1550 const char *ifname = NULL;
1551 DBusMessageIter iter, dict;
1554 DBG("technology %p request from %s", technology,
1555 dbus_message_get_sender(msg));
1557 if (!dbus_message_iter_init(msg, &iter))
1558 return __connman_error_invalid_arguments(msg);
1560 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1561 return __connman_error_invalid_arguments(msg);
1563 dbus_message_iter_recurse(&iter, &dict);
1564 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1565 DBusMessageIter entry, value2;
1569 dbus_message_iter_recurse(&dict, &entry);
1570 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1571 g_slist_free_full(specific_scan_list, g_free);
1572 return __connman_error_invalid_arguments(msg);
1575 dbus_message_iter_get_basic(&entry, &key);
1576 dbus_message_iter_next(&entry);
1578 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1579 g_slist_free_full(specific_scan_list, g_free);
1580 return __connman_error_invalid_arguments(msg);
1583 dbus_message_iter_recurse(&entry, &value2);
1584 type = dbus_message_iter_get_arg_type(&value2);
1585 if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
1587 dbus_message_iter_get_basic(&value2, &ifname);
1588 DBG("ifname %s", ifname);
1589 } else if (g_str_equal(key, "SSID")) {
1590 if (type != DBUS_TYPE_STRING) {
1591 g_slist_free_full(specific_scan_list, g_free);
1592 return __connman_error_invalid_arguments(msg);
1595 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1596 dbus_message_iter_get_basic(&value2, &name);
1597 DBG("name %s", name);
1598 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1599 } else if (g_str_equal(key, "Frequency")) {
1600 if (type != DBUS_TYPE_STRING) {
1601 g_slist_free_full(specific_scan_list, g_free);
1602 return __connman_error_invalid_arguments(msg);
1605 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1606 dbus_message_iter_get_basic(&value2, &freq);
1607 DBG("freq %s", freq);
1608 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1609 } else if (g_str_equal(key, "SSID_Mixed")) {
1610 if (type != DBUS_TYPE_STRING) {
1611 g_slist_free_full(specific_scan_list, g_free);
1612 return __connman_error_invalid_arguments(msg);
1615 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1616 dbus_message_iter_get_basic(&value2, &name);
1618 connman_multi_scan_ap_s *ap =
1619 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1621 g_strlcpy(ap->str, name, strlen(name) + 1);
1623 specific_scan_list = g_slist_append(specific_scan_list, ap);
1625 DBG("Failed to allocate memory");
1627 } else if (g_str_equal(key, "Frequency_Mixed")) {
1628 if (type != DBUS_TYPE_STRING) {
1629 g_slist_free_full(specific_scan_list, g_free);
1630 return __connman_error_invalid_arguments(msg);
1633 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1634 dbus_message_iter_get_basic(&value2, &freq);
1636 connman_multi_scan_ap_s *ap =
1637 (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1639 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1641 specific_scan_list = g_slist_append(specific_scan_list, ap);
1643 DBG("Failed to allocate memory");
1645 dbus_message_iter_next(&dict);
1648 err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
1650 return __connman_error_failed(msg, -err);
1652 guint list_size = g_slist_length(specific_scan_list);
1654 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1655 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
1656 g_slist_free_full(specific_scan_list, g_free);
1658 struct connman_scan_pending *pending_data =
1659 g_try_malloc0(sizeof(struct connman_scan_pending));
1661 return __connman_error_failed(msg, ENOMEM);
1664 pending_data->ifname = g_strdup(ifname);
1665 if (pending_data->ifname == NULL) {
1666 g_free(pending_data);
1667 return __connman_error_failed(msg, ENOMEM);
1672 pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1674 pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1675 DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
1677 pending_data->msg = dbus_message_ref(msg);
1679 technology->scan_pending =
1680 g_slist_prepend(technology->scan_pending, pending_data);
1685 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1688 DBusMessageIter iter, dict;
1690 struct connman_technology *technology = data;
1691 dbus_bool_t supported = false;
1692 const char *ifname = NULL;
1694 DBG("technology %p", technology);
1696 reply = dbus_message_new_method_return(msg);
1700 dbus_message_iter_init_append(reply, &iter);
1701 connman_dbus_dict_open(&iter, &dict);
1703 for (list = technology->device_list; list; list = list->next) {
1704 struct connman_device *device = list->data;
1706 supported = connman_device_get_wifi_5ghz_supported(device);
1707 ifname = connman_device_get_string(device, "Interface");
1709 DBG("ifname %s supported : %d", ifname, supported);
1710 connman_dbus_dict_append_basic(&dict, ifname,
1715 connman_dbus_dict_close(&iter, &dict);
1720 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1723 DBusMessageIter iter, dict;
1725 struct connman_technology *technology = data;
1726 dbus_bool_t scanning = false;
1727 const char *ifname = NULL;
1729 DBG("technology %p", technology);
1731 reply = dbus_message_new_method_return(msg);
1735 dbus_message_iter_init_append(reply, &iter);
1736 connman_dbus_dict_open(&iter, &dict);
1738 for (list = technology->device_list; list; list = list->next) {
1739 struct connman_device *device = list->data;
1741 scanning = connman_device_get_scanning(device, technology->type);
1742 ifname = connman_device_get_string(device, "Interface");
1744 DBG("ifname %s scanning : %d", ifname, scanning);
1745 connman_dbus_dict_append_basic(&dict, ifname,
1750 connman_dbus_dict_close(&iter, &dict);
1755 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
1758 DBusMessageIter iter, dict;
1760 struct connman_technology *technology = data;
1761 dbus_int32_t max_scan_ssids = 0;
1762 const char *ifname = NULL;
1764 DBG("technology %p", technology);
1766 reply = dbus_message_new_method_return(msg);
1770 dbus_message_iter_init_append(reply, &iter);
1771 connman_dbus_dict_open(&iter, &dict);
1773 for (list = technology->device_list; list; list = list->next) {
1774 struct connman_device *device = list->data;
1776 max_scan_ssids = connman_device_get_max_scan_ssids(device);
1777 ifname = connman_device_get_string(device, "Interface");
1779 DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
1780 connman_dbus_dict_append_basic(&dict, ifname,
1785 connman_dbus_dict_close(&iter, &dict);
1790 static int technology_enable_device(struct connman_technology *technology,
1791 bool enable_device, const char *ifname, struct connman_device **device_out)
1796 for (list = technology->device_list; list; list = list->next) {
1797 struct connman_device *device = list->data;
1798 const char *str = connman_device_get_string(device, "Interface");
1800 if (g_strcmp0(str, ifname) != 0)
1804 err = __connman_device_enable(device);
1806 err = __connman_device_disable(device);
1808 *device_out = device;
1815 static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
1816 DBusMessage *msg, bool powered, const char *ifname)
1818 DBusMessage *reply = NULL;
1819 struct connman_device *device = NULL;
1822 err = technology_enable_device(technology, powered, ifname, &device);
1824 if (err == -EINPROGRESS) {
1826 connman_device_set_pending_reply(device, msg);
1828 } else if (err == -EALREADY) {
1830 reply = __connman_error_already_enabled(msg);
1832 reply = __connman_error_already_disabled(msg);
1834 reply = __connman_error_failed(msg, -err);
1836 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1841 static DBusMessage *set_device_power(DBusConnection *conn,
1842 DBusMessage *msg, void *data)
1844 struct connman_technology *technology = data;
1845 DBusMessageIter iter;
1850 DBG("conn %p", conn);
1852 if (!dbus_message_iter_init(msg, &iter))
1853 return __connman_error_invalid_arguments(msg);
1855 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1856 return __connman_error_invalid_arguments(msg);
1858 dbus_message_iter_get_basic(&iter, &name);
1859 dbus_message_iter_next(&iter);
1861 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
1862 return __connman_error_invalid_arguments(msg);
1864 DBG("interface name %s", name);
1868 if (len + 1 > IFNAMSIZ)
1869 return __connman_error_invalid_arguments(msg);
1871 dbus_message_iter_get_basic(&iter, &enable);
1872 DBG("powered %s", enable ? "TRUE" : "FALSE");
1874 return technology_set_device_powered(technology, msg, enable, name);
1877 static DBusMessage *set_bssid(DBusConnection *conn,
1878 DBusMessage *msg, void *data)
1880 DBusMessageIter iter;
1884 DBG("conn %p", conn);
1886 if (!dbus_message_iter_init(msg, &iter))
1887 return __connman_error_invalid_arguments(msg);
1889 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1890 return __connman_error_invalid_arguments(msg);
1892 dbus_message_iter_get_basic(&iter, &name);
1893 dbus_message_iter_next(&iter);
1895 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1896 return __connman_error_invalid_arguments(msg);
1898 dbus_message_iter_get_basic(&iter, &bssid);
1900 DBG("interface name %s bssid %s", name, bssid);
1904 if (len + 1 > IFNAMSIZ)
1905 return __connman_error_invalid_arguments(msg);
1907 set_connman_bssid(SET_BSSID, bssid, name);
1909 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1911 static struct connman_technology *technology_get(enum connman_service_type type);
1913 void technology_save_device(struct connman_device *device)
1915 struct connman_technology *technology;
1916 enum connman_service_type type;
1918 type = __connman_device_get_service_type(device);
1919 technology = technology_get(type);
1925 const char *name = get_name(technology->type);
1927 DBG("technology %p type %d name %s", technology, technology->type,
1932 keyfile = __connman_storage_load_global();
1934 keyfile = g_key_file_new();
1936 identifier = g_strdup_printf("%s", name);
1940 GSList *list = NULL;
1941 gchar **ifname_list = NULL;
1942 guint dev_count = g_slist_length(technology->device_list);
1944 if (dev_count > 1) {
1945 GString *ifname_str = g_string_new(NULL);
1948 for (list = technology->device_list; list; list = list->next) {
1949 struct connman_device *device = list->data;
1951 if (connman_device_get_powered(device)) {
1952 const char *ifname = connman_device_get_string(device, "Interface");
1954 if (ifname_str->len > 0)
1955 g_string_append_printf(ifname_str, " %s", ifname);
1957 g_string_append(ifname_str, ifname);
1961 if (ifname_str->len > 0) {
1962 ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
1963 dev_count = g_strv_length(ifname_list);
1964 g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
1965 (const gchar **) ifname_list, dev_count);
1967 technology->enable_persistent = true;
1969 g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
1970 technology->enable_persistent = false;
1973 g_strfreev(ifname_list);
1974 g_string_free(ifname_str, TRUE);
1978 g_key_file_set_boolean(keyfile, identifier, "Enable",
1979 technology->enable_persistent);
1981 g_key_file_set_boolean(keyfile, identifier, "Tethering",
1982 technology->tethering_persistent);
1984 if (technology->tethering_ident)
1985 g_key_file_set_string(keyfile, identifier,
1986 "Tethering.Identifier",
1987 technology->tethering_ident);
1989 if (technology->tethering_passphrase)
1990 g_key_file_set_string(keyfile, identifier,
1991 "Tethering.Passphrase",
1992 technology->tethering_passphrase);
1997 __connman_storage_save_global(keyfile);
1999 g_key_file_free(keyfile);
2003 #if defined TIZEN_EXT_WIFI_MESH
2004 bool __connman_technology_get_connected(enum connman_service_type type)
2006 struct connman_technology *technology;
2008 technology = technology_find(type);
2013 return technology->connected;
2016 void __connman_technology_mesh_interface_create_finished(
2017 enum connman_service_type type, bool success,
2021 struct connman_technology *technology;
2023 technology = technology_find(type);
2025 DBG("technology %p success %d", technology, success);
2030 msg = technology->mesh_dbus_msg;
2032 DBG("No pending dbus message");
2037 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2038 __connman_device_request_scan(technology->type);
2040 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
2041 ".MeshInterfaceAddFailed", "%s", error);
2042 g_dbus_send_message(connection, reply);
2043 dbus_message_unref(msg);
2044 technology->mesh_dbus_msg = NULL;
2047 void __connman_technology_mesh_interface_remove_finished(
2048 enum connman_service_type type, bool success)
2051 struct connman_technology *technology;
2053 technology = technology_find(type);
2055 DBG("technology %p success %d", technology, success);
2057 if (!technology || !technology->mesh_dbus_msg)
2060 msg = technology->mesh_dbus_msg;
2062 DBG("No pending dbus message");
2067 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2069 reply = __connman_error_failed(msg, EINVAL);
2070 g_dbus_send_message(connection, reply);
2071 dbus_message_unref(msg);
2072 technology->mesh_dbus_msg = NULL;
2075 void __connman_technology_notify_abort_scan(enum connman_service_type type,
2079 struct connman_technology *technology;
2081 technology = technology_find(type);
2083 DBG("technology %p result %d", technology, result);
2085 if (!technology || !technology->mesh_dbus_msg)
2088 msg = technology->mesh_dbus_msg;
2090 DBG("No pending dbus message");
2095 reply = __connman_error_scan_abort_failed(msg);
2097 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2099 g_dbus_send_message(connection, reply);
2100 dbus_message_unref(msg);
2101 technology->mesh_dbus_msg = NULL;
2104 static DBusMessage *mesh_commands(DBusConnection *conn,
2105 DBusMessage *msg, void *data)
2107 struct connman_technology *technology = data;
2108 DBusMessageIter iter, value, dict;
2109 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
2112 DBG("conn %p", conn);
2114 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
2115 return __connman_error_invalid_arguments(msg);
2117 if (!dbus_message_iter_init(msg, &iter))
2118 return __connman_error_invalid_arguments(msg);
2120 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2121 return __connman_error_invalid_arguments(msg);
2123 dbus_message_iter_get_basic(&iter, &cmd);
2124 dbus_message_iter_next(&iter);
2126 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
2127 return __connman_error_invalid_arguments(msg);
2129 dbus_message_iter_recurse(&iter, &value);
2131 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
2132 return __connman_error_invalid_arguments(msg);
2134 DBG("Mesh Command %s", cmd);
2135 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
2136 dbus_message_iter_recurse(&value, &dict);
2137 const char *bridge_ifname = NULL;
2138 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2139 DBusMessageIter entry, value2;
2143 dbus_message_iter_recurse(&dict, &entry);
2145 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2146 return __connman_error_invalid_arguments(msg);
2148 dbus_message_iter_get_basic(&entry, &key);
2149 dbus_message_iter_next(&entry);
2151 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2152 return __connman_error_invalid_arguments(msg);
2154 dbus_message_iter_recurse(&entry, &value2);
2156 type = dbus_message_iter_get_arg_type(&value2);
2158 if (g_str_equal(key, "Ifname")) {
2159 if (type != DBUS_TYPE_STRING)
2160 return __connman_error_invalid_arguments(msg);
2162 dbus_message_iter_get_basic(&value2, &ifname);
2163 } else if (g_str_equal(key, "ParentIfname")) {
2164 if (type != DBUS_TYPE_STRING)
2165 return __connman_error_invalid_arguments(msg);
2167 dbus_message_iter_get_basic(&value2, &parent_ifname);
2168 } else if (g_str_equal(key, "BridgeIfname")) {
2169 if (type != DBUS_TYPE_STRING)
2170 return __connman_error_invalid_arguments(msg);
2172 dbus_message_iter_get_basic(&value2, &bridge_ifname);
2174 dbus_message_iter_next(&dict);
2176 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
2177 bridge_ifname ? bridge_ifname : "NULL");
2178 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
2182 DBG("Failed to add virtual mesh interface");
2183 return __connman_error_failed(msg, -err);
2186 DBG("Successfully added virtual mesh interface");
2188 dbus_message_ref(msg);
2189 technology->mesh_dbus_msg = msg;
2191 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
2192 dbus_message_iter_recurse(&value, &dict);
2193 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2194 DBusMessageIter entry, value2;
2198 dbus_message_iter_recurse(&dict, &entry);
2200 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2201 return __connman_error_invalid_arguments(msg);
2203 dbus_message_iter_get_basic(&entry, &key);
2204 dbus_message_iter_next(&entry);
2206 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2207 return __connman_error_invalid_arguments(msg);
2209 dbus_message_iter_recurse(&entry, &value2);
2211 type = dbus_message_iter_get_arg_type(&value2);
2213 if (g_str_equal(key, "Ifname")) {
2214 if (type != DBUS_TYPE_STRING)
2215 return __connman_error_invalid_arguments(msg);
2217 dbus_message_iter_get_basic(&value2, &ifname);
2219 dbus_message_iter_next(&dict);
2221 DBG("Mesh Ifname %s", ifname);
2222 err = __connman_mesh_remove_virtual_interface(ifname);
2225 DBG("Failed to remove virtual mesh interface");
2226 return __connman_error_failed(msg, -err);
2229 DBG("Successfully removed virtual mesh interface");
2231 dbus_message_ref(msg);
2232 technology->mesh_dbus_msg = msg;
2234 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
2235 struct connman_mesh *connman_mesh;
2236 const char *name = NULL;
2237 const char *sec_type = NULL;
2238 const char *mesh_ifname = NULL;
2239 char *identifier, *group, *address;
2240 unsigned int freq = 0;
2241 unsigned int ieee80211w = 0;
2244 dbus_message_iter_recurse(&value, &dict);
2245 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2246 DBusMessageIter entry, value2;
2250 dbus_message_iter_recurse(&dict, &entry);
2252 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2253 return __connman_error_invalid_arguments(msg);
2255 dbus_message_iter_get_basic(&entry, &key);
2256 dbus_message_iter_next(&entry);
2258 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2259 return __connman_error_invalid_arguments(msg);
2261 dbus_message_iter_recurse(&entry, &value2);
2263 type = dbus_message_iter_get_arg_type(&value2);
2265 if (g_str_equal(key, "Name")) {
2266 if (type != DBUS_TYPE_STRING)
2267 return __connman_error_invalid_arguments(msg);
2269 dbus_message_iter_get_basic(&value2, &name);
2270 } else if (g_str_equal(key, "Frequency")) {
2271 if (type != DBUS_TYPE_UINT16)
2272 return __connman_error_invalid_arguments(msg);
2274 dbus_message_iter_get_basic(&value2, &freq);
2275 } else if (g_str_equal(key, "Security")) {
2276 if (type != DBUS_TYPE_STRING)
2277 return __connman_error_invalid_arguments(msg);
2279 dbus_message_iter_get_basic(&value2, &sec_type);
2280 } else if (g_str_equal(key, "Pmf")) {
2281 if (type != DBUS_TYPE_UINT16)
2282 return __connman_error_invalid_arguments(msg);
2284 dbus_message_iter_get_basic(&value2, &ieee80211w);
2286 dbus_message_iter_next(&dict);
2289 if (name == NULL || sec_type == NULL || freq == 0)
2290 return __connman_error_invalid_arguments(msg);
2292 DBG("Name %s Frequency %d Security type %s Pmf %u",
2293 name, freq, sec_type, ieee80211w);
2295 if (g_strcmp0(sec_type, "none") != 0 &&
2296 g_strcmp0(sec_type, "sae") != 0) {
2297 DBG("Unsupported security");
2298 return __connman_error_invalid_arguments(msg);
2301 mesh_ifname = connman_mesh_get_interface_name();
2303 if (!connman_mesh_is_interface_created()) {
2304 DBG("Mesh interface doesn't exists");
2305 return __connman_error_invalid_command(msg);
2308 str = g_string_sized_new((strlen(name) * 2) + 24);
2310 for (i = 0; name[i]; i++)
2311 g_string_append_printf(str, "%02x", name[i]);
2313 g_string_append_printf(str, "_mesh");
2315 if (g_strcmp0(sec_type, "none") == 0)
2316 g_string_append_printf(str, "_none");
2317 else if (g_strcmp0(sec_type, "sae") == 0)
2318 g_string_append_printf(str, "_sae");
2320 group = g_string_free(str, FALSE);
2322 identifier = connman_inet_ifaddr(mesh_ifname);
2323 address = connman_inet_ifname2addr(mesh_ifname);
2325 connman_mesh = connman_mesh_create(identifier, group);
2326 connman_mesh_set_name(connman_mesh, name);
2327 connman_mesh_set_address(connman_mesh, address);
2328 connman_mesh_set_security(connman_mesh, sec_type);
2329 connman_mesh_set_frequency(connman_mesh, freq);
2330 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
2331 connman_mesh_set_peer_type(connman_mesh,
2332 CONNMAN_MESH_PEER_TYPE_CREATED);
2333 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
2335 connman_mesh_register(connman_mesh);
2339 DBG("Successfully Created Mesh Network");
2340 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2342 } else if (g_str_equal(cmd, "AbortScan")) {
2343 DBG("Abort Scan method");
2344 err = __connman_device_abort_scan(technology->type);
2346 DBG("Failed to abort scan");
2347 return __connman_error_failed(msg, -err);
2350 DBG("Successfully requested to abort scan");
2351 dbus_message_ref(msg);
2352 technology->mesh_dbus_msg = msg;
2354 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
2355 const char *name = NULL;
2356 unsigned int freq = 0;
2357 dbus_message_iter_recurse(&value, &dict);
2358 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2359 DBusMessageIter entry, value2;
2363 dbus_message_iter_recurse(&dict, &entry);
2365 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2366 return __connman_error_invalid_arguments(msg);
2368 dbus_message_iter_get_basic(&entry, &key);
2369 dbus_message_iter_next(&entry);
2371 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2372 return __connman_error_invalid_arguments(msg);
2374 dbus_message_iter_recurse(&entry, &value2);
2376 type = dbus_message_iter_get_arg_type(&value2);
2378 if (g_str_equal(key, "Name")) {
2379 if (type != DBUS_TYPE_STRING)
2380 return __connman_error_invalid_arguments(msg);
2382 dbus_message_iter_get_basic(&value2, &name);
2383 } else if (g_str_equal(key, "Frequency")) {
2384 if (type != DBUS_TYPE_UINT16)
2385 return __connman_error_invalid_arguments(msg);
2387 dbus_message_iter_get_basic(&value2, &freq);
2389 dbus_message_iter_next(&dict);
2392 DBG("MeshID %s Frequency %d sender %s", name, freq,
2393 dbus_message_get_sender(msg));
2395 struct connman_scan_pending *pending_data =
2396 g_try_malloc0(sizeof(struct connman_scan_pending));
2398 return __connman_error_failed(msg, ENOMEM);
2400 pending_data->msg = dbus_message_ref(msg);
2402 technology->scan_pending =
2403 g_slist_prepend(technology->scan_pending, pending_data);
2405 err = __connman_device_request_mesh_specific_scan(technology->type,
2408 reply_scan_pending(technology, err);
2410 DBG("Successfully requested to scan specific Mesh Network");
2412 } else if (g_str_equal(cmd, "SetMeshGate")) {
2413 unsigned int hwmp_rootmode = 0;
2414 bool gate_announce = false;
2415 unsigned int stp = 0;
2417 dbus_message_iter_recurse(&value, &dict);
2418 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
2419 DBusMessageIter entry, value2;
2423 dbus_message_iter_recurse(&dict, &entry);
2425 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
2426 return __connman_error_invalid_arguments(msg);
2428 dbus_message_iter_get_basic(&entry, &key);
2429 dbus_message_iter_next(&entry);
2431 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
2432 return __connman_error_invalid_arguments(msg);
2434 dbus_message_iter_recurse(&entry, &value2);
2436 type = dbus_message_iter_get_arg_type(&value2);
2438 if (g_str_equal(key, "GateAnnounce")) {
2439 if (type != DBUS_TYPE_BOOLEAN)
2440 return __connman_error_invalid_arguments(msg);
2442 dbus_message_iter_get_basic(&value2, &gate_announce);
2443 } else if (g_str_equal(key, "HWMPRootMode")) {
2444 if (type != DBUS_TYPE_UINT16)
2445 return __connman_error_invalid_arguments(msg);
2447 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
2448 } else if (g_str_equal(key, "STP")) {
2449 if (type != DBUS_TYPE_UINT16)
2450 return __connman_error_invalid_arguments(msg);
2452 dbus_message_iter_get_basic(&value2, &stp);
2454 dbus_message_iter_next(&dict);
2457 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
2458 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
2460 err = __connman_mesh_set_stp_gate_announce(gate_announce,
2465 return __connman_error_failed(msg, -err);
2467 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
2469 return __connman_error_invalid_command(msg);
2474 static const GDBusMethodTable technology_methods[] = {
2475 { GDBUS_DEPRECATED_METHOD("GetProperties",
2476 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
2478 { GDBUS_ASYNC_METHOD("SetProperty",
2479 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2480 NULL, set_property) },
2481 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
2482 #if defined TIZEN_EXT
2483 { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
2484 NULL, scan_device) },
2485 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
2486 NULL, specific_scan) },
2487 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
2489 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
2490 get_5ghz_supported) },
2491 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
2492 get_max_scan_ssid) },
2493 { GDBUS_ASYNC_METHOD("SetDevicePower",
2494 GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
2495 NULL, set_device_power) },
2496 { GDBUS_ASYNC_METHOD("SetBSSID",
2497 GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
2500 #if defined TIZEN_EXT_WIFI_MESH
2501 { GDBUS_ASYNC_METHOD("MeshCommands",
2502 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
2503 NULL, mesh_commands) },
2508 static const GDBusSignalTable technology_signals[] = {
2509 { GDBUS_SIGNAL("PropertyChanged",
2510 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
2511 #if defined TIZEN_EXT
2512 { GDBUS_SIGNAL("DeviceChanged",
2513 GDBUS_ARGS({ "device_property", "a{sv}" })) },
2514 { GDBUS_SIGNAL("DeviceDetected",
2515 GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
2520 static bool technology_dbus_register(struct connman_technology *technology)
2522 if (technology->dbus_registered ||
2523 (technology->rfkill_driven &&
2524 technology->hardblocked))
2527 if (!g_dbus_register_interface(connection, technology->path,
2528 CONNMAN_TECHNOLOGY_INTERFACE,
2529 technology_methods, technology_signals,
2530 NULL, technology, NULL)) {
2531 connman_error("Failed to register %s", technology->path);
2535 technology_added_signal(technology);
2536 technology->dbus_registered = true;
2541 static void technology_dbus_unregister(struct connman_technology *technology)
2543 if (!technology->dbus_registered)
2546 technology_removed_signal(technology);
2547 g_dbus_unregister_interface(connection, technology->path,
2548 CONNMAN_TECHNOLOGY_INTERFACE);
2550 technology->dbus_registered = false;
2553 static void technology_put(struct connman_technology *technology)
2555 DBG("technology %p", technology);
2557 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2560 reply_scan_pending(technology, -EINTR);
2562 while (technology->driver_list) {
2563 struct connman_technology_driver *driver;
2565 driver = technology->driver_list->data;
2568 driver->remove(technology);
2570 technology->driver_list =
2571 g_slist_delete_link(technology->driver_list,
2572 technology->driver_list);
2575 technology_list = g_slist_remove(technology_list, technology);
2577 technology_dbus_unregister(technology);
2579 g_slist_free(technology->device_list);
2581 if (technology->pending_reply) {
2582 dbus_message_unref(technology->pending_reply);
2583 technology->pending_reply = NULL;
2584 g_source_remove(technology->pending_timeout);
2585 technology->pending_timeout = 0;
2588 g_strfreev(technology->enabled_devices);
2590 g_free(technology->path);
2591 g_free(technology->regdom);
2592 g_free(technology->tethering_ident);
2593 g_free(technology->tethering_passphrase);
2597 static struct connman_technology *technology_get(enum connman_service_type type)
2599 GSList *tech_drivers = NULL;
2600 struct connman_technology_driver *driver;
2601 struct connman_technology *technology;
2605 DBG("type %d", type);
2607 str = __connman_service_type2string(type);
2611 technology = technology_find(type);
2613 #if defined TIZEN_EXT_WIFI_MESH
2614 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2615 type != CONNMAN_SERVICE_TYPE_MESH)
2617 if (type != CONNMAN_SERVICE_TYPE_P2P)
2619 __sync_fetch_and_add(&technology->refcount, 1);
2623 /* First check if we have a driver for this technology type */
2624 for (list = driver_list; list; list = list->next) {
2625 driver = list->data;
2627 if (driver->type == type) {
2628 DBG("technology %p driver %p", technology, driver);
2629 tech_drivers = g_slist_append(tech_drivers, driver);
2633 if (!tech_drivers) {
2634 DBG("No matching drivers found for %s.",
2635 __connman_service_type2string(type));
2639 technology = g_try_new0(struct connman_technology, 1);
2643 technology->refcount = 1;
2644 technology->type = type;
2645 technology->path = g_strdup_printf("%s/technology/%s",
2648 #if defined TIZEN_EXT_WIFI_MESH
2649 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2650 struct connman_technology *wifi;
2652 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2654 technology->enabled = wifi->enabled;
2658 technology_load(technology);
2659 technology_list = g_slist_prepend(technology_list, technology);
2660 technology->driver_list = tech_drivers;
2662 for (list = tech_drivers; list; list = list->next) {
2663 driver = list->data;
2665 if (driver->probe && driver->probe(technology) < 0)
2666 DBG("Driver probe failed for technology %p",
2670 if (!technology_dbus_register(technology)) {
2671 technology_put(technology);
2675 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2676 struct connman_technology *wifi;
2679 enable = technology->enable_persistent;
2681 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2683 enable = wifi->enabled;
2685 technology_affect_devices(technology, enable);
2688 DBG("technology %p %s", technology, get_name(technology->type));
2693 int connman_technology_driver_register(struct connman_technology_driver *driver)
2696 struct connman_device *device;
2697 enum connman_service_type type;
2699 for (list = driver_list; list; list = list->next) {
2700 if (list->data == driver)
2704 DBG("Registering %s driver", driver->name);
2706 driver_list = g_slist_insert_sorted(driver_list, driver,
2710 * Check for technology less devices if this driver
2711 * can service any of them.
2713 for (list = techless_device_list; list; list = list->next) {
2714 device = list->data;
2716 type = __connman_device_get_service_type(device);
2717 if (type != driver->type)
2720 techless_device_list = g_slist_remove(techless_device_list,
2723 __connman_technology_add_device(device);
2726 /* Check for orphaned rfkill switches. */
2727 g_hash_table_foreach(rfkill_list, rfkill_check,
2728 GINT_TO_POINTER(driver->type));
2731 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2732 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
2736 #if defined TIZEN_EXT_WIFI_MESH
2737 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2738 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
2746 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
2748 GSList *list, *tech_drivers;
2749 struct connman_technology *technology;
2750 struct connman_technology_driver *current;
2752 DBG("Unregistering driver %p name %s", driver, driver->name);
2754 for (list = technology_list; list; list = list->next) {
2755 technology = list->data;
2757 for (tech_drivers = technology->driver_list; tech_drivers;
2758 tech_drivers = g_slist_next(tech_drivers)) {
2759 current = tech_drivers->data;
2760 if (driver != current)
2764 driver->remove(technology);
2766 technology->driver_list =
2767 g_slist_remove(technology->driver_list,
2773 driver_list = g_slist_remove(driver_list, driver);
2775 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2776 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
2778 technology_put(technology);
2780 #if defined TIZEN_EXT_WIFI_MESH
2781 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2782 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
2784 technology_put(technology);
2789 void __connman_technology_add_interface(enum connman_service_type type,
2790 int index, const char *ident)
2792 struct connman_technology *technology;
2793 GSList *tech_drivers;
2794 struct connman_technology_driver *driver;
2798 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2799 case CONNMAN_SERVICE_TYPE_SYSTEM:
2801 case CONNMAN_SERVICE_TYPE_ETHERNET:
2802 case CONNMAN_SERVICE_TYPE_WIFI:
2803 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2804 case CONNMAN_SERVICE_TYPE_CELLULAR:
2805 case CONNMAN_SERVICE_TYPE_GPS:
2806 case CONNMAN_SERVICE_TYPE_VPN:
2807 case CONNMAN_SERVICE_TYPE_GADGET:
2808 case CONNMAN_SERVICE_TYPE_P2P:
2809 #if defined TIZEN_EXT_WIFI_MESH
2810 case CONNMAN_SERVICE_TYPE_MESH:
2815 name = connman_inet_ifname(index);
2816 connman_info("Adding interface %s [ %s ]", name,
2817 __connman_service_type2string(type));
2819 technology = technology_find(type);
2824 for (tech_drivers = technology->driver_list; tech_drivers;
2825 tech_drivers = g_slist_next(tech_drivers)) {
2826 driver = tech_drivers->data;
2828 if (driver->add_interface)
2829 driver->add_interface(technology, index, name, ident);
2833 * At this point we can try to enable tethering automatically as
2834 * now the interfaces are set properly.
2836 if (technology->tethering_persistent)
2837 enable_tethering(technology);
2843 void __connman_technology_remove_interface(enum connman_service_type type,
2844 int index, const char *ident)
2846 struct connman_technology *technology;
2847 GSList *tech_drivers;
2848 struct connman_technology_driver *driver;
2852 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2853 case CONNMAN_SERVICE_TYPE_SYSTEM:
2855 case CONNMAN_SERVICE_TYPE_ETHERNET:
2856 case CONNMAN_SERVICE_TYPE_WIFI:
2857 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2858 case CONNMAN_SERVICE_TYPE_CELLULAR:
2859 case CONNMAN_SERVICE_TYPE_GPS:
2860 case CONNMAN_SERVICE_TYPE_VPN:
2861 case CONNMAN_SERVICE_TYPE_GADGET:
2862 case CONNMAN_SERVICE_TYPE_P2P:
2863 #if defined TIZEN_EXT_WIFI_MESH
2864 case CONNMAN_SERVICE_TYPE_MESH:
2869 name = connman_inet_ifname(index);
2870 connman_info("Remove interface %s [ %s ]", name,
2871 __connman_service_type2string(type));
2874 technology = technology_find(type);
2879 for (tech_drivers = technology->driver_list; tech_drivers;
2880 tech_drivers = g_slist_next(tech_drivers)) {
2881 driver = tech_drivers->data;
2883 if (driver->remove_interface)
2884 driver->remove_interface(technology, index);
2888 int __connman_technology_add_device(struct connman_device *device)
2890 struct connman_technology *technology;
2891 enum connman_service_type type;
2893 type = __connman_device_get_service_type(device);
2895 DBG("device %p type %s", device, get_name(type));
2897 technology = technology_get(type);
2900 * Since no driver can be found for this device at the moment we
2901 * add it to the techless device list.
2903 techless_device_list = g_slist_prepend(techless_device_list,
2909 __sync_synchronize();
2910 if (technology->rfkill_driven) {
2911 if (technology->enabled)
2912 __connman_device_enable(device);
2914 __connman_device_disable(device);
2919 if (technology->enable_persistent &&
2920 !global_offlinemode) {
2921 #if defined TIZEN_EXT
2924 if (technology->enabled_devices) {
2927 const char *ifname = connman_device_get_string(device, "Interface");
2929 while (technology->enabled_devices[i]) {
2930 if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
2939 err = __connman_device_enable(device);
2941 int err = __connman_device_enable(device);
2944 * connman_technology_add_device() calls __connman_device_enable()
2945 * but since the device is already enabled, the call does not
2946 * propagate through to connman_technology_enabled via
2947 * connman_device_set_powered.
2949 if (err == -EALREADY)
2950 __connman_technology_enabled(type);
2952 /* if technology persistent state is offline */
2953 if (!technology->enable_persistent)
2954 __connman_device_disable(device);
2957 technology->device_list = g_slist_prepend(technology->device_list,
2960 #if defined TIZEN_EXT
2961 const char *ifname = connman_device_get_string(device, "Interface");
2962 __connman_technology_notify_device_detected(technology, ifname, true);
2967 int __connman_technology_remove_device(struct connman_device *device)
2969 struct connman_technology *technology;
2970 enum connman_service_type type;
2972 DBG("device %p", device);
2974 type = __connman_device_get_service_type(device);
2976 technology = technology_find(type);
2978 techless_device_list = g_slist_remove(techless_device_list,
2983 technology->device_list = g_slist_remove(technology->device_list,
2986 #if defined TIZEN_EXT
2987 const char *ifname = connman_device_get_string(device, "Interface");
2988 __connman_technology_notify_device_detected(technology, ifname, false);
2991 if (technology->tethering)
2992 set_tethering(technology, false);
2994 technology_put(technology);
2999 int __connman_technology_enabled(enum connman_service_type type)
3001 struct connman_technology *technology;
3003 technology = technology_find(type);
3007 DBG("technology %p type %s rfkill %d enabled %d", technology,
3008 get_name(type), technology->rfkill_driven,
3009 technology->enabled);
3011 #if !defined TIZEN_EXT
3012 if (technology->rfkill_driven) {
3013 if (technology->tethering_persistent)
3014 enable_tethering(technology);
3019 return technology_enabled(technology);
3022 int __connman_technology_disabled(enum connman_service_type type)
3024 struct connman_technology *technology;
3027 technology = technology_find(type);
3031 #if !defined TIZEN_EXT
3032 if (technology->rfkill_driven)
3036 for (list = technology->device_list; list; list = list->next) {
3037 struct connman_device *device = list->data;
3039 if (connman_device_get_powered(device))
3043 return technology_disabled(technology);
3046 int __connman_technology_set_offlinemode(bool offlinemode)
3049 int err = -EINVAL, enabled_tech_count = 0;
3051 if (global_offlinemode == offlinemode)
3054 DBG("offlinemode %s", offlinemode ? "On" : "Off");
3057 * This is a bit tricky. When you set offlinemode, there is no
3058 * way to differentiate between attempting offline mode and
3059 * resuming offlinemode from last saved profile. We need that
3060 * information in rfkill_update, otherwise it falls back on the
3061 * technology's persistent state. Hence we set the offline mode here
3062 * but save it & call the notifier only if it is successful.
3065 global_offlinemode = offlinemode;
3067 /* Traverse technology list, enable/disable each technology. */
3068 for (list = technology_list; list; list = list->next) {
3069 struct connman_technology *technology = list->data;
3072 err = technology_disable(technology);
3074 if (technology->hardblocked)
3077 if (technology->enable_persistent) {
3078 err = technology_enable(technology);
3079 enabled_tech_count++;
3084 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
3085 (err == -EINVAL && enabled_tech_count == 0)) {
3086 connman_technology_save_offlinemode();
3087 __connman_notifier_offlinemode(offlinemode);
3089 global_offlinemode = connman_technology_load_offlinemode();
3094 #if defined TIZEN_EXT_WIFI_MESH
3095 static gboolean __add_ethernet_to_bridge(gpointer data)
3098 __connman_mesh_add_ethernet_to_bridge();
3103 void __connman_technology_set_connected(enum connman_service_type type,
3106 struct connman_technology *technology;
3109 technology = technology_find(type);
3113 DBG("technology %p connected %d", technology, connected);
3115 technology->connected = connected;
3117 #if defined TIZEN_EXT_WIFI_MESH
3118 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
3119 g_idle_add(__add_ethernet_to_bridge, NULL);
3123 connman_dbus_property_changed_basic(technology->path,
3124 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
3125 DBUS_TYPE_BOOLEAN, &val);
3128 static bool technology_apply_rfkill_change(struct connman_technology *technology,
3133 bool hardblock_changed = false;
3135 GList *start, *list;
3137 DBG("technology %p --> %d/%d vs %d/%d",
3138 technology, softblock, hardblock,
3139 technology->softblocked, technology->hardblocked);
3141 if (technology->hardblocked == hardblock)
3142 goto softblock_change;
3144 if (!(new_rfkill && !hardblock)) {
3145 start = g_hash_table_get_values(rfkill_list);
3147 for (list = start; list; list = list->next) {
3148 struct connman_rfkill *rfkill = list->data;
3150 if (rfkill->type != technology->type)
3153 if (rfkill->hardblock != hardblock)
3161 goto softblock_change;
3163 technology->hardblocked = hardblock;
3164 hardblock_changed = true;
3167 if (!apply && technology->softblocked != softblock)
3171 return technology->hardblocked;
3173 technology->softblocked = softblock;
3175 if (technology->hardblocked ||
3176 technology->softblocked) {
3177 if (technology_disabled(technology) != -EALREADY)
3178 technology_affect_devices(technology, false);
3179 } else if (!technology->hardblocked &&
3180 !technology->softblocked) {
3181 if (technology_enabled(technology) != -EALREADY)
3182 technology_affect_devices(technology, true);
3185 if (hardblock_changed) {
3186 if (technology->hardblocked) {
3187 DBG("%s is switched off.", get_name(technology->type));
3188 technology_dbus_unregister(technology);
3190 DBG("%s is switched on.", get_name(technology->type));
3191 technology_dbus_register(technology);
3193 if (global_offlinemode)
3194 __connman_rfkill_block(technology->type, true);
3198 return technology->hardblocked;
3201 int __connman_technology_add_rfkill(unsigned int index,
3202 enum connman_service_type type,
3206 struct connman_technology *technology;
3207 struct connman_rfkill *rfkill;
3209 DBG("index %u type %d soft %u hard %u", index, type,
3210 softblock, hardblock);
3212 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3216 rfkill = g_try_new0(struct connman_rfkill, 1);
3220 rfkill->index = index;
3221 rfkill->type = type;
3222 rfkill->softblock = softblock;
3223 rfkill->hardblock = hardblock;
3225 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
3228 #if defined TIZEN_EXT
3229 /* Fix Svace Issue [WGID: 1348]. */
3232 technology = technology_get(type);
3233 /* If there is no driver for this type, ignore it. */
3237 technology->rfkill_driven = true;
3239 #if !defined TIZEN_EXT
3240 /* If hardblocked, there is no need to handle softblocked state */
3241 if (technology_apply_rfkill_change(technology,
3242 softblock, hardblock, true))
3246 if (global_offlinemode)
3250 * Depending on softblocked state we unblock/block according to
3251 * offlinemode and persistente state.
3253 if (technology->softblocked &&
3254 technology->enable_persistent)
3255 return __connman_rfkill_block(type, false);
3256 else if (!technology->softblocked &&
3257 !technology->enable_persistent)
3258 return __connman_rfkill_block(type, true);
3263 int __connman_technology_update_rfkill(unsigned int index,
3264 enum connman_service_type type,
3268 struct connman_technology *technology;
3269 struct connman_rfkill *rfkill;
3271 DBG("index %u soft %u hard %u", index, softblock, hardblock);
3273 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3277 if (rfkill->softblock == softblock &&
3278 rfkill->hardblock == hardblock)
3281 rfkill->softblock = softblock;
3282 rfkill->hardblock = hardblock;
3284 technology = technology_find(type);
3285 /* If there is no driver for this type, ignore it. */
3289 technology_apply_rfkill_change(technology, softblock, hardblock,
3292 if (technology->hardblocked)
3293 DBG("%s hardblocked", get_name(technology->type));
3295 DBG("%s is%s softblocked", get_name(technology->type),
3296 technology->softblocked ? "" : " not");
3301 int __connman_technology_remove_rfkill(unsigned int index,
3302 enum connman_service_type type)
3304 struct connman_technology *technology;
3305 struct connman_rfkill *rfkill;
3307 DBG("index %u", index);
3309 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
3313 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
3315 technology = technology_find(type);
3319 technology_apply_rfkill_change(technology,
3320 technology->softblocked, !technology->hardblocked, false);
3322 technology_put(technology);
3327 int __connman_technology_init(void)
3331 connection = connman_dbus_get_connection();
3333 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
3336 global_offlinemode = connman_technology_load_offlinemode();
3338 /* This will create settings file if it is missing */
3339 connman_technology_save_offlinemode();
3344 void __connman_technology_cleanup(void)
3348 while (technology_list) {
3349 struct connman_technology *technology = technology_list->data;
3350 technology_list = g_slist_remove(technology_list, technology);
3351 technology_put(technology);
3354 g_hash_table_destroy(rfkill_list);
3356 dbus_connection_unref(connection);