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
37 static DBusConnection *connection;
39 static GSList *technology_list = NULL;
42 * List of devices with no technology associated with them either because of
43 * no compiled in support or the driver is not yet loaded.
45 static GSList *techless_device_list = NULL;
46 static GHashTable *rfkill_list;
48 static bool global_offlinemode;
52 CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00,
53 CONNMAN_SCAN_TYPE_SPECIFIC_AP,
54 CONNMAN_SCAN_TYPE_MULTI_AP,
55 } connman_scan_type_e;
57 static connman_scan_type_e g_scan_type = -1;
60 struct connman_rfkill {
62 enum connman_service_type type;
67 struct connman_technology {
69 enum connman_service_type type;
77 bool tethering_persistent; /* Tells the save status, needed
78 * as offline mode might set
81 char *tethering_ident;
82 char *tethering_passphrase;
84 bool enable_persistent; /* Save the tech state */
88 DBusMessage *pending_reply;
89 guint pending_timeout;
97 #if defined TIZEN_EXT_WIFI_MESH
98 DBusMessage *mesh_dbus_msg;
100 #if defined TIZEN_EXT
101 bool is_5_0_ghz_supported;
106 static GSList *driver_list = NULL;
108 static int technology_enabled(struct connman_technology *technology);
109 static int technology_disabled(struct connman_technology *technology);
111 static gint compare_priority(gconstpointer a, gconstpointer b)
113 const struct connman_technology_driver *driver1 = a;
114 const struct connman_technology_driver *driver2 = b;
116 return driver2->priority - driver1->priority;
119 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
121 struct connman_rfkill *rfkill = value;
122 enum connman_service_type type = GPOINTER_TO_INT(user_data);
124 /* Calling _technology_add_rfkill will update the tech. */
125 if (rfkill->type == type)
126 __connman_technology_add_rfkill(rfkill->index, type,
127 rfkill->softblock, rfkill->hardblock);
131 connman_technology_is_tethering_allowed(enum connman_service_type type)
133 static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
135 const char *type_str = __connman_service_type2string(type);
142 allowed = connman_setting_get_string_list("TetheringTechnologies");
144 allowed = allowed_default;
146 for (i = 0; allowed[i]; i++) {
147 if (g_strcmp0(allowed[i], type_str) == 0)
154 static const char *get_name(enum connman_service_type type)
157 case CONNMAN_SERVICE_TYPE_UNKNOWN:
158 case CONNMAN_SERVICE_TYPE_SYSTEM:
159 case CONNMAN_SERVICE_TYPE_GPS:
160 case CONNMAN_SERVICE_TYPE_VPN:
162 case CONNMAN_SERVICE_TYPE_GADGET:
164 case CONNMAN_SERVICE_TYPE_ETHERNET:
166 case CONNMAN_SERVICE_TYPE_WIFI:
168 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
170 case CONNMAN_SERVICE_TYPE_CELLULAR:
172 case CONNMAN_SERVICE_TYPE_P2P:
174 #if defined TIZEN_EXT_WIFI_MESH
175 case CONNMAN_SERVICE_TYPE_MESH:
183 static void technology_save(struct connman_technology *technology)
187 const char *name = get_name(technology->type);
189 DBG("technology %p type %d name %s", technology, technology->type,
194 keyfile = __connman_storage_load_global();
196 keyfile = g_key_file_new();
198 identifier = g_strdup_printf("%s", name);
202 g_key_file_set_boolean(keyfile, identifier, "Enable",
203 technology->enable_persistent);
205 g_key_file_set_boolean(keyfile, identifier, "Tethering",
206 technology->tethering_persistent);
208 if (technology->tethering_ident)
209 g_key_file_set_string(keyfile, identifier,
210 "Tethering.Identifier",
211 technology->tethering_ident);
213 if (technology->tethering_passphrase)
214 g_key_file_set_string(keyfile, identifier,
215 "Tethering.Passphrase",
216 technology->tethering_passphrase);
221 __connman_storage_save_global(keyfile);
223 g_key_file_free(keyfile);
226 static void tethering_changed(struct connman_technology *technology)
228 dbus_bool_t tethering = technology->tethering;
230 connman_dbus_property_changed_basic(technology->path,
231 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
232 DBUS_TYPE_BOOLEAN, &tethering);
234 technology_save(technology);
237 int connman_technology_tethering_notify(struct connman_technology *technology,
242 DBG("technology %p enabled %u", technology, enabled);
244 if (technology->tethering == enabled)
248 err = __connman_tethering_set_enabled();
252 __connman_tethering_set_disabled();
254 technology->tethering = enabled;
255 tethering_changed(technology);
260 static int set_tethering(struct connman_technology *technology,
263 int result = -EOPNOTSUPP;
265 const char *ident, *passphrase, *bridge;
266 GSList *tech_drivers;
268 ident = technology->tethering_ident;
269 passphrase = technology->tethering_passphrase;
271 __sync_synchronize();
272 if (!technology->enabled)
275 bridge = __connman_tethering_get_bridge();
279 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
280 (!ident || !passphrase))
283 for (tech_drivers = technology->driver_list; tech_drivers;
284 tech_drivers = g_slist_next(tech_drivers)) {
285 struct connman_technology_driver *driver = tech_drivers->data;
287 if (!driver || !driver->set_tethering)
290 err = driver->set_tethering(technology, ident, passphrase,
293 if (result == -EINPROGRESS)
296 if (err == -EINPROGRESS || err == 0)
303 void connman_technology_regdom_notify(struct connman_technology *technology,
309 connman_error("Failed to set regulatory domain");
311 DBG("Regulatory domain set to %s", alpha2);
313 g_free(technology->regdom);
314 technology->regdom = g_strdup(alpha2);
317 static int set_regdom_by_device(struct connman_technology *technology,
322 for (list = technology->device_list; list; list = list->next) {
323 struct connman_device *device = list->data;
325 if (connman_device_set_regdom(device, alpha2) != 0)
332 int connman_technology_set_regdom(const char *alpha2)
334 GSList *list, *tech_drivers;
336 for (list = technology_list; list; list = list->next) {
337 struct connman_technology *technology = list->data;
339 if (set_regdom_by_device(technology, alpha2) != 0) {
341 for (tech_drivers = technology->driver_list;
343 tech_drivers = g_slist_next(tech_drivers)) {
345 struct connman_technology_driver *driver =
348 if (driver->set_regdom)
349 driver->set_regdom(technology, alpha2);
357 static struct connman_technology *technology_find(enum connman_service_type type)
361 DBG("type %d", type);
363 for (list = technology_list; list; list = list->next) {
364 struct connman_technology *technology = list->data;
366 if (technology->type == type)
373 enum connman_service_type connman_technology_get_type
374 (struct connman_technology *technology)
377 return CONNMAN_SERVICE_TYPE_UNKNOWN;
379 return technology->type;
382 bool connman_technology_get_wifi_tethering(const char **ssid,
385 struct connman_technology *technology;
392 technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
396 if (!technology->tethering)
399 *ssid = technology->tethering_ident;
400 *psk = technology->tethering_passphrase;
405 #if defined TIZEN_EXT
406 void connman_techonology_wifi_set_5ghz_supported(struct connman_technology *wifi_technology,
407 bool is_5_0_ghz_supported)
411 wifi_technology->is_5_0_ghz_supported = is_5_0_ghz_supported;
415 static void free_rfkill(gpointer data)
417 struct connman_rfkill *rfkill = data;
422 static void technology_load(struct connman_technology *technology)
426 GError *error = NULL;
427 bool enable, need_saving = false;
429 DBG("technology %p", technology);
431 keyfile = __connman_storage_load_global();
432 /* Fallback on disabling technology if file not found. */
434 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
435 /* We enable ethernet by default */
436 technology->enable_persistent = true;
438 technology->enable_persistent = false;
442 identifier = g_strdup_printf("%s", get_name(technology->type));
446 enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
448 technology->enable_persistent = enable;
450 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
451 technology->enable_persistent = true;
453 technology->enable_persistent = false;
456 g_clear_error(&error);
459 enable = g_key_file_get_boolean(keyfile, identifier,
460 "Tethering", &error);
462 technology->tethering_persistent = enable;
465 g_clear_error(&error);
469 technology_save(technology);
471 technology->tethering_ident = g_key_file_get_string(keyfile,
472 identifier, "Tethering.Identifier", NULL);
474 technology->tethering_passphrase = g_key_file_get_string(keyfile,
475 identifier, "Tethering.Passphrase", NULL);
479 g_key_file_free(keyfile);
482 bool __connman_technology_get_offlinemode(void)
484 return global_offlinemode;
487 static void connman_technology_save_offlinemode(void)
490 GError *error = NULL;
493 keyfile = __connman_storage_load_global();
496 keyfile = g_key_file_new();
497 g_key_file_set_boolean(keyfile, "global",
498 "OfflineMode", global_offlinemode);
500 __connman_storage_save_global(keyfile);
503 offlinemode = g_key_file_get_boolean(keyfile, "global",
504 "OfflineMode", &error);
506 if (error || offlinemode != global_offlinemode) {
507 g_key_file_set_boolean(keyfile, "global",
508 "OfflineMode", global_offlinemode);
510 g_clear_error(&error);
512 __connman_storage_save_global(keyfile);
516 g_key_file_free(keyfile);
519 static bool connman_technology_load_offlinemode(void)
522 GError *error = NULL;
525 /* If there is a error, we enable offlinemode */
526 keyfile = __connman_storage_load_global();
530 offlinemode = g_key_file_get_boolean(keyfile, "global",
531 "OfflineMode", &error);
534 g_clear_error(&error);
537 g_key_file_free(keyfile);
542 static void append_properties(DBusMessageIter *iter,
543 struct connman_technology *technology)
545 DBusMessageIter dict;
549 connman_dbus_dict_open(iter, &dict);
551 str = get_name(technology->type);
553 connman_dbus_dict_append_basic(&dict, "Name",
554 DBUS_TYPE_STRING, &str);
556 str = __connman_service_type2string(technology->type);
558 connman_dbus_dict_append_basic(&dict, "Type",
559 DBUS_TYPE_STRING, &str);
561 __sync_synchronize();
562 val = technology->enabled;
563 connman_dbus_dict_append_basic(&dict, "Powered",
567 val = technology->connected;
568 connman_dbus_dict_append_basic(&dict, "Connected",
572 val = technology->tethering;
573 connman_dbus_dict_append_basic(&dict, "Tethering",
577 if (technology->tethering_ident)
578 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
580 &technology->tethering_ident);
582 if (technology->tethering_passphrase)
583 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
585 &technology->tethering_passphrase);
587 connman_dbus_dict_close(iter, &dict);
590 static void technology_added_signal(struct connman_technology *technology)
593 DBusMessageIter iter;
595 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
596 CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
600 dbus_message_iter_init_append(signal, &iter);
601 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
603 append_properties(&iter, technology);
605 dbus_connection_send(connection, signal, NULL);
606 dbus_message_unref(signal);
609 static void technology_removed_signal(struct connman_technology *technology)
611 g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
612 CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
613 DBUS_TYPE_OBJECT_PATH, &technology->path,
617 static DBusMessage *get_properties(DBusConnection *conn,
618 DBusMessage *message, void *user_data)
620 struct connman_technology *technology = user_data;
622 DBusMessageIter iter;
624 reply = dbus_message_new_method_return(message);
628 dbus_message_iter_init_append(reply, &iter);
629 append_properties(&iter, technology);
634 void __connman_technology_list_struct(DBusMessageIter *array)
637 DBusMessageIter entry;
639 for (list = technology_list; list; list = list->next) {
640 struct connman_technology *technology = list->data;
642 if (!technology->path ||
643 (technology->rfkill_driven &&
644 technology->hardblocked))
647 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
649 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
651 append_properties(&entry, technology);
652 dbus_message_iter_close_container(array, &entry);
656 static gboolean technology_pending_reply(gpointer user_data)
658 struct connman_technology *technology = user_data;
661 /* Power request timed out, send ETIMEDOUT. */
662 if (technology->pending_reply) {
663 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
665 g_dbus_send_message(connection, reply);
667 dbus_message_unref(technology->pending_reply);
668 technology->pending_reply = NULL;
669 technology->pending_timeout = 0;
675 static int technology_affect_devices(struct connman_technology *technology,
678 int err = 0, err_dev;
681 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
683 __connman_technology_enabled(technology->type);
685 __connman_technology_disabled(technology->type);
689 #if defined TIZEN_EXT_WIFI_MESH
690 if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
694 for (list = technology->device_list; list; list = list->next) {
695 struct connman_device *device = list->data;
698 err_dev = __connman_device_enable(device);
700 err_dev = __connman_device_disable(device);
702 if (err_dev < 0 && err_dev != -EALREADY)
709 static void powered_changed(struct connman_technology *technology)
713 if (!technology->dbus_registered)
716 if (technology->pending_reply) {
717 g_dbus_send_reply(connection,
718 technology->pending_reply, DBUS_TYPE_INVALID);
719 dbus_message_unref(technology->pending_reply);
720 technology->pending_reply = NULL;
722 g_source_remove(technology->pending_timeout);
723 technology->pending_timeout = 0;
726 __sync_synchronize();
727 enabled = technology->enabled;
728 #if defined TIZEN_EXT
729 DBG("ConnMan, Powered : %s, %s",
730 enabled ? "TRUE" : "FALSE",technology->path);
732 connman_dbus_property_changed_basic(technology->path,
733 CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
734 DBUS_TYPE_BOOLEAN, &enabled);
737 static void enable_tethering(struct connman_technology *technology)
741 if (!connman_setting_get_bool("PersistentTetheringMode"))
744 ret = set_tethering(technology, true);
745 if (ret < 0 && ret != -EALREADY)
746 DBG("Cannot enable tethering yet for %s (%d/%s)",
747 get_name(technology->type),
748 -ret, strerror(-ret));
751 static int technology_enabled(struct connman_technology *technology)
753 __sync_synchronize();
754 if (technology->enabled)
757 technology->enabled = true;
759 if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
760 struct connman_technology *p2p;
762 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
763 if (p2p && !p2p->enabled && p2p->enable_persistent)
764 technology_enabled(p2p);
767 if (technology->tethering_persistent)
768 enable_tethering(technology);
770 powered_changed(technology);
775 static int technology_enable(struct connman_technology *technology)
780 DBG("technology %p enable", technology);
782 __sync_synchronize();
784 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
785 struct connman_technology *wifi;
787 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
788 if (wifi && wifi->enabled)
789 return technology_enabled(technology);
793 if (technology->enabled)
796 if (technology->pending_reply)
799 if (connman_setting_get_bool("PersistentTetheringMode") &&
800 technology->tethering)
801 set_tethering(technology, true);
803 if (technology->rfkill_driven)
804 err = __connman_rfkill_block(technology->type, false);
806 err_dev = technology_affect_devices(technology, true);
808 if (!technology->rfkill_driven)
814 static int technology_disabled(struct connman_technology *technology)
816 __sync_synchronize();
817 if (!technology->enabled)
820 technology->enabled = false;
822 powered_changed(technology);
827 static int technology_disable(struct connman_technology *technology)
831 DBG("technology %p disable", technology);
833 __sync_synchronize();
835 if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
836 technology->enable_persistent = false;
837 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
838 __connman_peer_disconnect_all();
839 return technology_disabled(technology);
840 } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
841 struct connman_technology *p2p;
843 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
844 if (p2p && p2p->enabled) {
845 p2p->enable_persistent = true;
846 technology_disabled(p2p);
850 if (!technology->enabled)
853 if (technology->pending_reply)
856 if (technology->tethering)
857 set_tethering(technology, false);
859 err = technology_affect_devices(technology, false);
861 if (technology->rfkill_driven)
862 err = __connman_rfkill_block(technology->type, true);
867 static DBusMessage *set_powered(struct connman_technology *technology,
868 DBusMessage *msg, bool powered)
870 DBusMessage *reply = NULL;
873 if (technology->rfkill_driven && technology->hardblocked) {
879 err = technology_enable(technology);
881 err = technology_disable(technology);
884 technology->enable_persistent = powered;
885 technology_save(technology);
889 if (err == -EINPROGRESS) {
890 technology->pending_reply = dbus_message_ref(msg);
891 technology->pending_timeout = g_timeout_add_seconds(10,
892 technology_pending_reply, technology);
893 } else if (err == -EALREADY) {
895 reply = __connman_error_already_enabled(msg);
897 reply = __connman_error_already_disabled(msg);
899 reply = __connman_error_failed(msg, -err);
901 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
906 #if defined TIZEN_EXT
907 int set_connman_bssid(enum bssid_type mode, char *bssid)
909 static unsigned char bssid_for_connect[6];
910 static int bssid_len;
912 DBG("mode : %d", mode);
914 if (mode == CHECK_BSSID) {
918 if (mode == GET_BSSID && bssid) {
919 memcpy(bssid, bssid_for_connect, 6);
923 if (mode == RESET_BSSID) {
928 if (mode != SET_BSSID || !bssid) {
929 DBG("Invalid parameter");
933 bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
934 &bssid_for_connect[0], &bssid_for_connect[1], &bssid_for_connect[2],
935 &bssid_for_connect[3], &bssid_for_connect[4], &bssid_for_connect[5]);
936 if (bssid_len != 6) {
937 DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
941 DBG("SET BSSID len : %d, BSSID : %02x:%02x:%02x:%02x:%02x:%02x", bssid_len,
942 bssid_for_connect[0], bssid_for_connect[1], bssid_for_connect[2],
943 bssid_for_connect[3], bssid_for_connect[4], bssid_for_connect[5]);
949 static DBusMessage *set_property(DBusConnection *conn,
950 DBusMessage *msg, void *data)
952 struct connman_technology *technology = data;
953 DBusMessageIter iter, value;
957 DBG("conn %p", conn);
959 if (!dbus_message_iter_init(msg, &iter))
960 return __connman_error_invalid_arguments(msg);
962 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
963 return __connman_error_invalid_arguments(msg);
965 dbus_message_iter_get_basic(&iter, &name);
966 dbus_message_iter_next(&iter);
968 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
969 return __connman_error_invalid_arguments(msg);
971 dbus_message_iter_recurse(&iter, &value);
973 type = dbus_message_iter_get_arg_type(&value);
975 DBG("property %s", name);
977 if (g_str_equal(name, "Tethering")) {
978 dbus_bool_t tethering;
981 if (type != DBUS_TYPE_BOOLEAN)
982 return __connman_error_invalid_arguments(msg);
984 if (!connman_technology_is_tethering_allowed(technology->type)) {
985 DBG("%s tethering not allowed by config file",
986 __connman_service_type2string(technology->type));
987 return __connman_error_not_supported(msg);
990 dbus_message_iter_get_basic(&value, &tethering);
992 if (technology->tethering == tethering) {
994 return __connman_error_already_disabled(msg);
996 return __connman_error_already_enabled(msg);
999 err = set_tethering(technology, tethering);
1001 return __connman_error_failed(msg, -err);
1003 technology->tethering_persistent = tethering;
1005 technology_save(technology);
1007 } else if (g_str_equal(name, "TetheringIdentifier")) {
1010 dbus_message_iter_get_basic(&value, &str);
1012 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1013 return __connman_error_not_supported(msg);
1015 if (strlen(str) < 1 || strlen(str) > 32)
1016 return __connman_error_invalid_arguments(msg);
1018 if (g_strcmp0(technology->tethering_ident, str) != 0) {
1019 g_free(technology->tethering_ident);
1020 technology->tethering_ident = g_strdup(str);
1021 technology_save(technology);
1023 connman_dbus_property_changed_basic(technology->path,
1024 CONNMAN_TECHNOLOGY_INTERFACE,
1025 "TetheringIdentifier",
1027 &technology->tethering_ident);
1029 } else if (g_str_equal(name, "TetheringPassphrase")) {
1032 dbus_message_iter_get_basic(&value, &str);
1034 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
1035 return __connman_error_not_supported(msg);
1037 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
1040 return __connman_error_passphrase_required(msg);
1042 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
1043 g_free(technology->tethering_passphrase);
1044 technology->tethering_passphrase = g_strdup(str);
1045 technology_save(technology);
1047 connman_dbus_property_changed_basic(technology->path,
1048 CONNMAN_TECHNOLOGY_INTERFACE,
1049 "TetheringPassphrase",
1051 &technology->tethering_passphrase);
1053 } else if (g_str_equal(name, "Powered")) {
1056 if (type != DBUS_TYPE_BOOLEAN)
1057 return __connman_error_invalid_arguments(msg);
1059 dbus_message_iter_get_basic(&value, &enable);
1061 return set_powered(technology, msg, enable);
1062 #if defined TIZEN_EXT
1063 } else if (g_str_equal(name, "SetBSSID")) {
1066 if (type != DBUS_TYPE_STRING)
1067 return __connman_error_invalid_arguments(msg);
1069 dbus_message_iter_get_basic(&value, &key);
1070 DBG("BSSID %s", key);
1071 set_connman_bssid(SET_BSSID, key);
1074 return __connman_error_invalid_property(msg);
1076 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1079 static void reply_scan_pending(struct connman_technology *technology, int err)
1083 DBG("technology %p err %d", technology, err);
1085 while (technology->scan_pending) {
1086 DBusMessage *msg = technology->scan_pending->data;
1088 DBG("reply to %s", dbus_message_get_sender(msg));
1091 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1093 reply = __connman_error_failed(msg, -err);
1094 g_dbus_send_message(connection, reply);
1095 dbus_message_unref(msg);
1097 technology->scan_pending =
1098 g_slist_delete_link(technology->scan_pending,
1099 technology->scan_pending);
1103 #if defined TIZEN_EXT
1104 dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
1107 DBusMessage *signal;
1108 DBusMessageIter iter;
1109 dbus_bool_t result = FALSE;
1111 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1112 CONNMAN_MANAGER_INTERFACE, "ScanChanged");
1116 dbus_message_iter_init_append(signal, &iter);
1117 connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
1119 result = dbus_connection_send(connection, signal, NULL);
1120 dbus_message_unref(signal);
1122 DBG("Successfuly sent signal");
1128 void __connman_technology_scan_started(struct connman_device *device)
1130 DBG("device %p", device);
1131 #if defined TIZEN_EXT
1132 dbus_bool_t status = 1;
1133 __connman_technology_notify_scan_changed("scan_started", &status);
1137 void __connman_technology_scan_stopped(struct connman_device *device,
1138 enum connman_service_type type)
1141 struct connman_technology *technology;
1144 technology = technology_find(type);
1146 DBG("technology %p device %p", technology, device);
1151 for (list = technology->device_list; list; list = list->next) {
1152 struct connman_device *other_device = list->data;
1154 if (device == other_device)
1157 if (connman_device_get_scanning(other_device, type))
1161 #if defined TIZEN_EXT
1163 DBusMessage *signal;
1164 DBusMessageIter iter;
1165 dbus_bool_t status = 0;
1166 __connman_technology_notify_scan_changed("scan_done", &status);
1168 signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
1169 CONNMAN_MANAGER_INTERFACE, "ScanDone");
1173 dbus_message_iter_init_append(signal, &iter);
1174 connman_dbus_property_append_basic(&iter, "Scantype",
1175 DBUS_TYPE_INT32, &g_scan_type);
1177 dbus_connection_send(connection, signal, NULL);
1178 dbus_message_unref(signal);
1179 reply_scan_pending(technology, 0);
1181 DBG("Successfuly sent ScanDone signal");
1185 reply_scan_pending(technology, 0);
1189 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1190 int result, const char *alpha2)
1192 bool regdom_set = false;
1193 struct connman_technology *technology;
1194 enum connman_service_type type;
1195 GSList *tech_drivers;
1197 type = __connman_device_get_service_type(device);
1198 technology = technology_find(type);
1205 for (tech_drivers = technology->driver_list;
1207 tech_drivers = g_slist_next(tech_drivers)) {
1208 struct connman_technology_driver *driver =
1211 if (driver->set_regdom) {
1212 driver->set_regdom(technology, alpha2);
1222 connman_technology_regdom_notify(technology, alpha2);
1225 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1227 struct connman_technology *technology = data;
1230 DBG("technology %p request from %s", technology,
1231 dbus_message_get_sender(msg));
1233 if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1234 !technology->enabled)
1235 return __connman_error_permission_denied(msg);
1237 dbus_message_ref(msg);
1238 #if !defined TIZEN_EXT
1239 technology->scan_pending =
1240 g_slist_prepend(technology->scan_pending, msg);
1243 err = __connman_device_request_scan_full(technology->type);
1245 #if defined TIZEN_EXT
1246 return __connman_error_failed(msg, -err);
1248 reply_scan_pending(technology, err);
1251 #if defined TIZEN_EXT
1253 g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
1254 DBG("g_scan_type %d", g_scan_type);
1256 technology->scan_pending =
1257 g_slist_prepend(technology->scan_pending, msg);
1262 #if defined TIZEN_EXT
1263 static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
1265 struct connman_technology *technology = data;
1266 GSList *specific_scan_list = NULL;
1268 const char *name = NULL;
1269 const char *freq = NULL;
1270 DBusMessageIter iter, dict;
1273 DBG("technology %p request from %s", technology,
1274 dbus_message_get_sender(msg));
1276 if (!dbus_message_iter_init(msg, &iter))
1277 return __connman_error_invalid_arguments(msg);
1279 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1280 return __connman_error_invalid_arguments(msg);
1282 dbus_message_iter_recurse(&iter, &dict);
1283 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1284 DBusMessageIter entry, value2;
1288 dbus_message_iter_recurse(&dict, &entry);
1289 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
1290 g_slist_free_full(specific_scan_list, g_free);
1291 return __connman_error_invalid_arguments(msg);
1294 dbus_message_iter_get_basic(&entry, &key);
1295 dbus_message_iter_next(&entry);
1297 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
1298 g_slist_free_full(specific_scan_list, g_free);
1299 return __connman_error_invalid_arguments(msg);
1302 dbus_message_iter_recurse(&entry, &value2);
1303 type = dbus_message_iter_get_arg_type(&value2);
1304 if (g_str_equal(key, "SSID")) {
1305 if (type != DBUS_TYPE_STRING) {
1306 g_slist_free_full(specific_scan_list, g_free);
1307 return __connman_error_invalid_arguments(msg);
1310 scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
1311 dbus_message_iter_get_basic(&value2, &name);
1312 DBG("name %s", name);
1313 specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
1314 } else if (g_str_equal(key, "Frequency")) {
1315 if (type != DBUS_TYPE_STRING) {
1316 g_slist_free_full(specific_scan_list, g_free);
1317 return __connman_error_invalid_arguments(msg);
1320 scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
1321 dbus_message_iter_get_basic(&value2, &freq);
1322 DBG("freq %s", freq);
1323 specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
1324 } else if (g_str_equal(key, "SSID_Mixed")) {
1325 if (type != DBUS_TYPE_STRING) {
1326 g_slist_free_full(specific_scan_list, g_free);
1327 return __connman_error_invalid_arguments(msg);
1330 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1331 dbus_message_iter_get_basic(&value2, &name);
1333 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1335 g_strlcpy(ap->str, name, strlen(name) + 1);
1337 specific_scan_list = g_slist_append(specific_scan_list, ap);
1339 DBG("Failed to allocate memory");
1341 } else if (g_str_equal(key, "Frequency_Mixed")) {
1342 if (type != DBUS_TYPE_STRING) {
1343 g_slist_free_full(specific_scan_list, g_free);
1344 return __connman_error_invalid_arguments(msg);
1347 scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
1348 dbus_message_iter_get_basic(&value2, &freq);
1350 connman_multi_scan_ap_s *ap = (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
1352 g_strlcpy(ap->str, freq, strlen(freq) + 1);
1354 specific_scan_list = g_slist_append(specific_scan_list, ap);
1356 DBG("Failed to allocate memory");
1358 dbus_message_iter_next(&dict);
1361 dbus_message_ref(msg);
1363 err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
1365 return __connman_error_failed(msg, -err);
1368 guint list_size = g_slist_length(specific_scan_list);
1370 g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
1372 g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
1373 DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
1375 technology->scan_pending =
1376 g_slist_prepend(technology->scan_pending, msg);
1378 if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
1379 scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) {
1380 g_slist_free_full(specific_scan_list, g_free);
1386 #if defined TIZEN_EXT
1387 static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
1390 DBusMessageIter iter, dict;
1391 struct connman_technology *technology = data;
1392 dbus_bool_t supported = technology->is_5_0_ghz_supported;
1394 DBG("technology %p", technology);
1396 reply = dbus_message_new_method_return(msg);
1400 dbus_message_iter_init_append(reply, &iter);
1402 connman_dbus_dict_open(&iter, &dict);
1403 connman_dbus_dict_append_basic(&dict, "Is5GhzSupported",
1407 connman_dbus_dict_close(&iter, &dict);
1413 static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
1416 DBusMessageIter iter, dict;
1418 struct connman_technology *technology = data;
1419 dbus_bool_t scanning = false;
1421 DBG("technology %p", technology);
1423 for (list = technology->device_list; list; list = list->next) {
1424 struct connman_device *device = list->data;
1425 scanning = connman_device_get_scanning(device,
1426 connman_device_get_type(device));
1431 DBG("scanning : %d", scanning);
1432 reply = dbus_message_new_method_return(msg);
1436 dbus_message_iter_init_append(reply, &iter);
1438 connman_dbus_dict_open(&iter, &dict);
1439 connman_dbus_dict_append_basic(&dict, "Scanstate",
1443 connman_dbus_dict_close(&iter, &dict);
1448 void connman_techonology_set_max_scan_ssids(struct connman_technology *technology,
1452 technology->max_scan_ssids = max_scan_ssids;
1455 static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
1458 DBusMessageIter iter, dict;
1459 struct connman_technology *technology = data;
1460 dbus_int32_t max_scan_ssids = technology->max_scan_ssids;
1462 DBG("technology %p", technology);
1464 reply = dbus_message_new_method_return(msg);
1468 dbus_message_iter_init_append(reply, &iter);
1470 connman_dbus_dict_open(&iter, &dict);
1471 connman_dbus_dict_append_basic(&dict, "MaxScanSSID",
1475 connman_dbus_dict_close(&iter, &dict);
1481 #if defined TIZEN_EXT_WIFI_MESH
1482 bool __connman_technology_get_connected(enum connman_service_type type)
1484 struct connman_technology *technology;
1486 technology = technology_find(type);
1491 return technology->connected;
1494 void __connman_technology_mesh_interface_create_finished(
1495 enum connman_service_type type, bool success,
1499 struct connman_technology *technology;
1501 technology = technology_find(type);
1503 DBG("technology %p success %d", technology, success);
1508 msg = technology->mesh_dbus_msg;
1510 DBG("No pending dbus message");
1515 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1516 __connman_device_request_scan(technology->type);
1518 reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
1519 ".MeshInterfaceAddFailed", "%s", error);
1520 g_dbus_send_message(connection, reply);
1521 dbus_message_unref(msg);
1522 technology->mesh_dbus_msg = NULL;
1525 void __connman_technology_mesh_interface_remove_finished(
1526 enum connman_service_type type, bool success)
1529 struct connman_technology *technology;
1531 technology = technology_find(type);
1533 DBG("technology %p success %d", technology, success);
1535 if (!technology || !technology->mesh_dbus_msg)
1538 msg = technology->mesh_dbus_msg;
1540 DBG("No pending dbus message");
1545 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1547 reply = __connman_error_failed(msg, EINVAL);
1548 g_dbus_send_message(connection, reply);
1549 dbus_message_unref(msg);
1550 technology->mesh_dbus_msg = NULL;
1553 void __connman_technology_notify_abort_scan(enum connman_service_type type,
1557 struct connman_technology *technology;
1559 technology = technology_find(type);
1561 DBG("technology %p result %d", technology, result);
1563 if (!technology || !technology->mesh_dbus_msg)
1566 msg = technology->mesh_dbus_msg;
1568 DBG("No pending dbus message");
1573 reply = __connman_error_scan_abort_failed(msg);
1575 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1577 g_dbus_send_message(connection, reply);
1578 dbus_message_unref(msg);
1579 technology->mesh_dbus_msg = NULL;
1582 static DBusMessage *mesh_commands(DBusConnection *conn,
1583 DBusMessage *msg, void *data)
1585 struct connman_technology *technology = data;
1586 DBusMessageIter iter, value, dict;
1587 const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
1590 DBG("conn %p", conn);
1592 if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
1593 return __connman_error_invalid_arguments(msg);
1595 if (!dbus_message_iter_init(msg, &iter))
1596 return __connman_error_invalid_arguments(msg);
1598 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1599 return __connman_error_invalid_arguments(msg);
1601 dbus_message_iter_get_basic(&iter, &cmd);
1602 dbus_message_iter_next(&iter);
1604 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1605 return __connman_error_invalid_arguments(msg);
1607 dbus_message_iter_recurse(&iter, &value);
1609 if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
1610 return __connman_error_invalid_arguments(msg);
1612 DBG("Mesh Command %s", cmd);
1613 if (g_str_equal(cmd, "MeshInterfaceAdd")) {
1614 dbus_message_iter_recurse(&value, &dict);
1615 const char *bridge_ifname = NULL;
1616 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1617 DBusMessageIter entry, value2;
1621 dbus_message_iter_recurse(&dict, &entry);
1623 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1624 return __connman_error_invalid_arguments(msg);
1626 dbus_message_iter_get_basic(&entry, &key);
1627 dbus_message_iter_next(&entry);
1629 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1630 return __connman_error_invalid_arguments(msg);
1632 dbus_message_iter_recurse(&entry, &value2);
1634 type = dbus_message_iter_get_arg_type(&value2);
1636 if (g_str_equal(key, "Ifname")) {
1637 if (type != DBUS_TYPE_STRING)
1638 return __connman_error_invalid_arguments(msg);
1640 dbus_message_iter_get_basic(&value2, &ifname);
1641 } else if (g_str_equal(key, "ParentIfname")) {
1642 if (type != DBUS_TYPE_STRING)
1643 return __connman_error_invalid_arguments(msg);
1645 dbus_message_iter_get_basic(&value2, &parent_ifname);
1646 } else if (g_str_equal(key, "BridgeIfname")) {
1647 if (type != DBUS_TYPE_STRING)
1648 return __connman_error_invalid_arguments(msg);
1650 dbus_message_iter_get_basic(&value2, &bridge_ifname);
1652 dbus_message_iter_next(&dict);
1654 DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
1655 bridge_ifname ? bridge_ifname : "NULL");
1656 err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
1660 DBG("Failed to add virtual mesh interface");
1661 return __connman_error_failed(msg, -err);
1664 DBG("Successfully added virtual mesh interface");
1666 dbus_message_ref(msg);
1667 technology->mesh_dbus_msg = msg;
1669 } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
1670 dbus_message_iter_recurse(&value, &dict);
1671 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1672 DBusMessageIter entry, value2;
1676 dbus_message_iter_recurse(&dict, &entry);
1678 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1679 return __connman_error_invalid_arguments(msg);
1681 dbus_message_iter_get_basic(&entry, &key);
1682 dbus_message_iter_next(&entry);
1684 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1685 return __connman_error_invalid_arguments(msg);
1687 dbus_message_iter_recurse(&entry, &value2);
1689 type = dbus_message_iter_get_arg_type(&value2);
1691 if (g_str_equal(key, "Ifname")) {
1692 if (type != DBUS_TYPE_STRING)
1693 return __connman_error_invalid_arguments(msg);
1695 dbus_message_iter_get_basic(&value2, &ifname);
1697 dbus_message_iter_next(&dict);
1699 DBG("Mesh Ifname %s", ifname);
1700 err = __connman_mesh_remove_virtual_interface(ifname);
1703 DBG("Failed to remove virtual mesh interface");
1704 return __connman_error_failed(msg, -err);
1707 DBG("Successfully removed virtual mesh interface");
1709 dbus_message_ref(msg);
1710 technology->mesh_dbus_msg = msg;
1712 } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
1713 struct connman_mesh *connman_mesh;
1714 const char *name = NULL;
1715 const char *sec_type = NULL;
1716 const char *mesh_ifname = NULL;
1717 char *identifier, *group, *address;
1718 unsigned int freq = 0;
1719 unsigned int ieee80211w = 0;
1722 dbus_message_iter_recurse(&value, &dict);
1723 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1724 DBusMessageIter entry, value2;
1728 dbus_message_iter_recurse(&dict, &entry);
1730 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1731 return __connman_error_invalid_arguments(msg);
1733 dbus_message_iter_get_basic(&entry, &key);
1734 dbus_message_iter_next(&entry);
1736 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1737 return __connman_error_invalid_arguments(msg);
1739 dbus_message_iter_recurse(&entry, &value2);
1741 type = dbus_message_iter_get_arg_type(&value2);
1743 if (g_str_equal(key, "Name")) {
1744 if (type != DBUS_TYPE_STRING)
1745 return __connman_error_invalid_arguments(msg);
1747 dbus_message_iter_get_basic(&value2, &name);
1748 } else if (g_str_equal(key, "Frequency")) {
1749 if (type != DBUS_TYPE_UINT16)
1750 return __connman_error_invalid_arguments(msg);
1752 dbus_message_iter_get_basic(&value2, &freq);
1753 } else if (g_str_equal(key, "Security")) {
1754 if (type != DBUS_TYPE_STRING)
1755 return __connman_error_invalid_arguments(msg);
1757 dbus_message_iter_get_basic(&value2, &sec_type);
1758 } else if (g_str_equal(key, "Pmf")) {
1759 if (type != DBUS_TYPE_UINT16)
1760 return __connman_error_invalid_arguments(msg);
1762 dbus_message_iter_get_basic(&value2, &ieee80211w);
1764 dbus_message_iter_next(&dict);
1767 if (name == NULL || sec_type == NULL || freq == 0)
1768 return __connman_error_invalid_arguments(msg);
1770 DBG("Name %s Frequency %d Security type %s Pmf %u",
1771 name, freq, sec_type, ieee80211w);
1773 if (g_strcmp0(sec_type, "none") != 0 &&
1774 g_strcmp0(sec_type, "sae") != 0) {
1775 DBG("Unsupported security");
1776 return __connman_error_invalid_arguments(msg);
1779 mesh_ifname = connman_mesh_get_interface_name();
1781 if (!connman_mesh_is_interface_created()) {
1782 DBG("Mesh interface doesn't exists");
1783 return __connman_error_invalid_command(msg);
1786 str = g_string_sized_new((strlen(name) * 2) + 24);
1788 for (i = 0; name[i]; i++)
1789 g_string_append_printf(str, "%02x", name[i]);
1791 g_string_append_printf(str, "_mesh");
1793 if (g_strcmp0(sec_type, "none") == 0)
1794 g_string_append_printf(str, "_none");
1795 else if (g_strcmp0(sec_type, "sae") == 0)
1796 g_string_append_printf(str, "_sae");
1798 group = g_string_free(str, FALSE);
1800 identifier = connman_inet_ifaddr(mesh_ifname);
1801 address = connman_inet_ifname2addr(mesh_ifname);
1803 connman_mesh = connman_mesh_create(identifier, group);
1804 connman_mesh_set_name(connman_mesh, name);
1805 connman_mesh_set_address(connman_mesh, address);
1806 connman_mesh_set_security(connman_mesh, sec_type);
1807 connman_mesh_set_frequency(connman_mesh, freq);
1808 connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
1809 connman_mesh_set_peer_type(connman_mesh,
1810 CONNMAN_MESH_PEER_TYPE_CREATED);
1811 connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
1813 connman_mesh_register(connman_mesh);
1817 DBG("Successfully Created Mesh Network");
1818 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1820 } else if (g_str_equal(cmd, "AbortScan")) {
1821 DBG("Abort Scan method");
1822 err = __connman_device_abort_scan(technology->type);
1824 DBG("Failed to abort scan");
1825 return __connman_error_failed(msg, -err);
1828 DBG("Successfully requested to abort scan");
1829 dbus_message_ref(msg);
1830 technology->mesh_dbus_msg = msg;
1832 } else if (g_str_equal(cmd, "MeshSpecificScan")) {
1833 const char *name = NULL;
1834 unsigned int freq = 0;
1835 dbus_message_iter_recurse(&value, &dict);
1836 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1837 DBusMessageIter entry, value2;
1841 dbus_message_iter_recurse(&dict, &entry);
1843 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1844 return __connman_error_invalid_arguments(msg);
1846 dbus_message_iter_get_basic(&entry, &key);
1847 dbus_message_iter_next(&entry);
1849 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1850 return __connman_error_invalid_arguments(msg);
1852 dbus_message_iter_recurse(&entry, &value2);
1854 type = dbus_message_iter_get_arg_type(&value2);
1856 if (g_str_equal(key, "Name")) {
1857 if (type != DBUS_TYPE_STRING)
1858 return __connman_error_invalid_arguments(msg);
1860 dbus_message_iter_get_basic(&value2, &name);
1861 } else if (g_str_equal(key, "Frequency")) {
1862 if (type != DBUS_TYPE_UINT16)
1863 return __connman_error_invalid_arguments(msg);
1865 dbus_message_iter_get_basic(&value2, &freq);
1867 dbus_message_iter_next(&dict);
1870 DBG("MeshID %s Frequency %d sender %s", name, freq,
1871 dbus_message_get_sender(msg));
1873 dbus_message_ref(msg);
1874 technology->scan_pending =
1875 g_slist_prepend(technology->scan_pending, msg);
1877 err = __connman_device_request_mesh_specific_scan(technology->type,
1880 reply_scan_pending(technology, err);
1882 DBG("Successfully requested to scan specific Mesh Network");
1884 } else if (g_str_equal(cmd, "SetMeshGate")) {
1885 unsigned int hwmp_rootmode = 0;
1886 bool gate_announce = false;
1887 unsigned int stp = 0;
1889 dbus_message_iter_recurse(&value, &dict);
1890 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1891 DBusMessageIter entry, value2;
1895 dbus_message_iter_recurse(&dict, &entry);
1897 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
1898 return __connman_error_invalid_arguments(msg);
1900 dbus_message_iter_get_basic(&entry, &key);
1901 dbus_message_iter_next(&entry);
1903 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
1904 return __connman_error_invalid_arguments(msg);
1906 dbus_message_iter_recurse(&entry, &value2);
1908 type = dbus_message_iter_get_arg_type(&value2);
1910 if (g_str_equal(key, "GateAnnounce")) {
1911 if (type != DBUS_TYPE_BOOLEAN)
1912 return __connman_error_invalid_arguments(msg);
1914 dbus_message_iter_get_basic(&value2, &gate_announce);
1915 } else if (g_str_equal(key, "HWMPRootMode")) {
1916 if (type != DBUS_TYPE_UINT16)
1917 return __connman_error_invalid_arguments(msg);
1919 dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
1920 } else if (g_str_equal(key, "STP")) {
1921 if (type != DBUS_TYPE_UINT16)
1922 return __connman_error_invalid_arguments(msg);
1924 dbus_message_iter_get_basic(&value2, &stp);
1926 dbus_message_iter_next(&dict);
1929 DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
1930 gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
1932 err = __connman_mesh_set_stp_gate_announce(gate_announce,
1937 return __connman_error_failed(msg, -err);
1939 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1941 return __connman_error_invalid_command(msg);
1946 static const GDBusMethodTable technology_methods[] = {
1947 { GDBUS_DEPRECATED_METHOD("GetProperties",
1948 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1950 { GDBUS_ASYNC_METHOD("SetProperty",
1951 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1952 NULL, set_property) },
1953 { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1954 #if defined TIZEN_EXT
1955 { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
1956 NULL, specific_scan) },
1957 { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
1959 { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
1960 get_5ghz_supported) },
1961 { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
1962 get_max_scan_ssid) },
1964 #if defined TIZEN_EXT_WIFI_MESH
1965 { GDBUS_ASYNC_METHOD("MeshCommands",
1966 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1967 NULL, mesh_commands) },
1972 static const GDBusSignalTable technology_signals[] = {
1973 { GDBUS_SIGNAL("PropertyChanged",
1974 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1978 static bool technology_dbus_register(struct connman_technology *technology)
1980 if (technology->dbus_registered ||
1981 (technology->rfkill_driven &&
1982 technology->hardblocked))
1985 if (!g_dbus_register_interface(connection, technology->path,
1986 CONNMAN_TECHNOLOGY_INTERFACE,
1987 technology_methods, technology_signals,
1988 NULL, technology, NULL)) {
1989 connman_error("Failed to register %s", technology->path);
1993 technology_added_signal(technology);
1994 technology->dbus_registered = true;
1999 static void technology_dbus_unregister(struct connman_technology *technology)
2001 if (!technology->dbus_registered)
2004 technology_removed_signal(technology);
2005 g_dbus_unregister_interface(connection, technology->path,
2006 CONNMAN_TECHNOLOGY_INTERFACE);
2008 technology->dbus_registered = false;
2011 static void technology_put(struct connman_technology *technology)
2013 DBG("technology %p", technology);
2015 if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
2018 reply_scan_pending(technology, -EINTR);
2020 while (technology->driver_list) {
2021 struct connman_technology_driver *driver;
2023 driver = technology->driver_list->data;
2026 driver->remove(technology);
2028 technology->driver_list =
2029 g_slist_delete_link(technology->driver_list,
2030 technology->driver_list);
2033 technology_list = g_slist_remove(technology_list, technology);
2035 technology_dbus_unregister(technology);
2037 g_slist_free(technology->device_list);
2039 if (technology->pending_reply) {
2040 dbus_message_unref(technology->pending_reply);
2041 technology->pending_reply = NULL;
2042 g_source_remove(technology->pending_timeout);
2043 technology->pending_timeout = 0;
2046 g_free(technology->path);
2047 g_free(technology->regdom);
2048 g_free(technology->tethering_ident);
2049 g_free(technology->tethering_passphrase);
2053 static struct connman_technology *technology_get(enum connman_service_type type)
2055 GSList *tech_drivers = NULL;
2056 struct connman_technology_driver *driver;
2057 struct connman_technology *technology;
2061 DBG("type %d", type);
2063 str = __connman_service_type2string(type);
2067 technology = technology_find(type);
2069 #if defined TIZEN_EXT_WIFI_MESH
2070 if (type != CONNMAN_SERVICE_TYPE_P2P &&
2071 type != CONNMAN_SERVICE_TYPE_MESH)
2073 if (type != CONNMAN_SERVICE_TYPE_P2P)
2075 __sync_fetch_and_add(&technology->refcount, 1);
2079 /* First check if we have a driver for this technology type */
2080 for (list = driver_list; list; list = list->next) {
2081 driver = list->data;
2083 if (driver->type == type) {
2084 DBG("technology %p driver %p", technology, driver);
2085 tech_drivers = g_slist_append(tech_drivers, driver);
2089 if (!tech_drivers) {
2090 DBG("No matching drivers found for %s.",
2091 __connman_service_type2string(type));
2095 technology = g_try_new0(struct connman_technology, 1);
2099 technology->refcount = 1;
2100 technology->type = type;
2101 technology->path = g_strdup_printf("%s/technology/%s",
2104 #if defined TIZEN_EXT_WIFI_MESH
2105 if (type == CONNMAN_SERVICE_TYPE_MESH) {
2106 struct connman_technology *wifi;
2108 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2110 technology->enabled = wifi->enabled;
2114 technology_load(technology);
2115 technology_list = g_slist_prepend(technology_list, technology);
2116 technology->driver_list = tech_drivers;
2118 for (list = tech_drivers; list; list = list->next) {
2119 driver = list->data;
2121 if (driver->probe && driver->probe(technology) < 0)
2122 DBG("Driver probe failed for technology %p",
2126 if (!technology_dbus_register(technology)) {
2127 technology_put(technology);
2131 if (type == CONNMAN_SERVICE_TYPE_P2P) {
2132 struct connman_technology *wifi;
2135 enable = technology->enable_persistent;
2137 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
2139 enable = wifi->enabled;
2141 technology_affect_devices(technology, enable);
2144 DBG("technology %p %s", technology, get_name(technology->type));
2149 int connman_technology_driver_register(struct connman_technology_driver *driver)
2152 struct connman_device *device;
2153 enum connman_service_type type;
2155 for (list = driver_list; list; list = list->next) {
2156 if (list->data == driver)
2160 DBG("Registering %s driver", driver->name);
2162 driver_list = g_slist_insert_sorted(driver_list, driver,
2166 * Check for technology less devices if this driver
2167 * can service any of them.
2169 for (list = techless_device_list; list; list = list->next) {
2170 device = list->data;
2172 type = __connman_device_get_service_type(device);
2173 if (type != driver->type)
2176 techless_device_list = g_slist_remove(techless_device_list,
2179 __connman_technology_add_device(device);
2182 /* Check for orphaned rfkill switches. */
2183 g_hash_table_foreach(rfkill_list, rfkill_check,
2184 GINT_TO_POINTER(driver->type));
2187 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2188 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
2192 #if defined TIZEN_EXT_WIFI_MESH
2193 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2194 if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
2202 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
2204 GSList *list, *tech_drivers;
2205 struct connman_technology *technology;
2206 struct connman_technology_driver *current;
2208 DBG("Unregistering driver %p name %s", driver, driver->name);
2210 for (list = technology_list; list; list = list->next) {
2211 technology = list->data;
2213 for (tech_drivers = technology->driver_list; tech_drivers;
2214 tech_drivers = g_slist_next(tech_drivers)) {
2215 current = tech_drivers->data;
2216 if (driver != current)
2220 driver->remove(technology);
2222 technology->driver_list =
2223 g_slist_remove(technology->driver_list,
2229 driver_list = g_slist_remove(driver_list, driver);
2231 if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
2232 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
2234 technology_put(technology);
2236 #if defined TIZEN_EXT_WIFI_MESH
2237 if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
2238 technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
2240 technology_put(technology);
2245 void __connman_technology_add_interface(enum connman_service_type type,
2246 int index, const char *ident)
2248 struct connman_technology *technology;
2249 GSList *tech_drivers;
2250 struct connman_technology_driver *driver;
2254 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2255 case CONNMAN_SERVICE_TYPE_SYSTEM:
2257 case CONNMAN_SERVICE_TYPE_ETHERNET:
2258 case CONNMAN_SERVICE_TYPE_WIFI:
2259 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2260 case CONNMAN_SERVICE_TYPE_CELLULAR:
2261 case CONNMAN_SERVICE_TYPE_GPS:
2262 case CONNMAN_SERVICE_TYPE_VPN:
2263 case CONNMAN_SERVICE_TYPE_GADGET:
2264 case CONNMAN_SERVICE_TYPE_P2P:
2265 #if defined TIZEN_EXT_WIFI_MESH
2266 case CONNMAN_SERVICE_TYPE_MESH:
2271 name = connman_inet_ifname(index);
2272 connman_info("Adding interface %s [ %s ]", name,
2273 __connman_service_type2string(type));
2275 technology = technology_find(type);
2280 for (tech_drivers = technology->driver_list; tech_drivers;
2281 tech_drivers = g_slist_next(tech_drivers)) {
2282 driver = tech_drivers->data;
2284 if (driver->add_interface)
2285 driver->add_interface(technology, index, name, ident);
2289 * At this point we can try to enable tethering automatically as
2290 * now the interfaces are set properly.
2292 if (technology->tethering_persistent)
2293 enable_tethering(technology);
2299 void __connman_technology_remove_interface(enum connman_service_type type,
2300 int index, const char *ident)
2302 struct connman_technology *technology;
2303 GSList *tech_drivers;
2304 struct connman_technology_driver *driver;
2308 case CONNMAN_SERVICE_TYPE_UNKNOWN:
2309 case CONNMAN_SERVICE_TYPE_SYSTEM:
2311 case CONNMAN_SERVICE_TYPE_ETHERNET:
2312 case CONNMAN_SERVICE_TYPE_WIFI:
2313 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
2314 case CONNMAN_SERVICE_TYPE_CELLULAR:
2315 case CONNMAN_SERVICE_TYPE_GPS:
2316 case CONNMAN_SERVICE_TYPE_VPN:
2317 case CONNMAN_SERVICE_TYPE_GADGET:
2318 case CONNMAN_SERVICE_TYPE_P2P:
2319 #if defined TIZEN_EXT_WIFI_MESH
2320 case CONNMAN_SERVICE_TYPE_MESH:
2325 name = connman_inet_ifname(index);
2326 connman_info("Remove interface %s [ %s ]", name,
2327 __connman_service_type2string(type));
2330 technology = technology_find(type);
2335 for (tech_drivers = technology->driver_list; tech_drivers;
2336 tech_drivers = g_slist_next(tech_drivers)) {
2337 driver = tech_drivers->data;
2339 if (driver->remove_interface)
2340 driver->remove_interface(technology, index);
2344 int __connman_technology_add_device(struct connman_device *device)
2346 struct connman_technology *technology;
2347 enum connman_service_type type;
2349 type = __connman_device_get_service_type(device);
2351 DBG("device %p type %s", device, get_name(type));
2353 technology = technology_get(type);
2356 * Since no driver can be found for this device at the moment we
2357 * add it to the techless device list.
2359 techless_device_list = g_slist_prepend(techless_device_list,
2365 __sync_synchronize();
2366 if (technology->rfkill_driven) {
2367 if (technology->enabled)
2368 __connman_device_enable(device);
2370 __connman_device_disable(device);
2375 if (technology->enable_persistent &&
2376 !global_offlinemode) {
2377 int err = __connman_device_enable(device);
2379 * connman_technology_add_device() calls __connman_device_enable()
2380 * but since the device is already enabled, the call does not
2381 * propagate through to connman_technology_enabled via
2382 * connman_device_set_powered.
2384 if (err == -EALREADY)
2385 __connman_technology_enabled(type);
2387 /* if technology persistent state is offline */
2388 if (!technology->enable_persistent)
2389 __connman_device_disable(device);
2392 technology->device_list = g_slist_prepend(technology->device_list,
2398 int __connman_technology_remove_device(struct connman_device *device)
2400 struct connman_technology *technology;
2401 enum connman_service_type type;
2403 DBG("device %p", device);
2405 type = __connman_device_get_service_type(device);
2407 technology = technology_find(type);
2409 techless_device_list = g_slist_remove(techless_device_list,
2414 technology->device_list = g_slist_remove(technology->device_list,
2417 if (technology->tethering)
2418 set_tethering(technology, false);
2420 technology_put(technology);
2425 int __connman_technology_enabled(enum connman_service_type type)
2427 struct connman_technology *technology;
2429 technology = technology_find(type);
2433 DBG("technology %p type %s rfkill %d enabled %d", technology,
2434 get_name(type), technology->rfkill_driven,
2435 technology->enabled);
2437 #if !defined TIZEN_EXT
2438 if (technology->rfkill_driven) {
2439 if (technology->tethering_persistent)
2440 enable_tethering(technology);
2445 return technology_enabled(technology);
2448 int __connman_technology_disabled(enum connman_service_type type)
2450 struct connman_technology *technology;
2453 technology = technology_find(type);
2457 #if !defined TIZEN_EXT
2458 if (technology->rfkill_driven)
2462 for (list = technology->device_list; list; list = list->next) {
2463 struct connman_device *device = list->data;
2465 if (connman_device_get_powered(device))
2469 return technology_disabled(technology);
2472 int __connman_technology_set_offlinemode(bool offlinemode)
2475 int err = -EINVAL, enabled_tech_count = 0;
2477 if (global_offlinemode == offlinemode)
2480 DBG("offlinemode %s", offlinemode ? "On" : "Off");
2483 * This is a bit tricky. When you set offlinemode, there is no
2484 * way to differentiate between attempting offline mode and
2485 * resuming offlinemode from last saved profile. We need that
2486 * information in rfkill_update, otherwise it falls back on the
2487 * technology's persistent state. Hence we set the offline mode here
2488 * but save it & call the notifier only if it is successful.
2491 global_offlinemode = offlinemode;
2493 /* Traverse technology list, enable/disable each technology. */
2494 for (list = technology_list; list; list = list->next) {
2495 struct connman_technology *technology = list->data;
2498 err = technology_disable(technology);
2500 if (technology->hardblocked)
2503 if (technology->enable_persistent) {
2504 err = technology_enable(technology);
2505 enabled_tech_count++;
2510 if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
2511 (err == -EINVAL && enabled_tech_count == 0)) {
2512 connman_technology_save_offlinemode();
2513 __connman_notifier_offlinemode(offlinemode);
2515 global_offlinemode = connman_technology_load_offlinemode();
2520 #if defined TIZEN_EXT_WIFI_MESH
2521 static gboolean __add_ethernet_to_bridge(gpointer data)
2524 __connman_mesh_add_ethernet_to_bridge();
2529 void __connman_technology_set_connected(enum connman_service_type type,
2532 struct connman_technology *technology;
2535 technology = technology_find(type);
2539 DBG("technology %p connected %d", technology, connected);
2541 technology->connected = connected;
2543 #if defined TIZEN_EXT_WIFI_MESH
2544 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
2545 g_idle_add(__add_ethernet_to_bridge, NULL);
2549 connman_dbus_property_changed_basic(technology->path,
2550 CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
2551 DBUS_TYPE_BOOLEAN, &val);
2554 static bool technology_apply_rfkill_change(struct connman_technology *technology,
2559 bool hardblock_changed = false;
2561 GList *start, *list;
2563 DBG("technology %p --> %d/%d vs %d/%d",
2564 technology, softblock, hardblock,
2565 technology->softblocked, technology->hardblocked);
2567 if (technology->hardblocked == hardblock)
2568 goto softblock_change;
2570 if (!(new_rfkill && !hardblock)) {
2571 start = g_hash_table_get_values(rfkill_list);
2573 for (list = start; list; list = list->next) {
2574 struct connman_rfkill *rfkill = list->data;
2576 if (rfkill->type != technology->type)
2579 if (rfkill->hardblock != hardblock)
2587 goto softblock_change;
2589 technology->hardblocked = hardblock;
2590 hardblock_changed = true;
2593 if (!apply && technology->softblocked != softblock)
2597 return technology->hardblocked;
2599 technology->softblocked = softblock;
2601 if (technology->hardblocked ||
2602 technology->softblocked) {
2603 if (technology_disabled(technology) != -EALREADY)
2604 technology_affect_devices(technology, false);
2605 } else if (!technology->hardblocked &&
2606 !technology->softblocked) {
2607 if (technology_enabled(technology) != -EALREADY)
2608 technology_affect_devices(technology, true);
2611 if (hardblock_changed) {
2612 if (technology->hardblocked) {
2613 DBG("%s is switched off.", get_name(technology->type));
2614 technology_dbus_unregister(technology);
2616 DBG("%s is switched on.", get_name(technology->type));
2617 technology_dbus_register(technology);
2619 if (global_offlinemode)
2620 __connman_rfkill_block(technology->type, true);
2624 return technology->hardblocked;
2627 int __connman_technology_add_rfkill(unsigned int index,
2628 enum connman_service_type type,
2632 struct connman_technology *technology;
2633 struct connman_rfkill *rfkill;
2635 DBG("index %u type %d soft %u hard %u", index, type,
2636 softblock, hardblock);
2638 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2642 rfkill = g_try_new0(struct connman_rfkill, 1);
2646 rfkill->index = index;
2647 rfkill->type = type;
2648 rfkill->softblock = softblock;
2649 rfkill->hardblock = hardblock;
2651 g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
2654 #if defined TIZEN_EXT
2655 /* Fix Svace Issue [WGID: 1348]. */
2658 technology = technology_get(type);
2659 /* If there is no driver for this type, ignore it. */
2663 technology->rfkill_driven = true;
2665 #if !defined TIZEN_EXT
2666 /* If hardblocked, there is no need to handle softblocked state */
2667 if (technology_apply_rfkill_change(technology,
2668 softblock, hardblock, true))
2672 if (global_offlinemode)
2676 * Depending on softblocked state we unblock/block according to
2677 * offlinemode and persistente state.
2679 if (technology->softblocked &&
2680 technology->enable_persistent)
2681 return __connman_rfkill_block(type, false);
2682 else if (!technology->softblocked &&
2683 !technology->enable_persistent)
2684 return __connman_rfkill_block(type, true);
2689 int __connman_technology_update_rfkill(unsigned int index,
2690 enum connman_service_type type,
2694 struct connman_technology *technology;
2695 struct connman_rfkill *rfkill;
2697 DBG("index %u soft %u hard %u", index, softblock, hardblock);
2699 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2703 if (rfkill->softblock == softblock &&
2704 rfkill->hardblock == hardblock)
2707 rfkill->softblock = softblock;
2708 rfkill->hardblock = hardblock;
2710 technology = technology_find(type);
2711 /* If there is no driver for this type, ignore it. */
2715 technology_apply_rfkill_change(technology, softblock, hardblock,
2718 if (technology->hardblocked)
2719 DBG("%s hardblocked", get_name(technology->type));
2721 DBG("%s is%s softblocked", get_name(technology->type),
2722 technology->softblocked ? "" : " not");
2727 int __connman_technology_remove_rfkill(unsigned int index,
2728 enum connman_service_type type)
2730 struct connman_technology *technology;
2731 struct connman_rfkill *rfkill;
2733 DBG("index %u", index);
2735 rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
2739 g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
2741 technology = technology_find(type);
2745 technology_apply_rfkill_change(technology,
2746 technology->softblocked, !technology->hardblocked, false);
2748 technology_put(technology);
2753 int __connman_technology_init(void)
2757 connection = connman_dbus_get_connection();
2759 rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2762 global_offlinemode = connman_technology_load_offlinemode();
2764 /* This will create settings file if it is missing */
2765 connman_technology_save_offlinemode();
2770 void __connman_technology_cleanup(void)
2774 while (technology_list) {
2775 struct connman_technology *technology = technology_list->data;
2776 technology_list = g_slist_remove(technology_list, technology);
2777 technology_put(technology);
2780 g_hash_table_destroy(rfkill_list);
2782 dbus_connection_unref(connection);